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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20