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

Contents of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20