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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20