/* * need: prerequisites program for mastodon-style init scripts * * Copyright (c) 2000 David Parsons. All rights reserved. * * This software is released under a berkeley-style copyright; the * details can be found in the file COPYRIGHT. */ #include #include #include #include #include #include #include "init.h" extern int getopt(); extern int optind; extern int opterr; extern char *optarg; volatile int refused; char *pgm; FILE *ipc; void not_talking(int sig) { fprintf(stderr, "init is not talking to us\n"); exit(1); } void sigusr(int sig) { refused = (sig != SIGUSR1); } void sendcommand(int cmd, char *arg) { int status; fprintf(ipc, arg ? "%d %c %s\n" : "%d %c\n", getpid(), cmd, arg); fflush(ipc); alarm(2); while (refused == -1) wait(&status); alarm(0); } /* sendcommand */ main(int argc, char ** argv) { int opt, delete=0, j, status; char pathname[200]; char *runlevel = get_runlevel(); pgm = basename(argv[0]); opterr = 1; while ( (opt = getopt(argc, argv, "c")) != EOF) { switch (opt) { case 'c': delete++; break; default: fprintf(stderr, "usage: %s -c\n" " %s token {token ...}\n", pgm, pgm); exit(1); } } if (runlevel == 0 && (runlevel = getenv("RUNLEVEL")) == 0) runlevel = "m"; signal(SIGALRM, not_talking); /* hello, init, are you out there? */ alarm(2); if ( (ipc = openfifo(COMMAND)) == 0) not_talking(0); alarm(0); if (delete) { signal(SIGUSR1, sigusr); signal(SIGUSR2, sigusr); sendcommand(UNREGISTER, 0); if (refused) fprintf(stderr, "Command refused"); exit(refused); } for (j = optind; j < argc; j++) { if (strlen(argv[j]) > 20) { fprintf(stderr, "%s: service names must be < 20 chars\n", pgm); exit(1); } if (strchr(argv[j], '/') != 0) { fprintf(stderr, "%s: service names may not contain ``/''\n", pgm); exit(1); } signal(SIGUSR1, sigusr); signal(SIGUSR2, sigusr); refused = -1; sendcommand(REGISTER, argv[j]); if (!refused) { pid_t pid; pid = fork(); if (pid < 0) { fprintf(stderr, "%s: cannot fork off %s (%s)\n", pgm, argv[j], strerror(errno)); continue; } else if (pid == 0) { snprintf(pathname, sizeof pathname, PREFIX "/etc/rc.d/rc.%c/%s", runlevel[0], argv[j]); execl(pathname, argv[j], "start", 0); snprintf(pathname, sizeof pathname, PREFIX "/etc/rc.d/init.d/%s", argv[j]); execl(pathname, argv[j], "start", 0); fprintf(stderr, "service %s not found\n", argv[j]); exit(1); } else { int rc; waitpid(pid, &status, 0); if ( (rc = WEXITSTATUS(status)) != 0) exit(rc); } } } exit(0); } /* need */