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

Contents of /trunk/src/librc.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20