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

Diff of /trunk/src/rc.c

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.20