/[baselayout]/trunk/src/rc.c
Gentoo

Contents of /trunk/src/rc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2656 - (hide annotations) (download) (as text)
Wed Apr 25 15:48:54 2007 UTC (11 years, 5 months ago) by uberlord
File MIME type: text/x-csrc
File size: 33449 byte(s)
Don't pass $CONSOLE to sulogin and split rc_environ_fd on NULLs
1 uberlord 2547 /*
2     rc.c
3     rc - manager for init scripts which control the startup, shutdown
4     and the running of daemons on a Gentoo system.
5    
6     Also a multicall binary for various commands that can be used in shell
7     scripts to query service state, mark service state and provide the
8     Gentoo einfo family of informational functions.
9 uberlord 2569
10 uberlord 2547 Copyright 2007 Gentoo Foundation
11     Released under the GPLv2
12     */
13    
14     #include <sys/types.h>
15     #include <sys/stat.h>
16     #include <sys/utsname.h>
17     #include <sys/wait.h>
18     #include <errno.h>
19     #include <ctype.h>
20     #include <libgen.h>
21     #include <limits.h>
22     #include <stdbool.h>
23     #include <stdio.h>
24     #include <stdlib.h>
25     #include <signal.h>
26     #include <string.h>
27     #include <termios.h>
28     #include <unistd.h>
29    
30     #include "einfo.h"
31     #include "rc.h"
32     #include "rc-misc.h"
33     #include "rc-plugin.h"
34     #include "strlist.h"
35    
36 uberlord 2615 #define INITSH RC_LIBDIR "sh/init.sh"
37     #define HALTSH RC_INITDIR "halt.sh"
38 uberlord 2547
39 uberlord 2615 #define RC_SVCDIR_STARTING RC_SVCDIR "starting/"
40     #define RC_SVCDIR_INACTIVE RC_SVCDIR "inactive/"
41     #define RC_SVCDIR_STARTED RC_SVCDIR "started/"
42 uberlord 2547 #define RC_SVCDIR_COLDPLUGGED RC_SVCDIR "coldplugged/"
43    
44 uberlord 2615 #define INTERACTIVE RC_SVCDIR "interactive"
45 uberlord 2547
46 uberlord 2615 #define DEVBOOT "/dev/.rcboot"
47 uberlord 2547
48     /* Cleanup anything in main */
49 uberlord 2577 #define CHAR_FREE(_item) if (_item) { \
50     free (_item); \
51     _item = NULL; \
52 uberlord 2547 }
53    
54     extern char **environ;
55    
56 uberlord 2563 static char *applet = NULL;
57 uberlord 2547 static char **env = NULL;
58     static char **newenv = NULL;
59 uberlord 2638 static char **coldplugged_services = NULL;
60 uberlord 2547 static char **stop_services = NULL;
61     static char **start_services = NULL;
62     static rc_depinfo_t *deptree = NULL;
63     static char **types = NULL;
64     static char *tmp = NULL;
65    
66 uberlord 2638 struct termios *termios_orig = NULL;
67 uberlord 2547
68 uberlord 2641 typedef struct pidlist
69     {
70     pid_t pid;
71     struct pidlist *next;
72     } pidlist_t;
73     static pidlist_t *service_pids = NULL;
74    
75 uberlord 2547 static void cleanup (void)
76     {
77 uberlord 2641 pidlist_t *pl = service_pids;
78    
79 uberlord 2577 rc_plugin_unload ();
80 uberlord 2547
81 uberlord 2577 if (termios_orig) {
82     tcsetattr (STDIN_FILENO, TCSANOW, termios_orig);
83     free (termios_orig);
84     }
85 uberlord 2547
86 uberlord 2641 while (pl) {
87     pidlist_t *p = pl->next;
88     free (pl);
89     pl = p;
90     }
91    
92 uberlord 2638 rc_strlist_free (env);
93     rc_strlist_free (newenv);
94     rc_strlist_free (coldplugged_services);
95     rc_strlist_free (stop_services);
96     rc_strlist_free (start_services);
97     rc_free_deptree (deptree);
98     rc_strlist_free (types);
99 uberlord 2547
100 uberlord 2577 /* Clean runlevel start, stop markers */
101     if (rc_is_dir (RC_SVCDIR "softscripts.new"))
102     rc_rm_dir (RC_SVCDIR "softscripts.new", true);
103     if (rc_is_dir (RC_SVCDIR "softscripts.old"))
104     rc_rm_dir (RC_SVCDIR "softscripts.old", true);
105 uberlord 2563
106 uberlord 2638 free (applet);
107 uberlord 2547 }
108    
109     static int do_e (int argc, char **argv)
110     {
111 uberlord 2577 int retval = EXIT_SUCCESS;
112     int i;
113     int l = 0;
114     char *message = NULL;
115     char *p;
116     char *fmt = NULL;
117 uberlord 2547
118 uberlord 2615 if (strcmp (applet, "eval_ecolors") == 0) {
119     printf ("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n",
120     ecolor (ecolor_good),
121     ecolor (ecolor_warn),
122     ecolor (ecolor_bad),
123     ecolor (ecolor_hilite),
124     ecolor (ecolor_bracket),
125     ecolor (ecolor_normal));
126     exit (EXIT_SUCCESS);
127     }
128    
129 uberlord 2577 if (strcmp (applet, "eend") == 0 ||
130     strcmp (applet, "ewend") == 0 ||
131     strcmp (applet, "veend") == 0 ||
132     strcmp (applet, "vweend") == 0)
133     {
134     if (argc > 0) {
135     errno = 0;
136     retval = strtol (argv[0], NULL, 0);
137     if (errno != 0)
138     retval = EXIT_FAILURE;
139     else {
140     argc--;
141     argv++;
142     }
143     }
144     else
145     retval = EXIT_FAILURE;
146     }
147 uberlord 2547
148 uberlord 2577 if (argc > 0) {
149     for (i = 0; i < argc; i++)
150     l += strlen (argv[i]) + 1;
151 uberlord 2547
152 uberlord 2577 message = rc_xmalloc (l);
153     p = message;
154 uberlord 2547
155 uberlord 2577 for (i = 0; i < argc; i++) {
156     if (i > 0)
157     *p++ = ' ';
158     memcpy (p, argv[i], strlen (argv[i]));
159     p += strlen (argv[i]);
160     }
161     *p = 0;
162     }
163 uberlord 2547
164 uberlord 2577 if (message)
165 uberlord 2634 fmt = rc_xstrdup ("%s");
166 uberlord 2547
167 uberlord 2577 if (strcmp (applet, "einfo") == 0)
168     einfo (fmt, message);
169     else if (strcmp (applet, "einfon") == 0)
170     einfon (fmt, message);
171     else if (strcmp (applet, "ewarn") == 0)
172     ewarn (fmt, message);
173     else if (strcmp (applet, "ewarnn") == 0)
174     ewarnn (fmt, message);
175     else if (strcmp (applet, "eerror") == 0) {
176     eerror (fmt, message);
177     retval = 1;
178     } else if (strcmp (applet, "eerrorn") == 0) {
179     eerrorn (fmt, message);
180     retval = 1;
181     } else if (strcmp (applet, "ebegin") == 0)
182     ebegin (fmt, message);
183     else if (strcmp (applet, "eend") == 0)
184     eend (retval, fmt, message);
185     else if (strcmp (applet, "ewend") == 0)
186     ewend (retval, fmt, message);
187     else if (strcmp (applet, "veinfo") == 0)
188     einfov (fmt, message);
189     else if (strcmp (applet, "veinfon") == 0)
190     einfovn (fmt, message);
191     else if (strcmp (applet, "vewarn") == 0)
192     ewarnv (fmt, message);
193     else if (strcmp (applet, "vewarnn") == 0)
194     ewarnvn (fmt, message);
195     else if (strcmp (applet, "vebegin") == 0)
196     ebeginv (fmt, message);
197     else if (strcmp (applet, "veend") == 0)
198     eendv (retval, fmt, message);
199     else if (strcmp (applet, "vewend") == 0)
200     ewendv (retval, fmt, message);
201     else if (strcmp (applet, "eindent") == 0)
202     eindent ();
203     else if (strcmp (applet, "eoutdent") == 0)
204     eoutdent ();
205     else if (strcmp (applet, "veindent") == 0)
206     eindentv ();
207     else if (strcmp (applet, "veoutdent") == 0)
208     eoutdentv ();
209     else if (strcmp (applet, "eflush") == 0)
210     eflush ();
211     else {
212     eerror ("%s: unknown applet", applet);
213     retval = EXIT_FAILURE;
214     }
215 uberlord 2547
216 uberlord 2577 if (fmt)
217     free (fmt);
218     if (message)
219     free (message);
220     return (retval);
221 uberlord 2547 }
222    
223     static int do_service (int argc, char **argv)
224     {
225 uberlord 2577 bool ok = false;
226 uberlord 2547
227 uberlord 2577 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
228     eerrorx ("%s: no service specified", applet);
229 uberlord 2547
230 uberlord 2577 if (strcmp (applet, "service_started") == 0)
231     ok = rc_service_state (argv[0], rc_service_started);
232     else if (strcmp (applet, "service_stopped") == 0)
233     ok = rc_service_state (argv[0], rc_service_stopped);
234     else if (strcmp (applet, "service_inactive") == 0)
235     ok = rc_service_state (argv[0], rc_service_inactive);
236     else if (strcmp (applet, "service_starting") == 0)
237     ok = rc_service_state (argv[0], rc_service_starting);
238     else if (strcmp (applet, "service_stopping") == 0)
239     ok = rc_service_state (argv[0], rc_service_stopping);
240     else if (strcmp (applet, "service_coldplugged") == 0)
241     ok = rc_service_state (argv[0], rc_service_coldplugged);
242     else if (strcmp (applet, "service_wasinactive") == 0)
243     ok = rc_service_state (argv[0], rc_service_wasinactive);
244     else if (strcmp (applet, "service_started_daemon") == 0) {
245     int idx = 0;
246     if (argc > 2)
247     sscanf (argv[2], "%d", &idx);
248     exit (rc_service_started_daemon (argv[0], argv[1], idx)
249     ? 0 : 1);
250     } else
251     eerrorx ("%s: unknown applet", applet);
252 uberlord 2547
253 uberlord 2577 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
254 uberlord 2547 }
255    
256     static int do_mark_service (int argc, char **argv)
257     {
258 uberlord 2577 bool ok = false;
259     char *svcname = getenv ("SVCNAME");
260 uberlord 2547
261 uberlord 2577 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
262     eerrorx ("%s: no service specified", applet);
263 uberlord 2547
264 uberlord 2577 if (strcmp (applet, "mark_service_started") == 0)
265     ok = rc_mark_service (argv[0], rc_service_started);
266     else if (strcmp (applet, "mark_service_stopped") == 0)
267     ok = rc_mark_service (argv[0], rc_service_stopped);
268     else if (strcmp (applet, "mark_service_inactive") == 0)
269     ok = rc_mark_service (argv[0], rc_service_inactive);
270     else if (strcmp (applet, "mark_service_starting") == 0)
271     ok = rc_mark_service (argv[0], rc_service_starting);
272     else if (strcmp (applet, "mark_service_stopping") == 0)
273     ok = rc_mark_service (argv[0], rc_service_stopping);
274     else if (strcmp (applet, "mark_service_coldplugged") == 0)
275     ok = rc_mark_service (argv[0], rc_service_coldplugged);
276     else
277     eerrorx ("%s: unknown applet", applet);
278 uberlord 2547
279 uberlord 2577 /* If we're marking ourselves then we need to inform our parent runscript
280     process so they do not mark us based on our exit code */
281     if (ok && svcname && strcmp (svcname, argv[0]) == 0) {
282     char *runscript_pid = getenv ("RC_RUNSCRIPT_PID");
283     char *mtime;
284     pid_t pid = 0;
285     int l;
286 uberlord 2547
287 uberlord 2577 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1)
288     if (kill (pid, SIGHUP) != 0)
289     eerror ("%s: failed to signal parent %d: %s",
290     applet, pid, strerror (errno));
291 uberlord 2547
292 uberlord 2577 /* Remove the exclsive time test. This ensures that it's not
293     in control as well */
294     l = strlen (RC_SVCDIR "exclusive") +
295     strlen (svcname) +
296     strlen (runscript_pid) +
297     4;
298     mtime = rc_xmalloc (l);
299     snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s",
300     svcname, runscript_pid);
301     if (rc_exists (mtime) && unlink (mtime) != 0)
302     eerror ("%s: unlink: %s", applet, strerror (errno));
303     free (mtime);
304     }
305 uberlord 2547
306 uberlord 2577 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
307 uberlord 2547 }
308    
309     static int do_options (int argc, char **argv)
310     {
311 uberlord 2577 bool ok = false;
312     char *service = getenv ("SVCNAME");
313 uberlord 2547
314 uberlord 2577 if (! service)
315     eerrorx ("%s: no service specified", applet);
316 uberlord 2547
317 uberlord 2577 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
318     eerrorx ("%s: no option specified", applet);
319 uberlord 2547
320 uberlord 2577 if (strcmp (applet, "get_options") == 0) {
321     char buffer[1024];
322     memset (buffer, 0, 1024);
323     ok = rc_get_service_option (service, argv[0], buffer);
324     if (ok)
325     printf ("%s", buffer);
326     } else if (strcmp (applet, "save_options") == 0)
327     ok = rc_set_service_option (service, argv[0], argv[1]);
328     else
329     eerrorx ("%s: unknown applet", applet);
330 uberlord 2547
331 uberlord 2577 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
332 uberlord 2547 }
333    
334     static char read_key (bool block)
335     {
336 uberlord 2577 struct termios termios;
337     char c = 0;
338 uberlord 2642
339 uberlord 2577 if (! isatty (STDIN_FILENO))
340     return (false);
341 uberlord 2547
342 uberlord 2577 /* Now save our terminal settings. We need to restore them at exit as we
343     will be changing it for non-blocking reads for Interactive */
344     if (! termios_orig) {
345     termios_orig = rc_xmalloc (sizeof (struct termios));
346     tcgetattr (STDIN_FILENO, termios_orig);
347     }
348 uberlord 2547
349 uberlord 2577 tcgetattr (STDIN_FILENO, &termios);
350     termios.c_lflag &= ~(ICANON | ECHO);
351     if (block)
352     termios.c_cc[VMIN] = 1;
353     else {
354     termios.c_cc[VMIN] = 0;
355     termios.c_cc[VTIME] = 0;
356     }
357     tcsetattr (STDIN_FILENO, TCSANOW, &termios);
358 uberlord 2547
359 uberlord 2577 read (STDIN_FILENO, &c, 1);
360 uberlord 2547
361 uberlord 2577 tcsetattr (STDIN_FILENO, TCSANOW, termios_orig);
362 uberlord 2547
363 uberlord 2577 return (c);
364 uberlord 2547 }
365    
366     static bool want_interactive (void)
367     {
368 uberlord 2577 char c = read_key (false);
369     return ((c == 'I' || c == 'i') ? true : false);
370 uberlord 2547 }
371    
372     static void mark_interactive (void)
373     {
374 uberlord 2577 FILE *fp = fopen (INTERACTIVE, "w");
375     if (fp)
376     fclose (fp);
377 uberlord 2547 }
378    
379     static void sulogin (bool cont)
380     {
381     #ifdef __linux__
382 uberlord 2638 char *e = getenv ("RC_SYS");
383    
384     /* VPS systems cannot do an sulogin */
385     if (e && strcmp (e, "VPS") == 0) {
386     execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
387     eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno));
388     }
389 uberlord 2641 #endif
390 uberlord 2638
391 uberlord 2652 newenv = rc_filter_env ();
392    
393 uberlord 2577 if (cont) {
394     int status = 0;
395 uberlord 2652 pid_t pid = vfork ();
396 uberlord 2547
397 uberlord 2577 if (pid == -1)
398 uberlord 2638 eerrorx ("%s: vfork: %s", applet, strerror (errno));
399 uberlord 2577 if (pid == 0) {
400 uberlord 2641 #ifdef __linux__
401 uberlord 2656 execle ("/sbin/sulogin", "/sbin/sulogin", (char *) NULL, newenv);
402 uberlord 2638 eerror ("%s: unable to exec `/sbin/sulogin': %s", applet,
403     strerror (errno));
404 uberlord 2641 #else
405     execle ("/bin/sh", "/bin/sh", (char *) NULL, newenv);
406     eerror ("%s: unable to exec `/bin/sh': %s", applet,
407     strerror (errno));
408     #endif
409 uberlord 2638 _exit (EXIT_FAILURE);
410 uberlord 2577 }
411     waitpid (pid, &status, 0);
412     } else {
413 uberlord 2641 #ifdef __linux
414 uberlord 2656 execle ("/sbin/sulogin", "/sbin/sulogin", (char *) NULL, newenv);
415 uberlord 2577 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno));
416 uberlord 2547 #else
417 uberlord 2641 exit (EXIT_SUCCESS);
418 uberlord 2547 #endif
419 uberlord 2641 }
420 uberlord 2547 }
421    
422 uberlord 2638 static void single_user (void)
423     {
424     #ifdef __linux__
425     execl ("/sbin/telinit", "/sbin/telinit", "S", (char *) NULL);
426     eerrorx ("%s: unable to exec `/sbin/telinit': %s",
427     applet, strerror (errno));
428     #else
429     if (kill (1, SIGTERM) != 0)
430     eerrorx ("%s: unable to send SIGTERM to init (pid 1): %s",
431     applet, strerror (errno));
432     exit (EXIT_SUCCESS);
433     #endif
434     }
435    
436 uberlord 2547 static void set_ksoftlevel (const char *runlevel)
437     {
438 uberlord 2577 FILE *fp;
439 uberlord 2547
440 uberlord 2577 if (! runlevel ||
441     strcmp (runlevel, RC_LEVEL_BOOT) == 0 ||
442     strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
443     strcmp (runlevel, RC_LEVEL_SYSINIT) == 0)
444     {
445     if (rc_exists (RC_SVCDIR "ksoftlevel") &&
446     unlink (RC_SVCDIR "ksoftlevel") != 0)
447     eerror ("unlink `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno));
448     return;
449     }
450 uberlord 2547
451 uberlord 2577 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "w"))) {
452     eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno));
453     return;
454     }
455 uberlord 2569
456 uberlord 2577 fprintf (fp, "%s", runlevel);
457     fclose (fp);
458 uberlord 2547 }
459    
460     static void wait_for_services ()
461     {
462 uberlord 2577 int status = 0;
463     while (wait (&status) != -1);
464 uberlord 2547 }
465    
466 uberlord 2641 static void add_pid (pid_t pid)
467     {
468     pidlist_t *sp = service_pids;
469     if (sp) {
470     while (sp->next)
471     sp = sp->next;
472     sp->next = rc_xmalloc (sizeof (pidlist_t));
473     sp = sp->next;
474     } else
475     sp = service_pids = rc_xmalloc (sizeof (pidlist_t));
476     memset (sp, 0, sizeof (pidlist_t));
477     sp->pid = pid;
478     }
479    
480     static void remove_pid (pid_t pid)
481     {
482     pidlist_t *last = NULL;
483     pidlist_t *pl;
484    
485     for (pl = service_pids; pl; pl = pl->next) {
486     if (pl->pid == pid) {
487     if (last)
488     last->next = pl->next;
489     else
490     service_pids = pl->next;
491     free (pl);
492     break;
493     }
494     last = pl;
495     }
496     }
497    
498 uberlord 2563 static void handle_signal (int sig)
499     {
500 uberlord 2577 int serrno = errno;
501     char signame[10] = { '\0' };
502 uberlord 2640 char *run;
503     char *prev;
504 uberlord 2641 pidlist_t *pl;
505     pid_t pid;
506     int status = 0;
507 uberlord 2563
508 uberlord 2577 switch (sig) {
509 uberlord 2641 case SIGCHLD:
510     do {
511     pid = waitpid (-1, &status, WNOHANG);
512     if (pid < 0) {
513     if (errno != ECHILD)
514     eerror ("waitpid: %s", strerror (errno));
515     return;
516     }
517     } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
518    
519     /* Remove that pid from our list */
520     if (pid > 0)
521     remove_pid (pid);
522     break;
523 uberlord 2642
524 uberlord 2577 case SIGINT:
525     if (! signame[0])
526     snprintf (signame, sizeof (signame), "SIGINT");
527     case SIGTERM:
528     if (! signame[0])
529     snprintf (signame, sizeof (signame), "SIGTERM");
530     case SIGQUIT:
531     if (! signame[0])
532     snprintf (signame, sizeof (signame), "SIGQUIT");
533     eerrorx ("%s: caught %s, aborting", applet, signame);
534 uberlord 2638 case SIGUSR1:
535     eerror ("rc: Aborting!");
536     /* Kill any running services we have started */
537 uberlord 2642
538 uberlord 2641 signal (SIGCHLD, SIG_IGN);
539     for (pl = service_pids; pl; pl = pl->next)
540     kill (pl->pid, SIGTERM);
541 uberlord 2642
542 uberlord 2640 /* Notify plugins we are aborting */
543 uberlord 2652 rc_plugin_run (rc_hook_abort, NULL);
544 uberlord 2642
545 uberlord 2641 /* Only drop into single user mode if we're booting */
546 uberlord 2640 run = getenv ("RUNLEVEL");
547     prev = getenv ("PREVLEVEL");
548     if ((prev && strcmp (prev, "S") == 0) ||
549 uberlord 2642 (run &&
550     (strcmp (run, "S") == 0 ||
551     strcmp (run, "1") == 0)))
552 uberlord 2638 single_user ();
553    
554     exit (EXIT_FAILURE);
555     break;
556    
557 uberlord 2577 default:
558     eerror ("%s: caught unknown signal %d", applet, sig);
559     }
560 uberlord 2563
561 uberlord 2577 /* Restore errno */
562     errno = serrno;
563 uberlord 2563 }
564    
565 uberlord 2547 int main (int argc, char **argv)
566     {
567 uberlord 2577 char *RUNLEVEL = NULL;
568     char *PREVLEVEL = NULL;
569     char *runlevel = NULL;
570     char *newlevel = NULL;
571     char *service = NULL;
572     char **deporder = NULL;
573     int i = 0;
574     int j = 0;
575     bool going_down = false;
576     bool interactive = false;
577     int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
578     char ksoftbuffer [PATH_MAX];
579 uberlord 2638 char pidstr[6];
580 uberlord 2547
581 uberlord 2577 if (argv[0])
582 uberlord 2634 applet = rc_xstrdup (basename (argv[0]));
583 uberlord 2547
584 uberlord 2577 if (! applet)
585     eerrorx ("arguments required");
586 uberlord 2547
587 uberlord 2577 argc--;
588     argv++;
589 uberlord 2547
590 uberlord 2577 /* Handle multicall stuff */
591     if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e'))
592     exit (do_e (argc, argv));
593 uberlord 2547
594 uberlord 2577 if (strncmp (applet, "service_", strlen ("service_")) == 0)
595     exit (do_service (argc, argv));
596 uberlord 2547
597 uberlord 2577 if (strcmp (applet, "get_options") == 0 ||
598     strcmp (applet, "save_options") == 0)
599     exit (do_options (argc, argv));
600 uberlord 2547
601 uberlord 2577 if (strncmp (applet, "mark_service_", strlen ("mark_service_")) == 0)
602     exit (do_mark_service (argc, argv));
603 uberlord 2547
604 uberlord 2577 if (strcmp (applet, "is_runlevel_start") == 0)
605     exit (rc_runlevel_starting () ? 0 : 1);
606     else if (strcmp (applet, "is_runlevel_stop") == 0)
607     exit (rc_runlevel_stopping () ? 0 : 1);
608 uberlord 2547
609 uberlord 2638 if (strcmp (applet, "rc-abort") == 0) {
610     char *p = getenv ("RC_PID");
611     pid_t pid = 0;
612    
613     if (p && sscanf (p, "%d", &pid) == 1) {
614     if (kill (pid, SIGUSR1) != 0)
615     eerrorx ("rc-abort: failed to signal parent %d: %s",
616     pid, strerror (errno));
617     exit (EXIT_SUCCESS);
618     }
619     exit (EXIT_FAILURE);
620     }
621    
622 uberlord 2577 if (strcmp (applet, "rc" ) != 0)
623     eerrorx ("%s: unknown applet", applet);
624 uberlord 2547
625 uberlord 2577 /* OK, so we really are the main RC process
626     Only root should be able to run us */
627     if (geteuid () != 0)
628     eerrorx ("%s: root access required", applet);
629 uberlord 2547
630 uberlord 2577 atexit (cleanup);
631     newlevel = argv[0];
632 uberlord 2547
633 uberlord 2577 /* Setup a signal handler */
634     signal (SIGINT, handle_signal);
635     signal (SIGQUIT, handle_signal);
636     signal (SIGTERM, handle_signal);
637 uberlord 2638 signal (SIGUSR1, handle_signal);
638 uberlord 2563
639 uberlord 2577 /* Ensure our environment is pure
640     Also, add our configuration to it */
641     env = rc_filter_env ();
642     env = rc_config_env (env);
643 uberlord 2547
644 uberlord 2577 if (env) {
645     char *p;
646 uberlord 2547
647     #ifdef __linux__
648 uberlord 2577 /* clearenv isn't portable, but there's no harm in using it
649     if we have it */
650     clearenv ();
651 uberlord 2547 #else
652 uberlord 2577 char *var;
653     /* No clearenv present here then.
654     We could manipulate environ directly ourselves, but it seems that
655     some kernels bitch about this according to the environ man pages
656     so we walk though environ and call unsetenv for each value. */
657     while (environ[0]) {
658     tmp = rc_xstrdup (environ[0]);
659     p = tmp;
660     var = strsep (&p, "=");
661     unsetenv (var);
662     free (tmp);
663     }
664     tmp = NULL;
665 uberlord 2547 #endif
666    
667 uberlord 2577 STRLIST_FOREACH (env, p, i)
668     if (strcmp (p, "RC_SOFTLEVEL") != 0 && strcmp (p, "SOFTLEVEL") != 0)
669     putenv (p);
670 uberlord 2547
671 uberlord 2577 /* We don't free our list as that would be null in environ */
672     }
673 uberlord 2547
674 uberlord 2577 /* Enable logging */
675     setenv ("RC_ELOG", "rc", 1);
676 uberlord 2547
677 uberlord 2638 /* Export our PID */
678     snprintf (pidstr, sizeof (pidstr), "%d", getpid ());
679     setenv ("RC_PID", pidstr, 1);
680    
681 uberlord 2577 interactive = rc_exists (INTERACTIVE);
682     rc_plugin_load ();
683 uberlord 2547
684 uberlord 2577 /* RUNLEVEL is set by sysvinit as is a magic number
685     RC_SOFTLEVEL is set by us and is the name for this magic number
686     even though all our userland documentation refers to runlevel */
687     RUNLEVEL = getenv ("RUNLEVEL");
688     PREVLEVEL = getenv ("PREVLEVEL");
689 uberlord 2547
690 uberlord 2577 if (RUNLEVEL && newlevel) {
691     if (strcmp (RUNLEVEL, "S") == 0 || strcmp (RUNLEVEL, "1") == 0) {
692     /* OK, we're either in runlevel 1 or single user mode */
693     if (strcmp (newlevel, RC_LEVEL_SYSINIT) == 0) {
694     struct utsname uts;
695     pid_t pid;
696     pid_t wpid;
697     int status = 0;
698 uberlord 2547 #ifdef __linux__
699 uberlord 2577 FILE *fp;
700 uberlord 2547 #endif
701    
702 uberlord 2577 uname (&uts);
703 uberlord 2547
704 uberlord 2577 printf ("\n");
705 uberlord 2615 printf (" %sGentoo/%s; %shttp://www.gentoo.org/%s"
706     "\n Copyright 1999-2007 Gentoo Foundation; "
707     "Distributed under the GPLv2\n\n",
708     ecolor (ecolor_good), uts.sysname, ecolor (ecolor_bracket),
709     ecolor (ecolor_normal));
710 uberlord 2547
711 uberlord 2615 printf ("Press %sI%s to enter interactive boot mode\n\n",
712     ecolor (ecolor_good), ecolor (ecolor_normal));
713 uberlord 2547
714 uberlord 2577 setenv ("RC_SOFTLEVEL", newlevel, 1);
715     rc_plugin_run (rc_hook_runlevel_start_in, newlevel);
716 uberlord 2547
717 uberlord 2638 if ((pid = vfork ()) == -1)
718     eerrorx ("%s: vfork: %s", applet, strerror (errno));
719 uberlord 2547
720 uberlord 2577 if (pid == 0) {
721 uberlord 2638 execl (INITSH, INITSH, (char *) NULL);
722     eerror ("%s: unable to exec `" INITSH "': %s",
723     applet, strerror (errno));
724     _exit (EXIT_FAILURE);
725 uberlord 2577 }
726 uberlord 2547
727 uberlord 2577 do {
728     wpid = waitpid (pid, &status, 0);
729     if (wpid < 1)
730     eerror ("waitpid: %s", strerror (errno));
731     } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
732 uberlord 2547
733 uberlord 2577 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0)
734     exit (EXIT_FAILURE);
735 uberlord 2547
736 uberlord 2577 /* If we requested a softlevel, save it now */
737 uberlord 2547 #ifdef __linux__
738 uberlord 2577 set_ksoftlevel (NULL);
739 uberlord 2547
740 uberlord 2577 if ((fp = fopen ("/proc/cmdline", "r"))) {
741     char buffer[RC_LINEBUFFER];
742     char *soft;
743 uberlord 2547
744 uberlord 2577 memset (buffer, 0, sizeof (buffer));
745     if (fgets (buffer, RC_LINEBUFFER, fp) &&
746     (soft = strstr (buffer, "softlevel=")))
747     {
748     i = soft - buffer;
749     if (i == 0 || buffer[i - 1] == ' ') {
750     char *level;
751 uberlord 2547
752 uberlord 2577 /* Trim the trailing carriage return if present */
753     i = strlen (buffer) - 1;
754     if (buffer[i] == '\n')
755     buffer[i] = 0;
756 uberlord 2547
757 uberlord 2577 soft += strlen ("softlevel=");
758     level = strsep (&soft, " ");
759     set_ksoftlevel (level);
760     }
761     }
762     fclose (fp);
763     }
764 uberlord 2547 #endif
765 uberlord 2577 rc_plugin_run (rc_hook_runlevel_start_out, newlevel);
766 uberlord 2547
767 uberlord 2577 if (want_interactive ())
768     mark_interactive ();
769 uberlord 2547
770 uberlord 2577 exit (EXIT_SUCCESS);
771     }
772 uberlord 2547
773     #ifdef __linux__
774 uberlord 2577 /* Parse the inittab file so we can work out the level to telinit */
775     if (strcmp (newlevel, RC_LEVEL_BOOT) != 0 &&
776     strcmp (newlevel, RC_LEVEL_SINGLE) != 0)
777     {
778     char **inittab = rc_get_list (NULL, "/etc/inittab");
779     char *line;
780     char *p;
781     char *token;
782     char lvl[2] = {0, 0};
783 uberlord 2547
784 uberlord 2577 STRLIST_FOREACH (inittab, line, i) {
785     p = line;
786     token = strsep (&p, ":");
787     if (! token || token[0] != 'l')
788     continue;
789 uberlord 2547
790 uberlord 2577 if ((token = strsep (&p, ":")) == NULL)
791     continue;
792 uberlord 2547
793 uberlord 2577 /* Snag the level */
794     lvl[0] = token[0];
795 uberlord 2547
796 uberlord 2577 /* The name is spaced after this */
797     if ((token = strsep (&p, " ")) == NULL)
798     continue;
799 uberlord 2547
800 uberlord 2577 if ((token = strsep (&p, " ")) == NULL)
801     continue;
802 uberlord 2569
803 uberlord 2577 if (strcmp (token, newlevel) == 0)
804     break;
805     }
806     rc_strlist_free (inittab);
807 uberlord 2569
808 uberlord 2577 /* We have a level, so telinit into it */
809     if (lvl[0] == 0) {
810     eerrorx ("%s: couldn't find a runlevel called `%s'",
811     applet, newlevel);
812     } else {
813 uberlord 2638 execl ("/sbin/telinit", "/sbin/telinit", lvl, (char *) NULL);
814 uberlord 2577 eerrorx ("%s: unable to exec `/sbin/telinit': %s",
815     applet, strerror (errno));
816     }
817     }
818 uberlord 2547 #endif
819 uberlord 2577 }
820     }
821 uberlord 2547
822 uberlord 2577 /* Check we're in the runlevel requested, ie from
823     rc single
824     rc shutdown
825     rc reboot
826     */
827     if (newlevel) {
828     if (strcmp (newlevel, RC_LEVEL_SINGLE) == 0) {
829     if (! RUNLEVEL ||
830     (strcmp (RUNLEVEL, "S") != 0 &&
831     strcmp (RUNLEVEL, "1") != 0))
832     {
833     /* Remember the current runlevel for when we come back */
834     set_ksoftlevel (runlevel);
835 uberlord 2638 single_user ();
836 uberlord 2577 }
837     } else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) {
838     if (! RUNLEVEL ||
839     strcmp (RUNLEVEL, "6") != 0)
840     {
841 uberlord 2638 execl ("/sbin/shutdown", "/sbin/shutdown", "-r", "now", (char *) NULL);
842     eerrorx ("%s: unable to exec `/sbin/shutdown': %s",
843     applet, strerror (errno));
844 uberlord 2577 }
845     } else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) {
846     if (! RUNLEVEL ||
847     strcmp (RUNLEVEL, "0") != 0)
848     {
849 uberlord 2638 execl ("/sbin/shutdown", "/sbin/shutdown",
850     #ifdef __linux
851     "-h",
852 uberlord 2547 #else
853 uberlord 2638 "-p",
854 uberlord 2547 #endif
855 uberlord 2638 "now", (char *) NULL);
856     eerrorx ("%s: unable to exec `/sbin/shutdown': %s",
857     applet, strerror (errno));
858 uberlord 2577 }
859     }
860     }
861 uberlord 2547
862 uberlord 2577 /* Export our current softlevel */
863     runlevel = rc_get_runlevel ();
864 uberlord 2547
865 uberlord 2641 /* Now we start handling our children */
866     signal (SIGCHLD, handle_signal);
867    
868 uberlord 2577 /* If we're in the default runlevel and ksoftlevel exists, we should use
869     that instead */
870     if (newlevel &&
871     rc_exists (RC_SVCDIR "ksoftlevel") &&
872     strcmp (newlevel, RC_LEVEL_DEFAULT) == 0)
873     {
874     /* We should only use ksoftlevel if we were in single user mode
875     If not, we need to erase ksoftlevel now. */
876     if (PREVLEVEL &&
877     (strcmp (PREVLEVEL, "1") == 0 ||
878     strcmp (PREVLEVEL, "S") == 0 ||
879     strcmp (PREVLEVEL, "N") == 0))
880     {
881     FILE *fp;
882 uberlord 2547
883 uberlord 2577 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "r")))
884     eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel",
885     strerror (errno));
886     else {
887     if (fgets (ksoftbuffer, sizeof (ksoftbuffer), fp)) {
888     i = strlen (ksoftbuffer) - 1;
889     if (ksoftbuffer[i] == '\n')
890     ksoftbuffer[i] = 0;
891     newlevel = ksoftbuffer;
892     }
893     fclose (fp);
894     }
895     } else
896     set_ksoftlevel (NULL);
897     }
898 uberlord 2547
899 uberlord 2577 if (newlevel &&
900     (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 ||
901     strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
902     strcmp (newlevel, RC_LEVEL_SINGLE) == 0))
903     {
904     going_down = true;
905     rc_set_runlevel (newlevel);
906     setenv ("RC_SOFTLEVEL", newlevel, 1);
907     rc_plugin_run (rc_hook_runlevel_stop_in, newlevel);
908     } else {
909     rc_plugin_run (rc_hook_runlevel_stop_in, runlevel);
910     }
911 uberlord 2547
912 uberlord 2577 /* Check if runlevel is valid if we're changing */
913     if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) {
914     tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel, (char *) NULL);
915     if (! rc_is_dir (tmp))
916     eerrorx ("%s: is not a valid runlevel", newlevel);
917     CHAR_FREE (tmp);
918     }
919 uberlord 2547
920 uberlord 2577 /* Load our deptree now */
921     if ((deptree = rc_load_deptree ()) == NULL)
922     eerrorx ("failed to load deptree");
923 uberlord 2547
924 uberlord 2577 /* Clean the failed services state dir now */
925     if (rc_is_dir (RC_SVCDIR "failed"))
926     rc_rm_dir (RC_SVCDIR "failed", false);
927 uberlord 2547
928 uberlord 2577 mkdir (RC_SVCDIR "/softscripts.new", 0755);
929 uberlord 2547
930     #ifdef __linux__
931 uberlord 2577 /* udev likes to start services before we're ready when it does
932     its coldplugging thing. runscript knows when we're not ready so it
933     stores a list of coldplugged services in DEVBOOT for us to pick up
934     here when we are ready for them */
935     if (rc_is_dir (DEVBOOT)) {
936     start_services = rc_ls_dir (NULL, DEVBOOT, RC_LS_INITD);
937     rc_rm_dir (DEVBOOT, true);
938 uberlord 2547
939 uberlord 2577 STRLIST_FOREACH (start_services, service, i)
940     if (rc_allow_plug (service))
941     rc_mark_service (service, rc_service_coldplugged);
942     /* We need to dump this list now.
943     This may seem redunant, but only Linux needs this and saves on
944     code bloat. */
945     rc_strlist_free (start_services);
946     start_services = NULL;
947     }
948 uberlord 2547 #else
949 uberlord 2577 /* BSD's on the other hand populate /dev automagically and use devd.
950     The only downside of this approach and ours is that we have to hard code
951     the device node to the init script to simulate the coldplug into
952     runlevel for our dependency tree to work. */
953     if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0 &&
954     (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
955     strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) &&
956     rc_is_env ("RC_COLDPLUG", "yes"))
957     {
958     /* The net interfaces are easy - they're all in net /dev/net :) */
959     start_services = rc_ls_dir (NULL, "/dev/net", 0);
960     STRLIST_FOREACH (start_services, service, i) {
961     j = (strlen ("net.") + strlen (service) + 1);
962     tmp = rc_xmalloc (sizeof (char *) * j);
963     snprintf (tmp, j, "net.%s", service);
964     if (rc_service_exists (tmp) && rc_allow_plug (tmp))
965     rc_mark_service (tmp, rc_service_coldplugged);
966     CHAR_FREE (tmp);
967     }
968     rc_strlist_free (start_services);
969 uberlord 2547
970 uberlord 2577 /* The mice are a little more tricky.
971     If we coldplug anything else, we'll probably do it here. */
972     start_services = rc_ls_dir (NULL, "/dev", 0);
973     STRLIST_FOREACH (start_services, service, i) {
974     if (strncmp (service, "psm", 3) == 0 ||
975     strncmp (service, "ums", 3) == 0)
976     {
977     char *p = service + 3;
978     if (p && isdigit (*p)) {
979     j = (strlen ("moused.") + strlen (service) + 1);
980     tmp = rc_xmalloc (sizeof (char *) * j);
981     snprintf (tmp, j, "moused.%s", service);
982     if (rc_service_exists (tmp) && rc_allow_plug (tmp))
983     rc_mark_service (tmp, rc_service_coldplugged);
984     CHAR_FREE (tmp);
985     }
986     }
987     }
988     rc_strlist_free (start_services);
989     start_services = NULL;
990     }
991 uberlord 2547 #endif
992    
993 uberlord 2577 /* Build a list of all services to stop and then work out the
994     correct order for stopping them */
995     stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTING, RC_LS_INITD);
996     stop_services = rc_ls_dir (stop_services, RC_SVCDIR_INACTIVE, RC_LS_INITD);
997     stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTED, RC_LS_INITD);
998 uberlord 2547
999 uberlord 2577 types = rc_strlist_add (NULL, "ineed");
1000     types = rc_strlist_add (types, "iuse");
1001     types = rc_strlist_add (types, "iafter");
1002     deporder = rc_get_depends (deptree, types, stop_services,
1003     runlevel, depoptions);
1004     rc_strlist_free (stop_services);
1005     rc_strlist_free (types);
1006     stop_services = deporder;
1007     deporder = NULL;
1008     types = NULL;
1009     rc_strlist_reverse (stop_services);
1010 uberlord 2547
1011 uberlord 2577 /* Load our list of coldplugged services */
1012     coldplugged_services = rc_ls_dir (coldplugged_services,
1013     RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
1014 uberlord 2547
1015 uberlord 2577 /* Load our start services now.
1016     We have different rules dependent on runlevel. */
1017     if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0) {
1018     if (coldplugged_services) {
1019     einfon ("Device initiated services:");
1020     STRLIST_FOREACH (coldplugged_services, service, i) {
1021     printf (" %s", service);
1022     start_services = rc_strlist_add (start_services, service);
1023     }
1024     printf ("\n");
1025     }
1026     tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel,
1027     (char *) NULL);
1028     start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD);
1029     CHAR_FREE (tmp);
1030     } else {
1031     /* Store our list of coldplugged services */
1032     coldplugged_services = rc_ls_dir (coldplugged_services, RC_SVCDIR_COLDPLUGGED,
1033     RC_LS_INITD);
1034     if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
1035     strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
1036     strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
1037     {
1038     /* We need to include the boot runlevel services if we're not in it */
1039     start_services = rc_ls_dir (start_services, RC_RUNLEVELDIR RC_LEVEL_BOOT,
1040     RC_LS_INITD);
1041     STRLIST_FOREACH (coldplugged_services, service, i)
1042     start_services = rc_strlist_add (start_services, service);
1043 uberlord 2547
1044 uberlord 2577 tmp = rc_strcatpaths (RC_RUNLEVELDIR,
1045     newlevel ? newlevel : runlevel, (char *) NULL);
1046     start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD);
1047     CHAR_FREE (tmp);
1048     }
1049     }
1050 uberlord 2547
1051 uberlord 2577 /* Save out softlevel now */
1052     if (going_down)
1053     rc_set_runlevel (newlevel);
1054 uberlord 2547
1055 uberlord 2577 types = rc_strlist_add (NULL, "needsme");
1056     types = rc_strlist_add (types, "usesme");
1057     /* Now stop the services that shouldn't be running */
1058     STRLIST_FOREACH (stop_services, service, i) {
1059     bool found = false;
1060     char *conf = NULL;
1061     char **stopdeps = NULL;
1062     char *svc1 = NULL;
1063     char *svc2 = NULL;
1064     int k;
1065 uberlord 2547
1066 uberlord 2577 if (rc_service_state (service, rc_service_stopped))
1067     continue;
1068 uberlord 2547
1069 uberlord 2577 /* We always stop the service when in these runlevels */
1070     if (going_down) {
1071 uberlord 2641 pid_t pid = rc_stop_service (service);
1072 uberlord 2650 if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes"))
1073 uberlord 2641 rc_waitpid (pid);
1074 uberlord 2577 }
1075 uberlord 2547
1076 uberlord 2577 /* If we're in the start list then don't bother stopping us */
1077     STRLIST_FOREACH (start_services, svc1, j)
1078     if (strcmp (svc1, service) == 0) {
1079     found = true;
1080     break;
1081     }
1082 uberlord 2547
1083 uberlord 2577 /* Unless we would use a different config file */
1084     if (found) {
1085     int len;
1086     if (! newlevel)
1087     continue;
1088 uberlord 2550
1089 uberlord 2577 len = strlen (service) + strlen (runlevel) + 2;
1090     tmp = rc_xmalloc (sizeof (char *) * len);
1091     snprintf (tmp, len, "%s.%s", service, runlevel);
1092     conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1093     found = rc_exists (conf);
1094     CHAR_FREE (conf);
1095     CHAR_FREE (tmp);
1096     if (! found) {
1097     len = strlen (service) + strlen (newlevel) + 2;
1098     tmp = rc_xmalloc (sizeof (char *) * len);
1099     snprintf (tmp, len, "%s.%s", service, newlevel);
1100     conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1101     found = rc_exists (conf);
1102     CHAR_FREE (conf);
1103     CHAR_FREE (tmp);
1104     if (!found)
1105     continue;
1106     }
1107     } else {
1108     /* Allow coldplugged services not to be in the runlevels list */
1109     if (rc_service_state (service, rc_service_coldplugged))
1110     continue;
1111     }
1112 uberlord 2547
1113 uberlord 2577 /* We got this far! Or last check is to see if any any service that
1114     going to be started depends on us */
1115     stopdeps = rc_strlist_add (stopdeps, service);
1116     deporder = rc_get_depends (deptree, types, stopdeps,
1117     runlevel, RC_DEP_STRICT);
1118     rc_strlist_free (stopdeps);
1119     stopdeps = NULL;
1120     found = false;
1121     STRLIST_FOREACH (deporder, svc1, j) {
1122     STRLIST_FOREACH (start_services, svc2, k)
1123     if (strcmp (svc1, svc2) == 0) {
1124     found = true;
1125     break;
1126     }
1127     if (found)
1128     break;
1129     }
1130     rc_strlist_free (deporder);
1131     deporder = NULL;
1132 uberlord 2547
1133 uberlord 2577 /* After all that we can finally stop the blighter! */
1134 uberlord 2641 if (! found) {
1135     pid_t pid = rc_stop_service (service);
1136 uberlord 2650 if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes"))
1137 uberlord 2641 rc_waitpid (pid);
1138     }
1139 uberlord 2577 }
1140     rc_strlist_free (types);
1141     types = NULL;
1142 uberlord 2547
1143 uberlord 2577 /* Wait for our services to finish */
1144 uberlord 2641 wait_for_services ();
1145 uberlord 2547
1146 uberlord 2577 /* Notify the plugins we have finished */
1147     rc_plugin_run (rc_hook_runlevel_stop_out, runlevel);
1148 uberlord 2547
1149 uberlord 2577 rmdir (RC_SVCDIR "/softscripts.new");
1150 uberlord 2547
1151 uberlord 2577 /* Store the new runlevel */
1152     if (newlevel) {
1153     rc_set_runlevel (newlevel);
1154     runlevel = newlevel;
1155     setenv ("RC_SOFTLEVEL", runlevel, 1);
1156     }
1157 uberlord 2547
1158 uberlord 2577 /* Run the halt script if needed */
1159     if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
1160     strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
1161     {
1162 uberlord 2638 execl (HALTSH, HALTSH, runlevel, (char *) NULL);
1163 uberlord 2577 eerrorx ("%s: unable to exec `%s': %s",
1164     applet, HALTSH, strerror (errno));
1165     }
1166 uberlord 2547
1167 uberlord 2577 /* Single user is done now */
1168     if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) {
1169     if (rc_exists (INTERACTIVE))
1170     unlink (INTERACTIVE);
1171     sulogin (false);
1172     }
1173 uberlord 2547
1174 uberlord 2577 mkdir (RC_SVCDIR "softscripts.old", 0755);
1175     rc_plugin_run (rc_hook_runlevel_start_in, runlevel);
1176 uberlord 2547
1177 uberlord 2577 /* Re-add our coldplugged services if they stopped */
1178     STRLIST_FOREACH (coldplugged_services, service, i)
1179     rc_mark_service (service, rc_service_coldplugged);
1180 uberlord 2547
1181 uberlord 2577 /* Order the services to start */
1182     types = rc_strlist_add (NULL, "ineed");
1183     types = rc_strlist_add (types, "iuse");
1184     types = rc_strlist_add (types, "iafter");
1185     deporder = rc_get_depends (deptree, types, start_services,
1186     runlevel, depoptions);
1187     rc_strlist_free (types);
1188     types = NULL;
1189     rc_strlist_free (start_services);
1190     start_services = deporder;
1191     deporder = NULL;
1192 uberlord 2547
1193 uberlord 2577 STRLIST_FOREACH (start_services, service, i) {
1194     if (rc_service_state (service, rc_service_stopped)) {
1195 uberlord 2641 pid_t pid;
1196    
1197 uberlord 2577 if (! interactive)
1198     interactive = want_interactive ();
1199 uberlord 2547
1200 uberlord 2577 if (interactive) {
1201 uberlord 2547 interactive_retry:
1202 uberlord 2577 printf ("\n");
1203     einfo ("About to start the service %s", service);
1204     eindent ();
1205     einfo ("1) Start the service\t\t2) Skip the service");
1206     einfo ("3) Continue boot process\t\t4) Exit to shell");
1207     eoutdent ();
1208 uberlord 2547 interactive_option:
1209 uberlord 2577 switch (read_key (true)) {
1210     case '1': break;
1211     case '2': continue;
1212     case '3': interactive = false; break;
1213     case '4': sulogin (true); goto interactive_retry;
1214     default: goto interactive_option;
1215     }
1216     }
1217 uberlord 2641
1218     /* Remember the pid if we're running in parallel */
1219     if ((pid = rc_start_service (service)))
1220     add_pid (pid);
1221    
1222 uberlord 2650 if (! rc_is_env ("RC_PARALLEL", "yes")) {
1223 uberlord 2641 rc_waitpid (pid);
1224     remove_pid (pid);
1225     }
1226 uberlord 2577 }
1227     }
1228 uberlord 2547
1229 uberlord 2577 /* Wait for our services to finish */
1230 uberlord 2636 wait_for_services ();
1231 uberlord 2547
1232 uberlord 2577 rc_plugin_run (rc_hook_runlevel_start_out, runlevel);
1233 uberlord 2547
1234 uberlord 2577 /* Store our interactive status for boot */
1235     if (interactive && strcmp (runlevel, RC_LEVEL_BOOT) == 0)
1236     mark_interactive ();
1237     else {
1238     if (rc_exists (INTERACTIVE))
1239     unlink (INTERACTIVE);
1240     }
1241 uberlord 2547
1242 uberlord 2577 return (EXIT_SUCCESS);
1243 uberlord 2547 }
1244    

  ViewVC Help
Powered by ViewVC 1.1.20