mirror of
https://github.com/pygos/init.git
synced 2024-12-22 15:20:49 +01:00
Simplifiy service file syntax
Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
This commit is contained in:
parent
ca7b7c15c5
commit
56e6004336
15 changed files with 247 additions and 247 deletions
|
@ -37,15 +37,28 @@ static NORETURN void split_and_exec(char *cmd)
|
|||
while (*cmd != '\0') {
|
||||
argv[i++] = cmd; /* FIXME: buffer overflow!! */
|
||||
|
||||
while (*cmd != '\0' && !isspace(*cmd))
|
||||
++cmd;
|
||||
if (*cmd == '"') {
|
||||
while (*cmd != '\0' && *cmd != '"') {
|
||||
if (cmd[0] == '\\' && cmd[1] != '\0')
|
||||
++cmd;
|
||||
|
||||
if (isspace(*cmd)) {
|
||||
*(cmd++) = '\0';
|
||||
|
||||
while (isspace(*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;
|
||||
|
|
|
@ -68,20 +68,10 @@ typedef struct {
|
|||
char *rdline(int fd, int argc, const char *const *argv);
|
||||
|
||||
/*
|
||||
Split a line of the shape "key = value" into key and value part.
|
||||
|
||||
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.
|
||||
Remove double quotes ('"') from a string and substitute escape
|
||||
sequences in between double quotes.
|
||||
*/
|
||||
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
|
||||
|
|
160
lib/src/rdsvc.c
160
lib/src/rdsvc.c
|
@ -28,10 +28,21 @@
|
|||
#include "service.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,
|
||||
const char *filename, size_t lineno)
|
||||
{
|
||||
(void)filename; (void)lineno;
|
||||
if (try_unescape(arg, filename, lineno))
|
||||
return -1;
|
||||
svc->desc = arg;
|
||||
return 0;
|
||||
}
|
||||
|
@ -39,7 +50,8 @@ static int svc_desc(service_t *svc, char *arg,
|
|||
static int svc_tty(service_t *svc, char *arg,
|
||||
const char *filename, size_t lineno)
|
||||
{
|
||||
(void)filename; (void)lineno;
|
||||
if (try_unescape(arg, filename, lineno))
|
||||
return -1;
|
||||
svc->ctty = arg;
|
||||
return 0;
|
||||
}
|
||||
|
@ -63,8 +75,12 @@ static int svc_exec(service_t *svc, char *arg,
|
|||
static int svc_before(service_t *svc, char *arg,
|
||||
const char *filename, size_t lineno)
|
||||
{
|
||||
char **new = realloc(svc->before,
|
||||
sizeof(char*) * (svc->num_before + 1));
|
||||
char **new;
|
||||
|
||||
if (try_unescape(arg, filename, lineno))
|
||||
return -1;
|
||||
|
||||
new = realloc(svc->before, sizeof(char*) * (svc->num_before + 1));
|
||||
|
||||
if (new == NULL) {
|
||||
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,
|
||||
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) {
|
||||
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,
|
||||
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) {
|
||||
fprintf(stderr, "%s: %zu: unknown service type '%s'\n",
|
||||
|
@ -104,15 +140,51 @@ static int svc_type(service_t *svc, char *arg,
|
|||
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;
|
||||
free(arg);
|
||||
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,
|
||||
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) {
|
||||
fprintf(stderr, "%s: %zu: unknown service target '%s'\n",
|
||||
|
@ -125,33 +197,6 @@ static int svc_target(service_t *svc, char *arg,
|
|||
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 {
|
||||
const char *key;
|
||||
|
||||
|
@ -165,7 +210,6 @@ static const struct {
|
|||
{ "tty", svc_tty },
|
||||
{ "before", svc_before },
|
||||
{ "after", svc_after },
|
||||
{ "respawn_limit", svc_rspwn_limit },
|
||||
};
|
||||
|
||||
|
||||
|
@ -239,36 +283,42 @@ service_t *rdsvc(int dirfd, const char *filename)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (splitkv(line, &key, &value)) {
|
||||
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) {
|
||||
if (!strlen(line)) {
|
||||
free(line);
|
||||
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) {
|
||||
if (!strcmp(svc_params[i].key, key))
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
goto fail_line;
|
||||
}
|
||||
|
|
|
@ -19,13 +19,6 @@
|
|||
|
||||
#include "util.h"
|
||||
|
||||
static char *skpspc(char *ptr)
|
||||
{
|
||||
while (*ptr == ' ' || *ptr == '\t')
|
||||
++ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int xdigit(int x)
|
||||
{
|
||||
if (isupper(x))
|
||||
|
@ -35,107 +28,61 @@ static int xdigit(int x)
|
|||
return x - '0';
|
||||
}
|
||||
|
||||
static char *parse_str(char *src)
|
||||
int unescape(char *src)
|
||||
{
|
||||
char *dst = src;
|
||||
int c;
|
||||
|
||||
for (;;) {
|
||||
c = *(src++);
|
||||
while (*src != '"' && *src != '\0')
|
||||
*(dst++) = *(src++);
|
||||
|
||||
switch (c) {
|
||||
case '\\':
|
||||
c = *(src++);
|
||||
|
||||
switch (c) {
|
||||
case 'a': c = '\a'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'f': c = '\f'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case '\\': break;
|
||||
case '"': break;
|
||||
case 'x':
|
||||
c = 0;
|
||||
if (isxdigit(*src))
|
||||
c = (c << 4) | xdigit(*(src++));
|
||||
if (isxdigit(*src))
|
||||
c = (c << 4) | xdigit(*(src++));
|
||||
break;
|
||||
case '0':
|
||||
c = 0;
|
||||
if (isdigit(*src) && *src < '8')
|
||||
c = (c << 3) | (*(src++) - '0');
|
||||
if (isdigit(*src) && *src < '8')
|
||||
c = (c << 3) | (*(src++) - '0');
|
||||
if (isdigit(*src) && *src < '8')
|
||||
c = (c << 3) | (*(src++) - '0');
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
if (*src == '\0')
|
||||
break;
|
||||
case '"':
|
||||
*(dst++) = '\0';
|
||||
goto out;
|
||||
|
||||
++src;
|
||||
|
||||
while ((c = *(src++)) != '"') {
|
||||
if (c == '\0')
|
||||
return -1;
|
||||
|
||||
if (c == '\\') {
|
||||
c = *(src++);
|
||||
|
||||
switch (c) {
|
||||
case 'a': c = '\a'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'f': c = '\f'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case '\\':
|
||||
case '"':
|
||||
break;
|
||||
case 'x':
|
||||
c = 0;
|
||||
if (isxdigit(*src))
|
||||
c = (c<<4) | xdigit(*(src++));
|
||||
if (isxdigit(*src))
|
||||
c = (c<<4) | xdigit(*(src++));
|
||||
break;
|
||||
case '0':
|
||||
c = 0;
|
||||
if (isdigit(*src) && *src < '8')
|
||||
c = (c<<3) | (*(src++) - '0');
|
||||
if (isdigit(*src) && *src < '8')
|
||||
c = (c<<3) | (*(src++) - '0');
|
||||
if (isdigit(*src) && *src < '8')
|
||||
c = (c<<3) | (*(src++) - '0');
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*(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 != '=')
|
||||
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;
|
||||
|
||||
*(dst++) = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
description = "agetty on %0"
|
||||
exec = "@SBINPATH@/agetty %0 linux"
|
||||
type = respawn
|
||||
target = boot
|
||||
after = sysinit
|
||||
tty = "/dev/%0"
|
||||
description agetty on %0
|
||||
exec "@SBINPATH@/agetty" %0 linux
|
||||
type respawn
|
||||
target boot
|
||||
after sysinit
|
||||
tty "/dev/%0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
description = "reload hostname"
|
||||
exec = "@BINPATH@/hostname --file /etc/hostname"
|
||||
type = wait
|
||||
target = boot
|
||||
before = sysinit
|
||||
after = hwclock
|
||||
description reload hostname
|
||||
exec "@BINPATH@/hostname" --file /etc/hostname
|
||||
type wait
|
||||
target boot
|
||||
before sysinit
|
||||
after hwclock
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
description = "restore time from RTC"
|
||||
exec = "@SBINPATH@/hwclock --hctosys --utc"
|
||||
type = wait
|
||||
target = boot
|
||||
before = sysinit
|
||||
description restore time from RTC
|
||||
exec "@SBINPATH@/hwclock" --hctosys --utc
|
||||
type wait
|
||||
target boot
|
||||
before sysinit
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
description = "configure network loopback device"
|
||||
type = wait
|
||||
target = boot
|
||||
before = sysinit
|
||||
after = hwclock
|
||||
after = hostname
|
||||
description configure network loopback device
|
||||
type wait
|
||||
target boot
|
||||
before sysinit
|
||||
after hwclock
|
||||
after hostname
|
||||
|
||||
exec = "@SBINPATH@/ip addr add 127.0.0.1/8 dev lo brd +"
|
||||
exec = "@SBINPATH@/ip link set lo up"
|
||||
exec "@SBINPATH@/ip" addr add 127.0.0.1/8 dev lo brd +
|
||||
exec "@SBINPATH@/ip" link set lo up
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
description = "system reboot"
|
||||
exec = "@SBINPATH@/shutdown -nrf"
|
||||
type = wait
|
||||
target = reboot
|
||||
after = "sync"
|
||||
after = "sigkill"
|
||||
after = "sigterm"
|
||||
description system reboot
|
||||
exec "@SBINPATH@/shutdown" -nrf
|
||||
type wait
|
||||
target reboot
|
||||
after sync
|
||||
after sigkill
|
||||
after sigterm
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
description = "system shutdown"
|
||||
exec = "@SBINPATH@/shutdown -npf"
|
||||
type = wait
|
||||
target = shutdown
|
||||
after = "sync"
|
||||
after = "sigkill"
|
||||
after = "sigterm"
|
||||
description system shutdown
|
||||
exec "@SBINPATH@/shutdown" -npf
|
||||
type wait
|
||||
target shutdown
|
||||
after sync
|
||||
after sigkill
|
||||
after sigterm
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
description = "send SIGKILL to remaining processes"
|
||||
exec = "@SCRIPTDIR@/killall5 9"
|
||||
type = wait
|
||||
target = "%0"
|
||||
after = "sigterm"
|
||||
before = "sync"
|
||||
before = "shutdown"
|
||||
before = "reboot"
|
||||
description send SIGKILL to remaining processes
|
||||
exec "@SCRIPTDIR@/killall5" 9
|
||||
type wait
|
||||
target %0
|
||||
after sigterm
|
||||
before sync
|
||||
before shutdown
|
||||
before reboot
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
description = "send SIGTERM to all processes"
|
||||
exec = "@SCRIPTDIR@/killall5 15"
|
||||
exec = "@BINPATH@/sleep 5"
|
||||
type = wait
|
||||
target = "%0"
|
||||
before = "sigkill"
|
||||
before = "sync"
|
||||
before = "reboot"
|
||||
before = "shutdown"
|
||||
description send SIGTERM to all processes
|
||||
exec "@SCRIPTDIR@/killall5" 15
|
||||
exec "@BINPATH@/sleep" 5
|
||||
type wait
|
||||
target %0
|
||||
before sigkill
|
||||
before sync
|
||||
before reboot
|
||||
before shutdown
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
description = "sync"
|
||||
exec = "@BINPATH@/sync"
|
||||
type = wait
|
||||
target = "%0"
|
||||
after = "sigkill"
|
||||
after = "sigterm"
|
||||
before = "reboot"
|
||||
before = "shutdown"
|
||||
description sync
|
||||
exec "@BINPATH@/sync"
|
||||
type wait
|
||||
target %0
|
||||
after sigkill
|
||||
after sigterm
|
||||
before reboot
|
||||
before shutdown
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
description = "configure kernel paramters"
|
||||
exec = "@SBINPATH@/sysctl --system"
|
||||
type = wait
|
||||
target = boot
|
||||
before = sysinit
|
||||
after = hwclock
|
||||
after = hostname
|
||||
description configure kernel paramters
|
||||
exec "@SBINPATH@/sysctl" --system
|
||||
type wait
|
||||
target boot
|
||||
before sysinit
|
||||
after hwclock
|
||||
after hostname
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
description = "basic system initialization"
|
||||
type = once
|
||||
target = boot
|
||||
description basic system initialization
|
||||
type once
|
||||
target boot
|
||||
|
|
Loading…
Reference in a new issue