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

Contents of /trunk/src/rc.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20