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>
50
#include "pathnames.h"
51
#include "linux_reboot.h"
54
#include "simpleinit.h"
57
#define CMDSIZ 150 /* max size of a line in inittab */
58
#define NUMCMD 30 /* max number of lines in inittab */
59
#define NUMTOK 20 /* max number of tokens in inittab command */
60
#define PATH_SIZE (CMDSIZ+CMDSIZ+1)
62
#define MAX_RESPAWN_RATE 5 /* number of respawns per 100 seconds */
64
#define TZFILE "/etc/TZ"
66
/* #define DEBUGGING */
68
/* Define this if you want init to ignore the termcap field in inittab for
70
/* #define SPECIAL_CONSOLE_TERM */
80
struct timeval last_start;
84
struct initline inittab[NUMCMD];
86
int stopped = 0; /* are we stopped */
87
static char boot_prog[PATH_SIZE] = _PATH_RC;
88
static char script_prefix[PATH_SIZE] = "\0";
89
static char final_prog[PATH_SIZE] = "\0";
90
static char init_path[PATH_SIZE] = "\0";
91
static int caught_sigint = 0;
92
static int no_reboot = 0;
93
static pid_t rc_child = -1;
94
static const char *initctl_name = "/dev/initctl";
95
static int initctl_fd = -1;
96
static volatile int do_longjmp = 0;
97
static sigjmp_buf jmp_env;
100
static void do_single (void);
101
static int do_rc_tty (const char *path);
102
static int process_path (const char *path, int (*func) (const char *path),
103
int ignore_dangling_symlink);
104
static int preload_file (const char *path);
105
static int run_file (const char *path);
106
static void spawn (int i), read_inittab (void);
107
static void sighup_handler (int sig);
108
static void sigtstp_handler (int sig);
109
static void sigint_handler (int sig);
110
static void sigchild_handler (int sig);
111
static void sigquit_handler (int sig);
112
static void sigterm_handler (int sig);
114
static void set_tz (void);
116
static void write_wtmp (void);
117
static pid_t mywait (int *status);
118
static int run_command (const char *file, const char *name, pid_t pid);
121
static void err (char *s)
125
if((fd = open("/dev/console", O_WRONLY)) < 0) return;
127
write(fd, "init: ", 6);
128
write(fd, s, strlen(s));
132
static void enter_single (void)
137
err(_("Booting to single user mode.\n"));
138
if((pid = fork()) == 0) {
140
execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
141
err(_("exec of single user shell failed\n"));
143
while (waitpid (pid, &i, 0) != pid) /* Nothing */;
145
err(_("fork of single user shell failed\n"));
147
unlink(_PATH_SINGLE);
150
int main(int argc, char *argv[])
161
sigfillset (&sa.sa_mask); /* longjmp and nested signals don't mix */
162
sa.sa_flags = SA_ONESHOT;
163
sa.sa_handler = sigint_handler;
164
sigaction (SIGINT, &sa, NULL);
166
sa.sa_handler = sigtstp_handler;
167
sigaction (SIGTSTP, &sa, NULL);
168
sa.sa_handler = sigterm_handler;
169
sigaction (SIGTERM, &sa, NULL);
170
sa.sa_handler = sigchild_handler;
171
sigaction (SIGCHLD, &sa, NULL);
172
sa.sa_handler = sigquit_handler;
173
sigaction (SIGQUIT, &sa, NULL);
175
setlocale(LC_ALL, "");
176
bindtextdomain(PACKAGE, LOCALEDIR);
179
my_reboot (LINUX_REBOOT_CMD_CAD_OFF);
180
/* Find script to run. Command-line overrides config file overrides
182
for (i = 0; i < NUMCMD; i++) inittab[i].pid = -1;
184
for (i = 1; i < argc; i++) {
185
if (strcmp (argv[i], "single") == 0)
187
else if (strcmp (argv[i], "-noreboot") == 0)
189
else if (strlen(script_prefix) + strlen(argv[i]) < PATH_SIZE) {
190
char path[PATH_SIZE];
192
strcpy (path, script_prefix);
193
strcat (path, argv[i]);
194
if (access (path, R_OK | X_OK) == 0)
195
strcpy (boot_prog, path);
198
if (init_path[0] == '\0')
202
if ( (stat (boot_prog, &statbuf) == 0) && S_ISDIR (statbuf.st_mode) )
204
strcpy (init_path, boot_prog);
205
i = strlen (init_path);
206
if (init_path[i - 1] == '/') init_path[i - 1] = '\0';
210
if ( ( initctl_fd = open (initctl_name, O_RDWR, 0) ) < 0 ) {
211
mkfifo (initctl_name, S_IRUSR | S_IWUSR);
212
if ( ( initctl_fd = open (initctl_name, O_RDWR, 0) ) < 0 )
213
err ( _("error opening fifo\n") );
216
if (initctl_fd >= 0 && fcntl(initctl_fd, F_SETFD, FD_CLOEXEC) != 0) {
217
err ( _("error setting close-on-exec on /dev/initctl") );
219
/* Can the fcntl ever fail? If it does, and we leave
220
the descriptor open in child processes, then any
221
process on the system will be able to write to
222
/dev/initctl and have us execute arbitrary commands
223
as root. So let's refuse to use the fifo in this case. */
229
if ( want_single || (access (_PATH_SINGLE, R_OK) == 0) ) do_single ();
231
/*If we get a SIGTSTP before multi-user mode, do nothing*/
235
if ( do_rc_tty (boot_prog) ) do_single ();
237
while (stopped) /* Also if /etc/rc fails & we get SIGTSTP */
240
write_wtmp(); /* write boottime record */
242
for(i = 0; i < numcmd; i++) {
245
printf("toks= %s %s %s %s\n",p[0], p[1], p[2], p[3]);
246
printf("tty= %s\n", inittab[i].tty);
247
printf("termcap= %s\n", inittab[i].termcap);
251
signal (SIGHUP, sighup_handler); /* Better semantics with signal(2) */
253
for (i = 0; i < getdtablesize (); i++)
254
if (i != initctl_fd) close (i);
256
for(i = 0; i < numcmd; i++)
259
if (final_prog[0] != '\0') {
263
execl (final_prog, final_prog, "start", NULL);
264
err ( _("error running finalprog\n") );
265
_exit (EXIT_FAILURE);
268
err ( _("error forking finalprog\n") );
270
default: /* Parent */
277
if (pid < 1) continue;
279
/* clear utmp entry, and append to wtmp if possible */
284
utmpname(_PATH_UTMP);
286
while((ut = getutent())) {
287
if(ut->ut_pid == pid) {
289
memset(&ut->ut_user, 0, UT_NAMESIZE);
290
memset(&ut->ut_host, 0, sizeof(ut->ut_host));
291
ut->ut_type = DEAD_PROCESS;
297
if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) {
298
flock(lf, LOCK_EX|LOCK_NB);
299
if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
300
write(ut_fd, ut, sizeof(struct utmp));
303
flock(lf, LOCK_UN|LOCK_NB);
312
for(i = 0; i < numcmd; i++) {
313
if(pid == inittab[i].pid || inittab[i].pid < 0) {
318
if (pid == inittab[i].pid)
325
#define MAXTRIES 3 /* number of tries allowed when giving the password */
328
* return true if singleuser mode is allowed.
329
* If /etc/securesingle exists ask for root password, otherwise always OK.
331
static int check_single_ok (void)
333
char *pass, *rootpass = NULL;
337
if (access (_PATH_SECURE, R_OK) != 0) return 1;
338
if ( ( pwd = getpwnam ("root") ) || ( pwd = getpwuid (0) ) )
339
rootpass = pwd->pw_passwd;
341
return 1; /* a bad /etc/passwd should not lock out */
343
for (i = 0; i < MAXTRIES; i++)
345
pass = getpass (_("Password: "));
346
if (pass == NULL) continue;
348
if ( !strcmp (crypt (pass, rootpass), rootpass) ) return 1;
350
puts (_("\nWrong password.\n"));
355
static void do_single (void)
357
char path[PATH_SIZE];
359
if (caught_sigint) return;
360
strcpy (path, script_prefix);
361
strcat (path, "single");
362
if (access (path, R_OK | X_OK) == 0)
363
if (do_rc_tty (path) == 0) return;
364
if ( check_single_ok () ) enter_single ();
365
} /* End Function do_single */
368
* run boot script(s). The environment is passed to the script(s), so the RC
369
* environment variable can be used to decide what to do.
370
* RC may be set from LILO.
371
* [RETURNS] 0 on success (exit status convention), otherwise error.
373
static int do_rc_tty (const char *path)
379
if (caught_sigint) return 0;
380
process_path (path, preload_file, 0);
381
/* Launch off a subprocess to start a new session (required for frobbing
382
the TTY) and capture control-C */
383
switch ( rc_child = fork () )
386
for (status = 1; status < NSIG; status++) signal (status, SIG_DFL);
388
sigprocmask (SIG_UNBLOCK, &ss, NULL);
389
sigdelset (&ss, SIGINT);
390
sigdelset (&ss, SIGQUIT);
392
ioctl (0, TIOCSCTTY, 0); /* I want my control-C */
393
sigsuspend (&ss); /* Should never return, should just be killed */
394
break; /* No-one else is controlled by this TTY now */
398
default: /* Parent */
402
process_path (path, run_file, 0);
405
if ( ( pid = mywait (&status) ) == rc_child )
406
return (WTERMSIG (status) == SIGINT) ? 0 : 1;
409
kill (rc_child, SIGKILL);
410
while (waitpid (rc_child, NULL, 0) != rc_child) /* Nothing */;
412
} /* End Function do_rc_tty */
414
static int process_path (const char *path, int (*func) (const char *path),
415
int ignore_dangling_symlink)
421
if (lstat (path, &statbuf) != 0)
423
err (_("lstat of path failed\n") );
426
if ( S_ISLNK (statbuf.st_mode) )
428
if (stat (path, &statbuf) != 0)
430
if ( (errno == ENOENT) && ignore_dangling_symlink ) return 0;
431
err (_("stat of path failed\n") );
435
if ( !( statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH) ) ) return 0;
436
if ( !S_ISDIR (statbuf.st_mode) ) return (*func) (path);
437
if ( ( dp = opendir (path) ) == NULL )
439
err (_("open of directory failed\n") );
442
while ( ( de = readdir (dp) ) != NULL )
445
char newpath[PATH_SIZE];
447
if (de->d_name[0] == '.') continue;
448
retval = snprintf (newpath, sizeof(newpath), "%s/%s", path, de->d_name);
449
if (newpath[retval - 1] == '~') continue; /* Common mistake */
450
if ( ( retval = process_path (newpath, func, 1) ) ) return retval;
454
} /* End Function process_path */
456
static int preload_file (const char *path)
461
if ( ( fd = open (path, O_RDONLY, 0) ) < 0) return 0;
462
while (read (fd, &ch, 1) == 1) lseek (fd, 1024, SEEK_CUR);
465
} /* End Function preload_file */
467
static int run_file (const char *path)
471
if ( ( ptr = strrchr ( (char *) path, '/' ) ) == NULL ) ptr = path;
473
return (run_command (path, ptr, 0) == SIG_FAILED) ? 1 : 0;
474
} /* End Function run_file */
476
static void spawn (int i)
480
signed long ds_taken;
483
if (inittab[i].toks[0] == NULL) return;
485
/* Check if respawning too fast */
486
gettimeofday (&ct, NULL);
487
ds_taken = ct.tv_sec - inittab[i].last_start.tv_sec;
489
/* On the first iteration last_start==0 and ds_taken
490
may be very large. Avoid overflow. -- Denis Vlasenko */
491
if (ds_taken > 10000)
495
ds_taken += (ct.tv_usec - inittab[i].last_start.tv_usec) / 100000;
498
inittab[i].rate = (9 * inittab[i].rate + 1000 / ds_taken) / 10;
499
if (inittab[i].rate > MAX_RESPAWN_RATE) {
502
inittab[i].toks[0] = NULL;
505
snprintf (txt, sizeof(txt),
506
_("respawning: \"%s\" too fast: quenching entry\n"),
512
if((pid = fork()) < 0) {
514
err(_("fork failed\n"));
518
/* this is the parent */
519
inittab[i].pid = pid;
520
inittab[i].last_start = ct;
524
/* this is the child */
532
for(j = 0; j < getdtablesize(); j++)
535
snprintf(term, sizeof(term), "TERM=%s", inittab[i].termcap);
539
snprintf(tz, sizeof(tz), "TZ=%s", tzone);
544
execve(inittab[i].toks[0], inittab[i].toks, env);
545
err(_("exec failed\n"));
551
static void read_inittab (void)
558
char prog[PATH_SIZE];
559
#ifdef SPECIAL_CONSOLE_TERM
565
termenv = getenv("TERM"); /* set by kernel */
566
/* termenv = "vt100"; */
568
if(!(f = fopen(_PATH_INITTAB, "r"))) {
569
err(_("cannot open inittab\n"));
575
while(!feof(f) && i < NUMCMD - 2) {
576
if(fgets(buf, CMDSIZ - 1, f) == 0) break;
579
for(k = 0; k < CMDSIZ && buf[k]; k++) {
580
if ((buf[k] == '#') || (buf[k] == '\n')) {
585
if(buf[0] == 0 || buf[0] == '\n') continue;
586
ptr = strchr (buf, '=');
589
if ( !strncmp (buf, "bootprog", 8) ) {
590
while ( isspace (*ptr) ) ++ptr;
595
if ( !strncmp (buf, "fileprefix", 10) ) {
596
while ( isspace (*ptr) ) ++ptr;
597
strcpy (script_prefix, ptr);
600
if ( !strncmp (buf, "PATH", 4) ) {
601
while ( isspace (*ptr) ) ++ptr;
602
setenv ("PATH", ptr, 1);
605
if ( !strncmp (buf, "INIT_PATH", 9) ) {
606
while ( isspace (*ptr) ) ++ptr;
607
strcpy (init_path, ptr);
610
if ( !strncmp (buf, "finalprog", 8) ) {
611
while ( isspace (*ptr) ) ++ptr;
612
strcpy (final_prog, ptr);
618
(void) strcpy(inittab[i].line, buf);
620
(void) strtok(inittab[i].line, ":");
621
xstrncpy(inittab[i].tty, inittab[i].line, 10);
622
xstrncpy(inittab[i].termcap, strtok((char *)0, ":"), 30);
624
getty = strtok((char *)0, ":");
625
(void) strtok(getty, " \t\n");
626
inittab[i].toks[0] = getty;
628
while((ptr = strtok((char *)0, " \t\n")))
629
inittab[i].toks[j++] = ptr;
630
inittab[i].toks[j] = (char *)0;
632
#ifdef SPECIAL_CONSOLE_TERM
633
/* special-case termcap for the console ttys */
634
snprintf(tty, sizeof(tty), "/dev/%s", inittab[i].tty);
635
if(!termenv || stat(tty, &stb) < 0) {
636
err(_("no TERM or cannot stat tty\n"));
638
/* is it a console tty? */
639
if(major(stb.st_rdev) == 4 && minor(stb.st_rdev) < 64)
640
xstrncpy(inittab[i].termcap, termenv, 30);
650
char path[PATH_SIZE];
652
strcpy (path, script_prefix);
655
if (path[len - 1] == '/') path[len - 1] = '\0';
656
if (access (path, R_OK | X_OK) == 0)
657
strcpy (boot_prog, path);
659
} /* End Function read_inittab */
661
static void sighup_handler (int sig)
665
struct initline savetab[NUMCMD];
668
signal (SIGHUP, SIG_IGN);
669
memcpy(savetab, inittab, NUMCMD * sizeof(struct initline));
673
for(i = 0; i < numcmd; i++) {
675
for(j = 0; j < oldnum; j++) {
676
if(!strcmp(savetab[j].tty, inittab[i].tty)) {
678
if((inittab[i].pid = savetab[j].pid) < 0)
682
if (!had_already) spawn (i);
684
signal (SIGHUP, sighup_handler);
685
} /* End Function sighup_handler */
687
static void sigtstp_handler (int sig)
690
if (!stopped) sighup_handler (sig);
691
} /* End Function sigtstp_handler */
693
static void sigterm_handler (int sig)
697
for (i = 0; i < numcmd; i++)
698
if (inittab[i].pid > 0) kill (inittab[i].pid, SIGTERM);
699
} /* End Function sigterm_handler */
701
static void sigint_handler (int sig)
706
kill (rc_child, SIGKILL);
707
if (no_reboot) _exit (EXIT_FAILURE) /*kill (0, SIGKILL)*/;
711
if (pid > 0) return; /* Parent */
712
if (pid == 0) /* Child: reboot properly... */
713
execl (_PATH_REBOOT, _PATH_REBOOT, (char *) 0);
715
/* fork or exec failed, try the hard way... */
716
my_reboot (LINUX_REBOOT_CMD_RESTART);
717
} /* End Function sigint_handler */
719
static void sigchild_handler (int sig)
721
if (!do_longjmp) return;
722
siglongjmp (jmp_env, 1);
725
static void sigquit_handler (int sig)
727
execl (_PATH_REBOOT, _PATH_REBOOT, NULL); /* It knows pid=1 must sleep */
731
static void set_tz (void)
736
if((f=fopen(TZFILE, "r")) == (FILE *)NULL) return;
737
fgets(tzone, CMDSIZ-2, f);
739
if((len=strlen(tzone)) < 2) return;
740
tzone[len-1] = 0; /* get rid of the '\n' */
741
setenv("TZ", tzone, 0);
745
static void write_wtmp (void)
750
memset((char *)&ut, 0, sizeof(ut));
751
strcpy(ut.ut_line, "~");
752
memset(ut.ut_name, 0, sizeof(ut.ut_name));
754
ut.ut_type = BOOT_TIME;
756
if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) {
757
flock(lf, LOCK_EX|LOCK_NB); /* make sure init won't hang */
758
if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) >= 0) {
759
write(fd, (char *)&ut, sizeof(ut));
762
flock(lf, LOCK_UN|LOCK_NB);
765
} /* End Function write_wtmp */
770
struct needer_struct *next;
774
struct service_struct
776
struct service_struct *prev, *next; /* Script services chain */
777
struct needer_struct *needers; /* Needers waiting for service */
778
struct script_struct *attempting_providers;
779
int failed; /* TRUE if attempting provider failed badly */
786
struct script_struct *prev, *next; /* For the list */
787
struct service_struct *first_service, *last_service; /*First is true name*/
788
struct script_struct *next_attempting_provider; /* Provider chain */
793
struct script_struct *first, *last;
794
unsigned int num_entries;
798
static struct list_head available_list = {NULL, NULL, 0};
799
static struct list_head starting_list = {NULL, NULL, 0};
800
static struct service_struct *unavailable_services = NULL; /* For needers */
801
static int num_needers = 0;
804
static int process_pidstat (pid_t pid, int status);
805
static void process_command (const struct command_struct *command);
806
static struct service_struct *find_service_in_list (const char *name,
807
struct service_struct *sv);
808
static struct script_struct *find_script_byname
809
(const char *name,struct list_head *head, struct service_struct **service);
810
static struct script_struct *find_script_bypid (pid_t pid,
811
struct list_head *head);
812
static void insert_entry (struct list_head *head, struct script_struct *entry);
813
static void remove_entry (struct list_head *head, struct script_struct *entry);
814
static void signal_needers (struct service_struct *service, int sig);
815
static void handle_nonworking (struct script_struct *script);
816
static int force_progress (void);
817
static void show_scripts (FILE *fp, const struct script_struct *script,
819
static const char *get_path (const char *file);
822
static pid_t mywait (int *status)
823
/* [RETURNS] The pid for a process to be reaped, 0 if no process is to be
824
reaped, and less than 0 if the boot scripts appear to have finished.
829
long buffer[COMMAND_SIZE / sizeof (long)];
830
struct command_struct *command = (struct command_struct *) buffer;
832
if (initctl_fd < 0) return wait (status);
833
/* Some magic to avoid races which can result in lost signals */
834
command->command = -1;
835
if ( sigsetjmp (jmp_env, 1) )
836
{ /* Jump from signal handler */
838
process_command (command);
841
sigemptyset (&ss); /* Block SIGCHLD so wait status cannot be lost */
842
sigaddset (&ss, SIGCHLD);
843
sigprocmask (SIG_BLOCK, &ss, NULL);
844
if ( ( pid = waitpid (-1, status, WNOHANG) ) > 0 )
846
sigprocmask (SIG_UNBLOCK, &ss, NULL);
847
return process_pidstat (pid, *status);
849
do_longjmp = 1; /* After this, SIGCHLD will cause a jump backwards */
850
sigprocmask (SIG_UNBLOCK, &ss, NULL);
851
read (initctl_fd, buffer, sizeof(buffer));
853
process_command (command);
855
} /* End Function mywait */
857
static pid_t process_pidstat (pid_t pid, int status)
858
/* [RETURNS] The pid for a process to be reaped, 0 if no process is to be
859
reaped, and less than 0 if the boot scripts appear to have finished.
863
struct script_struct *script;
864
struct service_struct *service;
866
if ( ( script = find_script_bypid (pid, &starting_list) ) == NULL )
868
remove_entry (&starting_list, script);
869
if ( WIFEXITED (status) && (WEXITSTATUS (status) == 0) )
871
struct script_struct *provider;
873
/* Notify needers and other providers */
874
for (service = script->first_service; service != NULL;
875
service = service->next)
877
signal_needers (service, SIG_PRESENT);
878
for (provider = service->attempting_providers; provider != NULL;
879
provider = provider->next_attempting_provider)
880
kill (provider->pid, SIG_PRESENT);
881
service->attempting_providers = NULL;
883
insert_entry (&available_list, script);
884
return force_progress ();
886
failed = ( WIFEXITED (status) && (WEXITSTATUS (status) == 2) ) ? 0 : 1;
887
for (service = script->first_service; service != NULL;
888
service = service->next)
889
service->failed = failed;
890
handle_nonworking (script);
891
return force_progress ();
892
} /* End Function process_pidstat */
894
static void process_command (const struct command_struct *command)
897
struct script_struct *script;
898
struct service_struct *service;
900
switch (command->command)
904
(find_script_byname (command->name, &available_list,
906
SIG_NOT_PRESENT : SIG_PRESENT);
909
ival = run_command (command->name, command->name, command->pid);
915
else kill (command->pid, ival);
917
case COMMAND_ROLLBACK:
918
if (command->name[0] == '\0') script = NULL;
921
if ( ( script = find_script_byname (command->name, &available_list,
924
kill (command->pid, SIG_NOT_PRESENT);
928
while (script != available_list.first)
931
struct script_struct *victim = available_list.first;
934
if ( ( pid = fork () ) == 0 ) /* Child */
936
for (ival = 1; ival < NSIG; ival++) signal (ival, SIG_DFL);
937
open ("/dev/console", O_RDONLY, 0);
938
open ("/dev/console", O_RDWR, 0);
940
execlp (get_path (victim->first_service->name),
941
victim->first_service->name, "stop", NULL);
942
snprintf (txt, sizeof(txt),
943
_("error at stopping service \"%s\"\n"),
944
victim->first_service->name);
946
_exit (SIG_NOT_STOPPED);
948
else if (pid == -1) break; /* Error */
951
while (waitpid (pid, &ival, 0) != pid) /* Nothing */;
952
if ( WIFEXITED (ival) && (WEXITSTATUS (ival) == 0) )
954
snprintf (txt, sizeof(txt),
955
_("Stopped service: %s\n"),
956
victim->first_service->name);
957
remove_entry (&available_list, victim);
965
(script ==available_list.first) ? SIG_STOPPED : SIG_NOT_STOPPED);
967
case COMMAND_DUMP_LIST:
968
if (fork () == 0) /* Do it in a child process so pid=1 doesn't block */
972
if ( ( fp = fopen (command->name, "w") ) == NULL ) _exit (EXIT_FAILURE);
973
show_scripts (fp, available_list.first, "AVAILABLE");
974
show_scripts (fp, starting_list.first, "STARTING");
975
fputs ("UNAVAILABLE SERVICES:\n", fp);
976
for (service = unavailable_services; service != NULL;
977
service = service->next)
978
fprintf (fp, "%s (%s)\n", service->name,
979
service->failed ? "FAILED" : "not configured");
981
_exit (EXIT_SUCCESS);
984
case COMMAND_PROVIDE:
986
if ( ( script = find_script_bypid (command->ppid, &starting_list) )
989
kill (command->pid, SIG_NOT_CHILD);
992
if (find_script_byname (command->name, &available_list, NULL) != NULL)
994
kill (command->pid, SIG_PRESENT);
997
if (find_script_byname (command->name, &starting_list, &service)
999
{ /* Someone else is trying to provide */
1000
script->next_attempting_provider = service->attempting_providers;
1001
service->attempting_providers = script;
1004
if ( ( service = find_service_in_list (command->name,
1005
unavailable_services) )
1007
{ /* We're the first to try and provide: create it */
1009
calloc (1, strlen (command->name) + sizeof *service) )
1012
kill (command->pid, SIG_NOT_CHILD);
1015
strcpy (service->name, command->name);
1018
{ /* Orphaned service: unhook and grab it */
1019
if (service->prev == NULL) unavailable_services = service->next;
1020
else service->prev->next = service->next;
1021
if (service->next != NULL) service->next->prev = service->prev;
1022
service->next = NULL;
1024
service->prev = script->last_service;
1025
script->last_service->next = service;
1026
script->last_service = service;
1027
kill (command->pid, SIG_NOT_PRESENT);
1033
} /* End Function process_command */
1035
static int run_command (const char *file, const char *name, pid_t pid)
1037
struct script_struct *script;
1038
struct needer_struct *needer = NULL;
1039
struct service_struct *service;
1041
if (find_script_byname (name, &available_list, NULL) != NULL)
1045
needer = calloc (1, sizeof *needer);
1046
if (needer == NULL) return SIG_FAILED;
1049
script = find_script_byname (name, &starting_list, &service);
1051
service = find_service_in_list (name, unavailable_services);
1052
if (service == NULL)
1057
if ( ( script = calloc (1, sizeof *script) ) == NULL )
1062
service = calloc (1, strlen (name) + sizeof *service);
1063
if (service == NULL)
1068
strcpy (service->name, name);
1069
switch ( script->pid = fork () )
1072
for (i = 1; i < NSIG; i++) signal (i, SIG_DFL);
1073
execlp (get_path (file), service->name, "start", NULL);
1074
snprintf (txt, sizeof(txt),
1075
_("error at starting service \"%s\"\n"), service->name);
1079
case -1: /* Error */
1080
service->next = unavailable_services;
1081
if (unavailable_services != NULL)
1082
unavailable_services->prev = service;
1083
unavailable_services = service;
1088
default: /* Parent */
1089
script->first_service = service;
1090
script->last_service = service;
1091
insert_entry (&starting_list, script);
1096
if (needer == NULL) return 0;
1097
needer->next = service->needers;
1098
service->needers = needer;
1100
} /* End Function run_command */
1102
static struct service_struct *find_service_in_list (const char *name,
1103
struct service_struct *sv)
1105
for (; sv != NULL; sv = sv->next)
1106
if (strcmp (sv->name, name) == 0) return (sv);
1108
} /* End Function find_service_in_list */
1110
static struct script_struct *find_script_byname (const char *name,
1111
struct list_head *head,
1112
struct service_struct **service)
1114
struct script_struct *script;
1116
for (script = head->first; script != NULL; script = script->next)
1118
struct service_struct *sv;
1120
if ( ( sv = find_service_in_list (name, script->first_service) )
1123
if (service != NULL) *service = sv;
1127
if (service != NULL) *service = NULL;
1129
} /* End Function find_script_byname */
1131
static struct script_struct *find_script_bypid (pid_t pid,
1132
struct list_head *head)
1134
struct script_struct *script;
1136
for (script = head->first; script != NULL; script = script->next)
1137
if (script->pid == pid) return (script);
1139
} /* End Function find_script_bypid */
1141
static void insert_entry (struct list_head *head, struct script_struct *entry)
1143
if (entry == NULL) return;
1145
entry->next = head->first;
1146
if (head->first != NULL) head->first->prev = entry;
1147
head->first = entry;
1148
if (head->last == NULL) head->last = entry;
1149
++head->num_entries;
1150
} /* End Function insert_entry */
1152
static void remove_entry (struct list_head *head, struct script_struct *entry)
1154
if (entry->prev == NULL) head->first = entry->next;
1155
else entry->prev->next = entry->next;
1156
if (entry->next == NULL) head->last = entry->prev;
1157
else entry->next->prev = entry->prev;
1158
--head->num_entries;
1159
} /* End Function remove_entry */
1161
static void signal_needers (struct service_struct *service, int sig)
1163
struct needer_struct *needer, *next_needer;
1165
for (needer = service->needers; needer != NULL; needer = next_needer)
1167
kill (needer->pid, sig);
1168
next_needer = needer->next;
1172
service->needers = NULL;
1173
} /* End Function signal_needers */
1175
static void handle_nonworking (struct script_struct *script)
1177
struct service_struct *service, *next;
1179
for (service = script->first_service; service != NULL; service = next)
1181
struct script_struct *provider = service->attempting_providers;
1183
next = service->next;
1184
if (provider == NULL)
1186
service->prev = NULL;
1187
service->next = unavailable_services;
1188
if (unavailable_services != NULL)
1189
unavailable_services->prev = service;
1190
unavailable_services = service;
1193
service->attempting_providers = provider->next_attempting_provider;
1194
provider->last_service->next = service;
1195
service->prev = provider->last_service;
1196
provider->last_service = service;
1197
service->next = NULL;
1198
kill (provider->pid, SIG_NOT_PRESENT);
1201
} /* End Function handle_nonworking */
1203
static int force_progress (void)
1204
/* [RETURNS] 0 if boot scripts are still running, else -1.
1207
struct service_struct *service;
1209
if (starting_list.num_entries > num_needers) return 0;
1210
/* No progress can be made: signal needers */
1211
for (service = unavailable_services; service != NULL;
1212
service = service->next)
1213
signal_needers (service,
1214
service->failed ? SIG_FAILED : SIG_NOT_PRESENT);
1215
return (starting_list.num_entries < 1) ? -1 : 0;
1216
} /* End Function force_progress */
1218
static void show_scripts (FILE *fp, const struct script_struct *script,
1221
fprintf (fp, "%s SERVICES:\n", type);
1222
for (; script != NULL; script = script->next)
1224
struct service_struct *service = script->first_service;
1226
fputs (service->name, fp);
1227
for (service = service->next; service != NULL; service = service->next)
1228
fprintf (fp, " (%s)", service->name);
1231
} /* End Function show_scripts */
1233
static const char *get_path (const char *file)
1236
static char path[PATH_SIZE];
1238
if (file[0] == '/') return file;
1239
if (init_path[0] == '\0') return file;
1240
for (p1 = init_path; *p1 != '\0'; p1 = p2)
1242
if ( ( p2 = strchr (p1, ':') ) == NULL )
1243
p2 = p1 + strlen (p1);
1244
strncpy (path, p1, p2 - p1);
1245
path[p2 - p1] = '/';
1246
strcpy (path + (p2 - p1) + 1, file);
1247
if (*p2 == ':') ++p2;
1248
if (access (path, X_OK) == 0) return path;
1251
} /* End Function get_path */