1 /* subprocs.c --- choosing, spawning, and killing screenhacks.
2 * xscreensaver, Copyright (c) 1991-2017 Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
21 #include <X11/Xlib.h> /* not used for much... */
27 #include <sys/time.h> /* sys/resource.h needs this for timeval */
28 #include <sys/param.h> /* for PATH_MAX */
30 #ifdef HAVE_SYS_WAIT_H
31 # include <sys/wait.h> /* for waitpid() and associated macros */
35 # include <sys/resource.h> /* for setrlimit() and RLIMIT_AS */
39 # include <processes.h>
40 # include <unixio.h> /* for close */
41 # include <unixlib.h> /* for getpid */
46 #include <signal.h> /* for the signal names */
49 #if !defined(SIGCHLD) && defined(SIGCLD)
50 # define SIGCHLD SIGCLD
53 #if 0 /* putenv() is declared in stdlib.h on modern linux systems. */
55 extern int putenv (/* const char * */); /* getenv() is in stdlib.h... */
59 extern int kill (pid_t, int); /* signal() is in sys/signal.h... */
61 /* This file doesn't need the Xt headers, so stub these types out... */
63 #define XtAppContext void*
64 #define XrmDatabase void*
65 #define XtIntervalId void*
66 #define XtPointer void*
69 #include "xscreensaver.h"
72 #include "visual.h" /* for id_to_visual() */
74 extern saver_info *global_si_kludge; /* I hate C so much... */
77 /* Used when printing error/debugging messages from signal handlers.
80 no_malloc_number_to_string (long num)
82 static char string[128] = "";
84 Bool negative_p = False;
97 while ((num > 0) && (num_digits < sizeof(string) - 1))
100 digit = (int) num % 10;
102 string[sizeof(string) - 1 - num_digits] = digit + '0';
109 string[sizeof(string) - 1 - num_digits] = '-';
112 return string + sizeof(string) - 1 - num_digits;
115 /* Like write(), but runs strlen() on the arg to get the length. */
117 write_string (int fd, const char *str)
119 return write (fd, str, strlen (str));
123 write_long (int fd, long n)
125 const char *str = no_malloc_number_to_string (n);
126 return write_string (fd, str);
130 /* RLIMIT_AS (called RLIMIT_VMEM on some systems) controls the maximum size
131 of a process's address space, i.e., the maximal brk(2) and mmap(2) values.
132 Setting this lets you put a cap on how much memory a process can allocate.
134 Except the "and mmap()" part kinda makes this useless, since many GL
135 implementations end up using mmap() to pull the whole frame buffer into
136 memory (or something along those lines) making it appear processes are
137 using hundreds of megabytes when in fact they're using very little, and
138 we end up capping their mallocs prematurely. YAY!
140 #if defined(RLIMIT_VMEM) && !defined(RLIMIT_AS)
141 # define RLIMIT_AS RLIMIT_VMEM
145 limit_subproc_memory (int address_space_limit, Bool verbose_p)
148 /* This has caused way more problems than it has solved...
149 Let's just completely ignore the "memoryLimit" option now.
151 #undef HAVE_SETRLIMIT
153 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_AS)
156 if (address_space_limit < 10 * 1024) /* let's not be crazy */
159 if (getrlimit (RLIMIT_AS, &r) != 0)
162 sprintf (buf, "%s: getrlimit(RLIMIT_AS) failed", blurb());
167 r.rlim_cur = address_space_limit;
169 if (setrlimit (RLIMIT_AS, &r) != 0)
172 sprintf (buf, "%s: setrlimit(RLIMIT_AS, {%lu, %lu}) failed",
173 blurb(), r.rlim_cur, r.rlim_max);
180 int i = address_space_limit;
182 if (i >= (1<<30) && i == ((i >> 30) << 30))
183 sprintf(buf, "%dG", i >> 30);
184 else if (i >= (1<<20) && i == ((i >> 20) << 20))
185 sprintf(buf, "%dM", i >> 20);
186 else if (i >= (1<<10) && i == ((i >> 10) << 10))
187 sprintf(buf, "%dK", i >> 10);
189 sprintf(buf, "%d bytes", i);
191 fprintf (stderr, "%s: limited pid %lu address space to %s.\n",
192 blurb(), (unsigned long) getpid (), buf);
195 #endif /* HAVE_SETRLIMIT && RLIMIT_AS */
199 /* Management of child processes, and de-zombification.
203 job_running, /* the process is still alive */
204 job_stopped, /* we have sent it a STOP signal */
205 job_killed, /* we have sent it a TERM signal */
206 job_dead /* we have wait()ed for it, and it's dead -- this state only
207 occurs so that we can avoid calling free() from a signal
208 handler. Shortly after going into this state, the list
209 element will be removed. */
212 struct screenhack_job {
216 enum job_status status;
217 time_t launched, killed;
218 struct screenhack_job *next;
221 static struct screenhack_job *jobs = 0;
223 /* for debugging -- nothing calls this, but it's useful to invoke from gdb.
225 void show_job_list (void);
230 struct screenhack_job *job;
231 fprintf(stderr, "%s: job list:\n", blurb());
232 for (job = jobs; job; job = job->next)
234 char b[] = " ??:??:?? ";
235 char *t = (job->killed ? timestring (job->killed) :
236 job->launched ? timestring (job->launched) : b);
239 fprintf (stderr, " %5ld: %2d: (%s) %s %s\n",
242 (job->status == job_running ? "running" :
243 job->status == job_stopped ? "stopped" :
244 job->status == job_killed ? " killed" :
245 job->status == job_dead ? " dead" : " ???"),
248 fprintf (stderr, "\n");
252 static void clean_job_list (void);
254 static struct screenhack_job *
255 make_job (pid_t pid, int screen, const char *cmd)
257 struct screenhack_job *job = (struct screenhack_job *) malloc (sizeof(*job));
259 static char name [1024];
260 const char *in = cmd;
267 while (isspace(*in)) in++; /* skip whitespace */
268 while (!isspace(*in) && *in != ':') {
269 if (*in == '=') got_eq = 1;
270 *out++ = *in++; /* snarf first token */
273 if (got_eq) /* if the first token was FOO=bar */
274 { /* then get the next token instead. */
280 while (isspace(*in)) in++; /* skip whitespace */
283 job->name = strdup(name);
285 job->screen = screen;
286 job->status = job_running;
287 job->launched = time ((time_t *) 0);
297 free_job (struct screenhack_job *job)
301 else if (job == jobs)
305 struct screenhack_job *job2, *prev;
306 for (prev = 0, job2 = jobs;
308 prev = job2, job2 = job2->next)
311 prev->next = job->next;
320 /* Cleans out dead jobs from the jobs list -- this must only be called
321 from the main thread, not from a signal handler.
324 clean_job_list (void)
326 struct screenhack_job *job, *prev, *next;
327 time_t now = time ((time_t *) 0);
328 static time_t last_warn = 0;
329 Bool warnedp = False;
331 for (prev = 0, job = jobs, next = (job ? job->next : 0);
333 prev = job, job = next, next = (job ? job->next : 0))
335 if (job->status == job_dead)
342 else if (job->status == job_killed &&
343 now - job->killed > 10 &&
344 now - last_warn > 10)
347 "%s: WARNING: pid %ld (%s) sent SIGTERM %ld seconds ago"
348 " and did not die!\n",
352 (long) (now - job->killed));
356 if (warnedp) last_warn = now;
360 static struct screenhack_job *
363 struct screenhack_job *job;
364 for (job = jobs; job; job = job->next)
370 static void await_dying_children (saver_info *si);
372 static void describe_dead_child (saver_info *, pid_t, int wait_status);
376 /* Semaphore to temporarily turn the SIGCHLD handler into a no-op.
377 Don't alter this directly -- use block_sigchld() / unblock_sigchld().
379 static int block_sigchld_handler = 0;
382 #ifdef HAVE_SIGACTION
384 #else /* !HAVE_SIGACTION */
386 #endif /* !HAVE_SIGACTION */
389 #ifdef HAVE_SIGACTION
393 memset (&sa, 0, sizeof (sa));
394 sa.sa_handler = SIG_IGN;
395 sigaction (SIGPIPE, &sa, NULL);
397 sigemptyset (&child_set);
398 sigaddset (&child_set, SIGCHLD);
399 sigprocmask (SIG_BLOCK, &child_set, 0);
401 #else /* !HAVE_SIGACTION */
402 signal (SIGPIPE, SIG_IGN);
403 #endif /* !HAVE_SIGACTION */
405 block_sigchld_handler++;
407 #ifdef HAVE_SIGACTION
409 #else /* !HAVE_SIGACTION */
411 #endif /* !HAVE_SIGACTION */
415 unblock_sigchld (void)
417 if (block_sigchld_handler <= 0)
420 if (block_sigchld_handler <= 1) /* only unblock if count going to 0 */
422 #ifdef HAVE_SIGACTION
426 memset(&sa, 0, sizeof (sa));
427 sa.sa_handler = SIG_DFL;
428 sigaction(SIGPIPE, &sa, NULL);
430 sigemptyset(&child_set);
431 sigaddset(&child_set, SIGCHLD);
432 sigprocmask(SIG_UNBLOCK, &child_set, 0);
434 #else /* !HAVE_SIGACTION */
435 signal(SIGPIPE, SIG_DFL);
436 #endif /* !HAVE_SIGACTION */
439 block_sigchld_handler--;
443 kill_job (saver_info *si, pid_t pid, int signal)
445 saver_preferences *p = &si->prefs;
446 struct screenhack_job *job;
451 if (in_signal_handler_p)
452 /* This function should not be called from the signal handler. */
455 block_sigchld(); /* we control the horizontal... */
457 job = find_job (pid);
460 job->status == job_killed)
463 fprintf (stderr, "%s: no child %ld to signal!\n",
464 blurb(), (long) pid);
470 job->status = job_killed;
471 job->killed = time ((time_t *) 0);
474 /* #### there must be a way to do this on VMS... */
475 case SIGSTOP: job->status = job_stopped; break;
476 case SIGCONT: job->status = job_running; break;
482 fprintf (stderr, "%s: %d: %s pid %lu (%s)\n",
483 blurb(), job->screen,
484 (job->status == job_killed ? "killing" :
485 job->status == job_stopped ? "suspending" : "resuming"),
486 (unsigned long) job->pid,
489 status = kill (job->pid, signal);
491 if (p->verbose_p && status < 0)
495 "%s: %d: child process %lu (%s) was already dead.\n",
496 blurb(), job->screen, (unsigned long) job->pid, job->name);
500 sprintf (buf, "%s: %d: couldn't kill child process %lu (%s)",
501 blurb(), job->screen, (unsigned long) job->pid, job->name);
506 await_dying_children (si);
510 if (block_sigchld_handler < 0)
520 sigchld_handler (int sig)
522 saver_info *si = global_si_kludge; /* I hate C so much... */
523 in_signal_handler_p++;
525 if (si->prefs.debug_p)
527 /* Don't call fprintf() from signal handlers, as it might malloc.
528 fprintf(stderr, "%s: got SIGCHLD%s\n", blurb(),
529 (block_sigchld_handler ? " (blocked)" : ""));
531 write_string (STDERR_FILENO, blurb());
532 write_string (STDERR_FILENO, ": got SIGCHLD");
534 if (block_sigchld_handler)
535 write_string (STDERR_FILENO, " (blocked)\n");
537 write_string (STDERR_FILENO, "\n");
540 if (block_sigchld_handler < 0)
542 else if (block_sigchld_handler == 0)
545 await_dying_children (si);
550 in_signal_handler_p--;
558 await_dying_children (saver_info *si)
566 kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED);
568 if (si->prefs.debug_p)
570 if (kid < 0 && errno)
572 /* Don't call fprintf() from signal handlers, as it might malloc.
573 fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", blurb(),
576 write_string (STDERR_FILENO, blurb());
577 write_string (STDERR_FILENO, ": waitpid(-1) ==> ");
578 write_long (STDERR_FILENO, (long) kid);
579 write_string (STDERR_FILENO, " (");
580 write_long (STDERR_FILENO, (long) errno);
581 write_string (STDERR_FILENO, ")\n");
585 /* Don't call fprintf() from signal handlers, as it might malloc.
586 fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", blurb(),
589 write_string (STDERR_FILENO, blurb());
590 write_string (STDERR_FILENO, ": waitpid(-1) ==> ");
591 write_long (STDERR_FILENO, (long) kid);
592 write_string (STDERR_FILENO, "\n");
596 /* 0 means no more children to reap.
597 -1 means error -- except "interrupted system call" isn't a "real"
598 error, so if we get that, we should just try again. */
600 (kid < 0 && errno != EINTR))
603 describe_dead_child (si, kid, wait_status);
609 describe_dead_child (saver_info *si, pid_t kid, int wait_status)
612 saver_preferences *p = &si->prefs;
613 struct screenhack_job *job = find_job (kid);
614 const char *name = job ? job->name : "<unknown>";
615 int screen_no = job ? job->screen : 0;
617 if (WIFEXITED (wait_status))
619 int exit_status = WEXITSTATUS (wait_status);
621 /* Treat exit code as a signed 8-bit quantity. */
622 if (exit_status & 0x80) exit_status |= ~0xFF;
624 /* One might assume that exiting with non-0 means something went wrong.
625 But that loser xswarm exits with the code that it was killed with, so
626 it *always* exits abnormally. Treat abnormal exits as "normal" (don't
627 mention them) if we've just killed the subprocess. But mention them
628 if they happen on their own.
632 (p->verbose_p || job->status != job_killed)))
634 /* Don't call fprintf() from signal handlers, as it might malloc.
636 "%s: %d: child pid %lu (%s) exited abnormally (code %d).\n",
637 blurb(), screen_no, (unsigned long) kid, name, exit_status);
639 write_string (STDERR_FILENO, blurb());
640 write_string (STDERR_FILENO, ": ");
641 write_long (STDERR_FILENO, (long) screen_no);
642 write_string (STDERR_FILENO, ": child pid ");
643 write_long (STDERR_FILENO, (long) kid);
644 write_string (STDERR_FILENO, " (");
645 write_string (STDERR_FILENO, name);
646 write_string (STDERR_FILENO, ") exited abnormally (code ");
647 write_long (STDERR_FILENO, (long) exit_status);
648 write_string (STDERR_FILENO, ").\n");
650 else if (p->verbose_p)
652 /* Don't call fprintf() from signal handlers, as it might malloc.
653 fprintf (stderr, "%s: %d: child pid %lu (%s) exited normally.\n",
654 blurb(), screen_no, (unsigned long) kid, name);
656 write_string (STDERR_FILENO, blurb());
657 write_string (STDERR_FILENO, ": ");
658 write_long (STDERR_FILENO, (long) screen_no);
659 write_string (STDERR_FILENO, ": child pid ");
660 write_long (STDERR_FILENO, (long) kid);
661 write_string (STDERR_FILENO, " (");
662 write_string (STDERR_FILENO, name);
663 write_string (STDERR_FILENO, ") exited normally.\n");
667 job->status = job_dead;
669 else if (WIFSIGNALED (wait_status))
673 job->status != job_killed ||
674 WTERMSIG (wait_status) != SIGTERM)
676 /* Don't call fprintf() from signal handlers, as it might malloc.
677 fprintf (stderr, "%s: %d: child pid %lu (%s) terminated with %s.\n",
678 blurb(), screen_no, (unsigned long) kid, name,
679 signal_name (WTERMSIG(wait_status)));
681 write_string (STDERR_FILENO, blurb());
682 write_string (STDERR_FILENO, ": ");
683 write_long (STDERR_FILENO, (long) screen_no);
684 write_string (STDERR_FILENO, ": child pid ");
685 write_long (STDERR_FILENO, (long) kid);
686 write_string (STDERR_FILENO, " (");
687 write_string (STDERR_FILENO, name);
688 write_string (STDERR_FILENO, ") terminated with signal ");
689 write_long (STDERR_FILENO, WTERMSIG(wait_status));
690 write_string (STDERR_FILENO, ".\n");
694 job->status = job_dead;
696 else if (WIFSTOPPED (wait_status))
700 /* Don't call fprintf() from signal handlers, as it might malloc.
701 fprintf (stderr, "%s: child pid %lu (%s) stopped with %s.\n",
702 blurb(), (unsigned long) kid, name,
703 signal_name (WSTOPSIG (wait_status)));
705 write_string (STDERR_FILENO, blurb());
706 write_string (STDERR_FILENO, ": ");
707 write_long (STDERR_FILENO, (long) screen_no);
708 write_string (STDERR_FILENO, ": child pid ");
709 write_long (STDERR_FILENO, (long) kid);
710 write_string (STDERR_FILENO, " (");
711 write_string (STDERR_FILENO, name);
712 write_string (STDERR_FILENO, ") stopped with signal ");
713 write_long (STDERR_FILENO, WSTOPSIG(wait_status));
714 write_string (STDERR_FILENO, ".\n");
718 job->status = job_stopped;
722 /* Don't call fprintf() from signal handlers, as it might malloc.
723 fprintf (stderr, "%s: child pid %lu (%s) died in a mysterious way!",
724 blurb(), (unsigned long) kid, name);
726 write_string (STDERR_FILENO, blurb());
727 write_string (STDERR_FILENO, ": ");
728 write_long (STDERR_FILENO, (long) screen_no);
729 write_string (STDERR_FILENO, ": child pid ");
730 write_long (STDERR_FILENO, (long) kid);
731 write_string (STDERR_FILENO, " (");
732 write_string (STDERR_FILENO, name);
733 write_string (STDERR_FILENO, ") died in a mysterious way!");
735 job->status = job_dead;
738 /* Clear out the pid so that screenhack_running_p() knows it's dead.
740 if (!job || job->status == job_dead)
741 for (i = 0; i < si->nscreens; i++)
743 saver_screen_info *ssi = &si->screens[i];
750 static void await_dying_children (saver_info *si) { return; }
759 # ifdef HAVE_SIGACTION /* Thanks to Tom Kelly <tom@ancilla.toronto.on.ca> */
761 static Bool sigchld_initialized_p = 0;
762 if (!sigchld_initialized_p)
764 struct sigaction action, old;
766 action.sa_handler = sigchld_handler;
767 sigemptyset(&action.sa_mask);
770 if (sigaction(SIGCHLD, &action, &old) < 0)
773 sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
776 sigchld_initialized_p = True;
779 # else /* !HAVE_SIGACTION */
781 if (((long) signal (SIGCHLD, sigchld_handler)) == -1L)
784 sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
787 # endif /* !HAVE_SIGACTION */
796 select_visual_of_hack (saver_screen_info *ssi, screenhack *hack)
798 saver_info *si = ssi->global;
799 saver_preferences *p = &si->prefs;
802 if (hack->visual && *hack->visual)
803 selected = select_visual(ssi, hack->visual);
805 selected = select_visual(ssi, 0);
807 if (!selected && (p->verbose_p || si->demoing_p))
810 ? "%s: warning, no \"%s\" visual for \"%s\".\n"
811 : "%s: no \"%s\" visual; skipping \"%s\".\n"),
813 (hack->visual && *hack->visual ? hack->visual : "???"),
821 print_path_error (const char *program)
824 char *cmd = strdup (program);
825 char *token = strchr (cmd, ' ');
827 if (token) *token = 0;
828 sprintf (buf, "%s: could not execute \"%.100s\"", blurb(), cmd);
832 if (errno == ENOENT &&
833 (token = getenv("PATH")))
837 # define PATH_MAX MAXPATHLEN
839 # define PATH_MAX 2048
843 fprintf (stderr, "\n");
845 # if defined(HAVE_GETCWD)
846 if (! getcwd (path, sizeof(path)))
848 # elif defined(HAVE_GETWD)
852 fprintf (stderr, " Current directory is: %s\n", path);
853 fprintf (stderr, " PATH is:\n");
854 token = strtok (strdup(token), ":");
857 fprintf (stderr, " %s\n", token);
858 token = strtok(0, ":");
860 fprintf (stderr, "\n");
865 /* Executes the command in another process.
866 Command may be any single command acceptable to /bin/sh.
867 It may include wildcards, but no semicolons.
868 If successful, the pid of the other process is returned.
869 Otherwise, -1 is returned and an error may have been
873 fork_and_exec (saver_screen_info *ssi, const char *command)
875 saver_info *si = ssi->global;
876 saver_preferences *p = &si->prefs;
879 switch ((int) (forked = fork ()))
884 sprintf (buf, "%s: couldn't fork", blurb());
890 close (ConnectionNumber (si->dpy)); /* close display fd */
891 limit_subproc_memory (p->inferior_memory_limit, p->verbose_p);
892 hack_subproc_environment (ssi->screen, ssi->screensaver_window);
895 fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n",
896 blurb(), ssi->number, command,
897 (unsigned long) getpid ());
899 exec_command (p->shell, command, p->nice_inferior);
901 /* If that returned, we were unable to exec the subprocess.
902 Print an error message, if desired.
904 if (! p->ignore_uninstalled_p)
905 print_path_error (command);
907 exit (1); /* exits child fork */
910 default: /* parent */
911 (void) make_job (forked, ssi->number, command);
920 spawn_screenhack (saver_screen_info *ssi)
922 saver_info *si = ssi->global;
923 saver_preferences *p = &si->prefs;
926 if (!monitor_powered_on_p (si))
928 if (si->prefs.verbose_p)
930 "%s: %d: X says monitor has powered down; "
931 "not launching a hack.\n", blurb(), ssi->number);
935 if (p->screenhacks_count)
946 if (p->screenhacks_count < 1)
948 /* No hacks at all */
951 else if (p->screenhacks_count == 1)
953 /* Exactly one hack in the list */
956 else if (si->selection_mode == -1)
958 /* Select the next hack, wrapping. */
959 new_hack = (ssi->current_hack + 1) % p->screenhacks_count;
961 else if (si->selection_mode == -2)
963 /* Select the previous hack, wrapping. */
964 if (ssi->current_hack < 0)
965 new_hack = p->screenhacks_count - 1;
967 new_hack = ((ssi->current_hack + p->screenhacks_count - 1)
968 % p->screenhacks_count);
970 else if (si->selection_mode > 0)
972 /* Select a specific hack, by number (via the ACTIVATE command.) */
973 new_hack = ((si->selection_mode - 1) % p->screenhacks_count);
976 else if (p->mode == ONE_HACK &&
977 p->selected_hack >= 0)
979 /* Select a specific hack, by number (via "One Saver" mode.) */
980 new_hack = p->selected_hack;
983 else if (p->mode == BLANK_ONLY || p->mode == DONT_BLANK)
987 else if (p->mode == RANDOM_HACKS_SAME &&
990 /* Use the same hack that's running on screen 0.
991 (Assumes this function was called on screen 0 first.)
993 new_hack = si->screens[0].current_hack;
995 else /* (p->mode == RANDOM_HACKS) */
997 /* Select a random hack (but not the one we just ran.) */
998 while ((new_hack = random () % p->screenhacks_count)
999 == ssi->current_hack)
1003 if (new_hack < 0) /* don't run a hack */
1005 ssi->current_hack = -1;
1006 if (si->selection_mode < 0)
1007 si->selection_mode = 0;
1011 ssi->current_hack = new_hack;
1012 hack = p->screenhacks[ssi->current_hack];
1014 /* If the hack is disabled, or there is no visual for this hack,
1015 then try again (move forward, or backward, or re-randomize.)
1016 Unless this hack was specified explicitly, in which case,
1020 select_visual_of_hack (ssi, hack);
1023 (!hack->enabled_p ||
1024 !on_path_p (hack->command) ||
1025 !select_visual_of_hack (ssi, hack)))
1027 if (++retry_count > (p->screenhacks_count*4))
1029 /* Uh, oops. Odds are, there are no suitable visuals,
1030 and we're looping. Give up. (This is totally lame,
1031 what we should do is make a list of suitable hacks at
1032 the beginning, then only loop over them.)
1036 "%s: %d: no programs enabled, or no suitable visuals.\n",
1037 blurb(), ssi->number);
1044 /* Turn off "next" and "prev" modes now, but "demo" mode is only
1045 turned off by explicit action.
1047 if (si->selection_mode < 0)
1048 si->selection_mode = 0;
1050 forked = fork_and_exec (ssi, hack->command);
1051 switch ((int) forked)
1053 case -1: /* fork failed */
1054 case 0: /* child fork (can't happen) */
1055 sprintf (buf, "%s: couldn't fork", blurb());
1057 restore_real_vroot (si);
1058 saver_exit (si, 1, "couldn't fork");
1067 store_saver_status (si); /* store current hack number */
1072 kill_screenhack (saver_screen_info *ssi)
1074 saver_info *si = ssi->global;
1076 kill_job (si, ssi->pid, SIGTERM);
1082 suspend_screenhack (saver_screen_info *ssi, Bool suspend_p)
1084 #ifdef SIGSTOP /* older VMS doesn't have it... */
1085 saver_info *si = ssi->global;
1087 kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT));
1088 #endif /* SIGSTOP */
1092 /* Called when we're exiting abnormally, to kill off the subproc. */
1094 emergency_kill_subproc (saver_info *si)
1098 signal (SIGCHLD, SIG_IGN);
1099 #endif /* SIGCHLD */
1101 for (i = 0; i < si->nscreens; i++)
1103 saver_screen_info *ssi = &si->screens[i];
1106 kill_job (si, ssi->pid, SIGTERM);
1113 screenhack_running_p (saver_info *si)
1115 Bool any_running_p = False;
1117 for (i = 0; i < si->nscreens; i++)
1119 saver_screen_info *ssi = &si->screens[i];
1120 if (ssi->pid) any_running_p = True;
1122 return any_running_p;
1126 /* Environment variables. */
1129 /* Modifies $PATH in the current environment, so that if DEFAULT_PATH_PREFIX
1130 is defined, the xscreensaver daemon will search that directory for hacks.
1133 hack_environment (saver_info *si)
1135 #if defined(HAVE_PUTENV) && defined(DEFAULT_PATH_PREFIX)
1136 static const char *def_path = DEFAULT_PATH_PREFIX;
1137 if (def_path && *def_path)
1139 const char *opath = getenv("PATH");
1141 if (! opath) opath = "/bin:/usr/bin"; /* WTF */
1142 npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20);
1143 strcpy (npath, "PATH=");
1144 strcat (npath, def_path);
1145 strcat (npath, ":");
1146 strcat (npath, opath);
1151 /* don't free (npath) -- some implementations of putenv (BSD 4.4,
1152 glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
1153 do not. So we must leak it (and/or the previous setting). Yay.
1156 #endif /* HAVE_PUTENV && DEFAULT_PATH_PREFIX */
1161 hack_subproc_environment (Screen *screen, Window saver_window)
1163 /* Store $DISPLAY into the environment, so that the $DISPLAY variable that
1164 the spawned processes inherit is correct. First, it must be on the same
1165 host and display as the value of -display passed in on our command line
1166 (which is not necessarily the same as what our $DISPLAY variable is.)
1167 Second, the screen number in the $DISPLAY passed to the subprocess should
1168 be the screen on which this particular hack is running -- not the display
1169 specification which the driver itself is using, since the driver ignores
1170 its screen number and manages all existing screens.
1172 Likewise, store a window ID in $XSCREENSAVER_WINDOW -- this will allow
1173 us to (eventually) run multiple hacks in Xinerama mode, where each hack
1174 has the same $DISPLAY but a different piece of glass.
1176 Display *dpy = DisplayOfScreen (screen);
1177 const char *odpy = DisplayString (dpy);
1178 char *ndpy = (char *) malloc (strlen(odpy) + 20);
1179 char *nssw = (char *) malloc (40);
1182 strcpy (ndpy, "DISPLAY=");
1183 s = ndpy + strlen(ndpy);
1186 /* We have to find the last colon since it is the boundary between
1187 hostname & screen - IPv6 numeric format addresses may have many
1188 colons before that point, and DECnet addresses always have two colons */
1189 c = strrchr(s,':'); /* skip to last colon */
1190 if (c != NULL) s = c+1;
1191 while (isdigit(*s)) s++; /* skip over dpy number */
1192 while (*s == '.') s++; /* skip over dot */
1193 if (s[-1] != '.') *s++ = '.'; /* put on a dot */
1194 sprintf(s, "%d", screen_number (screen)); /* put on screen number */
1196 sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX", (unsigned long) saver_window);
1198 /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
1199 any more, right? It's not Posix, but everyone seems to have it. */
1206 /* don't free ndpy/nssw -- some implementations of putenv (BSD 4.4,
1207 glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
1208 do not. So we must leak it (and/or the previous setting). Yay.
1210 #endif /* HAVE_PUTENV */
1217 get_best_gl_visual (saver_info *si, Screen *screen)
1223 int errin = -1, errout = -1;
1229 av[ac++] = "xscreensaver-gl-helper";
1234 perror ("error creating pipe:");
1241 if (!si->prefs.verbose_p)
1245 perror ("error creating pipe:");
1250 errout = errfds [1];
1253 block_sigchld(); /* This blocks it in the parent and child, to avoid
1254 racing. It is never unblocked in the child before
1255 the child exits, but that doesn't matter.
1258 switch ((int) (forked = fork ()))
1262 sprintf (buf, "%s: couldn't fork", blurb());
1264 saver_exit (si, 1, 0);
1268 close (in); /* don't need this one */
1269 close (ConnectionNumber (si->dpy)); /* close display fd */
1271 if (dup2 (out, STDOUT_FILENO) < 0) /* pipe stdout */
1273 perror ("could not dup() a new stdout:");
1277 if (! si->prefs.verbose_p)
1280 if (dup2 (errout, STDERR_FILENO) < 0)
1282 perror ("could not dup() a new stderr:");
1287 hack_subproc_environment (screen, 0); /* set $DISPLAY */
1289 execvp (av[0], av); /* shouldn't return. */
1291 if (errno != ENOENT /* || si->prefs.verbose_p */ )
1293 /* Ignore "no such file or directory" errors.
1294 Issue all other exec errors, though. */
1295 sprintf (buf, "%s: running %s", blurb(), av[0]);
1298 exit (1); /* exits fork */
1304 int wait_status = 0;
1307 FILE *f = fdopen (in, "r");
1308 unsigned long v = 0;
1311 close (out); /* don't need this one */
1314 if (! fgets (buf, sizeof(buf)-1, f))
1318 if (! si->prefs.verbose_p)
1324 /* Wait for the child to die - wait for this pid only, not others. */
1325 pid = waitpid (forked, &wait_status, 0);
1326 if (si->prefs.debug_p)
1328 write_string (STDERR_FILENO, blurb());
1329 write_string (STDERR_FILENO, ": waitpid(");
1330 write_long (STDERR_FILENO, (long) forked);
1331 write_string (STDERR_FILENO, ") ==> ");
1332 write_long (STDERR_FILENO, (long) pid);
1333 write_string (STDERR_FILENO, "\n");
1336 unblock_sigchld(); /* child is dead and waited, unblock now. */
1338 if (1 == sscanf (buf, "0x%lx %c", &v, &c))
1343 if (si->prefs.verbose_p)
1345 int L = strlen(buf);
1346 fprintf (stderr, "%s: %s did not report a GL visual!\n",
1349 if (L && buf[L-1] == '\n')
1352 fprintf (stderr, "%s: %s said: \"%s\"\n",
1353 blurb(), av[0], buf);
1359 Visual *v = id_to_visual (screen, result);
1360 if (si->prefs.verbose_p)
1361 fprintf (stderr, "%s: %d: %s: GL visual is 0x%X%s.\n",
1362 blurb(), screen_number (screen),
1364 (v == DefaultVisualOfScreen (screen)
1365 ? " (default)" : ""));
1376 /* Restarting the xscreensaver process from scratch. */
1378 static char **saved_argv;
1381 save_argv (int argc, char **argv)
1383 saved_argv = (char **) calloc (argc+2, sizeof (char *));
1384 saved_argv [argc] = 0;
1387 int i = strlen (argv [argc]) + 1;
1388 saved_argv [argc] = (char *) malloc (i);
1389 memcpy (saved_argv [argc], argv [argc], i);
1394 /* Re-execs the process with the arguments in saved_argv. Does not return.
1397 restart_process (saver_info *si)
1401 shutdown_stderr (si);
1402 if (si->prefs.verbose_p)
1405 fprintf (stderr, "%s: re-executing", blurb());
1406 for (i = 0; saved_argv[i]; i++)
1407 fprintf (stderr, " %s", saved_argv[i]);
1408 fprintf (stderr, "\n");
1410 describe_uids (si, stderr);
1411 fprintf (stderr, "\n");
1415 execvp (saved_argv [0], saved_argv); /* shouldn't return */
1418 sprintf (buf, "%s: could not restart process", blurb());