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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2818 - (hide annotations) (download) (as text)
Tue Aug 7 20:23:38 2007 UTC (6 years, 11 months ago) by uberlord
File MIME type: text/x-csrc
File size: 34369 byte(s)
More pppd fixes
1 uberlord 2547 /*
2     * runscript.c
3     * Handle launching of Gentoo init scripts.
4     *
5     * Copyright 1999-2007 Gentoo Foundation
6     * Distributed under the terms of the GNU General Public License v2
7     */
8    
9 vapier 2618 #define APPLET "runscript"
10    
11 uberlord 2547 #include <sys/types.h>
12 uberlord 2652 #include <sys/param.h>
13 uberlord 2547 #include <sys/stat.h>
14     #include <sys/wait.h>
15     #include <dlfcn.h>
16     #include <errno.h>
17 uberlord 2652 #include <fcntl.h>
18 uberlord 2580 #include <getopt.h>
19 uberlord 2634 #include <libgen.h>
20 uberlord 2547 #include <limits.h>
21 uberlord 2641 #include <signal.h>
22 uberlord 2547 #include <stdio.h>
23     #include <stdlib.h>
24     #include <string.h>
25     #include <unistd.h>
26    
27 uberlord 2799 #include "builtins.h"
28 uberlord 2547 #include "einfo.h"
29     #include "rc.h"
30     #include "rc-misc.h"
31     #include "rc-plugin.h"
32     #include "strlist.h"
33    
34 uberlord 2582 #define RCSCRIPT_HELP RC_LIBDIR "/sh/rc-help.sh"
35     #define SELINUX_LIB RC_LIBDIR "/runscript_selinux.so"
36 uberlord 2547
37 uberlord 2659 #define PREFIX_LOCK RC_SVCDIR "/prefix.lock"
38    
39 uberlord 2547 static char *applet = NULL;
40 uberlord 2669 static char *service = NULL;
41 uberlord 2547 static char *exclusive = NULL;
42     static char *mtime_test = NULL;
43     static rc_depinfo_t *deptree = NULL;
44     static char **services = NULL;
45     static char **svclist = NULL;
46     static char **tmplist = NULL;
47     static char **providelist = NULL;
48     static char **types = NULL;
49     static char **restart_services = NULL;
50     static char **need_services = NULL;
51 uberlord 2741 static char **use_services = NULL;
52 uberlord 2547 static char **env = NULL;
53     static char *tmp = NULL;
54     static char *softlevel = NULL;
55     static bool sighup = false;
56     static char *ibsave = NULL;
57     static bool in_background = false;
58     static rc_hook_t hook_out = 0;
59 uberlord 2641 static pid_t service_pid = 0;
60 uberlord 2652 static char *prefix = NULL;
61 uberlord 2659 static bool prefix_locked = false;
62 uberlord 2547
63     extern char **environ;
64    
65     #ifdef __linux__
66     static void (*selinux_run_init_old) (void);
67     static void (*selinux_run_init_new) (int argc, char **argv);
68    
69 uberlord 2652 static void setup_selinux (int argc, char **argv);
70 uberlord 2547
71 uberlord 2652 static void setup_selinux (int argc, char **argv)
72 uberlord 2547 {
73 uberlord 2577 void *lib_handle = NULL;
74 uberlord 2547
75 uberlord 2577 lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL);
76     if (lib_handle) {
77 uberlord 2638 /*
78     * FIXME: the below code generates the warning
79     * ISO C forbids assignment between function pointer and 'void *'
80     * which sucks ass
81     * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
82     */
83 uberlord 2704 selinux_run_init_old = (void (*)(void)) dlfunc (lib_handle, "selinux_runscript");
84     selinux_run_init_new = (void (*)(int, char **)) dlfunc (lib_handle, "selinux_runscript2");
85 uberlord 2547
86 uberlord 2577 /* Use new run_init if it rc_exists, else fall back to old */
87     if (selinux_run_init_new)
88     selinux_run_init_new (argc, argv);
89     else if (selinux_run_init_old)
90     selinux_run_init_old ();
91     else
92     /* This shouldnt happen... probably corrupt lib */
93     eerrorx ("run_init is missing from runscript_selinux.so!");
94     }
95 uberlord 2547 }
96     #endif
97    
98     static void handle_signal (int sig)
99     {
100 uberlord 2577 pid_t pid;
101     int status;
102     int serrno = errno;
103     char signame[10] = { '\0' };
104 uberlord 2547
105 uberlord 2577 switch (sig) {
106     case SIGHUP:
107     sighup = true;
108     break;
109 uberlord 2547
110 uberlord 2577 case SIGCHLD:
111     do {
112     pid = waitpid (-1, &status, WNOHANG);
113     if (pid < 0) {
114     if (errno != ECHILD)
115     eerror ("waitpid: %s", strerror (errno));
116     return;
117     }
118     } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
119 uberlord 2641 if (pid == service_pid)
120     service_pid = 0;
121 uberlord 2577 break;
122 uberlord 2569
123 uberlord 2577 case SIGINT:
124     if (! signame[0])
125     snprintf (signame, sizeof (signame), "SIGINT");
126     case SIGTERM:
127     if (! signame[0])
128     snprintf (signame, sizeof (signame), "SIGTERM");
129     case SIGQUIT:
130     if (! signame[0])
131     snprintf (signame, sizeof (signame), "SIGQUIT");
132 uberlord 2641 /* Send the signal to our children too */
133     if (service_pid > 0)
134     kill (service_pid, sig);
135 uberlord 2577 eerrorx ("%s: caught %s, aborting", applet, signame);
136 uberlord 2547
137 uberlord 2577 default:
138     eerror ("%s: caught unknown signal %d", applet, sig);
139     }
140 uberlord 2547
141 uberlord 2577 /* Restore errno */
142     errno = serrno;
143 uberlord 2547 }
144    
145     static time_t get_mtime (const char *pathname, bool follow_link)
146     {
147 uberlord 2577 struct stat buf;
148     int retval;
149 uberlord 2547
150 uberlord 2577 if (! pathname)
151     return (0);
152 uberlord 2547
153 uberlord 2577 retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf);
154     if (! retval)
155     return (buf.st_mtime);
156 uberlord 2547
157 uberlord 2577 errno = 0;
158     return (0);
159 uberlord 2547 }
160    
161     static bool in_control ()
162     {
163 uberlord 2577 char *path;
164     time_t mtime;
165     const char *tests[] = { "starting", "started", "stopping",
166     "inactive", "wasinactive", NULL };
167     int i = 0;
168 uberlord 2547
169 uberlord 2577 if (sighup)
170     return (false);
171 uberlord 2547
172 uberlord 2577 if (! mtime_test || ! rc_exists (mtime_test))
173     return (false);
174 uberlord 2547
175 uberlord 2577 if (rc_service_state (applet, rc_service_stopped))
176     return (false);
177 uberlord 2547
178 uberlord 2577 if (! (mtime = get_mtime (mtime_test, false)))
179     return (false);
180 uberlord 2547
181 uberlord 2577 while (tests[i]) {
182     path = rc_strcatpaths (RC_SVCDIR, tests[i], applet, (char *) NULL);
183     if (rc_exists (path)) {
184     time_t m = get_mtime (path, false);
185     if (mtime < m && m != 0) {
186     free (path);
187     return (false);
188     }
189     }
190     free (path);
191     i++;
192     }
193 uberlord 2547
194 uberlord 2577 return (true);
195 uberlord 2547 }
196    
197 uberlord 2669 static void uncoldplug ()
198 uberlord 2547 {
199 uberlord 2669 char *cold = rc_strcatpaths (RC_SVCDIR "coldplugged", applet, (char *) NULL);
200 uberlord 2577 if (rc_exists (cold) && unlink (cold) != 0)
201     eerror ("%s: unlink `%s': %s", applet, cold, strerror (errno));
202     free (cold);
203 uberlord 2547 }
204    
205 uberlord 2669 static void start_services (char **list) {
206     bool inactive;
207     char *svc;
208     int i;
209    
210     if (! list)
211     return;
212    
213     inactive = rc_service_state (service, rc_service_inactive);
214     if (! inactive)
215     inactive = rc_service_state (service, rc_service_wasinactive);
216    
217     if (inactive ||
218     rc_service_state (service, rc_service_starting) ||
219     rc_service_state (service, rc_service_started))
220     {
221     STRLIST_FOREACH (list, svc, i) {
222     if (rc_service_state (svc, rc_service_stopped)) {
223     if (inactive) {
224     rc_schedule_start_service (service, svc);
225     ewarn ("WARNING: %s is scheduled to started when %s has started",
226     svc, applet);
227     } else
228     rc_start_service (svc);
229     }
230     }
231     }
232     }
233    
234 uberlord 2547 static void cleanup (void)
235     {
236 uberlord 2770 if (! rc_in_plugin) {
237     if (prefix_locked)
238     unlink (PREFIX_LOCK);
239     if (hook_out)
240     rc_plugin_run (hook_out, applet);
241     if (restart_services)
242     start_services (restart_services);
243     }
244 uberlord 2659
245 uberlord 2577 rc_plugin_unload ();
246 uberlord 2652 rc_free_deptree (deptree);
247     rc_strlist_free (services);
248     rc_strlist_free (types);
249     rc_strlist_free (svclist);
250     rc_strlist_free (providelist);
251     rc_strlist_free (need_services);
252 uberlord 2741 rc_strlist_free (use_services);
253 uberlord 2770 rc_strlist_free (restart_services);
254 uberlord 2652 rc_strlist_free (tmplist);
255     free (ibsave);
256 uberlord 2547
257 uberlord 2744 if (! rc_in_plugin && in_control ()) {
258 uberlord 2577 if (rc_service_state (applet, rc_service_stopping)) {
259     /* If the we're shutting down, do it cleanly */
260     if ((softlevel &&
261     rc_runlevel_stopping () &&
262     (strcmp (softlevel, RC_LEVEL_SHUTDOWN) == 0 ||
263     strcmp (softlevel, RC_LEVEL_REBOOT) == 0)))
264     rc_mark_service (applet, rc_service_stopped);
265     else if (rc_service_state (applet, rc_service_wasinactive))
266     rc_mark_service (applet, rc_service_inactive);
267     else
268     rc_mark_service (applet, rc_service_started);
269     }
270     else if (rc_service_state (applet, rc_service_starting))
271     {
272     if (rc_service_state (applet, rc_service_wasinactive))
273     rc_mark_service (applet, rc_service_inactive);
274     else
275     rc_mark_service (applet, rc_service_stopped);
276     }
277     if (exclusive && rc_exists (exclusive))
278     unlink (exclusive);
279     }
280 uberlord 2547
281 uberlord 2652 rc_strlist_free (env);
282 uberlord 2547
283 uberlord 2577 if (mtime_test)
284     {
285 uberlord 2744 if (! rc_in_plugin)
286     unlink (mtime_test);
287 uberlord 2577 free (mtime_test);
288     }
289 uberlord 2652 free (exclusive);
290     free (applet);
291     free (prefix);
292 uberlord 2743 free (service);
293 uberlord 2652 }
294 uberlord 2547
295 uberlord 2652 static int write_prefix (int fd, const char *buffer, size_t bytes, bool *prefixed) {
296     unsigned int i;
297     const char *ec;
298     const char *ec_normal = ecolor (ecolor_normal);
299     ssize_t ret = 0;
300    
301     if (fd == fileno (stdout))
302     ec = ecolor (ecolor_hilite);
303     else
304     ec = ecolor (ecolor_bad);
305    
306     for (i = 0; i < bytes; i++) {
307     /* We don't prefix escape codes, like eend */
308     if (buffer[i] == '\033')
309     *prefixed = true;
310    
311     if (! *prefixed) {
312     ret += write (fd, ec, strlen (ec));
313 uberlord 2749 ret += write (fd, prefix, strlen (prefix));
314 uberlord 2652 ret += write (fd, ec_normal, strlen (ec_normal));
315 uberlord 2768 ret += write (fd, "|", 1);
316 uberlord 2652 *prefixed = true;
317     }
318    
319     if (buffer[i] == '\n')
320     *prefixed = false;
321     ret += write (fd, buffer + i, 1);
322     }
323    
324     return (ret);
325 uberlord 2547 }
326    
327 uberlord 2669 static bool svc_exec (const char *arg1, const char *arg2)
328 uberlord 2547 {
329 uberlord 2652 bool execok;
330     int stdout_pipes[2];
331     int stderr_pipes[2];
332 uberlord 2547
333 uberlord 2652 /* Setup our pipes for prefixed output */
334 uberlord 2768 if (prefix) {
335 uberlord 2652 if (pipe (stdout_pipes))
336     eerror ("pipe: %s", strerror (errno));
337     if (pipe (stderr_pipes))
338     eerror ("pipe: %s", strerror (errno));
339     }
340    
341 uberlord 2577 /* We need to disable our child signal handler now so we block
342     until our script returns. */
343     signal (SIGCHLD, NULL);
344 uberlord 2569
345 uberlord 2641 service_pid = vfork();
346 uberlord 2547
347 uberlord 2641 if (service_pid == -1)
348 uberlord 2638 eerrorx ("%s: vfork: %s", service, strerror (errno));
349 uberlord 2641 if (service_pid == 0) {
350 uberlord 2768 if (prefix) {
351 uberlord 2652 int flags;
352    
353     if (dup2 (stdout_pipes[1], fileno (stdout)) == -1)
354     eerror ("dup2 stdout: %s", strerror (errno));
355     close (stdout_pipes[0]);
356     if (dup2 (stderr_pipes[1], fileno (stderr)) == -1)
357     eerror ("dup2 stderr: %s", strerror (errno));
358     close (stderr_pipes[0]);
359    
360     /* Stop any scripts from inheriting us */
361     if ((flags = fcntl (stdout_pipes[1], F_GETFD, 0)) < 0 ||
362     fcntl (stdout_pipes[1], F_SETFD, flags | FD_CLOEXEC) < 0)
363     eerror ("fcntl: %s", strerror (errno));
364     if ((flags = fcntl (stderr_pipes[1], F_GETFD, 0)) < 0 ||
365     fcntl (stderr_pipes[1], F_SETFD, flags | FD_CLOEXEC) < 0)
366     eerror ("fcntl: %s", strerror (errno));
367     }
368    
369 uberlord 2577 if (rc_exists (RC_SVCDIR "runscript.sh")) {
370 uberlord 2638 execl (RC_SVCDIR "runscript.sh", service, service, arg1, arg2,
371 uberlord 2577 (char *) NULL);
372 uberlord 2638 eerror ("%s: exec `" RC_SVCDIR "runscript.sh': %s",
373 uberlord 2642 service, strerror (errno));
374 uberlord 2638 _exit (EXIT_FAILURE);
375 uberlord 2577 } else {
376 uberlord 2638 execl (RC_LIBDIR "sh/runscript.sh", service, service, arg1, arg2,
377 uberlord 2577 (char *) NULL);
378 uberlord 2638 eerror ("%s: exec `" RC_LIBDIR "sh/runscript.sh': %s",
379 uberlord 2642 service, strerror (errno));
380 uberlord 2638 _exit (EXIT_FAILURE);
381 uberlord 2577 }
382     }
383 uberlord 2547
384 uberlord 2652 /* Prefix our piped output */
385 uberlord 2768 if (prefix) {
386 uberlord 2652 bool stdout_done = false;
387     bool stdout_prefix_shown = false;
388     bool stderr_done = false;
389     bool stderr_prefix_shown = false;
390     char buffer[RC_LINEBUFFER];
391 uberlord 2547
392 uberlord 2652 close (stdout_pipes[1]);
393     close (stderr_pipes[1]);
394    
395     memset (buffer, 0, RC_LINEBUFFER);
396     while (! stdout_done && ! stderr_done) {
397     fd_set fds;
398     int retval;
399    
400     FD_ZERO (&fds);
401     FD_SET (stdout_pipes[0], &fds);
402     FD_SET (stderr_pipes[0], &fds);
403     retval = select (MAX (stdout_pipes[0], stderr_pipes[0]) + 1,
404     &fds, 0, 0, 0);
405     if (retval < 0) {
406 uberlord 2657 if (errno != EINTR) {
407 uberlord 2652 eerror ("select: %s", strerror (errno));
408 uberlord 2657 break;
409     }
410 uberlord 2652 } else if (retval) {
411     ssize_t nr;
412    
413 uberlord 2659 /* Wait until we get a lock */
414     while (true) {
415     struct timeval tv;
416    
417     if (mkfifo (PREFIX_LOCK, 0700) == 0) {
418     prefix_locked = true;
419     break;
420     }
421    
422     if (errno != EEXIST)
423     eerror ("mkfifo `%s': %s\n", PREFIX_LOCK, strerror (errno));
424     tv.tv_sec = 0;
425     tv.tv_usec = 20000;
426     select (0, NULL, NULL, NULL, &tv);
427     }
428    
429 uberlord 2652 if (FD_ISSET (stdout_pipes[0], &fds)) {
430     if ((nr = read (stdout_pipes[0], buffer,
431     sizeof (buffer))) <= 0)
432     stdout_done = true;
433     else
434     write_prefix (fileno (stdout), buffer, nr,
435     &stdout_prefix_shown);
436     }
437    
438     if (FD_ISSET (stderr_pipes[0], &fds)) {
439     if ((nr = read (stderr_pipes[0], buffer,
440     sizeof (buffer))) <= 0)
441     stderr_done = true;
442     else
443     write_prefix (fileno (stderr), buffer, nr,
444     &stderr_prefix_shown);
445     }
446 uberlord 2659
447     /* Clear the lock */
448     unlink (PREFIX_LOCK);
449     prefix_locked = false;
450 uberlord 2652 }
451     }
452    
453     /* Done now, so close the pipes */
454     close(stdout_pipes[0]);
455     close(stderr_pipes[0]);
456     }
457    
458     execok = rc_waitpid (service_pid) == 0 ? true : false;
459 uberlord 2641 service_pid = 0;
460 uberlord 2652
461 uberlord 2577 /* Done, so restore the signal handler */
462     signal (SIGCHLD, handle_signal);
463 uberlord 2547
464 uberlord 2652 return (execok);
465 uberlord 2547 }
466    
467 uberlord 2669 static rc_service_state_t svc_status ()
468 uberlord 2547 {
469 uberlord 2577 char status[10];
470     int (*e) (const char *fmt, ...) = &einfo;
471 uberlord 2547
472 uberlord 2577 rc_service_state_t retval = rc_service_stopped;
473 uberlord 2547
474 uberlord 2577 if (rc_service_state (service, rc_service_stopping)) {
475     snprintf (status, sizeof (status), "stopping");
476     e = &ewarn;
477     retval = rc_service_stopping;
478     } else if (rc_service_state (service, rc_service_starting)) {
479     snprintf (status, sizeof (status), "starting");
480     e = &ewarn;
481     retval = rc_service_starting;
482     } else if (rc_service_state (service, rc_service_inactive)) {
483     snprintf (status, sizeof (status), "inactive");
484     e = &ewarn;
485     retval = rc_service_inactive;
486     } else if (rc_service_state (service, rc_service_crashed)) {
487     snprintf (status, sizeof (status), "crashed");
488     e = &eerror;
489     retval = rc_service_crashed;
490     } else if (rc_service_state (service, rc_service_started)) {
491     snprintf (status, sizeof (status), "started");
492     retval = rc_service_started;
493     } else
494     snprintf (status, sizeof (status), "stopped");
495 uberlord 2547
496 uberlord 2577 e ("status: %s", status);
497     return (retval);
498 uberlord 2547 }
499    
500 uberlord 2669 static void make_exclusive ()
501 uberlord 2547 {
502 uberlord 2577 char *path;
503     int i;
504 uberlord 2547
505 uberlord 2577 /* We create a fifo so that other services can wait until we complete */
506     if (! exclusive)
507     exclusive = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL);
508 uberlord 2547
509 uberlord 2577 if (mkfifo (exclusive, 0600) != 0 && errno != EEXIST &&
510     (errno != EACCES || geteuid () == 0))
511     eerrorx ("%s: unable to create fifo `%s': %s",
512     applet, exclusive, strerror (errno));
513 uberlord 2547
514 uberlord 2577 path = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL);
515     i = strlen (path) + 16;
516     mtime_test = rc_xmalloc (sizeof (char *) * i);
517     snprintf (mtime_test, i, "%s.%d", path, getpid ());
518     free (path);
519 uberlord 2547
520 uberlord 2577 if (rc_exists (mtime_test) && unlink (mtime_test) != 0) {
521     eerror ("%s: unlink `%s': %s",
522     applet, mtime_test, strerror (errno));
523     free (mtime_test);
524     mtime_test = NULL;
525     return;
526     }
527 uberlord 2547
528 uberlord 2577 if (symlink (service, mtime_test) != 0) {
529     eerror ("%s: symlink `%s' to `%s': %s",
530     applet, service, mtime_test, strerror (errno));
531     free (mtime_test);
532     mtime_test = NULL;
533     }
534 uberlord 2547 }
535    
536     static void unlink_mtime_test ()
537     {
538 uberlord 2577 if (unlink (mtime_test) != 0)
539     eerror ("%s: unlink `%s': %s", applet, mtime_test, strerror (errno));
540     free (mtime_test);
541     mtime_test = NULL;
542 uberlord 2547 }
543    
544     static void get_started_services ()
545     {
546 uberlord 2669 char *svc;
547 uberlord 2577 int i;
548 uberlord 2547
549 uberlord 2577 rc_strlist_free (tmplist);
550     tmplist = rc_services_in_state (rc_service_inactive);
551 uberlord 2547
552 uberlord 2577 rc_strlist_free (restart_services);
553     restart_services = rc_services_in_state (rc_service_started);
554 uberlord 2547
555 uberlord 2669 STRLIST_FOREACH (tmplist, svc, i)
556     restart_services = rc_strlist_addsort (restart_services, svc);
557 uberlord 2547
558 uberlord 2577 rc_strlist_free (tmplist);
559     tmplist = NULL;
560 uberlord 2547 }
561    
562 uberlord 2669 static void svc_start (bool deps)
563 uberlord 2547 {
564 uberlord 2577 bool started;
565     bool background = false;
566     char *svc;
567     char *svc2;
568     int i;
569     int j;
570     int depoptions = RC_DEP_TRACE;
571 uberlord 2547
572 uberlord 2577 rc_plugin_run (rc_hook_service_start_in, applet);
573     hook_out = rc_hook_service_start_out;
574 uberlord 2573
575 uberlord 2577 if (rc_is_env ("IN_HOTPLUG", "1") || in_background) {
576 uberlord 2578 if (! rc_service_state (service, rc_service_inactive) &&
577 uberlord 2582 ! rc_service_state (service, rc_service_stopped))
578 uberlord 2577 exit (EXIT_FAILURE);
579     background = true;
580     }
581 uberlord 2547
582 uberlord 2666 if (rc_service_state (service, rc_service_started)) {
583     ewarn ("WARNING: %s has already been started", applet);
584     return;
585     } else if (rc_service_state (service, rc_service_starting))
586 uberlord 2577 ewarnx ("WARNING: %s is already starting", applet);
587     else if (rc_service_state (service, rc_service_stopping))
588     ewarnx ("WARNING: %s is stopping", applet);
589     else if (rc_service_state (service, rc_service_inactive) && ! background)
590     ewarnx ("WARNING: %s has already started, but is inactive", applet);
591 uberlord 2547
592 uberlord 2577 if (! rc_mark_service (service, rc_service_starting))
593     eerrorx ("ERROR: %s has been started by something else", applet);
594 uberlord 2547
595 uberlord 2577 make_exclusive (service);
596 uberlord 2547
597 uberlord 2786 if (rc_is_env ("RC_DEPEND_STRICT", "yes"))
598     depoptions |= RC_DEP_STRICT;
599    
600     if (rc_runlevel_starting ())
601     depoptions |= RC_DEP_START;
602    
603 uberlord 2577 if (deps) {
604     if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
605     eerrorx ("failed to load deptree");
606 uberlord 2547
607 uberlord 2577 rc_strlist_free (types);
608     types = rc_strlist_add (NULL, "broken");
609     rc_strlist_free (svclist);
610     svclist = rc_strlist_add (NULL, applet);
611     rc_strlist_free (services);
612     services = rc_get_depends (deptree, types, svclist, softlevel, 0);
613     if (services) {
614     eerrorn ("ERROR: `%s' needs ", applet);
615     STRLIST_FOREACH (services, svc, i) {
616     if (i > 0)
617     fprintf (stderr, ", ");
618     fprintf (stderr, "%s", svc);
619     }
620     exit (EXIT_FAILURE);
621     }
622     rc_strlist_free (services);
623     services = NULL;
624 uberlord 2547
625 uberlord 2577 rc_strlist_free (types);
626     types = rc_strlist_add (NULL, "ineed");
627     rc_strlist_free (need_services);
628     need_services = rc_get_depends (deptree, types, svclist,
629     softlevel, depoptions);
630 uberlord 2741
631 uberlord 2577 types = rc_strlist_add (types, "iuse");
632 uberlord 2741 rc_strlist_free (use_services);
633     use_services = rc_get_depends (deptree, types, svclist,
634     softlevel, depoptions);
635    
636 uberlord 2577 if (! rc_runlevel_starting ()) {
637 uberlord 2741 STRLIST_FOREACH (use_services, svc, i)
638 uberlord 2641 if (rc_service_state (svc, rc_service_stopped)) {
639     pid_t pid = rc_start_service (svc);
640 uberlord 2650 if (! rc_is_env ("RC_PARALLEL", "yes"))
641 uberlord 2641 rc_waitpid (pid);
642     }
643 uberlord 2577 }
644 uberlord 2547
645 uberlord 2577 /* Now wait for them to start */
646     types = rc_strlist_add (types, "iafter");
647     services = rc_get_depends (deptree, types, svclist,
648     softlevel, depoptions);
649 uberlord 2547
650 uberlord 2577 /* We use tmplist to hold our scheduled by list */
651     rc_strlist_free (tmplist);
652     tmplist = NULL;
653 uberlord 2547
654 uberlord 2577 STRLIST_FOREACH (services, svc, i) {
655 uberlord 2741 if (rc_service_state (svc, rc_service_started))
656 uberlord 2577 continue;
657 uberlord 2741
658     /* Don't wait for services which went inactive but are now in
659     * starting state which we are after */
660     if (rc_service_state (svc, rc_service_starting) &&
661     rc_service_state(svc, rc_service_wasinactive)) {
662     bool use = false;
663     STRLIST_FOREACH (use_services, svc2, j)
664     if (strcmp (svc, svc2) == 0) {
665     use = true;
666     break;
667     }
668     if (! use)
669     continue;
670     }
671 uberlord 2740
672 uberlord 2577 if (! rc_wait_service (svc))
673     eerror ("%s: timed out waiting for %s", applet, svc);
674     if (rc_service_state (svc, rc_service_started))
675     continue;
676 uberlord 2547
677 uberlord 2577 STRLIST_FOREACH (need_services, svc2, j)
678     if (strcmp (svc, svc2) == 0) {
679     if (rc_service_state (svc, rc_service_inactive) ||
680     rc_service_state (svc, rc_service_wasinactive))
681     tmplist = rc_strlist_add (tmplist, svc);
682     else
683     eerrorx ("ERROR: cannot start %s as %s would not start",
684     applet, svc);
685     }
686     }
687 uberlord 2547
688 uberlord 2577 if (tmplist) {
689     int n = 0;
690     int len = 0;
691     char *p;
692 uberlord 2547
693 uberlord 2577 /* Set the state now, then unlink our exclusive so that
694     our scheduled list is preserved */
695     rc_mark_service (service, rc_service_stopped);
696     unlink_mtime_test ();
697 uberlord 2547
698 uberlord 2577 rc_strlist_free (types);
699     types = rc_strlist_add (NULL, "iprovide");
700     STRLIST_FOREACH (tmplist, svc, i) {
701     rc_schedule_start_service (svc, service);
702 uberlord 2547
703 uberlord 2577 rc_strlist_free (svclist);
704     svclist = rc_strlist_add (NULL, svc);
705     rc_strlist_free (providelist);
706     providelist = rc_get_depends (deptree, types, svclist,
707     softlevel, depoptions);
708     STRLIST_FOREACH (providelist, svc2, j)
709     rc_schedule_start_service (svc2, service);
710 uberlord 2547
711 uberlord 2577 len += strlen (svc) + 2;
712     n++;
713     }
714 uberlord 2547
715 uberlord 2577 len += 5;
716     tmp = rc_xmalloc (sizeof (char *) * len);
717     p = tmp;
718     STRLIST_FOREACH (tmplist, svc, i) {
719     if (i > 1) {
720 uberlord 2770 if (i == n)
721 uberlord 2577 p += snprintf (p, len, " or ");
722     else
723     p += snprintf (p, len, ", ");
724     }
725     p += snprintf (p, len, "%s", svc);
726     }
727     ewarnx ("WARNING: %s is scheduled to start when %s has started",
728     applet, tmp);
729     }
730 uberlord 2547
731 uberlord 2577 rc_strlist_free (services);
732     services = NULL;
733     rc_strlist_free (types);
734     types = NULL;
735     rc_strlist_free (svclist);
736     svclist = NULL;
737     }
738 uberlord 2547
739 uberlord 2577 if (ibsave)
740     setenv ("IN_BACKGROUND", ibsave, 1);
741     rc_plugin_run (rc_hook_service_start_now, applet);
742 uberlord 2669 started = svc_exec ("start", NULL);
743 uberlord 2577 if (ibsave)
744     unsetenv ("IN_BACKGROUND");
745 uberlord 2547
746 uberlord 2577 if (in_control ()) {
747     if (! started) {
748     if (rc_service_state (service, rc_service_wasinactive))
749     rc_mark_service (service, rc_service_inactive);
750     else {
751     rc_mark_service (service, rc_service_stopped);
752     if (rc_runlevel_starting ())
753     rc_mark_service (service, rc_service_failed);
754     }
755     rc_plugin_run (rc_hook_service_start_done, applet);
756     eerrorx ("ERROR: %s failed to start", applet);
757     }
758     rc_mark_service (service, rc_service_started);
759     unlink_mtime_test ();
760     rc_plugin_run (rc_hook_service_start_done, applet);
761     } else {
762     rc_plugin_run (rc_hook_service_start_done, applet);
763     if (rc_service_state (service, rc_service_inactive))
764     ewarnx ("WARNING: %s has started, but is inactive", applet);
765     else
766     ewarnx ("WARNING: %s not under our control, aborting", applet);
767     }
768 uberlord 2547
769 uberlord 2577 /* Now start any scheduled services */
770     rc_strlist_free (services);
771     services = rc_services_scheduled (service);
772     STRLIST_FOREACH (services, svc, i)
773     if (rc_service_state (svc, rc_service_stopped))
774     rc_start_service (svc);
775     rc_strlist_free (services);
776     services = NULL;
777 uberlord 2547
778 uberlord 2577 /* Do the same for any services we provide */
779     rc_strlist_free (types);
780     types = rc_strlist_add (NULL, "iprovide");
781     rc_strlist_free (svclist);
782     svclist = rc_strlist_add (NULL, applet);
783     rc_strlist_free (tmplist);
784     tmplist = rc_get_depends (deptree, types, svclist, softlevel, depoptions);
785 uberlord 2547
786 uberlord 2577 STRLIST_FOREACH (tmplist, svc2, j) {
787     rc_strlist_free (services);
788     services = rc_services_scheduled (svc2);
789     STRLIST_FOREACH (services, svc, i)
790     if (rc_service_state (svc, rc_service_stopped))
791     rc_start_service (svc);
792     }
793 uberlord 2573
794 uberlord 2577 hook_out = 0;
795     rc_plugin_run (rc_hook_service_start_out, applet);
796 uberlord 2547 }
797    
798 uberlord 2669 static void svc_stop (bool deps)
799 uberlord 2547 {
800 uberlord 2577 bool stopped;
801 uberlord 2547
802 uberlord 2577 hook_out = rc_hook_service_stop_out;
803 uberlord 2573
804 uberlord 2577 if (rc_runlevel_stopping () &&
805     rc_service_state (service, rc_service_failed))
806     exit (EXIT_FAILURE);
807 uberlord 2547
808 uberlord 2577 if (rc_is_env ("IN_HOTPLUG", "1") || in_background)
809 uberlord 2578 if (! rc_service_state (service, rc_service_started) &&
810 uberlord 2582 ! rc_service_state (service, rc_service_inactive))
811 uberlord 2577 exit (EXIT_FAILURE);
812 uberlord 2547
813 uberlord 2666 if (rc_service_state (service, rc_service_stopped)) {
814     ewarn ("WARNING: %s is already stopped", applet);
815     return;
816     } else if (rc_service_state (service, rc_service_stopping))
817 uberlord 2577 ewarnx ("WARNING: %s is already stopping", applet);
818 uberlord 2547
819 uberlord 2577 if (! rc_mark_service (service, rc_service_stopping))
820     eerrorx ("ERROR: %s has been stopped by something else", applet);
821 uberlord 2547
822 uberlord 2577 make_exclusive (service);
823 uberlord 2547
824 uberlord 2577 if (! rc_runlevel_stopping () &&
825     rc_service_in_runlevel (service, RC_LEVEL_BOOT))
826     ewarn ("WARNING: you are stopping a boot service");
827 uberlord 2547
828 uberlord 2577 if (deps || ! rc_service_state (service, rc_service_wasinactive)) {
829     int depoptions = RC_DEP_TRACE;
830     char *svc;
831     int i;
832 uberlord 2569
833 uberlord 2786 if (rc_is_env ("RC_DEPEND_STRICT", "yes"))
834 uberlord 2577 depoptions |= RC_DEP_STRICT;
835 uberlord 2547
836 uberlord 2786 if (rc_runlevel_stopping ())
837     depoptions |= RC_DEP_STOP;
838    
839 uberlord 2577 if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
840     eerrorx ("failed to load deptree");
841 uberlord 2547
842 uberlord 2577 rc_strlist_free (types);
843     types = rc_strlist_add (NULL, "needsme");
844     rc_strlist_free (svclist);
845     svclist = rc_strlist_add (NULL, applet);
846     rc_strlist_free (tmplist);
847     tmplist = NULL;
848     rc_strlist_free (services);
849     services = rc_get_depends (deptree, types, svclist,
850     softlevel, depoptions);
851     rc_strlist_reverse (services);
852     STRLIST_FOREACH (services, svc, i) {
853     if (rc_service_state (svc, rc_service_started) ||
854     rc_service_state (svc, rc_service_inactive))
855     {
856     rc_wait_service (svc);
857     if (rc_service_state (svc, rc_service_started) ||
858     rc_service_state (svc, rc_service_inactive))
859     {
860 uberlord 2641 pid_t pid = rc_stop_service (svc);
861 uberlord 2650 if (! rc_is_env ("RC_PARALLEL", "yes"))
862 uberlord 2641 rc_waitpid (pid);
863 uberlord 2577 tmplist = rc_strlist_add (tmplist, svc);
864     }
865     }
866     }
867     rc_strlist_free (services);
868     services = NULL;
869 uberlord 2547
870 uberlord 2577 STRLIST_FOREACH (tmplist, svc, i) {
871     if (rc_service_state (svc, rc_service_stopped))
872     continue;
873 uberlord 2547
874 uberlord 2577 /* We used to loop 3 times here - maybe re-do this if needed */
875     rc_wait_service (svc);
876     if (! rc_service_state (svc, rc_service_stopped)) {
877     if (rc_runlevel_stopping ())
878     rc_mark_service (svc, rc_service_failed);
879     eerrorx ("ERROR: cannot stop %s as %s is still up",
880     applet, svc);
881     }
882     }
883     rc_strlist_free (tmplist);
884     tmplist = NULL;
885 uberlord 2547
886 uberlord 2577 /* We now wait for other services that may use us and are stopping
887     This is important when a runlevel stops */
888     types = rc_strlist_add (types, "usesme");
889     types = rc_strlist_add (types, "ibefore");
890     services = rc_get_depends (deptree, types, svclist,
891     softlevel, depoptions);
892     STRLIST_FOREACH (services, svc, i) {
893     if (rc_service_state (svc, rc_service_stopped))
894     continue;
895     rc_wait_service (svc);
896     }
897 uberlord 2547
898 uberlord 2577 rc_strlist_free (services);
899     services = NULL;
900     rc_strlist_free (types);
901     types = NULL;
902     }
903 uberlord 2547
904 uberlord 2577 if (ibsave)
905     setenv ("IN_BACKGROUND", ibsave, 1);
906     rc_plugin_run (rc_hook_service_stop_now, applet);
907 uberlord 2669 stopped = svc_exec ("stop", NULL);
908 uberlord 2577 if (ibsave)
909     unsetenv ("IN_BACKGROUND");
910 uberlord 2547
911 uberlord 2577 if (! in_control ()) {
912     rc_plugin_run (rc_hook_service_stop_done, applet);
913     ewarnx ("WARNING: %s not under our control, aborting", applet);
914     }
915 uberlord 2547
916 uberlord 2577 if (! stopped) {
917     if (rc_service_state (service, rc_service_wasinactive))
918     rc_mark_service (service, rc_service_inactive);
919     else
920     rc_mark_service (service, rc_service_started);
921     rc_plugin_run (rc_hook_service_stop_done, applet);
922     eerrorx ("ERROR: %s failed to stop", applet);
923     }
924 uberlord 2547
925 uberlord 2577 if (in_background)
926     rc_mark_service (service, rc_service_inactive);
927     else
928     rc_mark_service (service, rc_service_stopped);
929 uberlord 2547
930 uberlord 2577 unlink_mtime_test ();
931     rc_plugin_run (rc_hook_service_stop_done, applet);
932     hook_out = 0;
933     rc_plugin_run (rc_hook_service_stop_out, applet);
934 uberlord 2547 }
935    
936 uberlord 2669 static void svc_restart (bool deps)
937 uberlord 2547 {
938 uberlord 2577 /* This is hairly and a better way needs to be found I think!
939     The issue is this - openvpn need net and dns. net can restart
940     dns via resolvconf, so you could have openvpn trying to restart dnsmasq
941     which in turn is waiting on net which in turn is waiting on dnsmasq.
942     The work around is for resolvconf to restart it's services with --nodeps
943     which means just that. The downside is that there is a small window when
944     our status is invalid.
945     One workaround would be to introduce a new status, or status locking. */
946     if (! deps) {
947     if (rc_service_state (service, rc_service_started) ||
948     rc_service_state (service, rc_service_inactive))
949 uberlord 2669 svc_exec ("stop", "start");
950 uberlord 2577 else
951 uberlord 2669 svc_exec ("start", NULL);
952 uberlord 2577 return;
953     }
954 uberlord 2547
955 uberlord 2577 if (! rc_service_state (service, rc_service_stopped)) {
956     get_started_services ();
957 uberlord 2669 svc_stop (deps);
958 uberlord 2577 }
959 uberlord 2547
960 uberlord 2669 svc_start (deps);
961     start_services (restart_services);
962     rc_strlist_free (restart_services);
963     restart_services = NULL;
964 uberlord 2547 }
965    
966 vapier 2618 #define getoptstring "dCDNqvh"
967     static struct option longopts[] = {
968     { "debug", 0, NULL, 'd'},
969     { "nocolor", 0, NULL, 'C'},
970     { "nocolour", 0, NULL, 'C'},
971     { "nodeps", 0, NULL, 'D'},
972     { "quiet", 0, NULL, 'q'},
973     { "verbose", 0, NULL, 'v'},
974     { "help", 0, NULL, 'h'},
975     { NULL, 0, NULL, 0}
976     };
977 uberlord 2634 // #include "_usage.c"
978 vapier 2618
979 uberlord 2799 int runscript (int argc, char **argv)
980 uberlord 2547 {
981 uberlord 2577 int i;
982     bool deps = true;
983     bool doneone = false;
984     char pid[16];
985     int retval;
986 uberlord 2698 int opt;
987 uberlord 2762 char *svc;
988 uberlord 2547
989 uberlord 2743 /* We need the full path to the service */
990     if (*argv[1] == '/')
991     service = rc_xstrdup (argv[1]);
992     else {
993     char pwd[PATH_MAX];
994     if (! getcwd (pwd, PATH_MAX))
995     eerrorx ("getcwd: %s", strerror (errno));
996     service = rc_strcatpaths (pwd, argv[1], (char *) NULL);
997     }
998    
999 uberlord 2706 applet = rc_xstrdup (basename (service));
1000     atexit (cleanup);
1001 uberlord 2731
1002     /* Change dir to / to ensure all init scripts don't use stuff in pwd */
1003     chdir ("/");
1004 uberlord 2706
1005 uberlord 2577 /* Show help if insufficient args */
1006     if (argc < 3) {
1007     execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
1008     eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1009     applet, strerror (errno));
1010     }
1011 uberlord 2547
1012     #ifdef __linux__
1013 uberlord 2577 /* coldplug events can trigger init scripts, but we don't want to run them
1014     until after rc sysinit has completed so we punt them to the boot runlevel */
1015     if (rc_exists ("/dev/.rcsysinit")) {
1016     eerror ("%s: cannot run until sysvinit completes", applet);
1017     if (mkdir ("/dev/.rcboot", 0755) != 0 && errno != EEXIST)
1018     eerrorx ("%s: mkdir `/dev/.rcboot': %s", applet, strerror (errno));
1019     tmp = rc_strcatpaths ("/dev/.rcboot", applet, (char *) NULL);
1020     symlink (service, tmp);
1021     exit (EXIT_FAILURE);
1022     }
1023 uberlord 2547 #endif
1024    
1025 uberlord 2577 if ((softlevel = getenv ("RC_SOFTLEVEL")) == NULL) {
1026     /* Ensure our environment is pure
1027     Also, add our configuration to it */
1028     env = rc_filter_env ();
1029     env = rc_config_env (env);
1030 uberlord 2547
1031 uberlord 2577 if (env) {
1032     char *p;
1033 uberlord 2547
1034     #ifdef __linux__
1035 uberlord 2577 /* clearenv isn't portable, but there's no harm in using it
1036     if we have it */
1037     clearenv ();
1038 uberlord 2547 #else
1039 uberlord 2577 char *var;
1040     /* No clearenv present here then.
1041     We could manipulate environ directly ourselves, but it seems that
1042     some kernels bitch about this according to the environ man pages
1043     so we walk though environ and call unsetenv for each value. */
1044     while (environ[0]) {
1045     tmp = rc_xstrdup (environ[0]);
1046     p = tmp;
1047     var = strsep (&p, "=");
1048     unsetenv (var);
1049     free (tmp);
1050     }
1051     tmp = NULL;
1052 uberlord 2547 #endif
1053    
1054 uberlord 2577 STRLIST_FOREACH (env, p, i)
1055     putenv (p);
1056     /* We don't free our list as that would be null in environ */
1057     }
1058 uberlord 2547
1059 uberlord 2577 softlevel = rc_get_runlevel ();
1060     }
1061 uberlord 2547
1062 uberlord 2577 setenv ("RC_ELOG", service, 1);
1063     setenv ("SVCNAME", applet, 1);
1064 uberlord 2547
1065 uberlord 2577 /* Set an env var so that we always know our pid regardless of any
1066     subshells the init script may create so that our mark_service_*
1067     functions can always instruct us of this change */
1068     snprintf (pid, sizeof (pid), "%d", (int) getpid ());
1069     setenv ("RC_RUNSCRIPT_PID", pid, 1);
1070 uberlord 2547
1071 uberlord 2652 /* eprefix is kinda klunky, but it works for our purposes */
1072 uberlord 2768 if (rc_is_env ("RC_PARALLEL", "yes")) {
1073 uberlord 2749 int l = 0;
1074 uberlord 2750 int ll;
1075 uberlord 2749
1076     /* Get the longest service name */
1077     services = rc_services_in_runlevel (NULL);
1078     STRLIST_FOREACH (services, svc, i) {
1079 uberlord 2750 ll = strlen (svc);
1080 uberlord 2749 if (ll > l)
1081     l = ll;
1082     }
1083 uberlord 2750
1084     /* Make our prefix string */
1085     prefix = rc_xmalloc (sizeof (char *) * l);
1086     ll = strlen (applet);
1087     memcpy (prefix, applet, ll);
1088     memset (prefix + ll, ' ', l - ll);
1089     memset (prefix + l, 0, 1);
1090 uberlord 2652 eprefix (prefix);
1091     }
1092    
1093 uberlord 2547 #ifdef __linux__
1094 uberlord 2577 /* Ok, we are ready to go, so setup selinux if applicable */
1095     setup_selinux (argc, argv);
1096 uberlord 2547 #endif
1097    
1098 uberlord 2581 /* Punt the first arg as it's our service name */
1099     argc--;
1100     argv++;
1101    
1102 uberlord 2577 /* Right then, parse any options there may be */
1103 uberlord 2698 while ((opt = getopt_long (argc, argv, getoptstring,
1104     longopts, (int *) 0)) != -1)
1105     switch (opt) {
1106 uberlord 2580 case 'd':
1107     setenv ("RC_DEBUG", "yes", 1);
1108     break;
1109     case 'h':
1110     execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
1111     eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1112     applet, strerror (errno));
1113     case 'C':
1114     setenv ("RC_NOCOLOR", "yes", 1);
1115     break;
1116     case 'D':
1117     deps = false;
1118     break;
1119     case 'q':
1120     setenv ("RC_QUIET", "yes", 1);
1121     break;
1122     case 'v':
1123     setenv ("RC_VERBOSE", "yes", 1);
1124     break;
1125     default:
1126     exit (EXIT_FAILURE);
1127     }
1128 uberlord 2547
1129 uberlord 2581 /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service
1130     that is being called and not any dependents */
1131     if (getenv ("IN_BACKGROUND")) {
1132     in_background = rc_is_env ("IN_BACKGROUND", "true");
1133 uberlord 2634 ibsave = rc_xstrdup (getenv ("IN_BACKGROUND"));
1134 uberlord 2581 unsetenv ("IN_BACKGROUND");
1135     }
1136    
1137 uberlord 2577 if (rc_is_env ("IN_HOTPLUG", "1")) {
1138     if (! rc_is_env ("RC_HOTPLUG", "yes") || ! rc_allow_plug (applet))
1139     eerrorx ("%s: not allowed to be hotplugged", applet);
1140     }
1141 uberlord 2547
1142 uberlord 2577 /* Setup a signal handler */
1143     signal (SIGHUP, handle_signal);
1144     signal (SIGINT, handle_signal);
1145     signal (SIGQUIT, handle_signal);
1146     signal (SIGTERM, handle_signal);
1147     signal (SIGCHLD, handle_signal);
1148 uberlord 2547
1149 uberlord 2577 /* Load our plugins */
1150     rc_plugin_load ();
1151 uberlord 2547
1152 uberlord 2577 /* Now run each option */
1153     retval = EXIT_SUCCESS;
1154 uberlord 2580 while (optind < argc) {
1155     optarg = argv[optind++];
1156    
1157 uberlord 2577 /* Abort on a sighup here */
1158     if (sighup)
1159     exit (EXIT_FAILURE);
1160 uberlord 2547
1161 uberlord 2738 if (strcmp (optarg, "status") != 0 &&
1162     strcmp (optarg, "help") != 0) {
1163     /* Only root should be able to run us */
1164     }
1165    
1166 uberlord 2577 /* Export the command we're running.
1167     This is important as we stamp on the restart function now but
1168     some start/stop routines still need to behave differently if
1169     restarting. */
1170     unsetenv ("RC_CMD");
1171 uberlord 2580 setenv ("RC_CMD", optarg, 1);
1172 uberlord 2569
1173 uberlord 2577 doneone = true;
1174 uberlord 2765
1175     if (strcmp (optarg, "describe") == 0) {
1176     svc_exec (optarg, NULL);
1177     } else if (strcmp (optarg, "help") == 0) {
1178 uberlord 2577 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL);
1179     eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1180     applet, strerror (errno));
1181 uberlord 2762 } else if (strcmp (optarg, "ineed") == 0 ||
1182     strcmp (optarg, "iuse") == 0 ||
1183     strcmp (optarg, "needsme") == 0 ||
1184     strcmp (optarg, "usesme") == 0 ||
1185     strcmp (optarg, "iafter") == 0 ||
1186 uberlord 2763 strcmp (optarg, "ibefore") == 0 ||
1187     strcmp (optarg, "iprovide") == 0) {
1188 uberlord 2786 int depoptions = RC_DEP_TRACE;
1189    
1190     if (rc_is_env ("RC_DEPEND_STRICT", "yes"))
1191     depoptions |= RC_DEP_STRICT;
1192    
1193 uberlord 2762 if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
1194     eerrorx ("failed to load deptree");
1195    
1196     rc_strlist_free (types);
1197     types = rc_strlist_add (NULL, optarg);
1198     rc_strlist_free (svclist);
1199     svclist = rc_strlist_add (NULL, applet);
1200     rc_strlist_free (services);
1201 uberlord 2786 services = rc_get_depends (deptree, types, svclist,
1202     softlevel, depoptions);
1203 uberlord 2762 STRLIST_FOREACH (services, svc, i)
1204     printf ("%s%s", i == 1 ? "" : " ", svc);
1205     printf ("\n");
1206 uberlord 2763 } else if (strcmp (optarg, "status") == 0) {
1207     rc_service_state_t r = svc_status (service);
1208     retval = (int) r;
1209 uberlord 2765
1210 uberlord 2763 } else if (strcmp (optarg, "help") == 0) {
1211     execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL);
1212     eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1213     applet, strerror (errno));
1214     } else {
1215     if (geteuid () != 0)
1216     eerrorx ("%s: root access required", applet);
1217 uberlord 2547
1218 uberlord 2763 if (strcmp (optarg, "conditionalrestart") == 0 ||
1219     strcmp (optarg, "condrestart") == 0)
1220     {
1221     if (rc_service_state (service, rc_service_started))
1222     svc_restart (deps);
1223     } else if (strcmp (optarg, "restart") == 0) {
1224     svc_restart (deps);
1225     } else if (strcmp (optarg, "start") == 0) {
1226     svc_start (deps);
1227     } else if (strcmp (optarg, "stop") == 0) {
1228     if (in_background)
1229     get_started_services ();
1230 uberlord 2547
1231 uberlord 2763 svc_stop (deps);
1232 uberlord 2547
1233 uberlord 2763 if (! in_background &&
1234     ! rc_runlevel_stopping () &&
1235     rc_service_state (service, rc_service_stopped))
1236     uncoldplug ();
1237    
1238     if (in_background &&
1239     rc_service_state (service, rc_service_inactive))
1240     {
1241     int j;
1242     STRLIST_FOREACH (restart_services, svc, j)
1243     if (rc_service_state (svc, rc_service_stopped))
1244     rc_schedule_start_service (service, svc);
1245     }
1246     } else if (strcmp (optarg, "zap") == 0) {
1247     einfo ("Manually resetting %s to stopped state", applet);
1248     rc_mark_service (applet, rc_service_stopped);
1249     uncoldplug ();
1250 uberlord 2765 } else
1251 uberlord 2763 svc_exec (optarg, NULL);
1252    
1253     /* We should ensure this list is empty after an action is done */
1254     rc_strlist_free (restart_services);
1255     restart_services = NULL;
1256     }
1257    
1258     if (! doneone) {
1259     execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
1260     eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1261     applet, strerror (errno));
1262     }
1263 uberlord 2577 }
1264 uberlord 2547
1265 uberlord 2577 return (retval);
1266 uberlord 2547 }

  ViewVC Help
Powered by ViewVC 1.1.20