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

Contents of /trunk/src/rc.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20