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

Diff of /trunk/src/rc.c

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

Revision 2897 Revision 3036
18#include <sys/types.h> 18#include <sys/types.h>
19#include <sys/stat.h> 19#include <sys/stat.h>
20#include <sys/utsname.h> 20#include <sys/utsname.h>
21#include <sys/wait.h> 21#include <sys/wait.h>
22#include <errno.h> 22#include <errno.h>
23#include <dirent.h>
23#include <ctype.h> 24#include <ctype.h>
24#include <getopt.h> 25#include <getopt.h>
25#include <libgen.h> 26#include <libgen.h>
26#include <limits.h> 27#include <limits.h>
27#include <stdbool.h> 28#include <stdbool.h>
28#include <stdio.h> 29#include <stdio.h>
29#include <stdlib.h> 30#include <stdlib.h>
30#include <signal.h> 31#include <signal.h>
31#include <string.h> 32#include <string.h>
33#include <strings.h>
32#include <syslog.h> 34#include <syslog.h>
33#include <termios.h> 35#include <termios.h>
34#include <unistd.h> 36#include <unistd.h>
35 37
36#include "builtins.h" 38#include "builtins.h"
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_STARTING))
113 rc_rm_dir (RC_STARTING, true); 115 rmdir (RC_STARTING);
114 if (rc_is_dir (RC_STOPPING))
115 rc_rm_dir (RC_STOPPING, true); 116 rmdir (RC_STOPPING);
116 } 117 }
118
119 free (runlevel);
117 } 120 }
118 121
119 free (applet); 122 free (applet);
120} 123}
121 124
143 char *fmt = NULL; 146 char *fmt = NULL;
144 int level = 0; 147 int level = 0;
145 148
146 if (strcmp (applet, "eval_ecolors") == 0) { 149 if (strcmp (applet, "eval_ecolors") == 0) {
147 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",
148 ecolor (ecolor_good), 151 ecolor (ECOLOR_GOOD),
149 ecolor (ecolor_warn), 152 ecolor (ECOLOR_WARN),
150 ecolor (ecolor_bad), 153 ecolor (ECOLOR_BAD),
151 ecolor (ecolor_hilite), 154 ecolor (ECOLOR_HILITE),
152 ecolor (ecolor_bracket), 155 ecolor (ECOLOR_BRACKET),
153 ecolor (ecolor_normal)); 156 ecolor (ECOLOR_NORMAL));
154 exit (EXIT_SUCCESS); 157 exit (EXIT_SUCCESS);
155 } 158 }
156 159
157 if (argc > 0) { 160 if (argc > 0) {
158 161
188 191
189 if (argc > 0) { 192 if (argc > 0) {
190 for (i = 0; i < argc; i++) 193 for (i = 0; i < argc; i++)
191 l += strlen (argv[i]) + 1; 194 l += strlen (argv[i]) + 1;
192 195
193 message = rc_xmalloc (l); 196 message = xmalloc (l);
194 p = message; 197 p = message;
195 198
196 for (i = 0; i < argc; i++) { 199 for (i = 0; i < argc; i++) {
197 if (i > 0) 200 if (i > 0)
198 *p++ = ' '; 201 *p++ = ' ';
201 } 204 }
202 *p = 0; 205 *p = 0;
203 } 206 }
204 207
205 if (message) 208 if (message)
206 fmt = rc_xstrdup ("%s"); 209 fmt = xstrdup ("%s");
207 210
208 if (strcmp (applet, "einfo") == 0) 211 if (strcmp (applet, "einfo") == 0)
209 einfo (fmt, message); 212 einfo (fmt, message);
210 else if (strcmp (applet, "einfon") == 0) 213 else if (strcmp (applet, "einfon") == 0)
211 einfon (fmt, message); 214 einfon (fmt, message);
267 270
268 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 271 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
269 eerrorx ("%s: no service specified", applet); 272 eerrorx ("%s: no service specified", applet);
270 273
271 if (strcmp (applet, "service_started") == 0) 274 if (strcmp (applet, "service_started") == 0)
272 ok = rc_service_state (argv[0], rc_service_started); 275 ok = (rc_service_state (argv[0]) & RC_SERVICE_STARTED);
273 else if (strcmp (applet, "service_stopped") == 0) 276 else if (strcmp (applet, "service_stopped") == 0)
274 ok = rc_service_state (argv[0], rc_service_stopped); 277 ok = (rc_service_state (argv[0]) & RC_SERVICE_STOPPED);
275 else if (strcmp (applet, "service_inactive") == 0) 278 else if (strcmp (applet, "service_inactive") == 0)
276 ok = rc_service_state (argv[0], rc_service_inactive); 279 ok = (rc_service_state (argv[0]) & RC_SERVICE_INACTIVE);
277 else if (strcmp (applet, "service_starting") == 0) 280 else if (strcmp (applet, "service_starting") == 0)
278 ok = rc_service_state (argv[0], rc_service_starting); 281 ok = (rc_service_state (argv[0]) & RC_SERVICE_STOPPING);
279 else if (strcmp (applet, "service_stopping") == 0) 282 else if (strcmp (applet, "service_stopping") == 0)
280 ok = rc_service_state (argv[0], rc_service_stopping); 283 ok = (rc_service_state (argv[0]) & RC_SERVICE_STOPPING);
281 else if (strcmp (applet, "service_coldplugged") == 0) 284 else if (strcmp (applet, "service_coldplugged") == 0)
282 ok = rc_service_state (argv[0], rc_service_coldplugged); 285 ok = (rc_service_state (argv[0]) & RC_SERVICE_COLDPLUGGED);
283 else if (strcmp (applet, "service_wasinactive") == 0) 286 else if (strcmp (applet, "service_wasinactive") == 0)
284 ok = rc_service_state (argv[0], rc_service_wasinactive); 287 ok = (rc_service_state (argv[0]) & RC_SERVICE_WASINACTIVE);
285 else if (strcmp (applet, "service_started_daemon") == 0) { 288 else if (strcmp (applet, "service_started_daemon") == 0) {
286 int idx = 0; 289 int idx = 0;
287 if (argc > 2) 290 if (argc > 2)
288 sscanf (argv[2], "%d", &idx); 291 sscanf (argv[2], "%d", &idx);
289 exit (rc_service_started_daemon (argv[0], argv[1], idx) 292 exit (rc_service_started_daemon (argv[0], argv[1], idx)
301 304
302 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 305 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
303 eerrorx ("%s: no service specified", applet); 306 eerrorx ("%s: no service specified", applet);
304 307
305 if (strcmp (applet, "mark_service_started") == 0) 308 if (strcmp (applet, "mark_service_started") == 0)
306 ok = rc_mark_service (argv[0], rc_service_started); 309 ok = rc_service_mark (argv[0], RC_SERVICE_STARTED);
307 else if (strcmp (applet, "mark_service_stopped") == 0) 310 else if (strcmp (applet, "mark_service_stopped") == 0)
308 ok = rc_mark_service (argv[0], rc_service_stopped); 311 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPED);
309 else if (strcmp (applet, "mark_service_inactive") == 0) 312 else if (strcmp (applet, "mark_service_inactive") == 0)
310 ok = rc_mark_service (argv[0], rc_service_inactive); 313 ok = rc_service_mark (argv[0], RC_SERVICE_INACTIVE);
311 else if (strcmp (applet, "mark_service_starting") == 0) 314 else if (strcmp (applet, "mark_service_starting") == 0)
312 ok = rc_mark_service (argv[0], rc_service_starting); 315 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPING);
313 else if (strcmp (applet, "mark_service_stopping") == 0) 316 else if (strcmp (applet, "mark_service_stopping") == 0)
314 ok = rc_mark_service (argv[0], rc_service_stopping); 317 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPING);
315 else if (strcmp (applet, "mark_service_coldplugged") == 0) 318 else if (strcmp (applet, "mark_service_coldplugged") == 0)
316 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);
317 else 322 else
318 eerrorx ("%s: unknown applet", applet); 323 eerrorx ("%s: unknown applet", applet);
319 324
320 /* 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
321 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 */
328 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1) 333 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1)
329 if (kill (pid, SIGHUP) != 0) 334 if (kill (pid, SIGHUP) != 0)
330 eerror ("%s: failed to signal parent %d: %s", 335 eerror ("%s: failed to signal parent %d: %s",
331 applet, pid, strerror (errno)); 336 applet, pid, strerror (errno));
332 337
333 /* Remove the exclsive time test. This ensures that it's not 338 /* Remove the exclusive time test. This ensures that it's not
334 in control as well */ 339 in control as well */
335 l = strlen (RC_SVCDIR "exclusive") + 340 l = strlen (RC_SVCDIR "exclusive") +
336 strlen (svcname) + 341 strlen (svcname) +
337 strlen (runscript_pid) + 342 strlen (runscript_pid) +
338 4; 343 4;
339 mtime = rc_xmalloc (l); 344 mtime = xmalloc (l);
340 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s", 345 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s",
341 svcname, runscript_pid); 346 svcname, runscript_pid);
342 if (rc_exists (mtime) && unlink (mtime) != 0) 347 if (exists (mtime) && unlink (mtime) != 0)
343 eerror ("%s: unlink: %s", applet, strerror (errno)); 348 eerror ("%s: unlink: %s", applet, strerror (errno));
344 free (mtime); 349 free (mtime);
345 } 350 }
346 351
347 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 352 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
357 362
358 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 363 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
359 eerrorx ("%s: no option specified", applet); 364 eerrorx ("%s: no option specified", applet);
360 365
361 if (strcmp (applet, "get_options") == 0) { 366 if (strcmp (applet, "get_options") == 0) {
362 char buffer[1024]; 367 char *option = rc_service_value_get (service, argv[0]);
363 memset (buffer, 0, 1024); 368 if (option) {
364 ok = rc_get_service_option (service, argv[0], buffer);
365 if (ok)
366 printf ("%s", buffer); 369 printf ("%s", option);
370 free (option);
371 ok = true;
372 }
367 } else if (strcmp (applet, "save_options") == 0) 373 } else if (strcmp (applet, "save_options") == 0)
368 ok = rc_set_service_option (service, argv[0], argv[1]); 374 ok = rc_service_value_set (service, argv[0], argv[1]);
369 else 375 else
370 eerrorx ("%s: unknown applet", applet); 376 eerrorx ("%s: unknown applet", applet);
371 377
372 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 378 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
373} 379}
374 380
375#ifdef __linux__ 381#ifdef __linux__
376static char *proc_getent (const char *ent) 382static char *proc_getent (const char *ent)
377{ 383{
378 FILE *fp; 384 FILE *fp;
379 char buffer[RC_LINEBUFFER]; 385 char *buffer;
380 char *p; 386 char *p;
381 char *value = NULL; 387 char *value = NULL;
382 int i; 388 int i;
383 389
384 if (! rc_exists ("/proc/cmdline")) 390 if (! exists ("/proc/cmdline"))
385 return (NULL); 391 return (NULL);
386 392
387 if (! (fp = fopen ("/proc/cmdline", "r"))) { 393 if (! (fp = fopen ("/proc/cmdline", "r"))) {
388 eerror ("failed to open `/proc/cmdline': %s", strerror (errno)); 394 eerror ("failed to open `/proc/cmdline': %s", strerror (errno));
389 return (NULL); 395 return (NULL);
390 } 396 }
391 397
392 memset (buffer, 0, sizeof (buffer)); 398 buffer = xmalloc (sizeof (char) * RC_LINEBUFFER);
399 memset (buffer, 0, RC_LINEBUFFER);
393 if (fgets (buffer, RC_LINEBUFFER, fp) && 400 if (fgets (buffer, RC_LINEBUFFER, fp) &&
394 (p = strstr (buffer, ent))) 401 (p = strstr (buffer, ent)))
395 { 402 {
396 i = p - buffer; 403 i = p - buffer;
397 if (i == '\0' || buffer[i - 1] == ' ') { 404 if (i == '\0' || buffer[i - 1] == ' ') {
401 buffer[i] = 0; 408 buffer[i] = 0;
402 409
403 p += strlen (ent); 410 p += strlen (ent);
404 if (*p == '=') 411 if (*p == '=')
405 p++; 412 p++;
406 value = strdup (strsep (&p, " ")); 413 value = xstrdup (strsep (&p, " "));
407 } 414 }
408 } else 415 } else
409 errno = ENOENT; 416 errno = ENOENT;
417 free (buffer);
410 fclose (fp); 418 fclose (fp);
411 419
412 return (value); 420 return (value);
413} 421}
414#endif 422#endif
416static char read_key (bool block) 424static char read_key (bool block)
417{ 425{
418 struct termios termios; 426 struct termios termios;
419 char c = 0; 427 char c = 0;
420 int fd = fileno (stdin); 428 int fd = fileno (stdin);
421 429
422 if (! isatty (fd)) 430 if (! isatty (fd))
423 return (false); 431 return (false);
424 432
425 /* 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
426 will be changing it for non-blocking reads for Interactive */ 434 will be changing it for non-blocking reads for Interactive */
427 if (! termios_orig) { 435 if (! termios_orig) {
428 termios_orig = rc_xmalloc (sizeof (struct termios)); 436 termios_orig = xmalloc (sizeof (struct termios));
429 tcgetattr (fd, termios_orig); 437 tcgetattr (fd, termios_orig);
430 } 438 }
431 439
432 tcgetattr (fd, &termios); 440 tcgetattr (fd, &termios);
433 termios.c_lflag &= ~(ICANON | ECHO); 441 termios.c_lflag &= ~(ICANON | ECHO);
454 strcmp (PREVLEVEL, "N") != 0 && 462 strcmp (PREVLEVEL, "N") != 0 &&
455 strcmp (PREVLEVEL, "S") != 0 && 463 strcmp (PREVLEVEL, "S") != 0 &&
456 strcmp (PREVLEVEL, "1") != 0) 464 strcmp (PREVLEVEL, "1") != 0)
457 return (false); 465 return (false);
458 466
459 if (! rc_is_env ("RC_INTERACTIVE", "yes")) 467 if (! rc_env_bool ("RC_INTERACTIVE"))
460 return (false); 468 return (false);
461 469
462 c = read_key (false); 470 c = read_key (false);
463 return ((c == 'I' || c == 'i') ? true : false); 471 return ((c == 'I' || c == 'i') ? true : false);
464} 472}
480 execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); 488 execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
481 eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno)); 489 eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno));
482 } 490 }
483#endif 491#endif
484 492
485 newenv = rc_filter_env (); 493 newenv = env_filter ();
486 494
487 if (cont) { 495 if (cont) {
488 int status = 0; 496 int status = 0;
489#ifdef __linux__ 497#ifdef __linux__
490 char *tty = ttyname (fileno (stdout)); 498 char *tty = ttyname (fileno (stdout));
533 applet, strerror (errno)); 541 applet, strerror (errno));
534 exit (EXIT_SUCCESS); 542 exit (EXIT_SUCCESS);
535#endif 543#endif
536} 544}
537 545
538static void set_ksoftlevel (const char *runlevel) 546static void set_ksoftlevel (const char *level)
539{ 547{
540 FILE *fp; 548 FILE *fp;
541 549
542 if (! runlevel || 550 if (! level ||
543 strcmp (runlevel, getenv ("RC_BOOTLEVEL")) == 0 || 551 strcmp (level, getenv ("RC_BOOTLEVEL")) == 0 ||
544 strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 552 strcmp (level, RC_LEVEL_SINGLE) == 0 ||
545 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) 553 strcmp (level, RC_LEVEL_SYSINIT) == 0)
546 { 554 {
547 if (rc_exists (RC_KSOFTLEVEL) && 555 if (exists (RC_KSOFTLEVEL) &&
548 unlink (RC_KSOFTLEVEL) != 0) 556 unlink (RC_KSOFTLEVEL) != 0)
549 eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno)); 557 eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno));
550 return; 558 return;
551 } 559 }
552 560
553 if (! (fp = fopen (RC_KSOFTLEVEL, "w"))) { 561 if (! (fp = fopen (RC_KSOFTLEVEL, "w"))) {
554 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno)); 562 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno));
555 return; 563 return;
556 } 564 }
557 565
558 fprintf (fp, "%s", runlevel); 566 fprintf (fp, "%s", level);
559 fclose (fp); 567 fclose (fp);
560} 568}
561 569
562static int get_ksoftlevel (char *buffer, int buffer_len) 570static int get_ksoftlevel (char *buffer, int buffer_len)
563{ 571{
564 FILE *fp; 572 FILE *fp;
565 int i = 0; 573 int i = 0;
566 574
567 if (! rc_exists (RC_KSOFTLEVEL)) 575 if (! exists (RC_KSOFTLEVEL))
568 return (0); 576 return (0);
569 577
570 if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) { 578 if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) {
571 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno)); 579 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno));
572 return (-1); 580 return (-1);
592{ 600{
593 pidlist_t *sp = service_pids; 601 pidlist_t *sp = service_pids;
594 if (sp) { 602 if (sp) {
595 while (sp->next) 603 while (sp->next)
596 sp = sp->next; 604 sp = sp->next;
597 sp->next = rc_xmalloc (sizeof (pidlist_t)); 605 sp->next = xmalloc (sizeof (pidlist_t));
598 sp = sp->next; 606 sp = sp->next;
599 } else 607 } else
600 sp = service_pids = rc_xmalloc (sizeof (pidlist_t)); 608 sp = service_pids = xmalloc (sizeof (pidlist_t));
601 memset (sp, 0, sizeof (pidlist_t)); 609 memset (sp, 0, sizeof (pidlist_t));
602 sp->pid = pid; 610 sp->pid = pid;
603} 611}
604 612
605static void remove_pid (pid_t pid) 613static void remove_pid (pid_t pid)
616 free (pl); 624 free (pl);
617 break; 625 break;
618 } 626 }
619 last = pl; 627 last = pl;
620 } 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);
621} 644}
622 645
623static void handle_signal (int sig) 646static void handle_signal (int sig)
624{ 647{
625 int serrno = errno; 648 int serrno = errno;
661 signal (SIGCHLD, SIG_IGN); 684 signal (SIGCHLD, SIG_IGN);
662 for (pl = service_pids; pl; pl = pl->next) 685 for (pl = service_pids; pl; pl = pl->next)
663 kill (pl->pid, SIGTERM); 686 kill (pl->pid, SIGTERM);
664 687
665 /* Notify plugins we are aborting */ 688 /* Notify plugins we are aborting */
666 rc_plugin_run (rc_hook_abort, NULL); 689 rc_plugin_run (RC_HOOK_ABORT, NULL);
667 690
668 /* Only drop into single user mode if we're booting */ 691 /* Only drop into single user mode if we're booting */
669 if ((PREVLEVEL && 692 if ((PREVLEVEL &&
670 (strcmp (PREVLEVEL, "S") == 0 || 693 (strcmp (PREVLEVEL, "S") == 0 ||
671 strcmp (PREVLEVEL, "1") == 0)) || 694 strcmp (PREVLEVEL, "1") == 0)) ||
707 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0) 730 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0)
708 eerrorx ("%s: failed to exec `%s'", applet, script); 731 eerrorx ("%s: failed to exec `%s'", applet, script);
709} 732}
710 733
711#include "_usage.h" 734#include "_usage.h"
712#define getoptstring getoptstring_COMMON 735#define getoptstring getoptstring_COMMON
713static struct option longopts[] = { 736static struct option longopts[] = {
714 longopts_COMMON 737 longopts_COMMON
715 { NULL, 0, NULL, 0} 738};
739static const char * const longopts_help[] = {
740 longopts_help_COMMON
716}; 741};
717#include "_usage.c" 742#include "_usage.c"
718 743
719int main (int argc, char **argv) 744int main (int argc, char **argv)
720{ 745{
721 char *runlevel = NULL;
722 const char *bootlevel = NULL; 746 const char *bootlevel = NULL;
723 char *newlevel = NULL; 747 char *newlevel = NULL;
724 char *service = NULL; 748 char *service = NULL;
725 char **deporder = NULL; 749 char **deporder = NULL;
726 char **tmplist; 750 char **tmplist;
730 bool interactive = false; 754 bool interactive = false;
731 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE; 755 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
732 char ksoftbuffer [PATH_MAX]; 756 char ksoftbuffer [PATH_MAX];
733 char pidstr[6]; 757 char pidstr[6];
734 int opt; 758 int opt;
759 DIR *dp;
760 struct dirent *d;
735 761
736 atexit (cleanup); 762 atexit (cleanup);
737 if (argv[0]) 763 if (argv[0])
738 applet = rc_xstrdup (basename (argv[0])); 764 applet = xstrdup (basename (argv[0]));
739 765
740 if (! applet) 766 if (! applet)
741 eerrorx ("arguments required"); 767 eerrorx ("arguments required");
742 768
743 /* 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
815 signal (SIGTERM, handle_signal); 841 signal (SIGTERM, handle_signal);
816 signal (SIGUSR1, handle_signal); 842 signal (SIGUSR1, handle_signal);
817 843
818 /* Ensure our environment is pure 844 /* Ensure our environment is pure
819 Also, add our configuration to it */ 845 Also, add our configuration to it */
820 env = rc_filter_env (); 846 env = env_filter ();
821 tmplist = rc_make_env (); 847 tmplist = env_config ();
822 rc_strlist_join (&env, tmplist); 848 rc_strlist_join (&env, tmplist);
823 rc_strlist_free (tmplist); 849 rc_strlist_free (tmplist);
824 850
825 if (env) { 851 if (env) {
826 char *p; 852 char *p;
834 /* No clearenv present here then. 860 /* No clearenv present here then.
835 We could manipulate environ directly ourselves, but it seems that 861 We could manipulate environ directly ourselves, but it seems that
836 some kernels bitch about this according to the environ man pages 862 some kernels bitch about this according to the environ man pages
837 so we walk though environ and call unsetenv for each value. */ 863 so we walk though environ and call unsetenv for each value. */
838 while (environ[0]) { 864 while (environ[0]) {
839 tmp = rc_xstrdup (environ[0]); 865 tmp = xstrdup (environ[0]);
840 p = tmp; 866 p = tmp;
841 var = strsep (&p, "="); 867 var = strsep (&p, "=");
842 unsetenv (var); 868 unsetenv (var);
843 free (tmp); 869 free (tmp);
844 } 870 }
874 900
875 /* Export our PID */ 901 /* Export our PID */
876 snprintf (pidstr, sizeof (pidstr), "%d", getpid ()); 902 snprintf (pidstr, sizeof (pidstr), "%d", getpid ());
877 setenv ("RC_PID", pidstr, 1); 903 setenv ("RC_PID", pidstr, 1);
878 904
879 interactive = rc_exists (INTERACTIVE); 905 interactive = exists (INTERACTIVE);
880 rc_plugin_load (); 906 rc_plugin_load ();
881 907
882 /* Load current softlevel */ 908 /* Load current softlevel */
883 bootlevel = getenv ("RC_BOOTLEVEL"); 909 bootlevel = getenv ("RC_BOOTLEVEL");
884 runlevel = rc_get_runlevel (); 910 runlevel = rc_runlevel_get ();
885 911
886 /* Check we're in the runlevel requested, ie from 912 /* Check we're in the runlevel requested, ie from
887 rc single 913 rc single
888 rc shutdown 914 rc shutdown
889 rc reboot 915 rc reboot
901#endif 927#endif
902 928
903 /* exec init-early.sh if it exists 929 /* exec init-early.sh if it exists
904 * This should just setup the console to use the correct 930 * This should just setup the console to use the correct
905 * font. Maybe it should setup the keyboard too? */ 931 * font. Maybe it should setup the keyboard too? */
906 if (rc_exists (INITEARLYSH)) 932 if (exists (INITEARLYSH))
907 run_script (INITEARLYSH); 933 run_script (INITEARLYSH);
908 934
909 uname (&uts); 935 uname (&uts);
910 936
911 printf ("\n"); 937 printf ("\n");
912 printf (" %sGentoo/%s; %shttp://www.gentoo.org/%s" 938 printf (" %sGentoo/%s; %shttp://www.gentoo.org/%s"
913 "\n Copyright 1999-2007 Gentoo Foundation; " 939 "\n Copyright 1999-2007 Gentoo Foundation; "
914 "Distributed under the GPLv2\n\n", 940 "Distributed under the GPLv2\n\n",
915 ecolor (ecolor_good), uts.sysname, ecolor (ecolor_bracket), 941 ecolor (ECOLOR_GOOD), uts.sysname, ecolor (ECOLOR_BRACKET),
916 ecolor (ecolor_normal)); 942 ecolor (ECOLOR_NORMAL));
917 943
918 if (rc_is_env ("RC_INTERACTIVE", "yes")) 944 if (rc_env_bool ("RC_INTERACTIVE"))
919 printf ("Press %sI%s to enter interactive boot mode\n\n", 945 printf ("Press %sI%s to enter interactive boot mode\n\n",
920 ecolor (ecolor_good), ecolor (ecolor_normal)); 946 ecolor (ECOLOR_GOOD), ecolor (ECOLOR_NORMAL));
921 947
922 setenv ("RC_SOFTLEVEL", newlevel, 1); 948 setenv ("RC_SOFTLEVEL", newlevel, 1);
923 rc_plugin_run (rc_hook_runlevel_start_in, newlevel); 949 rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, newlevel);
924 run_script (INITSH); 950 run_script (INITSH);
925 951
926#ifdef __linux__ 952#ifdef __linux__
927 /* If we requested a softlevel, save it now */ 953 /* If we requested a softlevel, save it now */
928 set_ksoftlevel (NULL); 954 set_ksoftlevel (NULL);
930 set_ksoftlevel (cmd); 956 set_ksoftlevel (cmd);
931 free (cmd); 957 free (cmd);
932 } 958 }
933 959
934#endif 960#endif
935 rc_plugin_run (rc_hook_runlevel_start_out, newlevel); 961 rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, newlevel);
936 962
937 if (want_interactive ()) 963 if (want_interactive ())
938 mark_interactive (); 964 mark_interactive ();
939 965
940 exit (EXIT_SUCCESS); 966 exit (EXIT_SUCCESS);
999 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 || 1025 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 ||
1000 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 || 1026 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
1001 strcmp (newlevel, RC_LEVEL_SINGLE) == 0)) 1027 strcmp (newlevel, RC_LEVEL_SINGLE) == 0))
1002 { 1028 {
1003 going_down = true; 1029 going_down = true;
1004 rc_set_runlevel (newlevel); 1030 rc_runlevel_set (newlevel);
1005 setenv ("RC_SOFTLEVEL", newlevel, 1); 1031 setenv ("RC_SOFTLEVEL", newlevel, 1);
1006 rc_plugin_run (rc_hook_runlevel_stop_in, newlevel); 1032 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, newlevel);
1007 } else { 1033 } else {
1008 rc_plugin_run (rc_hook_runlevel_stop_in, runlevel); 1034 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, runlevel);
1009 } 1035 }
1010 1036
1011 /* Check if runlevel is valid if we're changing */ 1037 /* Check if runlevel is valid if we're changing */
1012 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) { 1038 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) {
1013 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel, (char *) NULL); 1039 if (! rc_runlevel_exists (newlevel))
1014 if (! rc_is_dir (tmp))
1015 eerrorx ("%s: is not a valid runlevel", newlevel); 1040 eerrorx ("%s: is not a valid runlevel", newlevel);
1016 CHAR_FREE (tmp);
1017 } 1041 }
1018 1042
1019 /* Load our deptree now */ 1043 /* Load our deptree now */
1020 if ((deptree = rc_load_deptree ()) == NULL) 1044 if ((deptree = _rc_deptree_load ()) == NULL)
1021 eerrorx ("failed to load deptree"); 1045 eerrorx ("failed to load deptree");
1022 1046
1023 /* Clean the failed services state dir now */ 1047 /* Clean the failed services state dir now */
1024 if (rc_is_dir (RC_SVCDIR "/failed")) 1048 if ((dp = opendir (RC_SVCDIR "/failed"))) {
1025 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;
1054
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 }
1026 1065
1027 mkdir (RC_STOPPING, 0755); 1066 mkdir (RC_STOPPING, 0755);
1028 1067
1029#ifdef __linux__ 1068#ifdef __linux__
1030 /* 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
1031 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
1032 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
1033 here when we are ready for them */ 1072 here when we are ready for them */
1034 if (rc_is_dir (DEVBOOT)) { 1073 if ((dp = opendir (DEVBOOT))) {
1035 start_services = rc_ls_dir (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);
1036 rc_rm_dir (DEVBOOT, true); 1093 rmdir (DEVBOOT);
1037
1038 STRLIST_FOREACH (start_services, service, i)
1039 if (rc_allow_plug (service))
1040 rc_mark_service (service, rc_service_coldplugged);
1041 /* We need to dump this list now.
1042 This may seem redunant, but only Linux needs this and saves on
1043 code bloat. */
1044 rc_strlist_free (start_services);
1045 start_services = NULL;
1046 } 1094 }
1047#else 1095#else
1048 /* 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.
1049 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
1050 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
1051 runlevel for our dependency tree to work. */ 1099 runlevel for our dependency tree to work. */
1052 if (newlevel && strcmp (newlevel, bootlevel) == 0 && 1100 if (newlevel && strcmp (newlevel, bootlevel) == 0 &&
1053 (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 1101 (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
1054 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) && 1102 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) &&
1055 rc_is_env ("RC_COLDPLUG", "yes")) 1103 rc_env_bool ("RC_COLDPLUG"))
1056 { 1104 {
1057#if defined(__DragonFly__) || defined(__FreeBSD__) 1105#if defined(__DragonFly__) || defined(__FreeBSD__)
1058 /* 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 :) */
1059 start_services = rc_ls_dir ("/dev/net", 0); 1107 if ((dp = opendir ("/dev/net"))) {
1060 STRLIST_FOREACH (start_services, service, i) { 1108 while ((d = readdir (dp))) {
1061 j = (strlen ("net.") + strlen (service) + 1); 1109 i = (strlen ("net.") + strlen (d->d_name) + 1);
1062 tmp = rc_xmalloc (sizeof (char *) * j); 1110 tmp = xmalloc (sizeof (char) * i);
1063 snprintf (tmp, j, "net.%s", service); 1111 snprintf (tmp, i, "net.%s", d->d_name);
1064 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 1112 if (rc_service_exists (tmp) &&
1065 rc_mark_service (tmp, rc_service_coldplugged); 1113 rc_service_plugable (tmp))
1114 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
1066 CHAR_FREE (tmp); 1115 CHAR_FREE (tmp);
1067 } 1116 }
1068 rc_strlist_free (start_services); 1117 closedir (dp);
1118 }
1069#endif 1119#endif
1070 1120
1071 /* The mice are a little more tricky. 1121 /* The mice are a little more tricky.
1072 If we coldplug anything else, we'll probably do it here. */ 1122 If we coldplug anything else, we'll probably do it here. */
1073 start_services = rc_ls_dir ("/dev", 0); 1123 if ((dp == opendir ("/dev"))) {
1074 STRLIST_FOREACH (start_services, service, i) { 1124 while ((d = readdir (dp))) {
1075 if (strncmp (service, "psm", 3) == 0 || 1125 if (strncmp (d->d_name, "psm", 3) == 0 ||
1076 strncmp (service, "ums", 3) == 0) 1126 strncmp (d->d_name, "ums", 3) == 0)
1077 { 1127 {
1078 char *p = service + 3; 1128 char *p = d->d_name + 3;
1079 if (p && isdigit (*p)) { 1129 if (p && isdigit (*p)) {
1080 j = (strlen ("moused.") + strlen (service) + 1); 1130 i = (strlen ("moused.") + strlen (d->d_name) + 1);
1081 tmp = rc_xmalloc (sizeof (char *) * j); 1131 tmp = xmalloc (sizeof (char) * i);
1082 snprintf (tmp, j, "moused.%s", service); 1132 snprintf (tmp, i, "moused.%s", d->d_name);
1083 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 1133 if (rc_service_exists (tmp) && rc_service_plugable (tmp))
1084 rc_mark_service (tmp, rc_service_coldplugged); 1134 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
1085 CHAR_FREE (tmp); 1135 CHAR_FREE (tmp);
1136 }
1086 } 1137 }
1087 } 1138 }
1139 closedir (dp);
1088 } 1140 }
1089 rc_strlist_free (start_services);
1090 start_services = NULL;
1091 } 1141 }
1092#endif 1142#endif
1093 1143
1094 /* 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
1095 correct order for stopping them */ 1145 correct order for stopping them */
1096 stop_services = rc_ls_dir (RC_SVCDIR_STARTING, RC_LS_INITD); 1146 stop_services = rc_services_in_state (RC_SERVICE_STARTING);
1097 1147
1098 tmplist = rc_ls_dir (RC_SVCDIR_INACTIVE, RC_LS_INITD); 1148 tmplist = rc_services_in_state (RC_SERVICE_INACTIVE);
1099 rc_strlist_join (&stop_services, tmplist); 1149 rc_strlist_join (&stop_services, tmplist);
1100 rc_strlist_free (tmplist); 1150 rc_strlist_free (tmplist);
1101 1151
1102 tmplist = rc_ls_dir (RC_SVCDIR_STARTED, RC_LS_INITD); 1152 tmplist = rc_services_in_state (RC_SERVICE_STARTED);
1103 rc_strlist_join (&stop_services, tmplist); 1153 rc_strlist_join (&stop_services, tmplist);
1104 rc_strlist_free (tmplist); 1154 rc_strlist_free (tmplist);
1105 1155
1106 types = NULL; 1156 types = NULL;
1107 rc_strlist_add (&types, "ineed"); 1157 rc_strlist_add (&types, "ineed");
1108 rc_strlist_add (&types, "iuse"); 1158 rc_strlist_add (&types, "iuse");
1109 rc_strlist_add (&types, "iafter"); 1159 rc_strlist_add (&types, "iafter");
1110 1160
1111 deporder = rc_get_depends (deptree, types, stop_services, 1161 deporder = rc_deptree_depends (deptree, types, stop_services,
1112 runlevel, depoptions | RC_DEP_STOP); 1162 runlevel, depoptions | RC_DEP_STOP);
1113 1163
1114 rc_strlist_free (stop_services); 1164 rc_strlist_free (stop_services);
1115 rc_strlist_free (types); 1165 rc_strlist_free (types);
1116 types = NULL; 1166 types = NULL;
1117 stop_services = deporder; 1167 stop_services = deporder;
1118 deporder = NULL; 1168 deporder = NULL;
1119 rc_strlist_reverse (stop_services); 1169 rc_strlist_reverse (stop_services);
1120 1170
1121 /* Load our list of coldplugged services */ 1171 /* Load our list of coldplugged services */
1122 coldplugged_services = rc_ls_dir (RC_SVCDIR_COLDPLUGGED, RC_LS_INITD); 1172 coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
1123 1173
1124 /* Load our start services now. 1174 /* Load our start services now.
1125 We have different rules dependent on runlevel. */ 1175 We have different rules dependent on runlevel. */
1126 if (newlevel && strcmp (newlevel, bootlevel) == 0) { 1176 if (newlevel && strcmp (newlevel, bootlevel) == 0) {
1127 if (coldplugged_services) { 1177 if (coldplugged_services) {
1130 printf (" %s", service); 1180 printf (" %s", service);
1131 rc_strlist_add (&start_services, service); 1181 rc_strlist_add (&start_services, service);
1132 } 1182 }
1133 printf ("\n"); 1183 printf ("\n");
1134 } 1184 }
1135 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel, 1185 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
1136 (char *) NULL);
1137 tmplist = rc_ls_dir (tmp, RC_LS_INITD);
1138 rc_strlist_join (&start_services, tmplist); 1186 rc_strlist_join (&start_services, tmplist);
1139 rc_strlist_free (tmplist); 1187 rc_strlist_free (tmplist);
1140 CHAR_FREE (tmp);
1141 } else { 1188 } else {
1142 /* Store our list of coldplugged services */ 1189 /* Store our list of coldplugged services */
1190 tmplist = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
1143 rc_strlist_join (&coldplugged_services, 1191 rc_strlist_join (&coldplugged_services, tmplist);
1144 rc_ls_dir (RC_SVCDIR_COLDPLUGGED, RC_LS_INITD)); 1192 rc_strlist_free (tmplist);
1145 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && 1193 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
1146 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && 1194 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
1147 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) 1195 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
1148 { 1196 {
1149 /* 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 */
1151 rc_strlist_join (&start_services, tmplist); 1199 rc_strlist_join (&start_services, tmplist);
1152 rc_strlist_free (tmplist); 1200 rc_strlist_free (tmplist);
1153 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel); 1201 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
1154 rc_strlist_join (&start_services, tmplist); 1202 rc_strlist_join (&start_services, tmplist);
1155 rc_strlist_free (tmplist); 1203 rc_strlist_free (tmplist);
1156 1204
1157 STRLIST_FOREACH (coldplugged_services, service, i) 1205 STRLIST_FOREACH (coldplugged_services, service, i)
1158 rc_strlist_add (&start_services, service); 1206 rc_strlist_add (&start_services, service);
1159 1207
1160 } 1208 }
1161 } 1209 }
1162 1210
1163 /* Save out softlevel now */ 1211 /* Save out softlevel now */
1164 if (going_down) 1212 if (going_down)
1165 rc_set_runlevel (newlevel); 1213 rc_runlevel_set (newlevel);
1166 1214
1167 types = NULL; 1215 types = NULL;
1168 rc_strlist_add (&types, "needsme"); 1216 rc_strlist_add (&types, "needsme");
1169 /* Now stop the services that shouldn't be running */ 1217 /* Now stop the services that shouldn't be running */
1170 STRLIST_FOREACH (stop_services, service, i) { 1218 STRLIST_FOREACH (stop_services, service, i) {
1173 char **stopdeps = NULL; 1221 char **stopdeps = NULL;
1174 char *svc1 = NULL; 1222 char *svc1 = NULL;
1175 char *svc2 = NULL; 1223 char *svc2 = NULL;
1176 int k; 1224 int k;
1177 1225
1178 if (rc_service_state (service, rc_service_stopped)) 1226 if (rc_service_state (service) & RC_SERVICE_STOPPED)
1179 continue; 1227 continue;
1180 1228
1181 /* We always stop the service when in these runlevels */ 1229 /* We always stop the service when in these runlevels */
1182 if (going_down) { 1230 if (going_down) {
1183 pid_t pid = rc_stop_service (service); 1231 pid_t pid = rc_service_stop (service);
1184 if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes")) 1232 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL"))
1185 rc_waitpid (pid); 1233 wait_pid (pid);
1186 continue; 1234 continue;
1187 } 1235 }
1188 1236
1189 /* 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 */
1190 STRLIST_FOREACH (start_services, svc1, j) 1238 STRLIST_FOREACH (start_services, svc1, j)
1198 int len; 1246 int len;
1199 if (! newlevel) 1247 if (! newlevel)
1200 continue; 1248 continue;
1201 1249
1202 len = strlen (service) + strlen (runlevel) + 2; 1250 len = strlen (service) + strlen (runlevel) + 2;
1203 tmp = rc_xmalloc (sizeof (char *) * len); 1251 tmp = xmalloc (sizeof (char) * len);
1204 snprintf (tmp, len, "%s.%s", service, runlevel); 1252 snprintf (tmp, len, "%s.%s", service, runlevel);
1205 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1253 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1206 found = rc_exists (conf); 1254 found = exists (conf);
1207 CHAR_FREE (conf); 1255 CHAR_FREE (conf);
1208 CHAR_FREE (tmp); 1256 CHAR_FREE (tmp);
1209 if (! found) { 1257 if (! found) {
1210 len = strlen (service) + strlen (newlevel) + 2; 1258 len = strlen (service) + strlen (newlevel) + 2;
1211 tmp = rc_xmalloc (sizeof (char *) * len); 1259 tmp = xmalloc (sizeof (char) * len);
1212 snprintf (tmp, len, "%s.%s", service, newlevel); 1260 snprintf (tmp, len, "%s.%s", service, newlevel);
1213 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1261 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1214 found = rc_exists (conf); 1262 found = exists (conf);
1215 CHAR_FREE (conf); 1263 CHAR_FREE (conf);
1216 CHAR_FREE (tmp); 1264 CHAR_FREE (tmp);
1217 if (!found) 1265 if (!found)
1218 continue; 1266 continue;
1219 } 1267 }
1220 } else { 1268 } else {
1221 /* Allow coldplugged services not to be in the runlevels list */ 1269 /* Allow coldplugged services not to be in the runlevels list */
1222 if (rc_service_state (service, rc_service_coldplugged)) 1270 if (rc_service_state (service) & RC_SERVICE_COLDPLUGGED)
1223 continue; 1271 continue;
1224 } 1272 }
1225 1273
1226 /* 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
1227 going to be started depends on us */ 1275 going to be started depends on us */
1228 rc_strlist_add (&stopdeps, service); 1276 rc_strlist_add (&stopdeps, service);
1229 deporder = rc_get_depends (deptree, types, stopdeps, 1277 deporder = rc_deptree_depends (deptree, types, stopdeps,
1230 runlevel, RC_DEP_STRICT); 1278 runlevel, RC_DEP_STRICT);
1231 rc_strlist_free (stopdeps); 1279 rc_strlist_free (stopdeps);
1232 stopdeps = NULL; 1280 stopdeps = NULL;
1233 found = false; 1281 found = false;
1234 STRLIST_FOREACH (deporder, svc1, j) { 1282 STRLIST_FOREACH (deporder, svc1, j) {
1235 STRLIST_FOREACH (start_services, svc2, k) 1283 STRLIST_FOREACH (start_services, svc2, k)
1243 rc_strlist_free (deporder); 1291 rc_strlist_free (deporder);
1244 deporder = NULL; 1292 deporder = NULL;
1245 1293
1246 /* After all that we can finally stop the blighter! */ 1294 /* After all that we can finally stop the blighter! */
1247 if (! found) { 1295 if (! found) {
1248 pid_t pid = rc_stop_service (service); 1296 pid_t pid = rc_service_stop (service);
1249 if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes")) 1297 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL"))
1250 rc_waitpid (pid); 1298 wait_pid (pid);
1251 } 1299 }
1252 } 1300 }
1253 rc_strlist_free (types); 1301 rc_strlist_free (types);
1254 types = NULL; 1302 types = NULL;
1255 1303
1256 /* Wait for our services to finish */ 1304 /* Wait for our services to finish */
1257 wait_for_services (); 1305 wait_for_services ();
1258 1306
1259 /* Notify the plugins we have finished */ 1307 /* Notify the plugins we have finished */
1260 rc_plugin_run (rc_hook_runlevel_stop_out, runlevel); 1308 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_OUT, runlevel);
1261 1309
1262 rmdir (RC_STOPPING); 1310 rmdir (RC_STOPPING);
1263 1311
1264 /* Store the new runlevel */ 1312 /* Store the new runlevel */
1265 if (newlevel) { 1313 if (newlevel) {
1266 rc_set_runlevel (newlevel); 1314 rc_runlevel_set (newlevel);
1315 free (runlevel);
1267 runlevel = newlevel; 1316 runlevel = xstrdup (newlevel);
1268 setenv ("RC_SOFTLEVEL", runlevel, 1); 1317 setenv ("RC_SOFTLEVEL", runlevel, 1);
1269 } 1318 }
1270 1319
1271 /* Run the halt script if needed */ 1320 /* Run the halt script if needed */
1272 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 || 1321 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
1277 applet, HALTSH, strerror (errno)); 1326 applet, HALTSH, strerror (errno));
1278 } 1327 }
1279 1328
1280 /* Single user is done now */ 1329 /* Single user is done now */
1281 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) { 1330 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) {
1282 if (rc_exists (INTERACTIVE)) 1331 if (exists (INTERACTIVE))
1283 unlink (INTERACTIVE); 1332 unlink (INTERACTIVE);
1284 sulogin (false); 1333 sulogin (false);
1285 } 1334 }
1286 1335
1287 mkdir (RC_STARTING, 0755); 1336 mkdir (RC_STARTING, 0755);
1288 rc_plugin_run (rc_hook_runlevel_start_in, runlevel); 1337 rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, runlevel);
1289 1338
1290 /* Re-add our coldplugged services if they stopped */ 1339 /* Re-add our coldplugged services if they stopped */
1291 STRLIST_FOREACH (coldplugged_services, service, i) 1340 STRLIST_FOREACH (coldplugged_services, service, i)
1292 rc_mark_service (service, rc_service_coldplugged); 1341 rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
1293 1342
1294 /* Order the services to start */ 1343 /* Order the services to start */
1295 rc_strlist_add (&types, "ineed"); 1344 rc_strlist_add (&types, "ineed");
1296 rc_strlist_add (&types, "iuse"); 1345 rc_strlist_add (&types, "iuse");
1297 rc_strlist_add (&types, "iafter"); 1346 rc_strlist_add (&types, "iafter");
1298 deporder = rc_get_depends (deptree, types, start_services, 1347 deporder = rc_deptree_depends (deptree, types, start_services,
1299 runlevel, depoptions | RC_DEP_START); 1348 runlevel, depoptions | RC_DEP_START);
1300 rc_strlist_free (types); 1349 rc_strlist_free (types);
1301 types = NULL; 1350 types = NULL;
1302 rc_strlist_free (start_services); 1351 rc_strlist_free (start_services);
1303 start_services = deporder; 1352 start_services = deporder;
1304 deporder = NULL; 1353 deporder = NULL;
1309 if ((service = proc_getent ("noinitd"))) { 1358 if ((service = proc_getent ("noinitd"))) {
1310 char *p = service; 1359 char *p = service;
1311 char *token; 1360 char *token;
1312 1361
1313 while ((token = strsep (&p, ","))) 1362 while ((token = strsep (&p, ",")))
1314 rc_mark_service (token, rc_service_started); 1363 rc_service_mark (token, RC_SERVICE_STARTED);
1315 free (service); 1364 free (service);
1316 } 1365 }
1317 } 1366 }
1318#endif 1367#endif
1319 1368
1320 1369
1321 STRLIST_FOREACH (start_services, service, i) { 1370 STRLIST_FOREACH (start_services, service, i) {
1322 if (rc_service_state (service, rc_service_stopped)) { 1371 if (rc_service_state (service) & RC_SERVICE_STOPPED) {
1323 pid_t pid; 1372 pid_t pid;
1324 1373
1325 if (! interactive) 1374 if (! interactive)
1326 interactive = want_interactive (); 1375 interactive = want_interactive ();
1327 1376
1342 default: goto interactive_option; 1391 default: goto interactive_option;
1343 } 1392 }
1344 } 1393 }
1345 1394
1346 /* Remember the pid if we're running in parallel */ 1395 /* Remember the pid if we're running in parallel */
1347 if ((pid = rc_start_service (service))) 1396 if ((pid = rc_service_start (service)))
1348 add_pid (pid); 1397 add_pid (pid);
1349 1398
1350 if (! rc_is_env ("RC_PARALLEL", "yes")) { 1399 if (! rc_env_bool ("RC_PARALLEL")) {
1351 rc_waitpid (pid); 1400 wait_pid (pid);
1352 remove_pid (pid); 1401 remove_pid (pid);
1353 } 1402 }
1354 } 1403 }
1355 } 1404 }
1356 1405
1357 /* Wait for our services to finish */ 1406 /* Wait for our services to finish */
1358 wait_for_services (); 1407 wait_for_services ();
1359 1408
1360 rc_plugin_run (rc_hook_runlevel_start_out, runlevel); 1409 rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, runlevel);
1361 1410
1362#ifdef __linux__ 1411#ifdef __linux__
1363 /* mark any services skipped as stopped */ 1412 /* mark any services skipped as stopped */
1364 if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) { 1413 if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) {
1365 if ((service = proc_getent ("noinitd"))) { 1414 if ((service = proc_getent ("noinitd"))) {
1366 char *p = service; 1415 char *p = service;
1367 char *token; 1416 char *token;
1368 1417
1369 while ((token = strsep (&p, ","))) 1418 while ((token = strsep (&p, ",")))
1370 rc_mark_service (token, rc_service_stopped); 1419 rc_service_mark (token, RC_SERVICE_STOPPED);
1371 free (service); 1420 free (service);
1372 } 1421 }
1373 } 1422 }
1374#endif 1423#endif
1375 1424
1376 /* Store our interactive status for boot */ 1425 /* Store our interactive status for boot */
1377 if (interactive && strcmp (runlevel, bootlevel) == 0) 1426 if (interactive && strcmp (runlevel, bootlevel) == 0)
1378 mark_interactive (); 1427 mark_interactive ();
1379 else { 1428 else {
1380 if (rc_exists (INTERACTIVE)) 1429 if (exists (INTERACTIVE))
1381 unlink (INTERACTIVE); 1430 unlink (INTERACTIVE);
1382 } 1431 }
1383 1432
1384 return (EXIT_SUCCESS); 1433 return (EXIT_SUCCESS);
1385} 1434}

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

  ViewVC Help
Powered by ViewVC 1.1.20