1
0
Fork 0
mirror of https://github.com/pygos/init.git synced 2024-11-22 19:19:47 +01:00

Simplifiy service file syntax

Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
This commit is contained in:
David Oberhollenzer 2018-04-04 14:03:23 +02:00
parent ca7b7c15c5
commit 56e6004336
15 changed files with 247 additions and 247 deletions

View file

@ -37,15 +37,28 @@ static NORETURN void split_and_exec(char *cmd)
while (*cmd != '\0') { while (*cmd != '\0') {
argv[i++] = cmd; /* FIXME: buffer overflow!! */ argv[i++] = cmd; /* FIXME: buffer overflow!! */
while (*cmd != '\0' && !isspace(*cmd)) if (*cmd == '"') {
while (*cmd != '\0' && *cmd != '"') {
if (cmd[0] == '\\' && cmd[1] != '\0')
++cmd; ++cmd;
if (isspace(*cmd)) {
*(cmd++) = '\0';
while (isspace(*cmd))
++cmd; ++cmd;
} }
if (*cmd == '"')
*(cmd++) = '\0';
unescape(argv[i - 1]);
} else {
while (*cmd != '\0' && *cmd != ' ')
++cmd;
if (*cmd == ' ')
*(cmd++) = '\0';
}
while (*cmd == ' ')
++cmd;
} }
argv[i] = NULL; argv[i] = NULL;

View file

@ -68,20 +68,10 @@ typedef struct {
char *rdline(int fd, int argc, const char *const *argv); char *rdline(int fd, int argc, const char *const *argv);
/* /*
Split a line of the shape "key = value" into key and value part. Remove double quotes ('"') from a string and substitute escape
sequences in between double quotes.
The key can contain alphanumeric characters and can be padded with
spaces or tabs.
The value can be either a sequence of alphanumeric characters, period
or underscore OR a string in quotation marks. For strings, the
quotation marks are removed and escape sequences are processed.
The value may also be padded with spaces or tabs but the line may not
contain anything else after the value, except for spaces, tabs or
the '#' symbol which is interpreted as start of a comment.
*/ */
int splitkv(char *line, char **key, char **value); int unescape(char *src);
/* /*
Search through an array of enum_map_t entries to resolve a string to Search through an array of enum_map_t entries to resolve a string to

View file

@ -28,10 +28,21 @@
#include "service.h" #include "service.h"
#include "util.h" #include "util.h"
static int try_unescape(char *arg, const char *filename, size_t lineno)
{
if (unescape(arg)) {
fprintf(stderr, "%s: %zu: malformed string constant\n",
filename, lineno);
return -1;
}
return 0;
}
static int svc_desc(service_t *svc, char *arg, static int svc_desc(service_t *svc, char *arg,
const char *filename, size_t lineno) const char *filename, size_t lineno)
{ {
(void)filename; (void)lineno; if (try_unescape(arg, filename, lineno))
return -1;
svc->desc = arg; svc->desc = arg;
return 0; return 0;
} }
@ -39,7 +50,8 @@ static int svc_desc(service_t *svc, char *arg,
static int svc_tty(service_t *svc, char *arg, static int svc_tty(service_t *svc, char *arg,
const char *filename, size_t lineno) const char *filename, size_t lineno)
{ {
(void)filename; (void)lineno; if (try_unescape(arg, filename, lineno))
return -1;
svc->ctty = arg; svc->ctty = arg;
return 0; return 0;
} }
@ -63,8 +75,12 @@ static int svc_exec(service_t *svc, char *arg,
static int svc_before(service_t *svc, char *arg, static int svc_before(service_t *svc, char *arg,
const char *filename, size_t lineno) const char *filename, size_t lineno)
{ {
char **new = realloc(svc->before, char **new;
sizeof(char*) * (svc->num_before + 1));
if (try_unescape(arg, filename, lineno))
return -1;
new = realloc(svc->before, sizeof(char*) * (svc->num_before + 1));
if (new == NULL) { if (new == NULL) {
fprintf(stderr, "%s: %zu: out of memory\n", filename, lineno); fprintf(stderr, "%s: %zu: out of memory\n", filename, lineno);
@ -80,7 +96,12 @@ static int svc_before(service_t *svc, char *arg,
static int svc_after(service_t *svc, char *arg, static int svc_after(service_t *svc, char *arg,
const char *filename, size_t lineno) const char *filename, size_t lineno)
{ {
char **new = realloc(svc->after, sizeof(char*) * (svc->num_after + 1)); char **new;
if (try_unescape(arg, filename, lineno))
return -1;
new = realloc(svc->after, sizeof(char*) * (svc->num_after + 1));
if (new == NULL) { if (new == NULL) {
fprintf(stderr, "%s: %zu: out of memory\n", filename, lineno); fprintf(stderr, "%s: %zu: out of memory\n", filename, lineno);
@ -96,7 +117,22 @@ static int svc_after(service_t *svc, char *arg,
static int svc_type(service_t *svc, char *arg, static int svc_type(service_t *svc, char *arg,
const char *filename, size_t lineno) const char *filename, size_t lineno)
{ {
int type = svc_type_from_string(arg); char *extra;
int type;
if (try_unescape(arg, filename, lineno))
return -1;
for (extra = arg; *extra != ' ' && *extra != '\0'; ++extra)
;
if (*extra == ' ') {
*(extra++) = '\0';
} else {
extra = NULL;
}
type = svc_type_from_string(arg);
if (type == -1) { if (type == -1) {
fprintf(stderr, "%s: %zu: unknown service type '%s'\n", fprintf(stderr, "%s: %zu: unknown service type '%s'\n",
@ -104,15 +140,51 @@ static int svc_type(service_t *svc, char *arg,
return -1; return -1;
} }
if (extra != NULL) {
switch (type) {
case SVC_RESPAWN:
if (strncmp(extra, "limit ", 6) != 0)
goto fail_limit;
extra += 6;
svc->rspwn_limit = 0;
if (!isdigit(*extra))
goto fail_limit;
while (isdigit(*extra)) {
svc->rspwn_limit *= 10;
svc->rspwn_limit += *(extra++) - '0';
}
if (*extra != '\0')
goto fail_limit;
break;
default:
fprintf(stderr, "%s: %zu: unexpected extra arguments "
"for type '%s'\n", filename, lineno, arg);
return -1;
}
}
svc->type = type; svc->type = type;
free(arg); free(arg);
return 0; return 0;
fail_limit:
fprintf(stderr, "%s: %zu: expected 'limit <value>' after 'respawn'\n",
filename, lineno);
return -1;
} }
static int svc_target(service_t *svc, char *arg, static int svc_target(service_t *svc, char *arg,
const char *filename, size_t lineno) const char *filename, size_t lineno)
{ {
int target = svc_target_from_string(arg); int target;
if (try_unescape(arg, filename, lineno))
return -1;
target = svc_target_from_string(arg);
if (target == -1) { if (target == -1) {
fprintf(stderr, "%s: %zu: unknown service target '%s'\n", fprintf(stderr, "%s: %zu: unknown service target '%s'\n",
@ -125,33 +197,6 @@ static int svc_target(service_t *svc, char *arg,
return 0; return 0;
} }
static int svc_rspwn_limit(service_t *svc, char *arg,
const char *filename, size_t lineno)
{
const char *ptr;
svc->rspwn_limit = 0;
if (!isdigit(*arg))
goto fail;
for (ptr = arg; isdigit(*ptr); ++ptr)
svc->rspwn_limit = svc->rspwn_limit * 10 + (*ptr - '0');
if (*ptr != '\0')
goto fail;
free(arg);
return 0;
fail:
fprintf(stderr,
"%s: %zu: expected numeric argument for respawn limit\n",
filename, lineno);
free(arg);
return -1;
}
static const struct { static const struct {
const char *key; const char *key;
@ -165,7 +210,6 @@ static const struct {
{ "tty", svc_tty }, { "tty", svc_tty },
{ "before", svc_before }, { "before", svc_before },
{ "after", svc_after }, { "after", svc_after },
{ "respawn_limit", svc_rspwn_limit },
}; };
@ -239,36 +283,42 @@ service_t *rdsvc(int dirfd, const char *filename)
goto fail; goto fail;
} }
if (splitkv(line, &key, &value)) { if (!strlen(line)) {
if (key == NULL) {
fprintf(stderr,
"%s: %zu: expected <key> = <value>\n",
filename, lineno);
} else if (value == NULL) {
fprintf(stderr,
"%s: %zu: expected value after %s\n",
filename, lineno, key);
} else {
fprintf(stderr,
"%s: %zu: unexpected arguments "
"after key-value pair\n",
filename, lineno);
}
goto fail;
}
if (key == NULL) {
free(line); free(line);
continue; continue;
} }
key = value = line;
while (*value != ' ' && *value != '\0') {
if (!isalpha(*value)) {
fprintf(stderr, "%s: %zu: unexpected '%c' in "
"keyword\n", filename, lineno, *value);
goto fail_line;
}
++value;
}
if (*value == ' ') {
*(value++) = '\0';
} else {
value = NULL;
}
for (i = 0; i < ARRAY_SIZE(svc_params); ++i) { for (i = 0; i < ARRAY_SIZE(svc_params); ++i) {
if (!strcmp(svc_params[i].key, key)) if (!strcmp(svc_params[i].key, key))
break; break;
} }
if (i >= ARRAY_SIZE(svc_params)) { if (i >= ARRAY_SIZE(svc_params)) {
fprintf(stderr, "%s: %zu: unknown parameter '%s'\n", fprintf(stderr, "%s: %zu: unknown keyword '%s'\n",
filename, lineno, key);
goto fail_line;
}
if (value == NULL) {
fprintf(stderr,
"%s: %zu: expected argument after '%s'\n",
filename, lineno, key); filename, lineno, key);
goto fail_line; goto fail_line;
} }

View file

@ -19,13 +19,6 @@
#include "util.h" #include "util.h"
static char *skpspc(char *ptr)
{
while (*ptr == ' ' || *ptr == '\t')
++ptr;
return ptr;
}
static int xdigit(int x) static int xdigit(int x)
{ {
if (isupper(x)) if (isupper(x))
@ -35,16 +28,25 @@ static int xdigit(int x)
return x - '0'; return x - '0';
} }
static char *parse_str(char *src) int unescape(char *src)
{ {
char *dst = src; char *dst = src;
int c; int c;
for (;;) { for (;;) {
c = *(src++); while (*src != '"' && *src != '\0')
*(dst++) = *(src++);
switch (c) { if (*src == '\0')
case '\\': break;
++src;
while ((c = *(src++)) != '"') {
if (c == '\0')
return -1;
if (c == '\\') {
c = *(src++); c = *(src++);
switch (c) { switch (c) {
@ -53,89 +55,34 @@ static char *parse_str(char *src)
case 'f': c = '\f'; break; case 'f': c = '\f'; break;
case 'n': c = '\n'; break; case 'n': c = '\n'; break;
case 't': c = '\t'; break; case 't': c = '\t'; break;
case '\\': break; case '\\':
case '"': break; case '"':
break;
case 'x': case 'x':
c = 0; c = 0;
if (isxdigit(*src)) if (isxdigit(*src))
c = (c << 4) | xdigit(*(src++)); c = (c<<4) | xdigit(*(src++));
if (isxdigit(*src)) if (isxdigit(*src))
c = (c << 4) | xdigit(*(src++)); c = (c<<4) | xdigit(*(src++));
break; break;
case '0': case '0':
c = 0; c = 0;
if (isdigit(*src) && *src < '8') if (isdigit(*src) && *src < '8')
c = (c << 3) | (*(src++) - '0'); c = (c<<3) | (*(src++) - '0');
if (isdigit(*src) && *src < '8') if (isdigit(*src) && *src < '8')
c = (c << 3) | (*(src++) - '0'); c = (c<<3) | (*(src++) - '0');
if (isdigit(*src) && *src < '8') if (isdigit(*src) && *src < '8')
c = (c << 3) | (*(src++) - '0'); c = (c<<3) | (*(src++) - '0');
break; break;
default: default:
return NULL; return -1;
} }
break;
case '"':
*(dst++) = '\0';
goto out;
} }
*(dst++) = c; *(dst++) = c;
} }
out:
return src;
}
int splitkv(char *line, char **key, char **value)
{
*key = NULL;
*value = NULL;
line = skpspc(line);
if (*line == '#' || *line == '\0')
return 0;
if (!isalpha(*line))
return -1;
*key = line;
while (isalnum(*line))
++line;
if (*line == ' ' || *line == '\t') {
*(line++) = '\0';
line = skpspc(line);
} }
if (*line != '=') *(dst++) = '\0';
return -1;
*(line++) = '\0';
line = skpspc(line);
if (*line == '"') {
++line;
*value = line;
line = parse_str(line);
} else if (isalnum(*line)) {
*value = line;
while (isalnum(*line) || *line == '.' || *line == '_')
++line;
if (*line != '\0')
*(line++) = '\0';
} else {
return -1;
}
line = skpspc(line);
if (*line != '\0' && *line != '#')
return -1;
return 0; return 0;
} }

View file

@ -1,6 +1,6 @@
description = "agetty on %0" description agetty on %0
exec = "@SBINPATH@/agetty %0 linux" exec "@SBINPATH@/agetty" %0 linux
type = respawn type respawn
target = boot target boot
after = sysinit after sysinit
tty = "/dev/%0" tty "/dev/%0"

View file

@ -1,6 +1,6 @@
description = "reload hostname" description reload hostname
exec = "@BINPATH@/hostname --file /etc/hostname" exec "@BINPATH@/hostname" --file /etc/hostname
type = wait type wait
target = boot target boot
before = sysinit before sysinit
after = hwclock after hwclock

View file

@ -1,5 +1,5 @@
description = "restore time from RTC" description restore time from RTC
exec = "@SBINPATH@/hwclock --hctosys --utc" exec "@SBINPATH@/hwclock" --hctosys --utc
type = wait type wait
target = boot target boot
before = sysinit before sysinit

View file

@ -1,9 +1,9 @@
description = "configure network loopback device" description configure network loopback device
type = wait type wait
target = boot target boot
before = sysinit before sysinit
after = hwclock after hwclock
after = hostname after hostname
exec = "@SBINPATH@/ip addr add 127.0.0.1/8 dev lo brd +" exec "@SBINPATH@/ip" addr add 127.0.0.1/8 dev lo brd +
exec = "@SBINPATH@/ip link set lo up" exec "@SBINPATH@/ip" link set lo up

View file

@ -1,7 +1,7 @@
description = "system reboot" description system reboot
exec = "@SBINPATH@/shutdown -nrf" exec "@SBINPATH@/shutdown" -nrf
type = wait type wait
target = reboot target reboot
after = "sync" after sync
after = "sigkill" after sigkill
after = "sigterm" after sigterm

View file

@ -1,7 +1,7 @@
description = "system shutdown" description system shutdown
exec = "@SBINPATH@/shutdown -npf" exec "@SBINPATH@/shutdown" -npf
type = wait type wait
target = shutdown target shutdown
after = "sync" after sync
after = "sigkill" after sigkill
after = "sigterm" after sigterm

View file

@ -1,8 +1,8 @@
description = "send SIGKILL to remaining processes" description send SIGKILL to remaining processes
exec = "@SCRIPTDIR@/killall5 9" exec "@SCRIPTDIR@/killall5" 9
type = wait type wait
target = "%0" target %0
after = "sigterm" after sigterm
before = "sync" before sync
before = "shutdown" before shutdown
before = "reboot" before reboot

View file

@ -1,9 +1,9 @@
description = "send SIGTERM to all processes" description send SIGTERM to all processes
exec = "@SCRIPTDIR@/killall5 15" exec "@SCRIPTDIR@/killall5" 15
exec = "@BINPATH@/sleep 5" exec "@BINPATH@/sleep" 5
type = wait type wait
target = "%0" target %0
before = "sigkill" before sigkill
before = "sync" before sync
before = "reboot" before reboot
before = "shutdown" before shutdown

View file

@ -1,8 +1,8 @@
description = "sync" description sync
exec = "@BINPATH@/sync" exec "@BINPATH@/sync"
type = wait type wait
target = "%0" target %0
after = "sigkill" after sigkill
after = "sigterm" after sigterm
before = "reboot" before reboot
before = "shutdown" before shutdown

View file

@ -1,7 +1,7 @@
description = "configure kernel paramters" description configure kernel paramters
exec = "@SBINPATH@/sysctl --system" exec "@SBINPATH@/sysctl" --system
type = wait type wait
target = boot target boot
before = sysinit before sysinit
after = hwclock after hwclock
after = hostname after hostname

View file

@ -1,3 +1,3 @@
description = "basic system initialization" description basic system initialization
type = once type once
target = boot target boot