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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20