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

Diff of /trunk/src/rc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.2760  
changed lines
  Added in v.3040

  ViewVC Help
Powered by ViewVC 1.1.20