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

Diff of /trunk/src/runscript.c

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

Revision 2567 Revision 2569
69 69
70 lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL); 70 lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL);
71 if (lib_handle) 71 if (lib_handle)
72 { 72 {
73 /* FIXME: the below code generates the warning 73 /* FIXME: the below code generates the warning
74 ISO C forbids assignment between function pointer and 'void *' 74 ISO C forbids assignment between function pointer and 'void *'
75 which sucks ass 75 which sucks ass
76 http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html */ 76http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html */
77 selinux_run_init_old = dlsym (lib_handle, "selinux_runscript"); 77 selinux_run_init_old = dlsym (lib_handle, "selinux_runscript");
78 selinux_run_init_new = dlsym (lib_handle, "selinux_runscript2"); 78 selinux_run_init_new = dlsym (lib_handle, "selinux_runscript2");
79 79
80 /* Use new run_init if it rc_exists, else fall back to old */ 80 /* Use new run_init if it rc_exists, else fall back to old */
81 if (selinux_run_init_new) 81 if (selinux_run_init_new)
82 selinux_run_init_new (argc, argv); 82 selinux_run_init_new (argc, argv);
83 else if (selinux_run_init_old) 83 else if (selinux_run_init_old)
84 selinux_run_init_old (); 84 selinux_run_init_old ();
85 else 85 else
86 /* This shouldnt happen... probably corrupt lib */ 86 /* This shouldnt happen... probably corrupt lib */
87 eerrorx ("run_init is missing from runscript_selinux.so!"); 87 eerrorx ("run_init is missing from runscript_selinux.so!");
88 } 88 }
89} 89}
90#endif 90#endif
91 91
92static void handle_signal (int sig) 92static void handle_signal (int sig)
102 sighup = true; 102 sighup = true;
103 break; 103 break;
104 104
105 case SIGCHLD: 105 case SIGCHLD:
106 do 106 do
107 { 107 {
108 pid = waitpid (-1, &status, WNOHANG); 108 pid = waitpid (-1, &status, WNOHANG);
109 if (pid < 0) 109 if (pid < 0)
110 { 110 {
111 if (errno != ECHILD) 111 if (errno != ECHILD)
112 eerror ("waitpid: %s", strerror (errno)); 112 eerror ("waitpid: %s", strerror (errno));
113 return; 113 return;
114 } 114 }
115 } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); 115 } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
116 break; 116 break;
117 117
118 case SIGINT: 118 case SIGINT:
119 if (! signame[0]) 119 if (! signame[0])
120 snprintf (signame, sizeof (signame), "SIGINT"); 120 snprintf (signame, sizeof (signame), "SIGINT");
121 case SIGTERM: 121 case SIGTERM:
122 if (! signame[0]) 122 if (! signame[0])
123 snprintf (signame, sizeof (signame), "SIGTERM"); 123 snprintf (signame, sizeof (signame), "SIGTERM");
124 case SIGQUIT: 124 case SIGQUIT:
125 if (! signame[0]) 125 if (! signame[0])
126 snprintf (signame, sizeof (signame), "SIGQUIT"); 126 snprintf (signame, sizeof (signame), "SIGQUIT");
127 eerrorx ("%s: caught %s, aborting", applet, signame); 127 eerrorx ("%s: caught %s, aborting", applet, signame);
128 128
129 default: 129 default:
130 eerror ("%s: caught unknown signal %d", applet, sig); 130 eerror ("%s: caught unknown signal %d", applet, sig);
131 } 131 }
172 172
173 while (tests[i]) 173 while (tests[i])
174 { 174 {
175 path = rc_strcatpaths (RC_SVCDIR, tests[i], applet, (char *) NULL); 175 path = rc_strcatpaths (RC_SVCDIR, tests[i], applet, (char *) NULL);
176 if (rc_exists (path)) 176 if (rc_exists (path))
177 { 177 {
178 int m = get_mtime (path, false); 178 int m = get_mtime (path, false);
179 if (mtime < m && m != 0) 179 if (mtime < m && m != 0)
180 { 180 {
181 free (path); 181 free (path);
182 return (false); 182 return (false);
183 } 183 }
184 } 184 }
185 free (path); 185 free (path);
186 i++; 186 i++;
187 } 187 }
188 188
189 return (true); 189 return (true);
190} 190}
191 191
192static void uncoldplug (char *service) 192static void uncoldplug (char *service)
193{ 193{
194 char *cold = rc_strcatpaths (RC_SVCDIR "coldplugged", basename (service), 194 char *cold = rc_strcatpaths (RC_SVCDIR "coldplugged", basename (service),
195 (char *) NULL); 195 (char *) NULL);
196 if (rc_exists (cold) && unlink (cold) != 0) 196 if (rc_exists (cold) && unlink (cold) != 0)
197 eerror ("%s: unlink `%s': %s", applet, cold, strerror (errno)); 197 eerror ("%s: unlink `%s': %s", applet, cold, strerror (errno));
198 free (cold); 198 free (cold);
199} 199}
200 200
233 free (ibsave); 233 free (ibsave);
234 234
235 if (in_control ()) 235 if (in_control ())
236 { 236 {
237 if (rc_service_state (applet, rc_service_stopping)) 237 if (rc_service_state (applet, rc_service_stopping))
238 { 238 {
239 /* If the we're shutting down, do it cleanly */ 239 /* If the we're shutting down, do it cleanly */
240 if ((softlevel && 240 if ((softlevel &&
241 rc_runlevel_stopping () && 241 rc_runlevel_stopping () &&
242 (strcmp (softlevel, RC_LEVEL_SHUTDOWN) == 0 || 242 (strcmp (softlevel, RC_LEVEL_SHUTDOWN) == 0 ||
243 strcmp (softlevel, RC_LEVEL_REBOOT) == 0))) 243 strcmp (softlevel, RC_LEVEL_REBOOT) == 0)))
244 rc_mark_service (applet, rc_service_stopped); 244 rc_mark_service (applet, rc_service_stopped);
245 else if (rc_service_state (applet, rc_service_wasinactive)) 245 else if (rc_service_state (applet, rc_service_wasinactive))
246 rc_mark_service (applet, rc_service_inactive); 246 rc_mark_service (applet, rc_service_inactive);
247 else 247 else
248 rc_mark_service (applet, rc_service_started); 248 rc_mark_service (applet, rc_service_started);
249 } 249 }
250 else if (rc_service_state (applet, rc_service_starting)) 250 else if (rc_service_state (applet, rc_service_starting))
251 { 251 {
252 if (rc_service_state (applet, rc_service_wasinactive)) 252 if (rc_service_state (applet, rc_service_wasinactive))
253 rc_mark_service (applet, rc_service_inactive); 253 rc_mark_service (applet, rc_service_inactive);
254 else 254 else
255 rc_mark_service (applet, rc_service_stopped); 255 rc_mark_service (applet, rc_service_stopped);
256 } 256 }
257 if (exclusive && rc_exists (exclusive)) 257 if (exclusive && rc_exists (exclusive))
258 unlink (exclusive); 258 unlink (exclusive);
259 } 259 }
260 260
261 if (env) 261 if (env)
262 rc_strlist_free (env); 262 rc_strlist_free (env);
263 263
279 pid_t pid; 279 pid_t pid;
280 280
281 /* We need to disable our child signal handler now so we block 281 /* We need to disable our child signal handler now so we block
282 until our script returns. */ 282 until our script returns. */
283 signal (SIGCHLD, NULL); 283 signal (SIGCHLD, NULL);
284 284
285 pid = fork(); 285 pid = fork();
286 286
287 if (pid == -1) 287 if (pid == -1)
288 eerrorx ("%s: fork: %s", service, strerror (errno)); 288 eerrorx ("%s: fork: %s", service, strerror (errno));
289 if (pid == 0) 289 if (pid == 0)
290 { 290 {
291 mycmd = rc_xstrdup (service); 291 mycmd = rc_xstrdup (service);
292 myarg1 = rc_xstrdup (arg1); 292 myarg1 = rc_xstrdup (arg1);
293 if (arg2) 293 if (arg2)
294 myarg2 = rc_xstrdup (arg2); 294 myarg2 = rc_xstrdup (arg2);
295 295
296 if (rc_exists (RC_SVCDIR "runscript.sh")) 296 if (rc_exists (RC_SVCDIR "runscript.sh"))
297 { 297 {
298 execl (RC_SVCDIR "runscript.sh", mycmd, mycmd, myarg1, myarg2, 298 execl (RC_SVCDIR "runscript.sh", mycmd, mycmd, myarg1, myarg2,
299 (char *) NULL); 299 (char *) NULL);
300 eerrorx ("%s: exec `" RC_SVCDIR "runscript.sh': %s", 300 eerrorx ("%s: exec `" RC_SVCDIR "runscript.sh': %s",
301 service, strerror (errno)); 301 service, strerror (errno));
302 } 302 }
303 else 303 else
304 { 304 {
305 execl (RC_LIBDIR "sh/runscript.sh", mycmd, mycmd, myarg1, myarg2, 305 execl (RC_LIBDIR "sh/runscript.sh", mycmd, mycmd, myarg1, myarg2,
306 (char *) NULL); 306 (char *) NULL);
307 eerrorx ("%s: exec `" RC_LIBDIR "sh/runscript.sh': %s", 307 eerrorx ("%s: exec `" RC_LIBDIR "sh/runscript.sh': %s",
308 service, strerror (errno)); 308 service, strerror (errno));
309 } 309 }
310 } 310 }
311 311
312 do 312 do
313 { 313 {
314 if (waitpid (pid, &status, 0) < 0) 314 if (waitpid (pid, &status, 0) < 0)
315 { 315 {
316 if (errno != ECHILD) 316 if (errno != ECHILD)
317 eerror ("waitpid: %s", strerror (errno)); 317 eerror ("waitpid: %s", strerror (errno));
318 break; 318 break;
319 } 319 }
320 } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); 320 } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
321 321
322 /* Done, so restore the signal handler */ 322 /* Done, so restore the signal handler */
323 signal (SIGCHLD, handle_signal); 323 signal (SIGCHLD, handle_signal);
324 324
381 exclusive = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL); 381 exclusive = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL);
382 382
383 if (mkfifo (exclusive, 0600) != 0 && errno != EEXIST && 383 if (mkfifo (exclusive, 0600) != 0 && errno != EEXIST &&
384 (errno != EACCES || geteuid () == 0)) 384 (errno != EACCES || geteuid () == 0))
385 eerrorx ("%s: unable to create fifo `%s': %s", 385 eerrorx ("%s: unable to create fifo `%s': %s",
386 applet, exclusive, strerror (errno)); 386 applet, exclusive, strerror (errno));
387 387
388 path = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL); 388 path = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL);
389 i = strlen (path) + 16; 389 i = strlen (path) + 16;
390 mtime_test = rc_xmalloc (sizeof (char *) * i); 390 mtime_test = rc_xmalloc (sizeof (char *) * i);
391 snprintf (mtime_test, i, "%s.%d", path, getpid ()); 391 snprintf (mtime_test, i, "%s.%d", path, getpid ());
392 free (path); 392 free (path);
393 393
394 if (rc_exists (mtime_test) && unlink (mtime_test) != 0) 394 if (rc_exists (mtime_test) && unlink (mtime_test) != 0)
395 { 395 {
396 eerror ("%s: unlink `%s': %s", 396 eerror ("%s: unlink `%s': %s",
397 applet, mtime_test, strerror (errno)); 397 applet, mtime_test, strerror (errno));
398 free (mtime_test); 398 free (mtime_test);
399 mtime_test = NULL; 399 mtime_test = NULL;
400 return; 400 return;
401 } 401 }
402 402
403 if (symlink (service, mtime_test) != 0) 403 if (symlink (service, mtime_test) != 0)
404 { 404 {
405 eerror ("%s: symlink `%s' to `%s': %s", 405 eerror ("%s: symlink `%s' to `%s': %s",
406 applet, service, mtime_test, strerror (errno)); 406 applet, service, mtime_test, strerror (errno));
407 free (mtime_test); 407 free (mtime_test);
408 mtime_test = NULL; 408 mtime_test = NULL;
409 } 409 }
410} 410}
411 411
449 depoptions |= RC_DEP_STRICT; 449 depoptions |= RC_DEP_STRICT;
450 450
451 if (rc_is_env ("IN_HOTPLUG", "1") || in_background) 451 if (rc_is_env ("IN_HOTPLUG", "1") || in_background)
452 { 452 {
453 if (! rc_service_state (service, rc_service_inactive)) 453 if (! rc_service_state (service, rc_service_inactive))
454 exit (EXIT_FAILURE); 454 exit (EXIT_FAILURE);
455 background = true; 455 background = true;
456 } 456 }
457 457
458 if (rc_service_state (service, rc_service_started)) 458 if (rc_service_state (service, rc_service_started))
459 ewarnx ("WARNING: %s has already been started", applet); 459 ewarnx ("WARNING: %s has already been started", applet);
470 make_exclusive (service); 470 make_exclusive (service);
471 471
472 if (deps) 472 if (deps)
473 { 473 {
474 if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) 474 if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
475 eerrorx ("failed to load deptree"); 475 eerrorx ("failed to load deptree");
476 476
477 rc_strlist_free (types); 477 rc_strlist_free (types);
478 types = rc_strlist_add (NULL, "broken"); 478 types = rc_strlist_add (NULL, "broken");
479 rc_strlist_free (svclist); 479 rc_strlist_free (svclist);
480 svclist = rc_strlist_add (NULL, applet); 480 svclist = rc_strlist_add (NULL, applet);
481 rc_strlist_free (services); 481 rc_strlist_free (services);
482 services = rc_get_depends (deptree, types, svclist, softlevel, 0); 482 services = rc_get_depends (deptree, types, svclist, softlevel, 0);
483 if (services) 483 if (services)
484 { 484 {
485 eerrorn ("ERROR: `%s' needs ", applet); 485 eerrorn ("ERROR: `%s' needs ", applet);
486 STRLIST_FOREACH (services, svc, i) 486 STRLIST_FOREACH (services, svc, i)
487 { 487 {
488 if (i > 0) 488 if (i > 0)
489 fprintf (stderr, ", "); 489 fprintf (stderr, ", ");
490 fprintf (stderr, "%s", svc); 490 fprintf (stderr, "%s", svc);
491 } 491 }
492 exit (EXIT_FAILURE); 492 exit (EXIT_FAILURE);
493 } 493 }
494 rc_strlist_free (services); 494 rc_strlist_free (services);
495 services = NULL; 495 services = NULL;
496 496
497 rc_strlist_free (types); 497 rc_strlist_free (types);
498 types = rc_strlist_add (NULL, "ineed"); 498 types = rc_strlist_add (NULL, "ineed");
499 rc_strlist_free (need_services); 499 rc_strlist_free (need_services);
500 need_services = rc_get_depends (deptree, types, svclist, 500 need_services = rc_get_depends (deptree, types, svclist,
501 softlevel, depoptions); 501 softlevel, depoptions);
502 types = rc_strlist_add (types, "iuse"); 502 types = rc_strlist_add (types, "iuse");
503 if (! rc_runlevel_starting ()) 503 if (! rc_runlevel_starting ())
504 { 504 {
505 services = rc_get_depends (deptree, types, svclist, 505 services = rc_get_depends (deptree, types, svclist,
506 softlevel, depoptions); 506 softlevel, depoptions);
507 STRLIST_FOREACH (services, svc, i) 507 STRLIST_FOREACH (services, svc, i)
508 if (rc_service_state (svc, rc_service_stopped)) 508 if (rc_service_state (svc, rc_service_stopped))
509 rc_start_service (svc); 509 rc_start_service (svc);
510 510
511 rc_strlist_free (services); 511 rc_strlist_free (services);
512 } 512 }
513 513
514 /* Now wait for them to start */ 514 /* Now wait for them to start */
515 types = rc_strlist_add (types, "iafter"); 515 types = rc_strlist_add (types, "iafter");
516 services = rc_get_depends (deptree, types, svclist, 516 services = rc_get_depends (deptree, types, svclist,
517 softlevel, depoptions); 517 softlevel, depoptions);
518 518
519 /* We use tmplist to hold our scheduled by list */ 519 /* We use tmplist to hold our scheduled by list */
520 rc_strlist_free (tmplist); 520 rc_strlist_free (tmplist);
521 tmplist = NULL; 521 tmplist = NULL;
522 522
523 STRLIST_FOREACH (services, svc, i) 523 STRLIST_FOREACH (services, svc, i)
524 { 524 {
525 if (rc_service_state (svc, rc_service_started)) 525 if (rc_service_state (svc, rc_service_started))
526 continue; 526 continue;
527 if (! rc_wait_service (svc)) 527 if (! rc_wait_service (svc))
528 eerror ("%s: timed out waiting for %s", applet, svc); 528 eerror ("%s: timed out waiting for %s", applet, svc);
529 if (rc_service_state (svc, rc_service_started)) 529 if (rc_service_state (svc, rc_service_started))
530 continue; 530 continue;
531 531
532 STRLIST_FOREACH (need_services, svc2, j) 532 STRLIST_FOREACH (need_services, svc2, j)
533 if (strcmp (svc, svc2) == 0) 533 if (strcmp (svc, svc2) == 0)
534 { 534 {
535 if (rc_service_state (svc, rc_service_inactive) || 535 if (rc_service_state (svc, rc_service_inactive) ||
536 rc_service_state (svc, rc_service_wasinactive)) 536 rc_service_state (svc, rc_service_wasinactive))
537 tmplist = rc_strlist_add (tmplist, svc); 537 tmplist = rc_strlist_add (tmplist, svc);
538 else 538 else
539 eerrorx ("ERROR: cannot start %s as %s would not start", 539 eerrorx ("ERROR: cannot start %s as %s would not start",
540 applet, svc); 540 applet, svc);
541 }
541 } 542 }
542 }
543 543
544 if (tmplist) 544 if (tmplist)
545 { 545 {
546 int n = 0; 546 int n = 0;
547 int len = 0; 547 int len = 0;
548 char *p; 548 char *p;
549 549
550 /* Set the state now, then unlink our exclusive so that 550 /* Set the state now, then unlink our exclusive so that
551 our scheduled list is preserved */ 551 our scheduled list is preserved */
552 rc_mark_service (service, rc_service_stopped); 552 rc_mark_service (service, rc_service_stopped);
553 unlink_mtime_test (); 553 unlink_mtime_test ();
554 554
555 rc_strlist_free (types); 555 rc_strlist_free (types);
556 types = rc_strlist_add (NULL, "iprovide"); 556 types = rc_strlist_add (NULL, "iprovide");
557 STRLIST_FOREACH (tmplist, svc, i) 557 STRLIST_FOREACH (tmplist, svc, i)
558 { 558 {
559 rc_schedule_start_service (svc, service); 559 rc_schedule_start_service (svc, service);
560 560
561 rc_strlist_free (svclist); 561 rc_strlist_free (svclist);
562 svclist = rc_strlist_add (NULL, svc); 562 svclist = rc_strlist_add (NULL, svc);
563 rc_strlist_free (providelist); 563 rc_strlist_free (providelist);
564 providelist = rc_get_depends (deptree, types, svclist, 564 providelist = rc_get_depends (deptree, types, svclist,
565 softlevel, depoptions); 565 softlevel, depoptions);
566 STRLIST_FOREACH (providelist, svc2, j) 566 STRLIST_FOREACH (providelist, svc2, j)
567 rc_schedule_start_service (svc2, service); 567 rc_schedule_start_service (svc2, service);
568 568
569 len += strlen (svc) + 2; 569 len += strlen (svc) + 2;
570 n++; 570 n++;
571 } 571 }
572 572
573 len += 5; 573 len += 5;
574 tmp = rc_xmalloc (sizeof (char *) * len); 574 tmp = rc_xmalloc (sizeof (char *) * len);
575 p = tmp; 575 p = tmp;
576 STRLIST_FOREACH (tmplist, svc, i) 576 STRLIST_FOREACH (tmplist, svc, i)
577 { 577 {
578 if (i > 1) 578 if (i > 1)
579 { 579 {
580 if (i == n - 1) 580 if (i == n - 1)
581 p += snprintf (p, len, " or "); 581 p += snprintf (p, len, " or ");
582 else 582 else
583 p += snprintf (p, len, ", "); 583 p += snprintf (p, len, ", ");
584 } 584 }
585 p += snprintf (p, len, "%s", svc); 585 p += snprintf (p, len, "%s", svc);
586 } 586 }
587 ewarnx ("WARNING: %s is scheduled to start when %s has started", 587 ewarnx ("WARNING: %s is scheduled to start when %s has started",
588 applet, tmp); 588 applet, tmp);
589 } 589 }
590 590
591 rc_strlist_free (services); 591 rc_strlist_free (services);
592 services = NULL; 592 services = NULL;
593 rc_strlist_free (types); 593 rc_strlist_free (types);
594 types = NULL; 594 types = NULL;
605 unsetenv ("IN_BACKGROUND"); 605 unsetenv ("IN_BACKGROUND");
606 606
607 if (in_control ()) 607 if (in_control ())
608 { 608 {
609 if (! started) 609 if (! started)
610 { 610 {
611 if (rc_service_state (service, rc_service_wasinactive)) 611 if (rc_service_state (service, rc_service_wasinactive))
612 rc_mark_service (service, rc_service_inactive); 612 rc_mark_service (service, rc_service_inactive);
613 else 613 else
614 { 614 {
615 rc_mark_service (service, rc_service_stopped); 615 rc_mark_service (service, rc_service_stopped);
616 if (rc_runlevel_starting ()) 616 if (rc_runlevel_starting ())
617 rc_mark_service (service, rc_service_failed); 617 rc_mark_service (service, rc_service_failed);
618 } 618 }
619 eerrorx ("ERROR: %s failed to start", applet); 619 eerrorx ("ERROR: %s failed to start", applet);
620 } 620 }
621 621
622 rc_mark_service (service, rc_service_started); 622 rc_mark_service (service, rc_service_started);
623 unlink_mtime_test (); 623 unlink_mtime_test ();
624 624
625 hook_out = 0; 625 hook_out = 0;
626 rc_plugin_run (rc_hook_service_start_out, applet); 626 rc_plugin_run (rc_hook_service_start_out, applet);
627 } 627 }
628 else 628 else
629 { 629 {
630 if (rc_service_state (service, rc_service_inactive)) 630 if (rc_service_state (service, rc_service_inactive))
631 ewarn ("WARNING: %s has started, but is inactive", applet); 631 ewarn ("WARNING: %s has started, but is inactive", applet);
632 else 632 else
633 ewarn ("WARNING: %s not under our control, aborting", applet); 633 ewarn ("WARNING: %s not under our control, aborting", applet);
634 } 634 }
635 635
636 /* Now start any scheduled services */ 636 /* Now start any scheduled services */
637 rc_strlist_free (services); 637 rc_strlist_free (services);
638 services = rc_services_scheduled (service); 638 services = rc_services_scheduled (service);
654 { 654 {
655 rc_strlist_free (services); 655 rc_strlist_free (services);
656 services = rc_services_scheduled (svc2); 656 services = rc_services_scheduled (svc2);
657 STRLIST_FOREACH (services, svc, i) 657 STRLIST_FOREACH (services, svc, i)
658 if (rc_service_state (svc, rc_service_stopped)) 658 if (rc_service_state (svc, rc_service_stopped))
659 rc_start_service (svc); 659 rc_start_service (svc);
660 } 660 }
661} 661}
662 662
663static void svc_stop (const char *service, bool deps) 663static void svc_stop (const char *service, bool deps)
664{ 664{
681 eerrorx ("ERROR: %s has been stopped by something else", applet); 681 eerrorx ("ERROR: %s has been stopped by something else", applet);
682 682
683 make_exclusive (service); 683 make_exclusive (service);
684 684
685 if (! rc_runlevel_stopping () && 685 if (! rc_runlevel_stopping () &&
686 rc_service_in_runlevel (service, RC_LEVEL_BOOT)) 686 rc_service_in_runlevel (service, RC_LEVEL_BOOT))
687 ewarn ("WARNING: you are stopping a boot service"); 687 ewarn ("WARNING: you are stopping a boot service");
688 688
689 if (deps || ! rc_service_state (service, rc_service_wasinactive)) 689 if (deps || ! rc_service_state (service, rc_service_wasinactive))
690 { 690 {
691 int depoptions = RC_DEP_TRACE; 691 int depoptions = RC_DEP_TRACE;
692 char *svc; 692 char *svc;
693 int i; 693 int i;
694 694
695 if (rc_is_env ("RC_STRICT_DEPEND", "yes")) 695 if (rc_is_env ("RC_STRICT_DEPEND", "yes"))
696 depoptions |= RC_DEP_STRICT; 696 depoptions |= RC_DEP_STRICT;
697 697
698 if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) 698 if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
699 eerrorx ("failed to load deptree"); 699 eerrorx ("failed to load deptree");
700 700
701 rc_strlist_free (types); 701 rc_strlist_free (types);
702 types = rc_strlist_add (NULL, "needsme"); 702 types = rc_strlist_add (NULL, "needsme");
703 rc_strlist_free (svclist); 703 rc_strlist_free (svclist);
704 svclist = rc_strlist_add (NULL, applet); 704 svclist = rc_strlist_add (NULL, applet);
705 rc_strlist_free (tmplist); 705 rc_strlist_free (tmplist);
706 tmplist = NULL; 706 tmplist = NULL;
707 rc_strlist_free (services); 707 rc_strlist_free (services);
708 services = rc_get_depends (deptree, types, svclist, 708 services = rc_get_depends (deptree, types, svclist,
709 softlevel, depoptions); 709 softlevel, depoptions);
710 rc_strlist_reverse (services); 710 rc_strlist_reverse (services);
711 STRLIST_FOREACH (services, svc, i) 711 STRLIST_FOREACH (services, svc, i)
712 { 712 {
713 if (rc_service_state (svc, rc_service_started) ||
714 rc_service_state (svc, rc_service_inactive))
715 {
716 rc_wait_service (svc);
717 if (rc_service_state (svc, rc_service_started) || 713 if (rc_service_state (svc, rc_service_started) ||
718 rc_service_state (svc, rc_service_inactive)) 714 rc_service_state (svc, rc_service_inactive))
719 { 715 {
720 rc_stop_service (svc); 716 rc_wait_service (svc);
717 if (rc_service_state (svc, rc_service_started) ||
718 rc_service_state (svc, rc_service_inactive))
719 {
720 rc_stop_service (svc);
721 tmplist = rc_strlist_add (tmplist, svc); 721 tmplist = rc_strlist_add (tmplist, svc);
722 } 722 }
723 } 723 }
724 } 724 }
725 rc_strlist_free (services); 725 rc_strlist_free (services);
726 services = NULL; 726 services = NULL;
727 727
728 STRLIST_FOREACH (tmplist, svc, i) 728 STRLIST_FOREACH (tmplist, svc, i)
729 { 729 {
730 if (rc_service_state (svc, rc_service_stopped)) 730 if (rc_service_state (svc, rc_service_stopped))
731 continue; 731 continue;
732 732
733 /* We used to loop 3 times here - maybe re-do this if needed */ 733 /* We used to loop 3 times here - maybe re-do this if needed */
734 rc_wait_service (svc); 734 rc_wait_service (svc);
735 if (! rc_service_state (svc, rc_service_stopped)) 735 if (! rc_service_state (svc, rc_service_stopped))
736 { 736 {
737 if (rc_runlevel_stopping ()) 737 if (rc_runlevel_stopping ())
738 rc_mark_service (svc, rc_service_failed); 738 rc_mark_service (svc, rc_service_failed);
739 eerrorx ("ERROR: cannot stop %s as %s is still up", 739 eerrorx ("ERROR: cannot stop %s as %s is still up",
740 applet, svc); 740 applet, svc);
741 } 741 }
742 } 742 }
743 rc_strlist_free (tmplist); 743 rc_strlist_free (tmplist);
744 tmplist = NULL; 744 tmplist = NULL;
745 745
746 /* We now wait for other services that may use us and are stopping 746 /* We now wait for other services that may use us and are stopping
747 This is important when a runlevel stops */ 747 This is important when a runlevel stops */
748 types = rc_strlist_add (types, "usesme"); 748 types = rc_strlist_add (types, "usesme");
749 types = rc_strlist_add (types, "ibefore"); 749 types = rc_strlist_add (types, "ibefore");
750 services = rc_get_depends (deptree, types, svclist, 750 services = rc_get_depends (deptree, types, svclist,
751 softlevel, depoptions); 751 softlevel, depoptions);
752 STRLIST_FOREACH (services, svc, i) 752 STRLIST_FOREACH (services, svc, i)
753 { 753 {
754 if (rc_service_state (svc, rc_service_stopped)) 754 if (rc_service_state (svc, rc_service_stopped))
755 continue; 755 continue;
756 rc_wait_service (svc); 756 rc_wait_service (svc);
757 } 757 }
758 758
759 rc_strlist_free (services); 759 rc_strlist_free (services);
760 services = NULL; 760 services = NULL;
761 rc_strlist_free (types); 761 rc_strlist_free (types);
762 types = NULL; 762 types = NULL;
774 ewarnx ("WARNING: %s not under our control, aborting", applet); 774 ewarnx ("WARNING: %s not under our control, aborting", applet);
775 775
776 if (! stopped) 776 if (! stopped)
777 { 777 {
778 if (rc_service_state (service, rc_service_wasinactive)) 778 if (rc_service_state (service, rc_service_wasinactive))
779 rc_mark_service (service, rc_service_inactive); 779 rc_mark_service (service, rc_service_inactive);
780 else 780 else
781 rc_mark_service (service, rc_service_started); 781 rc_mark_service (service, rc_service_started);
782 eerrorx ("ERROR: %s failed to stop", applet); 782 eerrorx ("ERROR: %s failed to stop", applet);
783 } 783 }
784 784
785 if (in_background) 785 if (in_background)
786 rc_mark_service (service, rc_service_inactive); 786 rc_mark_service (service, rc_service_inactive);
795static void svc_restart (const char *service, bool deps) 795static void svc_restart (const char *service, bool deps)
796{ 796{
797 char *svc; 797 char *svc;
798 int i; 798 int i;
799 bool inactive = false; 799 bool inactive = false;
800 800
801 /* This is hairly and a better way needs to be found I think! 801 /* This is hairly and a better way needs to be found I think!
802 The issue is this - openvpn need net and dns. net can restart 802 The issue is this - openvpn need net and dns. net can restart
803 dns via resolvconf, so you could have openvpn trying to restart dnsmasq 803 dns via resolvconf, so you could have openvpn trying to restart dnsmasq
804 which in turn is waiting on net which in turn is waiting on dnsmasq. 804 which in turn is waiting on net which in turn is waiting on dnsmasq.
805 The work around is for resolvconf to restart it's services with --nodeps 805 The work around is for resolvconf to restart it's services with --nodeps
807 our status is invalid. 807 our status is invalid.
808 One workaround would be to introduce a new status, or status locking. */ 808 One workaround would be to introduce a new status, or status locking. */
809 if (! deps) 809 if (! deps)
810 { 810 {
811 if (rc_service_state (service, rc_service_started) || 811 if (rc_service_state (service, rc_service_started) ||
812 rc_service_state (service, rc_service_inactive)) 812 rc_service_state (service, rc_service_inactive))
813 svc_exec (service, "stop", "start"); 813 svc_exec (service, "stop", "start");
814 else 814 else
815 svc_exec (service, "start", NULL); 815 svc_exec (service, "start", NULL);
816 return; 816 return;
817 } 817 }
818 818
819 if (! rc_service_state (service, rc_service_stopped)) 819 if (! rc_service_state (service, rc_service_stopped))
820 { 820 {
828 svc_start (service, deps); 828 svc_start (service, deps);
829 829
830 inactive = rc_service_state (service, rc_service_inactive); 830 inactive = rc_service_state (service, rc_service_inactive);
831 if (! inactive) 831 if (! inactive)
832 inactive = rc_service_state (service, rc_service_wasinactive); 832 inactive = rc_service_state (service, rc_service_wasinactive);
833 833
834 if (inactive || 834 if (inactive ||
835 rc_service_state (service, rc_service_starting) || 835 rc_service_state (service, rc_service_starting) ||
836 rc_service_state (service, rc_service_started)) 836 rc_service_state (service, rc_service_started))
837 { 837 {
838 STRLIST_FOREACH (restart_services, svc, i) 838 STRLIST_FOREACH (restart_services, svc, i)
839 { 839 {
840 if (rc_service_state (svc, rc_service_stopped)) 840 if (rc_service_state (svc, rc_service_stopped))
841 { 841 {
842 if (inactive) 842 if (inactive)
843 { 843 {
844 rc_schedule_start_service (service, svc); 844 rc_schedule_start_service (service, svc);
845 ewarn ("WARNING: %s is scheduled to started when %s has started", 845 ewarn ("WARNING: %s is scheduled to started when %s has started",
846 svc, basename (service)); 846 svc, basename (service));
847 } 847 }
848 else 848 else
849 rc_start_service (svc); 849 rc_start_service (svc);
850 } 850 }
851 } 851 }
852 } 852 }
853} 853}
854 854
855int main (int argc, char **argv) 855int main (int argc, char **argv)
856{ 856{
868 /* Show help if insufficient args */ 868 /* Show help if insufficient args */
869 if (argc < 3) 869 if (argc < 3)
870 { 870 {
871 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL); 871 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
872 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s", 872 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
873 applet, strerror (errno)); 873 applet, strerror (errno));
874 } 874 }
875 875
876#ifdef __linux__ 876#ifdef __linux__
877 /* coldplug events can trigger init scripts, but we don't want to run them 877 /* coldplug events can trigger init scripts, but we don't want to run them
878 until after rc sysinit has completed so we punt them to the boot runlevel */ 878 until after rc sysinit has completed so we punt them to the boot runlevel */
879 if (rc_exists ("/dev/.rcsysinit")) 879 if (rc_exists ("/dev/.rcsysinit"))
880 { 880 {
881 eerror ("%s: cannot run until sysvinit completes", applet); 881 eerror ("%s: cannot run until sysvinit completes", applet);
882 if (mkdir ("/dev/.rcboot", 0755) != 0 && errno != EEXIST) 882 if (mkdir ("/dev/.rcboot", 0755) != 0 && errno != EEXIST)
883 eerrorx ("%s: mkdir `/dev/.rcboot': %s", applet, strerror (errno)); 883 eerrorx ("%s: mkdir `/dev/.rcboot': %s", applet, strerror (errno));
884 tmp = rc_strcatpaths ("/dev/.rcboot", applet, (char *) NULL); 884 tmp = rc_strcatpaths ("/dev/.rcboot", applet, (char *) NULL);
885 symlink (service, tmp); 885 symlink (service, tmp);
886 exit (EXIT_FAILURE); 886 exit (EXIT_FAILURE);
887 } 887 }
888#endif 888#endif
889 889
890 if ((softlevel = getenv ("RC_SOFTLEVEL")) == NULL) 890 if ((softlevel = getenv ("RC_SOFTLEVEL")) == NULL)
891 { 891 {
892 /* Ensure our environment is pure 892 /* Ensure our environment is pure
893 Also, add our configuration to it */ 893 Also, add our configuration to it */
894 env = rc_filter_env (); 894 env = rc_filter_env ();
895 env = rc_config_env (env); 895 env = rc_config_env (env);
896 896
897 if (env) 897 if (env)
898 { 898 {
899 char *p; 899 char *p;
900 900
901#ifdef __linux__ 901#ifdef __linux__
902 /* clearenv isn't portable, but there's no harm in using it 902 /* clearenv isn't portable, but there's no harm in using it
903 if we have it */ 903 if we have it */
904 clearenv (); 904 clearenv ();
905#else 905#else
906 char *var; 906 char *var;
907 /* No clearenv present here then. 907 /* No clearenv present here then.
908 We could manipulate environ directly ourselves, but it seems that 908 We could manipulate environ directly ourselves, but it seems that
909 some kernels bitch about this according to the environ man pages 909 some kernels bitch about this according to the environ man pages
910 so we walk though environ and call unsetenv for each value. */ 910 so we walk though environ and call unsetenv for each value. */
911 while (environ[0]) 911 while (environ[0])
912 { 912 {
913 tmp = rc_xstrdup (environ[0]); 913 tmp = rc_xstrdup (environ[0]);
914 p = tmp; 914 p = tmp;
915 var = strsep (&p, "="); 915 var = strsep (&p, "=");
916 unsetenv (var); 916 unsetenv (var);
917 free (tmp); 917 free (tmp);
918 } 918 }
919 tmp = NULL; 919 tmp = NULL;
920#endif 920#endif
921 921
922 STRLIST_FOREACH (env, p, i) 922 STRLIST_FOREACH (env, p, i)
923 putenv (p); 923 putenv (p);
924 924
925 /* We don't free our list as that would be null in environ */ 925 /* We don't free our list as that would be null in environ */
926 } 926 }
927 927
928 softlevel = rc_get_runlevel (); 928 softlevel = rc_get_runlevel ();
929 929
930 /* If not called from RC or another service then don't be parallel */ 930 /* If not called from RC or another service then don't be parallel */
931 unsetenv ("RC_PARALLEL_STARTUP"); 931 unsetenv ("RC_PARALLEL_STARTUP");
967 967
968 /* Right then, parse any options there may be */ 968 /* Right then, parse any options there may be */
969 for (i = 2; i < argc; i++) 969 for (i = 2; i < argc; i++)
970 { 970 {
971 if (strlen (argv[i]) < 2 || argv[i][0] != '-' || argv[i][1] != '-') 971 if (strlen (argv[i]) < 2 || argv[i][0] != '-' || argv[i][1] != '-')
972 continue; 972 continue;
973 973
974 if (strcmp (argv[i], "--debug") == 0) 974 if (strcmp (argv[i], "--debug") == 0)
975 setenv ("RC_DEBUG", "yes", 1); 975 setenv ("RC_DEBUG", "yes", 1);
976 else if (strcmp (argv[i], "--help") == 0) 976 else if (strcmp (argv[i], "--help") == 0)
977 { 977 {
978 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL); 978 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
979 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s", 979 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
980 applet, strerror (errno)); 980 applet, strerror (errno));
981 } 981 }
982 else if (strcmp (argv[i],"--ifstarted") == 0) 982 else if (strcmp (argv[i],"--ifstarted") == 0)
983 ifstarted = true; 983 ifstarted = true;
984 else if (strcmp (argv[i], "--nocolour") == 0 || 984 else if (strcmp (argv[i], "--nocolour") == 0 ||
985 strcmp (argv[i], "--nocolor") == 0) 985 strcmp (argv[i], "--nocolor") == 0)
986 setenv ("RC_NOCOLOR", "yes", 1); 986 setenv ("RC_NOCOLOR", "yes", 1);
987 else if (strcmp (argv[i], "--nodeps") == 0) 987 else if (strcmp (argv[i], "--nodeps") == 0)
988 deps = false; 988 deps = false;
989 else if (strcmp (argv[i], "--quiet") == 0) 989 else if (strcmp (argv[i], "--quiet") == 0)
990 setenv ("RC_QUIET", "yes", 1); 990 setenv ("RC_QUIET", "yes", 1);
991 else if (strcmp (argv[i], "--verbose") == 0) 991 else if (strcmp (argv[i], "--verbose") == 0)
992 setenv ("RC_VERBOSE", "yes", 1); 992 setenv ("RC_VERBOSE", "yes", 1);
993 else if (strcmp (argv[i], "--version") == 0) 993 else if (strcmp (argv[i], "--version") == 0)
994 printf ("version me\n"); 994 printf ("version me\n");
995 else 995 else
996 eerror ("%s: unknown option `%s'", applet, argv[i]); 996 eerror ("%s: unknown option `%s'", applet, argv[i]);
997 } 997 }
998 998
999 if (ifstarted && ! rc_service_state (applet, rc_service_started)) 999 if (ifstarted && ! rc_service_state (applet, rc_service_started))
1000 { 1000 {
1001 if (! rc_is_env("RC_QUIET", "yes")) 1001 if (! rc_is_env("RC_QUIET", "yes"))
1002 eerror ("ERROR: %s is not started", applet); 1002 eerror ("ERROR: %s is not started", applet);
1003 exit (EXIT_FAILURE); 1003 exit (EXIT_FAILURE);
1004 } 1004 }
1005 1005
1006 if (rc_is_env ("IN_HOTPLUG", "1")) 1006 if (rc_is_env ("IN_HOTPLUG", "1"))
1007 { 1007 {
1008 if (! rc_is_env ("RC_HOTPLUG", "yes") || ! rc_allow_plug (applet)) 1008 if (! rc_is_env ("RC_HOTPLUG", "yes") || ! rc_allow_plug (applet))
1009 eerrorx ("%s: not allowed to be hotplugged", applet); 1009 eerrorx ("%s: not allowed to be hotplugged", applet);
1010 } 1010 }
1011 1011
1012 /* Setup a signal handler */ 1012 /* Setup a signal handler */
1013 signal (SIGHUP, handle_signal); 1013 signal (SIGHUP, handle_signal);
1014 signal (SIGINT, handle_signal); 1014 signal (SIGINT, handle_signal);
1023 retval = EXIT_SUCCESS; 1023 retval = EXIT_SUCCESS;
1024 for (i = 2; i < argc; i++) 1024 for (i = 2; i < argc; i++)
1025 { 1025 {
1026 /* Abort on a sighup here */ 1026 /* Abort on a sighup here */
1027 if (sighup) 1027 if (sighup)
1028 exit (EXIT_FAILURE); 1028 exit (EXIT_FAILURE);
1029 1029
1030 if (strlen (argv[i]) < 2 || 1030 if (strlen (argv[i]) < 2 ||
1031 (argv[i][0] == '-' && argv[i][1] == '-')) 1031 (argv[i][0] == '-' && argv[i][1] == '-'))
1032 continue; 1032 continue;
1033 1033
1034 /* Export the command we're running. 1034 /* Export the command we're running.
1035 This is important as we stamp on the restart function now but 1035 This is important as we stamp on the restart function now but
1036 some start/stop routines still need to behave differently if 1036 some start/stop routines still need to behave differently if
1037 restarting. */ 1037 restarting. */
1038 unsetenv ("RC_CMD"); 1038 unsetenv ("RC_CMD");
1039 setenv ("RC_CMD", argv[i], 1); 1039 setenv ("RC_CMD", argv[i], 1);
1040 1040
1041 doneone = true; 1041 doneone = true;
1042 if (strcmp (argv[i], "conditionalrestart") == 0 || 1042 if (strcmp (argv[i], "conditionalrestart") == 0 ||
1043 strcmp (argv[i], "condrestart") == 0) 1043 strcmp (argv[i], "condrestart") == 0)
1044 { 1044 {
1045 if (rc_service_state (service, rc_service_started)) 1045 if (rc_service_state (service, rc_service_started))
1046 svc_restart (service, deps); 1046 svc_restart (service, deps);
1047 } 1047 }
1048 else if (strcmp (argv[i], "restart") == 0) 1048 else if (strcmp (argv[i], "restart") == 0)
1049 svc_restart (service, deps); 1049 svc_restart (service, deps);
1050 else if (strcmp (argv[i], "start") == 0) 1050 else if (strcmp (argv[i], "start") == 0)
1051 svc_start (service, deps); 1051 svc_start (service, deps);
1052 else if (strcmp (argv[i], "status") == 0) 1052 else if (strcmp (argv[i], "status") == 0)
1053 { 1053 {
1054 rc_service_state_t r = svc_status (service); 1054 rc_service_state_t r = svc_status (service);
1055 retval = (int) r; 1055 retval = (int) r;
1056 } 1056 }
1057 else if (strcmp (argv[i], "stop") == 0) 1057 else if (strcmp (argv[i], "stop") == 0)
1058 { 1058 {
1059 if (in_background) 1059 if (in_background)
1060 get_started_services (); 1060 get_started_services ();
1061 1061
1062 svc_stop (service, deps); 1062 svc_stop (service, deps);
1063 1063
1064 if (! in_background && 1064 if (! in_background &&
1065 ! rc_runlevel_stopping () && 1065 ! rc_runlevel_stopping () &&
1066 rc_service_state (service, rc_service_stopped)) 1066 rc_service_state (service, rc_service_stopped))
1067 uncoldplug (applet); 1067 uncoldplug (applet);
1068 1068
1069 if (in_background && 1069 if (in_background &&
1070 rc_service_state (service, rc_service_inactive)) 1070 rc_service_state (service, rc_service_inactive))
1071 { 1071 {
1072 char *svc; 1072 char *svc;
1073 int j; 1073 int j;
1074 STRLIST_FOREACH (restart_services, svc, j) 1074 STRLIST_FOREACH (restart_services, svc, j)
1075 if (rc_service_state (svc, rc_service_stopped)) 1075 if (rc_service_state (svc, rc_service_stopped))
1076 rc_schedule_start_service (service, svc); 1076 rc_schedule_start_service (service, svc);
1077 } 1077 }
1078 } 1078 }
1079 else if (strcmp (argv[i], "zap") == 0) 1079 else if (strcmp (argv[i], "zap") == 0)
1080 { 1080 {
1081 einfo ("Manually resetting %s to stopped state", applet); 1081 einfo ("Manually resetting %s to stopped state", applet);
1082 rc_mark_service (applet, rc_service_stopped); 1082 rc_mark_service (applet, rc_service_stopped);
1083 uncoldplug (applet); 1083 uncoldplug (applet);
1084 } 1084 }
1085 else if (strcmp (argv[i], "help") == 0) 1085 else if (strcmp (argv[i], "help") == 0)
1086 { 1086 {
1087 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL); 1087 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL);
1088 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s", 1088 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1089 applet, strerror (errno)); 1089 applet, strerror (errno));
1090 } 1090 }
1091 else 1091 else
1092 svc_exec (service, argv[i], NULL); 1092 svc_exec (service, argv[i], NULL);
1093 1093
1094 /* Flush our buffered output if any */ 1094 /* Flush our buffered output if any */
1095 eflush (); 1095 eflush ();
1096 1096
1097 /* We should ensure this list is empty after an action is done */ 1097 /* We should ensure this list is empty after an action is done */
1101 1101
1102 if (! doneone) 1102 if (! doneone)
1103 { 1103 {
1104 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL); 1104 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
1105 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s", 1105 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1106 applet, strerror (errno)); 1106 applet, strerror (errno));
1107 } 1107 }
1108 1108
1109 return (retval); 1109 return (retval);
1110} 1110}

Legend:
Removed from v.2567  
changed lines
  Added in v.2569

  ViewVC Help
Powered by ViewVC 1.1.20