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

Diff of /trunk/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 2650 Revision 2652
7 */ 7 */
8 8
9#define APPLET "runscript" 9#define APPLET "runscript"
10 10
11#include <sys/types.h> 11#include <sys/types.h>
12#include <sys/param.h>
12#include <sys/stat.h> 13#include <sys/stat.h>
13#include <sys/wait.h> 14#include <sys/wait.h>
14#include <dlfcn.h> 15#include <dlfcn.h>
15#include <errno.h> 16#include <errno.h>
17#include <fcntl.h>
16#include <getopt.h> 18#include <getopt.h>
17#include <libgen.h> 19#include <libgen.h>
18#include <limits.h> 20#include <limits.h>
19#include <signal.h> 21#include <signal.h>
20#include <stdio.h> 22#include <stdio.h>
48static bool sighup = false; 50static bool sighup = false;
49static char *ibsave = NULL; 51static char *ibsave = NULL;
50static bool in_background = false; 52static bool in_background = false;
51static rc_hook_t hook_out = 0; 53static rc_hook_t hook_out = 0;
52static pid_t service_pid = 0; 54static pid_t service_pid = 0;
55static char *prefix = NULL;
56
57/* Pipes for prefixed output */
53 58
54extern char **environ; 59extern char **environ;
55 60
56#ifdef __linux__ 61#ifdef __linux__
57static void (*selinux_run_init_old) (void); 62static void (*selinux_run_init_old) (void);
58static void (*selinux_run_init_new) (int argc, char **argv); 63static void (*selinux_run_init_new) (int argc, char **argv);
59 64
60void setup_selinux (int argc, char **argv); 65static void setup_selinux (int argc, char **argv);
61#endif 66#endif
62 67
63#ifdef __linux__ 68#ifdef __linux__
64void setup_selinux (int argc, char **argv) 69static void setup_selinux (int argc, char **argv)
65{ 70{
66 void *lib_handle = NULL; 71 void *lib_handle = NULL;
67 72
68 lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL); 73 lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL);
69 if (lib_handle) { 74 if (lib_handle) {
203 208
204 if (hook_out) 209 if (hook_out)
205 rc_plugin_run (hook_out, applet); 210 rc_plugin_run (hook_out, applet);
206 rc_plugin_unload (); 211 rc_plugin_unload ();
207 212
208 if (deptree)
209 rc_free_deptree (deptree); 213 rc_free_deptree (deptree);
210 if (services)
211 rc_strlist_free (services); 214 rc_strlist_free (services);
212 if (types)
213 rc_strlist_free (types); 215 rc_strlist_free (types);
214 if (svclist)
215 rc_strlist_free (svclist); 216 rc_strlist_free (svclist);
216 if (providelist)
217 rc_strlist_free (providelist); 217 rc_strlist_free (providelist);
218 if (restart_services)
219 rc_strlist_free (restart_services); 218 rc_strlist_free (restart_services);
220 if (need_services)
221 rc_strlist_free (need_services); 219 rc_strlist_free (need_services);
222 if (tmplist)
223 rc_strlist_free (tmplist); 220 rc_strlist_free (tmplist);
224 if (ibsave)
225 free (ibsave); 221 free (ibsave);
226 222
227 if (in_control ()) { 223 if (in_control ()) {
228 if (rc_service_state (applet, rc_service_stopping)) { 224 if (rc_service_state (applet, rc_service_stopping)) {
229 /* If the we're shutting down, do it cleanly */ 225 /* If the we're shutting down, do it cleanly */
230 if ((softlevel && 226 if ((softlevel &&
246 } 242 }
247 if (exclusive && rc_exists (exclusive)) 243 if (exclusive && rc_exists (exclusive))
248 unlink (exclusive); 244 unlink (exclusive);
249 } 245 }
250 246
251 if (env)
252 rc_strlist_free (env); 247 rc_strlist_free (env);
253 248
254 if (mtime_test) 249 if (mtime_test)
255 { 250 {
256 unlink (mtime_test); 251 unlink (mtime_test);
257 free (mtime_test); 252 free (mtime_test);
258 } 253 }
259 if (exclusive)
260 free (exclusive); 254 free (exclusive);
261
262 if (applet)
263 free (applet); 255 free (applet);
256 free (prefix);
257}
258
259static int write_prefix (int fd, const char *buffer, size_t bytes, bool *prefixed) {
260 unsigned int i;
261 int j;
262 const char *ec;
263 const char *ec_normal = ecolor (ecolor_normal);
264 ssize_t ret = 0;
265
266 if (fd == fileno (stdout))
267 ec = ecolor (ecolor_hilite);
268 else
269 ec = ecolor (ecolor_bad);
270
271 for (i = 0; i < bytes; i++) {
272 /* We don't prefix escape codes, like eend */
273 if (buffer[i] == '\033')
274 *prefixed = true;
275
276 if (! *prefixed) {
277 ret += write (fd, ec, strlen (ec));
278 ret += write (fd, applet, strlen (applet));
279 for (j = strlen (applet); j < 11; j++)
280 ret += write (fd, " ", 1);
281 ret += write (fd, ec_normal, strlen (ec_normal));
282 ret += write (fd, " |", 2);
283 *prefixed = true;
284 }
285
286 if (buffer[i] == '\n')
287 *prefixed = false;
288 ret += write (fd, buffer + i, 1);
289 }
290
291 return (ret);
264} 292}
265 293
266static bool svc_exec (const char *service, const char *arg1, const char *arg2) 294static bool svc_exec (const char *service, const char *arg1, const char *arg2)
267{ 295{
268 bool retval; 296 bool execok;
297 int stdout_pipes[2];
298 int stderr_pipes[2];
269 299
270 /* To ensure any output has hit our ebuffer */ 300 /* To ensure any output has hit our ebuffer */
271 fflush (stdout); 301 fflush (stdout);
272 fflush (stderr); 302 fflush (stderr);
273 303
304 /* Setup our pipes for prefixed output */
305 if (rc_is_env ("RC_PREFIX", "yes")) {
306 if (pipe (stdout_pipes))
307 eerror ("pipe: %s", strerror (errno));
308 if (pipe (stderr_pipes))
309 eerror ("pipe: %s", strerror (errno));
310 }
311
274 /* We need to disable our child signal handler now so we block 312 /* We need to disable our child signal handler now so we block
275 until our script returns. */ 313 until our script returns. */
276 signal (SIGCHLD, NULL); 314 signal (SIGCHLD, NULL);
277 315
278 service_pid = vfork(); 316 service_pid = vfork();
279 317
280 if (service_pid == -1) 318 if (service_pid == -1)
281 eerrorx ("%s: vfork: %s", service, strerror (errno)); 319 eerrorx ("%s: vfork: %s", service, strerror (errno));
282 if (service_pid == 0) { 320 if (service_pid == 0) {
321 if (rc_is_env ("RC_PREFIX", "yes")) {
322 int flags;
323
324 if (dup2 (stdout_pipes[1], fileno (stdout)) == -1)
325 eerror ("dup2 stdout: %s", strerror (errno));
326 close (stdout_pipes[0]);
327 if (dup2 (stderr_pipes[1], fileno (stderr)) == -1)
328 eerror ("dup2 stderr: %s", strerror (errno));
329 close (stderr_pipes[0]);
330
331 /* Stop any scripts from inheriting us */
332 if ((flags = fcntl (stdout_pipes[1], F_GETFD, 0)) < 0 ||
333 fcntl (stdout_pipes[1], F_SETFD, flags | FD_CLOEXEC) < 0)
334 eerror ("fcntl: %s", strerror (errno));
335 if ((flags = fcntl (stderr_pipes[1], F_GETFD, 0)) < 0 ||
336 fcntl (stderr_pipes[1], F_SETFD, flags | FD_CLOEXEC) < 0)
337 eerror ("fcntl: %s", strerror (errno));
338 }
339
283 if (rc_exists (RC_SVCDIR "runscript.sh")) { 340 if (rc_exists (RC_SVCDIR "runscript.sh")) {
284 execl (RC_SVCDIR "runscript.sh", service, service, arg1, arg2, 341 execl (RC_SVCDIR "runscript.sh", service, service, arg1, arg2,
285 (char *) NULL); 342 (char *) NULL);
286 eerror ("%s: exec `" RC_SVCDIR "runscript.sh': %s", 343 eerror ("%s: exec `" RC_SVCDIR "runscript.sh': %s",
287 service, strerror (errno)); 344 service, strerror (errno));
293 service, strerror (errno)); 350 service, strerror (errno));
294 _exit (EXIT_FAILURE); 351 _exit (EXIT_FAILURE);
295 } 352 }
296 } 353 }
297 354
355 /* Prefix our piped output */
356 if (rc_is_env ("RC_PREFIX", "yes")) {
357 bool stdout_done = false;
358 bool stdout_prefix_shown = false;
359 bool stderr_done = false;
360 bool stderr_prefix_shown = false;
361 char buffer[RC_LINEBUFFER];
362
363 close (stdout_pipes[1]);
364 close (stderr_pipes[1]);
365
366 memset (buffer, 0, RC_LINEBUFFER);
367 while (! stdout_done && ! stderr_done) {
368 fd_set fds;
369 int retval;
370
371 FD_ZERO (&fds);
372 FD_SET (stdout_pipes[0], &fds);
373 FD_SET (stderr_pipes[0], &fds);
374 retval = select (MAX (stdout_pipes[0], stderr_pipes[0]) + 1,
375 &fds, 0, 0, 0);
376 if (retval < 0) {
377 if (errno != EINTR)
378 eerror ("select: %s", strerror (errno));
379 break;
380 } else if (retval) {
381 ssize_t nr;
382
383 if (FD_ISSET (stdout_pipes[0], &fds)) {
384 if ((nr = read (stdout_pipes[0], buffer,
385 sizeof (buffer))) <= 0)
386 stdout_done = true;
387 else
388 write_prefix (fileno (stdout), buffer, nr,
389 &stdout_prefix_shown);
390 }
391
392 if (FD_ISSET (stderr_pipes[0], &fds)) {
393 if ((nr = read (stderr_pipes[0], buffer,
394 sizeof (buffer))) <= 0)
395 stderr_done = true;
396 else
397 write_prefix (fileno (stderr), buffer, nr,
398 &stderr_prefix_shown);
399 }
400 }
401 }
402
403 /* Done now, so close the pipes */
404 close(stdout_pipes[0]);
405 close(stderr_pipes[0]);
406 }
407
298 retval = rc_waitpid (service_pid) == 0 ? true : false; 408 execok = rc_waitpid (service_pid) == 0 ? true : false;
299
300 service_pid = 0; 409 service_pid = 0;
410
301 /* Done, so restore the signal handler */ 411 /* Done, so restore the signal handler */
302 signal (SIGCHLD, handle_signal); 412 signal (SIGCHLD, handle_signal);
303 413
304 return (retval); 414 return (execok);
305} 415}
306 416
307static rc_service_state_t svc_status (const char *service) 417static rc_service_state_t svc_status (const char *service)
308{ 418{
309 char status[10]; 419 char status[10];
897 subshells the init script may create so that our mark_service_* 1007 subshells the init script may create so that our mark_service_*
898 functions can always instruct us of this change */ 1008 functions can always instruct us of this change */
899 snprintf (pid, sizeof (pid), "%d", (int) getpid ()); 1009 snprintf (pid, sizeof (pid), "%d", (int) getpid ());
900 setenv ("RC_RUNSCRIPT_PID", pid, 1); 1010 setenv ("RC_RUNSCRIPT_PID", pid, 1);
901 1011
1012 /* eprefix is kinda klunky, but it works for our purposes */
902 if (rc_is_env ("RC_PARALLEL", "yes")) { 1013 if (rc_is_env ("RC_PREFIX", "yes")) {
1014 int l = strlen (applet);
1015 if (l < 13)
1016 l = 13;
1017 prefix = rc_xmalloc (sizeof (char *) * l);
1018 snprintf (prefix, l, "%s%s", applet, " ");
1019 eprefix (prefix);
1020 }
1021
1022 /* If we're in parallel and we're not prefixing then we need the ebuffer */
1023 if (rc_is_env ("RC_PARALLEL", "yes") && ! rc_is_env ("RC_PREFIX", "yes")) {
903 char ebname[PATH_MAX]; 1024 char ebname[PATH_MAX];
904 char *eb; 1025 char *eb;
905 1026
906 snprintf (ebname, sizeof (ebname), "%s.%s", applet, pid); 1027 snprintf (ebname, sizeof (ebname), "%s.%s", applet, pid);
907 eb = rc_strcatpaths (RC_SVCDIR "ebuffer", ebname, (char *) NULL); 1028 eb = rc_strcatpaths (RC_SVCDIR "ebuffer", ebname, (char *) NULL);

Legend:
Removed from v.2650  
changed lines
  Added in v.2652

  ViewVC Help
Powered by ViewVC 1.1.20