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

Contents of /trunk/src/librc.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20