1 /* simpleinit.c - poe@daimi.aau.dk */
4 /* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
5 * - added Native Language Support
6 * 2001-01-25 Richard Gooch <rgooch@atnf.csiro.au>
7 * - fixed bug with failed services so they may be later "reclaimed"
8 * 2001-02-02 Richard Gooch <rgooch@atnf.csiro.au>
9 * - fixed race when reading from pipe and reaping children
10 * 2001-02-18 sam@quux.dropbear.id.au
11 * - fixed bug in <get_path>: multiple INIT_PATH components did not work
12 * 2001-02-21 Richard Gooch <rgooch@atnf.csiro.au>
13 * - block signals in handlers, so that longjmp() doesn't kill context
14 * 2001-02-25 Richard Gooch <rgooch@atnf.csiro.au>
15 * - make default INIT_PATH the boot_prog (if it is a directory) - YECCH
16 * 2002-11-20 patch from SuSE
17 * - refuse initctl_fd if setting FD_CLOEXEC fails
20 #include <sys/types.h>
34 #include <sys/sysmacros.h>
36 #include <sys/ioctl.h>
46 #include "pathnames.h"
47 #include "linux_reboot.h"
50 #include "simpleinit.h"
52 #define CMDSIZ 150 /* max size of a line in inittab */
53 #define NUMCMD 30 /* max number of lines in inittab */
54 #define NUMTOK 20 /* max number of tokens in inittab command */
55 #define PATH_SIZE (CMDSIZ+CMDSIZ+1)
57 #define MAX_RESPAWN_RATE 5 /* number of respawns per 100 seconds */
59 #define TZFILE "/etc/TZ"
61 /* #define DEBUGGING */
63 /* Define this if you want init to ignore the termcap field in inittab for
65 /* #define SPECIAL_CONSOLE_TERM */
75 struct timeval last_start;
79 struct initline inittab[NUMCMD];
81 int stopped = 0; /* are we stopped */
82 static char boot_prog[PATH_SIZE] = _PATH_RC;
83 static char script_prefix[PATH_SIZE] = "\0";
84 static char final_prog[PATH_SIZE] = "\0";
85 static char init_path[PATH_SIZE] = "\0";
86 static int caught_sigint = 0;
87 static int no_reboot = 0;
88 static pid_t rc_child = -1;
89 static const char *initctl_name = "/dev/initctl";
90 static int initctl_fd = -1;
91 static volatile int do_longjmp = 0;
92 static sigjmp_buf jmp_env;
95 static void do_single (void);
96 static int do_rc_tty (const char *path);
97 static int process_path (const char *path, int (*func) (const char *path),
98 int ignore_dangling_symlink);
99 static int preload_file (const char *path);
100 static int run_file (const char *path);
101 static void spawn (int i), read_inittab (void);
102 static void sighup_handler (int sig);
103 static void sigtstp_handler (int sig);
104 static void sigint_handler (int sig);
105 static void sigchild_handler (int sig);
106 static void sigquit_handler (int sig);
107 static void sigterm_handler (int sig);
109 static void set_tz (void);
111 static void write_wtmp (void);
112 static pid_t mywait (int *status);
113 static int run_command (const char *file, const char *name, pid_t pid);
116 static void err (char *s)
120 if((fd = open("/dev/console", O_WRONLY)) < 0) return;
122 write(fd, "init: ", 6);
123 write(fd, s, strlen(s));
127 static void enter_single (void)
132 err(_("Booting to single user mode.\n"));
133 if((pid = fork()) == 0) {
135 execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
136 err(_("exec of single user shell failed\n"));
138 while (waitpid (pid, &i, 0) != pid) /* Nothing */;
140 err(_("fork of single user shell failed\n"));
142 unlink(_PATH_SINGLE);
145 int main(int argc, char *argv[])
156 sigfillset (&sa.sa_mask); /* longjmp and nested signals don't mix */
157 sa.sa_flags = SA_ONESHOT;
158 sa.sa_handler = sigint_handler;
159 sigaction (SIGINT, &sa, NULL);
161 sa.sa_handler = sigtstp_handler;
162 sigaction (SIGTSTP, &sa, NULL);
163 sa.sa_handler = sigterm_handler;
164 sigaction (SIGTERM, &sa, NULL);
165 sa.sa_handler = sigchild_handler;
166 sigaction (SIGCHLD, &sa, NULL);
167 sa.sa_handler = sigquit_handler;
168 sigaction (SIGQUIT, &sa, NULL);
170 setlocale(LC_ALL, "");
171 bindtextdomain(PACKAGE, LOCALEDIR);
174 my_reboot (LINUX_REBOOT_CMD_CAD_OFF);
175 /* Find script to run. Command-line overrides config file overrides
177 for (i = 0; i < NUMCMD; i++) inittab[i].pid = -1;
179 for (i = 1; i < argc; i++) {
180 if (strcmp (argv[i], "single") == 0)
182 else if (strcmp (argv[i], "-noreboot") == 0)
184 else if (strlen(script_prefix) + strlen(argv[i]) < PATH_SIZE) {
185 char path[PATH_SIZE];
187 strcpy (path, script_prefix);
188 strcat (path, argv[i]);
189 if (access (path, R_OK | X_OK) == 0)
190 strcpy (boot_prog, path);
193 if (init_path[0] == '\0')
197 if ( (stat (boot_prog, &statbuf) == 0) && S_ISDIR (statbuf.st_mode) )
199 strcpy (init_path, boot_prog);
200 i = strlen (init_path);
201 if (init_path[i - 1] == '/') init_path[i - 1] = '\0';
205 if ( ( initctl_fd = open (initctl_name, O_RDWR, 0) ) < 0 ) {
206 mkfifo (initctl_name, S_IRUSR | S_IWUSR);
207 if ( ( initctl_fd = open (initctl_name, O_RDWR, 0) ) < 0 )
208 err ( _("error opening fifo\n") );
211 if (initctl_fd >= 0 && fcntl(initctl_fd, F_SETFD, FD_CLOEXEC) != 0) {
212 err ( _("error setting close-on-exec on /dev/initctl") );
214 /* Can the fcntl ever fail? If it does, and we leave
215 the descriptor open in child processes, then any
216 process on the system will be able to write to
217 /dev/initctl and have us execute arbitrary commands
218 as root. So let's refuse to use the fifo in this case. */
224 if ( want_single || (access (_PATH_SINGLE, R_OK) == 0) ) do_single ();
226 /*If we get a SIGTSTP before multi-user mode, do nothing*/
230 if ( do_rc_tty (boot_prog) ) do_single ();
232 while (stopped) /* Also if /etc/rc fails & we get SIGTSTP */
235 write_wtmp(); /* write boottime record */
237 for(i = 0; i < numcmd; i++) {
240 printf("toks= %s %s %s %s\n",p[0], p[1], p[2], p[3]);
241 printf("tty= %s\n", inittab[i].tty);
242 printf("termcap= %s\n", inittab[i].termcap);
246 signal (SIGHUP, sighup_handler); /* Better semantics with signal(2) */
248 for (i = 0; i < getdtablesize (); i++)
249 if (i != initctl_fd) close (i);
251 for(i = 0; i < numcmd; i++)
254 if (final_prog[0] != '\0') {
258 execl (final_prog, final_prog, "start", NULL);
259 err ( _("error running finalprog\n") );
263 err ( _("error forking finalprog\n") );
265 default: /* Parent */
272 if (pid < 1) continue;
274 /* clear utmp entry, and append to wtmp if possible */
279 utmpname(_PATH_UTMP);
281 while((ut = getutent())) {
282 if(ut->ut_pid == pid) {
284 memset(&ut->ut_user, 0, UT_NAMESIZE);
285 memset(&ut->ut_host, 0, sizeof(ut->ut_host));
286 ut->ut_type = DEAD_PROCESS;
292 if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) {
293 flock(lf, LOCK_EX|LOCK_NB);
294 if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
295 write(ut_fd, ut, sizeof(struct utmp));
298 flock(lf, LOCK_UN|LOCK_NB);
307 for(i = 0; i < numcmd; i++) {
308 if(pid == inittab[i].pid || inittab[i].pid < 0) {
313 if (pid == inittab[i].pid)
320 #define MAXTRIES 3 /* number of tries allowed when giving the password */
323 * return true if singleuser mode is allowed.
324 * If /etc/securesingle exists ask for root password, otherwise always OK.
326 static int check_single_ok (void)
328 char *pass, *rootpass = NULL;
332 if (access (_PATH_SECURE, R_OK) != 0) return 1;
333 if ( ( pwd = getpwnam ("root") ) || ( pwd = getpwuid (0) ) )
334 rootpass = pwd->pw_passwd;
336 return 1; /* a bad /etc/passwd should not lock out */
338 for (i = 0; i < MAXTRIES; i++)
340 pass = getpass (_("Password: "));
341 if (pass == NULL) continue;
343 if ( !strcmp (crypt (pass, rootpass), rootpass) ) return 1;
345 puts (_("\nWrong password.\n"));
350 static void do_single (void)
352 char path[PATH_SIZE];
354 if (caught_sigint) return;
355 strcpy (path, script_prefix);
356 strcat (path, "single");
357 if (access (path, R_OK | X_OK) == 0)
358 if (do_rc_tty (path) == 0) return;
359 if ( check_single_ok () ) enter_single ();
360 } /* End Function do_single */
363 * run boot script(s). The environment is passed to the script(s), so the RC
364 * environment variable can be used to decide what to do.
365 * RC may be set from LILO.
366 * [RETURNS] 0 on success (exit status convention), otherwise error.
368 static int do_rc_tty (const char *path)
374 if (caught_sigint) return 0;
375 process_path (path, preload_file, 0);
376 /* Launch off a subprocess to start a new session (required for frobbing
377 the TTY) and capture control-C */
378 switch ( rc_child = fork () )
381 for (status = 1; status < NSIG; status++) signal (status, SIG_DFL);
383 sigprocmask (SIG_UNBLOCK, &ss, NULL);
384 sigdelset (&ss, SIGINT);
385 sigdelset (&ss, SIGQUIT);
387 ioctl (0, TIOCSCTTY, 0); /* I want my control-C */
388 sigsuspend (&ss); /* Should never return, should just be killed */
389 break; /* No-one else is controlled by this TTY now */
393 default: /* Parent */
397 process_path (path, run_file, 0);
400 if ( ( pid = mywait (&status) ) == rc_child )
401 return (WTERMSIG (status) == SIGINT) ? 0 : 1;
404 kill (rc_child, SIGKILL);
405 while (waitpid (rc_child, NULL, 0) != rc_child) /* Nothing */;
407 } /* End Function do_rc_tty */
409 static int process_path (const char *path, int (*func) (const char *path),
410 int ignore_dangling_symlink)
416 if (lstat (path, &statbuf) != 0)
418 err (_("lstat of path failed\n") );
421 if ( S_ISLNK (statbuf.st_mode) )
423 if (stat (path, &statbuf) != 0)
425 if ( (errno == ENOENT) && ignore_dangling_symlink ) return 0;
426 err (_("stat of path failed\n") );
430 if ( !( statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH) ) ) return 0;
431 if ( !S_ISDIR (statbuf.st_mode) ) return (*func) (path);
432 if ( ( dp = opendir (path) ) == NULL )
434 err (_("open of directory failed\n") );
437 while ( ( de = readdir (dp) ) != NULL )
440 char newpath[PATH_SIZE];
442 if (de->d_name[0] == '.') continue;
443 retval = snprintf (newpath, sizeof(newpath), "%s/%s", path, de->d_name);
444 if (newpath[retval - 1] == '~') continue; /* Common mistake */
445 if ( ( retval = process_path (newpath, func, 1) ) ) return retval;
449 } /* End Function process_path */
451 static int preload_file (const char *path)
456 if ( ( fd = open (path, O_RDONLY, 0) ) < 0) return 0;
457 while (read (fd, &ch, 1) == 1) lseek (fd, 1024, SEEK_CUR);
460 } /* End Function preload_file */
462 static int run_file (const char *path)
466 if ( ( ptr = strrchr ( (char *) path, '/' ) ) == NULL ) ptr = path;
468 return (run_command (path, ptr, 0) == SIG_FAILED) ? 1 : 0;
469 } /* End Function run_file */
471 static void spawn (int i)
475 signed long ds_taken;
478 if (inittab[i].toks[0] == NULL) return;
480 /* Check if respawning too fast */
481 gettimeofday (&ct, NULL);
482 ds_taken = ct.tv_sec - inittab[i].last_start.tv_sec;
484 /* On the first iteration last_start==0 and ds_taken
485 may be very large. Avoid overflow. -- Denis Vlasenko */
486 if (ds_taken > 10000)
490 ds_taken += (ct.tv_usec - inittab[i].last_start.tv_usec) / 100000;
493 inittab[i].rate = (9 * inittab[i].rate + 1000 / ds_taken) / 10;
494 if (inittab[i].rate > MAX_RESPAWN_RATE) {
497 inittab[i].toks[0] = NULL;
500 snprintf (txt, sizeof(txt),
501 _("respawning: \"%s\" too fast: quenching entry\n"),
507 if((pid = fork()) < 0) {
509 err(_("fork failed\n"));
513 /* this is the parent */
514 inittab[i].pid = pid;
515 inittab[i].last_start = ct;
519 /* this is the child */
527 for(j = 0; j < getdtablesize(); j++)
530 snprintf(term, sizeof(term), "TERM=%s", inittab[i].termcap);
534 snprintf(tz, sizeof(tz), "TZ=%s", tzone);
539 execve(inittab[i].toks[0], inittab[i].toks, env);
540 err(_("exec failed\n"));
546 static void read_inittab (void)
553 char prog[PATH_SIZE];
554 #ifdef SPECIAL_CONSOLE_TERM
560 termenv = getenv("TERM"); /* set by kernel */
561 /* termenv = "vt100"; */
563 if(!(f = fopen(_PATH_INITTAB, "r"))) {
564 err(_("cannot open inittab\n"));
570 while(!feof(f) && i < NUMCMD - 2) {
571 if(fgets(buf, CMDSIZ - 1, f) == 0) break;
574 for(k = 0; k < CMDSIZ && buf[k]; k++) {
575 if ((buf[k] == '#') || (buf[k] == '\n')) {
580 if(buf[0] == 0 || buf[0] == '\n') continue;
581 ptr = strchr (buf, '=');
584 if ( !strncmp (buf, "bootprog", 8) ) {
585 while ( isspace (*ptr) ) ++ptr;
590 if ( !strncmp (buf, "fileprefix", 10) ) {
591 while ( isspace (*ptr) ) ++ptr;
592 strcpy (script_prefix, ptr);
595 if ( !strncmp (buf, "PATH", 4) ) {
596 while ( isspace (*ptr) ) ++ptr;
597 setenv ("PATH", ptr, 1);
600 if ( !strncmp (buf, "INIT_PATH", 9) ) {
601 while ( isspace (*ptr) ) ++ptr;
602 strcpy (init_path, ptr);
605 if ( !strncmp (buf, "finalprog", 8) ) {
606 while ( isspace (*ptr) ) ++ptr;
607 strcpy (final_prog, ptr);
613 (void) strcpy(inittab[i].line, buf);
615 (void) strtok(inittab[i].line, ":");
616 xstrncpy(inittab[i].tty, inittab[i].line, 10);
617 xstrncpy(inittab[i].termcap, strtok((char *)0, ":"), 30);
619 getty = strtok((char *)0, ":");
620 (void) strtok(getty, " \t\n");
621 inittab[i].toks[0] = getty;
623 while((ptr = strtok((char *)0, " \t\n")))
624 inittab[i].toks[j++] = ptr;
625 inittab[i].toks[j] = (char *)0;
627 #ifdef SPECIAL_CONSOLE_TERM
628 /* special-case termcap for the console ttys */
629 snprintf(tty, sizeof(tty), "/dev/%s", inittab[i].tty);
630 if(!termenv || stat(tty, &stb) < 0) {
631 err(_("no TERM or cannot stat tty\n"));
633 /* is it a console tty? */
634 if(major(stb.st_rdev) == 4 && minor(stb.st_rdev) < 64)
635 xstrncpy(inittab[i].termcap, termenv, 30);
645 char path[PATH_SIZE];
647 strcpy (path, script_prefix);
650 if (path[len - 1] == '/') path[len - 1] = '\0';
651 if (access (path, R_OK | X_OK) == 0)
652 strcpy (boot_prog, path);
654 } /* End Function read_inittab */
656 static void sighup_handler (int sig)
660 struct initline savetab[NUMCMD];
663 signal (SIGHUP, SIG_IGN);
664 memcpy(savetab, inittab, NUMCMD * sizeof(struct initline));
668 for(i = 0; i < numcmd; i++) {
670 for(j = 0; j < oldnum; j++) {
671 if(!strcmp(savetab[j].tty, inittab[i].tty)) {
673 if((inittab[i].pid = savetab[j].pid) < 0)
677 if (!had_already) spawn (i);
679 signal (SIGHUP, sighup_handler);
680 } /* End Function sighup_handler */
682 static void sigtstp_handler (int sig)
685 if (!stopped) sighup_handler (sig);
686 } /* End Function sigtstp_handler */
688 static void sigterm_handler (int sig)
692 for (i = 0; i < numcmd; i++)
693 if (inittab[i].pid > 0) kill (inittab[i].pid, SIGTERM);
694 } /* End Function sigterm_handler */
696 static void sigint_handler (int sig)
701 kill (rc_child, SIGKILL);
702 if (no_reboot) _exit (1) /*kill (0, SIGKILL)*/;
706 if (pid > 0) return; /* Parent */
707 if (pid == 0) /* Child: reboot properly... */
708 execl (_PATH_REBOOT, _PATH_REBOOT, (char *) 0);
710 /* fork or exec failed, try the hard way... */
711 my_reboot (LINUX_REBOOT_CMD_RESTART);
712 } /* End Function sigint_handler */
714 static void sigchild_handler (int sig)
716 if (!do_longjmp) return;
717 siglongjmp (jmp_env, 1);
720 static void sigquit_handler (int sig)
722 execl (_PATH_REBOOT, _PATH_REBOOT, NULL); /* It knows pid=1 must sleep */
726 static void set_tz (void)
731 if((f=fopen(TZFILE, "r")) == (FILE *)NULL) return;
732 fgets(tzone, CMDSIZ-2, f);
734 if((len=strlen(tzone)) < 2) return;
735 tzone[len-1] = 0; /* get rid of the '\n' */
736 setenv("TZ", tzone, 0);
740 static void write_wtmp (void)
745 memset((char *)&ut, 0, sizeof(ut));
746 strcpy(ut.ut_line, "~");
747 memset(ut.ut_name, 0, sizeof(ut.ut_name));
749 ut.ut_type = BOOT_TIME;
751 if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) {
752 flock(lf, LOCK_EX|LOCK_NB); /* make sure init won't hang */
753 if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) >= 0) {
754 write(fd, (char *)&ut, sizeof(ut));
757 flock(lf, LOCK_UN|LOCK_NB);
760 } /* End Function write_wtmp */
765 struct needer_struct *next;
769 struct service_struct
771 struct service_struct *prev, *next; /* Script services chain */
772 struct needer_struct *needers; /* Needers waiting for service */
773 struct script_struct *attempting_providers;
774 int failed; /* TRUE if attempting provider failed badly */
781 struct script_struct *prev, *next; /* For the list */
782 struct service_struct *first_service, *last_service; /*First is true name*/
783 struct script_struct *next_attempting_provider; /* Provider chain */
788 struct script_struct *first, *last;
789 unsigned int num_entries;
793 static struct list_head available_list = {NULL, NULL, 0};
794 static struct list_head starting_list = {NULL, NULL, 0};
795 static struct service_struct *unavailable_services = NULL; /* For needers */
796 static int num_needers = 0;
799 static int process_pidstat (pid_t pid, int status);
800 static void process_command (const struct command_struct *command);
801 static struct service_struct *find_service_in_list (const char *name,
802 struct service_struct *sv);
803 static struct script_struct *find_script_byname
804 (const char *name,struct list_head *head, struct service_struct **service);
805 static struct script_struct *find_script_bypid (pid_t pid,
806 struct list_head *head);
807 static void insert_entry (struct list_head *head, struct script_struct *entry);
808 static void remove_entry (struct list_head *head, struct script_struct *entry);
809 static void signal_needers (struct service_struct *service, int sig);
810 static void handle_nonworking (struct script_struct *script);
811 static int force_progress (void);
812 static void show_scripts (FILE *fp, const struct script_struct *script,
814 static const char *get_path (const char *file);
817 static pid_t mywait (int *status)
818 /* [RETURNS] The pid for a process to be reaped, 0 if no process is to be
819 reaped, and less than 0 if the boot scripts appear to have finished.
824 long buffer[COMMAND_SIZE / sizeof (long)];
825 struct command_struct *command = (struct command_struct *) buffer;
827 if (initctl_fd < 0) return wait (status);
828 /* Some magic to avoid races which can result in lost signals */
829 command->command = -1;
830 if ( sigsetjmp (jmp_env, 1) )
831 { /* Jump from signal handler */
833 process_command (command);
836 sigemptyset (&ss); /* Block SIGCHLD so wait status cannot be lost */
837 sigaddset (&ss, SIGCHLD);
838 sigprocmask (SIG_BLOCK, &ss, NULL);
839 if ( ( pid = waitpid (-1, status, WNOHANG) ) > 0 )
841 sigprocmask (SIG_UNBLOCK, &ss, NULL);
842 return process_pidstat (pid, *status);
844 do_longjmp = 1; /* After this, SIGCHLD will cause a jump backwards */
845 sigprocmask (SIG_UNBLOCK, &ss, NULL);
846 read (initctl_fd, buffer, sizeof(buffer));
848 process_command (command);
850 } /* End Function mywait */
852 static pid_t process_pidstat (pid_t pid, int status)
853 /* [RETURNS] The pid for a process to be reaped, 0 if no process is to be
854 reaped, and less than 0 if the boot scripts appear to have finished.
858 struct script_struct *script;
859 struct service_struct *service;
861 if ( ( script = find_script_bypid (pid, &starting_list) ) == NULL )
863 remove_entry (&starting_list, script);
864 if ( WIFEXITED (status) && (WEXITSTATUS (status) == 0) )
866 struct script_struct *provider;
868 /* Notify needers and other providers */
869 for (service = script->first_service; service != NULL;
870 service = service->next)
872 signal_needers (service, SIG_PRESENT);
873 for (provider = service->attempting_providers; provider != NULL;
874 provider = provider->next_attempting_provider)
875 kill (provider->pid, SIG_PRESENT);
876 service->attempting_providers = NULL;
878 insert_entry (&available_list, script);
879 return force_progress ();
881 failed = ( WIFEXITED (status) && (WEXITSTATUS (status) == 2) ) ? 0 : 1;
882 for (service = script->first_service; service != NULL;
883 service = service->next)
884 service->failed = failed;
885 handle_nonworking (script);
886 return force_progress ();
887 } /* End Function process_pidstat */
889 static void process_command (const struct command_struct *command)
892 struct script_struct *script;
893 struct service_struct *service;
895 switch (command->command)
899 (find_script_byname (command->name, &available_list,
901 SIG_NOT_PRESENT : SIG_PRESENT);
904 ival = run_command (command->name, command->name, command->pid);
910 else kill (command->pid, ival);
912 case COMMAND_ROLLBACK:
913 if (command->name[0] == '\0') script = NULL;
916 if ( ( script = find_script_byname (command->name, &available_list,
919 kill (command->pid, SIG_NOT_PRESENT);
923 while (script != available_list.first)
926 struct script_struct *victim = available_list.first;
929 if ( ( pid = fork () ) == 0 ) /* Child */
931 for (ival = 1; ival < NSIG; ival++) signal (ival, SIG_DFL);
932 open ("/dev/console", O_RDONLY, 0);
933 open ("/dev/console", O_RDWR, 0);
935 execlp (get_path (victim->first_service->name),
936 victim->first_service->name, "stop", NULL);
937 snprintf (txt, sizeof(txt),
938 _("error stopping service: \"%s\"\n"),
939 victim->first_service->name);
941 _exit (SIG_NOT_STOPPED);
943 else if (pid == -1) break; /* Error */
946 while (waitpid (pid, &ival, 0) != pid) /* Nothing */;
947 if ( WIFEXITED (ival) && (WEXITSTATUS (ival) == 0) )
949 snprintf (txt, sizeof(txt),
950 _("Stopped service: %s\n"),
951 victim->first_service->name);
952 remove_entry (&available_list, victim);
960 (script ==available_list.first) ? SIG_STOPPED : SIG_NOT_STOPPED);
962 case COMMAND_DUMP_LIST:
963 if (fork () == 0) /* Do it in a child process so pid=1 doesn't block */
967 if ( ( fp = fopen (command->name, "w") ) == NULL ) _exit (1);
968 show_scripts (fp, available_list.first, "AVAILABLE");
969 show_scripts (fp, starting_list.first, "STARTING");
970 fputs ("UNAVAILABLE SERVICES:\n", fp);
971 for (service = unavailable_services; service != NULL;
972 service = service->next)
973 fprintf (fp, "%s (%s)\n", service->name,
974 service->failed ? "FAILED" : "not configured");
979 case COMMAND_PROVIDE:
981 if ( ( script = find_script_bypid (command->ppid, &starting_list) )
984 kill (command->pid, SIG_NOT_CHILD);
987 if (find_script_byname (command->name, &available_list, NULL) != NULL)
989 kill (command->pid, SIG_PRESENT);
992 if (find_script_byname (command->name, &starting_list, &service)
994 { /* Someone else is trying to provide */
995 script->next_attempting_provider = service->attempting_providers;
996 service->attempting_providers = script;
999 if ( ( service = find_service_in_list (command->name,
1000 unavailable_services) )
1002 { /* We're the first to try and provide: create it */
1004 calloc (1, strlen (command->name) + sizeof *service) )
1007 kill (command->pid, SIG_NOT_CHILD);
1010 strcpy (service->name, command->name);
1013 { /* Orphaned service: unhook and grab it */
1014 if (service->prev == NULL) unavailable_services = service->next;
1015 else service->prev->next = service->next;
1016 if (service->next != NULL) service->next->prev = service->prev;
1017 service->next = NULL;
1019 service->prev = script->last_service;
1020 script->last_service->next = service;
1021 script->last_service = service;
1022 kill (command->pid, SIG_NOT_PRESENT);
1028 } /* End Function process_command */
1030 static int run_command (const char *file, const char *name, pid_t pid)
1032 struct script_struct *script;
1033 struct needer_struct *needer = NULL;
1034 struct service_struct *service;
1036 if (find_script_byname (name, &available_list, NULL) != NULL)
1040 needer = calloc (1, sizeof *needer);
1041 if (needer == NULL) return SIG_FAILED;
1044 script = find_script_byname (name, &starting_list, &service);
1046 service = find_service_in_list (name, unavailable_services);
1047 if (service == NULL)
1052 if ( ( script = calloc (1, sizeof *script) ) == NULL )
1057 service = calloc (1, strlen (name) + sizeof *service);
1058 if (service == NULL)
1063 strcpy (service->name, name);
1064 switch ( script->pid = fork () )
1067 for (i = 1; i < NSIG; i++) signal (i, SIG_DFL);
1068 execlp (get_path (file), service->name, "start", NULL);
1069 snprintf (txt, sizeof(txt),
1070 _("error running programme: \"%s\"\n"), service->name);
1074 case -1: /* Error */
1075 service->next = unavailable_services;
1076 if (unavailable_services != NULL)
1077 unavailable_services->prev = service;
1078 unavailable_services = service;
1083 default: /* Parent */
1084 script->first_service = service;
1085 script->last_service = service;
1086 insert_entry (&starting_list, script);
1091 if (needer == NULL) return 0;
1092 needer->next = service->needers;
1093 service->needers = needer;
1095 } /* End Function run_command */
1097 static struct service_struct *find_service_in_list (const char *name,
1098 struct service_struct *sv)
1100 for (; sv != NULL; sv = sv->next)
1101 if (strcmp (sv->name, name) == 0) return (sv);
1103 } /* End Function find_service_in_list */
1105 static struct script_struct *find_script_byname (const char *name,
1106 struct list_head *head,
1107 struct service_struct **service)
1109 struct script_struct *script;
1111 for (script = head->first; script != NULL; script = script->next)
1113 struct service_struct *sv;
1115 if ( ( sv = find_service_in_list (name, script->first_service) )
1118 if (service != NULL) *service = sv;
1122 if (service != NULL) *service = NULL;
1124 } /* End Function find_script_byname */
1126 static struct script_struct *find_script_bypid (pid_t pid,
1127 struct list_head *head)
1129 struct script_struct *script;
1131 for (script = head->first; script != NULL; script = script->next)
1132 if (script->pid == pid) return (script);
1134 } /* End Function find_script_bypid */
1136 static void insert_entry (struct list_head *head, struct script_struct *entry)
1138 if (entry == NULL) return;
1140 entry->next = head->first;
1141 if (head->first != NULL) head->first->prev = entry;
1142 head->first = entry;
1143 if (head->last == NULL) head->last = entry;
1144 ++head->num_entries;
1145 } /* End Function insert_entry */
1147 static void remove_entry (struct list_head *head, struct script_struct *entry)
1149 if (entry->prev == NULL) head->first = entry->next;
1150 else entry->prev->next = entry->next;
1151 if (entry->next == NULL) head->last = entry->prev;
1152 else entry->next->prev = entry->prev;
1153 --head->num_entries;
1154 } /* End Function remove_entry */
1156 static void signal_needers (struct service_struct *service, int sig)
1158 struct needer_struct *needer, *next_needer;
1160 for (needer = service->needers; needer != NULL; needer = next_needer)
1162 kill (needer->pid, sig);
1163 next_needer = needer->next;
1167 service->needers = NULL;
1168 } /* End Function signal_needers */
1170 static void handle_nonworking (struct script_struct *script)
1172 struct service_struct *service, *next;
1174 for (service = script->first_service; service != NULL; service = next)
1176 struct script_struct *provider = service->attempting_providers;
1178 next = service->next;
1179 if (provider == NULL)
1181 service->prev = NULL;
1182 service->next = unavailable_services;
1183 if (unavailable_services != NULL)
1184 unavailable_services->prev = service;
1185 unavailable_services = service;
1188 service->attempting_providers = provider->next_attempting_provider;
1189 provider->last_service->next = service;
1190 service->prev = provider->last_service;
1191 provider->last_service = service;
1192 service->next = NULL;
1193 kill (provider->pid, SIG_NOT_PRESENT);
1196 } /* End Function handle_nonworking */
1198 static int force_progress (void)
1199 /* [RETURNS] 0 if boot scripts are still running, else -1.
1202 struct service_struct *service;
1204 if (starting_list.num_entries > num_needers) return 0;
1205 /* No progress can be made: signal needers */
1206 for (service = unavailable_services; service != NULL;
1207 service = service->next)
1208 signal_needers (service,
1209 service->failed ? SIG_FAILED : SIG_NOT_PRESENT);
1210 return (starting_list.num_entries < 1) ? -1 : 0;
1211 } /* End Function force_progress */
1213 static void show_scripts (FILE *fp, const struct script_struct *script,
1216 fprintf (fp, "%s SERVICES:\n", type);
1217 for (; script != NULL; script = script->next)
1219 struct service_struct *service = script->first_service;
1221 fputs (service->name, fp);
1222 for (service = service->next; service != NULL; service = service->next)
1223 fprintf (fp, " (%s)", service->name);
1226 } /* End Function show_scripts */
1228 static const char *get_path (const char *file)
1231 static char path[PATH_SIZE];
1233 if (file[0] == '/') return file;
1234 if (init_path[0] == '\0') return file;
1235 for (p1 = init_path; *p1 != '\0'; p1 = p2)
1237 if ( ( p2 = strchr (p1, ':') ) == NULL )
1238 p2 = p1 + strlen (p1);
1239 strncpy (path, p1, p2 - p1);
1240 path[p2 - p1] = '/';
1241 strcpy (path + (p2 - p1) + 1, file);
1242 if (*p2 == ':') ++p2;
1243 if (access (path, X_OK) == 0) return path;
1246 } /* End Function get_path */