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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2786 - (hide annotations) (download) (as text)
Sat Jul 21 12:49:51 2007 UTC (7 years, 2 months ago) by uberlord
File MIME type: text/x-csrc
File size: 34366 byte(s)
    RC_DEPEND_STRICT now controls dependency strictness.
    If yes then we only use services in the boot and default runlevels,
    regradless of service state.
    If no then we take into account coldplugged services and the state
    of currently running services.
    Fixes #185640.
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 ("IN_HOTPLUG", "1") || in_background) {
577 uberlord 2578 if (! rc_service_state (service, rc_service_inactive) &&
578 uberlord 2582 ! rc_service_state (service, rc_service_stopped))
579 uberlord 2577 exit (EXIT_FAILURE);
580     background = true;
581     }
582 uberlord 2547
583 uberlord 2666 if (rc_service_state (service, rc_service_started)) {
584     ewarn ("WARNING: %s has already been started", applet);
585     return;
586     } else if (rc_service_state (service, rc_service_starting))
587 uberlord 2577 ewarnx ("WARNING: %s is already starting", applet);
588     else if (rc_service_state (service, rc_service_stopping))
589     ewarnx ("WARNING: %s is stopping", applet);
590     else if (rc_service_state (service, rc_service_inactive) && ! background)
591     ewarnx ("WARNING: %s has already started, but is inactive", applet);
592 uberlord 2547
593 uberlord 2577 if (! rc_mark_service (service, rc_service_starting))
594     eerrorx ("ERROR: %s has been started by something else", applet);
595 uberlord 2547
596 uberlord 2577 make_exclusive (service);
597 uberlord 2547
598 uberlord 2786 if (rc_is_env ("RC_DEPEND_STRICT", "yes"))
599     depoptions |= RC_DEP_STRICT;
600    
601     if (rc_runlevel_starting ())
602     depoptions |= RC_DEP_START;
603    
604 uberlord 2577 if (deps) {
605     if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
606     eerrorx ("failed to load deptree");
607 uberlord 2547
608 uberlord 2577 rc_strlist_free (types);
609     types = rc_strlist_add (NULL, "broken");
610     rc_strlist_free (svclist);
611     svclist = rc_strlist_add (NULL, applet);
612     rc_strlist_free (services);
613     services = rc_get_depends (deptree, types, svclist, softlevel, 0);
614     if (services) {
615     eerrorn ("ERROR: `%s' needs ", applet);
616     STRLIST_FOREACH (services, svc, i) {
617     if (i > 0)
618     fprintf (stderr, ", ");
619     fprintf (stderr, "%s", svc);
620     }
621     exit (EXIT_FAILURE);
622     }
623     rc_strlist_free (services);
624     services = NULL;
625 uberlord 2547
626 uberlord 2577 rc_strlist_free (types);
627     types = rc_strlist_add (NULL, "ineed");
628     rc_strlist_free (need_services);
629     need_services = rc_get_depends (deptree, types, svclist,
630     softlevel, depoptions);
631 uberlord 2741
632 uberlord 2577 types = rc_strlist_add (types, "iuse");
633 uberlord 2741 rc_strlist_free (use_services);
634     use_services = rc_get_depends (deptree, types, svclist,
635     softlevel, depoptions);
636    
637 uberlord 2577 if (! rc_runlevel_starting ()) {
638 uberlord 2741 STRLIST_FOREACH (use_services, svc, i)
639 uberlord 2641 if (rc_service_state (svc, rc_service_stopped)) {
640     pid_t pid = rc_start_service (svc);
641 uberlord 2650 if (! rc_is_env ("RC_PARALLEL", "yes"))
642 uberlord 2641 rc_waitpid (pid);
643     }
644 uberlord 2577 }
645 uberlord 2547
646 uberlord 2577 /* Now wait for them to start */
647     types = rc_strlist_add (types, "iafter");
648     services = rc_get_depends (deptree, types, svclist,
649     softlevel, depoptions);
650 uberlord 2547
651 uberlord 2577 /* We use tmplist to hold our scheduled by list */
652     rc_strlist_free (tmplist);
653     tmplist = NULL;
654 uberlord 2547
655 uberlord 2577 STRLIST_FOREACH (services, svc, i) {
656 uberlord 2741 if (rc_service_state (svc, rc_service_started))
657 uberlord 2577 continue;
658 uberlord 2741
659     /* Don't wait for services which went inactive but are now in
660     * starting state which we are after */
661     if (rc_service_state (svc, rc_service_starting) &&
662     rc_service_state(svc, rc_service_wasinactive)) {
663     bool use = false;
664     STRLIST_FOREACH (use_services, svc2, j)
665     if (strcmp (svc, svc2) == 0) {
666     use = true;
667     break;
668     }
669     if (! use)
670     continue;
671     }
672 uberlord 2740
673 uberlord 2577 if (! rc_wait_service (svc))
674     eerror ("%s: timed out waiting for %s", applet, svc);
675     if (rc_service_state (svc, rc_service_started))
676     continue;
677 uberlord 2547
678 uberlord 2577 STRLIST_FOREACH (need_services, svc2, j)
679     if (strcmp (svc, svc2) == 0) {
680     if (rc_service_state (svc, rc_service_inactive) ||
681     rc_service_state (svc, rc_service_wasinactive))
682     tmplist = rc_strlist_add (tmplist, svc);
683     else
684     eerrorx ("ERROR: cannot start %s as %s would not start",
685     applet, svc);
686     }
687     }
688 uberlord 2547
689 uberlord 2577 if (tmplist) {
690     int n = 0;
691     int len = 0;
692     char *p;
693 uberlord 2547
694 uberlord 2577 /* Set the state now, then unlink our exclusive so that
695     our scheduled list is preserved */
696     rc_mark_service (service, rc_service_stopped);
697     unlink_mtime_test ();
698 uberlord 2547
699 uberlord 2577 rc_strlist_free (types);
700     types = rc_strlist_add (NULL, "iprovide");
701     STRLIST_FOREACH (tmplist, svc, i) {
702     rc_schedule_start_service (svc, service);
703 uberlord 2547
704 uberlord 2577 rc_strlist_free (svclist);
705     svclist = rc_strlist_add (NULL, svc);
706     rc_strlist_free (providelist);
707     providelist = rc_get_depends (deptree, types, svclist,
708     softlevel, depoptions);
709     STRLIST_FOREACH (providelist, svc2, j)
710     rc_schedule_start_service (svc2, service);
711 uberlord 2547
712 uberlord 2577 len += strlen (svc) + 2;
713     n++;
714     }
715 uberlord 2547
716 uberlord 2577 len += 5;
717     tmp = rc_xmalloc (sizeof (char *) * len);
718     p = tmp;
719     STRLIST_FOREACH (tmplist, svc, i) {
720     if (i > 1) {
721 uberlord 2770 if (i == n)
722 uberlord 2577 p += snprintf (p, len, " or ");
723     else
724     p += snprintf (p, len, ", ");
725     }
726     p += snprintf (p, len, "%s", svc);
727     }
728     ewarnx ("WARNING: %s is scheduled to start when %s has started",
729     applet, tmp);
730     }
731 uberlord 2547
732 uberlord 2577 rc_strlist_free (services);
733     services = NULL;
734     rc_strlist_free (types);
735     types = NULL;
736     rc_strlist_free (svclist);
737     svclist = NULL;
738     }
739 uberlord 2547
740 uberlord 2577 if (ibsave)
741     setenv ("IN_BACKGROUND", ibsave, 1);
742     rc_plugin_run (rc_hook_service_start_now, applet);
743 uberlord 2669 started = svc_exec ("start", NULL);
744 uberlord 2577 if (ibsave)
745     unsetenv ("IN_BACKGROUND");
746 uberlord 2547
747 uberlord 2577 if (in_control ()) {
748     if (! started) {
749     if (rc_service_state (service, rc_service_wasinactive))
750     rc_mark_service (service, rc_service_inactive);
751     else {
752     rc_mark_service (service, rc_service_stopped);
753     if (rc_runlevel_starting ())
754     rc_mark_service (service, rc_service_failed);
755     }
756     rc_plugin_run (rc_hook_service_start_done, applet);
757     eerrorx ("ERROR: %s failed to start", applet);
758     }
759     rc_mark_service (service, rc_service_started);
760     unlink_mtime_test ();
761     rc_plugin_run (rc_hook_service_start_done, applet);
762     } else {
763     rc_plugin_run (rc_hook_service_start_done, applet);
764     if (rc_service_state (service, rc_service_inactive))
765     ewarnx ("WARNING: %s has started, but is inactive", applet);
766     else
767     ewarnx ("WARNING: %s not under our control, aborting", applet);
768     }
769 uberlord 2547
770 uberlord 2577 /* Now start any scheduled services */
771     rc_strlist_free (services);
772     services = rc_services_scheduled (service);
773     STRLIST_FOREACH (services, svc, i)
774     if (rc_service_state (svc, rc_service_stopped))
775     rc_start_service (svc);
776     rc_strlist_free (services);
777     services = NULL;
778 uberlord 2547
779 uberlord 2577 /* Do the same for any services we provide */
780     rc_strlist_free (types);
781     types = rc_strlist_add (NULL, "iprovide");
782     rc_strlist_free (svclist);
783     svclist = rc_strlist_add (NULL, applet);
784     rc_strlist_free (tmplist);
785     tmplist = rc_get_depends (deptree, types, svclist, softlevel, depoptions);
786 uberlord 2547
787 uberlord 2577 STRLIST_FOREACH (tmplist, svc2, j) {
788     rc_strlist_free (services);
789     services = rc_services_scheduled (svc2);
790     STRLIST_FOREACH (services, svc, i)
791     if (rc_service_state (svc, rc_service_stopped))
792     rc_start_service (svc);
793     }
794 uberlord 2573
795 uberlord 2577 hook_out = 0;
796     rc_plugin_run (rc_hook_service_start_out, applet);
797 uberlord 2547 }
798    
799 uberlord 2669 static void svc_stop (bool deps)
800 uberlord 2547 {
801 uberlord 2577 bool stopped;
802 uberlord 2547
803 uberlord 2577 hook_out = rc_hook_service_stop_out;
804 uberlord 2573
805 uberlord 2577 if (rc_runlevel_stopping () &&
806     rc_service_state (service, rc_service_failed))
807     exit (EXIT_FAILURE);
808 uberlord 2547
809 uberlord 2577 if (rc_is_env ("IN_HOTPLUG", "1") || in_background)
810 uberlord 2578 if (! rc_service_state (service, rc_service_started) &&
811 uberlord 2582 ! rc_service_state (service, rc_service_inactive))
812 uberlord 2577 exit (EXIT_FAILURE);
813 uberlord 2547
814 uberlord 2666 if (rc_service_state (service, rc_service_stopped)) {
815     ewarn ("WARNING: %s is already stopped", applet);
816     return;
817     } else if (rc_service_state (service, rc_service_stopping))
818 uberlord 2577 ewarnx ("WARNING: %s is already stopping", applet);
819 uberlord 2547
820 uberlord 2577 if (! rc_mark_service (service, rc_service_stopping))
821     eerrorx ("ERROR: %s has been stopped by something else", applet);
822 uberlord 2547
823 uberlord 2577 make_exclusive (service);
824 uberlord 2547
825 uberlord 2577 if (! rc_runlevel_stopping () &&
826     rc_service_in_runlevel (service, RC_LEVEL_BOOT))
827     ewarn ("WARNING: you are stopping a boot service");
828 uberlord 2547
829 uberlord 2577 if (deps || ! rc_service_state (service, rc_service_wasinactive)) {
830     int depoptions = RC_DEP_TRACE;
831     char *svc;
832     int i;
833 uberlord 2569
834 uberlord 2786 if (rc_is_env ("RC_DEPEND_STRICT", "yes"))
835 uberlord 2577 depoptions |= RC_DEP_STRICT;
836 uberlord 2547
837 uberlord 2786 if (rc_runlevel_stopping ())
838     depoptions |= RC_DEP_STOP;
839    
840 uberlord 2577 if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
841     eerrorx ("failed to load deptree");
842 uberlord 2547
843 uberlord 2577 rc_strlist_free (types);
844     types = rc_strlist_add (NULL, "needsme");
845     rc_strlist_free (svclist);
846     svclist = rc_strlist_add (NULL, applet);
847     rc_strlist_free (tmplist);
848     tmplist = NULL;
849     rc_strlist_free (services);
850     services = rc_get_depends (deptree, types, svclist,
851     softlevel, depoptions);
852     rc_strlist_reverse (services);
853     STRLIST_FOREACH (services, svc, i) {
854     if (rc_service_state (svc, rc_service_started) ||
855     rc_service_state (svc, rc_service_inactive))
856     {
857     rc_wait_service (svc);
858     if (rc_service_state (svc, rc_service_started) ||
859     rc_service_state (svc, rc_service_inactive))
860     {
861 uberlord 2641 pid_t pid = rc_stop_service (svc);
862 uberlord 2650 if (! rc_is_env ("RC_PARALLEL", "yes"))
863 uberlord 2641 rc_waitpid (pid);
864 uberlord 2577 tmplist = rc_strlist_add (tmplist, svc);
865     }
866     }
867     }
868     rc_strlist_free (services);
869     services = NULL;
870 uberlord 2547
871 uberlord 2577 STRLIST_FOREACH (tmplist, svc, i) {
872     if (rc_service_state (svc, rc_service_stopped))
873     continue;
874 uberlord 2547
875 uberlord 2577 /* We used to loop 3 times here - maybe re-do this if needed */
876     rc_wait_service (svc);
877     if (! rc_service_state (svc, rc_service_stopped)) {
878     if (rc_runlevel_stopping ())
879     rc_mark_service (svc, rc_service_failed);
880     eerrorx ("ERROR: cannot stop %s as %s is still up",
881     applet, svc);
882     }
883     }
884     rc_strlist_free (tmplist);
885     tmplist = NULL;
886 uberlord 2547
887 uberlord 2577 /* We now wait for other services that may use us and are stopping
888     This is important when a runlevel stops */
889     types = rc_strlist_add (types, "usesme");
890     types = rc_strlist_add (types, "ibefore");
891     services = rc_get_depends (deptree, types, svclist,
892     softlevel, depoptions);
893     STRLIST_FOREACH (services, svc, i) {
894     if (rc_service_state (svc, rc_service_stopped))
895     continue;
896     rc_wait_service (svc);
897     }
898 uberlord 2547
899 uberlord 2577 rc_strlist_free (services);
900     services = NULL;
901     rc_strlist_free (types);
902     types = NULL;
903     }
904 uberlord 2547
905 uberlord 2577 if (ibsave)
906     setenv ("IN_BACKGROUND", ibsave, 1);
907     rc_plugin_run (rc_hook_service_stop_now, applet);
908 uberlord 2669 stopped = svc_exec ("stop", NULL);
909 uberlord 2577 if (ibsave)
910     unsetenv ("IN_BACKGROUND");
911 uberlord 2547
912 uberlord 2577 if (! in_control ()) {
913     rc_plugin_run (rc_hook_service_stop_done, applet);
914     ewarnx ("WARNING: %s not under our control, aborting", applet);
915     }
916 uberlord 2547
917 uberlord 2577 if (! stopped) {
918     if (rc_service_state (service, rc_service_wasinactive))
919     rc_mark_service (service, rc_service_inactive);
920     else
921     rc_mark_service (service, rc_service_started);
922     rc_plugin_run (rc_hook_service_stop_done, applet);
923     eerrorx ("ERROR: %s failed to stop", applet);
924     }
925 uberlord 2547
926 uberlord 2577 if (in_background)
927     rc_mark_service (service, rc_service_inactive);
928     else
929     rc_mark_service (service, rc_service_stopped);
930 uberlord 2547
931 uberlord 2577 unlink_mtime_test ();
932     rc_plugin_run (rc_hook_service_stop_done, applet);
933     hook_out = 0;
934     rc_plugin_run (rc_hook_service_stop_out, applet);
935 uberlord 2547 }
936    
937 uberlord 2669 static void svc_restart (bool deps)
938 uberlord 2547 {
939 uberlord 2577 /* This is hairly and a better way needs to be found I think!
940     The issue is this - openvpn need net and dns. net can restart
941     dns via resolvconf, so you could have openvpn trying to restart dnsmasq
942     which in turn is waiting on net which in turn is waiting on dnsmasq.
943     The work around is for resolvconf to restart it's services with --nodeps
944     which means just that. The downside is that there is a small window when
945     our status is invalid.
946     One workaround would be to introduce a new status, or status locking. */
947     if (! deps) {
948     if (rc_service_state (service, rc_service_started) ||
949     rc_service_state (service, rc_service_inactive))
950 uberlord 2669 svc_exec ("stop", "start");
951 uberlord 2577 else
952 uberlord 2669 svc_exec ("start", NULL);
953 uberlord 2577 return;
954     }
955 uberlord 2547
956 uberlord 2577 if (! rc_service_state (service, rc_service_stopped)) {
957     get_started_services ();
958 uberlord 2669 svc_stop (deps);
959 uberlord 2577 }
960 uberlord 2547
961 uberlord 2669 svc_start (deps);
962     start_services (restart_services);
963     rc_strlist_free (restart_services);
964     restart_services = NULL;
965 uberlord 2547 }
966    
967 vapier 2618 #define getoptstring "dCDNqvh"
968     static struct option longopts[] = {
969     { "debug", 0, NULL, 'd'},
970     { "nocolor", 0, NULL, 'C'},
971     { "nocolour", 0, NULL, 'C'},
972     { "nodeps", 0, NULL, 'D'},
973     { "quiet", 0, NULL, 'q'},
974     { "verbose", 0, NULL, 'v'},
975     { "help", 0, NULL, 'h'},
976     { NULL, 0, NULL, 0}
977     };
978 uberlord 2634 // #include "_usage.c"
979 vapier 2618
980 uberlord 2547 int main (int argc, char **argv)
981     {
982 uberlord 2577 int i;
983     bool deps = true;
984     bool doneone = false;
985     char pid[16];
986     int retval;
987 uberlord 2698 int opt;
988 uberlord 2762 char *svc;
989 uberlord 2547
990 uberlord 2743 /* We need the full path to the service */
991     if (*argv[1] == '/')
992     service = rc_xstrdup (argv[1]);
993     else {
994     char pwd[PATH_MAX];
995     if (! getcwd (pwd, PATH_MAX))
996     eerrorx ("getcwd: %s", strerror (errno));
997     service = rc_strcatpaths (pwd, argv[1], (char *) NULL);
998     }
999    
1000 uberlord 2706 applet = rc_xstrdup (basename (service));
1001     atexit (cleanup);
1002 uberlord 2731
1003     /* Change dir to / to ensure all init scripts don't use stuff in pwd */
1004     chdir ("/");
1005 uberlord 2706
1006 uberlord 2577 /* Show help if insufficient args */
1007     if (argc < 3) {
1008     execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
1009     eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1010     applet, strerror (errno));
1011     }
1012 uberlord 2547
1013     #ifdef __linux__
1014 uberlord 2577 /* coldplug events can trigger init scripts, but we don't want to run them
1015     until after rc sysinit has completed so we punt them to the boot runlevel */
1016     if (rc_exists ("/dev/.rcsysinit")) {
1017     eerror ("%s: cannot run until sysvinit completes", applet);
1018     if (mkdir ("/dev/.rcboot", 0755) != 0 && errno != EEXIST)
1019     eerrorx ("%s: mkdir `/dev/.rcboot': %s", applet, strerror (errno));
1020     tmp = rc_strcatpaths ("/dev/.rcboot", applet, (char *) NULL);
1021     symlink (service, tmp);
1022     exit (EXIT_FAILURE);
1023     }
1024 uberlord 2547 #endif
1025    
1026 uberlord 2577 if ((softlevel = getenv ("RC_SOFTLEVEL")) == NULL) {
1027     /* Ensure our environment is pure
1028     Also, add our configuration to it */
1029     env = rc_filter_env ();
1030     env = rc_config_env (env);
1031 uberlord 2547
1032 uberlord 2577 if (env) {
1033     char *p;
1034 uberlord 2547
1035     #ifdef __linux__
1036 uberlord 2577 /* clearenv isn't portable, but there's no harm in using it
1037     if we have it */
1038     clearenv ();
1039 uberlord 2547 #else
1040 uberlord 2577 char *var;
1041     /* No clearenv present here then.
1042     We could manipulate environ directly ourselves, but it seems that
1043     some kernels bitch about this according to the environ man pages
1044     so we walk though environ and call unsetenv for each value. */
1045     while (environ[0]) {
1046     tmp = rc_xstrdup (environ[0]);
1047     p = tmp;
1048     var = strsep (&p, "=");
1049     unsetenv (var);
1050     free (tmp);
1051     }
1052     tmp = NULL;
1053 uberlord 2547 #endif
1054    
1055 uberlord 2577 STRLIST_FOREACH (env, p, i)
1056     putenv (p);
1057     /* We don't free our list as that would be null in environ */
1058     }
1059 uberlord 2547
1060 uberlord 2577 softlevel = rc_get_runlevel ();
1061     }
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 uberlord 2768 if (rc_is_env ("RC_PARALLEL", "yes")) {
1074 uberlord 2749 int l = 0;
1075 uberlord 2750 int ll;
1076 uberlord 2749
1077     /* Get the longest service name */
1078     services = rc_services_in_runlevel (NULL);
1079     STRLIST_FOREACH (services, svc, i) {
1080 uberlord 2750 ll = strlen (svc);
1081 uberlord 2749 if (ll > l)
1082     l = ll;
1083     }
1084 uberlord 2750
1085     /* Make our prefix string */
1086     prefix = rc_xmalloc (sizeof (char *) * l);
1087     ll = strlen (applet);
1088     memcpy (prefix, applet, ll);
1089     memset (prefix + ll, ' ', l - ll);
1090     memset (prefix + l, 0, 1);
1091 uberlord 2652 eprefix (prefix);
1092     }
1093    
1094 uberlord 2547 #ifdef __linux__
1095 uberlord 2577 /* Ok, we are ready to go, so setup selinux if applicable */
1096     setup_selinux (argc, argv);
1097 uberlord 2547 #endif
1098    
1099 uberlord 2581 /* Punt the first arg as it's our service name */
1100     argc--;
1101     argv++;
1102    
1103 uberlord 2577 /* Right then, parse any options there may be */
1104 uberlord 2698 while ((opt = getopt_long (argc, argv, getoptstring,
1105     longopts, (int *) 0)) != -1)
1106     switch (opt) {
1107 uberlord 2580 case 'd':
1108     setenv ("RC_DEBUG", "yes", 1);
1109     break;
1110     case 'h':
1111     execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
1112     eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1113     applet, strerror (errno));
1114     case 'C':
1115     setenv ("RC_NOCOLOR", "yes", 1);
1116     break;
1117     case 'D':
1118     deps = false;
1119     break;
1120     case 'q':
1121     setenv ("RC_QUIET", "yes", 1);
1122     break;
1123     case 'v':
1124     setenv ("RC_VERBOSE", "yes", 1);
1125     break;
1126     default:
1127     exit (EXIT_FAILURE);
1128     }
1129 uberlord 2547
1130 uberlord 2581 /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service
1131     that is being called and not any dependents */
1132     if (getenv ("IN_BACKGROUND")) {
1133     in_background = rc_is_env ("IN_BACKGROUND", "true");
1134 uberlord 2634 ibsave = rc_xstrdup (getenv ("IN_BACKGROUND"));
1135 uberlord 2581 unsetenv ("IN_BACKGROUND");
1136     }
1137    
1138 uberlord 2577 if (rc_is_env ("IN_HOTPLUG", "1")) {
1139     if (! rc_is_env ("RC_HOTPLUG", "yes") || ! rc_allow_plug (applet))
1140     eerrorx ("%s: not allowed to be hotplugged", applet);
1141     }
1142 uberlord 2547
1143 uberlord 2577 /* Setup a signal handler */
1144     signal (SIGHUP, handle_signal);
1145     signal (SIGINT, handle_signal);
1146     signal (SIGQUIT, handle_signal);
1147     signal (SIGTERM, handle_signal);
1148     signal (SIGCHLD, handle_signal);
1149 uberlord 2547
1150 uberlord 2577 /* Load our plugins */
1151     rc_plugin_load ();
1152 uberlord 2547
1153 uberlord 2577 /* Now run each option */
1154     retval = EXIT_SUCCESS;
1155 uberlord 2580 while (optind < argc) {
1156     optarg = argv[optind++];
1157    
1158 uberlord 2577 /* Abort on a sighup here */
1159     if (sighup)
1160     exit (EXIT_FAILURE);
1161 uberlord 2547
1162 uberlord 2738 if (strcmp (optarg, "status") != 0 &&
1163     strcmp (optarg, "help") != 0) {
1164     /* Only root should be able to run us */
1165     }
1166    
1167 uberlord 2577 /* Export the command we're running.
1168     This is important as we stamp on the restart function now but
1169     some start/stop routines still need to behave differently if
1170     restarting. */
1171     unsetenv ("RC_CMD");
1172 uberlord 2580 setenv ("RC_CMD", optarg, 1);
1173 uberlord 2569
1174 uberlord 2577 doneone = true;
1175 uberlord 2765
1176     if (strcmp (optarg, "describe") == 0) {
1177     svc_exec (optarg, NULL);
1178     } else if (strcmp (optarg, "help") == 0) {
1179 uberlord 2577 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL);
1180     eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1181     applet, strerror (errno));
1182 uberlord 2762 } else if (strcmp (optarg, "ineed") == 0 ||
1183     strcmp (optarg, "iuse") == 0 ||
1184     strcmp (optarg, "needsme") == 0 ||
1185     strcmp (optarg, "usesme") == 0 ||
1186     strcmp (optarg, "iafter") == 0 ||
1187 uberlord 2763 strcmp (optarg, "ibefore") == 0 ||
1188     strcmp (optarg, "iprovide") == 0) {
1189 uberlord 2786 int depoptions = RC_DEP_TRACE;
1190    
1191     if (rc_is_env ("RC_DEPEND_STRICT", "yes"))
1192     depoptions |= RC_DEP_STRICT;
1193    
1194 uberlord 2762 if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
1195     eerrorx ("failed to load deptree");
1196    
1197     rc_strlist_free (types);
1198     types = rc_strlist_add (NULL, optarg);
1199     rc_strlist_free (svclist);
1200     svclist = rc_strlist_add (NULL, applet);
1201     rc_strlist_free (services);
1202 uberlord 2786 services = rc_get_depends (deptree, types, svclist,
1203     softlevel, depoptions);
1204 uberlord 2762 STRLIST_FOREACH (services, svc, i)
1205     printf ("%s%s", i == 1 ? "" : " ", svc);
1206     printf ("\n");
1207 uberlord 2763 } else if (strcmp (optarg, "status") == 0) {
1208     rc_service_state_t r = svc_status (service);
1209     retval = (int) r;
1210 uberlord 2765
1211 uberlord 2763 } else if (strcmp (optarg, "help") == 0) {
1212     execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL);
1213     eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1214     applet, strerror (errno));
1215     } else {
1216     if (geteuid () != 0)
1217     eerrorx ("%s: root access required", applet);
1218 uberlord 2547
1219 uberlord 2763 if (strcmp (optarg, "conditionalrestart") == 0 ||
1220     strcmp (optarg, "condrestart") == 0)
1221     {
1222     if (rc_service_state (service, rc_service_started))
1223     svc_restart (deps);
1224     } else if (strcmp (optarg, "restart") == 0) {
1225     svc_restart (deps);
1226     } else if (strcmp (optarg, "start") == 0) {
1227     svc_start (deps);
1228     } else if (strcmp (optarg, "stop") == 0) {
1229     if (in_background)
1230     get_started_services ();
1231 uberlord 2547
1232 uberlord 2763 svc_stop (deps);
1233 uberlord 2547
1234 uberlord 2763 if (! in_background &&
1235     ! rc_runlevel_stopping () &&
1236     rc_service_state (service, rc_service_stopped))
1237     uncoldplug ();
1238    
1239     if (in_background &&
1240     rc_service_state (service, rc_service_inactive))
1241     {
1242     int j;
1243     STRLIST_FOREACH (restart_services, svc, j)
1244     if (rc_service_state (svc, rc_service_stopped))
1245     rc_schedule_start_service (service, svc);
1246     }
1247     } else if (strcmp (optarg, "zap") == 0) {
1248     einfo ("Manually resetting %s to stopped state", applet);
1249     rc_mark_service (applet, rc_service_stopped);
1250     uncoldplug ();
1251 uberlord 2765 } else
1252 uberlord 2763 svc_exec (optarg, NULL);
1253    
1254     /* We should ensure this list is empty after an action is done */
1255     rc_strlist_free (restart_services);
1256     restart_services = NULL;
1257     }
1258    
1259     if (! doneone) {
1260     execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
1261     eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1262     applet, strerror (errno));
1263     }
1264 uberlord 2577 }
1265 uberlord 2547
1266 uberlord 2577 return (retval);
1267 uberlord 2547 }

  ViewVC Help
Powered by ViewVC 1.1.20