diff options
Diffstat (limited to 'src/rc')
-rw-r--r-- | src/rc/.gitignore | 4 | ||||
-rw-r--r-- | src/rc/Makefile | 9 | ||||
-rw-r--r-- | src/rc/_usage.c | 33 | ||||
-rw-r--r-- | src/rc/builtins.h | 2 | ||||
-rw-r--r-- | src/rc/checkpath.c | 129 | ||||
-rw-r--r-- | src/rc/fstabinfo.c | 211 | ||||
-rw-r--r-- | src/rc/mountinfo.c | 351 | ||||
-rw-r--r-- | src/rc/rc-applets.c | 453 | ||||
-rw-r--r-- | src/rc/rc-depend.c | 166 | ||||
-rw-r--r-- | src/rc/rc-logger.c | 255 | ||||
-rw-r--r-- | src/rc/rc-misc.c | 380 | ||||
-rw-r--r-- | src/rc/rc-plugin.c | 183 | ||||
-rw-r--r-- | src/rc/rc-plugin.h | 10 | ||||
-rw-r--r-- | src/rc/rc-status.c | 200 | ||||
-rw-r--r-- | src/rc/rc-update.c | 153 | ||||
-rw-r--r-- | src/rc/rc.c | 1230 | ||||
-rw-r--r-- | src/rc/runscript.c | 1263 | ||||
-rw-r--r-- | src/rc/start-stop-daemon.c | 973 |
18 files changed, 2932 insertions, 3073 deletions
diff --git a/src/rc/.gitignore b/src/rc/.gitignore index eaa7de9e..d2499761 100644 --- a/src/rc/.gitignore +++ b/src/rc/.gitignore @@ -55,6 +55,7 @@ rc-abort checkpath.o fstabinfo.o mountinfo.o +start-stop-daemon.o rc-applets.o rc-depend.o rc-logger.o @@ -62,8 +63,7 @@ rc-misc.o rc-plugin.o rc-status.o rc-update.o -rc.o runscript.o -start-stop-daemon.o +rc.o rc .depend diff --git a/src/rc/Makefile b/src/rc/Makefile index df185d69..469ac984 100644 --- a/src/rc/Makefile +++ b/src/rc/Makefile @@ -1,8 +1,8 @@ PROG= rc -SRCS= checkpath.c fstabinfo.c mountinfo.c \ +SRCS= checkpath.c fstabinfo.c mountinfo.c start-stop-daemon.c \ rc-applets.c rc-depend.c rc-logger.c \ - rc-misc.c rc-plugin.c rc-status.c rc-update.c rc.c \ - runscript.c start-stop-daemon.c + rc-misc.c rc-plugin.c rc-status.c rc-update.c \ + runscript.c rc.c CLEANFILES= version.h @@ -31,8 +31,9 @@ ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS} CLEANFILES+= ${ALL_LINKS} LDFLAGS+= -L../librc -L../libeinfo -#LDFLAGS+= -Wl,--rpath=../librc -Wl,--rpath=../libeinfo LDADD+= -lutil -lrc -leinfo +#CFLAGS+= -ggdb +#LDFLAGS+= -Wl,--rpath=../librc -Wl,--rpath=../libeinfo MK= ../../mk include ${MK}/cc.mk diff --git a/src/rc/_usage.c b/src/rc/_usage.c index 7ad925d0..afe517f1 100644 --- a/src/rc/_usage.c +++ b/src/rc/_usage.c @@ -33,35 +33,36 @@ # define _noreturn #endif -_noreturn static void usage (int exit_status) +_noreturn static void usage(int exit_status) { const char * const has_arg[] = { "", "<arg>", "[arg]" }; int i; + int len; + char *lo; + char *p; + char *token; #ifdef usagestring - printf (usagestring); + printf(usagestring); #else - printf ("Usage: %s [options] ", applet); + printf("Usage: %s [options] ", applet); #endif #ifdef extraopts - printf (extraopts); + printf(extraopts); #endif - printf ("\n\nOptions: [" getoptstring "]\n"); + printf("\n\nOptions: [" getoptstring "]\n"); for (i = 0; longopts[i].name; ++i) { - int len = printf (" -%c, --%s %s", longopts[i].val, longopts[i].name, - has_arg[longopts[i].has_arg]); + len = printf(" -%c, --%s %s", longopts[i].val, longopts[i].name, + has_arg[longopts[i].has_arg]); - char *lo = xstrdup (longopts_help[i]); - char *p = lo; - char *token; - - while ((token = strsep (&p, "\n"))) { + lo = p = xstrdup(longopts_help[i]); + while ((token = strsep(&p, "\n"))) { while (++len < 37) - printf (" "); - puts (token); + printf(" "); + puts(token); len = 0; } - free (lo); + free(lo); } - exit (exit_status); + exit(exit_status); } diff --git a/src/rc/builtins.h b/src/rc/builtins.h index 6d180bab..81325847 100644 --- a/src/rc/builtins.h +++ b/src/rc/builtins.h @@ -38,4 +38,4 @@ int start_stop_daemon (int argc, char **argv); void run_applets (int argc, char **argv); /* Handy function so we can wrap einfo around our deptree */ -rc_depinfo_t *_rc_deptree_load (int *regen); +RC_DEPTREE *_rc_deptree_load (int *regen); diff --git a/src/rc/checkpath.c b/src/rc/checkpath.c index 7b16aee5..4bf0c46a 100644 --- a/src/rc/checkpath.c +++ b/src/rc/checkpath.c @@ -32,6 +32,7 @@ #include <sys/types.h> #include <sys/stat.h> + #include <errno.h> #include <fcntl.h> #include <getopt.h> @@ -48,84 +49,84 @@ extern const char *applet; -static int do_check (char *path, uid_t uid, gid_t gid, mode_t mode, int file) +static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, int file) { struct stat st; + int fd; - memset (&st, 0, sizeof (st)); - - if (stat (path, &st)) { + if (stat(path, &st)) { if (file) { - int fd; - einfo ("%s: creating file", path); - if ((fd = open (path, O_CREAT)) == -1) { - eerror ("%s: open: %s", applet, strerror (errno)); - return (-1); + einfo("%s: creating file", path); + if ((fd = open(path, O_CREAT)) == -1) { + eerror("%s: open: %s", applet, strerror(errno)); + return -1; } close (fd); } else { - einfo ("%s: creating directory", path); + einfo("%s: creating directory", path); if (! mode) mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; - if (mkdir (path, mode)) { - eerror ("%s: mkdir: %s", applet, strerror (errno)); - return (-1); + if (mkdir(path, mode)) { + eerror("%s: mkdir: %s", applet, strerror (errno)); + return -1; } mode = 0; } } else { - if ((file && S_ISDIR (st.st_mode)) || - (! file && ! S_ISDIR (st.st_mode))) + if ((file && S_ISDIR(st.st_mode)) || + (! file && ! S_ISDIR(st.st_mode))) { if (file) - eerror ("%s: is a directory", path); + eerror("%s: is a directory", path); else - eerror ("%s: is a file", path); - return (-1); + eerror("%s: is a file", path); + return -1; } } if (mode && (st.st_mode & 0777) != mode) { - einfo ("%s: correcting mode", applet); - if (chmod (path, mode)) { - eerror ("%s: chmod: %s", applet, strerror (errno)); - return (-1); + einfo("%s: correcting mode", applet); + if (chmod(path, mode)) { + eerror("%s: chmod: %s", applet, strerror(errno)); + return -1; } } if (st.st_uid != uid || st.st_gid != gid) { if (st.st_dev || st.st_ino) - einfo ("%s: correcting owner", path); - if (chown (path, uid, gid)) { - eerror ("%s: chown: %s", applet, strerror (errno)); - return (-1); + einfo("%s: correcting owner", path); + if (chown(path, uid, gid)) { + eerror("%s: chown: %s", applet, strerror(errno)); + return -1; } } - return (0); + return 0; } /* Based on busybox */ static int parse_mode (mode_t *mode, char *text) { + char *p; + unsigned long l; + /* Check for a numeric mode */ if ((*text - '0') < 8) { - char *p; - unsigned long l = strtoul (text, &p, 8); + l = strtoul(text, &p, 8); if (*p || l > 07777U) { errno = EINVAL; - return (-1); + return -1; } *mode = (mode_t) l; - return (0); + return 0; } /* We currently don't check g+w type stuff */ errno = EINVAL; - return (-1); + return -1; } -static int parse_owner (struct passwd **user, struct group **group, +static int parse_owner(struct passwd **user, struct group **group, const char *owner) { char *u = xstrdup (owner); @@ -137,25 +138,25 @@ static int parse_owner (struct passwd **user, struct group **group, *g++ = '\0'; if (user && *u) { - if (sscanf (u, "%d", &id) == 1) - *user = getpwuid ((uid_t) id); + if (sscanf(u, "%d", &id) == 1) + *user = getpwuid((uid_t) id); else - *user = getpwnam (u); + *user = getpwnam(u); if (! *user) retval = -1; } if (group && g && *g) { - if (sscanf (g, "%d", &id) == 1) - *group = getgrgid ((gid_t) id); + if (sscanf(g, "%d", &id) == 1) + *group = getgrgid((gid_t) id); else - *group = getgrnam (g); + *group = getgrnam(g); if (! *group) retval = -1; } - free (u); - return (retval); + free(u); + return retval; } #include "_usage.h" @@ -177,7 +178,7 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int checkpath (int argc, char **argv) +int checkpath(int argc, char **argv) { int opt; uid_t uid = geteuid(); @@ -188,33 +189,31 @@ int checkpath (int argc, char **argv) bool file = 0; int retval = EXIT_SUCCESS; - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, + longopts, (int *) 0)) != -1) { switch (opt) { - case 'd': - file = 0; - break; - case 'f': - file = 1; - break; - case 'm': - if (parse_mode (&mode, optarg) != 0) - eerrorx ("%s: invalid mode `%s'", - applet, optarg); - break; - case 'o': - if (parse_owner (&pw, &gr, optarg) != 0) - eerrorx ("%s: owner `%s' not found", - applet, optarg); - break; - - case_RC_COMMON_GETOPT + case 'd': + file = 0; + break; + case 'f': + file = 1; + break; + case 'm': + if (parse_mode(&mode, optarg) != 0) + eerrorx("%s: invalid mode `%s'", applet, optarg); + break; + case 'o': + if (parse_owner(&pw, &gr, optarg) != 0) + eerrorx("%s: owner `%s' not found", applet, optarg); + break; + + case_RC_COMMON_GETOPT } } if (optind >= argc) - usage (EXIT_FAILURE); + usage(EXIT_FAILURE); if (pw) { uid = pw->pw_uid; @@ -224,11 +223,11 @@ int checkpath (int argc, char **argv) gid = gr->gr_gid; while (optind < argc) { - if (do_check (argv[optind], uid, gid, mode, file)) + if (do_check(argv[optind], uid, gid, mode, file)) retval = EXIT_FAILURE; optind++; } - exit (retval); + exit(retval); /* NOTREACHED */ } diff --git a/src/rc/fstabinfo.c b/src/rc/fstabinfo.c index 309c6842..54812bfe 100644 --- a/src/rc/fstabinfo.c +++ b/src/rc/fstabinfo.c @@ -30,6 +30,7 @@ */ #include <sys/wait.h> + #include <errno.h> #include <getopt.h> #include <stdio.h> @@ -72,27 +73,26 @@ #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" #ifdef HAVE_GETMNTENT -static struct mntent *getmntfile (const char *file) +static struct mntent *getmntfile(const char *file) { - struct mntent *ent = NULL; + struct mntent *ent; FILE *fp; START_ENT; - while ((ent = getmntent (fp))) - if (strcmp (file, ent->mnt_dir) == 0) + while ((ent = getmntent(fp))) + if (strcmp(file, ent->mnt_dir) == 0) break; END_ENT; - return (ent); + return ent; } #endif extern const char *applet; -static int do_mount (struct ENT *ent) +static int do_mount(struct ENT *ent) { char *argv[8]; pid_t pid; @@ -100,29 +100,27 @@ static int do_mount (struct ENT *ent) argv[0] = (char *) "mount"; argv[1] = (char *) "-o"; - argv[2] = ENT_OPTS (*ent); + argv[2] = ENT_OPTS(*ent); argv[3] = (char *) "-t"; - argv[4] = ENT_TYPE (*ent); - argv[5] = ENT_BLOCKDEVICE (*ent); - argv[6] = ENT_FILE (*ent); + argv[4] = ENT_TYPE(*ent); + argv[5] = ENT_BLOCKDEVICE(*ent); + argv[6] = ENT_FILE(*ent); argv[7] = NULL; switch (pid = vfork()) { case -1: - eerrorx ("%s: vfork: %s", applet, - strerror (errno)); + eerrorx("%s: vfork: %s", applet, strerror(errno)); /* NOTREACHED */ case 0: - execvp (argv[0], argv); - eerror ("%s: execv: %s", applet, - strerror (errno)); + execvp(argv[0], argv); + eerror("%s: execv: %s", applet, strerror(errno)); _exit(EXIT_FAILURE); /* NOTREACHED */ default: - waitpid (pid, &status, 0); - if (WIFEXITED (status)) - return (WEXITSTATUS(status)); + waitpid(pid, &status, 0); + if (WIFEXITED(status)) + return WEXITSTATUS(status); else - return (-1); + return -1; /* NOTREACHED */ } } @@ -155,7 +153,7 @@ static const char * const longopts_help[] = { #define OUTPUT_BLOCKDEV (1 << 5) #define OUTPUT_MOUNT (1 << 6) -int fstabinfo (int argc, char **argv) +int fstabinfo(int argc, char **argv) { struct ENT *ent; int result = EXIT_SUCCESS; @@ -163,8 +161,8 @@ int fstabinfo (int argc, char **argv) int i; int opt; int output = OUTPUT_FILE; - char **files = NULL; - char *file; + RC_STRINGLIST *files = rc_stringlist_new(); + RC_STRING *file; bool filtered = false; #ifdef HAVE_GETMNTENT @@ -172,125 +170,126 @@ int fstabinfo (int argc, char **argv) #endif /* Ensure that we are only quiet when explicitly told to be */ - unsetenv ("EINFO_QUIET"); + unsetenv("EINFO_QUIET"); - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, + longopts, (int *) 0)) != -1) { switch (opt) { - case 'M': - output = OUTPUT_MOUNT; - break; - case 'b': - output = OUTPUT_BLOCKDEV; - break; - case 'o': - output = OUTPUT_OPTIONS; - break; - case 'm': - output = OUTPUT_MOUNTARGS; - break; + case 'M': + output = OUTPUT_MOUNT; + break; + case 'b': + output = OUTPUT_BLOCKDEV; + break; + case 'o': + output = OUTPUT_OPTIONS; + break; + case 'm': + output = OUTPUT_MOUNTARGS; + break; - case 'p': - switch (optarg[0]) { - case '=': - case '<': - case '>': - if (sscanf (optarg + 1, "%d", &i) != 1) - eerrorx ("%s: invalid passno %s", argv[0], optarg + 1); - - filtered = true; - START_ENT; - while ((ent = GET_ENT)) { - if (((optarg[0] == '=' && i == ENT_PASS (ent)) || - (optarg[0] == '<' && i > ENT_PASS (ent)) || - (optarg[0] == '>' && i < ENT_PASS (ent))) && - strcmp (ENT_FILE (ent), "none") != 0) - rc_strlist_add (&files, ENT_FILE (ent)); - } - END_ENT; - break; - - default: - rc_strlist_add (&files, optarg); - output = OUTPUT_PASSNO; - break; - } - break; + case 'p': + switch (optarg[0]) { + case '=': + case '<': + case '>': + if (sscanf(optarg + 1, "%d", &i) != 1) + eerrorx("%s: invalid passno %s", + argv[0], optarg + 1); - case 't': filtered = true; - while ((token = strsep (&optarg, ","))) { - START_ENT; - while ((ent = GET_ENT)) - if (strcmp (token, ENT_TYPE (ent)) == 0) - rc_strlist_add (&files, ENT_FILE (ent)); - END_ENT; + START_ENT; + while ((ent = GET_ENT)) { + if (((optarg[0] == '=' && i == ENT_PASS(ent)) || + (optarg[0] == '<' && i > ENT_PASS(ent)) || + (optarg[0] == '>' && i < ENT_PASS(ent))) && + strcmp(ENT_FILE(ent), "none") != 0) + rc_stringlist_add(files, ENT_FILE(ent)); } + END_ENT; break; - case_RC_COMMON_GETOPT + default: + rc_stringlist_add(files, optarg); + output = OUTPUT_PASSNO; + break; + } + break; + + case 't': + filtered = true; + while ((token = strsep(&optarg, ","))) { + START_ENT; + while ((ent = GET_ENT)) + if (strcmp(token, ENT_TYPE(ent)) == 0) + rc_stringlist_add(files, ENT_FILE(ent)); + END_ENT; + } + break; + + case_RC_COMMON_GETOPT } } - while (optind < argc) - rc_strlist_add (&files, argv[optind++]); - - if (! files && ! filtered) { + if (optind < argc) { + while (optind < argc) + rc_stringlist_add(files, argv[optind++]); + } else if (! filtered) { START_ENT; while ((ent = GET_ENT)) - rc_strlist_add (&files, ENT_FILE (ent)); + rc_stringlist_add(files, ENT_FILE(ent)); END_ENT; - if (! files) - eerrorx ("%s: emtpy fstab", argv[0]); + if (! TAILQ_FIRST(files)) + eerrorx("%s: emtpy fstab", argv[0]); } /* Ensure we always display something */ START_ENT; - STRLIST_FOREACH (files, file, i) { - if (! (ent = GET_ENT_FILE (file))) { + TAILQ_FOREACH(file, files, entries) { + if (! (ent = GET_ENT_FILE(file->value))) { result = EXIT_FAILURE; continue; } /* No point in outputting if quiet */ - if (rc_yesno (getenv ("EINFO_QUIET"))) + if (rc_yesno(getenv("EINFO_QUIET"))) continue; switch (output) { - case OUTPUT_BLOCKDEV: - printf ("%s\n", ENT_BLOCKDEVICE (ent)); - break; + case OUTPUT_BLOCKDEV: + printf("%s\n", ENT_BLOCKDEVICE(ent)); + break; - case OUTPUT_MOUNT: - result += do_mount (ent); - break; + case OUTPUT_MOUNT: + result += do_mount(ent); + break; - case OUTPUT_MOUNTARGS: - printf ("-o %s -t %s %s %s\n", - ENT_OPTS (ent), - ENT_TYPE (ent), - ENT_BLOCKDEVICE (ent), - file); - break; + case OUTPUT_MOUNTARGS: + printf("-o %s -t %s %s %s\n", + ENT_OPTS(ent), + ENT_TYPE(ent), + ENT_BLOCKDEVICE(ent), + file->value); + break; - case OUTPUT_OPTIONS: - printf ("%s\n", ENT_OPTS (ent)); - break; + case OUTPUT_OPTIONS: + printf("%s\n", ENT_OPTS(ent)); + break; - case OUTPUT_FILE: - printf ("%s\n", file); - break; + case OUTPUT_FILE: + printf("%s\n", file->value); + break; - case OUTPUT_PASSNO: - printf ("%d\n", ENT_PASS (ent)); - break; + case OUTPUT_PASSNO: + printf("%d\n", ENT_PASS(ent)); + break; } } END_ENT; - rc_strlist_free (files); - exit (result); + rc_stringlist_free(files); + exit(result); /* NOTREACHED */ } diff --git a/src/rc/mountinfo.c b/src/rc/mountinfo.c index a05c3929..3adff5de 100644 --- a/src/rc/mountinfo.c +++ b/src/rc/mountinfo.c @@ -47,16 +47,15 @@ #include <errno.h> #include <getopt.h> #include <limits.h> +#include <regex.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <regex.h> #include "builtins.h" #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" extern const char *applet; @@ -80,93 +79,93 @@ struct args { regex_t *skip_fstype_regex; regex_t *options_regex; regex_t *skip_options_regex; - char **mounts; + RC_STRINGLIST *mounts; mount_type mount_type; net_opts netdev; }; -static int process_mount (char ***list, struct args *args, - char *from, char *to, char *fstype, char *options, - int netdev) +static int process_mount(RC_STRINGLIST *list, struct args *args, + char *from, char *to, char *fstype, char *options, + int netdev) { char *p; + RC_STRING *s; errno = ENOENT; #ifdef __linux__ /* Skip the really silly rootfs */ - if (strcmp (fstype, "rootfs") == 0) - return (-1); + if (strcmp(fstype, "rootfs") == 0) + return -1; #endif - if (args->netdev == net_yes && (netdev != -1 || args->mounts)) { + if (args->netdev == net_yes && + (netdev != -1 || TAILQ_FIRST(args->mounts))) + { if (netdev != 0) - return (1); - } else if (args->netdev == net_no && (netdev != -1 || args->mounts)) { + return 1; + } else if (args->netdev == net_no && + (netdev != -1 || TAILQ_FIRST(args->mounts))) + { if (netdev != 1) - return (1); + return 1; } else { if (args->node_regex && - regexec (args->node_regex, from, 0, NULL, 0) != 0) - return (1); + regexec(args->node_regex, from, 0, NULL, 0) != 0) + return 1; if (args->skip_node_regex && - regexec (args->skip_node_regex, from, 0, NULL, 0) == 0) - return (1); + regexec(args->skip_node_regex, from, 0, NULL, 0) == 0) + return 1; if (args->fstype_regex && - regexec (args->fstype_regex, fstype, 0, NULL, 0) != 0) - return (-1); + regexec(args->fstype_regex, fstype, 0, NULL, 0) != 0) + return -1; if (args->skip_fstype_regex && - regexec (args->skip_fstype_regex, fstype, 0, NULL, 0) == 0) - return (-1); + regexec(args->skip_fstype_regex, fstype, 0, NULL, 0) == 0) + return -1; if (args->options_regex && - regexec (args->options_regex, options, 0, NULL, 0) != 0) - return (-1); + regexec(args->options_regex, options, 0, NULL, 0) != 0) + return -1; if (args->skip_options_regex && - regexec (args->skip_options_regex, options, 0, NULL, 0) == 0) - return (-1); + regexec(args->skip_options_regex, options, 0, NULL, 0) == 0) + return -1; } - if (args->mounts) { - bool found = false; - int j; - char *mnt; - STRLIST_FOREACH (args->mounts, mnt, j) - if (strcmp (mnt, to) == 0) { - found = true; + if (TAILQ_FIRST(args->mounts)) { + TAILQ_FOREACH(s, args->mounts, entries) + if (strcmp(s->value, to) == 0) break; - } - if (! found) - return (-1); + if (! s) + return -1; } switch (args->mount_type) { - case mount_from: - p = from; - break; - case mount_to: - p = to; - break; - case mount_fstype: - p = fstype; - break; - case mount_options: - p = options; - break; - default: - p = NULL; - errno = EINVAL; - break; + case mount_from: + p = from; + break; + case mount_to: + p = to; + break; + case mount_fstype: + p = fstype; + break; + case mount_options: + p = options; + break; + default: + p = NULL; + errno = EINVAL; + break; } if (p) { errno = 0; - rc_strlist_addsortc (list, p); - return (0); + rc_stringlist_add(list, p); + return 0; } - return (-1); + return -1; } #ifdef BSD @@ -212,70 +211,73 @@ static struct opt { { 0, NULL } }; -static char **find_mounts (struct args *args) +static RC_STRINGLIST *find_mounts(struct args *args) { struct statfs *mnts; int nmnts; int i; - char **list = NULL; + RC_STRINGLIST *list; char *options = NULL; uint64_t flags; struct opt *o; + int netdev; + char *tmp; + size_t l; - if ((nmnts = getmntinfo (&mnts, MNT_NOWAIT)) == 0) - eerrorx ("getmntinfo: %s", strerror (errno)); + if ((nmnts = getmntinfo(&mnts, MNT_NOWAIT)) == 0) + eerrorx("getmntinfo: %s", strerror (errno)); + list = rc_stringlist_new(); for (i = 0; i < nmnts; i++) { - int netdev = 0; + netdev = 0; flags = mnts[i].F_FLAGS & MNT_VISFLAGMASK; for (o = optnames; flags && o->o_opt; o++) { if (flags & o->o_opt) { if (o->o_opt == MNT_LOCAL) netdev = 1; if (! options) - options = xstrdup (o->o_name); + options = xstrdup(o->o_name); else { - char *tmp = NULL; - size_t l = strlen (options) + strlen (o->o_name) + 2; - tmp = xmalloc (sizeof (char) * l); - snprintf (tmp, l, "%s,%s", options, o->o_name); - free (options); + l = strlen(options) + strlen(o->o_name) + 2; + tmp = xmalloc(sizeof (char) * l); + snprintf(tmp, l, "%s,%s", options, o->o_name); + free(options); options = tmp; } } flags &= ~o->o_opt; } - process_mount (&list, args, - mnts[i].f_mntfromname, - mnts[i].f_mntonname, - mnts[i].f_fstypename, - options, - netdev); + process_mount(list, args, + mnts[i].f_mntfromname, + mnts[i].f_mntonname, + mnts[i].f_fstypename, + options, + netdev); - free (options); + free(options); options = NULL; } - return (list); + return list; } #elif defined (__linux__) -static struct mntent *getmntfile (const char *file) +static struct mntent *getmntfile(const char *file) { struct mntent *ent = NULL; FILE *fp; - fp = setmntent ("/etc/fstab", "r"); - while ((ent = getmntent (fp))) - if (strcmp (file, ent->mnt_dir) == 0) + fp = setmntent("/etc/fstab", "r"); + while ((ent = getmntent(fp))) + if (strcmp(file, ent->mnt_dir) == 0) break; - endmntent (fp); + endmntent(fp); - return (ent); + return ent; } -static char **find_mounts (struct args *args) +static RC_STRINGLIST *find_mounts(struct args *args) { FILE *fp; char *buffer; @@ -284,52 +286,54 @@ static char **find_mounts (struct args *args) char *to; char *fst; char *opts; - char **list = NULL; struct mntent *ent; int netdev; + RC_STRINGLIST *list; - if ((fp = fopen ("/proc/mounts", "r")) == NULL) - eerrorx ("getmntinfo: %s", strerror (errno)); + if ((fp = fopen("/proc/mounts", "r")) == NULL) + eerrorx("getmntinfo: %s", strerror(errno)); - buffer = xmalloc (sizeof (char) * PATH_MAX * 3); - while (fgets (buffer, PATH_MAX * 3, fp)) { + list = rc_stringlist_new(); + + buffer = xmalloc(sizeof(char) * PATH_MAX * 3); + while (fgets(buffer, PATH_MAX * 3, fp)) { netdev = -1; p = buffer; - from = strsep (&p, " "); - to = strsep (&p, " "); - fst = strsep (&p, " "); - opts = strsep (&p, " "); + from = strsep(&p, " "); + to = strsep(&p, " "); + fst = strsep(&p, " "); + opts = strsep(&p, " "); - if ((ent = getmntfile (to))) { - if (strstr (ent->mnt_opts, "_netdev")) + if ((ent = getmntfile(to))) { + if (strstr(ent->mnt_opts, "_netdev")) netdev = 0; } - process_mount (&list, args, from, to, fst, opts, netdev); + process_mount(list, args, from, to, fst, opts, netdev); } - free (buffer); - fclose (fp); + free(buffer); + fclose(fp); - return (list); + return list; } #else # error "Operating system not supported!" #endif -static regex_t *get_regex (const char *string) +static regex_t *get_regex(const char *string) { - regex_t *reg = xmalloc (sizeof (*reg)); + regex_t *reg = xmalloc(sizeof (*reg)); int result; char buffer[256]; - if ((result = regcomp (reg, string, REG_EXTENDED | REG_NOSUB)) != 0) + if ((result = regcomp(reg, string, REG_EXTENDED | REG_NOSUB)) != 0) { - regerror (result, reg, buffer, sizeof (buffer)); - eerrorx ("%s: invalid regex `%s'", applet, buffer); + regerror(result, reg, buffer, sizeof(buffer)); + eerrorx("%s: invalid regex `%s'", applet, buffer); } - return (reg); + return reg; } #include "_usage.h" @@ -347,7 +351,7 @@ static const struct option longopts[] = { { "options", 0, NULL, 'i'}, { "fstype", 0, NULL, 's'}, { "node", 0, NULL, 't'}, - { "netdev", 0, NULL, 'e'}, + { "netdev", 0, NULL, 'e'}, { "nonetdev", 0, NULL, 'E'}, longopts_COMMON }; @@ -369,112 +373,113 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int mountinfo (int argc, char **argv) +int mountinfo(int argc, char **argv) { - int i; struct args args; regex_t *point_regex = NULL; regex_t *skip_point_regex = NULL; - char **nodes = NULL; - char *n; + RC_STRINGLIST *nodes; + RC_STRING *s; int opt; int result; bool quiet; /* Ensure that we are only quiet when explicitly told to be */ - unsetenv ("EINFO_QUIET"); + unsetenv("EINFO_QUIET"); #define DO_REG(_var) \ - if (_var) free (_var); \ - _var = get_regex (optarg); + if (_var) free(_var); \ + _var = get_regex(optarg); #define REG_FREE(_var) \ - if (_var) { regfree (_var); free (_var); } + if (_var) { regfree(_var); free(_var); } - memset (&args, 0, sizeof (args)); + memset (&args, 0, sizeof(args)); args.mount_type = mount_to; args.netdev = net_ignore; + args.mounts = rc_stringlist_new(); - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, + longopts, (int *) 0)) != -1) { switch (opt) { - case 'e': - args.netdev = net_yes; - break; - case 'E': - args.netdev = net_no; - break; - case 'f': - DO_REG (args.fstype_regex); - break; - case 'F': - DO_REG (args.skip_fstype_regex); - break; - case 'n': - DO_REG (args.node_regex); - break; - case 'N': - DO_REG (args.skip_node_regex); - break; - case 'o': - DO_REG (args.options_regex); - break; - case 'O': - DO_REG (args.skip_options_regex); - break; - case 'p': - DO_REG (point_regex); - break; - case 'P': - DO_REG (skip_point_regex); - break; - case 'i': - args.mount_type = mount_options; - break; - case 's': - args.mount_type = mount_fstype; - break; - case 't': - args.mount_type = mount_from; - break; + case 'e': + args.netdev = net_yes; + break; + case 'E': + args.netdev = net_no; + break; + case 'f': + DO_REG(args.fstype_regex); + break; + case 'F': + DO_REG(args.skip_fstype_regex); + break; + case 'n': + DO_REG(args.node_regex); + break; + case 'N': + DO_REG(args.skip_node_regex); + break; + case 'o': + DO_REG(args.options_regex); + break; + case 'O': + DO_REG(args.skip_options_regex); + break; + case 'p': + DO_REG(point_regex); + break; + case 'P': + DO_REG(skip_point_regex); + break; + case 'i': + args.mount_type = mount_options; + break; + case 's': + args.mount_type = mount_fstype; + break; + case 't': + args.mount_type = mount_from; + break; - case_RC_COMMON_GETOPT + case_RC_COMMON_GETOPT } } while (optind < argc) { if (argv[optind][0] != '/') - eerrorx ("%s: `%s' is not a mount point", argv[0], argv[optind]); - rc_strlist_add (&args.mounts, argv[optind++]); + eerrorx("%s: `%s' is not a mount point", argv[0], argv[optind]); + rc_stringlist_add(args.mounts, argv[optind++]); } + nodes = find_mounts(&args); + rc_stringlist_free(args.mounts); + rc_stringlist_sort(&nodes); - nodes = find_mounts (&args); - - REG_FREE (args.fstype_regex); - REG_FREE (args.skip_fstype_regex); - REG_FREE (args.node_regex); - REG_FREE (args.skip_node_regex); - REG_FREE (args.options_regex); - REG_FREE (args.skip_options_regex); - - rc_strlist_reverse (nodes); + REG_FREE(args.fstype_regex); + REG_FREE(args.skip_fstype_regex); + REG_FREE(args.node_regex); + REG_FREE(args.skip_node_regex); + REG_FREE(args.options_regex); + REG_FREE(args.skip_options_regex); result = EXIT_FAILURE; - quiet = rc_yesno (getenv ("EINFO_QUIET")); - STRLIST_FOREACH (nodes, n, i) { - if (point_regex && regexec (point_regex, n, 0, NULL, 0) != 0) + quiet = rc_yesno(getenv("EINFO_QUIET")); + TAILQ_FOREACH_REVERSE(s, nodes, rc_stringlist, entries) { + if (point_regex && + regexec(point_regex, s->value, 0, NULL, 0) != 0) continue; - if (skip_point_regex && regexec (skip_point_regex, n, 0, NULL, 0) == 0) + if (skip_point_regex && + regexec(skip_point_regex, s->value, 0, NULL, 0) == 0) continue; if (! quiet) - printf ("%s\n", n); + printf("%s\n", s->value); result = EXIT_SUCCESS; } - rc_strlist_free (nodes); + rc_stringlist_free(nodes); - REG_FREE (point_regex); - REG_FREE (skip_point_regex); + REG_FREE(point_regex); + REG_FREE(skip_point_regex); - exit (result); + exit(result); /* NOTREACHED */ } diff --git a/src/rc/rc-applets.c b/src/rc/rc-applets.c index 5f242f70..96b392d8 100644 --- a/src/rc/rc-applets.c +++ b/src/rc/rc-applets.c @@ -35,6 +35,7 @@ #define SYSLOG_NAMES #include <sys/types.h> + #include <errno.h> #include <ctype.h> #include <inttypes.h> @@ -49,26 +50,25 @@ #include "builtins.h" #include "einfo.h" #include "rc-misc.h" -#include "strlist.h" /* Applet is first parsed in rc.c - no point in doing it again */ extern const char *applet; -static int syslog_decode (char *name, CODE *codetab) +static int syslog_decode(char *name, CODE *codetab) { CODE *c; - if (isdigit ((int) *name)) - return (atoi (name)); + if (isdigit((int) *name)) + return atoi(name); for (c = codetab; c->c_name; c++) - if (! strcasecmp (name, c->c_name)) - return (c->c_val); + if (! strcasecmp(name, c->c_name)) + return c->c_val; - return (-1); + return -1; } -static int do_e (int argc, char **argv) +static int do_e(int argc, char **argv) { int retval = EXIT_SUCCESS; int i; @@ -82,42 +82,42 @@ static int do_e (int argc, char **argv) argc--; argv++; - if (strcmp (applet, "eval_ecolors") == 0) { - printf ("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n", - ecolor (ECOLOR_GOOD), - ecolor (ECOLOR_WARN), - ecolor (ECOLOR_BAD), - ecolor (ECOLOR_HILITE), - ecolor (ECOLOR_BRACKET), - ecolor (ECOLOR_NORMAL)); - exit (EXIT_SUCCESS); + if (strcmp(applet, "eval_ecolors") == 0) { + printf("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n", + ecolor(ECOLOR_GOOD), + ecolor(ECOLOR_WARN), + ecolor(ECOLOR_BAD), + ecolor(ECOLOR_HILITE), + ecolor(ECOLOR_BRACKET), + ecolor(ECOLOR_NORMAL)); + exit(EXIT_SUCCESS); } if (argc > 0) { - if (strcmp (applet, "eend") == 0 || - strcmp (applet, "ewend") == 0 || - strcmp (applet, "veend") == 0 || - strcmp (applet, "vweend") == 0) + if (strcmp(applet, "eend") == 0 || + strcmp(applet, "ewend") == 0 || + strcmp(applet, "veend") == 0 || + strcmp(applet, "vweend") == 0) { errno = 0; - retval = (int) strtoimax (argv[0], NULL, 0); + retval = (int) strtoimax(argv[0], NULL, 0); if (errno != 0) retval = EXIT_FAILURE; else { argc--; argv++; } - } else if (strcmp (applet, "esyslog") == 0 || - strcmp (applet, "elog") == 0) { - char *dot = strchr (argv[0], '.'); - if ((level = syslog_decode (dot + 1, prioritynames)) == -1) - eerrorx ("%s: invalid log level `%s'", applet, argv[0]); + } else if (strcmp(applet, "esyslog") == 0 || + strcmp(applet, "elog") == 0) { + p = strchr(argv[0], '.'); + if ((level = syslog_decode(p + 1, prioritynames)) == -1) + eerrorx("%s: invalid log level `%s'", applet, argv[0]); if (argc < 3) - eerrorx ("%s: not enough arguments", applet); + eerrorx("%s: not enough arguments", applet); - unsetenv ("EINFO_LOG"); - setenv ("EINFO_LOG", argv[1], 1); + unsetenv("EINFO_LOG"); + setenv("EINFO_LOG", argv[1], 1); argc -= 2; argv += 2; @@ -126,16 +126,17 @@ static int do_e (int argc, char **argv) if (argc > 0) { for (i = 0; i < argc; i++) - l += strlen (argv[i]) + 1; + l += strlen(argv[i]) + 1; - message = xmalloc (l); + message = xmalloc(l); p = message; for (i = 0; i < argc; i++) { if (i > 0) *p++ = ' '; - memcpy (p, argv[i], strlen (argv[i])); - p += strlen (argv[i]); + l = strlen(argv[i]); + memcpy(p, argv[i], l); + p += l; } *p = 0; } @@ -143,300 +144,302 @@ static int do_e (int argc, char **argv) if (! message) fmt = ""; - if (strcmp (applet, "einfo") == 0) - einfo (fmt, message); - else if (strcmp (applet, "einfon") == 0) - einfon (fmt, message); - else if (strcmp (applet, "ewarn") == 0) - ewarn (fmt, message); - else if (strcmp (applet, "ewarnn") == 0) - ewarnn (fmt, message); - else if (strcmp (applet, "eerror") == 0) { - eerror (fmt, message); + if (strcmp(applet, "einfo") == 0) + einfo(fmt, message); + else if (strcmp(applet, "einfon") == 0) + einfon(fmt, message); + else if (strcmp(applet, "ewarn") == 0) + ewarn(fmt, message); + else if (strcmp(applet, "ewarnn") == 0) + ewarnn(fmt, message); + else if (strcmp(applet, "eerror") == 0) { + eerror(fmt, message); retval = 1; - } else if (strcmp (applet, "eerrorn") == 0) { - eerrorn (fmt, message); + } else if (strcmp(applet, "eerrorn") == 0) { + eerrorn(fmt, message); retval = 1; - } else if (strcmp (applet, "ebegin") == 0) - ebegin (fmt, message); - else if (strcmp (applet, "eend") == 0) - eend (retval, fmt, message); - else if (strcmp (applet, "ewend") == 0) - ewend (retval, fmt, message); - else if (strcmp (applet, "esyslog") == 0) - elog (level, fmt, message); - else if (strcmp (applet, "veinfo") == 0) - einfov (fmt, message); - else if (strcmp (applet, "veinfon") == 0) - einfovn (fmt, message); - else if (strcmp (applet, "vewarn") == 0) - ewarnv (fmt, message); - else if (strcmp (applet, "vewarnn") == 0) - ewarnvn (fmt, message); - else if (strcmp (applet, "vebegin") == 0) - ebeginv (fmt, message); - else if (strcmp (applet, "veend") == 0) - eendv (retval, fmt, message); - else if (strcmp (applet, "vewend") == 0) - ewendv (retval, fmt, message); - else if (strcmp (applet, "eindent") == 0) - eindent (); - else if (strcmp (applet, "eoutdent") == 0) - eoutdent (); - else if (strcmp (applet, "veindent") == 0) - eindentv (); - else if (strcmp (applet, "veoutdent") == 0) - eoutdentv (); + } else if (strcmp(applet, "ebegin") == 0) + ebegin(fmt, message); + else if (strcmp(applet, "eend") == 0) + eend(retval, fmt, message); + else if (strcmp(applet, "ewend") == 0) + ewend(retval, fmt, message); + else if (strcmp(applet, "esyslog") == 0) + elog(level, fmt, message); + else if (strcmp(applet, "veinfo") == 0) + einfov(fmt, message); + else if (strcmp(applet, "veinfon") == 0) + einfovn(fmt, message); + else if (strcmp(applet, "vewarn") == 0) + ewarnv(fmt, message); + else if (strcmp(applet, "vewarnn") == 0) + ewarnvn(fmt, message); + else if (strcmp(applet, "vebegin") == 0) + ebeginv(fmt, message); + else if (strcmp(applet, "veend") == 0) + eendv(retval, fmt, message); + else if (strcmp(applet, "vewend") == 0) + ewendv(retval, fmt, message); + else if (strcmp(applet, "eindent") == 0) + eindent(); + else if (strcmp(applet, "eoutdent") == 0) + eoutdent(); + else if (strcmp(applet, "veindent") == 0) + eindentv(); + else if (strcmp(applet, "veoutdent") == 0) + eoutdentv(); else { - eerror ("%s: unknown applet", applet); + eerror("%s: unknown applet", applet); retval = EXIT_FAILURE; } - free (message); - return (retval); + free(message); + return retval; } -static int do_service (int argc, char **argv) +static int do_service(int argc, char **argv) { bool ok = false; char *service = NULL; + int idx = 0; + char *d[] = { NULL, NULL }; if (argc > 1) service = argv[1]; else - service = getenv ("SVCNAME"); + service = getenv("SVCNAME"); if (! service || *service == '\0') - eerrorx ("%s: no service specified", applet); - - if (strcmp (applet, "service_started") == 0) - ok = (rc_service_state (service) & RC_SERVICE_STARTED); - else if (strcmp (applet, "service_stopped") == 0) - ok = (rc_service_state (service) & RC_SERVICE_STOPPED); - else if (strcmp (applet, "service_inactive") == 0) - ok = (rc_service_state (service) & RC_SERVICE_INACTIVE); - else if (strcmp (applet, "service_starting") == 0) - ok = (rc_service_state (service) & RC_SERVICE_STARTING); - else if (strcmp (applet, "service_stopping") == 0) - ok = (rc_service_state (service) & RC_SERVICE_STOPPING); - else if (strcmp (applet, "service_coldplugged") == 0) - ok = (rc_service_state (service) & RC_SERVICE_COLDPLUGGED); - else if (strcmp (applet, "service_wasinactive") == 0) - ok = (rc_service_state (service) & RC_SERVICE_WASINACTIVE); - else if (strcmp (applet, "service_started_daemon") == 0) { - int idx = 0; - char *d[] = { argv[1], NULL }; - - service = getenv ("SVCNAME"); + eerrorx("%s: no service specified", applet); + + if (strcmp(applet, "service_started") == 0) + ok = (rc_service_state(service) & RC_SERVICE_STARTED); + else if (strcmp(applet, "service_stopped") == 0) + ok = (rc_service_state(service) & RC_SERVICE_STOPPED); + else if (strcmp(applet, "service_inactive") == 0) + ok = (rc_service_state(service) & RC_SERVICE_INACTIVE); + else if (strcmp(applet, "service_starting") == 0) + ok = (rc_service_state(service) & RC_SERVICE_STARTING); + else if (strcmp(applet, "service_stopping") == 0) + ok = (rc_service_state(service) & RC_SERVICE_STOPPING); + else if (strcmp(applet, "service_coldplugged") == 0) + ok = (rc_service_state(service) & RC_SERVICE_COLDPLUGGED); + else if (strcmp(applet, "service_wasinactive") == 0) + ok = (rc_service_state(service) & RC_SERVICE_WASINACTIVE); + else if (strcmp(applet, "service_started_daemon") == 0) { + d[0] = argv[1]; + + service = getenv("SVCNAME"); if (argc > 3) { service = argv[1]; d[0] = argv[2]; - sscanf (argv[3], "%d", &idx); + sscanf(argv[3], "%d", &idx); } else if (argc == 3) { - if (sscanf (argv[2], "%d", &idx) != 1) { + if (sscanf(argv[2], "%d", &idx) != 1) { service = argv[1]; - *d = argv[2]; + d[0] = argv[2]; } } - ok = rc_service_started_daemon (service, - (const char * const *)d, idx); + ok = rc_service_started_daemon(service, + (const char * const *)d, idx); } else - eerrorx ("%s: unknown applet", applet); + eerrorx("%s: unknown applet", applet); - return (ok ? EXIT_SUCCESS : EXIT_FAILURE); + return ok ? EXIT_SUCCESS : EXIT_FAILURE; } -static int do_mark_service (int argc, char **argv) +static int do_mark_service(int argc, char **argv) { bool ok = false; - char *svcname = getenv ("SVCNAME"); + char *svcname = getenv("SVCNAME"); char *service = NULL; + char *runscript_pid; + char *mtime; + pid_t pid; + size_t l; if (argc > 1) service = argv[1]; else - service = getenv ("SVCNAME"); + service = getenv("SVCNAME"); if (! service || *service == '\0') - eerrorx ("%s: no service specified", applet); - - if (strcmp (applet, "mark_service_started") == 0) - ok = rc_service_mark (service, RC_SERVICE_STARTED); - else if (strcmp (applet, "mark_service_stopped") == 0) - ok = rc_service_mark (service, RC_SERVICE_STOPPED); - else if (strcmp (applet, "mark_service_inactive") == 0) - ok = rc_service_mark (service, RC_SERVICE_INACTIVE); - else if (strcmp (applet, "mark_service_starting") == 0) - ok = rc_service_mark (service, RC_SERVICE_STARTING); - else if (strcmp (applet, "mark_service_stopping") == 0) - ok = rc_service_mark (service, RC_SERVICE_STOPPING); - else if (strcmp (applet, "mark_service_coldplugged") == 0) - ok = rc_service_mark (service, RC_SERVICE_COLDPLUGGED); - else if (strcmp (applet, "mark_service_failed") == 0) - ok = rc_service_mark (service, RC_SERVICE_FAILED); + eerrorx("%s: no service specified", applet); + + if (strcmp(applet, "mark_service_started") == 0) + ok = rc_service_mark(service, RC_SERVICE_STARTED); + else if (strcmp(applet, "mark_service_stopped") == 0) + ok = rc_service_mark(service, RC_SERVICE_STOPPED); + else if (strcmp(applet, "mark_service_inactive") == 0) + ok = rc_service_mark(service, RC_SERVICE_INACTIVE); + else if (strcmp(applet, "mark_service_starting") == 0) + ok = rc_service_mark(service, RC_SERVICE_STARTING); + else if (strcmp(applet, "mark_service_stopping") == 0) + ok = rc_service_mark(service, RC_SERVICE_STOPPING); + else if (strcmp(applet, "mark_service_coldplugged") == 0) + ok = rc_service_mark(service, RC_SERVICE_COLDPLUGGED); + else if (strcmp(applet, "mark_service_failed") == 0) + ok = rc_service_mark(service, RC_SERVICE_FAILED); else - eerrorx ("%s: unknown applet", applet); + eerrorx("%s: unknown applet", applet); /* If we're marking ourselves then we need to inform our parent runscript process so they do not mark us based on our exit code */ - if (ok && svcname && strcmp (svcname, service) == 0) { - char *runscript_pid = getenv ("RC_RUNSCRIPT_PID"); - char *mtime; - pid_t pid = 0; - size_t l; - - if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1) - if (kill (pid, SIGHUP) != 0) - eerror ("%s: failed to signal parent %d: %s", - applet, pid, strerror (errno)); + if (ok && svcname && strcmp(svcname, service) == 0) { + runscript_pid = getenv("RC_RUNSCRIPT_PID"); + if (runscript_pid && sscanf(runscript_pid, "%d", &pid) == 1) + if (kill(pid, SIGHUP) != 0) + eerror("%s: failed to signal parent %d: %s", + applet, pid, strerror(errno)); /* Remove the exclusive time test. This ensures that it's not in control as well */ - l = strlen (RC_SVCDIR "exclusive") + - strlen (svcname) + - strlen (runscript_pid) + - 4; - mtime = xmalloc (l); - snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s", - svcname, runscript_pid); - if (exists (mtime) && unlink (mtime) != 0) - eerror ("%s: unlink: %s", applet, strerror (errno)); - free (mtime); + l = strlen(RC_SVCDIR "exclusive") + strlen(svcname) + + strlen(runscript_pid) + 4; + mtime = xmalloc(l); + snprintf(mtime, l, RC_SVCDIR "exclusive/%s.%s", + svcname, runscript_pid); + if (exists(mtime) && unlink(mtime) != 0) + eerror("%s: unlink: %s", applet, strerror(errno)); + free(mtime); } - return (ok ? EXIT_SUCCESS : EXIT_FAILURE); + return ok ? EXIT_SUCCESS : EXIT_FAILURE; } -static int do_value (int argc, char **argv) +static int do_value(int argc, char **argv) { bool ok = false; - char *service = getenv ("SVCNAME"); + char *service = getenv("SVCNAME"); + char *option; if (! service) - eerrorx ("%s: no service specified", applet); + eerrorx("%s: no service specified", applet); if (argc < 2 || ! argv[1] || *argv[1] == '\0') - eerrorx ("%s: no option specified", applet); + eerrorx("%s: no option specified", applet); - if (strcmp (applet, "service_get_value") == 0 || - strcmp (applet, "get_options") == 0) + if (strcmp(applet, "service_get_value") == 0 || + strcmp(applet, "get_options") == 0) { - char *option = rc_service_value_get (service, argv[1]); + option = rc_service_value_get(service, argv[1]); if (option) { - printf ("%s", option); - free (option); + printf("%s", option); + free(option); ok = true; } - } else if (strcmp (applet, "service_set_value") == 0 || - strcmp (applet, "save_options") == 0) - ok = rc_service_value_set (service, argv[1], argv[2]); + } else if (strcmp(applet, "service_set_value") == 0 || + strcmp(applet, "save_options") == 0) + ok = rc_service_value_set(service, argv[1], argv[2]); else - eerrorx ("%s: unknown applet", applet); + eerrorx("%s: unknown applet", applet); - return (ok ? EXIT_SUCCESS : EXIT_FAILURE); + return ok ? EXIT_SUCCESS : EXIT_FAILURE; } -static int do_shell_var (int argc, char **argv) +static int do_shell_var(int argc, char **argv) { int i; + char *p; + int c; for (i = 1; i < argc; i++) { - char *p = argv[i]; + p = argv[i]; if (i != 1) - putchar (' '); + putchar(' '); while (*p) { - char c = *p++; - if (! isalnum ((int) c)) + c = *p++; + if (! isalnum(c)) c = '_'; - putchar (c); + putchar(c); } } - putchar ('\n'); + putchar('\n'); - return (EXIT_SUCCESS); + return EXIT_SUCCESS; } -void run_applets (int argc, char **argv) +void run_applets(int argc, char **argv) { + int i = 2; + bool match = false; + char *p; + pid_t pid = 0; + /* These are designed to be applications in their own right */ - if (strcmp (applet, "fstabinfo") == 0) - exit (fstabinfo (argc, argv)); - else if (strcmp (applet, "mountinfo") == 0) - exit (mountinfo (argc, argv)); - else if (strcmp (applet, "rc-depend") == 0) - exit (rc_depend (argc, argv)); - else if (strcmp (applet, "rc-status") == 0) - exit (rc_status (argc, argv)); - else if (strcmp (applet, "rc-update") == 0 || - strcmp (applet, "update-rc") == 0) - exit (rc_update (argc, argv)); - else if (strcmp (applet, "runscript") == 0) - exit (runscript (argc, argv)); - else if (strcmp (applet, "start-stop-daemon") == 0) - exit (start_stop_daemon (argc, argv)); + if (strcmp(applet, "fstabinfo") == 0) + exit(fstabinfo(argc, argv)); + else if (strcmp(applet, "mountinfo") == 0) + exit(mountinfo(argc, argv)); + else if (strcmp(applet, "rc-depend") == 0) + exit(rc_depend(argc, argv)); + else if (strcmp(applet, "rc-status") == 0) + exit(rc_status(argc, argv)); + else if (strcmp(applet, "rc-update") == 0 || + strcmp(applet, "update-rc") == 0) + exit(rc_update(argc, argv)); + else if (strcmp(applet, "runscript") == 0) + exit(runscript(argc, argv)); + else if (strcmp(applet, "start-stop-daemon") == 0) + exit(start_stop_daemon(argc, argv)); else if (strcmp (applet, "checkpath") == 0) - exit (checkpath (argc, argv)); + exit(checkpath(argc, argv)); /* These could also be applications in their own right */ - if (strcmp (applet, "shell_var") == 0) - exit (do_shell_var (argc, argv)); + if (strcmp(applet, "shell_var") == 0) + exit(do_shell_var(argc, argv)); - if (strcmp (applet, "is_newer_than") == 0 || - strcmp (applet, "is_older_than") == 0) + if (strcmp(applet, "is_newer_than") == 0 || + strcmp(applet, "is_older_than") == 0) { - bool match = false; - int i = 2; - if (argc < 3) exit (EXIT_FAILURE); - if (strcmp (applet, "is_newer_than") == 0) + if (strcmp(applet, "is_newer_than") == 0) match = true; while (i < argc) { - if (rc_newer_than (argv[1], argv[i++]) != match) + if (rc_newer_than(argv[1], argv[i++]) != match) exit (EXIT_FAILURE); } - exit (EXIT_SUCCESS); + exit(EXIT_SUCCESS); }; if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e')) - exit (do_e (argc, argv)); + exit(do_e(argc, argv)); /* These are purely for init scripts and do not make sense as * anything else */ - if (strcmp (applet, "service_get_value") == 0 || - strcmp (applet, "service_set_value") == 0 || - strcmp (applet, "get_options") == 0 || - strcmp (applet, "save_options") == 0) - exit (do_value (argc, argv)); + if (strcmp(applet, "service_get_value") == 0 || + strcmp(applet, "service_set_value") == 0 || + strcmp(applet, "get_options") == 0 || + strcmp(applet, "save_options") == 0) + exit(do_value(argc, argv)); - if (strncmp (applet, "service_", strlen ("service_")) == 0) - exit (do_service (argc, argv)); + if (strncmp(applet, "service_", strlen("service_")) == 0) + exit(do_service(argc, argv)); - if (strncmp (applet, "mark_service_", strlen ("mark_service_")) == 0) - exit (do_mark_service (argc, argv)); + if (strncmp(applet, "mark_service_", strlen("mark_service_")) == 0) + exit(do_mark_service(argc, argv)); - if (strcmp (applet, "is_runlevel_start") == 0) - exit (rc_runlevel_starting () ? 0 : 1); + if (strcmp(applet, "is_runlevel_start") == 0) + exit(rc_runlevel_starting() ? 0 : 1); else if (strcmp (applet, "is_runlevel_stop") == 0) - exit (rc_runlevel_stopping () ? 0 : 1); - - if (strcmp (applet, "rc-abort") == 0) { - char *p = getenv ("RC_PID"); - pid_t pid = 0; - - if (p && sscanf (p, "%d", &pid) == 1) { - if (kill (pid, SIGUSR1) != 0) - eerrorx ("rc-abort: failed to signal parent %d: %s", - pid, strerror (errno)); - exit (EXIT_SUCCESS); + exit(rc_runlevel_stopping() ? 0 : 1); + + if (strcmp(applet, "rc-abort") == 0) { + p = getenv("RC_PID"); + if (p && sscanf(p, "%d", &pid) == 1) { + if (kill(pid, SIGUSR1) != 0) + eerrorx("rc-abort: failed to signal parent %d: %s", + pid, strerror(errno)); + exit(EXIT_SUCCESS); } - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); } - if (strcmp (applet, "rc" ) != 0) - eerrorx ("%s: unknown applet", applet); + if (strcmp(applet, "rc") != 0) + eerrorx("%s: unknown applet", applet); } diff --git a/src/rc/rc-depend.c b/src/rc/rc-depend.c index 0eda7f0f..33a50f06 100644 --- a/src/rc/rc-depend.c +++ b/src/rc/rc-depend.c @@ -45,34 +45,33 @@ #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" extern const char *applet; -rc_depinfo_t *_rc_deptree_load (int *regen) { - if (rc_deptree_update_needed ()) { - int fd; - int retval; - int serrno = errno; - int merrno; +RC_DEPTREE *_rc_deptree_load(int *regen) { + int fd; + int retval; + int serrno = errno; + int merrno; + if (rc_deptree_update_needed()) { /* Test if we have permission to update the deptree */ - fd = open (RC_DEPTREE, O_WRONLY); + fd = open(RC_DEPTREE_CACHE, O_WRONLY); merrno = errno; errno = serrno; if (fd == -1 && merrno == EACCES) - return (rc_deptree_load ()); - close (fd); + return rc_deptree_load(); + close(fd); if (regen) *regen = 1; - ebegin ("Caching service dependencies"); - retval = rc_deptree_update (); + ebegin("Caching service dependencies"); + retval = rc_deptree_update(); eend (retval ? 0 : -1, "Failed to update the dependency tree"); } - return (rc_deptree_load ()); + return rc_deptree_load(); } #include "_usage.h" @@ -97,117 +96,114 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int rc_depend (int argc, char **argv) +int rc_depend(int argc, char **argv) { - char **types = NULL; - char **services = NULL; - char **depends = NULL; - char **list; - rc_depinfo_t *deptree = NULL; - char *service; + RC_STRINGLIST *list; + RC_STRINGLIST *types; + RC_STRINGLIST *services; + RC_STRINGLIST *depends; + RC_STRING *s; + RC_DEPTREE *deptree = NULL; int options = RC_DEP_TRACE; bool first = true; - int i; bool update = false; - char *runlevel = xstrdup( getenv ("RC_SOFTLEVEL")); + char *runlevel = xstrdup(getenv("RC_SOFTLEVEL")); int opt; char *token; - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + types = rc_stringlist_new(); + + while ((opt = getopt_long(argc, argv, getoptstring, + longopts, (int *) 0)) != -1) { switch (opt) { - case 'a': - options |= RC_DEP_START; - break; - case 'o': - options |= RC_DEP_STOP; - break; - case 's': - options |= RC_DEP_STRICT; - break; - case 't': - while ((token = strsep (&optarg, ","))) - rc_strlist_addu (&types, token); - break; - case 'u': - update = true; - break; - case 'T': - options &= RC_DEP_TRACE; - break; - - case_RC_COMMON_GETOPT + case 'a': + options |= RC_DEP_START; + break; + case 'o': + options |= RC_DEP_STOP; + break; + case 's': + options |= RC_DEP_STRICT; + break; + case 't': + while ((token = strsep(&optarg, ","))) + rc_stringlist_add(types, token); + break; + case 'u': + update = true; + break; + case 'T': + options &= RC_DEP_TRACE; + break; + + case_RC_COMMON_GETOPT } } if (update) { - bool u = false; - ebegin ("Caching service dependencies"); - u = rc_deptree_update (); - eend (u ? 0 : -1, "%s: %s", applet, strerror (errno)); - if (! u) - eerrorx ("Failed to update the dependency tree"); + ebegin("Caching service dependencies"); + update = rc_deptree_update(); + eend(update ? 0 : -1, "%s: %s", applet, strerror(errno)); + if (! update) + eerrorx("Failed to update the dependency tree"); } - if (! (deptree = _rc_deptree_load (NULL))) - eerrorx ("failed to load deptree"); + if (! (deptree = _rc_deptree_load(NULL))) + eerrorx("failed to load deptree"); if (! runlevel) - runlevel = rc_runlevel_get (); + runlevel = rc_runlevel_get(); + services = rc_stringlist_new(); while (optind < argc) { - list = NULL; - rc_strlist_add (&list, argv[optind]); + list = rc_stringlist_new(); + rc_stringlist_add(list, argv[optind]); errno = 0; - depends = rc_deptree_depends (deptree, NULL, (const char **) list, - runlevel, 0); + depends = rc_deptree_depends(deptree, NULL, list, runlevel, 0); if (! depends && errno == ENOENT) - eerror ("no dependency info for service `%s'", argv[optind]); + eerror("no dependency info for service `%s'", argv[optind]); else - rc_strlist_add (&services, argv[optind]); + rc_stringlist_add(services, argv[optind]); - rc_strlist_free (depends); - rc_strlist_free (list); + rc_stringlist_free(depends); + rc_stringlist_free(list); optind++; } - - if (! services) { - rc_strlist_free (types); - rc_deptree_free (deptree); - free (runlevel); + if (! TAILQ_FIRST(services)) { + rc_stringlist_free(services); + rc_stringlist_free(types); + rc_deptree_free(deptree); + free(runlevel); if (update) - return (EXIT_SUCCESS); - eerrorx ("no services specified"); + return EXIT_SUCCESS; + eerrorx("no services specified"); } /* If we don't have any types, then supply some defaults */ - if (! types) { - rc_strlist_add (&types, "ineed"); - rc_strlist_add (&types, "iuse"); + if (! TAILQ_FIRST(types)) { + rc_stringlist_add(types, "ineed"); + rc_stringlist_add(types, "iuse"); } - depends = rc_deptree_depends (deptree, (const char **) types, - (const char **) services, runlevel, options); + depends = rc_deptree_depends(deptree, types, services, runlevel, options); - if (depends) { - STRLIST_FOREACH (depends, service, i) { + if (TAILQ_FIRST(depends)) { + TAILQ_FOREACH(s, depends, entries) { if (first) first = false; else printf (" "); - - if (service) - printf ("%s", service); + printf ("%s", s->value); } printf ("\n"); } - rc_strlist_free (types); - rc_strlist_free (services); - rc_strlist_free (depends); - rc_deptree_free (deptree); - free (runlevel); - return (EXIT_SUCCESS); + rc_stringlist_free(types); + rc_stringlist_free(services); + rc_stringlist_free(depends); + rc_deptree_free(deptree); + free(runlevel); + return EXIT_SUCCESS; } diff --git a/src/rc/rc-logger.c b/src/rc/rc-logger.c index 3e02a1aa..b4e4e352 100644 --- a/src/rc/rc-logger.c +++ b/src/rc/rc-logger.c @@ -33,6 +33,7 @@ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/wait.h> + #include <ctype.h> #include <fcntl.h> #include <signal.h> @@ -76,67 +77,67 @@ pid_t rc_logger_pid = -1; int rc_logger_tty = -1; bool rc_in_logger = false; -static void write_log (int logfd, const char *buffer, size_t bytes) +static void write_log(int logfd, const char *buffer, size_t bytes) { const char *p = buffer; while ((size_t) (p - buffer) < bytes) { switch (*p) { - case '\r': - goto cont; - case '\033': - in_escape = true; - in_term = false; - goto cont; - case '\n': - in_escape = in_term = false; - break; - case '[': - if (in_escape) - in_term = true; - break; + case '\r': + goto cont; + case '\033': + in_escape = true; + in_term = false; + goto cont; + case '\n': + in_escape = in_term = false; + break; + case '[': + if (in_escape) + in_term = true; + break; } if (! in_escape) { - write (logfd, p++, 1); + write(logfd, p++, 1); continue; } - if (! in_term || isalpha ((int) *p)) + if (! in_term || isalpha((int) *p)) in_escape = in_term = false; cont: p++; } } - -static void write_time (FILE *f, const char *s) +static void write_time(FILE *f, const char *s) { - time_t now = time (NULL); - struct tm *tm = localtime (&now); + time_t now = time(NULL); + struct tm *tm = localtime(&now); - fprintf (f, "\nrc %s logging %s at %s\n", runlevel, s, asctime (tm)); - fflush (f); + fprintf(f, "\nrc %s logging %s at %s\n", runlevel, s, asctime(tm)); + fflush(f); } -void rc_logger_close () +void rc_logger_close(void) { + int sig = SIGTERM; + if (signal_pipe[1] > -1) { - int sig = SIGTERM; - write (signal_pipe[1], &sig, sizeof (sig)); - close (signal_pipe[1]); + write(signal_pipe[1], &sig, sizeof(sig)); + close(signal_pipe[1]); signal_pipe[1] = -1; } if (rc_logger_pid > 0) - waitpid (rc_logger_pid, 0, 0); + waitpid(rc_logger_pid, 0, 0); if (fd_stdout > -1) - dup2 (fd_stdout, STDOUT_FILENO); + dup2(fd_stdout, STDOUT_FILENO); if (fd_stderr > -1) - dup2 (fd_stderr, STDERR_FILENO); + dup2(fd_stderr, STDERR_FILENO); } -void rc_logger_open (const char *level) +void rc_logger_open(const char *level) { int slave_tty; struct termios tt; @@ -149,125 +150,127 @@ void rc_logger_open (const char *level) int i; FILE *log = NULL; - if (! isatty (STDOUT_FILENO)) + if (! isatty(STDOUT_FILENO)) return; - if (! rc_conf_yesno ("rc_logger")) + if (! rc_conf_yesno("rc_logger")) return; - if (pipe (signal_pipe) == -1) - eerrorx ("pipe: %s", strerror (errno)); + if (pipe(signal_pipe) == -1) + eerrorx("pipe: %s", strerror(errno)); for (i = 0; i < 2; i++) if ((s = fcntl (signal_pipe[i], F_GETFD, 0) == -1 || fcntl (signal_pipe[i], F_SETFD, s | FD_CLOEXEC) == -1)) - eerrorx ("fcntl: %s", strerror (errno)); + eerrorx("fcntl: %s", strerror (errno)); - tcgetattr (STDOUT_FILENO, &tt); - ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws); + tcgetattr(STDOUT_FILENO, &tt); + ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws); /* /dev/pts may not be available yet */ - if (openpty (&rc_logger_tty, &slave_tty, NULL, &tt, &ws)) + if (openpty(&rc_logger_tty, &slave_tty, NULL, &tt, &ws)) return; - if ((s = fcntl (rc_logger_tty, F_GETFD, 0)) == 0) - fcntl (rc_logger_tty, F_SETFD, s | FD_CLOEXEC); + if ((s = fcntl(rc_logger_tty, F_GETFD, 0)) == 0) + fcntl(rc_logger_tty, F_SETFD, s | FD_CLOEXEC); - if ((s = fcntl (slave_tty, F_GETFD, 0)) == 0) - fcntl (slave_tty, F_SETFD, s | FD_CLOEXEC); + if ((s = fcntl(slave_tty, F_GETFD, 0)) == 0) + fcntl(slave_tty, F_SETFD, s | FD_CLOEXEC); - rc_logger_pid = fork (); + rc_logger_pid = fork(); switch (rc_logger_pid) { - case -1: - eerror ("forkpty: %s", strerror (errno)); - break; - case 0: - rc_in_logger = true; - close (signal_pipe[1]); - signal_pipe[1] = -1; - - runlevel = level; - if ((log = fopen (LOGFILE, "a"))) - write_time (log, "started"); - else { - free (logbuf); - logbuf_size = BUFSIZ * 10; - logbuf = xmalloc (sizeof (char) * logbuf_size); - logbuf_len = 0; - } + case -1: + eerror("fork: %s", strerror(errno)); + break; + case 0: + rc_in_logger = true; + close(signal_pipe[1]); + signal_pipe[1] = -1; - buffer = xmalloc (sizeof (char) * BUFSIZ); - selfd = rc_logger_tty > signal_pipe[0] ? rc_logger_tty : signal_pipe[0]; - for (;;) { - FD_ZERO (&rset); - FD_SET (rc_logger_tty, &rset); - FD_SET (signal_pipe[0], &rset); + runlevel = level; + if ((log = fopen(LOGFILE, "a"))) + write_time(log, "started"); + else { + free(logbuf); + logbuf_size = BUFSIZ * 10; + logbuf = xmalloc(sizeof (char) * logbuf_size); + logbuf_len = 0; + } - if ((s = select (selfd + 1, &rset, NULL, NULL, NULL)) == -1) { - eerror ("select: %s", strerror (errno)); - break; - } + buffer = xmalloc(sizeof (char) * BUFSIZ); + selfd = rc_logger_tty > signal_pipe[0] ? rc_logger_tty : signal_pipe[0]; + for (;;) { + FD_ZERO(&rset); + FD_SET(rc_logger_tty, &rset); + FD_SET(signal_pipe[0], &rset); - if (s > 0) { - if (FD_ISSET (rc_logger_tty, &rset)) { - memset (buffer, 0, BUFSIZ); - bytes = read (rc_logger_tty, buffer, BUFSIZ); - write (STDOUT_FILENO, buffer, bytes); - - if (log) - write_log (fileno (log), buffer, bytes); - else { - if (logbuf_size - logbuf_len < bytes) { - logbuf_size += BUFSIZ * 10; - logbuf = xrealloc (logbuf, sizeof (char ) * - logbuf_size); - } - - memcpy (logbuf + logbuf_len, buffer, bytes); - logbuf_len += bytes; + if ((s = select(selfd + 1, &rset, NULL, NULL, NULL)) == -1) { + eerror("select: %s", strerror(errno)); + break; + } + + if (s > 0) { + if (FD_ISSET(rc_logger_tty, &rset)) { + memset(buffer, 0, BUFSIZ); + bytes = read(rc_logger_tty, buffer, BUFSIZ); + write(STDOUT_FILENO, buffer, bytes); + + if (log) + write_log(fileno (log), buffer, bytes); + else { + if (logbuf_size - logbuf_len < bytes) { + logbuf_size += BUFSIZ * 10; + logbuf = xrealloc(logbuf, + sizeof(char ) * + logbuf_size); } - } - /* Only SIGTERMS signals come down this pipe */ - if (FD_ISSET (signal_pipe[0], &rset)) - break; - } - } - free (buffer); - if (logbuf) { - if ((log = fopen (LOGFILE, "a"))) { - write_time (log, "started"); - write_log (fileno (log), logbuf, logbuf_len); + memcpy(logbuf + logbuf_len, buffer, bytes); + logbuf_len += bytes; + } } - free (logbuf); + + /* Only SIGTERMS signals come down this pipe */ + if (FD_ISSET(signal_pipe[0], &rset)) + break; } - if (log) { - write_time (log, "stopped"); - fclose (log); + } + free(buffer); + if (logbuf) { + if ((log = fopen(LOGFILE, "a"))) { + write_time(log, "started"); + write_log(fileno(log), logbuf, logbuf_len); } + free(logbuf); + } + if (log) { + write_time(log, "stopped"); + fclose(log); + } - /* Try and cat our new logfile to a more permament location and then - * punt it */ - system (MOVELOG); - - exit (0); - /* NOTREACHED */ - default: - setpgid (rc_logger_pid, 0); - fd_stdout = dup (STDOUT_FILENO); - fd_stderr = dup (STDERR_FILENO); - if ((s = fcntl (fd_stdout, F_GETFD, 0)) == 0) - fcntl (fd_stdout, F_SETFD, s | FD_CLOEXEC); - - if ((s = fcntl (fd_stderr, F_GETFD, 0)) == 0) - fcntl (fd_stderr, F_SETFD, s | FD_CLOEXEC); - dup2 (slave_tty, STDOUT_FILENO); - dup2 (slave_tty, STDERR_FILENO); - if (slave_tty != STDIN_FILENO && - slave_tty != STDOUT_FILENO && - slave_tty != STDERR_FILENO) - close (slave_tty); - close (signal_pipe[0]); - signal_pipe[0] = -1; - break; + /* Try and cat our new logfile to a more permament location and then + * punt it */ + system(MOVELOG); + + exit(0); + /* NOTREACHED */ + + default: + setpgid(rc_logger_pid, 0); + fd_stdout = dup(STDOUT_FILENO); + fd_stderr = dup(STDERR_FILENO); + if ((s = fcntl(fd_stdout, F_GETFD, 0)) == 0) + fcntl(fd_stdout, F_SETFD, s | FD_CLOEXEC); + + if ((s = fcntl(fd_stderr, F_GETFD, 0)) == 0) + fcntl(fd_stderr, F_SETFD, s | FD_CLOEXEC); + dup2(slave_tty, STDOUT_FILENO); + dup2(slave_tty, STDERR_FILENO); + if (slave_tty != STDIN_FILENO && + slave_tty != STDOUT_FILENO && + slave_tty != STDERR_FILENO) + close(slave_tty); + close(signal_pipe[0]); + signal_pipe[0] = -1; + break; } } diff --git a/src/rc/rc-misc.c b/src/rc/rc-misc.c index 343a1534..3167f26b 100644 --- a/src/rc/rc-misc.c +++ b/src/rc/rc-misc.c @@ -30,13 +30,13 @@ */ #include <sys/types.h> +#include <sys/utsname.h> #ifdef __linux__ #include <sys/sysinfo.h> #include <regex.h> #endif -#include <sys/utsname.h> #include <ctype.h> #include <limits.h> #include <signal.h> @@ -47,7 +47,6 @@ #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" #define PROFILE_ENV SYSCONFDIR "/profile.env" #define SYS_WHITELIST RC_LIBDIR "/conf.d/env_whitelist" @@ -57,314 +56,253 @@ #define PATH_PREFIX RC_LIBDIR "/bin:/bin:/sbin:/usr/bin:/usr/sbin" -static char **rc_conf = NULL; +static RC_STRINGLIST *rc_conf = NULL; + +extern char** environ; -static void _free_rc_conf (void) +static void _free_rc_conf(void) { - rc_strlist_free (rc_conf); + rc_stringlist_free(rc_conf); } -char *rc_conf_value (const char *setting) +char *rc_conf_value(const char *setting) { - if (! rc_conf) { - char *line; - int i; + RC_STRINGLIST *old; + RC_STRING *s; + char *p; - rc_conf = rc_config_load (RC_CONF); - atexit (_free_rc_conf); + if (! rc_conf) { + rc_conf = rc_config_load(RC_CONF); + atexit(_free_rc_conf); /* Support old configs */ - if (exists (RC_CONF_OLD)) { - char **old = rc_config_load (RC_CONF_OLD); - rc_strlist_join (&rc_conf, old); - rc_strlist_free (old); + if (exists(RC_CONF_OLD)) { + old = rc_config_load(RC_CONF_OLD); + if (old) { + TAILQ_CONCAT(rc_conf, old); + free(old); + } } /* Convert old uppercase to lowercase */ - STRLIST_FOREACH (rc_conf, line, i) { - char *p = line; + TAILQ_FOREACH(s, rc_conf, entries) { + p = s->value; while (p && *p && *p != '=') { - if (isupper ((int) *p)) - *p = tolower ((int) *p); + if (isupper((int) *p)) + *p = tolower((int) *p); p++; } } } - return (rc_config_value ((const char *const *)rc_conf, setting)); + return rc_config_value(rc_conf, setting); } -bool rc_conf_yesno (const char *setting) +bool rc_conf_yesno(const char *setting) { - return (rc_yesno (rc_conf_value (setting))); + return rc_yesno(rc_conf_value (setting)); } -char **env_filter (void) +static const char *const env_whitelist[] = { + "PATH", "SHELL", "USER", "HOME", "TERM", + "LANG", "LC_CTYPE", "LC_NUMERIC", "LC_TIME", "LC_COLLATE", + "LC_MONETARY", "LC_MESSAGES", "LC_PAPER", "LC_NAME", "LC_ADDRESS", + "LC_TELEPHONE", "LC_MEASUREMENT", "LC_IDENTIFICATION", "LC_ALL", + "INIT_HALT", "INIT_VERSION", "RUNLEVEL", "PREVLEVEL", "CONSOLE", + "IN_HOTPLUG", "IN_BACKGROUND", "RC_INTERFACE_KEEP_CONFIG", + NULL +}; + +void env_filter(void) { - char **env = NULL; - char **whitelist = NULL; - char *env_name = NULL; - char **profile = NULL; - int count = 0; - bool got_path = false; - char *env_var; - size_t env_len; - char *token; - char *sep; + RC_STRINGLIST *env_allow; + RC_STRINGLIST *profile = NULL; + RC_STRINGLIST *env_list; + RC_STRING *env; + RC_STRING *s; + char *env_name; char *e; - char *p; - size_t pplen = strlen (PATH_PREFIX); - - /* Init a system whitelist, start with shell vars we need */ - rc_strlist_add (&whitelist, "PATH"); - rc_strlist_add (&whitelist, "SHELL"); - rc_strlist_add (&whitelist, "USER"); - rc_strlist_add (&whitelist, "HOME"); - rc_strlist_add (&whitelist, "TERM"); - - /* Add Language vars */ - rc_strlist_add (&whitelist, "LANG"); - rc_strlist_add (&whitelist, "LC_CTYPE"); - rc_strlist_add (&whitelist, "LC_NUMERIC"); - rc_strlist_add (&whitelist, "LC_TIME"); - rc_strlist_add (&whitelist, "LC_COLLATE"); - rc_strlist_add (&whitelist, "LC_MONETARY"); - rc_strlist_add (&whitelist, "LC_MESSAGES"); - rc_strlist_add (&whitelist, "LC_PAPER"); - rc_strlist_add (&whitelist, "LC_NAME"); - rc_strlist_add (&whitelist, "LC_ADDRESS"); - rc_strlist_add (&whitelist, "LC_TELEPHONE"); - rc_strlist_add (&whitelist, "LC_MEASUREMENT"); - rc_strlist_add (&whitelist, "LC_IDENTIFICATION"); - rc_strlist_add (&whitelist, "LC_ALL"); - - /* Allow rc to override library path */ - rc_strlist_add (&whitelist, "LD_LIBRARY_PATH"); - - /* We need to know sysvinit stuff - we emulate this for BSD too */ - rc_strlist_add (&whitelist, "INIT_HALT"); - rc_strlist_add (&whitelist, "INIT_VERSION"); - rc_strlist_add (&whitelist, "RUNLEVEL"); - rc_strlist_add (&whitelist, "PREVLEVEL"); - rc_strlist_add (&whitelist, "CONSOLE"); - - /* Hotplug and daemon vars */ - rc_strlist_add (&whitelist, "IN_HOTPLUG"); - rc_strlist_add (&whitelist, "IN_BACKGROUND"); - rc_strlist_add (&whitelist, "RC_INTERFACE_KEEP_CONFIG"); + char *token; + size_t i = 0; /* Add the user defined list of vars */ - e = env_name = xstrdup (rc_conf_value ("rc_env_allow")); - while ((token = strsep (&e, " "))) { + env_allow = rc_stringlist_new(); + e = env_name = xstrdup(rc_conf_value ("rc_env_allow")); + while ((token = strsep(&e, " "))) { if (token[0] == '*') { - free (env_name); - return (NULL); + free(env_name); + rc_stringlist_free(env_allow); + return; } - rc_strlist_add (&whitelist, token); + rc_stringlist_add(env_allow, token); } - free (env_name); - - if (exists (PROFILE_ENV)) - profile = rc_config_load (PROFILE_ENV); + free(env_name); - STRLIST_FOREACH (whitelist, env_name, count) { - char *space = strchr (env_name, ' '); - if (space) - *space = 0; + if (exists(PROFILE_ENV)) + profile = rc_config_load(PROFILE_ENV); - env_var = getenv (env_name); + /* Copy the env and work from this so we can remove safely */ + env_list = rc_stringlist_new(); + while (environ[i]) + rc_stringlist_add(env_list, environ[i++]); - if (! env_var && profile) { - env_len = strlen (env_name) + strlen ("export ") + 1; - p = xmalloc (sizeof (char) * env_len); - snprintf (p, env_len, "export %s", env_name); - env_var = rc_config_value ((const char *const *) profile, p); - free (p); + TAILQ_FOREACH(env, env_list, entries) { + /* Check the whitelist */ + i = 0; + while (env_whitelist[i]) { + if (strcmp(env_whitelist[i++], env->value)) + break; } + if (env_whitelist[i]) + continue; - if (! env_var) + /* Check our user defined list */ + TAILQ_FOREACH(s, env_allow, entries) + if (strcmp(s->value, env->value) == 0) + break; + if (s) continue; - /* Ensure our PATH is prefixed with the system locations first - for a little extra security */ - if (strcmp (env_name, "PATH") == 0 && - strncmp (PATH_PREFIX, env_var, pplen) != 0) - { - got_path = true; - env_len = strlen (env_name) + strlen (env_var) + pplen + 3; - e = p = xmalloc (sizeof (char) * env_len); - p += snprintf (e, env_len, "%s=%s", env_name, PATH_PREFIX); - - /* Now go through the env var and only add bits not in our PREFIX */ - sep = env_var; - while ((token = strsep (&sep, ":"))) { - char *np = xstrdup (PATH_PREFIX); - char *npp = np; - char *tok = NULL; - while ((tok = strsep (&npp, ":"))) - if (strcmp (tok, token) == 0) - break; - if (! tok) - p += snprintf (p, env_len - (p - e), ":%s", token); - free (np); - } - *p++ = 0; - } else { - env_len = strlen (env_name) + strlen (env_var) + 2; - e = xmalloc (sizeof (char) * env_len); - snprintf (e, env_len, "%s=%s", env_name, env_var); - } + /* Now check our profile */ - rc_strlist_add (&env, e); - free (e); + /* OK, not allowed! */ + e = strchr(env->value, '='); + *e = '\0'; + unsetenv(env->value); } - - /* We filtered the env but didn't get a PATH? Very odd. - However, we do need a path, so use a default. */ - if (! got_path) { - env_len = strlen ("PATH=") + strlen (PATH_PREFIX) + 1; - e = xmalloc (sizeof (char) * env_len); - snprintf (e, env_len, "PATH=%s", PATH_PREFIX); - rc_strlist_add (&env, e); - free (e); - } - - rc_strlist_free (whitelist); - rc_strlist_free (profile); - - return (env); + rc_stringlist_free(env_list); + rc_stringlist_free(env_allow); + rc_stringlist_free(profile); } -char **env_config (void) +void env_config(void) { - char **env = NULL; - char *line; + size_t pplen = strlen(PATH_PREFIX); + char *path; + char *p; + char *e; size_t l; - const char *sys = rc_sys (); struct utsname uts; FILE *fp; + char *token; + char *np; + char *npp; + char *tok; + const char *sys = rc_sys(); char buffer[PATH_MAX]; - char *runlevel = rc_runlevel_get (); - - /* One char less to drop the trailing / */ - l = strlen ("RC_LIBDIR=") + strlen (RC_LIBDIR) + 1; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_LIBDIR=" RC_LIBDIR); - rc_strlist_add (&env, line); - free (line); - - /* One char less to drop the trailing / */ - l = strlen ("RC_SVCDIR=") + strlen (RC_SVCDIR) + 1; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_SVCDIR=" RC_SVCDIR); - rc_strlist_add (&env, line); - free (line); - - rc_strlist_add (&env, "RC_BOOTLEVEL=" RC_LEVEL_BOOT); - - l = strlen ("RC_SOFTLEVEL=") + strlen (runlevel) + 1; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_SOFTLEVEL=%s", runlevel); - rc_strlist_add (&env, line); - free (line); - - if ((fp = fopen (RC_KSOFTLEVEL, "r"))) { - memset (buffer, 0, sizeof (buffer)); - if (fgets (buffer, sizeof (buffer), fp)) { + + /* Ensure our PATH is prefixed with the system locations first + for a little extra security */ + path = getenv("PATH"); + if (! path) + setenv("PATH", PATH_PREFIX, 1); + else if (strncmp (PATH_PREFIX, path, pplen) != 0) { + l = strlen(path) + pplen + 3; + e = p = xmalloc(sizeof(char) * l); + p += snprintf(p, l, "%s", PATH_PREFIX); + + /* Now go through the env var and only add bits not in our PREFIX */ + while ((token = strsep(&path, ":"))) { + np = npp = xstrdup(PATH_PREFIX); + while ((tok = strsep(&npp, ":"))) + if (strcmp(tok, token) == 0) + break; + if (! tok) + p += snprintf(p, l - (p - e), ":%s", token); + free (np); + } + *p++ = '\0'; + unsetenv("PATH"); + setenv("PATH", e, 1); + free(e); + } + + setenv("RC_LIBDIR", RC_LIBDIR, 1); + setenv("RC_SVCDIR", RC_SVCDIR, 1); + setenv("RC_BOOTLEVEL", RC_LEVEL_BOOT, 1); + e = rc_runlevel_get(); + setenv("RC_RUNLEVEL", e, 1); + free(e); + + if ((fp = fopen(RC_KSOFTLEVEL, "r"))) { + memset(buffer, 0, sizeof (buffer)); + if (fgets(buffer, sizeof (buffer), fp)) { l = strlen (buffer) - 1; if (buffer[l] == '\n') buffer[l] = 0; - l += strlen ("RC_DEFAULTLEVEL=") + 2; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_DEFAULTLEVEL=%s", buffer); - rc_strlist_add (&env, line); - free (line); + setenv("RC_DEFAULTLEVEL", buffer, 1); } - fclose (fp); + fclose(fp); } else - rc_strlist_add (&env, "RC_DEFAULTLEVEL=" RC_LEVEL_DEFAULT); - - if (sys) { - l = strlen ("RC_SYS=") + strlen (sys) + 2; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_SYS=%s", sys); - rc_strlist_add (&env, line); - free (line); - } + setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1); + + if (sys) + setenv("RC_SYS", sys, 1); /* Some scripts may need to take a different code path if Linux/FreeBSD, etc To save on calling uname, we store it in an environment variable */ - if (uname (&uts) == 0) { - l = strlen ("RC_UNAME=") + strlen (uts.sysname) + 2; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_UNAME=%s", uts.sysname); - rc_strlist_add (&env, line); - free (line); - } + if (uname(&uts) == 0) + setenv("RC_UNAME", uts.sysname, 1); /* Be quiet or verbose as necessary */ - if (rc_conf_yesno ("rc_quiet")) - rc_strlist_add (&env, "EINFO_QUIET=YES"); - if (rc_conf_yesno ("rc_verbose")) - rc_strlist_add (&env, "EINFO_VERBOSE=YES"); + if (rc_conf_yesno("rc_quiet")) + setenv("EINFO_QUIET", "YES", 1); + if (rc_conf_yesno("rc_verbose")) + setenv("EINFO_VERBOSE", "YES", 1); errno = 0; - if ((! rc_conf_yesno ("rc_color") && errno == 0) || - rc_conf_yesno ("rc_nocolor")) - rc_strlist_add (&env, "EINFO_COLOR=NO"); - - free (runlevel); - return (env); + if ((! rc_conf_yesno("rc_color") && errno == 0) || + rc_conf_yesno("rc_nocolor")) + setenv("EINFO_COLOR", "NO", 1); } -bool service_plugable (const char *service) +bool service_plugable(const char *service) { char *list; char *p; char *star; char *token; bool allow = true; - char *match = rc_conf_value ("rc_plug_services"); + char *match = rc_conf_value("rc_plug_services"); + bool truefalse; if (! match) - return (true); + return true; - list = xstrdup (match); + list = xstrdup(match); p = list; - while ((token = strsep (&p, " "))) { - bool truefalse = true; - + while ((token = strsep(&p, " "))) { if (token[0] == '!') { truefalse = false; token++; - } + } else + truefalse = true; - star = strchr (token, '*'); + star = strchr(token, '*'); if (star) { - if (strncmp (service, token, (size_t) (star - token)) - == 0) + if (strncmp(service, token, (size_t)(star - token)) == 0) { allow = truefalse; break; } } else { - if (strcmp (service, token) == 0) { + if (strcmp(service, token) == 0) { allow = truefalse; break; } } } - free (list); - return (allow); + free(list); + return allow; } -int signal_setup (int sig, void (*handler)(int)) +int signal_setup(int sig, void (*handler)(int)) { struct sigaction sa; - memset (&sa, 0, sizeof (sa)); - sigemptyset (&sa.sa_mask); + memset(&sa, 0, sizeof (sa)); + sigemptyset(&sa.sa_mask); sa.sa_handler = handler; - return (sigaction (sig, &sa, NULL)); + return sigaction(sig, &sa, NULL); } diff --git a/src/rc/rc-plugin.c b/src/rc/rc-plugin.c index e3184a34..f0ee5a61 100644 --- a/src/rc/rc-plugin.c +++ b/src/rc/rc-plugin.c @@ -31,6 +31,7 @@ #include <sys/types.h> #include <sys/wait.h> + #include <dirent.h> #include <dlfcn.h> #include <errno.h> @@ -46,7 +47,6 @@ #include "rc.h" #include "rc-misc.h" #include "rc-plugin.h" -#include "strlist.h" #define RC_PLUGIN_HOOK "rc_plugin_hook" @@ -56,129 +56,117 @@ typedef struct plugin { char *name; void *handle; - int (*hook) (rc_hook_t, const char *); - struct plugin *next; -} plugin_t; - -static plugin_t *plugins = NULL; + int (*hook)(RC_HOOK, const char *); + STAILQ_ENTRY(plugin) entries; +} PLUGIN; +STAILQ_HEAD(, plugin) plugins; #ifndef __FreeBSD__ -dlfunc_t dlfunc (void * __restrict handle, const char * __restrict symbol) +dlfunc_t dlfunc(void * __restrict handle, const char * __restrict symbol) { union { void *d; dlfunc_t f; } rv; - rv.d = dlsym (handle, symbol); - return (rv.f); + rv.d = dlsym(handle, symbol); + return rv.f; } #endif -void rc_plugin_load (void) +void rc_plugin_load(void) { DIR *dp; struct dirent *d; - plugin_t *plugin = plugins; + PLUGIN *plugin; char *p; void *h; - int (*fptr) (rc_hook_t, const char *); + int (*fptr)(RC_HOOK, const char *); /* Don't load plugins if we're in one */ if (rc_in_plugin) return; - /* Ensure some sanity here */ - rc_plugin_unload (); + STAILQ_INIT(&plugins); - if (! (dp = opendir (RC_PLUGINDIR))) + if (! (dp = opendir(RC_PLUGINDIR))) return; - while ((d = readdir (dp))) { + while ((d = readdir(dp))) { if (d->d_name[0] == '.') continue; - p = rc_strcatpaths (RC_PLUGINDIR, d->d_name, NULL); - h = dlopen (p, RTLD_LAZY); - free (p); + p = rc_strcatpaths(RC_PLUGINDIR, d->d_name, NULL); + h = dlopen(p, RTLD_LAZY); + free(p); if (! h) { - eerror ("dlopen: %s", dlerror ()); + eerror("dlopen: %s", dlerror()); continue; } - fptr = (int (*)(rc_hook_t, const char*)) dlfunc (h, RC_PLUGIN_HOOK); + fptr = (int (*)(RC_HOOK, const char*))dlfunc(h, RC_PLUGIN_HOOK); if (! fptr) { - eerror ("%s: cannot find symbol `%s'", d->d_name, RC_PLUGIN_HOOK); - dlclose (h); + eerror("%s: cannot find symbol `%s'", d->d_name, RC_PLUGIN_HOOK); + dlclose(h); } else { - if (plugin) { - plugin->next = xmalloc (sizeof (*plugin->next)); - plugin = plugin->next; - } else - plugin = plugins = xmalloc (sizeof (*plugin)); - - plugin->name = xstrdup (d->d_name); + plugin = xmalloc(sizeof(*plugin)); + plugin->name = xstrdup(d->d_name); plugin->handle = h; plugin->hook = fptr; - plugin->next = NULL; + STAILQ_INSERT_TAIL(&plugins, plugin, entries); } } - closedir (dp); + closedir(dp); } -int rc_waitpid (pid_t pid) +int rc_waitpid(pid_t pid) { int status = 0; pid_t savedpid = pid; int retval = -1; errno = 0; - while ((pid = waitpid (savedpid, &status, 0)) > 0) { + while ((pid = waitpid(savedpid, &status, 0)) > 0) { if (pid == savedpid) - retval = WIFEXITED (status) ? WEXITSTATUS (status) : EXIT_FAILURE; + retval = WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE; } - return (retval); + return retval; } -void rc_plugin_run (rc_hook_t hook, const char *value) +void rc_plugin_run(RC_HOOK hook, const char *value) { - plugin_t *plugin = plugins; + PLUGIN *plugin; struct sigaction sa; sigset_t empty; sigset_t full; sigset_t old; + int i; + int flags; + int pfd[2]; + pid_t pid; + char *buffer; + char *token; + char *p; + ssize_t nr; + int retval; /* Don't run plugins if we're in one */ if (rc_in_plugin) return; /* We need to block signals until we have forked */ - memset (&sa, 0, sizeof (sa)); + memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; - sigemptyset (&sa.sa_mask); - sigemptyset (&empty); - sigfillset (&full); - - while (plugin) { - int i; - int flags; - int pfd[2]; - pid_t pid; - char *buffer; - char *token; - char *p; - ssize_t nr; - - if (! plugin->hook) { - plugin = plugin->next; - continue; - } + sigemptyset(&sa.sa_mask); + sigemptyset(&empty); + sigfillset(&full); + STAILQ_FOREACH(plugin, &plugins, entries) { /* We create a pipe so that plugins can affect our environment * vars, which in turn influence our scripts. */ - if (pipe (pfd) == -1) { - eerror ("pipe: %s", strerror (errno)); + if (pipe(pfd) == -1) { + eerror("pipe: %s", strerror(errno)); return; } @@ -188,81 +176,78 @@ void rc_plugin_run (rc_hook_t hook, const char *value) for (i = 0; i < 2; i++) if ((flags = fcntl (pfd[i], F_GETFD, 0)) < 0 || fcntl (pfd[i], F_SETFD, flags | FD_CLOEXEC) < 0) - eerror ("fcntl: %s", strerror (errno)); + eerror("fcntl: %s", strerror(errno)); - sigprocmask (SIG_SETMASK, &full, &old); + sigprocmask(SIG_SETMASK, &full, &old); /* We run the plugin in a new process so we never crash * or otherwise affected by it */ - if ((pid = fork ()) == -1) { - eerror ("fork: %s", strerror (errno)); + if ((pid = fork()) == -1) { + eerror("fork: %s", strerror(errno)); break; } if (pid == 0) { - int retval; - /* Restore default handlers */ - sigaction (SIGCHLD, &sa, NULL); - sigaction (SIGHUP, &sa, NULL); - sigaction (SIGINT, &sa, NULL); - sigaction (SIGQUIT, &sa, NULL); - sigaction (SIGTERM, &sa, NULL); - sigaction (SIGUSR1, &sa, NULL); - sigaction (SIGWINCH, &sa, NULL); - sigprocmask (SIG_SETMASK, &old, NULL); + sigaction(SIGCHLD, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGWINCH, &sa, NULL); + sigprocmask(SIG_SETMASK, &old, NULL); rc_in_plugin = true; - close (pfd[0]); - rc_environ_fd = fdopen (pfd[1], "w"); - retval = plugin->hook (hook, value); - fclose (rc_environ_fd); + close(pfd[0]); + rc_environ_fd = fdopen(pfd[1], "w"); + retval = plugin->hook(hook, value); + fclose(rc_environ_fd); rc_environ_fd = NULL; /* Just in case the plugin sets this to false */ rc_in_plugin = true; - exit (retval); + exit(retval); } - sigprocmask (SIG_SETMASK, &old, NULL); - close (pfd[1]); - buffer = xmalloc (sizeof (char) * BUFSIZ); - memset (buffer, 0, BUFSIZ); + sigprocmask(SIG_SETMASK, &old, NULL); + close(pfd[1]); + buffer = xmalloc(sizeof(char) * BUFSIZ); + memset(buffer, 0, BUFSIZ); - while ((nr = read (pfd[0], buffer, BUFSIZ)) > 0) { + while ((nr = read(pfd[0], buffer, BUFSIZ)) > 0) { p = buffer; while (*p && p - buffer < nr) { - token = strsep (&p, "="); + token = strsep(&p, "="); if (token) { - unsetenv (token); + unsetenv(token); if (*p) { - setenv (token, p, 1); - p += strlen (p) + 1; + setenv(token, p, 1); + p += strlen(p) + 1; } else p++; } } } - free (buffer); - close (pfd[0]); + free(buffer); + close(pfd[0]); - rc_waitpid (pid); - plugin = plugin->next; + rc_waitpid(pid); } } -void rc_plugin_unload (void) +void rc_plugin_unload(void) { - plugin_t *plugin = plugins; - plugin_t *next; + PLUGIN *plugin = STAILQ_FIRST(&plugins); + PLUGIN *next; while (plugin) { - next = plugin->next; - dlclose (plugin->handle); - free (plugin->name); - free (plugin); + next = STAILQ_NEXT(plugin, entries); + dlclose(plugin->handle); + free(plugin->name); + free(plugin); plugin = next; } - plugins = NULL; + STAILQ_INIT(&plugins); } diff --git a/src/rc/rc-plugin.h b/src/rc/rc-plugin.h index 91ba5619..0b8ab090 100644 --- a/src/rc/rc-plugin.h +++ b/src/rc/rc-plugin.h @@ -36,10 +36,10 @@ * Mainly used in atexit code. */ extern bool rc_in_plugin; -int rc_waitpid (pid_t pid); -void rc_plugin_load (); -void rc_plugin_unload (); -void rc_plugin_run (rc_hook_t, const char *value); +int rc_waitpid(pid_t pid); +void rc_plugin_load(void); +void rc_plugin_unload(void); +void rc_plugin_run(RC_HOOK, const char *value); /* dlfunc defines needed to avoid ISO errors. FreeBSD has this right :) */ #ifndef __FreeBSD__ @@ -47,7 +47,7 @@ struct __dlfunc_arg { int __dlfunc_dummy; }; -typedef void (*dlfunc_t) (struct __dlfunc_arg); +typedef void (*dlfunc_t)(struct __dlfunc_arg); dlfunc_t dlfunc (void * __restrict handle, const char * __restrict symbol); #endif diff --git a/src/rc/rc-status.c b/src/rc/rc-status.c index 579c416b..9f7167f6 100644 --- a/src/rc/rc-status.c +++ b/src/rc/rc-status.c @@ -39,57 +39,56 @@ #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" extern const char *applet; static const char *const types_nua[] = { "ineed", "iuse", "iafter", NULL }; -static void print_level (char *level) +static void print_level(char *level) { printf ("Runlevel: "); - if (isatty (fileno (stdout))) - printf ("%s%s%s\n", - ecolor (ECOLOR_HILITE), - level, - ecolor (ECOLOR_NORMAL)); + if (isatty(fileno(stdout))) + printf("%s%s%s\n", + ecolor(ECOLOR_HILITE), + level, + ecolor(ECOLOR_NORMAL)); else - printf ("%s\n", level); + printf("%s\n", level); } -static void print_service (char *service) +static void print_service(char *service) { char status[10]; - int cols = printf (" %s", service); - const char *c = ecolor (ECOLOR_GOOD); - rc_service_state_t state = rc_service_state (service); - einfo_color_t color = ECOLOR_BAD; + int cols = printf(" %s", service); + const char *c = ecolor(ECOLOR_GOOD); + RC_SERVICE state = rc_service_state(service); + ECOLOR color = ECOLOR_BAD; if (state & RC_SERVICE_STOPPING) - snprintf (status, sizeof (status), "stopping "); + snprintf(status, sizeof(status), "stopping "); else if (state & RC_SERVICE_STARTING) { - snprintf (status, sizeof (status), "starting "); + snprintf(status, sizeof(status), "starting "); color = ECOLOR_WARN; } else if (state & RC_SERVICE_INACTIVE) { - snprintf (status, sizeof (status), "inactive "); + snprintf(status, sizeof(status), "inactive "); color = ECOLOR_WARN; } else if (state & RC_SERVICE_STARTED) { - if (geteuid () == 0 && rc_service_daemons_crashed (service)) - snprintf (status, sizeof (status), " crashed "); + if (rc_service_daemons_crashed(service)) + snprintf(status, sizeof(status), " crashed "); else { - snprintf (status, sizeof (status), " started "); + snprintf(status, sizeof(status), " started "); color = ECOLOR_GOOD; } } else if (state & RC_SERVICE_SCHEDULED) { - snprintf (status, sizeof (status), "scheduled"); + snprintf(status, sizeof(status), "scheduled"); color = ECOLOR_WARN; } else - snprintf (status, sizeof (status), " stopped "); + snprintf(status, sizeof(status), " stopped "); errno = 0; - if (c && *c && isatty (fileno (stdout))) - printf ("\n"); - ebracket (cols, color, status); + if (c && *c && isatty(fileno(stdout))) + printf("\n"); + ebracket(cols, color, status); } #include "_usage.h" @@ -115,99 +114,100 @@ static const char * const longopts_help[] = { int rc_status (int argc, char **argv) { - rc_depinfo_t *deptree = NULL; - char **levels = NULL; - char **services = NULL; - char **ordered = NULL; - char *level; - char *service; + RC_DEPTREE *deptree = NULL; + RC_STRINGLIST *levels = NULL; + RC_STRINGLIST *services; + RC_STRINGLIST *types = NULL; + RC_STRINGLIST *ordered; + RC_STRING *s; + RC_STRING *l; + char *p; int opt; - int i; - int j; int depopts = RC_DEP_STRICT | RC_DEP_START | RC_DEP_TRACE; - while ((opt = getopt_long (argc, argv, getoptstring, longopts, - (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, longopts, + (int *) 0)) != -1) switch (opt) { - case 'a': - levels = rc_runlevel_list (); - break; - case 'l': - levels = rc_runlevel_list (); - STRLIST_FOREACH (levels, level, i) - printf ("%s\n", level); - rc_strlist_free (levels); - exit (EXIT_SUCCESS); - /* NOTREACHED */ - case 'r': - level = rc_runlevel_get (); - printf ("%s\n", level); - free (level); - exit (EXIT_SUCCESS); - /* NOTREACHED */ - case 's': - services = rc_services_in_runlevel (NULL); - STRLIST_FOREACH (services, service, i) - print_service (service); - rc_strlist_free (services); - exit (EXIT_SUCCESS); - /* NOTREACHED */ - case 'u': - services = rc_services_in_runlevel (NULL); - levels = rc_runlevel_list (); - STRLIST_FOREACH (services, service, i) { - bool found = false; - STRLIST_FOREACH (levels, level, j) - if (rc_service_in_runlevel (service, level)) { - found = true; - break; - } - if (! found) - print_service (service); - } - rc_strlist_free (levels); - rc_strlist_free (services); - exit (EXIT_SUCCESS); - /* NOTREACHED */ - - case_RC_COMMON_GETOPT + case 'a': + levels = rc_runlevel_list(); + break; + case 'l': + levels = rc_runlevel_list(); + TAILQ_FOREACH (l, levels, entries) + printf("%s\n", l->value); + rc_stringlist_free(levels); + exit(EXIT_SUCCESS); + /* NOTREACHED */ + case 'r': + p = rc_runlevel_get (); + printf("%s\n", p); + free(p); + exit(EXIT_SUCCESS); + /* NOTREACHED */ + case 's': + services = rc_services_in_runlevel(NULL); + TAILQ_FOREACH(s, services, entries) + print_service(s->value); + rc_stringlist_free(services); + exit (EXIT_SUCCESS); + /* NOTREACHED */ + case 'u': + services = rc_services_in_runlevel(NULL); + levels = rc_runlevel_list(); + TAILQ_FOREACH(s, services, entries) { + TAILQ_FOREACH(l, levels, entries) + if (rc_service_in_runlevel(s->value, l->value)) + break; + if (! l) + print_service(s->value); + } + rc_stringlist_free(levels); + rc_stringlist_free(services); + exit (EXIT_SUCCESS); + /* NOTREACHED */ + + case_RC_COMMON_GETOPT } + if (! levels) + levels = rc_stringlist_new(); while (optind < argc) - rc_strlist_add (&levels, argv[optind++]); - - if (! levels) { - level = rc_runlevel_get (); - rc_strlist_add (&levels, level); - free (level); + rc_stringlist_add(levels, argv[optind++]); + if (! TAILQ_FIRST(levels)) { + p = rc_runlevel_get(); + rc_stringlist_add(levels, p); + free(p); } /* Output the services in the order in which they would start */ - if (geteuid () == 0) - deptree = _rc_deptree_load (NULL); - else - deptree = rc_deptree_load (); + deptree = _rc_deptree_load(NULL); - STRLIST_FOREACH (levels, level, i) { - print_level (level); - services = rc_services_in_runlevel (level); + TAILQ_FOREACH(l, levels, entries) { + print_level(l->value); + services = rc_services_in_runlevel(l->value); if (deptree) { - ordered = rc_deptree_depends (deptree, types_nua, - (const char **) services, - level, depopts); - rc_strlist_free (services); + if (! types) { + types = rc_stringlist_new(); + rc_stringlist_add(types, "ineed"); + rc_stringlist_add(types, "iuse"); + rc_stringlist_add(types, "iafter"); + } + ordered = rc_deptree_depends(deptree, types, services, + l->value, depopts); + rc_stringlist_free(services); services = ordered; ordered = NULL; } - STRLIST_FOREACH (services, service, j) - if (rc_service_in_runlevel (service, level)) - print_service (service); - rc_strlist_free (services); + TAILQ_FOREACH(s, services, entries) + if (rc_service_in_runlevel(s->value, l->value)) + print_service(s->value); + rc_stringlist_free(services); } - rc_strlist_free (levels); - rc_deptree_free (deptree); + rc_stringlist_free(types); + rc_stringlist_free(levels); + rc_deptree_free(deptree); - exit (EXIT_SUCCESS); + exit(EXIT_SUCCESS); /* NOTREACHED */ } diff --git a/src/rc/rc-update.c b/src/rc/rc-update.c index fdd1417c..e09f521c 100644 --- a/src/rc/rc-update.c +++ b/src/rc/rc-update.c @@ -42,7 +42,6 @@ #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" extern const char *applet; @@ -68,7 +67,7 @@ static int add (const char *runlevel, const char *service) eerror ("%s: failed to add service `%s' to runlevel `%s': %s", applet, service, runlevel, strerror (errno)); - return (retval); + return retval; } static int delete (const char *runlevel, const char *service) @@ -88,44 +87,47 @@ static int delete (const char *runlevel, const char *service) eerror ("%s: failed to remove service `%s' from runlevel `%s': %s", applet, service, runlevel, strerror (errno)); - return (retval); + return retval; } -static void show (char **runlevels, bool verbose) +static void show (RC_STRINGLIST *runlevels, bool verbose) { - char *service; - char **services = rc_services_in_runlevel (NULL); - char *runlevel; - int i; - int j; - - STRLIST_FOREACH (services, service, i) { - char **in = NULL; - bool inone = false; - - STRLIST_FOREACH (runlevels, runlevel, j) { - if (rc_service_in_runlevel (service, runlevel)) { - rc_strlist_add (&in, runlevel); + RC_STRINGLIST *services = rc_services_in_runlevel(NULL); + RC_STRING *service; + RC_STRING *runlevel; + RC_STRINGLIST *in; + bool inone; + char buffer[PATH_MAX]; + size_t l; + + TAILQ_FOREACH(service, services, entries) { + in = rc_stringlist_new(); + inone = false; + + TAILQ_FOREACH(runlevel, runlevels, entries) { + if (rc_service_in_runlevel(service->value, + runlevel->value)) + { + rc_stringlist_add(in, runlevel->value); inone = true; } else { - char buffer[PATH_MAX]; - memset (buffer, ' ', strlen (runlevel)); - buffer[strlen (runlevel)] = 0; - rc_strlist_add (&in, buffer); + l = strlen(runlevel->value); + memset (buffer, ' ', l); + buffer[l] = 0; + rc_stringlist_add (in, buffer); } } - if (! inone && ! verbose) - continue; - - printf (" %20s |", service); - STRLIST_FOREACH (in, runlevel, j) - printf (" %s", runlevel); - printf ("\n"); - rc_strlist_free (in); + if (inone || verbose) { + printf(" %20s |", service->value); + TAILQ_FOREACH(runlevel, in, entries) + printf (" %s", runlevel->value); + printf ("\n"); + } + rc_stringlist_free(in); } - rc_strlist_free (services); + rc_stringlist_free (services); } #include "_usage.h" @@ -146,111 +148,124 @@ static const char * const longopts_help[] = { #define DODELETE (1 << 2) #define DOSHOW (1 << 3) -int rc_update (int argc, char **argv) +int rc_update(int argc, char **argv) { - int i; + RC_STRINGLIST *runlevels; + RC_STRING *runlevel; char *service = NULL; - char **runlevels = NULL; - char *runlevel; + char *p; int action = 0; bool verbose = false; int opt; int retval = EXIT_FAILURE; + int num_updated = 0; + int (*actfunc)(const char *, const char *); + int ret; - while ((opt = getopt_long (argc, argv, getoptstring, + while ((opt = getopt_long(argc, argv, getoptstring, longopts, (int *) 0)) != -1) - { switch (opt) { - case_RC_COMMON_GETOPT + case_RC_COMMON_GETOPT } - } - verbose = rc_yesno (getenv ("EINFO_VERBOSE")); + verbose = rc_yesno(getenv ("EINFO_VERBOSE")); if ((action & DOSHOW && action != DOSHOW) || (action & DOADD && action != DOADD) || (action & DODELETE && action != DODELETE)) - eerrorx ("%s: cannot mix commands", applet); + eerrorx("%s: cannot mix commands", applet); /* We need to be backwards compatible */ if (optind < argc) { - if (strcmp (argv[optind], "add") == 0) + if (strcmp(argv[optind], "add") == 0) action = DOADD; - else if (strcmp (argv[optind], "delete") == 0 || - strcmp (argv[optind], "del") == 0) + else if (strcmp(argv[optind], "delete") == 0 || + strcmp(argv[optind], "del") == 0) action = DODELETE; - else if (strcmp (argv[optind], "show") == 0) + else if (strcmp(argv[optind], "show") == 0) action = DOSHOW; if (action) optind++; else - eerrorx ("%s: invalid command `%s'", applet, argv[optind]); + eerrorx("%s: invalid command `%s'", applet, argv[optind]); } if (! action) action = DOSHOW; + runlevels = rc_stringlist_new(); + if (optind >= argc) { if (! action & DOSHOW) - eerrorx ("%s: no service specified", applet); + eerrorx("%s: no service specified", applet); } else { service = argv[optind]; optind++; while (optind < argc) - if (rc_runlevel_exists (argv[optind])) - rc_strlist_add (&runlevels, argv[optind++]); + if (rc_runlevel_exists(argv[optind])) + rc_stringlist_add(runlevels, argv[optind++]); else { - rc_strlist_free (runlevels); - eerrorx ("%s: `%s' is not a valid runlevel", applet, argv[optind]); + rc_stringlist_free(runlevels); + eerrorx ("%s: `%s' is not a valid runlevel", + applet, argv[optind]); } } retval = EXIT_SUCCESS; if (action & DOSHOW) { if (service) - rc_strlist_add (&runlevels, service); - if (! runlevels) - runlevels = rc_runlevel_list (); + rc_stringlist_add(runlevels, service); + if (! TAILQ_FIRST(runlevels)) { + free(runlevels); + runlevels = rc_runlevel_list(); + } show (runlevels, verbose); } else { if (! service) eerror ("%s: no service specified", applet); else { - int num_updated = 0; - int (*actfunc)(const char *, const char *); - int ret; - if (action & DOADD) { actfunc = add; } else if (action & DODELETE) { actfunc = delete; - } else + } else { + rc_stringlist_free(runlevels); eerrorx ("%s: invalid action", applet); + } - if (! runlevels) - rc_strlist_add (&runlevels, rc_runlevel_get ()); + if (! TAILQ_FIRST(runlevels)) { + p = rc_runlevel_get(); + rc_stringlist_add(runlevels, p); + free(p); + } - if (! runlevels) + if (! TAILQ_FIRST(runlevels)) { + free(runlevels); eerrorx ("%s: no runlevels found", applet); + } - STRLIST_FOREACH (runlevels, runlevel, i) { - if (! rc_runlevel_exists (runlevel)) { - eerror ("%s: runlevel `%s' does not exist", applet, runlevel); + TAILQ_FOREACH (runlevel, runlevels, entries) { + if (! rc_runlevel_exists(runlevel->value)) { + eerror ("%s: runlevel `%s' does not exist", + applet, runlevel->value); continue; } - ret = actfunc (runlevel, service); + ret = actfunc(runlevel->value, service); if (ret < 0) retval = EXIT_FAILURE; num_updated += ret; } - if (retval == EXIT_SUCCESS && num_updated == 0 && action & DODELETE) - ewarnx ("%s: service `%s' not found in any of the specified runlevels", applet, service); + if (retval == EXIT_SUCCESS && + num_updated == 0 && action & DODELETE) + ewarnx("%s: service `%s' not found in any" + " of the specified runlevels", + applet, service); } } - rc_strlist_free (runlevels); - return (retval); + rc_stringlist_free(runlevels); + return retval; } diff --git a/src/rc/rc.c b/src/rc/rc.c index 98b44cc8..6a6aa0a4 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -42,10 +42,18 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; #include <sys/stat.h> #include <sys/utsname.h> #include <sys/wait.h> + +/* So we can coldplug net devices */ +#ifdef BSD +# include <sys/socket.h> +# include <ifaddrs.h> +#endif + #include <errno.h> #include <dirent.h> #include <ctype.h> #include <getopt.h> +#include <libgen.h> #include <limits.h> #include <stdbool.h> #include <stdio.h> @@ -56,19 +64,12 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; #include <termios.h> #include <unistd.h> -/* So we can coldplug net devices */ -#ifdef BSD -# include <sys/socket.h> -# include <ifaddrs.h> -#endif - #include "builtins.h" #include "einfo.h" #include "rc.h" #include "rc-logger.h" #include "rc-misc.h" #include "rc-plugin.h" -#include "strlist.h" #include "version.h" @@ -81,43 +82,31 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; #define INTERACTIVE RC_SVCDIR "/interactive" -#define DEVBOOT "/dev/.rcboot" - -/* Cleanup anything in main */ -#define CHAR_FREE(_item) if (_item) { \ - free (_item); \ - _item = NULL; \ -} - -extern char **environ; +#define DEVBOOT "/dev/.rcboot" static char *RUNLEVEL = NULL; static char *PREVLEVEL = NULL; const char *applet = NULL; static char *runlevel = NULL; -static char **env = NULL; -static char **newenv = NULL; -static char **coldplugged_services = NULL; -static char **stop_services = NULL; -static char **start_services = NULL; -static rc_depinfo_t *deptree = NULL; -static rc_hook_t hook_out = 0; -static char *tmp = NULL; +static RC_STRINGLIST *coldplugged_services = NULL; +static RC_STRINGLIST *stop_services = NULL; +static RC_STRINGLIST *start_services = NULL; +static RC_STRINGLIST *types_n = NULL; +static RC_STRINGLIST *types_nua = NULL; +static RC_DEPTREE *deptree = NULL; +static RC_HOOK hook_out = 0; struct termios *termios_orig = NULL; -typedef struct pidlist +typedef struct piditem { pid_t pid; - struct pidlist *next; -} pidlist_t; -static pidlist_t *service_pids = NULL; - -static const char *const types_n[] = { "needsme", NULL }; -static const char *const types_nua[] = { "ineed", "iuse", "iafter", NULL }; + LIST_ENTRY(piditem) entries; +} PIDITEM; +LIST_HEAD(, piditem) service_pids; -static void clean_failed (void) +static void clean_failed(void) { DIR *dp; struct dirent *d; @@ -125,70 +114,71 @@ static void clean_failed (void) char *path; /* Clean the failed services state dir now */ - if ((dp = opendir (RC_SVCDIR "/failed"))) { - while ((d = readdir (dp))) { + if ((dp = opendir(RC_SVCDIR "/failed"))) { + while ((d = readdir(dp))) { if (d->d_name[0] == '.' && (d->d_name[1] == '\0' || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) continue; - l = strlen (RC_SVCDIR "/failed/") + strlen (d->d_name) + 1; - path = xmalloc (sizeof (char) * l); - snprintf (path, l, RC_SVCDIR "/failed/%s", d->d_name); + l = strlen(RC_SVCDIR "/failed/") + strlen(d->d_name) + 1; + path = xmalloc(sizeof(char) * l); + snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name); if (path) { - if (unlink (path)) - eerror ("%s: unlink `%s': %s", applet, path, - strerror (errno)); - free (path); + if (unlink(path)) + eerror("%s: unlink `%s': %s", applet, path, + strerror(errno)); + free(path); } } - closedir (dp); + closedir(dp); } } -static void cleanup (void) +static void cleanup(void) { - if (applet && strcmp (applet, "rc") == 0) { - pidlist_t *pl = service_pids; + if (applet && strcmp(applet, "rc") == 0) { + PIDITEM *p1 = LIST_FIRST(&service_pids); + PIDITEM *p2; if (hook_out) - rc_plugin_run (hook_out, runlevel); + rc_plugin_run(hook_out, runlevel); - rc_plugin_unload (); + rc_plugin_unload(); if (! rc_in_plugin && termios_orig) { - tcsetattr (fileno (stdin), TCSANOW, termios_orig); - free (termios_orig); + tcsetattr(fileno(stdin), TCSANOW, termios_orig); + free(termios_orig); } - while (pl) { - pidlist_t *p = pl->next; - free (pl); - pl = p; + while (p1) { + p2 = LIST_NEXT(p1, entries); + free(p1); + p1 = p2; } - rc_strlist_free (env); - rc_strlist_free (newenv); - rc_strlist_free (coldplugged_services); - rc_strlist_free (stop_services); - rc_strlist_free (start_services); - rc_deptree_free (deptree); + rc_stringlist_free(coldplugged_services); + rc_stringlist_free(stop_services); + rc_stringlist_free(start_services); + rc_stringlist_free(types_n); + rc_stringlist_free(types_nua); + rc_deptree_free(deptree); /* Clean runlevel start, stop markers */ if (! rc_in_plugin && ! rc_in_logger) { - rmdir (RC_STARTING); - rmdir (RC_STOPPING); - clean_failed (); + rmdir(RC_STARTING); + rmdir(RC_STOPPING); + clean_failed(); - rc_logger_close (); + rc_logger_close(); } - free (runlevel); + free(runlevel); } } #ifdef __linux__ -static char *proc_getent (const char *ent) +static char *proc_getent(const char *ent) { FILE *fp; char *proc; @@ -196,50 +186,50 @@ static char *proc_getent (const char *ent) char *value = NULL; int i; - if (! exists ("/proc/cmdline")) - return (NULL); + if (! exists("/proc/cmdline")) + return NULL; - if (! (fp = fopen ("/proc/cmdline", "r"))) { - eerror ("failed to open `/proc/cmdline': %s", strerror (errno)); - return (NULL); + if (! (fp = fopen("/proc/cmdline", "r"))) { + eerror("failed to open `/proc/cmdline': %s", strerror(errno)); + return NULL; } - if ((proc = rc_getline (fp)) && - (p = strstr (proc, ent))) + if ((proc = rc_getline(fp)) && + (p = strstr(proc, ent))) { i = p - proc; if (i == '\0' || proc[i - 1] == ' ') { - p += strlen (ent); + p += strlen(ent); if (*p == '=') p++; - value = xstrdup (strsep (&p, " ")); + value = xstrdup(strsep(&p, " ")); } } else errno = ENOENT; - free (proc); - fclose (fp); + free(proc); + fclose(fp); - return (value); + return value; } #endif -static char read_key (bool block) +static char read_key(bool block) { struct termios termios; char c = 0; - int fd = fileno (stdin); + int fd = fileno(stdin); - if (! isatty (fd)) - return (false); + if (! isatty(fd)) + return false; /* Now save our terminal settings. We need to restore them at exit as we * will be changing it for non-blocking reads for Interactive */ if (! termios_orig) { - termios_orig = xmalloc (sizeof (*termios_orig)); - tcgetattr (fd, termios_orig); + termios_orig = xmalloc(sizeof(*termios_orig)); + tcgetattr(fd, termios_orig); } - tcgetattr (fd, &termios); + tcgetattr(fd, &termios); termios.c_lflag &= ~(ICANON | ECHO); if (block) termios.c_cc[VMIN] = 1; @@ -247,49 +237,49 @@ static char read_key (bool block) termios.c_cc[VMIN] = 0; termios.c_cc[VTIME] = 0; } - tcsetattr (fd, TCSANOW, &termios); + tcsetattr(fd, TCSANOW, &termios); - read (fd, &c, 1); + read(fd, &c, 1); - tcsetattr (fd, TCSANOW, termios_orig); + tcsetattr(fd, TCSANOW, termios_orig); - return (c); + return c; } -static bool want_interactive (void) +static bool want_interactive(void) { char c; static bool gotinteractive; static bool interactive; - if (rc_yesno (getenv ("EINFO_QUIET"))) - return (false); + if (rc_yesno(getenv("EINFO_QUIET"))) + return false; if (PREVLEVEL && - strcmp (PREVLEVEL, "N") != 0 && - strcmp (PREVLEVEL, "S") != 0 && - strcmp (PREVLEVEL, "1") != 0) - return (false); + strcmp(PREVLEVEL, "N") != 0 && + strcmp(PREVLEVEL, "S") != 0 && + strcmp(PREVLEVEL, "1") != 0) + return false; if (! gotinteractive) { gotinteractive = true; - interactive = rc_conf_yesno ("rc_interactive"); + interactive = rc_conf_yesno("rc_interactive"); } if (! interactive) - return (false); + return false; - c = read_key (false); - return ((c == 'I' || c == 'i') ? true : false); + c = read_key(false); + return (c == 'I' || c == 'i') ? true : false; } -static void mark_interactive (void) +static void mark_interactive(void) { - FILE *fp = fopen (INTERACTIVE, "w"); + FILE *fp = fopen(INTERACTIVE, "w"); if (fp) - fclose (fp); + fclose(fp); } -static void sulogin (bool cont) +static void sulogin(bool cont) { int status = 0; struct sigaction sa; @@ -297,287 +287,276 @@ static void sulogin (bool cont) sigset_t old; pid_t pid; #ifdef __linux__ - const char *sys = rc_sys (); + const char *sys = rc_sys(); /* VSERVER and OPENVZ systems cannot do a sulogin */ - if (sys && (strcmp (sys, "VSERVER") == 0 || strcmp (sys, "OPENVZ") == 0)) { - execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); - eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno)); + if (sys && (strcmp(sys, "VSERVER") == 0 || strcmp(sys, "OPENVZ") == 0)) { + execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); + eerrorx("%s: unable to exec `/sbin/halt': %s", + applet, strerror(errno)); } #endif - newenv = env_filter (); - if (! cont) { - rc_logger_close (); + rc_logger_close(); #ifdef __linux__ - execle ("/sbin/sulogin", "/sbin/sulogin", (char *) NULL, newenv); - eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno)); + execl("/sbin/sulogin", "/sbin/sulogin", (char *) NULL); + eerrorx("%s: unable to exec `/sbin/sulogin': %s", + applet, strerror(errno)); #else - exit (EXIT_SUCCESS); + exit(EXIT_SUCCESS); #endif } /* We need to block signals until we have forked */ - memset (&sa, 0, sizeof (sa)); + memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; - sigemptyset (&sa.sa_mask); - sigfillset (&full); - sigprocmask (SIG_SETMASK, &full, &old); - pid = vfork (); + sigemptyset(&sa.sa_mask); + sigfillset(&full); + sigprocmask(SIG_SETMASK, &full, &old); + pid = vfork(); if (pid == -1) - eerrorx ("%s: fork: %s", applet, strerror (errno)); + eerrorx("%s: fork: %s", applet, strerror(errno)); if (pid == 0) { /* Restore default handlers */ - sigaction (SIGCHLD, &sa, NULL); - sigaction (SIGHUP, &sa, NULL); - sigaction (SIGINT, &sa, NULL); - sigaction (SIGQUIT, &sa, NULL); - sigaction (SIGTERM, &sa, NULL); - sigaction (SIGUSR1, &sa, NULL); - sigaction (SIGWINCH, &sa, NULL); + sigaction(SIGCHLD, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGWINCH, &sa, NULL); /* Unmask signals */ - sigprocmask (SIG_SETMASK, &old, NULL); + sigprocmask(SIG_SETMASK, &old, NULL); if (termios_orig) - tcsetattr (fileno (stdin), TCSANOW, termios_orig); + tcsetattr(fileno(stdin), TCSANOW, termios_orig); #ifdef __linux__ - execle (SULOGIN, SULOGIN, (char *) NULL, newenv); - eerror ("%s: unable to exec `%s': %s", applet, SULOGIN, - strerror (errno)); + execl(SULOGIN, SULOGIN, (char *) NULL); + eerror("%s: unable to exec `%s': %s", applet, SULOGIN, + strerror(errno)); #else - execle ("/bin/sh", "/bin/sh", (char *) NULL, newenv); - eerror ("%s: unable to exec `/bin/sh': %s", applet, - strerror (errno)); + execl("/bin/sh", "/bin/sh", (char *) NULL); + eerror("%s: unable to exec `/bin/sh': %s", applet, + strerror(errno)); #endif - _exit (EXIT_FAILURE); + _exit(EXIT_FAILURE); } /* Unmask signals and wait for child */ - sigprocmask (SIG_SETMASK, &old, NULL); - waitpid (pid, &status, 0); + sigprocmask(SIG_SETMASK, &old, NULL); + waitpid(pid, &status, 0); } -static void single_user (void) +static void single_user(void) { - rc_logger_close (); + rc_logger_close(); - execl (SHUTDOWN, SHUTDOWN, "now", (char *) NULL); - eerrorx ("%s: unable to exec `" SHUTDOWN "': %s", - applet, strerror (errno)); + execl(SHUTDOWN, SHUTDOWN, "now", (char *) NULL); + eerrorx("%s: unable to exec `" SHUTDOWN "': %s", + applet, strerror(errno)); } -static bool set_ksoftlevel (const char *level) +static bool set_ksoftlevel(const char *level) { FILE *fp; if (! level || - strcmp (level, getenv ("RC_BOOTLEVEL")) == 0 || - strcmp (level, RC_LEVEL_SINGLE) == 0 || - strcmp (level, RC_LEVEL_SYSINIT) == 0) + strcmp(level, getenv ("RC_BOOTLEVEL")) == 0 || + strcmp(level, RC_LEVEL_SINGLE) == 0 || + strcmp(level, RC_LEVEL_SYSINIT) == 0) { - if (exists (RC_KSOFTLEVEL) && - unlink (RC_KSOFTLEVEL) != 0) - eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno)); - return (false); + if (exists(RC_KSOFTLEVEL) && + unlink(RC_KSOFTLEVEL) != 0) + eerror("unlink `%s': %s", RC_KSOFTLEVEL, strerror(errno)); + return false; } - if (! (fp = fopen (RC_KSOFTLEVEL, "w"))) { - eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno)); - return (false); + if (! (fp = fopen(RC_KSOFTLEVEL, "w"))) { + eerror("fopen `%s': %s", RC_KSOFTLEVEL, strerror(errno)); + return false; } - fprintf (fp, "%s", level); - fclose (fp); - return (true); + fprintf(fp, "%s", level); + fclose(fp); + return true; } -static int get_ksoftlevel (char *buffer, int buffer_len) +static int get_ksoftlevel(char *buffer, int buffer_len) { FILE *fp; int i = 0; - if (! exists (RC_KSOFTLEVEL)) - return (0); + if (! exists(RC_KSOFTLEVEL)) + return 0; - if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) { - eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno)); - return (-1); + if (! (fp = fopen(RC_KSOFTLEVEL, "r"))) { + eerror("fopen `%s': %s", RC_KSOFTLEVEL, strerror(errno)); + return -1; } - if (fgets (buffer, buffer_len, fp)) { - i = strlen (buffer) - 1; + if (fgets(buffer, buffer_len, fp)) { + i = strlen(buffer) - 1; if (buffer[i] == '\n') buffer[i] = 0; } - fclose (fp); - return (i); + fclose(fp); + return i; } -static void add_pid (pid_t pid) +static void add_pid(pid_t pid) { - pidlist_t *sp = service_pids; - if (sp) { - while (sp->next) - sp = sp->next; - sp->next = xmalloc (sizeof (*sp->next)); - sp = sp->next; - } else - sp = service_pids = xmalloc (sizeof (*sp)); - memset (sp, 0, sizeof (*sp)); - sp->pid = pid; + PIDITEM *p = xmalloc(sizeof(*p)); + p->pid = pid; + LIST_INSERT_HEAD(&service_pids, p, entries); } -static void remove_pid (pid_t pid) +static void remove_pid(pid_t pid) { - pidlist_t *last = NULL; - pidlist_t *pl; + PIDITEM *p; - for (pl = service_pids; pl; pl = pl->next) { - if (pl->pid == pid) { - if (last) - last->next = pl->next; - else - service_pids = pl->next; - free (pl); - break; + LIST_FOREACH(p, &service_pids, entries) + if (p->pid == pid) { + LIST_REMOVE(p, entries); + free(p); + return; } - last = pl; - } } -static void wait_for_services () +static void wait_for_services(void) { - while (waitpid (0, 0, 0) != -1); + while (waitpid(0, 0, 0) != -1); } -static void handle_signal (int sig) +static void handle_signal(int sig) { int serrno = errno; char signame[10] = { '\0' }; - pidlist_t *pl; pid_t pid; + PIDITEM *pi; int status = 0; struct winsize ws; sigset_t sset; switch (sig) { - case SIGCHLD: - do { - pid = waitpid (-1, &status, WNOHANG); - if (pid < 0) { - if (errno != ECHILD) - eerror ("waitpid: %s", strerror (errno)); - return; - } - } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); - - /* Remove that pid from our list */ - if (pid > 0) - remove_pid (pid); - break; - - case SIGWINCH: - if (rc_logger_tty >= 0) { - ioctl (STDIN_FILENO, TIOCGWINSZ, &ws); - ioctl (rc_logger_tty, TIOCSWINSZ, &ws); + case SIGCHLD: + do { + pid = waitpid(-1, &status, WNOHANG); + if (pid < 0) { + if (errno != ECHILD) + eerror("waitpid: %s", strerror(errno)); + return; } - break; - - case SIGINT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGINT"); - /* FALLTHROUGH */ - case SIGTERM: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGTERM"); - /* FALLTHROUGH */ - case SIGQUIT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGQUIT"); - eerrorx ("%s: caught %s, aborting", applet, signame); - /* NOTREACHED */ - case SIGUSR1: - eerror ("rc: Aborting!"); - - /* Block child signals */ - sigemptyset (&sset); - sigaddset (&sset, SIGCHLD); - sigprocmask (SIG_BLOCK, &sset, NULL); - - /* Kill any running services we have started */ - for (pl = service_pids; pl; pl = pl->next) - kill (pl->pid, SIGTERM); - - /* Notify plugins we are aborting */ - rc_plugin_run (RC_HOOK_ABORT, NULL); - - /* Only drop into single user mode if we're booting */ - if ((PREVLEVEL && - (strcmp (PREVLEVEL, "S") == 0 || - strcmp (PREVLEVEL, "1") == 0)) || - (RUNLEVEL && - (strcmp (RUNLEVEL, "S") == 0 || - strcmp (RUNLEVEL, "1") == 0))) - single_user (); - - exit (EXIT_FAILURE); - /* NOTREACHED */ + } while (! WIFEXITED(status) && ! WIFSIGNALED(status)); - default: - eerror ("%s: caught unknown signal %d", applet, sig); + /* Remove that pid from our list */ + if (pid > 0) + remove_pid(pid); + break; + + case SIGWINCH: + if (rc_logger_tty >= 0) { + ioctl(STDIN_FILENO, TIOCGWINSZ, &ws); + ioctl(rc_logger_tty, TIOCSWINSZ, &ws); + } + break; + + case SIGINT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGINT"); + /* FALLTHROUGH */ + case SIGTERM: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGTERM"); + /* FALLTHROUGH */ + case SIGQUIT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGQUIT"); + eerrorx("%s: caught %s, aborting", applet, signame); + /* NOTREACHED */ + case SIGUSR1: + eerror("rc: Aborting!"); + + /* Block child signals */ + sigemptyset(&sset); + sigaddset(&sset, SIGCHLD); + sigprocmask(SIG_BLOCK, &sset, NULL); + + /* Kill any running services we have started */ + LIST_FOREACH(pi, &service_pids, entries) + kill(pi->pid, SIGTERM); + + /* Notify plugins we are aborting */ + rc_plugin_run(RC_HOOK_ABORT, NULL); + + /* Only drop into single user mode if we're booting */ + if ((PREVLEVEL && + (strcmp(PREVLEVEL, "S") == 0 || + strcmp(PREVLEVEL, "1") == 0)) || + (RUNLEVEL && + (strcmp(RUNLEVEL, "S") == 0 || + strcmp(RUNLEVEL, "1") == 0))) + single_user(); + + exit(EXIT_FAILURE); + /* NOTREACHED */ + + default: + eerror("%s: caught unknown signal %d", applet, sig); } /* Restore errno */ errno = serrno; } -static void run_script (const char *script) +static void run_script(const char *script) { int status = 0; - pid_t pid = vfork (); + pid_t pid = vfork(); + pid_t wpid; if (pid < 0) - eerrorx ("%s: vfork: %s", applet, strerror (errno)); + eerrorx("%s: vfork: %s", applet, strerror(errno)); else if (pid == 0) { - execl (script, script, (char *) NULL); - eerror ("%s: unable to exec `%s': %s", - script, applet, strerror (errno)); - _exit (EXIT_FAILURE); + execl(script, script, (char *) NULL); + eerror("%s: unable to exec `%s': %s", + script, applet, strerror(errno)); + _exit(EXIT_FAILURE); } do { - pid_t wpid = waitpid (pid, &status, 0); + wpid = waitpid(pid, &status, 0); if (wpid < 1) - eerror ("waitpid: %s", strerror (errno)); - } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); + eerror("waitpid: %s", strerror(errno)); + } while (! WIFEXITED(status) && ! WIFSIGNALED(status)); - if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0) - eerrorx ("%s: failed to exec `%s'", applet, script); + if (! WIFEXITED(status) || ! WEXITSTATUS(status) == 0) + eerrorx("%s: failed to exec `%s'", applet, script); } -static void do_coldplug (void) +static void do_coldplug(void) { - size_t s; - int i; + size_t l; DIR *dp; struct dirent *d; char *service; + RC_STRING *s; #ifdef BSD struct ifaddrs *ifap; struct ifaddrs *ifa; + char *p; #endif - if (! rc_conf_yesno ("rc_coldplug") && errno != ENOENT) + if (! rc_conf_yesno("rc_coldplug") && errno != ENOENT) return; /* We need to ensure our state dirs exist. * We should have a better call than this, but oh well. */ - rc_deptree_update_needed (); + rc_deptree_update_needed(); #ifdef BSD if (getifaddrs(&ifap) == 0) { @@ -585,33 +564,33 @@ static void do_coldplug (void) if (ifa->ifa_addr->sa_family != AF_LINK) continue; - s = strlen ("net.") + strlen (ifa->ifa_name) + 1; - tmp = xmalloc (sizeof (char) * s); - snprintf (tmp, s, "net.%s", ifa->ifa_name); - if (rc_service_exists (tmp) && - service_plugable (tmp)) - rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED); - CHAR_FREE (tmp); + l = strlen("net.") + strlen(ifa->ifa_name) + 1; + service = xmalloc(sizeof (char) * l); + snprintf(service, l, "net.%s", ifa->ifa_name); + if (rc_service_exists(service) && + service_plugable(service)) + rc_service_mark(service, RC_SERVICE_COLDPLUGGED); + free(service); } freeifaddrs (ifap); } /* The mice are a little more tricky. * If we coldplug anything else, we'll probably do it here. */ - if ((dp = opendir ("/dev"))) { - while ((d = readdir (dp))) { - if (strncmp (d->d_name, "psm", 3) == 0 || - strncmp (d->d_name, "ums", 3) == 0) + if ((dp = opendir("/dev"))) { + while ((d = readdir(dp))) { + if (strncmp(d->d_name, "psm", 3) == 0 || + strncmp(d->d_name, "ums", 3) == 0) { - char *p = d->d_name + 3; - if (p && isdigit ((int) *p)) { - s = strlen ("moused.") + strlen (d->d_name) + 1; - tmp = xmalloc (sizeof (char) * s); - snprintf (tmp, s, "moused.%s", d->d_name); - if (rc_service_exists (tmp) && - service_plugable (tmp)) - rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED); - CHAR_FREE (tmp); + p = d->d_name + 3; + if (p && isdigit((int) *p)) { + l = strlen("moused.") + strlen(d->d_name) + 1; + service = xmalloc(sizeof(char) * l); + snprintf (service, l, "moused.%s", d->d_name); + if (rc_service_exists (service) && + service_plugable (service)) + rc_service_mark (service, RC_SERVICE_COLDPLUGGED); + free(service); } } } @@ -624,41 +603,57 @@ static void do_coldplug (void) * its coldplugging thing. runscript knows when we're not ready so it * stores a list of coldplugged services in DEVBOOT for us to pick up * here when we are ready for them */ - if ((dp = opendir (DEVBOOT))) { - while ((d = readdir (dp))) { + if ((dp = opendir(DEVBOOT))) { + while ((d = readdir(dp))) { if (d->d_name[0] == '.' && (d->d_name[1] == '\0' || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) continue; - if (rc_service_exists (d->d_name) && - service_plugable (d->d_name)) - rc_service_mark (d->d_name, RC_SERVICE_COLDPLUGGED); - - s = strlen (DEVBOOT "/") + strlen (d->d_name) + 1; - tmp = xmalloc (sizeof (char) * s); - snprintf (tmp, s, DEVBOOT "/%s", d->d_name); - if (tmp) { - if (unlink (tmp)) - eerror ("%s: unlink `%s': %s", applet, tmp, - strerror (errno)); - free (tmp); - } + if (rc_service_exists(d->d_name) && + service_plugable(d->d_name)) + rc_service_mark(d->d_name, RC_SERVICE_COLDPLUGGED); + + l = strlen(DEVBOOT "/") + strlen(d->d_name) + 1; + service = xmalloc(sizeof (char) * l); + snprintf(service, l, DEVBOOT "/%s", d->d_name); + if (unlink(service)) + eerror("%s: unlink `%s': %s", applet, service, + strerror(errno)); + free(service); } - closedir (dp); - rmdir (DEVBOOT); + closedir(dp); + rmdir(DEVBOOT); } #endif - if (rc_yesno (getenv ("EINFO_QUIET"))) + if (rc_yesno(getenv("EINFO_QUIET"))) return; /* Load our list of coldplugged services and display them */ - einfon ("Device initiated services:%s", ecolor (ECOLOR_HILITE)); - coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED); - STRLIST_FOREACH (coldplugged_services, service, i) - printf (" %s", service); - printf ("%s\n", ecolor (ECOLOR_NORMAL)); + einfon("Device initiated services:%s", ecolor(ECOLOR_HILITE)); + coldplugged_services = rc_services_in_state(RC_SERVICE_COLDPLUGGED); + TAILQ_FOREACH(s, coldplugged_services, entries) + printf(" %s", s->value); + printf ("%s\n", ecolor(ECOLOR_NORMAL)); +} + +static bool runlevel_config(const char *service, const char *level) +{ + char *init = rc_service_resolve(service); + char *conf; + size_t l; + bool retval; + + init = dirname(init); + init = dirname(init); + l = strlen(init) + strlen(level) + strlen(service) + 10; + conf = xmalloc(sizeof(char) * l); + snprintf(conf, l, "%s/conf.d/%s.%s", init, service, level); + retval = exists(conf); + free(conf); + + return retval; } #include "_usage.h" @@ -673,16 +668,14 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int main (int argc, char **argv) +int main(int argc, char **argv) { const char *bootlevel = NULL; - const char *sys = rc_sys (); + const char *sys = rc_sys(); char *newlevel = NULL; - char *service = NULL; - char **deporder = NULL; - char **tmplist; - int i = 0; - int j = 0; + RC_STRINGLIST *deporder = NULL; + RC_STRINGLIST *tmplist; + RC_STRING *service; bool going_down = false; bool interactive = false; int depoptions = RC_DEP_STRICT | RC_DEP_TRACE; @@ -692,116 +685,94 @@ int main (int argc, char **argv) bool parallel; int regen = 0; pid_t pid; + RC_STRING *svc1; + RC_STRING *svc2 = NULL; + struct utsname uts; +#ifdef __linux__ + char *cmd; + char *proc; + char *p; + char *token; +#endif - applet = basename_c (argv[0]); - atexit (cleanup); + applet = basename_c(argv[0]); + LIST_INIT(&service_pids); + atexit(cleanup); if (! applet) - eerrorx ("arguments required"); + eerrorx("arguments required"); - if (argc > 1 && (strcmp (argv[1], "--version") == 0)) { - printf ("%s (OpenRC", applet); + if (argc > 1 && (strcmp(argv[1], "--version") == 0)) { + printf("%s (OpenRC", applet); if (sys) - printf (" [%s]", sys); - printf (") " VERSION + printf(" [%s]", sys); + printf(") " VERSION #ifdef BRANDING - " (" BRANDING ")" + " (" BRANDING ")" #endif - "\n"); - exit (EXIT_SUCCESS); + "\n"); + exit(EXIT_SUCCESS); } /* Run our built in applets. If we ran one, we don't return. */ - run_applets (argc, argv); + run_applets(argc, argv); argc--; argv++; /* Change dir to / to ensure all scripts don't use stuff in pwd */ - chdir ("/"); + chdir("/"); /* RUNLEVEL is set by sysvinit as is a magic number * RC_SOFTLEVEL is set by us and is the name for this magic number * even though all our userland documentation refers to runlevel */ - RUNLEVEL = getenv ("RUNLEVEL"); - PREVLEVEL = getenv ("PREVLEVEL"); + RUNLEVEL = getenv("RUNLEVEL"); + PREVLEVEL = getenv("PREVLEVEL"); /* Ensure our environment is pure * Also, add our configuration to it */ - env = env_filter (); - tmplist = env_config (); - rc_strlist_join (&env, tmplist); - rc_strlist_free (tmplist); - - if (env) { - char *p; - -#ifdef __linux__ - /* clearenv isn't portable, but there's no harm in using it - * if we have it */ - clearenv (); -#else - char *var; - /* No clearenv present here then. - * We could manipulate environ directly ourselves, but it seems that - * some kernels bitch about this according to the environ man pages - * so we walk though environ and call unsetenv for each value. */ - while (environ[0]) { - tmp = xstrdup (environ[0]); - p = tmp; - var = strsep (&p, "="); - unsetenv (var); - free (tmp); - } - tmp = NULL; -#endif - - STRLIST_FOREACH (env, p, i) - if (strcmp (p, "RC_SOFTLEVEL") != 0 && strcmp (p, "SOFTLEVEL") != 0) - putenv (p); - - /* We don't free our list as that would be null in environ */ - } + env_filter(); + env_config(); argc++; argv--; - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, + longopts, (int *) 0)) != -1) { switch (opt) { - case 'o': - if (*optarg == '\0') - optarg = NULL; - exit (set_ksoftlevel (optarg) ? EXIT_SUCCESS : EXIT_FAILURE); - /* NOTREACHED */ - case_RC_COMMON_GETOPT + case 'o': + if (*optarg == '\0') + optarg = NULL; + exit(set_ksoftlevel(optarg) ? EXIT_SUCCESS : EXIT_FAILURE); + /* NOTREACHED */ + case_RC_COMMON_GETOPT } } newlevel = argv[optind++]; /* Enable logging */ - setenv ("EINFO_LOG", "rc", 1); + setenv("EINFO_LOG", "rc", 1); /* Export our PID */ - snprintf (pidstr, sizeof (pidstr), "%d", getpid ()); - setenv ("RC_PID", pidstr, 1); + snprintf(pidstr, sizeof(pidstr), "%d", getpid()); + setenv("RC_PID", pidstr, 1); /* Load current softlevel */ - bootlevel = getenv ("RC_BOOTLEVEL"); - runlevel = rc_runlevel_get (); + bootlevel = getenv("RC_BOOTLEVEL"); + runlevel = rc_runlevel_get(); - rc_logger_open (newlevel ? newlevel : runlevel); + rc_logger_open(newlevel ? newlevel : runlevel); /* Setup a signal handler */ - signal_setup (SIGINT, handle_signal); - signal_setup (SIGQUIT, handle_signal); - signal_setup (SIGTERM, handle_signal); - signal_setup (SIGUSR1, handle_signal); - signal_setup (SIGWINCH, handle_signal); - - if (! rc_yesno (getenv ("EINFO_QUIET"))) - interactive = exists (INTERACTIVE); - rc_plugin_load (); + signal_setup(SIGINT, handle_signal); + signal_setup(SIGQUIT, handle_signal); + signal_setup(SIGTERM, handle_signal); + signal_setup(SIGUSR1, handle_signal); + signal_setup(SIGWINCH, handle_signal); + + if (! rc_yesno(getenv("EINFO_QUIET"))) + interactive = exists(INTERACTIVE); + rc_plugin_load(); /* Check we're in the runlevel requested, ie from * rc single @@ -809,450 +780,417 @@ int main (int argc, char **argv) * rc reboot */ if (newlevel) { - if (strcmp (newlevel, RC_LEVEL_SYSINIT) == 0 + if (strcmp(newlevel, RC_LEVEL_SYSINIT) == 0 #ifndef PREFIX && RUNLEVEL && - (strcmp (RUNLEVEL, "S") == 0 || - strcmp (RUNLEVEL, "1") == 0) + (strcmp(RUNLEVEL, "S") == 0 || + strcmp(RUNLEVEL, "1") == 0) #endif - ) + ) { - - struct utsname uts; /* OK, we're either in runlevel 1 or single user mode */ -#ifdef __linux__ - char *cmd; -#endif /* exec init-early.sh if it exists * This should just setup the console to use the correct * font. Maybe it should setup the keyboard too? */ - if (exists (INITEARLYSH)) - run_script (INITEARLYSH); + if (exists(INITEARLYSH)) + run_script(INITEARLYSH); - uname (&uts); - printf ("\n %sOpenRC %s" VERSION "%s is starting up %s", - ecolor (ECOLOR_GOOD), ecolor (ECOLOR_HILITE), - ecolor (ECOLOR_NORMAL), ecolor (ECOLOR_BRACKET)); + uname(&uts); + printf("\n %sOpenRC %s" VERSION "%s is starting up %s", + ecolor(ECOLOR_GOOD), ecolor(ECOLOR_HILITE), + ecolor(ECOLOR_NORMAL), ecolor(ECOLOR_BRACKET)); #ifdef BRANDING - printf (BRANDING " (%s)", uts.machine); + printf(BRANDING " (%s)", uts.machine); #else - printf ("%s %s (%s)", - uts.sysname, - uts.release, - uts.machine); + printf("%s %s (%s)", + uts.sysname, + uts.release, + uts.machine); #endif if (sys) - printf (" [%s]", sys); + printf(" [%s]", sys); - printf ("%s\n\n", ecolor (ECOLOR_NORMAL)); + printf("%s\n\n", ecolor(ECOLOR_NORMAL)); - if (! rc_yesno (getenv ("EINFO_QUIET")) && - rc_conf_yesno ("rc_interactive")) - printf ("Press %sI%s to enter interactive boot mode\n\n", - ecolor (ECOLOR_GOOD), ecolor (ECOLOR_NORMAL)); + if (! rc_yesno(getenv ("EINFO_QUIET")) && + rc_conf_yesno("rc_interactive")) + printf("Press %sI%s to enter interactive boot mode\n\n", + ecolor(ECOLOR_GOOD), ecolor(ECOLOR_NORMAL)); - setenv ("RC_SOFTLEVEL", newlevel, 1); - rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, newlevel); + setenv("RC_SOFTLEVEL", newlevel, 1); + rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, newlevel); hook_out = RC_HOOK_RUNLEVEL_START_OUT; - run_script (INITSH); + run_script(INITSH); #ifdef __linux__ /* If we requested a softlevel, save it now */ - set_ksoftlevel (NULL); - if ((cmd = proc_getent ("softlevel"))) { - set_ksoftlevel (cmd); - free (cmd); + set_ksoftlevel(NULL); + if ((cmd = proc_getent("softlevel"))) { + set_ksoftlevel(cmd); + free(cmd); } #endif /* Setup our coldplugged services now */ - do_coldplug (); + do_coldplug(); - rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, newlevel); + rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, newlevel); hook_out = 0; - if (want_interactive ()) - mark_interactive (); + if (want_interactive()) + mark_interactive(); - exit (EXIT_SUCCESS); - } else if (strcmp (newlevel, RC_LEVEL_SINGLE) == 0) { + exit(EXIT_SUCCESS); + } else if (strcmp(newlevel, RC_LEVEL_SINGLE) == 0) { #ifndef PREFIX if (! RUNLEVEL || - (strcmp (RUNLEVEL, "S") != 0 && - strcmp (RUNLEVEL, "1") != 0)) + (strcmp(RUNLEVEL, "S") != 0 && + strcmp(RUNLEVEL, "1") != 0)) { /* Remember the current runlevel for when we come back */ - set_ksoftlevel (runlevel); - single_user (); + set_ksoftlevel(runlevel); + single_user(); } #endif - } else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) { + } else if (strcmp(newlevel, RC_LEVEL_REBOOT) == 0) { if (! RUNLEVEL || - strcmp (RUNLEVEL, "6") != 0) + strcmp(RUNLEVEL, "6") != 0) { - rc_logger_close (); - execl (SHUTDOWN, SHUTDOWN, "-r", "now", (char *) NULL); - eerrorx ("%s: unable to exec `" SHUTDOWN "': %s", - applet, strerror (errno)); + rc_logger_close(); + execl(SHUTDOWN, SHUTDOWN, "-r", "now", (char *) NULL); + eerrorx("%s: unable to exec `" SHUTDOWN "': %s", + applet, strerror(errno)); } - } else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) { + } else if (strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0) { if (! RUNLEVEL || - strcmp (RUNLEVEL, "0") != 0) + strcmp(RUNLEVEL, "0") != 0) { - rc_logger_close (); - execl (SHUTDOWN, SHUTDOWN, + rc_logger_close(); + execl(SHUTDOWN, SHUTDOWN, #ifdef __linux__ - "-h", + "-h", #else - "-p", + "-p", #endif - "now", (char *) NULL); - eerrorx ("%s: unable to exec `" SHUTDOWN "': %s", - applet, strerror (errno)); + "now", (char *) NULL); + eerrorx("%s: unable to exec `" SHUTDOWN "': %s", + applet, strerror(errno)); } } } /* Now we start handling our children */ - signal_setup (SIGCHLD, handle_signal); + signal_setup(SIGCHLD, handle_signal); /* We should only use ksoftlevel if we were in single user mode * If not, we need to erase ksoftlevel now. */ if (PREVLEVEL && - (strcmp (PREVLEVEL, "1") == 0 || - strcmp (PREVLEVEL, "S") == 0 || - strcmp (PREVLEVEL, "N") == 0)) + (strcmp(PREVLEVEL, "1") == 0 || + strcmp(PREVLEVEL, "S") == 0 || + strcmp(PREVLEVEL, "N") == 0)) { /* Try not to join boot and ksoftlevels together */ if (! newlevel || - strcmp (newlevel, getenv ("RC_BOOTLEVEL")) != 0) - if (get_ksoftlevel (ksoftbuffer, sizeof (ksoftbuffer))) + strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0) + if (get_ksoftlevel(ksoftbuffer, sizeof(ksoftbuffer))) newlevel = ksoftbuffer; } else if (! RUNLEVEL || - (strcmp (RUNLEVEL, "1") != 0 && - strcmp (RUNLEVEL, "S") != 0 && - strcmp (RUNLEVEL, "N") != 0)) + (strcmp(RUNLEVEL, "1") != 0 && + strcmp(RUNLEVEL, "S") != 0 && + strcmp(RUNLEVEL, "N") != 0)) { - set_ksoftlevel (NULL); + set_ksoftlevel(NULL); } if (newlevel && - (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 || - strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 || - strcmp (newlevel, RC_LEVEL_SINGLE) == 0)) + (strcmp(newlevel, RC_LEVEL_REBOOT) == 0 || + strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 || + strcmp(newlevel, RC_LEVEL_SINGLE) == 0)) { going_down = true; - rc_runlevel_set (newlevel); - setenv ("RC_SOFTLEVEL", newlevel, 1); + rc_runlevel_set(newlevel); + setenv("RC_RUNLEVEL", newlevel, 1); #ifdef __FreeBSD__ /* FIXME: we shouldn't have todo this */ /* For some reason, wait_for_services waits for the logger proccess * to finish as well, but only on FreeBSD. We cannot allow this so * we stop logging now. */ - rc_logger_close (); + rc_logger_close(); #endif - rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, newlevel); + rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_IN, newlevel); } else { - rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, runlevel); + rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_IN, runlevel); } hook_out = RC_HOOK_RUNLEVEL_STOP_OUT; /* Check if runlevel is valid if we're changing */ - if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) { - if (! rc_runlevel_exists (newlevel)) + if (newlevel && strcmp(runlevel, newlevel) != 0 && ! going_down) { + if (! rc_runlevel_exists(newlevel)) eerrorx ("%s: is not a valid runlevel", newlevel); } /* Load our deptree */ - if ((deptree = _rc_deptree_load (®en)) == NULL) - eerrorx ("failed to load deptree"); + if ((deptree = _rc_deptree_load(®en)) == NULL) + eerrorx("failed to load deptree"); /* Clean the failed services state dir */ - clean_failed (); + clean_failed(); - if (mkdir (RC_STOPPING, 0755) != 0) { + if (mkdir(RC_STOPPING, 0755) != 0) { if (errno == EACCES) - eerrorx ("%s: superuser access required", applet); - eerrorx ("%s: failed to create stopping dir: %s", - applet, strerror (errno)); + eerrorx("%s: superuser access required", applet); + eerrorx("%s: failed to create stopping dir `%s': %s", + applet, RC_STOPPING, strerror(errno)); } /* Build a list of all services to stop and then work out the * correct order for stopping them */ - stop_services = rc_services_in_state (RC_SERVICE_STARTING); - - tmplist = rc_services_in_state (RC_SERVICE_INACTIVE); - rc_strlist_join (&stop_services, tmplist); - rc_strlist_free (tmplist); - - tmplist = rc_services_in_state (RC_SERVICE_STARTED); - rc_strlist_join (&stop_services, tmplist); - rc_strlist_free (tmplist); - - deporder = rc_deptree_depends (deptree, types_nua, - (const char **) stop_services, - runlevel, depoptions | RC_DEP_STOP); - - rc_strlist_free (stop_services); - stop_services = deporder; - deporder = NULL; - rc_strlist_reverse (stop_services); + stop_services = rc_services_in_state(RC_SERVICE_STARTED); + tmplist = rc_services_in_state(RC_SERVICE_INACTIVE); + TAILQ_CONCAT(stop_services, tmplist); + free(tmplist); + tmplist = rc_services_in_state(RC_SERVICE_STARTING); + TAILQ_CONCAT(stop_services, tmplist); + free(tmplist); + rc_stringlist_sort(&stop_services); + + types_n = rc_stringlist_new(); + rc_stringlist_add(types_n, "needsme"); + + types_nua = rc_stringlist_new(); + rc_stringlist_add(types_nua, "ineed"); + rc_stringlist_add(types_nua, "iuse"); + rc_stringlist_add(types_nua, "iafter"); + + tmplist = rc_deptree_depends(deptree, types_nua, stop_services, + runlevel, depoptions | RC_DEP_STOP); + rc_stringlist_free(stop_services); + stop_services = tmplist; /* Load our list of coldplugged services */ - coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED); - if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && - strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && - strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) + coldplugged_services = rc_services_in_state(RC_SERVICE_COLDPLUGGED); + if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && + strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && + strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) { /* We need to include the boot runlevel services if we're not in it */ - start_services = rc_services_in_runlevel (bootlevel); + start_services = rc_services_in_runlevel(bootlevel); if (strcmp (newlevel ? newlevel : runlevel, bootlevel) != 0) { - tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel); - rc_strlist_join (&start_services, tmplist); - rc_strlist_free (tmplist); + tmplist = rc_services_in_runlevel(newlevel ? newlevel : runlevel); + TAILQ_CONCAT(start_services, tmplist); + free(tmplist); } - STRLIST_FOREACH (coldplugged_services, service, i) - rc_strlist_add (&start_services, service); + TAILQ_FOREACH(service, coldplugged_services, entries) + rc_stringlist_addu(start_services, service->value); } /* Save our softlevel now */ if (going_down) - rc_runlevel_set (newlevel); + rc_runlevel_set(newlevel); - parallel = rc_conf_yesno ("rc_parallel"); + parallel = rc_conf_yesno("rc_parallel"); /* Now stop the services that shouldn't be running */ - STRLIST_FOREACH (stop_services, service, i) { - bool found = false; - char *conf = NULL; - char **stopdeps = NULL; - char *svc1 = NULL; - char *svc2 = NULL; - int k; - - if (rc_service_state (service) & RC_SERVICE_STOPPED) + TAILQ_FOREACH_REVERSE(service, stop_services, rc_stringlist, entries) { + if (rc_service_state(service->value) & RC_SERVICE_STOPPED) continue; /* We always stop the service when in these runlevels */ if (going_down) { - pid = rc_service_stop (service); + pid = rc_service_stop(service->value); if (pid > 0 && ! parallel) - rc_waitpid (pid); + rc_waitpid(pid); continue; } /* If we're in the start list then don't bother stopping us */ - STRLIST_FOREACH (start_services, svc1, j) - if (strcmp (svc1, service) == 0) { - found = true; + TAILQ_FOREACH(svc1, start_services, entries) + if (strcmp (svc1->value, service->value) == 0) break; - } - /* Unless we would use a different config file */ - if (found) { - size_t len; - if (! newlevel) - continue; - - len = strlen (service) + strlen (runlevel) + 2; - tmp = xmalloc (sizeof (char) * len); - snprintf (tmp, len, "%s.%s", service, runlevel); - conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); - found = exists (conf); - CHAR_FREE (conf); - CHAR_FREE (tmp); - if (! found) { - len = strlen (service) + strlen (newlevel) + 2; - tmp = xmalloc (sizeof (char) * len); - snprintf (tmp, len, "%s.%s", service, newlevel); - conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); - found = exists (conf); - CHAR_FREE (conf); - CHAR_FREE (tmp); - if (!found) + if (svc1) { + if (newlevel && strcmp(runlevel, newlevel) != 0) { + /* So we're in the start list. But we should + * be stopped if we have a runlevel + * configuration file for either the current + * or next so we use the correct one. */ + if (! runlevel_config(service->value, runlevel) && + ! runlevel_config(service->value, newlevel)) continue; } - } else { - /* Allow coldplugged services not to be in the runlevels list */ - if (rc_service_state (service) & RC_SERVICE_COLDPLUGGED) + else continue; } - /* We got this far! Or last check is to see if any any service that - * going to be started depends on us */ - rc_strlist_add (&stopdeps, service); - deporder = rc_deptree_depends (deptree, types_n, - (const char **) stopdeps, - runlevel, RC_DEP_STRICT); - rc_strlist_free (stopdeps); - stopdeps = NULL; - found = false; - STRLIST_FOREACH (deporder, svc1, j) { - STRLIST_FOREACH (start_services, svc2, k) - if (strcmp (svc1, svc2) == 0) { - found = true; + /* We got this far! Or last check is to see if any any service + * that going to be started depends on us */ + if (! svc1) { + tmplist = rc_stringlist_new(); + rc_stringlist_add(tmplist, service->value); + deporder = rc_deptree_depends(deptree, types_n, tmplist, + runlevel, RC_DEP_STRICT); + rc_stringlist_free(tmplist); + svc2 = NULL; + TAILQ_FOREACH (svc1, deporder, entries) { + TAILQ_FOREACH(svc2, start_services, entries) + if (strcmp (svc1->value, svc2->value) == 0) + break; + if (svc2) break; - } - if (found) - break; + } + rc_stringlist_free(deporder); + + if (svc2) + continue; } - rc_strlist_free (deporder); - deporder = NULL; /* After all that we can finally stop the blighter! */ - if (! found) { - pid = rc_service_stop (service); - - if (pid > 0) { - add_pid (pid); - if (! parallel) { - rc_waitpid (pid); - remove_pid (pid); - } + pid = rc_service_stop(service->value); + if (pid > 0) { + add_pid(pid); + if (! parallel) { + rc_waitpid(pid); + remove_pid(pid); } } } /* Wait for our services to finish */ - wait_for_services (); + wait_for_services(); /* Notify the plugins we have finished */ - rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_OUT, runlevel); + rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, runlevel); hook_out = 0; - rmdir (RC_STOPPING); + rmdir(RC_STOPPING); /* Store the new runlevel */ if (newlevel) { - rc_runlevel_set (newlevel); - free (runlevel); - runlevel = xstrdup (newlevel); - setenv ("RC_SOFTLEVEL", runlevel, 1); + rc_runlevel_set(newlevel); + free(runlevel); + runlevel = xstrdup(newlevel); + setenv("RC_RUNLEVEL", runlevel, 1); } /* Run the halt script if needed */ - if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 || - strcmp (runlevel, RC_LEVEL_REBOOT) == 0) + if (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 || + strcmp(runlevel, RC_LEVEL_REBOOT) == 0) { - rc_logger_close (); - execl (HALTSH, HALTSH, runlevel, (char *) NULL); - eerrorx ("%s: unable to exec `%s': %s", - applet, HALTSH, strerror (errno)); + rc_logger_close(); + execl(HALTSH, HALTSH, runlevel, (char *) NULL); + eerrorx("%s: unable to exec `%s': %s", + applet, HALTSH, strerror(errno)); } /* Single user is done now */ - if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) { - if (exists (INTERACTIVE)) - unlink (INTERACTIVE); - sulogin (false); + if (strcmp(runlevel, RC_LEVEL_SINGLE) == 0) { + if (exists(INTERACTIVE)) + unlink(INTERACTIVE); + sulogin(false); } - mkdir (RC_STARTING, 0755); - rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, runlevel); + mkdir(RC_STARTING, 0755); + rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, runlevel); hook_out = RC_HOOK_RUNLEVEL_START_OUT; /* Re-add our coldplugged services if they stopped */ - STRLIST_FOREACH (coldplugged_services, service, i) - rc_service_mark (service, RC_SERVICE_COLDPLUGGED); + TAILQ_FOREACH(service, coldplugged_services, entries) + rc_service_mark(service->value, RC_SERVICE_COLDPLUGGED); /* Order the services to start */ - deporder = rc_deptree_depends (deptree, types_nua, - (const char **) start_services, - runlevel, depoptions | RC_DEP_START); - rc_strlist_free (start_services); + rc_stringlist_sort(&start_services); + deporder = rc_deptree_depends(deptree, types_nua, start_services, + runlevel, depoptions | RC_DEP_START); + rc_stringlist_free(start_services); start_services = deporder; - deporder = NULL; #ifdef __linux__ /* mark any services skipped as started */ - if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) { - if ((service = proc_getent ("noinitd"))) { - char *p = service; - char *token; - - while ((token = strsep (&p, ","))) - rc_service_mark (token, RC_SERVICE_STARTED); - free (service); + if (PREVLEVEL && strcmp(PREVLEVEL, "N") == 0) { + proc = p = proc_getent("noinitd"); + if (proc) { + while ((token = strsep(&p, ","))) + rc_service_mark(token, RC_SERVICE_STARTED); + free(proc); } } #endif - STRLIST_FOREACH (start_services, service, i) { - if (rc_service_state (service) & RC_SERVICE_STOPPED) { + TAILQ_FOREACH(service, start_services, entries) { + if (rc_service_state(service->value) & RC_SERVICE_STOPPED) { if (! interactive) - interactive = want_interactive (); + interactive = want_interactive(); if (interactive) { interactive_retry: - printf ("\n"); - einfo ("About to start the service %s", service); - eindent (); - einfo ("1) Start the service\t\t2) Skip the service"); - einfo ("3) Continue boot process\t\t4) Exit to shell"); - eoutdent (); + printf("\n"); + einfo("About to start the service %s", + service->value); + eindent(); + einfo("1) Start the service\t\t2) Skip the service"); + einfo("3) Continue boot process\t\t4) Exit to shell"); + eoutdent(); interactive_option: - switch (read_key (true)) { - case '1': break; - case '2': continue; - case '3': interactive = false; break; - case '4': sulogin (true); goto interactive_retry; - default: goto interactive_option; + switch (read_key(true)) { + case '1': break; + case '2': continue; + case '3': interactive = false; break; + case '4': sulogin(true); goto interactive_retry; + default: goto interactive_option; } } - pid = rc_service_start (service); + pid = rc_service_start(service->value); /* Remember the pid if we're running in parallel */ if (pid > 0) { - add_pid (pid); + add_pid(pid); if (! parallel) { - rc_waitpid (pid); - remove_pid (pid); + rc_waitpid(pid); + remove_pid(pid); } } } } /* Wait for our services to finish */ - wait_for_services (); + wait_for_services(); - rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, runlevel); + rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel); hook_out = 0; #ifdef __linux__ /* mark any services skipped as stopped */ - if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) { - if ((service = proc_getent ("noinitd"))) { - char *p = service; - char *token; - - while ((token = strsep (&p, ","))) - rc_service_mark (token, RC_SERVICE_STOPPED); - free (service); + if (PREVLEVEL && strcmp(PREVLEVEL, "N") == 0) { + proc = p = proc_getent("noinitd"); + if (proc) { + while ((token = strsep(&p, ","))) + rc_service_mark(token, RC_SERVICE_STOPPED); + free(proc); } } #endif /* Store our interactive status for boot */ - if (interactive && strcmp (runlevel, bootlevel) == 0) - mark_interactive (); + if (interactive && strcmp(runlevel, bootlevel) == 0) + mark_interactive(); else { - if (exists (INTERACTIVE)) - unlink (INTERACTIVE); + if (exists(INTERACTIVE)) + unlink(INTERACTIVE); } /* If we're in the boot runlevel and we regenerated our dependencies * we need to delete them so that they are regenerated again in the * default runlevel as they may depend on things that are now available */ - if (regen && strcmp (runlevel, bootlevel) == 0) - unlink (RC_DEPTREE); + if (regen && strcmp(runlevel, bootlevel) == 0) + unlink(RC_DEPTREE_CACHE); - return (EXIT_SUCCESS); + return EXIT_SUCCESS; } diff --git a/src/rc/runscript.c b/src/rc/runscript.c index ef9a3e2a..cfc2611a 100644 --- a/src/rc/runscript.c +++ b/src/rc/runscript.c @@ -34,6 +34,7 @@ #include <sys/ioctl.h> #include <sys/param.h> #include <sys/stat.h> + #include <dlfcn.h> #include <errno.h> #include <fcntl.h> @@ -60,11 +61,10 @@ #include "rc.h" #include "rc-misc.h" #include "rc-plugin.h" -#include "strlist.h" #define SELINUX_LIB RC_LIBDIR "/runscript_selinux.so" -#define PREFIX_LOCK RC_SVCDIR "/prefix.lock" +#define PREFIX_LOCK RC_SVCDIR "/prefix.lock" /* usecs to wait while we poll the fifo */ #define WAIT_INTERVAL 20000000 @@ -75,192 +75,187 @@ #define ONE_SECOND 1000000000 static const char *applet = NULL; -static char **applet_list = NULL; +static RC_STRINGLIST *applet_list = NULL; +static RC_STRINGLIST *restart_services = NULL; +static RC_STRINGLIST *need_services = NULL; +static RC_STRINGLIST *use_services = NULL; +static RC_STRINGLIST *services = NULL; +static RC_STRINGLIST *tmplist = NULL; static char *service = NULL; static char *exclusive = NULL; static char *mtime_test = NULL; -static rc_depinfo_t *deptree = NULL; -static char **services = NULL; -static char **tmplist = NULL; -static char **providelist = NULL; -static char **restart_services = NULL; -static char **need_services = NULL; -static char **use_services = NULL; -static char **env = NULL; -static char *tmp = NULL; -static char *softlevel = NULL; +static RC_DEPTREE *deptree = NULL; +static char *runlevel = NULL; static bool sighup = false; static char *ibsave = NULL; static bool in_background = false; -static rc_hook_t hook_out = 0; +static RC_HOOK hook_out = 0; static pid_t service_pid = 0; static char *prefix = NULL; static bool prefix_locked = false; static int signal_pipe[2] = { -1, -1 }; static int master_tty = -1; -extern char **environ; - -static const char *const types_b[] = { "broken", NULL }; -static const char *const types_n[] = { "ineed", NULL }; -static const char *const types_nu[] = { "ineed", "iuse", NULL }; -static const char *const types_nua[] = { "ineed", "iuse", "iafter", NULL }; - -static const char *const types_m[] = { "needsme", NULL }; -static const char *const types_mua[] = { "needsme", "usesme", "beforeme", NULL }; +static RC_STRINGLIST *types_b = NULL; +static RC_STRINGLIST *types_n = NULL; +static RC_STRINGLIST *types_nu = NULL; +static RC_STRINGLIST *types_nua = NULL; +static RC_STRINGLIST *types_m = NULL; +static RC_STRINGLIST *types_mua = NULL; #ifdef __linux__ -static void (*selinux_run_init_old) (void); -static void (*selinux_run_init_new) (int argc, char **argv); +static void (*selinux_run_init_old)(void); +static void (*selinux_run_init_new)(int argc, char **argv); -static void setup_selinux (int argc, char **argv); +static void setup_selinux(int argc, char **argv); -static void setup_selinux (int argc, char **argv) +static void setup_selinux(int argc, char **argv) { void *lib_handle = NULL; - if (! exists (SELINUX_LIB)) + if (! exists(SELINUX_LIB)) return; - lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL); + lib_handle = dlopen(SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL); if (! lib_handle) { - eerror ("dlopen: %s", dlerror ()); + eerror("dlopen: %s", dlerror()); return; } selinux_run_init_old = (void (*)(void)) - dlfunc (lib_handle, "selinux_runscript"); + dlfunc(lib_handle, "selinux_runscript"); selinux_run_init_new = (void (*)(int, char **)) - dlfunc (lib_handle, "selinux_runscript2"); + dlfunc(lib_handle, "selinux_runscript2"); /* Use new run_init if it exists, else fall back to old */ if (selinux_run_init_new) - selinux_run_init_new (argc, argv); + selinux_run_init_new(argc, argv); else if (selinux_run_init_old) - selinux_run_init_old (); + selinux_run_init_old(); else /* This shouldnt happen... probably corrupt lib */ - eerrorx ("run_init is missing from runscript_selinux.so!"); + eerrorx("run_init is missing from runscript_selinux.so!"); - dlclose (lib_handle); + dlclose(lib_handle); } #endif -static void handle_signal (int sig) +static void handle_signal(int sig) { int serrno = errno; char signame[10] = { '\0' }; struct winsize ws; switch (sig) { - case SIGHUP: - sighup = true; - break; - - case SIGCHLD: - if (signal_pipe[1] > -1) { - if (write (signal_pipe[1], &sig, sizeof (sig)) == -1) - eerror ("%s: send: %s", service, strerror (errno)); - } else - rc_waitpid (-1); - break; - - case SIGWINCH: - if (master_tty >= 0) { - ioctl (fileno (stdout), TIOCGWINSZ, &ws); - ioctl (master_tty, TIOCSWINSZ, &ws); - } - break; + case SIGHUP: + sighup = true; + break; + + case SIGCHLD: + if (signal_pipe[1] > -1) { + if (write(signal_pipe[1], &sig, sizeof(sig)) == -1) + eerror("%s: send: %s", service, strerror(errno)); + } else + rc_waitpid (-1); + break; - case SIGINT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGINT"); - /* FALLTHROUGH */ - case SIGTERM: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGTERM"); - /* FALLTHROUGH */ - case SIGQUIT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGQUIT"); - /* Send the signal to our children too */ - if (service_pid > 0) - kill (service_pid, sig); - eerrorx ("%s: caught %s, aborting", applet, signame); - /* NOTREACHED */ - - default: - eerror ("%s: caught unknown signal %d", applet, sig); + case SIGWINCH: + if (master_tty >= 0) { + ioctl(fileno(stdout), TIOCGWINSZ, &ws); + ioctl(master_tty, TIOCSWINSZ, &ws); + } + break; + + case SIGINT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGINT"); + /* FALLTHROUGH */ + case SIGTERM: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGTERM"); + /* FALLTHROUGH */ + case SIGQUIT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGQUIT"); + /* Send the signal to our children too */ + if (service_pid > 0) + kill(service_pid, sig); + eerrorx("%s: caught %s, aborting", applet, signame); + /* NOTREACHED */ + + default: + eerror("%s: caught unknown signal %d", applet, sig); } /* Restore errno */ errno = serrno; } -static time_t get_mtime (const char *pathname, bool follow_link) +static time_t get_mtime(const char *pathname, bool follow_link) { struct stat buf; int retval; if (! pathname) - return (0); + return 0; - retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf); + retval = follow_link ? stat(pathname, &buf) : lstat(pathname, &buf); if (! retval) - return (buf.st_mtime); + return buf.st_mtime; errno = 0; - return (0); + return 0; } -static bool in_control () +static const char *const tests[] = { + "starting", "started", "stopping", "inactive", "wasinactive", NULL +}; +static bool in_control() { char *path; + time_t m; time_t mtime; - const char *tests[] = { "starting", "started", "stopping", - "inactive", "wasinactive", NULL }; int i = 0; if (sighup) - return (false); + return false; - if (! mtime_test || ! exists (mtime_test)) - return (false); + if (! mtime_test || ! exists(mtime_test)) + return false; - if (rc_service_state (applet) & RC_SERVICE_STOPPED) - return (false); + if (rc_service_state(applet) & RC_SERVICE_STOPPED) + return false; - if (! (mtime = get_mtime (mtime_test, false))) - return (false); + if (! (mtime = get_mtime(mtime_test, false))) + return false; while (tests[i]) { - path = rc_strcatpaths (RC_SVCDIR, tests[i], applet, (char *) NULL); - if (exists (path)) { - time_t m = get_mtime (path, false); + path = rc_strcatpaths(RC_SVCDIR, tests[i], applet, (char *) NULL); + if (exists(path)) { + m = get_mtime(path, false); if (mtime < m && m != 0) { - free (path); - return (false); + free(path); + return false; } } - free (path); + free(path); i++; } - return (true); + return true; } -static void uncoldplug () +static void uncoldplug() { - char *cold = rc_strcatpaths (RC_SVCDIR, "coldplugged", applet, (char *) NULL); - if (exists (cold) && unlink (cold) != 0) - eerror ("%s: unlink `%s': %s", applet, cold, strerror (errno)); - free (cold); + char *cold = rc_strcatpaths(RC_SVCDIR, "coldplugged", applet, (char *) NULL); + if (exists(cold) && unlink(cold) != 0) + eerror("%s: unlink `%s': %s", applet, cold, strerror(errno)); + free(cold); } -static void start_services (char **list) { - char *svc; - int i; - rc_service_state_t state = rc_service_state (service); +static void start_services(RC_STRINGLIST *list) { + RC_STRING *svc; + RC_SERVICE state = rc_service_state (service); if (! list) return; @@ -270,102 +265,107 @@ static void start_services (char **list) { state & RC_SERVICE_STARTING || state & RC_SERVICE_STARTED) { - STRLIST_FOREACH (list, svc, i) { - if (rc_service_state (svc) & RC_SERVICE_STOPPED) { + TAILQ_FOREACH(svc, list, entries) { + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) { if (state & RC_SERVICE_INACTIVE || state & RC_SERVICE_WASINACTIVE) { - rc_service_schedule_start (service, svc); - ewarn ("WARNING: %s is scheduled to started when %s has started", - svc, applet); + rc_service_schedule_start(service, svc->value); + ewarn("WARNING: %s is scheduled to started" + " when %s has started", + svc->value, applet); } else - rc_service_start (svc); + rc_service_start(svc->value); } } } } -static void restore_state (void) +static void restore_state(void) { - rc_service_state_t state; + RC_SERVICE state; - if (rc_in_plugin || ! in_control ()) + if (rc_in_plugin || ! in_control()) return; - state = rc_service_state (applet); + state = rc_service_state(applet); if (state & RC_SERVICE_STOPPING) { - if (state & RC_SERVICE_WASINACTIVE) - rc_service_mark (applet, RC_SERVICE_INACTIVE); + rc_service_mark(applet, RC_SERVICE_INACTIVE); else - rc_service_mark (applet, RC_SERVICE_STARTED); - if (rc_runlevel_stopping ()) - rc_service_mark (applet, RC_SERVICE_FAILED); + rc_service_mark(applet, RC_SERVICE_STARTED); + if (rc_runlevel_stopping()) + rc_service_mark(applet, RC_SERVICE_FAILED); } else if (state & RC_SERVICE_STARTING) { if (state & RC_SERVICE_WASINACTIVE) - rc_service_mark (applet, RC_SERVICE_INACTIVE); + rc_service_mark(applet, RC_SERVICE_INACTIVE); else - rc_service_mark (applet, RC_SERVICE_STOPPED); - if (rc_runlevel_starting ()) - rc_service_mark (applet, RC_SERVICE_FAILED); + rc_service_mark(applet, RC_SERVICE_STOPPED); + if (rc_runlevel_starting()) + rc_service_mark(applet, RC_SERVICE_FAILED); } if (exclusive) - unlink (exclusive); - free (exclusive); + unlink(exclusive); + free(exclusive); exclusive = NULL; } -static void cleanup (void) +static void cleanup(void) { - restore_state (); + restore_state(); if (! rc_in_plugin) { if (prefix_locked) - unlink (PREFIX_LOCK); + unlink(PREFIX_LOCK); if (hook_out) { - rc_plugin_run (hook_out, applet); + rc_plugin_run(hook_out, applet); if (hook_out == RC_HOOK_SERVICE_START_DONE) - rc_plugin_run (RC_HOOK_SERVICE_START_OUT, applet); + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); else if (hook_out == RC_HOOK_SERVICE_STOP_DONE) - rc_plugin_run (RC_HOOK_SERVICE_STOP_OUT, applet); + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); } if (restart_services) - start_services (restart_services); + start_services(restart_services); } - rc_plugin_unload (); - rc_deptree_free (deptree); - rc_strlist_free (services); - rc_strlist_free (providelist); - rc_strlist_free (need_services); - rc_strlist_free (use_services); - rc_strlist_free (restart_services); - rc_strlist_free (applet_list); - rc_strlist_free (tmplist); + rc_stringlist_free(types_b); + rc_stringlist_free(types_n); + rc_stringlist_free(types_nu); + rc_stringlist_free(types_nua); + rc_stringlist_free(types_m); + rc_stringlist_free(types_mua); + + rc_plugin_unload(); + rc_deptree_free(deptree); + + rc_stringlist_free(restart_services); + rc_stringlist_free(need_services); + rc_stringlist_free(use_services); + rc_stringlist_free(services); + rc_stringlist_free(applet_list); + rc_stringlist_free(tmplist); free (ibsave); - rc_strlist_free (env); - if (mtime_test) { if (! rc_in_plugin) - unlink (mtime_test); - free (mtime_test); + unlink(mtime_test); + free(mtime_test); } - free (exclusive); - free (service); - free (prefix); - free (softlevel); + free(exclusive); + free(service); + free(prefix); + free(runlevel); } -static int write_prefix (const char *buffer, size_t bytes, bool *prefixed) { +static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) { unsigned int i; - const char *ec = ecolor (ECOLOR_HILITE); - const char *ec_normal = ecolor (ECOLOR_NORMAL); + const char *ec = ecolor(ECOLOR_HILITE); + const char *ec_normal = ecolor(ECOLOR_NORMAL); ssize_t ret = 0; - int fd = fileno (stdout); + int fd = fileno(stdout); for (i = 0; i < bytes; i++) { /* We don't prefix escape codes, like eend */ @@ -373,25 +373,25 @@ static int write_prefix (const char *buffer, size_t bytes, bool *prefixed) { *prefixed = true; if (! *prefixed) { - ret += write (fd, ec, strlen (ec)); - ret += write (fd, prefix, strlen (prefix)); - ret += write (fd, ec_normal, strlen (ec_normal)); - ret += write (fd, "|", 1); + ret += write(fd, ec, strlen(ec)); + ret += write(fd, prefix, strlen(prefix)); + ret += write(fd, ec_normal, strlen(ec_normal)); + ret += write(fd, "|", 1); *prefixed = true; } if (buffer[i] == '\n') *prefixed = false; - ret += write (fd, buffer + i, 1); + ret += write(fd, buffer + i, 1); } - return (ret); + return ret; } -static bool svc_exec (const char *arg1, const char *arg2) +static bool svc_exec(const char *arg1, const char *arg2) { bool execok; - int fdout = fileno (stdout); + int fdout = fileno(stdout); struct termios tt; struct winsize ws; int i; @@ -405,12 +405,12 @@ static bool svc_exec (const char *arg1, const char *arg2) int slave_tty; /* Setup our signal pipe */ - if (pipe (signal_pipe) == -1) - eerrorx ("%s: pipe: %s", service, applet); + if (pipe(signal_pipe) == -1) + eerrorx("%s: pipe: %s", service, applet); for (i = 0; i < 2; i++) - if ((flags = fcntl (signal_pipe[i], F_GETFD, 0) == -1 || - fcntl (signal_pipe[i], F_SETFD, flags | FD_CLOEXEC) == -1)) - eerrorx ("%s: fcntl: %s", service, strerror (errno)); + if ((flags = fcntl(signal_pipe[i], F_GETFD, 0) == -1 || + fcntl(signal_pipe[i], F_SETFD, flags | FD_CLOEXEC) == -1)) + eerrorx("%s: fcntl: %s", service, strerror(errno)); /* Open a pty for our prefixed output * We do this instead of mapping pipes to stdout, stderr so that @@ -418,127 +418,125 @@ static bool svc_exec (const char *arg1, const char *arg2) * The only loss is that we can no longer tell the difference * between the childs stdout or stderr */ master_tty = slave_tty = -1; - if (prefix && isatty (fdout)) { - tcgetattr (fdout, &tt); - ioctl (fdout, TIOCGWINSZ, &ws); + if (prefix && isatty(fdout)) { + tcgetattr(fdout, &tt); + ioctl(fdout, TIOCGWINSZ, &ws); /* If the below call fails due to not enough ptys then we don't * prefix the output, but we still work */ - openpty (&master_tty, &slave_tty, NULL, &tt, &ws); + openpty(&master_tty, &slave_tty, NULL, &tt, &ws); if (master_tty >= 0 && - (flags = fcntl (master_tty, F_GETFD, 0)) == 0) - fcntl (master_tty, F_SETFD, flags | FD_CLOEXEC); + (flags = fcntl(master_tty, F_GETFD, 0)) == 0) + fcntl(master_tty, F_SETFD, flags | FD_CLOEXEC); if (slave_tty >=0 && - (flags = fcntl (slave_tty, F_GETFD, 0)) == 0) - fcntl (slave_tty, F_SETFD, flags | FD_CLOEXEC); + (flags = fcntl(slave_tty, F_GETFD, 0)) == 0) + fcntl(slave_tty, F_SETFD, flags | FD_CLOEXEC); } service_pid = fork(); if (service_pid == -1) - eerrorx ("%s: fork: %s", service, strerror (errno)); + eerrorx("%s: fork: %s", service, strerror(errno)); if (service_pid == 0) { if (slave_tty >= 0) { - dup2 (slave_tty, 1); - dup2 (slave_tty, 2); + dup2(slave_tty, 1); + dup2(slave_tty, 2); } - if (exists (RC_SVCDIR "/runscript.sh")) { - execl (RC_SVCDIR "/runscript.sh", RC_SVCDIR "/runscript.sh", - service, arg1, arg2, (char *) NULL); - eerror ("%s: exec `" RC_SVCDIR "/runscript.sh': %s", - service, strerror (errno)); - _exit (EXIT_FAILURE); + if (exists(RC_SVCDIR "/runscript.sh")) { + execl(RC_SVCDIR "/runscript.sh", RC_SVCDIR "/runscript.sh", + service, arg1, arg2, (char *) NULL); + eerror("%s: exec `" RC_SVCDIR "/runscript.sh': %s", + service, strerror(errno)); + _exit(EXIT_FAILURE); } else { - execl (RC_LIBDIR "/sh/runscript.sh", RC_LIBDIR "/sh/runscript.sh", - service, arg1, arg2, (char *) NULL); - eerror ("%s: exec `" RC_LIBDIR "/sh/runscript.sh': %s", - service, strerror (errno)); - _exit (EXIT_FAILURE); + execl(RC_LIBDIR "/sh/runscript.sh", RC_LIBDIR "/sh/runscript.sh", + service, arg1, arg2, (char *) NULL); + eerror("%s: exec `" RC_LIBDIR "/sh/runscript.sh': %s", + service, strerror(errno)); + _exit(EXIT_FAILURE); } } - selfd = MAX (master_tty, signal_pipe[0]) + 1; - buffer = xmalloc (sizeof (char) * BUFSIZ); + selfd = MAX(master_tty, signal_pipe[0]) + 1; + buffer = xmalloc(sizeof(char) * BUFSIZ); for (;;) { - FD_ZERO (&rset); - FD_SET (signal_pipe[0], &rset); + FD_ZERO(&rset); + FD_SET(signal_pipe[0], &rset); if (master_tty >= 0) - FD_SET (master_tty, &rset); + FD_SET(master_tty, &rset); - if ((s = select (selfd, &rset, NULL, NULL, NULL)) == -1) { + if ((s = select(selfd, &rset, NULL, NULL, NULL)) == -1) { if (errno != EINTR) { - eerror ("%s: select: %s", service, strerror (errno)); + eerror("%s: select: %s", service, strerror(errno)); break; } } if (s > 0) { - if (master_tty >= 0 && FD_ISSET (master_tty, &rset)) { - bytes = read (master_tty, buffer, BUFSIZ); - write_prefix (buffer, bytes, &prefixed); + if (master_tty >= 0 && FD_ISSET(master_tty, &rset)) { + bytes = read(master_tty, buffer, BUFSIZ); + write_prefix(buffer, bytes, &prefixed); } /* Only SIGCHLD signals come down this pipe */ - if (FD_ISSET (signal_pipe[0], &rset)) + if (FD_ISSET(signal_pipe[0], &rset)) break; } } - free (buffer); - close (signal_pipe[0]); - close (signal_pipe[1]); + free(buffer); + close(signal_pipe[0]); + close(signal_pipe[1]); signal_pipe[0] = signal_pipe[1] = -1; if (master_tty >= 0) { /* Why did we do this? */ /* signal (SIGWINCH, SIG_IGN); */ - close (master_tty); + close(master_tty); master_tty = -1; } - execok = rc_waitpid (service_pid) == 0 ? true : false; + execok = rc_waitpid(service_pid) == 0 ? true : false; service_pid = 0; - return (execok); + return execok; } -static bool svc_wait (rc_depinfo_t *depinfo, const char *svc) +static bool svc_wait(const char *svc) { - char *s; - char *fifo; + char fifo[PATH_MAX]; struct timespec ts; int nloops = WAIT_MAX * (ONE_SECOND / WAIT_INTERVAL); bool retval = false; bool forever = false; - char **keywords = NULL; - int i; - - if (! service) - return (false); + RC_STRINGLIST *keywords; + RC_STRING *s; /* Some services don't have a timeout, like fsck */ - keywords = rc_deptree_depend (depinfo, svc, "keyword"); - STRLIST_FOREACH (keywords, s, i) { - if (strcmp (s, "notimeout") == 0) { - forever = true; - break; + keywords = rc_deptree_depend(deptree, svc, "keyword"); + if (keywords) { + TAILQ_FOREACH(s, keywords, entries) { + if (strcmp (s->value, "notimeout") == 0) { + forever = true; + break; + } } + rc_stringlist_free (keywords); } - rc_strlist_free (keywords); - fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename_c (svc), (char *) NULL); + snprintf(fifo, sizeof(fifo), RC_SVCDIR "/exclusive/%s", basename_c(svc)); ts.tv_sec = 0; ts.tv_nsec = WAIT_INTERVAL; while (nloops) { - if (! exists (fifo)) { + if (! exists(fifo)) { retval = true; break; } - if (nanosleep (&ts, NULL) == -1) { + if (nanosleep(&ts, NULL) == -1) { if (errno != EINTR) break; } @@ -547,190 +545,211 @@ static bool svc_wait (rc_depinfo_t *depinfo, const char *svc) nloops --; } - if (! exists (fifo)) + if (! exists(fifo)) retval = true; - free (fifo); - return (retval); + return retval; } -static rc_service_state_t svc_status () +static RC_SERVICE svc_status(void) { char status[10]; int (*e) (const char *fmt, ...) = &einfo; - - rc_service_state_t state = rc_service_state (service); + RC_SERVICE state = rc_service_state(service); if (state & RC_SERVICE_STOPPING) { - snprintf (status, sizeof (status), "stopping"); + snprintf(status, sizeof(status), "stopping"); e = &ewarn; } else if (state & RC_SERVICE_STARTING) { - snprintf (status, sizeof (status), "starting"); + snprintf(status, sizeof(status), "starting"); e = &ewarn; } else if (state & RC_SERVICE_INACTIVE) { - snprintf (status, sizeof (status), "inactive"); + snprintf(status, sizeof(status), "inactive"); e = &ewarn; } else if (state & RC_SERVICE_STARTED) { - if (geteuid () == 0 && rc_service_daemons_crashed (service)) { - snprintf (status, sizeof (status), "crashed"); + if (rc_service_daemons_crashed(service)) { + snprintf(status, sizeof (status), "crashed"); e = &eerror; } else - snprintf (status, sizeof (status), "started"); + snprintf(status, sizeof(status), "started"); } else - snprintf (status, sizeof (status), "stopped"); + snprintf(status, sizeof(status), "stopped"); - e ("status: %s", status); - return (state); + e("status: %s", status); + return state; } -static void make_exclusive () +static void make_exclusive(void) { char *path; size_t l; /* We create a fifo so that other services can wait until we complete */ if (! exclusive) - exclusive = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL); + exclusive = rc_strcatpaths(RC_SVCDIR, "exclusive", applet, (char *) NULL); - if (mkfifo (exclusive, 0600) != 0 && errno != EEXIST && + if (mkfifo(exclusive, 0600) != 0 && errno != EEXIST && (errno != EACCES || geteuid () == 0)) eerrorx ("%s: unable to create fifo `%s': %s", - applet, exclusive, strerror (errno)); + applet, exclusive, strerror(errno)); - path = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL); + path = rc_strcatpaths(RC_SVCDIR, "exclusive", applet, (char *) NULL); l = strlen (path) + 16; - mtime_test = xmalloc (sizeof (char) * l); - snprintf (mtime_test, l, "%s.%d", path, getpid ()); - free (path); - - if (exists (mtime_test) && unlink (mtime_test) != 0) { - eerror ("%s: unlink `%s': %s", - applet, mtime_test, strerror (errno)); - free (mtime_test); + mtime_test = xmalloc(sizeof (char) * l); + snprintf(mtime_test, l, "%s.%d", path, getpid()); + free(path); + + if (exists(mtime_test) && unlink(mtime_test) != 0) { + eerror("%s: unlink `%s': %s", + applet, mtime_test, strerror(errno)); + free(mtime_test); mtime_test = NULL; return; } - if (symlink (service, mtime_test) != 0) { - eerror ("%s: symlink `%s' to `%s': %s", - applet, service, mtime_test, strerror (errno)); - free (mtime_test); + if (symlink(service, mtime_test) != 0) { + eerror("%s: symlink `%s' to `%s': %s", + applet, service, mtime_test, strerror(errno)); + free(mtime_test); mtime_test = NULL; } } -static void unlink_mtime_test () +static void unlink_mtime_test(void) { - if (unlink (mtime_test) != 0) - eerror ("%s: unlink `%s': %s", applet, mtime_test, strerror (errno)); - free (mtime_test); + if (unlink(mtime_test) != 0) + eerror("%s: unlink `%s': %s", applet, mtime_test, strerror(errno)); + free(mtime_test); mtime_test = NULL; } -static void get_started_services () +static void get_started_services(void) +{ + RC_STRINGLIST *tmp = rc_services_in_state(RC_SERVICE_INACTIVE); + rc_stringlist_free(restart_services); + restart_services = rc_services_in_state(RC_SERVICE_STARTED); + TAILQ_CONCAT(restart_services, tmp); + free(tmp); +} + +static void setup_types(void) { - rc_strlist_free (tmplist); - tmplist = rc_services_in_state (RC_SERVICE_INACTIVE); - rc_strlist_free (restart_services); - restart_services = rc_services_in_state (RC_SERVICE_STARTED); - rc_strlist_join (&restart_services, tmplist); - rc_strlist_free (tmplist); - tmplist = NULL; + types_b = rc_stringlist_new(); + rc_stringlist_add(types_b, "broken"); + + types_n = rc_stringlist_new(); + rc_stringlist_add(types_n, "ineed"); + + types_nu = rc_stringlist_new(); + rc_stringlist_add(types_nu, "ineed"); + rc_stringlist_add(types_nu, "iuse"); + + types_nua = rc_stringlist_new(); + rc_stringlist_add(types_nua, "ineed"); + rc_stringlist_add(types_nua, "iuse"); + rc_stringlist_add(types_nua, "iafter"); + + types_m = rc_stringlist_new(); + rc_stringlist_add(types_m, "needsme"); + + types_mua = rc_stringlist_new(); + rc_stringlist_add(types_mua, "needsme"); + rc_stringlist_add(types_mua, "usesme"); + rc_stringlist_add(types_mua, "beforeme"); } -static void svc_start (bool deps) +static void svc_start(bool deps) { bool started; bool background = false; - char *svc; - char *svc2; - int i; - int j; + RC_STRING *svc; + RC_STRING *svc2; int depoptions = RC_DEP_TRACE; - rc_service_state_t state; + RC_SERVICE state; + bool first; + int n; + size_t len; + char *p; + char *tmp; - state = rc_service_state (service); + state = rc_service_state(service); - if (rc_yesno (getenv ("IN_HOTPLUG")) || in_background) { + if (rc_yesno(getenv("IN_HOTPLUG")) || in_background) { if (! state & RC_SERVICE_INACTIVE && ! state & RC_SERVICE_STOPPED) - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); background = true; } if (state & RC_SERVICE_STARTED) { - ewarn ("WARNING: %s has already been started", applet); + ewarn("WARNING: %s has already been started", applet); return; } else if (state & RC_SERVICE_STARTING) - ewarnx ("WARNING: %s is already starting", applet); + ewarnx("WARNING: %s is already starting", applet); else if (state & RC_SERVICE_STOPPING) - ewarnx ("WARNING: %s is stopping", applet); + ewarnx("WARNING: %s is stopping", applet); else if (state & RC_SERVICE_INACTIVE && ! background) - ewarnx ("WARNING: %s has already started, but is inactive", applet); + ewarnx("WARNING: %s has already started, but is inactive", applet); - if (! rc_service_mark (service, RC_SERVICE_STARTING)) { + if (! rc_service_mark(service, RC_SERVICE_STARTING)) { if (errno == EACCES) - eerrorx ("%s: superuser access required", applet); - eerrorx ("ERROR: %s has been started by something else", applet); + eerrorx("%s: superuser access required", applet); + eerrorx("ERROR: %s has been started by something else", applet); } - make_exclusive (service); + make_exclusive(); hook_out = RC_HOOK_SERVICE_START_OUT; - rc_plugin_run (RC_HOOK_SERVICE_START_IN, applet); + rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet); - if (rc_conf_yesno ("rc_depend_strict")) + if (rc_conf_yesno("rc_depend_strict")) depoptions |= RC_DEP_STRICT; if (deps) { if (! deptree && ((deptree = _rc_deptree_load (NULL)) == NULL)) - eerrorx ("failed to load deptree"); + eerrorx("failed to load deptree"); - rc_strlist_free (services); - services = rc_deptree_depends (deptree, types_b, - (const char * const *) applet_list, - softlevel, 0); - if (services) { + if (! types_b) + setup_types(); + + services = rc_deptree_depends(deptree, types_b, applet_list, + runlevel, 0); + if (TAILQ_FIRST(services)) { eerrorn ("ERROR: `%s' needs ", applet); - STRLIST_FOREACH (services, svc, i) { - if (i > 0) - fprintf (stderr, ", "); - fprintf (stderr, "%s", svc); + first = true; + TAILQ_FOREACH(svc, services, entries) { + if (first) + first = false; + else + fprintf(stderr, ", "); + fprintf(stderr, "%s", svc->value); } - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); } - rc_strlist_free (services); + rc_stringlist_free(services); services = NULL; - rc_strlist_free (need_services); - need_services = rc_deptree_depends (deptree, types_n, - (const char * const *) applet_list, - softlevel, depoptions); - - rc_strlist_free (use_services); - use_services = rc_deptree_depends (deptree, types_nu, - (const char * const *) applet_list, - softlevel, depoptions); - - if (! rc_runlevel_starting ()) { - STRLIST_FOREACH (use_services, svc, i) - if (rc_service_state (svc) & RC_SERVICE_STOPPED) { - pid_t pid = rc_service_start (svc); - if (! rc_conf_yesno ("rc_parallel")) - rc_waitpid (pid); + need_services = rc_deptree_depends(deptree, types_n, applet_list, + runlevel, depoptions); + use_services = rc_deptree_depends(deptree, types_nu, applet_list, + runlevel, depoptions); + + if (! rc_runlevel_starting()) + TAILQ_FOREACH(svc, use_services, entries) + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) { + pid_t pid = rc_service_start(svc->value); + if (! rc_conf_yesno("rc_parallel")) + rc_waitpid(pid); } - } /* Now wait for them to start */ - services = rc_deptree_depends (deptree, types_nua, - (const char * const *) applet_list, - softlevel, depoptions); + services = rc_deptree_depends(deptree, types_nua, applet_list, + runlevel, depoptions); /* We use tmplist to hold our scheduled by list */ - rc_strlist_free (tmplist); - tmplist = NULL; + tmplist = rc_stringlist_new(); - STRLIST_FOREACH (services, svc, i) { - rc_service_state_t svcs = rc_service_state (svc); + TAILQ_FOREACH(svc, services, entries) { + RC_SERVICE svcs = rc_service_state(svc->value); if (svcs & RC_SERVICE_STARTED) continue; @@ -738,270 +757,272 @@ static void svc_start (bool deps) * starting state which we are after */ if (svcs & RC_SERVICE_STARTING && svcs & RC_SERVICE_WASINACTIVE) { - bool use = false; - STRLIST_FOREACH (use_services, svc2, j) - if (strcmp (svc, svc2) == 0) { - use = true; + TAILQ_FOREACH(svc2, use_services, entries) { + if (strcmp (svc->value, svc2->value) == 0) break; } - if (! use) + if (! svc2) continue; } - if (! svc_wait (deptree, svc)) - eerror ("%s: timed out waiting for %s", applet, svc); - if ((svcs = rc_service_state (svc)) & RC_SERVICE_STARTED) + if (! svc_wait(svc->value)) + eerror ("%s: timed out waiting for %s", + applet, svc->value); + if ((svcs = rc_service_state(svc->value)) & RC_SERVICE_STARTED) continue; - - STRLIST_FOREACH (need_services, svc2, j) - if (strcmp (svc, svc2) == 0) { + TAILQ_FOREACH(svc2, need_services, entries) { + if (strcmp (svc->value, svc2->value) == 0) { if (svcs & RC_SERVICE_INACTIVE || svcs & RC_SERVICE_WASINACTIVE) - rc_strlist_add (&tmplist, svc); + rc_stringlist_add(tmplist, svc->value); else - eerrorx ("ERROR: cannot start %s as %s would not start", - applet, svc); + eerrorx("ERROR: cannot start %s as" + " %s would not start", + applet, svc->value); } + } } - if (tmplist) { - int n = 0; - size_t len = 0; - char *p; - + if (TAILQ_FIRST(tmplist)) { /* Set the state now, then unlink our exclusive so that our scheduled list is preserved */ - rc_service_mark (service, RC_SERVICE_STOPPED); - unlink_mtime_test (); - - STRLIST_FOREACH (tmplist, svc, i) { - rc_service_schedule_start (svc, service); - rc_strlist_free (providelist); - providelist = rc_deptree_depend (deptree, "iprovide", svc); - STRLIST_FOREACH (providelist, svc2, j) - rc_service_schedule_start (svc2, service); - - len += strlen (svc) + 2; + rc_service_mark(service, RC_SERVICE_STOPPED); + unlink_mtime_test(); + + rc_stringlist_free(use_services); + use_services = NULL; + len = 0; + n = 0; + TAILQ_FOREACH(svc, tmplist, entries) { + rc_service_schedule_start(svc->value, service); + use_services = rc_deptree_depend(deptree, "iprovide", + svc->value); + TAILQ_FOREACH (svc2, use_services, entries) + rc_service_schedule_start(svc2->value, service); + rc_stringlist_free(use_services); + use_services = NULL; + len += strlen(svc->value) + 2; n++; } len += 5; - tmp = xmalloc (sizeof (char) * len); - p = tmp; - STRLIST_FOREACH (tmplist, svc, i) { - if (i > 1) { - if (i == n) - p += snprintf (p, len, " or "); - else - p += snprintf (p, len, ", "); - } - p += snprintf (p, len, "%s", svc); + tmp = p = xmalloc(sizeof(char) * len); + TAILQ_FOREACH(svc, tmplist, entries) { + if (p != tmp) + p += snprintf(p, len, ", "); + p += snprintf(p, len, "%s", svc->value); } - ewarnx ("WARNING: %s is scheduled to start when %s has started", - applet, tmp); + free(tmp); + ewarnx("WARNING: %s is scheduled to start when %s has started", + applet, tmp); } - rc_strlist_free (services); + rc_stringlist_free(services); services = NULL; + rc_stringlist_free(tmplist); + tmplist = NULL; } if (ibsave) - setenv ("IN_BACKGROUND", ibsave, 1); + setenv("IN_BACKGROUND", ibsave, 1); hook_out = RC_HOOK_SERVICE_START_DONE; - rc_plugin_run (RC_HOOK_SERVICE_START_NOW, applet); - started = svc_exec ("start", NULL); + rc_plugin_run(RC_HOOK_SERVICE_START_NOW, applet); + started = svc_exec("start", NULL); if (ibsave) - unsetenv ("IN_BACKGROUND"); + unsetenv("IN_BACKGROUND"); - if (in_control ()) { + if (in_control()) { if (! started) - eerrorx ("ERROR: %s failed to start", applet); + eerrorx("ERROR: %s failed to start", applet); } else { - if (rc_service_state (service) & RC_SERVICE_INACTIVE) - ewarnx ("WARNING: %s has started, but is inactive", applet); + if (rc_service_state(service) & RC_SERVICE_INACTIVE) + ewarnx("WARNING: %s has started, but is inactive", applet); else - ewarnx ("WARNING: %s not under our control, aborting", applet); + ewarnx("WARNING: %s not under our control, aborting", applet); } - rc_service_mark (service, RC_SERVICE_STARTED); - unlink_mtime_test (); + rc_service_mark(service, RC_SERVICE_STARTED); + unlink_mtime_test(); hook_out = RC_HOOK_SERVICE_START_OUT; - rc_plugin_run (RC_HOOK_SERVICE_START_DONE, applet); + rc_plugin_run(RC_HOOK_SERVICE_START_DONE, applet); if (exclusive) - unlink (exclusive); + unlink(exclusive); /* Now start any scheduled services */ - rc_strlist_free (services); - services = rc_services_scheduled (service); - STRLIST_FOREACH (services, svc, i) - if (rc_service_state (svc) & RC_SERVICE_STOPPED) - rc_service_start (svc); - rc_strlist_free (services); - services = NULL; + services = rc_services_scheduled(service); + if (services) { + TAILQ_FOREACH(svc, services, entries) + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) + rc_service_start(svc->value); + rc_stringlist_free(services); + services = NULL; + } /* Do the same for any services we provide */ - rc_strlist_free (tmplist); - tmplist = rc_deptree_depend (deptree, "iprovide", applet); - - STRLIST_FOREACH (tmplist, svc2, j) { - rc_strlist_free (services); - services = rc_services_scheduled (svc2); - STRLIST_FOREACH (services, svc, i) - if (rc_service_state (svc) & RC_SERVICE_STOPPED) - rc_service_start (svc); + tmplist = rc_deptree_depend(deptree, "iprovide", applet); + if (tmplist) { + TAILQ_FOREACH(svc, tmplist, entries) { + services = rc_services_scheduled(svc->value); + if (services) { + TAILQ_FOREACH(svc2, services, entries) + if (rc_service_state(svc2->value) & RC_SERVICE_STOPPED) + rc_service_start(svc2->value); + rc_stringlist_free(services); + services = NULL; + } + } + rc_stringlist_free(tmplist); + tmplist = NULL; } hook_out = 0; - rc_plugin_run (RC_HOOK_SERVICE_START_OUT, applet); + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); } -static void svc_stop (bool deps) +static void svc_stop(bool deps) { bool stopped; - rc_service_state_t state = rc_service_state (service); + RC_SERVICE state = rc_service_state(service); + int depoptions = RC_DEP_TRACE; + RC_STRING *svc; - if (rc_runlevel_stopping () && + if (rc_runlevel_stopping() && state & RC_SERVICE_FAILED) exit (EXIT_FAILURE); - if (rc_yesno (getenv ("IN_HOTPLUG")) || in_background) + if (rc_yesno(getenv("IN_HOTPLUG")) || in_background) if (! (state & RC_SERVICE_STARTED) && ! (state & RC_SERVICE_INACTIVE)) exit (EXIT_FAILURE); if (state & RC_SERVICE_STOPPED) { - ewarn ("WARNING: %s is already stopped", applet); + ewarn("WARNING: %s is already stopped", applet); return; } else if (state & RC_SERVICE_STOPPING) - ewarnx ("WARNING: %s is already stopping", applet); + ewarnx("WARNING: %s is already stopping", applet); - if (! rc_service_mark (service, RC_SERVICE_STOPPING)) { + if (! rc_service_mark(service, RC_SERVICE_STOPPING)) { if (errno == EACCES) - eerrorx ("%s: superuser access required", applet); - eerrorx ("ERROR: %s has been stopped by something else", applet); + eerrorx("%s: superuser access required", applet); + eerrorx("ERROR: %s has been stopped by something else", applet); } - make_exclusive (service); + make_exclusive(); hook_out = RC_HOOK_SERVICE_STOP_OUT; - rc_plugin_run (RC_HOOK_SERVICE_STOP_IN, applet); + rc_plugin_run(RC_HOOK_SERVICE_STOP_IN, applet); - if (! rc_runlevel_stopping () && - rc_service_in_runlevel (service, RC_LEVEL_BOOT)) + if (! rc_runlevel_stopping() && + rc_service_in_runlevel(service, RC_LEVEL_BOOT)) ewarn ("WARNING: you are stopping a boot service"); if (deps && ! (state & RC_SERVICE_WASINACTIVE)) { - int depoptions = RC_DEP_TRACE; - char *svc; - int i; - if (rc_conf_yesno ("rc_depend_strict")) + if (rc_conf_yesno("rc_depend_strict")) depoptions |= RC_DEP_STRICT; - if (! deptree && ((deptree = _rc_deptree_load (NULL)) == NULL)) + if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL)) eerrorx ("failed to load deptree"); - rc_strlist_free (tmplist); - tmplist = NULL; - rc_strlist_free (services); - services = rc_deptree_depends (deptree, types_m, - (const char * const *) applet_list, - softlevel, depoptions); - rc_strlist_reverse (services); - STRLIST_FOREACH (services, svc, i) { - rc_service_state_t svcs = rc_service_state (svc); + if (! types_m) + setup_types(); + + tmplist = rc_stringlist_new(); + services = rc_deptree_depends(deptree, types_m, applet_list, + runlevel, depoptions); + TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) { + RC_SERVICE svcs = rc_service_state(svc->value); if (svcs & RC_SERVICE_STARTED || svcs & RC_SERVICE_INACTIVE) { - svc_wait (deptree, svc); - svcs = rc_service_state (svc); + svc_wait(svc->value); + svcs = rc_service_state(svc->value); if (svcs & RC_SERVICE_STARTED || svcs & RC_SERVICE_INACTIVE) { - pid_t pid = rc_service_stop (svc); - if (! rc_conf_yesno ("rc_parallel")) - rc_waitpid (pid); - rc_strlist_add (&tmplist, svc); + pid_t pid = rc_service_stop(svc->value); + if (! rc_conf_yesno("rc_parallel")) + rc_waitpid(pid); + rc_stringlist_add(tmplist, svc->value); } } } - rc_strlist_free (services); + rc_stringlist_free(services); services = NULL; - STRLIST_FOREACH (tmplist, svc, i) { - if (rc_service_state (svc) & RC_SERVICE_STOPPED) + TAILQ_FOREACH(svc, tmplist, entries) { + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) continue; /* We used to loop 3 times here - maybe re-do this if needed */ - svc_wait (deptree, svc); - if (! (rc_service_state (svc) & RC_SERVICE_STOPPED)) { - if (rc_runlevel_stopping ()) { - /* If shutting down, we should stop even if a dependant failed */ - if (softlevel && - (strcmp (softlevel, RC_LEVEL_SHUTDOWN) == 0 || - strcmp (softlevel, RC_LEVEL_REBOOT) == 0 || - strcmp (softlevel, RC_LEVEL_SINGLE) == 0)) + svc_wait(svc->value); + if (! (rc_service_state(svc->value) & RC_SERVICE_STOPPED)) { + if (rc_runlevel_stopping()) { + /* If shutting down, we should stop even + * if a dependant failed */ + if (runlevel && + (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 || + strcmp(runlevel, RC_LEVEL_REBOOT) == 0 || + strcmp(runlevel, RC_LEVEL_SINGLE) == 0)) continue; - rc_service_mark (service, RC_SERVICE_FAILED); + rc_service_mark(service, RC_SERVICE_FAILED); } - eerrorx ("ERROR: cannot stop %s as %s is still up", - applet, svc); + eerrorx("ERROR: cannot stop %s as %s is still up", + applet, svc->value); } } - rc_strlist_free (tmplist); + rc_stringlist_free(tmplist); tmplist = NULL; /* We now wait for other services that may use us and are stopping This is important when a runlevel stops */ - services = rc_deptree_depends (deptree, types_mua, - (const char * const *) applet_list, - softlevel, depoptions); - STRLIST_FOREACH (services, svc, i) { - if (rc_service_state (svc) & RC_SERVICE_STOPPED) + services = rc_deptree_depends(deptree, types_mua, applet_list, + runlevel, depoptions); + TAILQ_FOREACH(svc, services, entries) { + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) continue; - svc_wait (deptree, svc); + svc_wait(svc->value); } - - rc_strlist_free (services); + rc_stringlist_free (services); services = NULL; } /* If we're stopping localmount, set LC_ALL=C so that * bash doesn't load anything blocking the unmounting of /usr */ - if (strcmp (applet, "localmount") == 0) - setenv ("LC_ALL", "C", 1); + if (strcmp(applet, "localmount") == 0) + setenv("LC_ALL", "C", 1); if (ibsave) - setenv ("IN_BACKGROUND", ibsave, 1); + setenv("IN_BACKGROUND", ibsave, 1); hook_out = RC_HOOK_SERVICE_STOP_DONE; - rc_plugin_run (RC_HOOK_SERVICE_STOP_NOW, applet); - stopped = svc_exec ("stop", NULL); + rc_plugin_run(RC_HOOK_SERVICE_STOP_NOW, applet); + stopped = svc_exec("stop", NULL); if (ibsave) - unsetenv ("IN_BACKGROUND"); + unsetenv("IN_BACKGROUND"); - if (! in_control ()) - ewarnx ("WARNING: %s not under our control, aborting", applet); + if (! in_control()) + ewarnx("WARNING: %s not under our control, aborting", applet); if (! stopped) - eerrorx ("ERROR: %s failed to stop", applet); + eerrorx("ERROR: %s failed to stop", applet); if (in_background) - rc_service_mark (service, RC_SERVICE_INACTIVE); + rc_service_mark(service, RC_SERVICE_INACTIVE); else - rc_service_mark (service, RC_SERVICE_STOPPED); + rc_service_mark(service, RC_SERVICE_STOPPED); - unlink_mtime_test (); + unlink_mtime_test(); hook_out = RC_HOOK_SERVICE_STOP_OUT; - rc_plugin_run (RC_HOOK_SERVICE_STOP_DONE, applet); + rc_plugin_run(RC_HOOK_SERVICE_STOP_DONE, applet); if (exclusive) - unlink (exclusive); + unlink(exclusive); hook_out = 0; - rc_plugin_run (RC_HOOK_SERVICE_STOP_OUT, applet); + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); } -static void svc_restart (bool deps) +static void svc_restart(bool deps) { /* This is hairly and a better way needs to be found I think! The issue is this - openvpn need net and dns. net can restart @@ -1012,22 +1033,22 @@ static void svc_restart (bool deps) our status is invalid. One workaround would be to introduce a new status, or status locking. */ if (! deps) { - rc_service_state_t state = rc_service_state (service); + RC_SERVICE state = rc_service_state(service); if (state & RC_SERVICE_STARTED || state & RC_SERVICE_INACTIVE) - svc_exec ("stop", "start"); + svc_exec("stop", "start"); else - svc_exec ("start", NULL); + svc_exec("start", NULL); return; } - if (! (rc_service_state (service) & RC_SERVICE_STOPPED)) { - get_started_services (); - svc_stop (deps); + if (! (rc_service_state(service) & RC_SERVICE_STOPPED)) { + get_started_services(); + svc_stop(deps); } - svc_start (deps); - start_services (restart_services); - rc_strlist_free (restart_services); + svc_start(deps); + start_services(restart_services); + rc_stringlist_free(restart_services); restart_services = NULL; } @@ -1048,128 +1069,94 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int runscript (int argc, char **argv) +int runscript(int argc, char **argv) { - size_t i; bool deps = true; bool doneone = false; char pid[16]; int retval; int opt; - char *svc; + RC_STRING *svc; + char dir[PATH_MAX]; + size_t l = 0; + size_t ll; + char *save; + int depoptions = RC_DEP_TRACE; /* Show help if insufficient args */ - if (argc < 2 || ! exists (argv[1])) { - fprintf (stderr, "runscript is not meant to be to run directly\n"); - exit (EXIT_FAILURE); + if (argc < 2 || ! exists(argv[1])) { + fprintf(stderr, "runscript is not meant to be to run directly\n"); + exit(EXIT_FAILURE); } - applet = basename_c (argv[1]); + applet = basename_c(argv[1]); if (argc < 3) - usage (EXIT_FAILURE); + usage(EXIT_FAILURE); if (*argv[1] == '/') - service = xstrdup (argv[1]); + service = xstrdup(argv[1]); else { - char d[PATH_MAX]; - getcwd (d, sizeof (d)); - i = strlen (d) + strlen (argv[1]) + 2; - service = xmalloc (sizeof (char) * i); - snprintf (service, i, "%s/%s", d, argv[1]); + getcwd(dir, sizeof(dir)); + l = strlen(dir) + strlen(argv[1]) + 2; + service = xmalloc(sizeof (char) * l); + snprintf(service, l, "%s/%s", dir, argv[1]); } - atexit (cleanup); + atexit(cleanup); /* Change dir to / to ensure all init scripts don't use stuff in pwd */ - chdir ("/"); + chdir("/"); #ifdef __linux__ /* coldplug events can trigger init scripts, but we don't want to run them until after rc sysinit has completed so we punt them to the boot runlevel */ - if (exists ("/dev/.rcsysinit")) { - eerror ("%s: cannot run until sysvinit completes", applet); - if (mkdir ("/dev/.rcboot", 0755) != 0 && errno != EEXIST) - eerrorx ("%s: mkdir `/dev/.rcboot': %s", applet, strerror (errno)); - tmp = rc_strcatpaths ("/dev/.rcboot", applet, (char *) NULL); - symlink (service, tmp); + if (exists("/dev/.rcsysinit")) { + eerror("%s: cannot run until sysvinit completes", applet); + if (mkdir("/dev/.rcboot", 0755) != 0 && errno != EEXIST) + eerrorx("%s: mkdir `/dev/.rcboot': %s", applet, strerror(errno)); + prefix = rc_strcatpaths("/dev/.rcboot", applet, (char *) NULL); + symlink(service, prefix); exit (EXIT_FAILURE); } #endif - if ((softlevel = xstrdup (getenv ("RC_SOFTLEVEL"))) == NULL) { - /* Ensure our environment is pure - Also, add our configuration to it */ - char *p; - env = env_filter (); - - if (env) { - -#ifdef __linux__ - /* clearenv isn't portable, but there's no harm in using it - if we have it */ - clearenv (); -#else - char *var; - /* No clearenv present here then. - We could manipulate environ directly ourselves, but it seems that - some kernels bitch about this according to the environ man pages - so we walk though environ and call unsetenv for each value. */ - while (environ[0]) { - tmp = xstrdup (environ[0]); - p = tmp; - var = strsep (&p, "="); - unsetenv (var); - free (tmp); - } - tmp = NULL; -#endif - } - - tmplist = env_config (); - rc_strlist_join (&env, tmplist); - rc_strlist_free (tmplist); - tmplist = NULL; - STRLIST_FOREACH (env, p, i) - putenv (p); - /* We don't free our list as that would be null in environ */ - - softlevel = rc_runlevel_get (); + if ((runlevel = xstrdup (getenv ("RC_RUNLEVEL"))) == NULL) { + env_filter(); + env_config(); + runlevel = rc_runlevel_get(); } - setenv ("EINFO_LOG", service, 1); - setenv ("SVCNAME", applet, 1); + setenv("EINFO_LOG", service, 1); + setenv("SVCNAME", applet, 1); /* Set an env var so that we always know our pid regardless of any subshells the init script may create so that our mark_service_* functions can always instruct us of this change */ - snprintf (pid, sizeof (pid), "%d", (int) getpid ()); - setenv ("RC_RUNSCRIPT_PID", pid, 1); + snprintf(pid, sizeof(pid), "%d", (int) getpid()); + setenv("RC_RUNSCRIPT_PID", pid, 1); /* eprefix is kinda klunky, but it works for our purposes */ - if (rc_conf_yesno ("rc_parallel")) { - size_t l = 0; - size_t ll; - + if (rc_conf_yesno("rc_parallel")) { /* Get the longest service name */ - services = rc_services_in_runlevel (NULL); - STRLIST_FOREACH (services, svc, i) { - ll = strlen (svc); + services = rc_services_in_runlevel(NULL); + TAILQ_FOREACH(svc, services, entries) { + ll = strlen(svc->value); if (ll > l) l = ll; } /* Make our prefix string */ - prefix = xmalloc (sizeof (char) * l + 1); - ll = strlen (applet); - memcpy (prefix, applet, ll); - memset (prefix + ll, ' ', l - ll); - memset (prefix + l, 0, 1); - eprefix (prefix); + prefix = xmalloc(sizeof(char) * l + 1); + ll = strlen(applet); + memcpy(prefix, applet, ll); + memset(prefix + ll, ' ', l - ll); + memset(prefix + l, 0, 1); + eprefix(prefix); } #ifdef __linux__ /* Ok, we are ready to go, so setup selinux if applicable */ - setup_selinux (argc, argv); + setup_selinux(argc, argv); #endif /* Punt the first arg as it's our service name */ @@ -1177,44 +1164,46 @@ int runscript (int argc, char **argv) argv++; /* Right then, parse any options there may be */ - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, longopts, (int *) 0)) != -1) switch (opt) { - case 'd': - setenv ("RC_DEBUG", "yes", 1); - break; - case 's': - if (! (rc_service_state (service) & RC_SERVICE_STARTED)) - exit (EXIT_FAILURE); - break; - case 'D': - deps = false; - break; - case_RC_COMMON_GETOPT - } + case 'd': + setenv("RC_DEBUG", "yes", 1); + break; + case 's': + if (! (rc_service_state(service) & RC_SERVICE_STARTED)) + exit(EXIT_FAILURE); + break; + case 'D': + deps = false; + break; + case_RC_COMMON_GETOPT + } /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service that is being called and not any dependents */ - if (getenv ("IN_BACKGROUND")) { - ibsave = xstrdup (getenv ("IN_BACKGROUND")); - in_background = rc_yesno (ibsave); - unsetenv ("IN_BACKGROUND"); + if (getenv("IN_BACKGROUND")) { + ibsave = xstrdup(getenv("IN_BACKGROUND")); + in_background = rc_yesno(ibsave); + unsetenv("IN_BACKGROUND"); } - if (rc_yesno (getenv ("IN_HOTPLUG"))) { - if (! rc_conf_yesno ("rc_hotplug") || ! service_plugable (applet)) - eerrorx ("%s: not allowed to be hotplugged", applet); + if (rc_yesno(getenv("IN_HOTPLUG"))) { + if (! rc_conf_yesno("rc_hotplug") || ! service_plugable(applet)) + eerrorx("%s: not allowed to be hotplugged", applet); } /* Setup a signal handler */ - signal_setup (SIGHUP, handle_signal); - signal_setup (SIGINT, handle_signal); - signal_setup (SIGQUIT, handle_signal); - signal_setup (SIGTERM, handle_signal); - signal_setup (SIGCHLD, handle_signal); + signal_setup(SIGHUP, handle_signal); + signal_setup(SIGINT, handle_signal); + signal_setup(SIGQUIT, handle_signal); + signal_setup(SIGTERM, handle_signal); + signal_setup(SIGCHLD, handle_signal); /* Load our plugins */ - rc_plugin_load (); + rc_plugin_load(); + + applet_list = rc_stringlist_new(); + rc_stringlist_add(applet_list, applet); /* Now run each option */ retval = EXIT_SUCCESS; @@ -1229,99 +1218,95 @@ int runscript (int argc, char **argv) This is important as we stamp on the restart function now but some start/stop routines still need to behave differently if restarting. */ - unsetenv ("RC_CMD"); - setenv ("RC_CMD", optarg, 1); + unsetenv("RC_CMD"); + setenv("RC_CMD", optarg, 1); doneone = true; - rc_strlist_add (&applet_list, applet); if (strcmp (optarg, "describe") == 0 || strcmp (optarg, "help") == 0) { - char *save = prefix; - - eprefix (NULL); + save = prefix; + eprefix(NULL); prefix = NULL; - svc_exec (optarg, NULL); - eprefix (save); - } else if (strcmp (optarg, "ineed") == 0 || - strcmp (optarg, "iuse") == 0 || - strcmp (optarg, "needsme") == 0 || - strcmp (optarg, "usesme") == 0 || - strcmp (optarg, "iafter") == 0 || - strcmp (optarg, "ibefore") == 0 || - strcmp (optarg, "iprovide") == 0) + svc_exec(optarg, NULL); + eprefix(save); + } else if (strcmp(optarg, "ineed") == 0 || + strcmp(optarg, "iuse") == 0 || + strcmp(optarg, "needsme") == 0 || + strcmp(optarg, "usesme") == 0 || + strcmp(optarg, "iafter") == 0 || + strcmp(optarg, "ibefore") == 0 || + strcmp(optarg, "iprovide") == 0) { - int depoptions = RC_DEP_TRACE; - - if (rc_conf_yesno ("rc_depend_strict")) + if (rc_conf_yesno("rc_depend_strict")) depoptions |= RC_DEP_STRICT; - if (! deptree && ((deptree = _rc_deptree_load (NULL)) == NULL)) - eerrorx ("failed to load deptree"); - - rc_strlist_free (services); - rc_strlist_free (tmplist); - rc_strlist_add (&tmplist, optarg); - services = rc_deptree_depends (deptree, - (const char * const *) tmplist, - (const char * const *) applet_list, - softlevel, depoptions); - STRLIST_FOREACH (services, svc, i) - printf ("%s%s", i == 1 ? "" : " ", svc); - if (services) + if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL)) + eerrorx("failed to load deptree"); + + tmplist = rc_stringlist_new(); + rc_stringlist_add(tmplist, optarg); + services = rc_deptree_depends(deptree, tmplist, applet_list, + runlevel, depoptions); + rc_stringlist_free(tmplist); + tmplist = NULL; + TAILQ_FOREACH(svc, services, entries) + printf("%s ", svc->value); + if (TAILQ_FIRST(services)) printf ("\n"); + rc_stringlist_free(services); + services = NULL; } else if (strcmp (optarg, "status") == 0) { - rc_service_state_t r = svc_status (service); + RC_SERVICE r = svc_status(); retval = (int) r; if (retval & RC_SERVICE_STARTED) retval = 0; } else { - if (strcmp (optarg, "conditionalrestart") == 0 || - strcmp (optarg, "condrestart") == 0) + if (strcmp(optarg, "conditionalrestart") == 0 || + strcmp(optarg, "condrestart") == 0) { - if (rc_service_state (service) & RC_SERVICE_STARTED) - svc_restart (deps); - } else if (strcmp (optarg, "restart") == 0) { + if (rc_service_state(service) & RC_SERVICE_STARTED) + svc_restart(deps); + } else if (strcmp(optarg, "restart") == 0) { svc_restart (deps); - } else if (strcmp (optarg, "start") == 0) { - svc_start (deps); - } else if (strcmp (optarg, "stop") == 0) { + } else if (strcmp(optarg, "start") == 0) { + svc_start(deps); + } else if (strcmp(optarg, "stop") == 0) { if (deps && in_background) - get_started_services (); + get_started_services(); - svc_stop (deps); + svc_stop(deps); if (deps) { if (! in_background && - ! rc_runlevel_stopping () && - rc_service_state (service) & RC_SERVICE_STOPPED) - uncoldplug (); + ! rc_runlevel_stopping() && + rc_service_state(service) & RC_SERVICE_STOPPED) + uncoldplug(); if (in_background && - rc_service_state (service) & RC_SERVICE_INACTIVE) + rc_service_state(service) & RC_SERVICE_INACTIVE) { - int j; - STRLIST_FOREACH (restart_services, svc, j) - if (rc_service_state (svc) & RC_SERVICE_STOPPED) - rc_service_schedule_start (service, svc); + TAILQ_FOREACH(svc, restart_services, entries) + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) + rc_service_schedule_start(service, svc->value); } } - } else if (strcmp (optarg, "zap") == 0) { - einfo ("Manually resetting %s to stopped state", applet); - rc_service_mark (applet, RC_SERVICE_STOPPED); - uncoldplug (); + } else if (strcmp(optarg, "zap") == 0) { + einfo("Manually resetting %s to stopped state", applet); + rc_service_mark(applet, RC_SERVICE_STOPPED); + uncoldplug(); } else - svc_exec (optarg, NULL); + svc_exec(optarg, NULL); /* We should ensure this list is empty after an action is done */ - rc_strlist_free (restart_services); + rc_stringlist_free(restart_services); restart_services = NULL; } if (! doneone) - usage (EXIT_FAILURE); + usage(EXIT_FAILURE); } - return (retval); + return retval; } diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c index 9ffeba05..bfb737a5 100644 --- a/src/rc/start-stop-daemon.c +++ b/src/rc/start-stop-daemon.c @@ -46,6 +46,7 @@ #include <sys/termios.h> #include <sys/time.h> #include <sys/wait.h> + #include <ctype.h> #include <errno.h> #include <fcntl.h> @@ -71,63 +72,57 @@ static struct pam_conv conv = { NULL, NULL}; #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" -typedef struct schedulelist +typedef struct scheduleitem { enum { - schedule_timeout, - schedule_signal, - schedule_goto, - schedule_forever + SC_TIMEOUT, + SC_SIGNAL, + SC_GOTO, + SC_FOREVER } type; int value; - struct schedulelist *gotolist; - struct schedulelist *next; -} schedulelist_t; -static schedulelist_t *schedule; + struct scheduleitem *gotoitem; + STAILQ_ENTRY(scheduleitem) entries; +} SCHEDULEITEM; +STAILQ_HEAD(, scheduleitem) schedule; extern const char *applet; static char *changeuser; -static char **newenv; extern char **environ; -static void free_schedulelist (schedulelist_t **list) +static void free_schedulelist(void) { - schedulelist_t *here; - schedulelist_t *next; + SCHEDULEITEM *s1 = STAILQ_FIRST(&schedule); + SCHEDULEITEM *s2; - for (here = *list; here; here = next) { - next = here->next; - free (here); + while (s1) { + s2 = STAILQ_NEXT(s1, entries); + free(s1); + s1 = s2; } - - *list = NULL; + STAILQ_INIT(&schedule); } -static void cleanup (void) +static void cleanup(void) { if (changeuser) - free (changeuser); - - if (schedule) - free_schedulelist (&schedule); + free(changeuser); - if (newenv) - rc_strlist_free (newenv); + free_schedulelist(); } -static int parse_signal (const char *sig) +static int parse_signal(const char *sig) { typedef struct signalpair { const char *name; int signal; - } signalpair_t; + } SIGNALPAIR; - static const signalpair_t signallist[] = { + static const SIGNALPAIR signallist[] = { { "ABRT", SIGABRT }, { "ALRM", SIGALRM }, { "FPE", SIGFPE }, @@ -153,161 +148,158 @@ static int parse_signal (const char *sig) const char *s; if (! sig || *sig == '\0') - return (-1); + return -1; - if (sscanf (sig, "%u", &i) == 1) { - if (i > 0 && i < sizeof (signallist) / sizeof (signallist[0])) - return (i); - eerrorx ("%s: `%s' is not a valid signal", applet, sig); + if (sscanf(sig, "%u", &i) == 1) { + if (i > 0 && i < sizeof(signallist) / sizeof(signallist[0])) + return i; + eerrorx("%s: `%s' is not a valid signal", applet, sig); } - if (strncmp (sig, "SIG", 3) == 0) + if (strncmp(sig, "SIG", 3) == 0) s = sig + 3; else s = NULL; - for (i = 0; i < sizeof (signallist) / sizeof (signallist[0]); i++) - if (strcmp (sig, signallist[i].name) == 0 || - (s && strcmp (s, signallist[i].name) == 0)) - return (signallist[i].signal); + for (i = 0; i < sizeof(signallist) / sizeof(signallist[0]); i++) + if (strcmp(sig, signallist[i].name) == 0 || + (s && strcmp(s, signallist[i].name) == 0)) + return signallist[i].signal; - eerrorx ("%s: `%s' is not a valid signal", applet, sig); + eerrorx("%s: `%s' is not a valid signal", applet, sig); /* NOTREACHED */ } -static void parse_schedule_item (schedulelist_t *item, const char *string) +static SCHEDULEITEM *parse_schedule_item(const char *string) { const char *after_hyph; int sig; - - if (strcmp (string,"forever") == 0) - item->type = schedule_forever; - else if (isdigit ((int) string[0])) { - item->type = schedule_timeout; + SCHEDULEITEM *item = xmalloc(sizeof(*item)); + + item->value = 0; + item->gotoitem = NULL; + if (strcmp(string,"forever") == 0) + item->type = SC_FOREVER; + else if (isdigit((int) string[0])) { + item->type = SC_TIMEOUT; errno = 0; - if (sscanf (string, "%d", &item->value) != 1) - eerrorx ("%s: invalid timeout value in schedule `%s'", applet, - string); + if (sscanf(string, "%d", &item->value) != 1) + eerrorx("%s: invalid timeout value in schedule `%s'", applet, + string); } else if ((after_hyph = string + (string[0] == '-')) && - ((sig = parse_signal (after_hyph)) != -1)) + ((sig = parse_signal(after_hyph)) != -1)) { - item->type = schedule_signal; - item->value = (int) sig; + item->type = SC_SIGNAL; + item->value = (int)sig; } else - eerrorx ("%s: invalid schedule item `%s'", applet, string); + eerrorx("%s: invalid schedule item `%s'", applet, string); + + return item; } -static void parse_schedule (const char *string, int default_signal) +static void parse_schedule(const char *string, int timeout) { char buffer[20]; const char *slash; int count = 0; - schedulelist_t *repeatat = NULL; + SCHEDULEITEM *repeatat = NULL; size_t len; - schedulelist_t *next; + SCHEDULEITEM *item; if (string) for (slash = string; *slash; slash++) if (*slash == '/') count++; - if (schedule) - free_schedulelist (&schedule); - - schedule = xmalloc (sizeof (*schedule)); - schedule->gotolist = NULL; + free_schedulelist(); if (count == 0) { - schedule->type = schedule_signal; - schedule->value = default_signal; - schedule->next = xmalloc (sizeof (*schedule->next)); - next = schedule->next; - next->type = schedule_timeout; - next->gotolist = NULL; + item = xmalloc(sizeof(*item)); + item->type = SC_SIGNAL; + item->value = timeout; + item->gotoitem = NULL; + STAILQ_INSERT_TAIL(&schedule, item, entries); + + item = xmalloc(sizeof(*item)); + item->type = SC_TIMEOUT; + item->gotoitem = NULL; + STAILQ_INSERT_TAIL(&schedule, item, entries); if (string) { - if (sscanf (string, "%d", &next->value) != 1) - eerrorx ("%s: invalid timeout value in schedule", applet); - } - else - next->value = 5; - next->next = NULL; + if (sscanf(string, "%d", &item->value) != 1) + eerrorx("%s: invalid timeout value in schedule", applet); + } else + item->value = 5; return; } - next = schedule; while (string != NULL) { - if ((slash = strchr (string, '/'))) + if ((slash = strchr(string, '/'))) len = slash - string; else - len = strlen (string); + len = strlen(string); - if (len >= (ptrdiff_t) sizeof (buffer)) - eerrorx ("%s: invalid schedule item, far too long", applet); + if (len >= (ptrdiff_t) sizeof(buffer)) + eerrorx("%s: invalid schedule item, far too long", applet); - memcpy (buffer, string, len); + memcpy(buffer, string, len); buffer[len] = 0; string = slash ? slash + 1 : NULL; - parse_schedule_item (next, buffer); - if (next->type == schedule_forever) { + item = parse_schedule_item(buffer); + STAILQ_INSERT_TAIL(&schedule, item, entries); + if (item->type == SC_FOREVER) { if (repeatat) - eerrorx ("%s: invalid schedule, `forever' appears more than once", - applet); + eerrorx("%s: invalid schedule, `forever' " + "appears more than once", applet); - repeatat = next; + repeatat = item; continue; } - - if (string) { - next->next = xmalloc (sizeof (*next->next)); - next = next->next; - next->gotolist = NULL; - } } if (repeatat) { - next->next = xmalloc (sizeof (*next->next)); - next = next->next; - next->type = schedule_goto; - next->value = 0; - next->gotolist = repeatat; + item = xmalloc(sizeof(*item)); + item->type = SC_GOTO; + item->value = 0; + item->gotoitem = repeatat; + STAILQ_INSERT_TAIL(&schedule, item, entries); } - next->next = NULL; return; } -static pid_t get_pid (const char *pidfile, bool quiet) +static pid_t get_pid(const char *pidfile, bool quiet) { FILE *fp; pid_t pid; if (! pidfile) - return (-1); + return -1; - if ((fp = fopen (pidfile, "r")) == NULL) { + if ((fp = fopen(pidfile, "r")) == NULL) { if (! quiet) - eerror ("%s: fopen `%s': %s", applet, pidfile, strerror (errno)); - return (-1); + eerror("%s: fopen `%s': %s", applet, pidfile, strerror(errno)); + return -1; } - if (fscanf (fp, "%d", &pid) != 1) { + if (fscanf(fp, "%d", &pid) != 1) { if (! quiet) - eerror ("%s: no pid found in `%s'", applet, pidfile); - fclose (fp); - return (-1); + eerror("%s: no pid found in `%s'", applet, pidfile); + fclose(fp); + return -1; } - fclose (fp); + + fclose(fp); - return (pid); + return pid; } /* return number of processed killed, -1 on error */ -static int do_stop (const char *const *argv, const char *cmd, - const char *pidfile, uid_t uid,int sig, - bool quiet, bool verbose, bool test) +static int do_stop(const char *const *argv, const char *cmd, + const char *pidfile, uid_t uid,int sig, + bool quiet, bool verbose, bool test) { pid_t *pids; bool killed; @@ -316,30 +308,30 @@ static int do_stop (const char *const *argv, const char *cmd, int i; if (pidfile) { - if ((pid = get_pid (pidfile, quiet)) == -1) - return (quiet ? 0 : -1); - pids = rc_find_pids (NULL, NULL, 0, pid); + if ((pid = get_pid(pidfile, quiet)) == -1) + return quiet ? 0 : -1; + pids = rc_find_pids(NULL, NULL, 0, pid); } else - pids = rc_find_pids (argv, cmd, uid, pid); + pids = rc_find_pids(argv, cmd, uid, pid); if (! pids) - return (0); + return 0; for (i = 0; pids[i]; i++) { if (test) { if (! quiet) - einfo ("Would send signal %d to PID %d", sig, pids[i]); + einfo("Would send signal %d to PID %d", sig, pids[i]); nkilled++; continue; } if (verbose) - ebegin ("Sending signal %d to PID %d", sig, pids[i]); + ebegin("Sending signal %d to PID %d", sig, pids[i]); errno = 0; - killed = (kill (pids[i], sig) == 0 || errno == ESRCH ? true : false); + killed = (kill(pids[i], sig) == 0 || errno == ESRCH ? true : false); if (verbose) - eend (killed ? 0 : 1, "%s: failed to send signal %d to PID %d: %s", - applet, sig, pids[i], strerror (errno)); + eend(killed ? 0 : 1, "%s: failed to send signal %d to PID %d: %s", + applet, sig, pids[i], strerror(errno)); if (! killed) { nkilled = -1; } else { @@ -348,15 +340,15 @@ static int do_stop (const char *const *argv, const char *cmd, } } - free (pids); - return (nkilled); + free(pids); + return nkilled; } -static int run_stop_schedule (const char *const *argv, const char *cmd, - const char *pidfile, uid_t uid, - bool quiet, bool verbose, bool test) +static int run_stop_schedule(const char *const *argv, const char *cmd, + const char *pidfile, uid_t uid, + bool quiet, bool verbose, bool test) { - schedulelist_t *item = schedule; + SCHEDULEITEM *item = STAILQ_FIRST(&schedule); int nkilled = 0; int tkilled = 0; int nrunning = 0; @@ -365,119 +357,121 @@ static int run_stop_schedule (const char *const *argv, const char *cmd, if (verbose) { if (pidfile) - einfo ("Will stop PID in pidfile `%s'", pidfile); + einfo("Will stop PID in pidfile `%s'", pidfile); if (uid) - einfo ("Will stop processes owned by UID %d", uid); + einfo("Will stop processes owned by UID %d", uid); if (argv && *argv) - einfo ("Will stop processes of `%s'", *argv); + einfo("Will stop processes of `%s'", *argv); if (cmd) - einfo ("Will stop processes called `%s'", cmd); + einfo("Will stop processes called `%s'", cmd); } while (item) { - switch (item->type) { - case schedule_goto: - item = item->gotolist; - continue; + switch (item->type) { + case SC_GOTO: + item = item->gotoitem; + continue; - case schedule_signal: - nrunning = 0; - nkilled = do_stop (argv, cmd, pidfile, uid, item->value, - quiet, verbose, test); - if (nkilled == 0) { - if (tkilled == 0) { - if (! quiet) - eerror ("%s: no matching processes found", applet); - } - return (tkilled); + case SC_SIGNAL: + nrunning = 0; + nkilled = do_stop(argv, cmd, pidfile, uid, item->value, + quiet, verbose, test); + if (nkilled == 0) { + if (tkilled == 0) { + if (! quiet) + eerror("%s: no matching " + "processes found", applet); } - else if (nkilled == -1) - return (0); + return tkilled; + } + else if (nkilled == -1) + return 0; - tkilled += nkilled; + tkilled += nkilled; + break; + case SC_TIMEOUT: + if (item->value < 1) { + item = NULL; break; - case schedule_timeout: - if (item->value < 1) { - item = NULL; - break; - } + } - nloops = (ONE_SECOND / POLL_INTERVAL) * item->value; - ts.tv_sec = 0; - ts.tv_nsec = POLL_INTERVAL; - - while (nloops) { - if ((nrunning = do_stop (argv, cmd, pidfile, - uid, 0, true, false, true)) == 0) - return (true); - - if (nanosleep (&ts, NULL) == -1) { - if (errno == EINTR) - eerror ("%s: caught an interrupt", applet); - else { - eerror ("%s: nanosleep: %s", applet, strerror (errno)); - return (0); - } + nloops = (ONE_SECOND / POLL_INTERVAL) * item->value; + ts.tv_sec = 0; + ts.tv_nsec = POLL_INTERVAL; + + while (nloops) { + if ((nrunning = do_stop(argv, cmd, pidfile, + uid, 0, true, false, true)) == 0) + return true; + + if (nanosleep(&ts, NULL) == -1) { + if (errno == EINTR) + eerror("%s: caught an interrupt", applet); + else { + eerror("%s: nanosleep: %s", + applet, strerror(errno)); + return 0; } - nloops --; } - break; + nloops --; + } + break; - default: - eerror ("%s: invalid schedule item `%d'", applet, item->type); - return (0); + default: + eerror("%s: invalid schedule item `%d'", applet, item->type); + return 0; } if (item) - item = item->next; + item = STAILQ_NEXT(item, entries); } if (test || (tkilled > 0 && nrunning == 0)) - return (nkilled); + return nkilled; if (! quiet) { if (nrunning == 1) - eerror ("%s: %d process refused to stop", applet, nrunning); + eerror("%s: %d process refused to stop", applet, nrunning); else - eerror ("%s: %d process(es) refused to stop", applet, nrunning); + eerror("%s: %d process(es) refused to stop", applet, nrunning); } - return (-nrunning); + return -nrunning; } -static void handle_signal (int sig) +static void handle_signal(int sig) { int status; int serrno = errno; char signame[10] = { '\0' }; switch (sig) { - case SIGINT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGINT"); - /* FALLTHROUGH */ - case SIGTERM: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGTERM"); - /* FALLTHROUGH */ - case SIGQUIT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGQUIT"); - eerrorx ("%s: caught %s, aborting", applet, signame); - /* NOTREACHED */ - - case SIGCHLD: - for (;;) { - if (waitpid (-1, &status, WNOHANG) < 0) { - if (errno != ECHILD) - eerror ("%s: waitpid: %s", applet, strerror (errno)); - break; - } + case SIGINT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGINT"); + /* FALLTHROUGH */ + case SIGTERM: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGTERM"); + /* FALLTHROUGH */ + case SIGQUIT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGQUIT"); + eerrorx("%s: caught %s, aborting", applet, signame); + /* NOTREACHED */ + + case SIGCHLD: + for (;;) { + if (waitpid(-1, &status, WNOHANG) < 0) { + if (errno != ECHILD) + eerror("%s: waitpid: %s", applet, strerror(errno)); + break; } - break; + } + break; - default: - eerror ("%s: caught unknown signal %d", applet, sig); + default: + eerror("%s: caught unknown signal %d", applet, sig); } /* Restore errno */ @@ -537,7 +531,7 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int start_stop_daemon (int argc, char **argv) +int start_stop_daemon(int argc, char **argv) { int devnull_fd = -1; #ifdef TIOCNOTTY @@ -574,154 +568,160 @@ int start_stop_daemon (int argc, char **argv) int stderr_fd; pid_t pid; int i; - char *svcname = getenv ("SVCNAME"); - char *env; + char *svcname = getenv("SVCNAME"); + RC_STRINGLIST *env_list; + RC_STRING *env; + char *path; bool sethome = false; bool setuser = false; + char *p; + char *tmp; + struct passwd *pw; + struct group *gr; + char line[130]; + FILE *fp; + size_t len; - atexit (cleanup); + STAILQ_INIT(&schedule); + atexit(cleanup); - signal_setup (SIGINT, handle_signal); - signal_setup (SIGQUIT, handle_signal); - signal_setup (SIGTERM, handle_signal); + signal_setup(SIGINT, handle_signal); + signal_setup(SIGQUIT, handle_signal); + signal_setup(SIGTERM, handle_signal); - if ((env = getenv ("SSD_NICELEVEL"))) - if (sscanf (env, "%d", &nicelevel) != 1) - eerror ("%s: invalid nice level `%s' (SSD_NICELEVEL)", applet, env); + if ((path = getenv("SSD_NICELEVEL"))) + if (sscanf(path, "%d", &nicelevel) != 1) + eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)", + applet, path); - while ((opt = getopt_long (argc, argv, "e:" getoptstring, longopts, - (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, "e:" getoptstring, longopts, + (int *) 0)) != -1) switch (opt) { - case 'K': /* --stop */ - stop = true; - break; - - case 'N': /* --nice */ - if (sscanf (optarg, "%d", &nicelevel) != 1) - eerrorx ("%s: invalid nice level `%s'", applet, optarg); - break; + case 'K': /* --stop */ + stop = true; + break; - case 'R': /* --retry <schedule>|<timeout> */ - parse_schedule (optarg, sig); - break; + case 'N': /* --nice */ + if (sscanf(optarg, "%d", &nicelevel) != 1) + eerrorx("%s: invalid nice level `%s'", applet, optarg); + break; - case 'S': /* --start */ - start = true; - break; + case 'R': /* --retry <schedule>|<timeout> */ + parse_schedule(optarg, sig); + break; - case 'b': /* --background */ - background = true; - break; + case 'S': /* --start */ + start = true; + break; - case 'u': /* --user <username>|<uid> */ - case 'c': /* --chuid <username>|<uid> */ - { - char *p = optarg; - char *cu = strsep (&p, ":"); - struct passwd *pw = NULL; + case 'b': /* --background */ + background = true; + break; - changeuser = xstrdup (cu); - if (sscanf (cu, "%d", &tid) != 1) - pw = getpwnam (cu); + case 'u': /* --user <username>|<uid> */ + case 'c': /* --chuid <username>|<uid> */ + { + p = optarg; + tmp = strsep(&p, ":"); + changeuser = xstrdup(tmp); + if (sscanf(tmp, "%d", &tid) != 1) + pw = getpwnam(tmp); + else + pw = getpwuid((uid_t) tid); + + if (! pw) + eerrorx("%s: user `%s' not found", applet, tmp); + uid = pw->pw_uid; + if (! gid) + gid = pw->pw_gid; + + if (p) { + tmp = strsep (&p, ":"); + if (sscanf(tmp, "%d", &tid) != 1) + gr = getgrnam(tmp); else - pw = getpwuid ((uid_t) tid); - - if (! pw) - eerrorx ("%s: user `%s' not found", applet, cu); - uid = pw->pw_uid; - if (! gid) - gid = pw->pw_gid; - - if (p) { - struct group *gr = NULL; - char *cg = strsep (&p, ":"); - - if (sscanf (cg, "%d", &tid) != 1) - gr = getgrnam (cg); - else - gr = getgrgid ((gid_t) tid); - - if (! gr) - eerrorx ("%s: group `%s' not found", applet, cg); - gid = gr->gr_gid; - } - } - break; + gr = getgrgid((gid_t) tid); - case 'd': /* --chdir /new/dir */ - ch_dir = optarg; - break; - - case 'e': /* --env */ - if (putenv (optarg) == 0) { - if (strncmp ("HOME=", optarg, 5) == 0) - sethome = true; - else if (strncmp ("USER=", optarg, 5) == 0) - setuser = true; + if (! gr) + eerrorx("%s: group `%s' not found", + applet, tmp); + gid = gr->gr_gid; } - break; + } + break; - case 'g': /* --group <group>|<gid> */ - { - struct group *gr = getgrnam (optarg); + case 'd': /* --chdir /new/dir */ + ch_dir = optarg; + break; - if (sscanf (optarg, "%d", &tid) != 1) - gr = getgrnam (optarg); - else - gr = getgrgid ((gid_t) tid); + case 'e': /* --env */ + if (putenv(optarg) == 0) { + if (strncmp("HOME=", optarg, 5) == 0) + sethome = true; + else if (strncmp("USER=", optarg, 5) == 0) + setuser = true; + } + break; - if (! gr) - eerrorx ("%s: group `%s' not found", applet, optarg); - gid = gr->gr_gid; - } - break; + case 'g': /* --group <group>|<gid> */ + { + if (sscanf(optarg, "%d", &tid) != 1) + gr = getgrnam(optarg); + else + gr = getgrgid((gid_t) tid); - case 'm': /* --make-pidfile */ - makepidfile = true; - break; + if (! gr) + eerrorx("%s: group `%s' not found", applet, optarg); + gid = gr->gr_gid; + } + break; - case 'n': /* --name <process-name> */ - cmd = optarg; - break; + case 'm': /* --make-pidfile */ + makepidfile = true; + break; - case 'o': /* --oknodo */ - oknodo = true; - break; + case 'n': /* --name <process-name> */ + cmd = optarg; + break; - case 'p': /* --pidfile <pid-file> */ - pidfile = optarg; - break; + case 'o': /* --oknodo */ + oknodo = true; + break; - case 's': /* --signal <signal> */ - sig = parse_signal (optarg); - break; + case 'p': /* --pidfile <pid-file> */ + pidfile = optarg; + break; - case 't': /* --test */ - test = true; - break; + case 's': /* --signal <signal> */ + sig = parse_signal(optarg); + break; - case 'r': /* --chroot /new/root */ - ch_root = optarg; - break; + case 't': /* --test */ + test = true; + break; - case 'a': - case 'x': /* --exec <executable> */ - exec = optarg; - break; + case 'r': /* --chroot /new/root */ + ch_root = optarg; + break; - case '1': /* --stdout /path/to/stdout.lgfile */ - redirect_stdout = optarg; - break; + case 'a': + case 'x': /* --exec <executable> */ + exec = optarg; + break; - case '2': /* --stderr /path/to/stderr.logfile */ - redirect_stderr = optarg; - break; + case '1': /* --stdout /path/to/stdout.lgfile */ + redirect_stdout = optarg; + break; + + case '2': /* --stderr /path/to/stderr.logfile */ + redirect_stderr = optarg; + break; - case_RC_COMMON_GETOPT + case_RC_COMMON_GETOPT } - quiet = rc_yesno (getenv ("EINFO_QUIET")); - verbose = rc_yesno (getenv ("EINFO_VERBOSE")); + quiet = rc_yesno(getenv("EINFO_QUIET")); + verbose = rc_yesno(getenv("EINFO_VERBOSE")); /* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq * instead of forcing --stop --oknodo as well */ @@ -736,22 +736,22 @@ int start_stop_daemon (int argc, char **argv) } if (start == stop) - eerrorx ("%s: need one of --start or --stop", applet); + eerrorx("%s: need one of --start or --stop", applet); if (start && ! exec) - eerrorx ("%s: --start needs --exec", applet); + eerrorx("%s: --start needs --exec", applet); if (stop && ! exec && ! pidfile && ! cmd && ! uid) - eerrorx ("%s: --stop needs --exec, --pidfile, --name or --user", applet); + eerrorx("%s: --stop needs --exec, --pidfile, --name or --user", applet); if (makepidfile && ! pidfile) - eerrorx ("%s: --make-pidfile is only relevant with --pidfile", applet); + eerrorx("%s: --make-pidfile is only relevant with --pidfile", applet); if (background && ! start) - eerrorx ("%s: --background is only relevant with --start", applet); + eerrorx("%s: --background is only relevant with --start", applet); if ((redirect_stdout || redirect_stderr) && ! background) - eerrorx ("%s: --stdout and --stderr are only relevant with --background", + eerrorx("%s: --stdout and --stderr are only relevant with --background", applet); argc -= optind; @@ -759,52 +759,49 @@ int start_stop_daemon (int argc, char **argv) /* Validate that the binary exists if we are starting */ if (exec) { - char *tmp; if (ch_root) - tmp = rc_strcatpaths (ch_root, exec, (char *) NULL); + tmp = rc_strcatpaths(ch_root, exec, (char *) NULL); else tmp = exec; - if (start && ! exists (tmp)) { - eerror ("%s: %s does not exist", applet, tmp); + if (start && ! exists(tmp)) { + eerror("%s: %s does not exist", applet, tmp); if (ch_root) - free (tmp); - exit (EXIT_FAILURE); + free(tmp); + exit(EXIT_FAILURE); } /* If we don't have a pidfile or name, check it's not * interpreted, otherwise we should fail */ if (! pidfile && ! cmd) { - char line[130]; - FILE *fp = fopen (tmp, "r"); - + fp = fopen (tmp, "r"); if (fp) { - fgets (line, sizeof (line), fp); - fclose (fp); + fgets(line, sizeof(line), fp); + fclose(fp); if (line[0] == '#' && line[1] == '!') { - size_t len = strlen (line) - 1; + len = strlen (line) - 1; /* Remove the trailing newline */ if (line[len] == '\n') line[len] = '\0'; - eerror ("%s: %s is a script", + eerror("%s: %s is a script", applet, exec); - eerror ("%s: and should be started, stopped or signalled with ", - applet); - eerror ("%s: --exec %s %s", + eerror("%s: and should be started, stopped" + " or signalled with ", applet); + eerror("%s: --exec %s %s", applet, line + 2, exec); - eerror ("%s: or you should specify a pidfile or process name", - applet); + eerror("%s: or you should specify a pidfile" + " or process name", applet); if (ch_root) - free (tmp); - exit (EXIT_FAILURE); + free(tmp); + exit(EXIT_FAILURE); } } } if (ch_root) - free (tmp); + free(tmp); } /* Add exec to our arguments */ @@ -813,83 +810,79 @@ int start_stop_daemon (int argc, char **argv) if (stop) { int result; - if (! schedule) { + if (! STAILQ_FIRST(&schedule)) { if (test || oknodo) - parse_schedule ("0", sig); + parse_schedule("0", sig); else - parse_schedule (NULL, sig); + parse_schedule(NULL, sig); } - result = run_stop_schedule ((const char *const *)argv, cmd, - pidfile, uid, quiet, verbose, test); + result = run_stop_schedule((const char *const *)argv, cmd, + pidfile, uid, quiet, verbose, test); if (result < 0) /* We failed to stop something */ - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); if (test || oknodo) - return (result > 0 ? EXIT_SUCCESS : EXIT_FAILURE); + return result > 0 ? EXIT_SUCCESS : EXIT_FAILURE; /* Even if we have not actually killed anything, we should * remove information about it as it may have unexpectedly * crashed out. We should also return success as the end * result would be the same. */ - if (pidfile && exists (pidfile)) - unlink (pidfile); + if (pidfile && exists(pidfile)) + unlink(pidfile); if (svcname) - rc_service_daemon_set (svcname, - (const char *const *)argv, - cmd, pidfile, false); + rc_service_daemon_set(svcname, + (const char *const *)argv, + cmd, pidfile, false); - exit (EXIT_SUCCESS); + exit(EXIT_SUCCESS); } - if (do_stop ((const char * const *)argv, cmd, pidfile, uid, - 0, true, false, true) > 0) - eerrorx ("%s: %s is already running", applet, exec); + if (do_stop((const char * const *)argv, cmd, pidfile, uid, + 0, true, false, true) > 0) + eerrorx("%s: %s is already running", applet, exec); if (test) { if (quiet) exit (EXIT_SUCCESS); - einfon ("Would start"); + einfon("Would start"); while (argc-- >= 0) printf(" %s", *argv++); - printf ("\n"); - eindent (); + printf("\n"); + eindent(); if (uid != 0) - einfo ("as user id %d", uid); + einfo("as user id %d", uid); if (gid != 0) - einfo ("as group id %d", gid); + einfo("as group id %d", gid); if (ch_root) - einfo ("in root `%s'", ch_root); + einfo("in root `%s'", ch_root); if (ch_dir) - einfo ("in dir `%s'", ch_dir); + einfo("in dir `%s'", ch_dir); if (nicelevel != 0) - einfo ("with a priority of %d", nicelevel); - eoutdent (); - exit (EXIT_SUCCESS); + einfo("with a priority of %d", nicelevel); + eoutdent(); + exit(EXIT_SUCCESS); } - /* Ensure this is unset, so if the daemon does /etc/init.d/foo - Then we filter the environment accordingly */ - unsetenv ("RC_SOFTLEVEL"); - if (verbose) { - ebegin ("Detaching to start `%s'", exec); - eindent (); + ebegin("Detaching to start `%s'", exec); + eindent(); } if (background) - signal_setup (SIGCHLD, handle_signal); + signal_setup(SIGCHLD, handle_signal); - if ((pid = fork ()) == -1) - eerrorx ("%s: fork: %s", applet, strerror (errno)); + if ((pid = fork()) == -1) + eerrorx("%s: fork: %s", applet, strerror(errno)); /* Child process - lets go! */ if (pid == 0) { - pid_t mypid = getpid (); + pid_t mypid = getpid(); #ifdef TIOCNOTTY tty_fd = open("/dev/tty", O_RDWR); @@ -898,66 +891,66 @@ int start_stop_daemon (int argc, char **argv) devnull_fd = open("/dev/null", O_RDWR); if (nicelevel) { - if (setpriority (PRIO_PROCESS, mypid, nicelevel) == -1) - eerrorx ("%s: setpritory %d: %s", applet, nicelevel, + if (setpriority(PRIO_PROCESS, mypid, nicelevel) == -1) + eerrorx("%s: setpritory %d: %s", applet, nicelevel, strerror(errno)); } - if (ch_root && chroot (ch_root) < 0) - eerrorx ("%s: chroot `%s': %s", applet, ch_root, strerror (errno)); + if (ch_root && chroot(ch_root) < 0) + eerrorx("%s: chroot `%s': %s", applet, ch_root, strerror(errno)); if (ch_dir && chdir (ch_dir) < 0) - eerrorx ("%s: chdir `%s': %s", applet, ch_dir, strerror (errno)); + eerrorx("%s: chdir `%s': %s", applet, ch_dir, strerror(errno)); if (makepidfile && pidfile) { - FILE *fp = fopen (pidfile, "w"); + fp = fopen(pidfile, "w"); if (! fp) - eerrorx ("%s: fopen `%s': %s", applet, pidfile, strerror - (errno)); - fprintf (fp, "%d\n", mypid); - fclose (fp); + eerrorx("%s: fopen `%s': %s", applet, pidfile, + strerror(errno)); + fprintf(fp, "%d\n", mypid); + fclose(fp); } #ifdef HAVE_PAM if (changeuser != NULL) - pamr = pam_start ("start-stop-daemon", changeuser, &conv, &pamh); + pamr = pam_start("start-stop-daemon", changeuser, &conv, &pamh); else - pamr = pam_start ("start-stop-daemon", "nobody", &conv, &pamh); + pamr = pam_start("start-stop-daemon", "nobody", &conv, &pamh); if (pamr == PAM_SUCCESS) - pamr = pam_authenticate (pamh, PAM_SILENT); + pamr = pam_authenticate(pamh, PAM_SILENT); if (pamr == PAM_SUCCESS) - pamr = pam_acct_mgmt (pamh, PAM_SILENT); + pamr = pam_acct_mgmt(pamh, PAM_SILENT); if (pamr == PAM_SUCCESS) - pamr = pam_open_session (pamh, PAM_SILENT); + pamr = pam_open_session(pamh, PAM_SILENT); if (pamr != PAM_SUCCESS) - eerrorx ("%s: pam error: %s", applet, pam_strerror(pamh, pamr)); + eerrorx("%s: pam error: %s", applet, pam_strerror(pamh, pamr)); #endif - if (gid && setgid (gid)) - eerrorx ("%s: unable to set groupid to %d", applet, gid); - if (changeuser && initgroups (changeuser, gid)) - eerrorx ("%s: initgroups (%s, %d)", applet, changeuser, gid); - if (uid && setuid (uid)) + if (gid && setgid(gid)) + eerrorx("%s: unable to set groupid to %d", applet, gid); + if (changeuser && initgroups(changeuser, gid)) + eerrorx("%s: initgroups (%s, %d)", applet, changeuser, gid); + if (uid && setuid(uid)) eerrorx ("%s: unable to set userid to %d", applet, uid); else { - struct passwd *passwd = getpwuid (uid); - if (passwd) { + pw = getpwuid(uid); + if (pw) { if (! sethome) { - unsetenv ("HOME"); - if (passwd->pw_dir) - setenv ("HOME", passwd->pw_dir, 1); + unsetenv("HOME"); + if (pw->pw_dir) + setenv("HOME", pw->pw_dir, 1); } if (! setuser) { - unsetenv ("USER"); - if (passwd->pw_name) - setenv ("USER", passwd->pw_name, 1); + unsetenv("USER"); + if (pw->pw_name) + setenv("USER", pw->pw_name, 1); } } } /* Close any fd's to the passwd database */ - endpwent (); + endpwent(); #ifdef TIOCNOTTY ioctl(tty_fd, TIOCNOTTY, 0); @@ -965,84 +958,81 @@ int start_stop_daemon (int argc, char **argv) #endif /* Clean the environment of any RC_ variables */ - STRLIST_FOREACH (environ, env, i) { - if ((strncmp (env, "RC_", 3) == 0 && - strncmp (env, "RC_SERVICE=", strlen ("RC_SERVICE=")) != 0) || - strncmp (env, "SSD_NICELEVEL=", strlen ("SSD_NICELEVEL=")) == 0) + env_list = rc_stringlist_new(); + i = 0; + while(environ[i]) + rc_stringlist_add(env_list, environ[i++]); + TAILQ_FOREACH(env, env_list, entries) { + if ((strncmp(env->value, "RC_", 3) == 0 && + strncmp(env->value, "RC_SERVICE=", strlen("RC_SERVICE=")) != 0) || + strncmp(env->value, "SSD_NICELEVEL=", strlen("SSD_NICELEVEL=")) == 0) + { + p = strchr(env->value, '='); + *p = '\0'; + unsetenv(env->value); continue; - - /* For the path, remove the rcscript bin dir from it */ - if (strncmp (env, "PATH=", 5) == 0) { - char *path = xstrdup (env); - char *newpath = NULL; - char *p = path; - char *token; - char *np; - size_t l; - int t; - - p += 5; - while ((token = strsep (&p, ":"))) { - if (strcmp (token, RC_LIBDIR "/bin") == 0 || - strcmp (token, RC_LIBDIR "/sbin") == 0) - continue; - - t = strlen (token); - if (newpath) { - l = strlen (newpath); - newpath = xrealloc (newpath, sizeof (char) * (l + t + 2)); - np = newpath + l; - *np++ = ':'; - memcpy (np, token, sizeof (char) * strlen (token)); - np += t; - *np = '\0'; - } else { - l = strlen ("PATH=") + t + 1; - newpath = xmalloc (sizeof (char) * l); - snprintf (newpath, l, "PATH=%s", token); - } - } - rc_strlist_add (&newenv, newpath); - free (path); - free (newpath); - } else - rc_strlist_add (&newenv, env); + } + } + rc_stringlist_free(env_list); + + /* For the path, remove the rcscript bin dir from it */ + if ((path = getenv("PATH"))) { + size_t mx = strlen(path); + char *newpath = xmalloc(mx); + char *token; + char *np = newpath; + size_t l; + + p = path; + while ((token = strsep (&p, ":"))) { + if (strcmp (token, RC_LIBDIR "/bin") == 0 || + strcmp (token, RC_LIBDIR "/sbin") == 0) + continue; + + l = strlen (token); + if (np != newpath) + *np++ = ':'; + memcpy (np, token, l); + np += l; + *np = '\0'; + } + unsetenv("PATH"); + setenv("PATH", newpath, 1); } - umask (022); + umask(022); stdout_fd = devnull_fd; stderr_fd = devnull_fd; if (redirect_stdout) { - if ((stdout_fd = open (redirect_stdout, O_WRONLY | O_CREAT | O_APPEND, - S_IRUSR | S_IWUSR)) == -1) - eerrorx ("%s: unable to open the logfile for stdout `%s': %s", - applet, redirect_stdout, strerror (errno)); + if ((stdout_fd = open(redirect_stdout, O_WRONLY | O_CREAT | O_APPEND, + S_IRUSR | S_IWUSR)) == -1) + eerrorx("%s: unable to open the logfile for stdout `%s': %s", + applet, redirect_stdout, strerror(errno)); } if (redirect_stderr) { - if ((stderr_fd = open (redirect_stderr, O_WRONLY | O_CREAT | O_APPEND, - S_IRUSR | S_IWUSR)) == -1) - eerrorx ("%s: unable to open the logfile for stderr `%s': %s", - applet, redirect_stderr, strerror (errno)); + if ((stderr_fd = open(redirect_stderr, O_WRONLY | O_CREAT | O_APPEND, + S_IRUSR | S_IWUSR)) == -1) + eerrorx("%s: unable to open the logfile for stderr `%s': %s", + applet, redirect_stderr, strerror(errno)); } /* We don't redirect stdin as some daemons may need it */ if (background || quiet || redirect_stdout) - dup2 (stdout_fd, STDOUT_FILENO); + dup2(stdout_fd, STDOUT_FILENO); if (background || quiet || redirect_stderr) - dup2 (stderr_fd, STDERR_FILENO); + dup2(stderr_fd, STDERR_FILENO); - for (i = getdtablesize () - 1; i >= 3; --i) + for (i = getdtablesize() - 1; i >= 3; --i) close(i); - setsid (); - - execve (exec, argv, newenv); + setsid(); + execv(exec, argv); #ifdef HAVE_PAM if (pamr == PAM_SUCCESS) - pam_close_session (pamh, PAM_SILENT); + pam_close_session(pamh, PAM_SILENT); #endif - eerrorx ("%s: failed to exec `%s': %s", applet, exec, strerror (errno)); + eerrorx("%s: failed to exec `%s': %s", applet, exec, strerror(errno)); } /* Parent process */ @@ -1053,17 +1043,17 @@ int start_stop_daemon (int argc, char **argv) errno = 0; do { - pid = waitpid (savepid, &status, 0); + pid = waitpid(savepid, &status, 0); if (pid < 1) { - eerror ("waitpid %d: %s", savepid, strerror (errno)); - return (-1); + eerror("waitpid %d: %s", savepid, strerror(errno)); + return -1; } - } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); + } while (! WIFEXITED(status) && ! WIFSIGNALED(status)); - if (! WIFEXITED (status) || WEXITSTATUS (status) != 0) { + if (! WIFEXITED(status) || WEXITSTATUS(status) != 0) { if (! quiet) - eerrorx ("%s: failed to start `%s'", applet, exec); - exit (EXIT_FAILURE); + eerrorx("%s: failed to start `%s'", applet, exec); + exit(EXIT_FAILURE); } pid = savepid; @@ -1081,12 +1071,12 @@ int start_stop_daemon (int argc, char **argv) ts.tv_nsec = POLL_INTERVAL; while (nloops) { - if (nanosleep (&ts, NULL) == -1) { + if (nanosleep(&ts, NULL) == -1) { if (errno == EINTR) - eerror ("%s: caught an interrupt", applet); + eerror("%s: caught an interrupt", applet); else { - eerror ("%s: nanosleep: %s", applet, strerror (errno)); - return (0); + eerror("%s: nanosleep: %s", applet, strerror(errno)); + return 0; } } @@ -1111,27 +1101,28 @@ int start_stop_daemon (int argc, char **argv) } else { if (pidfile) { /* The pidfile may not have been written yet - give it some time */ - if (get_pid (pidfile, true) == -1) { + if (get_pid(pidfile, true) == -1) { if (! nloopsp) - eerrorx ("%s: did not create a valid pid in `%s'", - applet, pidfile); + eerrorx("%s: did not create a valid pid in `%s'", + applet, pidfile); alive = true; } else nloopsp = 0; } - if (do_stop ((const char *const *)argv, cmd, - pidfile, uid, 0, true, false, true) > 0) + if (do_stop((const char *const *)argv, cmd, + pidfile, uid, 0, true, false, true) > 0) alive = true; } if (! alive) - eerrorx ("%s: %s died", applet, exec); + eerrorx("%s: %s died", applet, exec); } } if (svcname) - rc_service_daemon_set (svcname, (const char *const *)argv, cmd, pidfile, true); + rc_service_daemon_set(svcname, (const char *const *)argv, + cmd, pidfile, true); - exit (EXIT_SUCCESS); + exit(EXIT_SUCCESS); /* NOTREACHED */ } |