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

Diff of /trunk/src/rc.c

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

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

Legend:
Removed from v.2815  
changed lines
  Added in v.3036

  ViewVC Help
Powered by ViewVC 1.1.20