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

Contents of /trunk/src/rc.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20