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

Contents of /trunk/src/rc.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20