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

Diff of /trunk/src/rc.c

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

Revision 2713 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 INITEARLYSH RC_LIBDIR "sh/init-early.sh" 46#define INITEARLYSH RC_LIBDIR "/sh/init-early.sh"
38#define HALTSH RC_INITDIR "halt.sh" 47#define HALTSH RC_INITDIR "/halt.sh"
48
49#define SHUTDOWN "/sbin/shutdown"
39#define SULOGIN "/sbin/sulogin" 50#define SULOGIN "/sbin/sulogin"
40 51
41#define RC_SVCDIR_STARTING RC_SVCDIR "starting/"
42#define RC_SVCDIR_INACTIVE RC_SVCDIR "inactive/"
43#define RC_SVCDIR_STARTED RC_SVCDIR "started/"
44#define RC_SVCDIR_COLDPLUGGED RC_SVCDIR "coldplugged/"
45
46#define INTERACTIVE RC_SVCDIR "interactive" 52#define INTERACTIVE RC_SVCDIR "/interactive"
47 53
48#define DEVBOOT "/dev/.rcboot" 54#define DEVBOOT "/dev/.rcboot"
49 55
50/* Cleanup anything in main */ 56/* Cleanup anything in main */
51#define CHAR_FREE(_item) if (_item) { \ 57#define CHAR_FREE(_item) if (_item) { \
53 _item = NULL; \ 59 _item = NULL; \
54} 60}
55 61
56extern char **environ; 62extern char **environ;
57 63
64static char *RUNLEVEL = NULL;
65static char *PREVLEVEL = NULL;
66
58static char *applet = NULL; 67static char *applet = NULL;
68static char *runlevel = NULL;
59static char **env = NULL; 69static char **env = NULL;
60static char **newenv = NULL; 70static char **newenv = NULL;
61static char **coldplugged_services = NULL; 71static char **coldplugged_services = NULL;
62static char **stop_services = NULL; 72static char **stop_services = NULL;
63static char **start_services = NULL; 73static char **start_services = NULL;
64static rc_depinfo_t *deptree = NULL; 74static rc_depinfo_t *deptree = NULL;
65static char **types = NULL;
66static char *tmp = NULL; 75static char *tmp = NULL;
67 76
68struct termios *termios_orig = NULL; 77struct termios *termios_orig = NULL;
69 78
70typedef struct pidlist 79typedef struct pidlist
72 pid_t pid; 81 pid_t pid;
73 struct pidlist *next; 82 struct pidlist *next;
74} pidlist_t; 83} pidlist_t;
75static pidlist_t *service_pids = NULL; 84static pidlist_t *service_pids = NULL;
76 85
86static const char *types_n[] = { "needsme", NULL };
87static const char *types_nua[] = { "ineed", "iuse", "iafter", NULL };
88
77static void cleanup (void) 89static void cleanup (void)
78{ 90{
91 if (applet && strcmp (applet, "rc") == 0) {
79 pidlist_t *pl = service_pids; 92 pidlist_t *pl = service_pids;
80 93
81 rc_plugin_unload (); 94 rc_plugin_unload ();
82 95
83 if (termios_orig) { 96 if (! rc_in_plugin && termios_orig) {
84 tcsetattr (STDIN_FILENO, TCSANOW, termios_orig); 97 tcsetattr (fileno (stdin), TCSANOW, termios_orig);
85 free (termios_orig); 98 free (termios_orig);
86 } 99 }
87 100
88 while (pl) { 101 while (pl) {
89 pidlist_t *p = pl->next; 102 pidlist_t *p = pl->next;
90 free (pl); 103 free (pl);
91 pl = p; 104 pl = p;
92 } 105 }
93 106
94 rc_strlist_free (env); 107 rc_strlist_free (env);
95 rc_strlist_free (newenv); 108 rc_strlist_free (newenv);
96 rc_strlist_free (coldplugged_services); 109 rc_strlist_free (coldplugged_services);
97 rc_strlist_free (stop_services); 110 rc_strlist_free (stop_services);
98 rc_strlist_free (start_services); 111 rc_strlist_free (start_services);
99 rc_free_deptree (deptree); 112 rc_deptree_free (deptree);
100 rc_strlist_free (types);
101 113
102 /* Clean runlevel start, stop markers */ 114 /* Clean runlevel start, stop markers */
103 if (rc_is_dir (RC_SVCDIR "softscripts.new")) 115 if (! rc_in_plugin) {
104 rc_rm_dir (RC_SVCDIR "softscripts.new", true); 116 rmdir (RC_STARTING);
105 if (rc_is_dir (RC_SVCDIR "softscripts.old")) 117 rmdir (RC_STOPPING);
106 rc_rm_dir (RC_SVCDIR "softscripts.old", true); 118 }
119
120 free (runlevel);
121 }
107 122
108 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);
109} 138}
110 139
111static int do_e (int argc, char **argv) 140static int do_e (int argc, char **argv)
112{ 141{
113 int retval = EXIT_SUCCESS; 142 int retval = EXIT_SUCCESS;
114 int i; 143 int i;
115 int l = 0; 144 int l = 0;
116 char *message = NULL; 145 char *message = NULL;
117 char *p; 146 char *p;
118 char *fmt = NULL; 147 char *fmt = NULL;
148 int level = 0;
119 149
120 if (strcmp (applet, "eval_ecolors") == 0) { 150 if (strcmp (applet, "eval_ecolors") == 0) {
121 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",
122 ecolor (ecolor_good), 152 ecolor (ECOLOR_GOOD),
123 ecolor (ecolor_warn), 153 ecolor (ECOLOR_WARN),
124 ecolor (ecolor_bad), 154 ecolor (ECOLOR_BAD),
125 ecolor (ecolor_hilite), 155 ecolor (ECOLOR_HILITE),
126 ecolor (ecolor_bracket), 156 ecolor (ECOLOR_BRACKET),
127 ecolor (ecolor_normal)); 157 ecolor (ECOLOR_NORMAL));
128 exit (EXIT_SUCCESS); 158 exit (EXIT_SUCCESS);
129 } 159 }
130 160
161 if (argc > 0) {
162
131 if (strcmp (applet, "eend") == 0 || 163 if (strcmp (applet, "eend") == 0 ||
132 strcmp (applet, "ewend") == 0 || 164 strcmp (applet, "ewend") == 0 ||
133 strcmp (applet, "veend") == 0 || 165 strcmp (applet, "veend") == 0 ||
134 strcmp (applet, "vweend") == 0) 166 strcmp (applet, "vweend") == 0)
135 { 167 {
136 if (argc > 0) {
137 errno = 0; 168 errno = 0;
138 retval = strtol (argv[0], NULL, 0); 169 retval = strtol (argv[0], NULL, 0);
139 if (errno != 0) 170 if (errno != 0)
140 retval = EXIT_FAILURE; 171 retval = EXIT_FAILURE;
141 else { 172 else {
142 argc--; 173 argc--;
143 argv++; 174 argv++;
144 } 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;
145 } 190 }
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{
368 char c; 460 char c;
369 461
462 if (PREVLEVEL &&
463 strcmp (PREVLEVEL, "N") != 0 &&
464 strcmp (PREVLEVEL, "S") != 0 &&
465 strcmp (PREVLEVEL, "1") != 0)
466 return (false);
467
370 if (! rc_is_env ("RC_INTERACTIVE", "yes")) 468 if (! rc_env_bool ("RC_INTERACTIVE"))
371 return (false); 469 return (false);
372 470
373 c = read_key (false); 471 c = read_key (false);
374 return ((c == 'I' || c == 'i') ? true : false); 472 return ((c == 'I' || c == 'i') ? true : false);
375} 473}
391 execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); 489 execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
392 eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno)); 490 eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno));
393 } 491 }
394#endif 492#endif
395 493
396 newenv = rc_filter_env (); 494 newenv = env_filter ();
397 495
398 if (cont) { 496 if (cont) {
399 int status = 0; 497 int status = 0;
400#ifdef __linux__ 498#ifdef __linux__
401 char *tty = ttyname (fileno (stdout)); 499 char *tty = ttyname (fileno (stdout));
421#endif 519#endif
422 _exit (EXIT_FAILURE); 520 _exit (EXIT_FAILURE);
423 } 521 }
424 waitpid (pid, &status, 0); 522 waitpid (pid, &status, 0);
425 } else { 523 } else {
426#ifdef __linux 524#ifdef __linux__
427 execle ("/sbin/sulogin", "/sbin/sulogin", (char *) NULL, newenv); 525 execle ("/sbin/sulogin", "/sbin/sulogin", (char *) NULL, newenv);
428 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno)); 526 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno));
429#else 527#else
430 exit (EXIT_SUCCESS); 528 exit (EXIT_SUCCESS);
431#endif 529#endif
444 applet, strerror (errno)); 542 applet, strerror (errno));
445 exit (EXIT_SUCCESS); 543 exit (EXIT_SUCCESS);
446#endif 544#endif
447} 545}
448 546
449static void set_ksoftlevel (const char *runlevel) 547static void set_ksoftlevel (const char *level)
450{ 548{
451 FILE *fp; 549 FILE *fp;
452 550
453 if (! runlevel || 551 if (! level ||
454 strcmp (runlevel, RC_LEVEL_BOOT) == 0 || 552 strcmp (level, getenv ("RC_BOOTLEVEL")) == 0 ||
455 strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 553 strcmp (level, RC_LEVEL_SINGLE) == 0 ||
456 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) 554 strcmp (level, RC_LEVEL_SYSINIT) == 0)
457 { 555 {
458 if (rc_exists (RC_SVCDIR "ksoftlevel") && 556 if (exists (RC_KSOFTLEVEL) &&
459 unlink (RC_SVCDIR "ksoftlevel") != 0) 557 unlink (RC_KSOFTLEVEL) != 0)
460 eerror ("unlink `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno)); 558 eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno));
461 return; 559 return;
462 } 560 }
463 561
464 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "w"))) { 562 if (! (fp = fopen (RC_KSOFTLEVEL, "w"))) {
465 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno)); 563 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno));
466 return; 564 return;
467 } 565 }
468 566
469 fprintf (fp, "%s", runlevel); 567 fprintf (fp, "%s", level);
470 fclose (fp); 568 fclose (fp);
569}
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);
471} 592}
472 593
473static void wait_for_services () 594static void wait_for_services ()
474{ 595{
475 int status = 0; 596 int status = 0;
480{ 601{
481 pidlist_t *sp = service_pids; 602 pidlist_t *sp = service_pids;
482 if (sp) { 603 if (sp) {
483 while (sp->next) 604 while (sp->next)
484 sp = sp->next; 605 sp = sp->next;
485 sp->next = rc_xmalloc (sizeof (pidlist_t)); 606 sp->next = xmalloc (sizeof (pidlist_t));
486 sp = sp->next; 607 sp = sp->next;
487 } else 608 } else
488 sp = service_pids = rc_xmalloc (sizeof (pidlist_t)); 609 sp = service_pids = xmalloc (sizeof (pidlist_t));
489 memset (sp, 0, sizeof (pidlist_t)); 610 memset (sp, 0, sizeof (pidlist_t));
490 sp->pid = pid; 611 sp->pid = pid;
491} 612}
492 613
493static void remove_pid (pid_t pid) 614static void remove_pid (pid_t pid)
506 } 627 }
507 last = pl; 628 last = pl;
508 } 629 }
509} 630}
510 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
511static void handle_signal (int sig) 647static void handle_signal (int sig)
512{ 648{
513 int serrno = errno; 649 int serrno = errno;
514 char signame[10] = { '\0' }; 650 char signame[10] = { '\0' };
515 char *run;
516 char *prev;
517 pidlist_t *pl; 651 pidlist_t *pl;
518 pid_t pid; 652 pid_t pid;
519 int status = 0; 653 int status = 0;
520 654
521 switch (sig) { 655 switch (sig) {
551 signal (SIGCHLD, SIG_IGN); 685 signal (SIGCHLD, SIG_IGN);
552 for (pl = service_pids; pl; pl = pl->next) 686 for (pl = service_pids; pl; pl = pl->next)
553 kill (pl->pid, SIGTERM); 687 kill (pl->pid, SIGTERM);
554 688
555 /* Notify plugins we are aborting */ 689 /* Notify plugins we are aborting */
556 rc_plugin_run (rc_hook_abort, NULL); 690 rc_plugin_run (RC_HOOK_ABORT, NULL);
557 691
558 /* Only drop into single user mode if we're booting */ 692 /* Only drop into single user mode if we're booting */
559 run = getenv ("RUNLEVEL"); 693 if ((PREVLEVEL &&
560 prev = getenv ("PREVLEVEL"); 694 (strcmp (PREVLEVEL, "S") == 0 ||
561 if ((prev && 695 strcmp (PREVLEVEL, "1") == 0)) ||
696 (RUNLEVEL &&
562 (strcmp (prev, "S") == 0 || 697 (strcmp (RUNLEVEL, "S") == 0 ||
563 strcmp (prev, "1") == 0)) ||
564 (run &&
565 (strcmp (run, "S") == 0 ||
566 strcmp (run, "1") == 0))) 698 strcmp (RUNLEVEL, "1") == 0)))
567 single_user (); 699 single_user ();
568 700
569 exit (EXIT_FAILURE); 701 exit (EXIT_FAILURE);
570 break; 702 break;
571 703
578} 710}
579 711
580static void run_script (const char *script) { 712static void run_script (const char *script) {
581 int status = 0; 713 int status = 0;
582 pid_t pid = vfork (); 714 pid_t pid = vfork ();
583 715
584 if (pid < 0) 716 if (pid < 0)
585 eerrorx ("%s: vfork: %s", applet, strerror (errno)); 717 eerrorx ("%s: vfork: %s", applet, strerror (errno));
586 else if (pid == 0) { 718 else if (pid == 0) {
587 execl (script, script, (char *) NULL); 719 execl (script, script, (char *) NULL);
588 eerror ("%s: unable to exec `%s': %s", 720 eerror ("%s: unable to exec `%s': %s",
595 if (wpid < 1) 727 if (wpid < 1)
596 eerror ("waitpid: %s", strerror (errno)); 728 eerror ("waitpid: %s", strerror (errno));
597 } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); 729 } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
598 730
599 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0) 731 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0)
600 exit (EXIT_FAILURE); 732 eerrorx ("%s: failed to exec `%s'", applet, script);
601} 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"
602 744
603int main (int argc, char **argv) 745int main (int argc, char **argv)
604{ 746{
605 char *RUNLEVEL = NULL;
606 char *PREVLEVEL = NULL;
607 char *runlevel = NULL; 747 const char *bootlevel = NULL;
608 char *newlevel = NULL; 748 char *newlevel = NULL;
609 char *service = NULL; 749 char *service = NULL;
610 char **deporder = NULL; 750 char **deporder = NULL;
751 char **tmplist;
611 int i = 0; 752 int i = 0;
612 int j = 0; 753 int j = 0;
613 bool going_down = false; 754 bool going_down = false;
614 bool interactive = false; 755 bool interactive = false;
615 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE; 756 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
616 char ksoftbuffer [PATH_MAX]; 757 char ksoftbuffer [PATH_MAX];
617 char pidstr[6]; 758 char pidstr[6];
759 int opt;
760 DIR *dp;
761 struct dirent *d;
618 762
763 atexit (cleanup);
619 if (argv[0]) 764 if (argv[0])
620 applet = rc_xstrdup (basename (argv[0])); 765 applet = xstrdup (basename (argv[0]));
621 766
622 if (! applet) 767 if (! applet)
623 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));
624 791
625 argc--; 792 argc--;
626 argv++; 793 argv++;
627 794
628 /* Handle multicall stuff */ 795 /* Handle multicall stuff */
658 } 825 }
659 826
660 if (strcmp (applet, "rc" ) != 0) 827 if (strcmp (applet, "rc" ) != 0)
661 eerrorx ("%s: unknown applet", applet); 828 eerrorx ("%s: unknown applet", applet);
662 829
663 /* OK, so we really are the main RC process 830 /* Change dir to / to ensure all scripts don't use stuff in pwd */
664 Only root should be able to run us */ 831 chdir ("/");
665 if (geteuid () != 0)
666 eerrorx ("%s: root access required", applet);
667 832
668 atexit (cleanup); 833 /* RUNLEVEL is set by sysvinit as is a magic number
669 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");
670 838
671 /* Setup a signal handler */ 839 /* Setup a signal handler */
672 signal (SIGINT, handle_signal); 840 signal (SIGINT, handle_signal);
673 signal (SIGQUIT, handle_signal); 841 signal (SIGQUIT, handle_signal);
674 signal (SIGTERM, handle_signal); 842 signal (SIGTERM, handle_signal);
675 signal (SIGUSR1, handle_signal); 843 signal (SIGUSR1, handle_signal);
676 844
677 /* Ensure our environment is pure 845 /* Ensure our environment is pure
678 Also, add our configuration to it */ 846 Also, add our configuration to it */
679 env = rc_filter_env (); 847 env = env_filter ();
680 env = rc_config_env (env); 848 tmplist = env_config ();
849 rc_strlist_join (&env, tmplist);
850 rc_strlist_free (tmplist);
681 851
682 if (env) { 852 if (env) {
683 char *p; 853 char *p;
684 854
685#ifdef __linux__ 855#ifdef __linux__
691 /* No clearenv present here then. 861 /* No clearenv present here then.
692 We could manipulate environ directly ourselves, but it seems that 862 We could manipulate environ directly ourselves, but it seems that
693 some kernels bitch about this according to the environ man pages 863 some kernels bitch about this according to the environ man pages
694 so we walk though environ and call unsetenv for each value. */ 864 so we walk though environ and call unsetenv for each value. */
695 while (environ[0]) { 865 while (environ[0]) {
696 tmp = rc_xstrdup (environ[0]); 866 tmp = xstrdup (environ[0]);
697 p = tmp; 867 p = tmp;
698 var = strsep (&p, "="); 868 var = strsep (&p, "=");
699 unsetenv (var); 869 unsetenv (var);
700 free (tmp); 870 free (tmp);
701 } 871 }
707 putenv (p); 877 putenv (p);
708 878
709 /* 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 */
710 } 880 }
711 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
712 /* Enable logging */ 899 /* Enable logging */
713 setenv ("RC_ELOG", "rc", 1); 900 setenv ("RC_ELOG", "rc", 1);
714 901
715 /* Export our PID */ 902 /* Export our PID */
716 snprintf (pidstr, sizeof (pidstr), "%d", getpid ()); 903 snprintf (pidstr, sizeof (pidstr), "%d", getpid ());
717 setenv ("RC_PID", pidstr, 1); 904 setenv ("RC_PID", pidstr, 1);
718 905
719 interactive = rc_exists (INTERACTIVE); 906 interactive = exists (INTERACTIVE);
720 rc_plugin_load (); 907 rc_plugin_load ();
721 908
722 /* RUNLEVEL is set by sysvinit as is a magic number 909 /* Load current softlevel */
723 RC_SOFTLEVEL is set by us and is the name for this magic number 910 bootlevel = getenv ("RC_BOOTLEVEL");
724 even though all our userland documentation refers to runlevel */ 911 runlevel = rc_runlevel_get ();
725 RUNLEVEL = getenv ("RUNLEVEL");
726 PREVLEVEL = getenv ("PREVLEVEL");
727
728 if (RUNLEVEL && newlevel) {
729 if (strcmp (RUNLEVEL, "S") == 0 || strcmp (RUNLEVEL, "1") == 0) {
730 /* OK, we're either in runlevel 1 or single user mode */
731 if (strcmp (newlevel, RC_LEVEL_SYSINIT) == 0) {
732 struct utsname uts;
733#ifdef __linux__
734 FILE *fp;
735#endif
736
737 /* exec init-early.sh if it exists
738 * This should just setup the console to use the correct
739 * font. Maybe it should setup the keyboard too? */
740 if (rc_exists (INITEARLYSH))
741 run_script (INITEARLYSH);
742
743 uname (&uts);
744
745 printf ("\n");
746 printf (" %sGentoo/%s; %shttp://www.gentoo.org/%s"
747 "\n Copyright 1999-2007 Gentoo Foundation; "
748 "Distributed under the GPLv2\n\n",
749 ecolor (ecolor_good), uts.sysname, ecolor (ecolor_bracket),
750 ecolor (ecolor_normal));
751
752 if (rc_is_env ("RC_INTERACTIVE", "yes"))
753 printf ("Press %sI%s to enter interactive boot mode\n\n",
754 ecolor (ecolor_good), ecolor (ecolor_normal));
755
756 setenv ("RC_SOFTLEVEL", newlevel, 1);
757 rc_plugin_run (rc_hook_runlevel_start_in, newlevel);
758 run_script (INITSH);
759
760 /* If we requested a softlevel, save it now */
761#ifdef __linux__
762 set_ksoftlevel (NULL);
763
764 if ((fp = fopen ("/proc/cmdline", "r"))) {
765 char buffer[RC_LINEBUFFER];
766 char *soft;
767
768 memset (buffer, 0, sizeof (buffer));
769 if (fgets (buffer, RC_LINEBUFFER, fp) &&
770 (soft = strstr (buffer, "softlevel=")))
771 {
772 i = soft - buffer;
773 if (i == 0 || buffer[i - 1] == ' ') {
774 char *level;
775
776 /* Trim the trailing carriage return if present */
777 i = strlen (buffer) - 1;
778 if (buffer[i] == '\n')
779 buffer[i] = 0;
780
781 soft += strlen ("softlevel=");
782 level = strsep (&soft, " ");
783 set_ksoftlevel (level);
784 }
785 }
786 fclose (fp);
787 }
788#endif
789 rc_plugin_run (rc_hook_runlevel_start_out, newlevel);
790
791 if (want_interactive ())
792 mark_interactive ();
793
794 exit (EXIT_SUCCESS);
795 }
796
797#ifdef __linux__
798 /* Parse the inittab file so we can work out the level to telinit */
799 if (strcmp (newlevel, RC_LEVEL_BOOT) != 0 &&
800 strcmp (newlevel, RC_LEVEL_SINGLE) != 0)
801 {
802 char **inittab = rc_get_list (NULL, "/etc/inittab");
803 char *line;
804 char *p;
805 char *token;
806 char lvl[2] = {0, 0};
807
808 STRLIST_FOREACH (inittab, line, i) {
809 p = line;
810 token = strsep (&p, ":");
811 if (! token || token[0] != 'l')
812 continue;
813
814 if ((token = strsep (&p, ":")) == NULL)
815 continue;
816
817 /* Snag the level */
818 lvl[0] = token[0];
819
820 /* The name is spaced after this */
821 if ((token = strsep (&p, " ")) == NULL)
822 continue;
823
824 if ((token = strsep (&p, " ")) == NULL)
825 continue;
826
827 if (strcmp (token, newlevel) == 0)
828 break;
829 }
830 rc_strlist_free (inittab);
831
832 /* We have a level, so telinit into it */
833 if (lvl[0] == 0) {
834 eerrorx ("%s: couldn't find a runlevel called `%s'",
835 applet, newlevel);
836 } else {
837 execl ("/sbin/telinit", "/sbin/telinit", lvl, (char *) NULL);
838 eerrorx ("%s: unable to exec `/sbin/telinit': %s",
839 applet, strerror (errno));
840 }
841 }
842#endif
843 }
844 }
845 912
846 /* Check we're in the runlevel requested, ie from 913 /* Check we're in the runlevel requested, ie from
847 rc single 914 rc single
848 rc shutdown 915 rc shutdown
849 rc reboot 916 rc reboot
850 */ 917 */
851 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);
852 if (strcmp (newlevel, RC_LEVEL_SINGLE) == 0) { 968 } else if (strcmp (newlevel, RC_LEVEL_SINGLE) == 0) {
853 if (! RUNLEVEL || 969 if (! RUNLEVEL ||
854 (strcmp (RUNLEVEL, "S") != 0 && 970 (strcmp (RUNLEVEL, "S") != 0 &&
855 strcmp (RUNLEVEL, "1") != 0)) 971 strcmp (RUNLEVEL, "1") != 0))
856 { 972 {
857 /* Remember the current runlevel for when we come back */ 973 /* Remember the current runlevel for when we come back */
860 } 976 }
861 } else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) { 977 } else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) {
862 if (! RUNLEVEL || 978 if (! RUNLEVEL ||
863 strcmp (RUNLEVEL, "6") != 0) 979 strcmp (RUNLEVEL, "6") != 0)
864 { 980 {
865 execl ("/sbin/shutdown", "/sbin/shutdown", "-r", "now", (char *) NULL); 981 execl (SHUTDOWN, SHUTDOWN, "-r", "now", (char *) NULL);
866 eerrorx ("%s: unable to exec `/sbin/shutdown': %s", 982 eerrorx ("%s: unable to exec `" SHUTDOWN "': %s",
867 applet, strerror (errno)); 983 applet, strerror (errno));
868 } 984 }
869 } else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) { 985 } else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) {
870 if (! RUNLEVEL || 986 if (! RUNLEVEL ||
871 strcmp (RUNLEVEL, "0") != 0) 987 strcmp (RUNLEVEL, "0") != 0)
872 { 988 {
873 execl ("/sbin/shutdown", "/sbin/shutdown", 989 execl (SHUTDOWN, SHUTDOWN,
874#ifdef __linux 990#ifdef __linux__
875 "-h", 991 "-h",
876#else 992#else
877 "-p", 993 "-p",
878#endif 994#endif
879 "now", (char *) NULL); 995 "now", (char *) NULL);
880 eerrorx ("%s: unable to exec `/sbin/shutdown': %s", 996 eerrorx ("%s: unable to exec `" SHUTDOWN "': %s",
881 applet, strerror (errno)); 997 applet, strerror (errno));
882 } 998 }
883 } 999 }
884 } 1000 }
885 1001
886 /* Export our current softlevel */
887 runlevel = rc_get_runlevel ();
888
889 /* Now we start handling our children */ 1002 /* Now we start handling our children */
890 signal (SIGCHLD, handle_signal); 1003 signal (SIGCHLD, handle_signal);
891 1004
892 /* 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
893 that instead */ 1006 If not, we need to erase ksoftlevel now. */
894 if (newlevel && 1007 if (PREVLEVEL &&
895 rc_exists (RC_SVCDIR "ksoftlevel") && 1008 (strcmp (PREVLEVEL, "1") == 0 ||
896 strcmp (newlevel, RC_LEVEL_DEFAULT) == 0) 1009 strcmp (PREVLEVEL, "S") == 0 ||
1010 strcmp (PREVLEVEL, "N") == 0))
897 { 1011 {
898 /* We should only use ksoftlevel if we were in single user mode 1012 /* Try not to join boot and ksoftlevels together */
899 If not, we need to erase ksoftlevel now. */ 1013 if (! newlevel ||
900 if (PREVLEVEL && 1014 strcmp (newlevel, getenv ("RC_BOOTLEVEL")) != 0)
901 (strcmp (PREVLEVEL, "1") == 0 ||
902 strcmp (PREVLEVEL, "S") == 0 ||
903 strcmp (PREVLEVEL, "N") == 0))
904 {
905 FILE *fp;
906
907 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "r")))
908 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel",
909 strerror (errno));
910 else {
911 if (fgets (ksoftbuffer, sizeof (ksoftbuffer), fp)) { 1015 if (get_ksoftlevel (ksoftbuffer, sizeof (ksoftbuffer)))
912 i = strlen (ksoftbuffer) - 1;
913 if (ksoftbuffer[i] == '\n')
914 ksoftbuffer[i] = 0;
915 newlevel = ksoftbuffer; 1016 newlevel = ksoftbuffer;
916 } 1017 } else if (! RUNLEVEL ||
917 fclose (fp); 1018 (strcmp (RUNLEVEL, "1") != 0 &&
918 } 1019 strcmp (RUNLEVEL, "S") != 0 &&
919 } else 1020 strcmp (RUNLEVEL, "N") != 0))
1021 {
920 set_ksoftlevel (NULL); 1022 set_ksoftlevel (NULL);
921 } 1023 }
922 1024
923 if (newlevel && 1025 if (newlevel &&
924 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 || 1026 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 ||
925 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 || 1027 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
926 strcmp (newlevel, RC_LEVEL_SINGLE) == 0)) 1028 strcmp (newlevel, RC_LEVEL_SINGLE) == 0))
927 { 1029 {
928 going_down = true; 1030 going_down = true;
929 rc_set_runlevel (newlevel); 1031 rc_runlevel_set (newlevel);
930 setenv ("RC_SOFTLEVEL", newlevel, 1); 1032 setenv ("RC_SOFTLEVEL", newlevel, 1);
931 rc_plugin_run (rc_hook_runlevel_stop_in, newlevel); 1033 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, newlevel);
932 } else { 1034 } else {
933 rc_plugin_run (rc_hook_runlevel_stop_in, runlevel); 1035 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, runlevel);
934 } 1036 }
935 1037
936 /* Check if runlevel is valid if we're changing */ 1038 /* Check if runlevel is valid if we're changing */
937 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) { 1039 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) {
938 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel, (char *) NULL); 1040 if (! rc_runlevel_exists (newlevel))
939 if (! rc_is_dir (tmp))
940 eerrorx ("%s: is not a valid runlevel", newlevel); 1041 eerrorx ("%s: is not a valid runlevel", newlevel);
941 CHAR_FREE (tmp);
942 } 1042 }
943 1043
944 /* Load our deptree now */ 1044 /* Load our deptree now */
945 if ((deptree = rc_load_deptree ()) == NULL) 1045 if ((deptree = _rc_deptree_load ()) == NULL)
946 eerrorx ("failed to load deptree"); 1046 eerrorx ("failed to load deptree");
947 1047
948 /* Clean the failed services state dir now */ 1048 /* Clean the failed services state dir now */
949 if (rc_is_dir (RC_SVCDIR "failed")) 1049 if ((dp = opendir (RC_SVCDIR "/failed"))) {
950 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;
951 1055
952 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);
953 1068
954#ifdef __linux__ 1069#ifdef __linux__
955 /* 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
956 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
957 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
958 here when we are ready for them */ 1073 here when we are ready for them */
959 if (rc_is_dir (DEVBOOT)) { 1074 if ((dp = opendir (DEVBOOT))) {
960 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);
961 rc_rm_dir (DEVBOOT, true); 1094 rmdir (DEVBOOT);
962
963 STRLIST_FOREACH (start_services, service, i)
964 if (rc_allow_plug (service))
965 rc_mark_service (service, rc_service_coldplugged);
966 /* We need to dump this list now.
967 This may seem redunant, but only Linux needs this and saves on
968 code bloat. */
969 rc_strlist_free (start_services);
970 start_services = NULL;
971 } 1095 }
972#else 1096#else
973 /* 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.
974 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
975 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
976 runlevel for our dependency tree to work. */ 1100 runlevel for our dependency tree to work. */
977 if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0 && 1101 if (newlevel && strcmp (newlevel, bootlevel) == 0 &&
978 (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 1102 (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
979 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) && 1103 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) &&
980 rc_is_env ("RC_COLDPLUG", "yes")) 1104 rc_env_bool ("RC_COLDPLUG"))
981 { 1105 {
1106#if defined(__DragonFly__) || defined(__FreeBSD__)
982 /* 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 :) */
983 start_services = rc_ls_dir (NULL, "/dev/net", 0); 1108 if ((dp = opendir ("/dev/net"))) {
984 STRLIST_FOREACH (start_services, service, i) { 1109 while ((d = readdir (dp))) {
985 j = (strlen ("net.") + strlen (service) + 1); 1110 i = (strlen ("net.") + strlen (d->d_name) + 1);
986 tmp = rc_xmalloc (sizeof (char *) * j); 1111 tmp = xmalloc (sizeof (char) * i);
987 snprintf (tmp, j, "net.%s", service); 1112 snprintf (tmp, i, "net.%s", d->d_name);
988 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 1113 if (rc_service_exists (tmp) &&
989 rc_mark_service (tmp, rc_service_coldplugged); 1114 rc_service_plugable (tmp))
1115 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
990 CHAR_FREE (tmp); 1116 CHAR_FREE (tmp);
991 } 1117 }
992 rc_strlist_free (start_services); 1118 closedir (dp);
1119 }
1120#endif
993 1121
994 /* The mice are a little more tricky. 1122 /* The mice are a little more tricky.
995 If we coldplug anything else, we'll probably do it here. */ 1123 If we coldplug anything else, we'll probably do it here. */
996 start_services = rc_ls_dir (NULL, "/dev", 0); 1124 if ((dp == opendir ("/dev"))) {
997 STRLIST_FOREACH (start_services, service, i) { 1125 while ((d = readdir (dp))) {
998 if (strncmp (service, "psm", 3) == 0 || 1126 if (strncmp (d->d_name, "psm", 3) == 0 ||
999 strncmp (service, "ums", 3) == 0) 1127 strncmp (d->d_name, "ums", 3) == 0)
1000 { 1128 {
1001 char *p = service + 3; 1129 char *p = d->d_name + 3;
1002 if (p && isdigit (*p)) { 1130 if (p && isdigit (*p)) {
1003 j = (strlen ("moused.") + strlen (service) + 1); 1131 i = (strlen ("moused.") + strlen (d->d_name) + 1);
1004 tmp = rc_xmalloc (sizeof (char *) * j); 1132 tmp = xmalloc (sizeof (char) * i);
1005 snprintf (tmp, j, "moused.%s", service); 1133 snprintf (tmp, i, "moused.%s", d->d_name);
1006 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 1134 if (rc_service_exists (tmp) && rc_service_plugable (tmp))
1007 rc_mark_service (tmp, rc_service_coldplugged); 1135 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
1008 CHAR_FREE (tmp); 1136 CHAR_FREE (tmp);
1137 }
1009 } 1138 }
1010 } 1139 }
1140 closedir (dp);
1011 } 1141 }
1012 rc_strlist_free (start_services);
1013 start_services = NULL;
1014 } 1142 }
1015#endif 1143#endif
1016 1144
1017 /* 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
1018 correct order for stopping them */ 1146 correct order for stopping them */
1019 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTING, RC_LS_INITD); 1147 stop_services = rc_services_in_state (RC_SERVICE_STARTING);
1020 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_INACTIVE, RC_LS_INITD);
1021 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTED, RC_LS_INITD);
1022 1148
1023 types = rc_strlist_add (NULL, "ineed"); 1149 tmplist = rc_services_in_state (RC_SERVICE_INACTIVE);
1024 types = rc_strlist_add (types, "iuse"); 1150 rc_strlist_join (&stop_services, tmplist);
1025 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
1026 deporder = rc_get_depends (deptree, types, stop_services, 1157 deporder = rc_deptree_depends (deptree, types_nua,
1158 (const char **) stop_services,
1027 runlevel, depoptions); 1159 runlevel, depoptions | RC_DEP_STOP);
1160
1028 rc_strlist_free (stop_services); 1161 rc_strlist_free (stop_services);
1029 rc_strlist_free (types);
1030 stop_services = deporder; 1162 stop_services = deporder;
1031 deporder = NULL; 1163 deporder = NULL;
1032 types = NULL;
1033 rc_strlist_reverse (stop_services); 1164 rc_strlist_reverse (stop_services);
1034 1165
1035 /* Load our list of coldplugged services */ 1166 /* Load our list of coldplugged services */
1036 coldplugged_services = rc_ls_dir (coldplugged_services, 1167 coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
1037 RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
1038 1168
1039 /* Load our start services now. 1169 /* Load our start services now.
1040 We have different rules dependent on runlevel. */ 1170 We have different rules dependent on runlevel. */
1041 if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0) { 1171 if (newlevel && strcmp (newlevel, bootlevel) == 0) {
1042 if (coldplugged_services) { 1172 if (coldplugged_services) {
1043 einfon ("Device initiated services:"); 1173 einfon ("Device initiated services:");
1044 STRLIST_FOREACH (coldplugged_services, service, i) { 1174 STRLIST_FOREACH (coldplugged_services, service, i) {
1045 printf (" %s", service); 1175 printf (" %s", service);
1046 start_services = rc_strlist_add (start_services, service); 1176 rc_strlist_add (&start_services, service);
1047 } 1177 }
1048 printf ("\n"); 1178 printf ("\n");
1049 } 1179 }
1050 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel, 1180 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
1051 (char *) NULL); 1181 rc_strlist_join (&start_services, tmplist);
1052 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD); 1182 rc_strlist_free (tmplist);
1053 CHAR_FREE (tmp);
1054 } else { 1183 } else {
1055 /* Store our list of coldplugged services */ 1184 /* Store our list of coldplugged services */
1056 coldplugged_services = rc_ls_dir (coldplugged_services, RC_SVCDIR_COLDPLUGGED, 1185 tmplist = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
1057 RC_LS_INITD); 1186 rc_strlist_join (&coldplugged_services, tmplist);
1187 rc_strlist_free (tmplist);
1058 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && 1188 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
1059 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && 1189 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
1060 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) 1190 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
1061 { 1191 {
1062 /* 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 */
1063 start_services = rc_ls_dir (start_services, RC_RUNLEVELDIR RC_LEVEL_BOOT, 1193 tmplist = rc_services_in_runlevel (bootlevel);
1064 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
1065 STRLIST_FOREACH (coldplugged_services, service, i) 1200 STRLIST_FOREACH (coldplugged_services, service, i)
1066 start_services = rc_strlist_add (start_services, service); 1201 rc_strlist_add (&start_services, service);
1067 1202
1068 tmp = rc_strcatpaths (RC_RUNLEVELDIR,
1069 newlevel ? newlevel : runlevel, (char *) NULL);
1070 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD);
1071 CHAR_FREE (tmp);
1072 } 1203 }
1073 } 1204 }
1074 1205
1075 /* Save out softlevel now */ 1206 /* Save out softlevel now */
1076 if (going_down) 1207 if (going_down)
1077 rc_set_runlevel (newlevel); 1208 rc_runlevel_set (newlevel);
1078 1209
1079 types = rc_strlist_add (NULL, "needsme");
1080 types = rc_strlist_add (types, "usesme");
1081 /* Now stop the services that shouldn't be running */ 1210 /* Now stop the services that shouldn't be running */
1082 STRLIST_FOREACH (stop_services, service, i) { 1211 STRLIST_FOREACH (stop_services, service, i) {
1083 bool found = false; 1212 bool found = false;
1084 char *conf = NULL; 1213 char *conf = NULL;
1085 char **stopdeps = NULL; 1214 char **stopdeps = NULL;
1086 char *svc1 = NULL; 1215 char *svc1 = NULL;
1087 char *svc2 = NULL; 1216 char *svc2 = NULL;
1088 int k; 1217 int k;
1089 1218
1090 if (rc_service_state (service, rc_service_stopped)) 1219 if (rc_service_state (service) & RC_SERVICE_STOPPED)
1091 continue; 1220 continue;
1092 1221
1093 /* We always stop the service when in these runlevels */ 1222 /* We always stop the service when in these runlevels */
1094 if (going_down) { 1223 if (going_down) {
1095 pid_t pid = rc_stop_service (service); 1224 pid_t pid = rc_service_stop (service);
1096 if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes")) 1225 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL"))
1097 rc_waitpid (pid); 1226 wait_pid (pid);
1098 continue; 1227 continue;
1099 } 1228 }
1100 1229
1101 /* 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 */
1102 STRLIST_FOREACH (start_services, svc1, j) 1231 STRLIST_FOREACH (start_services, svc1, j)
1110 int len; 1239 int len;
1111 if (! newlevel) 1240 if (! newlevel)
1112 continue; 1241 continue;
1113 1242
1114 len = strlen (service) + strlen (runlevel) + 2; 1243 len = strlen (service) + strlen (runlevel) + 2;
1115 tmp = rc_xmalloc (sizeof (char *) * len); 1244 tmp = xmalloc (sizeof (char) * len);
1116 snprintf (tmp, len, "%s.%s", service, runlevel); 1245 snprintf (tmp, len, "%s.%s", service, runlevel);
1117 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1246 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1118 found = rc_exists (conf); 1247 found = exists (conf);
1119 CHAR_FREE (conf); 1248 CHAR_FREE (conf);
1120 CHAR_FREE (tmp); 1249 CHAR_FREE (tmp);
1121 if (! found) { 1250 if (! found) {
1122 len = strlen (service) + strlen (newlevel) + 2; 1251 len = strlen (service) + strlen (newlevel) + 2;
1123 tmp = rc_xmalloc (sizeof (char *) * len); 1252 tmp = xmalloc (sizeof (char) * len);
1124 snprintf (tmp, len, "%s.%s", service, newlevel); 1253 snprintf (tmp, len, "%s.%s", service, newlevel);
1125 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1254 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1126 found = rc_exists (conf); 1255 found = exists (conf);
1127 CHAR_FREE (conf); 1256 CHAR_FREE (conf);
1128 CHAR_FREE (tmp); 1257 CHAR_FREE (tmp);
1129 if (!found) 1258 if (!found)
1130 continue; 1259 continue;
1131 } 1260 }
1132 } else { 1261 } else {
1133 /* Allow coldplugged services not to be in the runlevels list */ 1262 /* Allow coldplugged services not to be in the runlevels list */
1134 if (rc_service_state (service, rc_service_coldplugged)) 1263 if (rc_service_state (service) & RC_SERVICE_COLDPLUGGED)
1135 continue; 1264 continue;
1136 } 1265 }
1137 1266
1138 /* 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
1139 going to be started depends on us */ 1268 going to be started depends on us */
1140 stopdeps = rc_strlist_add (stopdeps, service); 1269 rc_strlist_add (&stopdeps, service);
1141 deporder = rc_get_depends (deptree, types, stopdeps, 1270 deporder = rc_deptree_depends (deptree, types_n,
1271 (const char **) stopdeps,
1142 runlevel, RC_DEP_STRICT); 1272 runlevel, RC_DEP_STRICT);
1143 rc_strlist_free (stopdeps); 1273 rc_strlist_free (stopdeps);
1144 stopdeps = NULL; 1274 stopdeps = NULL;
1145 found = false; 1275 found = false;
1146 STRLIST_FOREACH (deporder, svc1, j) { 1276 STRLIST_FOREACH (deporder, svc1, j) {
1147 STRLIST_FOREACH (start_services, svc2, k) 1277 STRLIST_FOREACH (start_services, svc2, k)
1155 rc_strlist_free (deporder); 1285 rc_strlist_free (deporder);
1156 deporder = NULL; 1286 deporder = NULL;
1157 1287
1158 /* After all that we can finally stop the blighter! */ 1288 /* After all that we can finally stop the blighter! */
1159 if (! found) { 1289 if (! found) {
1160 pid_t pid = rc_stop_service (service); 1290 pid_t pid = rc_service_stop (service);
1161 if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes")) 1291 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL"))
1162 rc_waitpid (pid); 1292 wait_pid (pid);
1163 }
1164 } 1293 }
1165 rc_strlist_free (types); 1294 }
1166 types = NULL;
1167 1295
1168 /* Wait for our services to finish */ 1296 /* Wait for our services to finish */
1169 wait_for_services (); 1297 wait_for_services ();
1170 1298
1171 /* Notify the plugins we have finished */ 1299 /* Notify the plugins we have finished */
1172 rc_plugin_run (rc_hook_runlevel_stop_out, runlevel); 1300 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_OUT, runlevel);
1173 1301
1174 rmdir (RC_SVCDIR "/softscripts.new"); 1302 rmdir (RC_STOPPING);
1175 1303
1176 /* Store the new runlevel */ 1304 /* Store the new runlevel */
1177 if (newlevel) { 1305 if (newlevel) {
1178 rc_set_runlevel (newlevel); 1306 rc_runlevel_set (newlevel);
1307 free (runlevel);
1179 runlevel = newlevel; 1308 runlevel = xstrdup (newlevel);
1180 setenv ("RC_SOFTLEVEL", runlevel, 1); 1309 setenv ("RC_SOFTLEVEL", runlevel, 1);
1181 } 1310 }
1182 1311
1183 /* Run the halt script if needed */ 1312 /* Run the halt script if needed */
1184 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 || 1313 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
1189 applet, HALTSH, strerror (errno)); 1318 applet, HALTSH, strerror (errno));
1190 } 1319 }
1191 1320
1192 /* Single user is done now */ 1321 /* Single user is done now */
1193 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) { 1322 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) {
1194 if (rc_exists (INTERACTIVE)) 1323 if (exists (INTERACTIVE))
1195 unlink (INTERACTIVE); 1324 unlink (INTERACTIVE);
1196 sulogin (false); 1325 sulogin (false);
1197 } 1326 }
1198 1327
1199 mkdir (RC_SVCDIR "softscripts.old", 0755); 1328 mkdir (RC_STARTING, 0755);
1200 rc_plugin_run (rc_hook_runlevel_start_in, runlevel); 1329 rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, runlevel);
1201 1330
1202 /* Re-add our coldplugged services if they stopped */ 1331 /* Re-add our coldplugged services if they stopped */
1203 STRLIST_FOREACH (coldplugged_services, service, i) 1332 STRLIST_FOREACH (coldplugged_services, service, i)
1204 rc_mark_service (service, rc_service_coldplugged); 1333 rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
1205 1334
1206 /* Order the services to start */ 1335 /* Order the services to start */
1207 types = rc_strlist_add (NULL, "ineed");
1208 types = rc_strlist_add (types, "iuse");
1209 types = rc_strlist_add (types, "iafter");
1210 deporder = rc_get_depends (deptree, types, start_services, 1336 deporder = rc_deptree_depends (deptree, types_nua,
1337 (const char **) start_services,
1211 runlevel, depoptions); 1338 runlevel, depoptions | RC_DEP_START);
1212 rc_strlist_free (types);
1213 types = NULL;
1214 rc_strlist_free (start_services); 1339 rc_strlist_free (start_services);
1215 start_services = deporder; 1340 start_services = deporder;
1216 deporder = NULL; 1341 deporder = NULL;
1217 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
1218 STRLIST_FOREACH (start_services, service, i) { 1358 STRLIST_FOREACH (start_services, service, i) {
1219 if (rc_service_state (service, rc_service_stopped)) { 1359 if (rc_service_state (service) & RC_SERVICE_STOPPED) {
1220 pid_t pid; 1360 pid_t pid;
1221 1361
1222 if (! interactive) 1362 if (! interactive)
1223 interactive = want_interactive (); 1363 interactive = want_interactive ();
1224 1364
1239 default: goto interactive_option; 1379 default: goto interactive_option;
1240 } 1380 }
1241 } 1381 }
1242 1382
1243 /* Remember the pid if we're running in parallel */ 1383 /* Remember the pid if we're running in parallel */
1244 if ((pid = rc_start_service (service))) 1384 if ((pid = rc_service_start (service)))
1245 add_pid (pid); 1385 add_pid (pid);
1246 1386
1247 if (! rc_is_env ("RC_PARALLEL", "yes")) { 1387 if (! rc_env_bool ("RC_PARALLEL")) {
1248 rc_waitpid (pid); 1388 wait_pid (pid);
1249 remove_pid (pid); 1389 remove_pid (pid);
1250 } 1390 }
1251 } 1391 }
1252 } 1392 }
1253 1393
1254 /* Wait for our services to finish */ 1394 /* Wait for our services to finish */
1255 wait_for_services (); 1395 wait_for_services ();
1256 1396
1257 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
1258 1412
1259 /* Store our interactive status for boot */ 1413 /* Store our interactive status for boot */
1260 if (interactive && strcmp (runlevel, RC_LEVEL_BOOT) == 0) 1414 if (interactive && strcmp (runlevel, bootlevel) == 0)
1261 mark_interactive (); 1415 mark_interactive ();
1262 else { 1416 else {
1263 if (rc_exists (INTERACTIVE)) 1417 if (exists (INTERACTIVE))
1264 unlink (INTERACTIVE); 1418 unlink (INTERACTIVE);
1265 } 1419 }
1266 1420
1267 return (EXIT_SUCCESS); 1421 return (EXIT_SUCCESS);
1268} 1422}

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

  ViewVC Help
Powered by ViewVC 1.1.20