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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20