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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20