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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20