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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20