| … | |
… | |
| 67 | int i; |
67 | int i; |
| 68 | char *dir; |
68 | char *dir; |
| 69 | |
69 | |
| 70 | STRLIST_FOREACH (dirs, dir, i) |
70 | STRLIST_FOREACH (dirs, dir, i) |
| 71 | { |
71 | { |
| 72 | char *path = rc_strcatpaths (RC_RUNLEVELDIR, dir, NULL); |
72 | char *path = rc_strcatpaths (RC_RUNLEVELDIR, dir, (char *) NULL); |
| 73 | if (rc_is_dir (path)) |
73 | if (rc_is_dir (path)) |
| 74 | runlevels = rc_strlist_addsort (runlevels, dir); |
74 | runlevels = rc_strlist_addsort (runlevels, dir); |
| 75 | free (path); |
75 | free (path); |
| 76 | } |
76 | } |
| 77 | rc_strlist_free (dirs); |
77 | rc_strlist_free (dirs); |
| … | |
… | |
| 119 | bool retval; |
119 | bool retval; |
| 120 | |
120 | |
| 121 | if (! runlevel) |
121 | if (! runlevel) |
| 122 | return (false); |
122 | return (false); |
| 123 | |
123 | |
| 124 | path = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, NULL); |
124 | path = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL); |
| 125 | retval = rc_is_dir (path); |
125 | retval = rc_is_dir (path); |
| 126 | free (path); |
126 | free (path); |
| 127 | return (retval); |
127 | return (retval); |
| 128 | } |
128 | } |
| 129 | |
129 | |
| … | |
… | |
| 138 | return (NULL); |
138 | return (NULL); |
| 139 | |
139 | |
| 140 | if (service[0] == '/') |
140 | if (service[0] == '/') |
| 141 | return (strdup (service)); |
141 | return (strdup (service)); |
| 142 | |
142 | |
| 143 | file = rc_strcatpaths (RC_SVCDIR, "started", service, NULL); |
143 | file = rc_strcatpaths (RC_SVCDIR, "started", service, (char *) NULL); |
| 144 | if (! rc_is_link (file)) |
144 | if (! rc_is_link (file)) |
| 145 | { |
145 | { |
| 146 | free (file); |
146 | free (file); |
| 147 | file = rc_strcatpaths (RC_SVCDIR, "inactive", service, NULL); |
147 | file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL); |
| 148 | if (! rc_is_link (file)) |
148 | if (! rc_is_link (file)) |
| 149 | { |
149 | { |
| 150 | free (file); |
150 | free (file); |
| 151 | file = NULL; |
151 | file = NULL; |
| 152 | } |
152 | } |
| … | |
… | |
| 198 | return (false); |
198 | return (false); |
| 199 | |
199 | |
| 200 | if (! rc_service_exists (service)) |
200 | if (! rc_service_exists (service)) |
| 201 | return (false); |
201 | return (false); |
| 202 | |
202 | |
| 203 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), NULL); |
203 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), |
|
|
204 | (char *) NULL); |
| 204 | retval = rc_exists (file); |
205 | retval = rc_exists (file); |
| 205 | free (file); |
206 | free (file); |
| 206 | |
207 | |
| 207 | return (retval); |
208 | return (retval); |
| 208 | } |
209 | } |
| … | |
… | |
| 227 | { |
228 | { |
| 228 | free (init); |
229 | free (init); |
| 229 | return (false); |
230 | return (false); |
| 230 | } |
231 | } |
| 231 | |
232 | |
| 232 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], base, NULL); |
233 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], base, |
|
|
234 | (char *) NULL); |
| 233 | if (rc_exists (file)) |
235 | if (rc_exists (file)) |
| 234 | unlink (file); |
236 | unlink (file); |
| 235 | i = symlink (init, file); |
237 | i = symlink (init, file); |
| 236 | if (i != 0) |
238 | if (i != 0) |
| 237 | { |
239 | { |
| … | |
… | |
| 260 | i != rc_service_stopped && |
262 | i != rc_service_stopped && |
| 261 | i != rc_service_coldplugged && |
263 | i != rc_service_coldplugged && |
| 262 | i != rc_service_crashed) && |
264 | i != rc_service_crashed) && |
| 263 | (! skip_wasinactive || i != rc_service_wasinactive)) |
265 | (! skip_wasinactive || i != rc_service_wasinactive)) |
| 264 | { |
266 | { |
| 265 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i], base, NULL); |
267 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i], base, |
|
|
268 | (char *) NULL); |
| 266 | if (rc_exists (file)) |
269 | if (rc_exists (file)) |
| 267 | { |
270 | { |
| 268 | if ((state == rc_service_starting || |
271 | if ((state == rc_service_starting || |
| 269 | state == rc_service_stopping) && |
272 | state == rc_service_stopping) && |
| 270 | i == rc_service_inactive) |
273 | i == rc_service_inactive) |
| 271 | { |
274 | { |
| 272 | char *wasfile = rc_strcatpaths (RC_SVCDIR, |
275 | char *wasfile = rc_strcatpaths (RC_SVCDIR, |
| 273 | rc_service_state_names[rc_service_wasinactive], |
276 | rc_service_state_names[rc_service_wasinactive], |
| 274 | base, NULL); |
277 | base, (char *) NULL); |
| 275 | |
278 | |
| 276 | if (symlink (init, wasfile) != 0) |
279 | if (symlink (init, wasfile) != 0) |
| 277 | eerror ("symlink `%s' to `%s': %s", init, wasfile, |
280 | eerror ("symlink `%s' to `%s': %s", init, wasfile, |
| 278 | strerror (errno)); |
281 | strerror (errno)); |
| 279 | |
282 | |
| … | |
… | |
| 294 | /* Remove the exclusive state if we're inactive */ |
297 | /* Remove the exclusive state if we're inactive */ |
| 295 | if (state == rc_service_started || |
298 | if (state == rc_service_started || |
| 296 | state == rc_service_stopped || |
299 | state == rc_service_stopped || |
| 297 | state == rc_service_inactive) |
300 | state == rc_service_inactive) |
| 298 | { |
301 | { |
| 299 | file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, NULL); |
302 | file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL); |
| 300 | if (rc_exists (file)) |
303 | if (rc_exists (file)) |
| 301 | if (unlink (file) != 0) |
304 | if (unlink (file) != 0) |
| 302 | eerror ("unlink `%s': %s", file, strerror (errno)); |
305 | eerror ("unlink `%s': %s", file, strerror (errno)); |
| 303 | free (file); |
306 | free (file); |
| 304 | } |
307 | } |
| 305 | |
308 | |
| 306 | /* Remove any options and daemons the service may have stored */ |
309 | /* Remove any options and daemons the service may have stored */ |
| 307 | if (state == rc_service_stopped) |
310 | if (state == rc_service_stopped) |
| 308 | { |
311 | { |
| 309 | char *dir = rc_strcatpaths (RC_SVCDIR, "options", base, NULL); |
312 | char *dir = rc_strcatpaths (RC_SVCDIR, "options", base, (char *) NULL); |
| 310 | |
313 | |
| 311 | if (rc_is_dir (dir)) |
314 | if (rc_is_dir (dir)) |
| 312 | rc_rm_dir (dir, true); |
315 | rc_rm_dir (dir, true); |
| 313 | free (dir); |
316 | free (dir); |
| 314 | |
317 | |
| 315 | dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, NULL); |
318 | dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL); |
| 316 | if (rc_is_dir (dir)) |
319 | if (rc_is_dir (dir)) |
| 317 | rc_rm_dir (dir, true); |
320 | rc_rm_dir (dir, true); |
| 318 | free (dir); |
321 | free (dir); |
| 319 | |
322 | |
| 320 | rc_schedule_clear (service); |
323 | rc_schedule_clear (service); |
| 321 | } |
324 | } |
| 322 | |
325 | |
| 323 | /* These are final states, so remove us from scheduled */ |
326 | /* These are final states, so remove us from scheduled */ |
| 324 | if (state == rc_service_started || state == rc_service_stopped) |
327 | if (state == rc_service_started || state == rc_service_stopped) |
| 325 | { |
328 | { |
| 326 | char *sdir = rc_strcatpaths (RC_SVCDIR, "scheduled", NULL); |
329 | char *sdir = rc_strcatpaths (RC_SVCDIR, "scheduled", (char *) NULL); |
| 327 | char **dirs = rc_ls_dir (NULL, sdir, 0); |
330 | char **dirs = rc_ls_dir (NULL, sdir, 0); |
| 328 | char *dir; |
331 | char *dir; |
| 329 | int serrno; |
332 | int serrno; |
| 330 | |
333 | |
| 331 | STRLIST_FOREACH (dirs, dir, i) |
334 | STRLIST_FOREACH (dirs, dir, i) |
| 332 | { |
335 | { |
| 333 | char *bdir = rc_strcatpaths (sdir, dir, NULL); |
336 | char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL); |
| 334 | file = rc_strcatpaths (bdir, base, NULL); |
337 | file = rc_strcatpaths (bdir, base, (char *) NULL); |
| 335 | if (rc_exists (file)) |
338 | if (rc_exists (file)) |
| 336 | if (unlink (file) != 0) |
339 | if (unlink (file) != 0) |
| 337 | eerror ("unlink `%s': %s", file, strerror (errno)); |
340 | eerror ("unlink `%s': %s", file, strerror (errno)); |
| 338 | free (file); |
341 | free (file); |
| 339 | |
342 | |
| … | |
… | |
| 380 | } |
383 | } |
| 381 | |
384 | |
| 382 | /* Now we just check if a file by the service name rc_exists |
385 | /* Now we just check if a file by the service name rc_exists |
| 383 | in the state dir */ |
386 | in the state dir */ |
| 384 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], |
387 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], |
| 385 | basename (service), NULL); |
388 | basename (service), (char*) NULL); |
| 386 | retval = rc_exists (file); |
389 | retval = rc_exists (file); |
| 387 | free (file); |
390 | free (file); |
| 388 | return (retval); |
391 | return (retval); |
| 389 | } |
392 | } |
| 390 | |
393 | |
| 391 | bool rc_get_service_option (const char *service, const char *option, |
394 | bool rc_get_service_option (const char *service, const char *option, |
| 392 | char *value) |
395 | char *value) |
| 393 | { |
396 | { |
| 394 | FILE *fp; |
397 | FILE *fp; |
| 395 | char buffer[1024]; |
398 | char buffer[RC_LINEBUFFER]; |
| 396 | char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option, NULL); |
399 | char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option, |
|
|
400 | (char *) NULL); |
| 397 | bool retval = false; |
401 | bool retval = false; |
| 398 | |
402 | |
| 399 | if (rc_exists (file)) |
403 | if (rc_exists (file)) |
| 400 | { |
404 | { |
| 401 | if ((fp = fopen (file, "r")) == NULL) |
405 | if ((fp = fopen (file, "r")) == NULL) |
| … | |
… | |
| 419 | |
423 | |
| 420 | bool rc_set_service_option (const char *service, const char *option, |
424 | bool rc_set_service_option (const char *service, const char *option, |
| 421 | const char *value) |
425 | const char *value) |
| 422 | { |
426 | { |
| 423 | FILE *fp; |
427 | FILE *fp; |
| 424 | char *path = rc_strcatpaths (RC_SVCDIR, "options", service, NULL); |
428 | char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL); |
| 425 | char *file = rc_strcatpaths (path, option, NULL); |
429 | char *file = rc_strcatpaths (path, option, (char *) NULL); |
| 426 | bool retval = false; |
430 | bool retval = false; |
| 427 | |
431 | |
| 428 | if (! rc_is_dir (path)) |
432 | if (! rc_is_dir (path)) |
| 429 | { |
433 | { |
| 430 | if (mkdir (path, 0755) != 0) |
434 | if (mkdir (path, 0755) != 0) |
| … | |
… | |
| 466 | free (file); |
470 | free (file); |
| 467 | return (0); |
471 | return (0); |
| 468 | } |
472 | } |
| 469 | |
473 | |
| 470 | /* We create a fifo so that other services can wait until we complete */ |
474 | /* We create a fifo so that other services can wait until we complete */ |
| 471 | fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service), NULL); |
475 | fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service), |
|
|
476 | (char *) NULL); |
| 472 | |
477 | |
| 473 | if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) |
478 | if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) |
| 474 | { |
479 | { |
| 475 | eerror ("unable to create fifo `%s': %s", fifo, strerror (errno)); |
480 | eerror ("unable to create fifo `%s': %s", fifo, strerror (errno)); |
| 476 | free (fifo); |
481 | free (fifo); |
| … | |
… | |
| 480 | |
485 | |
| 481 | if ((pid = fork ()) == 0) |
486 | if ((pid = fork ()) == 0) |
| 482 | { |
487 | { |
| 483 | char *myarg = strdup (arg); |
488 | char *myarg = strdup (arg); |
| 484 | int e = 0; |
489 | int e = 0; |
| 485 | execl (file, file, myarg, NULL); |
490 | execl (file, file, myarg, (char *) NULL); |
| 486 | e = errno; |
491 | e = errno; |
| 487 | free (myarg); |
492 | free (myarg); |
| 488 | unlink (fifo); |
493 | unlink (fifo); |
| 489 | free (fifo); |
494 | free (fifo); |
| 490 | eerrorx ("unable to exec `%s': %s", file, strerror (errno)); |
495 | eerrorx ("unable to exec `%s': %s", file, strerror (errno)); |
| … | |
… | |
| 543 | char *file; |
548 | char *file; |
| 544 | |
549 | |
| 545 | if (! rc_service_exists (service) || ! rc_service_exists (service_to_start)) |
550 | if (! rc_service_exists (service) || ! rc_service_exists (service_to_start)) |
| 546 | return; |
551 | return; |
| 547 | |
552 | |
| 548 | dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), NULL); |
553 | dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), |
|
|
554 | (char *) NULL); |
| 549 | if (! rc_is_dir (dir)) |
555 | if (! rc_is_dir (dir)) |
| 550 | if (mkdir (dir, 0755) != 0) |
556 | if (mkdir (dir, 0755) != 0) |
| 551 | { |
557 | { |
| 552 | eerror ("mkdir `%s': %s", dir, strerror (errno)); |
558 | eerror ("mkdir `%s': %s", dir, strerror (errno)); |
| 553 | free (dir); |
559 | free (dir); |
| 554 | return; |
560 | return; |
| 555 | } |
561 | } |
| 556 | |
562 | |
| 557 | init = rc_resolve_service (service_to_start); |
563 | init = rc_resolve_service (service_to_start); |
| 558 | file = rc_strcatpaths (dir, basename (service_to_start), NULL); |
564 | file = rc_strcatpaths (dir, basename (service_to_start), (char *) NULL); |
| 559 | if (! rc_exists (file) && symlink (init, file) != 0) |
565 | if (! rc_exists (file) && symlink (init, file) != 0) |
| 560 | eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno)); |
566 | eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno)); |
| 561 | |
567 | |
| 562 | free (init); |
568 | free (init); |
| 563 | free (file); |
569 | free (file); |
| 564 | free (dir); |
570 | free (dir); |
| 565 | } |
571 | } |
| 566 | |
572 | |
| 567 | void rc_schedule_clear (const char *service) |
573 | void rc_schedule_clear (const char *service) |
| 568 | { |
574 | { |
| 569 | char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), NULL); |
575 | char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), |
|
|
576 | (char *) NULL); |
| 570 | |
577 | |
| 571 | if (rc_is_dir (dir)) |
578 | if (rc_is_dir (dir)) |
| 572 | rc_rm_dir (dir, true); |
579 | rc_rm_dir (dir, true); |
| 573 | free (dir); |
580 | free (dir); |
| 574 | } |
581 | } |
| 575 | |
582 | |
| 576 | bool rc_wait_service (const char *service) |
583 | bool rc_wait_service (const char *service) |
| 577 | { |
584 | { |
| 578 | char *fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service), NULL); |
585 | char *fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service), |
|
|
586 | (char *) NULL); |
| 579 | struct timeval tv; |
587 | struct timeval tv; |
| 580 | struct timeval stopat; |
588 | struct timeval stopat; |
| 581 | struct timeval now; |
589 | struct timeval now; |
| 582 | bool retval = false; |
590 | bool retval = false; |
| 583 | |
591 | |
| … | |
… | |
| 630 | /* These special levels never contain any services */ |
638 | /* These special levels never contain any services */ |
| 631 | if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 || |
639 | if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 || |
| 632 | strcmp (runlevel, RC_LEVEL_SINGLE) == 0) |
640 | strcmp (runlevel, RC_LEVEL_SINGLE) == 0) |
| 633 | return (NULL); |
641 | return (NULL); |
| 634 | |
642 | |
| 635 | dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, NULL); |
643 | dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL); |
| 636 | if (! rc_is_dir (dir)) |
644 | if (! rc_is_dir (dir)) |
| 637 | eerror ("runlevel `%s' does not exist", runlevel); |
645 | eerror ("runlevel `%s' does not exist", runlevel); |
| 638 | else |
646 | else |
| 639 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
647 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
| 640 | |
648 | |
| … | |
… | |
| 642 | return (list); |
650 | return (list); |
| 643 | } |
651 | } |
| 644 | |
652 | |
| 645 | char **rc_services_in_state (rc_service_state_t state) |
653 | char **rc_services_in_state (rc_service_state_t state) |
| 646 | { |
654 | { |
| 647 | char *dir = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], NULL); |
655 | char *dir = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], |
|
|
656 | (char *) NULL); |
| 648 | char **list = NULL; |
657 | char **list = NULL; |
| 649 | |
658 | |
| 650 | if (rc_is_dir (dir)) |
659 | if (rc_is_dir (dir)) |
| 651 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
660 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
| 652 | |
661 | |
| … | |
… | |
| 671 | errno = EEXIST; |
680 | errno = EEXIST; |
| 672 | return (false); |
681 | return (false); |
| 673 | } |
682 | } |
| 674 | |
683 | |
| 675 | init = rc_resolve_service (service); |
684 | init = rc_resolve_service (service); |
| 676 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), NULL); |
685 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), |
|
|
686 | (char *) NULL); |
| 677 | retval = (symlink (init, file) == 0); |
687 | retval = (symlink (init, file) == 0); |
| 678 | free (init); |
688 | free (init); |
| 679 | free (file); |
689 | free (file); |
| 680 | return (retval); |
690 | return (retval); |
| 681 | } |
691 | } |
| … | |
… | |
| 686 | bool retval = false; |
696 | bool retval = false; |
| 687 | |
697 | |
| 688 | if (! runlevel || ! service) |
698 | if (! runlevel || ! service) |
| 689 | return (false); |
699 | return (false); |
| 690 | |
700 | |
| 691 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), NULL); |
701 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), |
|
|
702 | (char *) NULL); |
| 692 | if (unlink (file) == 0) |
703 | if (unlink (file) == 0) |
| 693 | retval = true; |
704 | retval = true; |
| 694 | |
705 | |
| 695 | free (file); |
706 | free (file); |
| 696 | return (retval); |
707 | return (retval); |
| … | |
… | |
| 703 | char *dir; |
714 | char *dir; |
| 704 | int i; |
715 | int i; |
| 705 | |
716 | |
| 706 | STRLIST_FOREACH (dirs, dir, i) |
717 | STRLIST_FOREACH (dirs, dir, i) |
| 707 | { |
718 | { |
| 708 | char *file = rc_strcatpaths (RC_SVCDIR "scheduled", dir, service, NULL); |
719 | char *file = rc_strcatpaths (RC_SVCDIR "scheduled", dir, service, |
|
|
720 | (char *) NULL); |
| 709 | if (rc_exists (file)) |
721 | if (rc_exists (file)) |
| 710 | list = rc_strlist_add (list, file); |
722 | list = rc_strlist_add (list, file); |
| 711 | free (file); |
723 | free (file); |
| 712 | } |
724 | } |
| 713 | rc_strlist_free (dirs); |
725 | rc_strlist_free (dirs); |
| … | |
… | |
| 715 | return (list); |
727 | return (list); |
| 716 | } |
728 | } |
| 717 | |
729 | |
| 718 | char **rc_services_scheduled (const char *service) |
730 | char **rc_services_scheduled (const char *service) |
| 719 | { |
731 | { |
| 720 | char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), NULL); |
732 | char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), |
|
|
733 | (char *) NULL); |
| 721 | char **list = NULL; |
734 | char **list = NULL; |
| 722 | |
735 | |
| 723 | if (rc_is_dir (dir)) |
736 | if (rc_is_dir (dir)) |
| 724 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
737 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
| 725 | |
738 | |