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

Contents of /trunk/src/librc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2883 - (show annotations) (download) (as text)
Tue Sep 18 12:04:51 2007 UTC (6 years, 10 months ago) by uberlord
File MIME type: text/x-csrc
File size: 19151 byte(s)
    API change! rc_ls_dir, rc_get_config and rc_get_list no longer take
    a starting list as a first argument. Instead, use rc_strlist_join
    to append or prepend the new list to an existing list.
1 /*
2 librc
3 core RC functions
4 Copyright 2007 Gentoo Foundation
5 Released under the GPLv2
6 */
7
8 #include "librc.h"
9
10 /* usecs to wait while we poll the fifo */
11 #define WAIT_INTERVAL 20000000
12
13 /* max nsecs to wait until a service comes up */
14 #define WAIT_MAX 60000000000
15
16 #define SOFTLEVEL RC_SVCDIR "/softlevel"
17
18 /* File stream used for plugins to write environ vars to */
19 FILE *rc_environ_fd = NULL;
20
21 static const char *rc_service_state_names[] = {
22 "started",
23 "stopped",
24 "starting",
25 "stopping",
26 "inactive",
27 "wasinactive",
28 "coldplugged",
29 "failed",
30 "scheduled",
31 NULL
32 };
33
34 bool rc_runlevel_starting (void)
35 {
36 return (rc_is_dir (RC_STARTING));
37 }
38 librc_hidden_def(rc_runlevel_starting)
39
40 bool rc_runlevel_stopping (void)
41 {
42 return (rc_is_dir (RC_STOPPING));
43 }
44 librc_hidden_def(rc_runlevel_stopping)
45
46 char **rc_get_runlevels (void)
47 {
48 char **dirs = rc_ls_dir (RC_RUNLEVELDIR, 0);
49 char **runlevels = NULL;
50 int i;
51 char *dir;
52
53 STRLIST_FOREACH (dirs, dir, i) {
54 char *path = rc_strcatpaths (RC_RUNLEVELDIR, dir, (char *) NULL);
55 if (rc_is_dir (path))
56 rc_strlist_addsort (&runlevels, dir);
57 free (path);
58 }
59 rc_strlist_free (dirs);
60
61 return (runlevels);
62 }
63 librc_hidden_def(rc_get_runlevels)
64
65 char *rc_get_runlevel (void)
66 {
67 FILE *fp;
68 static char buffer[PATH_MAX];
69
70 if (! (fp = fopen (SOFTLEVEL, "r"))) {
71 snprintf (buffer, sizeof (buffer), "sysinit");
72 return (buffer);
73 }
74
75 if (fgets (buffer, PATH_MAX, fp)) {
76 int i = strlen (buffer) - 1;
77 if (buffer[i] == '\n')
78 buffer[i] = 0;
79 fclose (fp);
80 return (buffer);
81 }
82
83 fclose (fp);
84 snprintf (buffer, sizeof (buffer), "sysinit");
85 return (buffer);
86 }
87 librc_hidden_def(rc_get_runlevel)
88
89 void rc_set_runlevel (const char *runlevel)
90 {
91 FILE *fp = fopen (SOFTLEVEL, "w");
92 if (! fp)
93 eerrorx ("failed to open `" SOFTLEVEL "': %s", strerror (errno));
94 fprintf (fp, "%s", runlevel);
95 fclose (fp);
96 }
97 librc_hidden_def(rc_set_runlevel)
98
99 bool rc_runlevel_exists (const char *runlevel)
100 {
101 char *path;
102 bool retval;
103
104 if (! runlevel)
105 return (false);
106
107 path = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
108 retval = rc_is_dir (path);
109 free (path);
110 return (retval);
111 }
112 librc_hidden_def(rc_runlevel_exists)
113
114 /* Resolve a service name to it's full path */
115 char *rc_resolve_service (const char *service)
116 {
117 char buffer[PATH_MAX];
118 char *file;
119 int r = 0;
120
121 if (! service)
122 return (NULL);
123
124 if (service[0] == '/')
125 return (rc_xstrdup (service));
126
127 file = rc_strcatpaths (RC_SVCDIR, "started", service, (char *) NULL);
128 if (! rc_is_link (file)) {
129 free (file);
130 file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL);
131 if (! rc_is_link (file)) {
132 free (file);
133 file = NULL;
134 }
135 }
136
137 memset (buffer, 0, sizeof (buffer));
138 if (file) {
139 r = readlink (file, buffer, sizeof (buffer));
140 free (file);
141 if (r > 0)
142 return (rc_xstrdup (buffer));
143 }
144
145 snprintf (buffer, sizeof (buffer), RC_INITDIR "/%s", service);
146 return (rc_xstrdup (buffer));
147 }
148 librc_hidden_def(rc_resolve_service)
149
150 bool rc_service_exists (const char *service)
151 {
152 char *file;
153 bool retval = false;
154 int len;
155
156 if (! service)
157 return (false);
158
159 len = strlen (service);
160
161 /* .sh files are not init scripts */
162 if (len > 2 && service[len - 3] == '.' &&
163 service[len - 2] == 's' &&
164 service[len - 1] == 'h')
165 return (false);
166
167 file = rc_resolve_service (service);
168 if (rc_exists (file))
169 retval = rc_is_exec (file);
170 free (file);
171 return (retval);
172 }
173 librc_hidden_def(rc_service_exists)
174
175 char **rc_service_options (const char *service)
176 {
177 char *svc;
178 char cmd[PATH_MAX];
179 char buffer[RC_LINEBUFFER];
180 char **opts = NULL;
181 char *token;
182 char *p = buffer;
183 FILE *fp;
184
185 if (! rc_service_exists (service))
186 return (NULL);
187
188 svc = rc_resolve_service (service);
189
190 snprintf (cmd, sizeof (cmd), ". '%s'; echo \"${opts}\"", svc);
191 if (! (fp = popen (cmd, "r"))) {
192 eerror ("popen `%s': %s", svc, strerror (errno));
193 free (svc);
194 return (NULL);
195 }
196
197 if (fgets (buffer, RC_LINEBUFFER, fp)) {
198 if (buffer[strlen (buffer) - 1] == '\n')
199 buffer[strlen (buffer) - 1] = '\0';
200 while ((token = strsep (&p, " ")))
201 rc_strlist_addsort (&opts, token);
202 }
203 pclose (fp);
204 return (opts);
205 }
206 librc_hidden_def(rc_service_options)
207
208 char *rc_service_description (const char *service, const char *option)
209 {
210 char *svc;
211 char cmd[PATH_MAX];
212 char buffer[RC_LINEBUFFER];
213 char *desc = NULL;
214 FILE *fp;
215 int i;
216
217 if (! rc_service_exists (service))
218 return (NULL);
219
220 svc = rc_resolve_service (service);
221
222 if (! option)
223 option = "";
224
225 snprintf (cmd, sizeof (cmd), ". '%s'; echo \"${description%s%s}\"",
226 svc, option ? "_" : "", option);
227 if (! (fp = popen (cmd, "r"))) {
228 eerror ("popen `%s': %s", svc, strerror (errno));
229 free (svc);
230 return (NULL);
231 }
232 free (svc);
233
234 while (fgets (buffer, RC_LINEBUFFER, fp)) {
235 if (! desc) {
236 desc = rc_xmalloc (strlen (buffer) + 1);
237 *desc = '\0';
238 } else {
239 desc = rc_xrealloc (desc, strlen (desc) + strlen (buffer) + 1);
240 }
241 i = strlen (desc);
242 memcpy (desc + i, buffer, strlen (buffer));
243 memset (desc + i + strlen (buffer), 0, 1);
244 }
245
246 pclose (fp);
247 return (desc);
248 }
249 librc_hidden_def(rc_service_description)
250
251 bool rc_service_in_runlevel (const char *service, const char *runlevel)
252 {
253 char *file;
254 bool retval;
255 char *svc;
256
257 if (! runlevel || ! service)
258 return (false);
259
260 svc = rc_xstrdup (service);
261 file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (svc),
262 (char *) NULL);
263 free (svc);
264 retval = rc_exists (file);
265 free (file);
266
267 return (retval);
268 }
269 librc_hidden_def(rc_service_in_runlevel)
270
271 bool rc_mark_service (const char *service, const rc_service_state_t state)
272 {
273 char *file;
274 int i = 0;
275 int skip_state = -1;
276 char *base;
277 char *svc;
278 char *init = rc_resolve_service (service);
279 bool skip_wasinactive = false;
280
281 if (! service)
282 return (false);
283
284 svc = rc_xstrdup (service);
285 base = basename (svc);
286
287 if (state != rc_service_stopped) {
288 if (! rc_is_file(init)) {
289 free (init);
290 free (svc);
291 return (false);
292 }
293
294 file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], base,
295 (char *) NULL);
296 if (rc_exists (file))
297 unlink (file);
298 i = symlink (init, file);
299 if (i != 0) {
300 eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno));
301 free (file);
302 free (init);
303 free (svc);
304 return (false);
305 }
306
307 free (file);
308 skip_state = state;
309 }
310
311 if (state == rc_service_coldplugged) {
312 free (init);
313 free (svc);
314 return (true);
315 }
316
317 /* Remove any old states now */
318 i = 0;
319 while (rc_service_state_names[i]) {
320 if ((i != skip_state &&
321 i != rc_service_stopped &&
322 i != rc_service_coldplugged &&
323 i != rc_service_scheduled &&
324 i != rc_service_crashed) &&
325 (! skip_wasinactive || i != rc_service_wasinactive))
326 {
327 file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i], base,
328 (char *) NULL);
329 if (rc_exists (file)) {
330 if ((state == rc_service_starting ||
331 state == rc_service_stopping) &&
332 i == rc_service_inactive)
333 {
334 char *wasfile = rc_strcatpaths (RC_SVCDIR,
335 rc_service_state_names[rc_service_wasinactive],
336 base, (char *) NULL);
337
338 if (symlink (init, wasfile) != 0)
339 eerror ("symlink `%s' to `%s': %s", init, wasfile,
340 strerror (errno));
341
342 skip_wasinactive = true;
343 free (wasfile);
344 }
345
346 errno = 0;
347 if (unlink (file) != 0 && errno != ENOENT)
348 eerror ("failed to delete `%s': %s", file,
349 strerror (errno));
350 }
351 free (file);
352 }
353 i++;
354 }
355
356 /* Remove the exclusive state if we're inactive */
357 if (state == rc_service_started ||
358 state == rc_service_stopped ||
359 state == rc_service_inactive)
360 {
361 file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL);
362 if (rc_exists (file))
363 if (unlink (file) != 0)
364 eerror ("unlink `%s': %s", file, strerror (errno));
365 free (file);
366 }
367
368 /* Remove any options and daemons the service may have stored */
369 if (state == rc_service_stopped) {
370 char *dir = rc_strcatpaths (RC_SVCDIR, "options", base, (char *) NULL);
371
372 if (rc_is_dir (dir))
373 rc_rm_dir (dir, true);
374 free (dir);
375
376 dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL);
377 if (rc_is_dir (dir))
378 rc_rm_dir (dir, true);
379 free (dir);
380
381 rc_schedule_clear (service);
382 }
383
384 /* These are final states, so remove us from scheduled */
385 if (state == rc_service_started || state == rc_service_stopped) {
386 char *sdir = rc_strcatpaths (RC_SVCDIR, "scheduled", (char *) NULL);
387 char **dirs = rc_ls_dir (sdir, 0);
388 char *dir;
389 int serrno;
390
391 STRLIST_FOREACH (dirs, dir, i) {
392 char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL);
393 file = rc_strcatpaths (bdir, base, (char *) NULL);
394 if (rc_exists (file))
395 if (unlink (file) != 0)
396 eerror ("unlink `%s': %s", file, strerror (errno));
397 free (file);
398
399 /* Try and remove the dir - we don't care about errors */
400 serrno = errno;
401 rmdir (bdir);
402 errno = serrno;
403 free (bdir);
404 }
405 rc_strlist_free (dirs);
406 free (sdir);
407 }
408
409 free (svc);
410 free (init);
411 return (true);
412 }
413 librc_hidden_def(rc_mark_service)
414
415 bool rc_service_state (const char *service, const rc_service_state_t state)
416 {
417 char *file;
418 bool retval;
419 char *svc;
420
421 /* If the init script does not exist then we are stopped */
422 if (! rc_service_exists (service))
423 return (state == rc_service_stopped ? true : false);
424
425 /* We check stopped state by not being in any of the others */
426 if (state == rc_service_stopped)
427 return ( ! (rc_service_state (service, rc_service_started) ||
428 rc_service_state (service, rc_service_starting) ||
429 rc_service_state (service, rc_service_stopping) ||
430 rc_service_state (service, rc_service_inactive)));
431
432 /* The crashed state and scheduled states are virtual */
433 if (state == rc_service_crashed)
434 return (rc_service_daemons_crashed (service));
435 else if (state == rc_service_scheduled) {
436 char **services = rc_services_scheduled_by (service);
437 retval = (services);
438 if (services)
439 free (services);
440 return (retval);
441 }
442
443 /* Now we just check if a file by the service name rc_exists
444 in the state dir */
445 svc = rc_xstrdup (service);
446 file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state],
447 basename (svc), (char*) NULL);
448 free (svc);
449 retval = rc_exists (file);
450 free (file);
451 return (retval);
452 }
453 librc_hidden_def(rc_service_state)
454
455 bool rc_get_service_option (const char *service, const char *option,
456 char *value)
457 {
458 FILE *fp;
459 char buffer[RC_LINEBUFFER];
460 char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option,
461 (char *) NULL);
462 bool retval = false;
463
464 if (rc_exists (file)) {
465 if ((fp = fopen (file, "r")) == NULL)
466 eerror ("fopen `%s': %s", file, strerror (errno));
467 else {
468 memset (buffer, 0, sizeof (buffer));
469 while (fgets (buffer, RC_LINEBUFFER, fp)) {
470 memcpy (value, buffer, strlen (buffer));
471 value += strlen (buffer);
472 }
473 fclose (fp);
474 retval = true;
475 }
476 }
477
478 free (file);
479 return (retval);
480 }
481 librc_hidden_def(rc_get_service_option)
482
483 bool rc_set_service_option (const char *service, const char *option,
484 const char *value)
485 {
486 FILE *fp;
487 char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL);
488 char *file = rc_strcatpaths (path, option, (char *) NULL);
489 bool retval = false;
490
491 if (! rc_is_dir (path)) {
492 if (mkdir (path, 0755) != 0) {
493 eerror ("mkdir `%s': %s", path, strerror (errno));
494 free (path);
495 free (file);
496 return (false);
497 }
498 }
499
500 if ((fp = fopen (file, "w")) == NULL)
501 eerror ("fopen `%s': %s", file, strerror (errno));
502 else {
503 if (value)
504 fprintf (fp, "%s", value);
505 fclose (fp);
506 retval = true;
507 }
508
509 free (path);
510 free (file);
511 return (retval);
512 }
513 librc_hidden_def(rc_set_service_option)
514
515 static pid_t _exec_service (const char *service, const char *arg)
516 {
517 char *file;
518 char *fifo;
519 pid_t pid = -1;
520 char *svc;
521
522 file = rc_resolve_service (service);
523 if (! rc_is_file (file)) {
524 rc_mark_service (service, rc_service_stopped);
525 free (file);
526 return (0);
527 }
528
529 /* We create a fifo so that other services can wait until we complete */
530 svc = rc_xstrdup (service);
531 fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (svc),
532 (char *) NULL);
533 free (svc);
534
535 if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) {
536 eerror ("unable to create fifo `%s': %s", fifo, strerror (errno));
537 free (fifo);
538 free (file);
539 return (-1);
540 }
541
542 if ((pid = vfork ()) == 0) {
543 execl (file, file, arg, (char *) NULL);
544 eerror ("unable to exec `%s': %s", file, strerror (errno));
545 unlink (fifo);
546 _exit (EXIT_FAILURE);
547 }
548
549 free (fifo);
550 free (file);
551
552 if (pid == -1)
553 eerror ("vfork: %s", strerror (errno));
554
555 return (pid);
556 }
557
558 int rc_waitpid (pid_t pid) {
559 int status = 0;
560 pid_t savedpid = pid;
561
562 errno = 0;
563 do {
564 pid = waitpid (savedpid, &status, 0);
565 if (pid < 0) {
566 if (errno != ECHILD)
567 eerror ("waitpid %d: %s", savedpid, strerror (errno));
568 return (-1);
569 }
570 } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
571
572 return (WIFEXITED (status) ? WEXITSTATUS (status) : EXIT_FAILURE);
573 }
574
575 pid_t rc_stop_service (const char *service)
576 {
577 if (rc_service_state (service, rc_service_stopped))
578 return (0);
579
580 return (_exec_service (service, "stop"));
581 }
582 librc_hidden_def(rc_stop_service)
583
584 pid_t rc_start_service (const char *service)
585 {
586 if (! rc_service_state (service, rc_service_stopped))
587 return (0);
588
589 return (_exec_service (service, "start"));
590 }
591 librc_hidden_def(rc_start_service)
592
593 void rc_schedule_start_service (const char *service,
594 const char *service_to_start)
595 {
596 char *dir;
597 char *init;
598 char *file;
599 char *svc;
600
601 /* service may be a provided service, like net */
602 if (! service || ! rc_service_exists (service_to_start))
603 return;
604
605 svc = rc_xstrdup (service);
606 dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (svc),
607 (char *) NULL);
608 free (svc);
609 if (! rc_is_dir (dir))
610 if (mkdir (dir, 0755) != 0) {
611 eerror ("mkdir `%s': %s", dir, strerror (errno));
612 free (dir);
613 return;
614 }
615
616 init = rc_resolve_service (service_to_start);
617 svc = rc_xstrdup (service_to_start);
618 file = rc_strcatpaths (dir, basename (svc), (char *) NULL);
619 free (svc);
620 if (! rc_exists (file) && symlink (init, file) != 0)
621 eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno));
622
623 free (init);
624 free (file);
625 free (dir);
626 }
627 librc_hidden_def(rc_schedule_start_service)
628
629 void rc_schedule_clear (const char *service)
630 {
631 char *svc = rc_xstrdup (service);
632 char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (svc),
633 (char *) NULL);
634
635 free (svc);
636 if (rc_is_dir (dir))
637 rc_rm_dir (dir, true);
638 free (dir);
639 }
640 librc_hidden_def(rc_schedule_clear)
641
642 bool rc_wait_service (const char *service)
643 {
644 char *svc;
645 char *base;
646 char *fifo;
647 struct timespec ts;
648 int nloops = WAIT_MAX / WAIT_INTERVAL;
649 bool retval = false;
650 bool forever = false;
651
652 if (! service)
653 return (false);
654
655 svc = rc_xstrdup (service);
656 base = basename (svc);
657 fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL);
658 /* FIXME: find a better way of doing this
659 * Maybe a setting in the init script? */
660 if (strcmp (base, "checkfs") == 0 || strcmp (base, "checkroot") == 0)
661 forever = true;
662 free (svc);
663
664 ts.tv_sec = 0;
665 ts.tv_nsec = WAIT_INTERVAL;
666
667 while (nloops) {
668 if (! rc_exists (fifo)) {
669 retval = true;
670 break;
671 }
672
673 if (nanosleep (&ts, NULL) == -1) {
674 if (errno != EINTR) {
675 eerror ("nanosleep: %s", strerror (errno));
676 break;
677 }
678 }
679
680 if (! forever)
681 nloops --;
682 }
683
684 free (fifo);
685 return (retval);
686 }
687 librc_hidden_def(rc_wait_service)
688
689 char **rc_services_in_runlevel (const char *runlevel)
690 {
691 char *dir;
692 char **list = NULL;
693
694 if (! runlevel)
695 return (rc_ls_dir (RC_INITDIR, RC_LS_INITD));
696
697 /* These special levels never contain any services */
698 if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 ||
699 strcmp (runlevel, RC_LEVEL_SINGLE) == 0)
700 return (NULL);
701
702 dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
703 if (! rc_is_dir (dir))
704 eerror ("runlevel `%s' does not exist", runlevel);
705 else
706 list = rc_ls_dir (dir, RC_LS_INITD);
707
708 free (dir);
709 return (list);
710 }
711 librc_hidden_def(rc_services_in_runlevel)
712
713 char **rc_services_in_state (rc_service_state_t state)
714 {
715 char *dir = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state],
716 (char *) NULL);
717 char **list = NULL;
718
719 if (state == rc_service_scheduled) {
720 char **dirs = rc_ls_dir (dir, 0);
721 char *d;
722 int i;
723
724 STRLIST_FOREACH (dirs, d, i) {
725 char *p = rc_strcatpaths (dir, d, (char *) NULL);
726 char **entries = rc_ls_dir (p, RC_LS_INITD);
727 char *e;
728 int j;
729
730 STRLIST_FOREACH (entries, e, j)
731 rc_strlist_addsortu (&list, e);
732
733 if (entries)
734 free (entries);
735 }
736
737 if (dirs)
738 free (dirs);
739 } else {
740 if (rc_is_dir (dir))
741 list = rc_ls_dir (dir, RC_LS_INITD);
742 }
743
744 free (dir);
745 return (list);
746 }
747 librc_hidden_def(rc_services_in_state)
748
749 bool rc_service_add (const char *runlevel, const char *service)
750 {
751 bool retval;
752 char *init;
753 char *file;
754 char *svc;
755
756 if (! rc_runlevel_exists (runlevel)) {
757 errno = ENOENT;
758 return (false);
759 }
760
761 if (rc_service_in_runlevel (service, runlevel)) {
762 errno = EEXIST;
763 return (false);
764 }
765
766 init = rc_resolve_service (service);
767 svc = rc_xstrdup (service);
768 file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (svc),
769 (char *) NULL);
770 free (svc);
771 retval = (symlink (init, file) == 0);
772 free (init);
773 free (file);
774 return (retval);
775 }
776 librc_hidden_def(rc_service_add)
777
778 bool rc_service_delete (const char *runlevel, const char *service)
779 {
780 char *file;
781 char *svc;
782 bool retval = false;
783
784 if (! runlevel || ! service)
785 return (false);
786
787 svc = rc_xstrdup (service);
788 file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (svc),
789 (char *) NULL);
790 free (svc);
791 if (unlink (file) == 0)
792 retval = true;
793
794 free (file);
795 return (retval);
796 }
797 librc_hidden_def(rc_service_delete)
798
799 char **rc_services_scheduled_by (const char *service)
800 {
801 char **dirs = rc_ls_dir (RC_SVCDIR "/scheduled", 0);
802 char **list = NULL;
803 char *dir;
804 int i;
805
806 STRLIST_FOREACH (dirs, dir, i) {
807 char *file = rc_strcatpaths (RC_SVCDIR, "scheduled", dir, service,
808 (char *) NULL);
809 if (rc_exists (file))
810 rc_strlist_add (&list, file);
811 free (file);
812 }
813 rc_strlist_free (dirs);
814
815 return (list);
816 }
817 librc_hidden_def(rc_services_scheduled_by)
818
819 char **rc_services_scheduled (const char *service)
820 {
821 char *svc = rc_xstrdup (service);
822 char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (svc),
823 (char *) NULL);
824 char **list = NULL;
825
826 if (rc_is_dir (dir))
827 list = rc_ls_dir (dir, RC_LS_INITD);
828
829 free (svc);
830 free (dir);
831 return (list);
832 }
833 librc_hidden_def(rc_services_scheduled)
834
835 bool rc_allow_plug (char *service)
836 {
837 char *list;
838 char *p;
839 char *star;
840 char *token;
841 bool allow = true;
842 char *match = getenv ("RC_PLUG_SERVICES");
843 if (! match)
844 return true;
845
846 list = rc_xstrdup (match);
847 p = list;
848 while ((token = strsep (&p, " "))) {
849 bool truefalse = true;
850 if (token[0] == '!') {
851 truefalse = false;
852 token++;
853 }
854
855 star = strchr (token, '*');
856 if (star) {
857 if (strncmp (service, token, star - token) == 0) {
858 allow = truefalse;
859 break;
860 }
861 } else {
862 if (strcmp (service, token) == 0) {
863 allow = truefalse;
864 break;
865 }
866 }
867 }
868
869 free (list);
870 return (allow);
871 }
872 librc_hidden_def(rc_allow_plug)

  ViewVC Help
Powered by ViewVC 1.1.20