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

Diff of /trunk/src/rc.c

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.20