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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20