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

Contents of /trunk/src/rc.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20