1 /* subprocs.c --- choosing, spawning, and killing screenhacks.
2 * xscreensaver, Copyright (c) 1991-2012 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 */
48 #if !defined(SIGCHLD) && defined(SIGCLD)
49 # define SIGCHLD SIGCLD
52 #if 0 /* putenv() is declared in stdlib.h on modern linux systems. */
54 extern int putenv (/* const char * */); /* getenv() is in stdlib.h... */
58 extern int kill (pid_t, int); /* signal() is in sys/signal.h... */
60 /* This file doesn't need the Xt headers, so stub these types out... */
62 #define XtAppContext void*
63 #define XrmDatabase void*
64 #define XtIntervalId void*
65 #define XtPointer void*
68 #include "xscreensaver.h"
71 #include "visual.h" /* for id_to_visual() */
73 extern saver_info *global_si_kludge; /* I hate C so much... */
76 /* Used when printing error/debugging messages from signal handlers.
79 no_malloc_number_to_string (long num)
81 static char string[128] = "";
83 Bool negative_p = False;
96 while ((num > 0) && (num_digits < sizeof(string) - 1))
99 digit = (int) num % 10;
101 string[sizeof(string) - 1 - num_digits] = digit + '0';
108 string[sizeof(string) - 1 - num_digits] = '-';
111 return string + sizeof(string) - 1 - num_digits;
114 /* Like write(), but runs strlen() on the arg to get the length. */
116 write_string (int fd, const char *str)
118 return write (fd, str, strlen (str));
122 write_long (int fd, long n)
124 const char *str = no_malloc_number_to_string (n);
125 return write_string (fd, str);
129 /* RLIMIT_AS (called RLIMIT_VMEM on some systems) controls the maximum size
130 of a process's address space, i.e., the maximal brk(2) and mmap(2) values.
131 Setting this lets you put a cap on how much memory a process can allocate.
133 Except the "and mmap()" part kinda makes this useless, since many GL
134 implementations end up using mmap() to pull the whole frame buffer into
135 memory (or something along those lines) making it appear processes are
136 using hundreds of megabytes when in fact they're using very little, and
137 we end up capping their mallocs prematurely. YAY!
139 #if defined(RLIMIT_VMEM) && !defined(RLIMIT_AS)
140 # define RLIMIT_AS RLIMIT_VMEM
144 limit_subproc_memory (int address_space_limit, Bool verbose_p)
147 /* This has caused way more problems than it has solved...
148 Let's just completely ignore the "memoryLimit" option now.
150 #undef HAVE_SETRLIMIT
152 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_AS)
155 if (address_space_limit < 10 * 1024) /* let's not be crazy */
158 if (getrlimit (RLIMIT_AS, &r) != 0)
161 sprintf (buf, "%s: getrlimit(RLIMIT_AS) failed", blurb());
166 r.rlim_cur = address_space_limit;
168 if (setrlimit (RLIMIT_AS, &r) != 0)
171 sprintf (buf, "%s: setrlimit(RLIMIT_AS, {%lu, %lu}) failed",
172 blurb(), r.rlim_cur, r.rlim_max);
179 int i = address_space_limit;
181 if (i >= (1<<30) && i == ((i >> 30) << 30))
182 sprintf(buf, "%dG", i >> 30);
183 else if (i >= (1<<20) && i == ((i >> 20) << 20))
184 sprintf(buf, "%dM", i >> 20);
185 else if (i >= (1<<10) && i == ((i >> 10) << 10))
186 sprintf(buf, "%dK", i >> 10);
188 sprintf(buf, "%d bytes", i);
190 fprintf (stderr, "%s: limited pid %lu address space to %s.\n",
191 blurb(), (unsigned long) getpid (), buf);
194 #endif /* HAVE_SETRLIMIT && RLIMIT_AS */
198 /* Management of child processes, and de-zombification.
202 job_running, /* the process is still alive */
203 job_stopped, /* we have sent it a STOP signal */
204 job_killed, /* we have sent it a TERM signal */
205 job_dead /* we have wait()ed for it, and it's dead -- this state only
206 occurs so that we can avoid calling free() from a signal
207 handler. Shortly after going into this state, the list
208 element will be removed. */
211 struct screenhack_job {
215 enum job_status status;
216 struct screenhack_job *next;
219 static struct screenhack_job *jobs = 0;
221 /* for debugging -- nothing calls this, but it's useful to invoke from gdb.
223 void show_job_list (void);
228 struct screenhack_job *job;
229 fprintf(stderr, "%s: job list:\n", blurb());
230 for (job = jobs; job; job = job->next)
231 fprintf (stderr, " %5ld: %2d: (%s) %s\n",
234 (job->status == job_running ? "running" :
235 job->status == job_stopped ? "stopped" :
236 job->status == job_killed ? " killed" :
237 job->status == job_dead ? " dead" : " ???"),
239 fprintf (stderr, "\n");
243 static void clean_job_list (void);
245 static struct screenhack_job *
246 make_job (pid_t pid, int screen, const char *cmd)
248 struct screenhack_job *job = (struct screenhack_job *) malloc (sizeof(*job));
250 static char name [1024];
251 const char *in = cmd;
259 while (isspace(*in)) in++; /* skip whitespace */
260 while (!isspace(*in) && *in != ':') {
261 if (*in == '=') got_eq = 1;
262 *out++ = *in++; /* snarf first token */
265 if (got_eq) /* if the first token was FOO=bar */
266 { /* then get the next token instead. */
273 while (isspace(*in)) in++; /* skip whitespace */
276 job->name = strdup(name);
278 job->screen = screen;
279 job->status = job_running;
288 free_job (struct screenhack_job *job)
292 else if (job == jobs)
296 struct screenhack_job *job2, *prev;
297 for (prev = 0, job2 = jobs;
299 prev = job2, job2 = job2->next)
302 prev->next = job->next;
311 /* Cleans out dead jobs from the jobs list -- this must only be called
312 from the main thread, not from a signal handler.
315 clean_job_list (void)
317 struct screenhack_job *job, *prev, *next;
318 for (prev = 0, job = jobs, next = (job ? job->next : 0);
320 prev = job, job = next, next = (job ? job->next : 0))
322 if (job->status == job_dead)
333 static struct screenhack_job *
336 struct screenhack_job *job;
337 for (job = jobs; job; job = job->next)
343 static void await_dying_children (saver_info *si);
345 static void describe_dead_child (saver_info *, pid_t, int wait_status);
349 /* Semaphore to temporarily turn the SIGCHLD handler into a no-op.
350 Don't alter this directly -- use block_sigchld() / unblock_sigchld().
352 static int block_sigchld_handler = 0;
355 #ifdef HAVE_SIGACTION
357 #else /* !HAVE_SIGACTION */
359 #endif /* !HAVE_SIGACTION */
362 #ifdef HAVE_SIGACTION
366 memset (&sa, 0, sizeof (sa));
367 sa.sa_handler = SIG_IGN;
368 sigaction (SIGPIPE, &sa, NULL);
370 sigemptyset (&child_set);
371 sigaddset (&child_set, SIGCHLD);
372 sigprocmask (SIG_BLOCK, &child_set, 0);
374 #else /* !HAVE_SIGACTION */
375 signal (SIGPIPE, SIG_IGN);
376 #endif /* !HAVE_SIGACTION */
378 block_sigchld_handler++;
380 #ifdef HAVE_SIGACTION
382 #else /* !HAVE_SIGACTION */
384 #endif /* !HAVE_SIGACTION */
388 unblock_sigchld (void)
390 #ifdef HAVE_SIGACTION
394 memset(&sa, 0, sizeof (sa));
395 sa.sa_handler = SIG_DFL;
396 sigaction(SIGPIPE, &sa, NULL);
398 sigemptyset(&child_set);
399 sigaddset(&child_set, SIGCHLD);
400 sigprocmask(SIG_UNBLOCK, &child_set, 0);
402 #else /* !HAVE_SIGACTION */
403 signal(SIGPIPE, SIG_DFL);
404 #endif /* !HAVE_SIGACTION */
406 block_sigchld_handler--;
410 kill_job (saver_info *si, pid_t pid, int signal)
412 saver_preferences *p = &si->prefs;
413 struct screenhack_job *job;
418 if (block_sigchld_handler)
419 /* This function should not be called from the signal handler. */
422 block_sigchld(); /* we control the horizontal... */
424 job = find_job (pid);
427 job->status == job_killed)
430 fprintf (stderr, "%s: no child %ld to signal!\n",
431 blurb(), (long) pid);
436 case SIGTERM: job->status = job_killed; break;
438 /* #### there must be a way to do this on VMS... */
439 case SIGSTOP: job->status = job_stopped; break;
440 case SIGCONT: job->status = job_running; break;
446 fprintf (stderr, "%s: %d: %s pid %lu (%s)\n",
447 blurb(), job->screen,
448 (job->status == job_killed ? "killing" :
449 job->status == job_stopped ? "suspending" : "resuming"),
450 (unsigned long) job->pid,
453 status = kill (job->pid, signal);
455 if (p->verbose_p && status < 0)
459 "%s: %d: child process %lu (%s) was already dead.\n",
460 blurb(), job->screen, (unsigned long) job->pid, job->name);
464 sprintf (buf, "%s: %d: couldn't kill child process %lu (%s)",
465 blurb(), job->screen, (unsigned long) job->pid, job->name);
470 await_dying_children (si);
474 if (block_sigchld_handler < 0)
484 sigchld_handler (int sig)
486 saver_info *si = global_si_kludge; /* I hate C so much... */
487 in_signal_handler_p++;
489 if (si->prefs.debug_p)
491 /* Don't call fprintf() from signal handlers, as it might malloc.
492 fprintf(stderr, "%s: got SIGCHLD%s\n", blurb(),
493 (block_sigchld_handler ? " (blocked)" : ""));
495 write_string (STDERR_FILENO, blurb());
496 write_string (STDERR_FILENO, ": got SIGCHLD");
498 if (block_sigchld_handler)
499 write_string (STDERR_FILENO, " (blocked)\n");
501 write_string (STDERR_FILENO, "\n");
504 if (block_sigchld_handler < 0)
506 else if (block_sigchld_handler == 0)
509 await_dying_children (si);
514 in_signal_handler_p--;
522 await_dying_children (saver_info *si)
530 kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED);
532 if (si->prefs.debug_p)
534 if (kid < 0 && errno)
536 /* Don't call fprintf() from signal handlers, as it might malloc.
537 fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", blurb(),
540 write_string (STDERR_FILENO, blurb());
541 write_string (STDERR_FILENO, ": waitpid(-1) ==> ");
542 write_long (STDERR_FILENO, (long) kid);
543 write_string (STDERR_FILENO, " (");
544 write_long (STDERR_FILENO, (long) errno);
545 write_string (STDERR_FILENO, ")\n");
549 /* Don't call fprintf() from signal handlers, as it might malloc.
550 fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", blurb(),
553 write_string (STDERR_FILENO, blurb());
554 write_string (STDERR_FILENO, ": waitpid(-1) ==> ");
555 write_long (STDERR_FILENO, (long) kid);
556 write_string (STDERR_FILENO, "\n");
560 /* 0 means no more children to reap.
561 -1 means error -- except "interrupted system call" isn't a "real"
562 error, so if we get that, we should just try again. */
564 (kid < 0 && errno != EINTR))
567 describe_dead_child (si, kid, wait_status);
573 describe_dead_child (saver_info *si, pid_t kid, int wait_status)
576 saver_preferences *p = &si->prefs;
577 struct screenhack_job *job = find_job (kid);
578 const char *name = job ? job->name : "<unknown>";
579 int screen_no = job ? job->screen : 0;
581 if (WIFEXITED (wait_status))
583 int exit_status = WEXITSTATUS (wait_status);
585 /* Treat exit code as a signed 8-bit quantity. */
586 if (exit_status & 0x80) exit_status |= ~0xFF;
588 /* One might assume that exiting with non-0 means something went wrong.
589 But that loser xswarm exits with the code that it was killed with, so
590 it *always* exits abnormally. Treat abnormal exits as "normal" (don't
591 mention them) if we've just killed the subprocess. But mention them
592 if they happen on their own.
596 (p->verbose_p || job->status != job_killed)))
598 /* Don't call fprintf() from signal handlers, as it might malloc.
600 "%s: %d: child pid %lu (%s) exited abnormally (code %d).\n",
601 blurb(), screen_no, (unsigned long) kid, name, exit_status);
603 write_string (STDERR_FILENO, blurb());
604 write_string (STDERR_FILENO, ": ");
605 write_long (STDERR_FILENO, (long) screen_no);
606 write_string (STDERR_FILENO, ": child pid ");
607 write_long (STDERR_FILENO, (long) kid);
608 write_string (STDERR_FILENO, " (");
609 write_string (STDERR_FILENO, name);
610 write_string (STDERR_FILENO, ") exited abnormally (code ");
611 write_long (STDERR_FILENO, (long) exit_status);
612 write_string (STDERR_FILENO, ").\n");
614 else if (p->verbose_p)
616 /* Don't call fprintf() from signal handlers, as it might malloc.
617 fprintf (stderr, "%s: %d: child pid %lu (%s) exited normally.\n",
618 blurb(), screen_no, (unsigned long) kid, name);
620 write_string (STDERR_FILENO, blurb());
621 write_string (STDERR_FILENO, ": ");
622 write_long (STDERR_FILENO, (long) screen_no);
623 write_string (STDERR_FILENO, ": child pid ");
624 write_long (STDERR_FILENO, (long) kid);
625 write_string (STDERR_FILENO, " (");
626 write_string (STDERR_FILENO, name);
627 write_string (STDERR_FILENO, ") exited normally.\n");
631 job->status = job_dead;
633 else if (WIFSIGNALED (wait_status))
637 job->status != job_killed ||
638 WTERMSIG (wait_status) != SIGTERM)
640 /* Don't call fprintf() from signal handlers, as it might malloc.
641 fprintf (stderr, "%s: %d: child pid %lu (%s) terminated with %s.\n",
642 blurb(), screen_no, (unsigned long) kid, name,
643 signal_name (WTERMSIG(wait_status)));
645 write_string (STDERR_FILENO, blurb());
646 write_string (STDERR_FILENO, ": ");
647 write_long (STDERR_FILENO, (long) screen_no);
648 write_string (STDERR_FILENO, ": child pid ");
649 write_long (STDERR_FILENO, (long) kid);
650 write_string (STDERR_FILENO, " (");
651 write_string (STDERR_FILENO, name);
652 write_string (STDERR_FILENO, ") terminated with signal ");
653 write_long (STDERR_FILENO, WTERMSIG(wait_status));
654 write_string (STDERR_FILENO, ".\n");
658 job->status = job_dead;
660 else if (WIFSTOPPED (wait_status))
664 /* Don't call fprintf() from signal handlers, as it might malloc.
665 fprintf (stderr, "%s: child pid %lu (%s) stopped with %s.\n",
666 blurb(), (unsigned long) kid, name,
667 signal_name (WSTOPSIG (wait_status)));
669 write_string (STDERR_FILENO, blurb());
670 write_string (STDERR_FILENO, ": ");
671 write_long (STDERR_FILENO, (long) screen_no);
672 write_string (STDERR_FILENO, ": child pid ");
673 write_long (STDERR_FILENO, (long) kid);
674 write_string (STDERR_FILENO, " (");
675 write_string (STDERR_FILENO, name);
676 write_string (STDERR_FILENO, ") stopped with signal ");
677 write_long (STDERR_FILENO, WSTOPSIG(wait_status));
678 write_string (STDERR_FILENO, ".\n");
682 job->status = job_stopped;
686 /* Don't call fprintf() from signal handlers, as it might malloc.
687 fprintf (stderr, "%s: child pid %lu (%s) died in a mysterious way!",
688 blurb(), (unsigned long) kid, name);
690 write_string (STDERR_FILENO, blurb());
691 write_string (STDERR_FILENO, ": ");
692 write_long (STDERR_FILENO, (long) screen_no);
693 write_string (STDERR_FILENO, ": child pid ");
694 write_long (STDERR_FILENO, (long) kid);
695 write_string (STDERR_FILENO, " (");
696 write_string (STDERR_FILENO, name);
697 write_string (STDERR_FILENO, ") died in a mysterious way!");
699 job->status = job_dead;
702 /* Clear out the pid so that screenhack_running_p() knows it's dead.
704 if (!job || job->status == job_dead)
705 for (i = 0; i < si->nscreens; i++)
707 saver_screen_info *ssi = &si->screens[i];
714 static void await_dying_children (saver_info *si) { return; }
723 # ifdef HAVE_SIGACTION /* Thanks to Tom Kelly <tom@ancilla.toronto.on.ca> */
725 static Bool sigchld_initialized_p = 0;
726 if (!sigchld_initialized_p)
728 struct sigaction action, old;
730 action.sa_handler = sigchld_handler;
731 sigemptyset(&action.sa_mask);
734 if (sigaction(SIGCHLD, &action, &old) < 0)
737 sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
740 sigchld_initialized_p = True;
743 # else /* !HAVE_SIGACTION */
745 if (((long) signal (SIGCHLD, sigchld_handler)) == -1L)
748 sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
751 # endif /* !HAVE_SIGACTION */
760 select_visual_of_hack (saver_screen_info *ssi, screenhack *hack)
762 saver_info *si = ssi->global;
763 saver_preferences *p = &si->prefs;
766 if (hack->visual && *hack->visual)
767 selected = select_visual(ssi, hack->visual);
769 selected = select_visual(ssi, 0);
771 if (!selected && (p->verbose_p || si->demoing_p))
774 ? "%s: warning, no \"%s\" visual for \"%s\".\n"
775 : "%s: no \"%s\" visual; skipping \"%s\".\n"),
777 (hack->visual && *hack->visual ? hack->visual : "???"),
785 print_path_error (const char *program)
788 char *cmd = strdup (program);
789 char *token = strchr (cmd, ' ');
791 if (token) *token = 0;
792 sprintf (buf, "%s: could not execute \"%.100s\"", blurb(), cmd);
796 if (errno == ENOENT &&
797 (token = getenv("PATH")))
801 # define PATH_MAX MAXPATHLEN
803 # define PATH_MAX 2048
807 fprintf (stderr, "\n");
809 # if defined(HAVE_GETCWD)
810 if (! getcwd (path, sizeof(path)))
812 # elif defined(HAVE_GETWD)
816 fprintf (stderr, " Current directory is: %s\n", path);
817 fprintf (stderr, " PATH is:\n");
818 token = strtok (strdup(token), ":");
821 fprintf (stderr, " %s\n", token);
822 token = strtok(0, ":");
824 fprintf (stderr, "\n");
829 /* Executes the command in another process.
830 Command may be any single command acceptable to /bin/sh.
831 It may include wildcards, but no semicolons.
832 If successful, the pid of the other process is returned.
833 Otherwise, -1 is returned and an error may have been
837 fork_and_exec (saver_screen_info *ssi, const char *command)
839 saver_info *si = ssi->global;
840 saver_preferences *p = &si->prefs;
843 switch ((int) (forked = fork ()))
848 sprintf (buf, "%s: couldn't fork", blurb());
854 close (ConnectionNumber (si->dpy)); /* close display fd */
855 limit_subproc_memory (p->inferior_memory_limit, p->verbose_p);
856 hack_subproc_environment (ssi->screen, ssi->screensaver_window);
859 fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n",
860 blurb(), ssi->number, command,
861 (unsigned long) getpid ());
863 exec_command (p->shell, command, p->nice_inferior);
865 /* If that returned, we were unable to exec the subprocess.
866 Print an error message, if desired.
868 if (! p->ignore_uninstalled_p)
869 print_path_error (command);
871 exit (1); /* exits child fork */
874 default: /* parent */
875 (void) make_job (forked, ssi->number, command);
884 spawn_screenhack (saver_screen_info *ssi)
886 saver_info *si = ssi->global;
887 saver_preferences *p = &si->prefs;
890 if (!monitor_powered_on_p (si))
892 if (si->prefs.verbose_p)
894 "%s: %d: X says monitor has powered down; "
895 "not launching a hack.\n", blurb(), ssi->number);
899 if (p->screenhacks_count)
910 if (p->screenhacks_count < 1)
912 /* No hacks at all */
915 else if (p->screenhacks_count == 1)
917 /* Exactly one hack in the list */
920 else if (si->selection_mode == -1)
922 /* Select the next hack, wrapping. */
923 new_hack = (ssi->current_hack + 1) % p->screenhacks_count;
925 else if (si->selection_mode == -2)
927 /* Select the previous hack, wrapping. */
928 if (ssi->current_hack < 0)
929 new_hack = p->screenhacks_count - 1;
931 new_hack = ((ssi->current_hack + p->screenhacks_count - 1)
932 % p->screenhacks_count);
934 else if (si->selection_mode > 0)
936 /* Select a specific hack, by number (via the ACTIVATE command.) */
937 new_hack = ((si->selection_mode - 1) % p->screenhacks_count);
940 else if (p->mode == ONE_HACK &&
941 p->selected_hack >= 0)
943 /* Select a specific hack, by number (via "One Saver" mode.) */
944 new_hack = p->selected_hack;
947 else if (p->mode == BLANK_ONLY || p->mode == DONT_BLANK)
951 else if (p->mode == RANDOM_HACKS_SAME &&
954 /* Use the same hack that's running on screen 0.
955 (Assumes this function was called on screen 0 first.)
957 new_hack = si->screens[0].current_hack;
959 else /* (p->mode == RANDOM_HACKS) */
961 /* Select a random hack (but not the one we just ran.) */
962 while ((new_hack = random () % p->screenhacks_count)
963 == ssi->current_hack)
967 if (new_hack < 0) /* don't run a hack */
969 ssi->current_hack = -1;
970 if (si->selection_mode < 0)
971 si->selection_mode = 0;
975 ssi->current_hack = new_hack;
976 hack = p->screenhacks[ssi->current_hack];
978 /* If the hack is disabled, or there is no visual for this hack,
979 then try again (move forward, or backward, or re-randomize.)
980 Unless this hack was specified explicitly, in which case,
984 select_visual_of_hack (ssi, hack);
988 !on_path_p (hack->command) ||
989 !select_visual_of_hack (ssi, hack)))
991 if (++retry_count > (p->screenhacks_count*4))
993 /* Uh, oops. Odds are, there are no suitable visuals,
994 and we're looping. Give up. (This is totally lame,
995 what we should do is make a list of suitable hacks at
996 the beginning, then only loop over them.)
1000 "%s: %d: no programs enabled, or no suitable visuals.\n",
1001 blurb(), ssi->number);
1008 /* Turn off "next" and "prev" modes now, but "demo" mode is only
1009 turned off by explicit action.
1011 if (si->selection_mode < 0)
1012 si->selection_mode = 0;
1014 forked = fork_and_exec (ssi, hack->command);
1015 switch ((int) forked)
1017 case -1: /* fork failed */
1018 case 0: /* child fork (can't happen) */
1019 sprintf (buf, "%s: couldn't fork", blurb());
1021 restore_real_vroot (si);
1022 saver_exit (si, 1, "couldn't fork");
1031 store_saver_status (si); /* store current hack number */
1036 kill_screenhack (saver_screen_info *ssi)
1038 saver_info *si = ssi->global;
1040 kill_job (si, ssi->pid, SIGTERM);
1046 suspend_screenhack (saver_screen_info *ssi, Bool suspend_p)
1048 #ifdef SIGSTOP /* older VMS doesn't have it... */
1049 saver_info *si = ssi->global;
1051 kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT));
1052 #endif /* SIGSTOP */
1056 /* Called when we're exiting abnormally, to kill off the subproc. */
1058 emergency_kill_subproc (saver_info *si)
1062 signal (SIGCHLD, SIG_IGN);
1063 #endif /* SIGCHLD */
1065 for (i = 0; i < si->nscreens; i++)
1067 saver_screen_info *ssi = &si->screens[i];
1070 kill_job (si, ssi->pid, SIGTERM);
1077 screenhack_running_p (saver_info *si)
1079 Bool any_running_p = False;
1081 for (i = 0; i < si->nscreens; i++)
1083 saver_screen_info *ssi = &si->screens[i];
1084 if (ssi->pid) any_running_p = True;
1086 return any_running_p;
1090 /* Environment variables. */
1093 /* Modifies $PATH in the current environment, so that if DEFAULT_PATH_PREFIX
1094 is defined, the xscreensaver daemon will search that directory for hacks.
1097 hack_environment (saver_info *si)
1099 #if defined(HAVE_PUTENV) && defined(DEFAULT_PATH_PREFIX)
1100 static const char *def_path = DEFAULT_PATH_PREFIX;
1101 if (def_path && *def_path)
1103 const char *opath = getenv("PATH");
1104 char *npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20);
1105 strcpy (npath, "PATH=");
1106 strcat (npath, def_path);
1107 strcat (npath, ":");
1108 strcat (npath, opath);
1113 /* don't free (npath) -- some implementations of putenv (BSD 4.4,
1114 glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
1115 do not. So we must leak it (and/or the previous setting). Yay.
1118 #endif /* HAVE_PUTENV && DEFAULT_PATH_PREFIX */
1123 hack_subproc_environment (Screen *screen, Window saver_window)
1125 /* Store $DISPLAY into the environment, so that the $DISPLAY variable that
1126 the spawned processes inherit is correct. First, it must be on the same
1127 host and display as the value of -display passed in on our command line
1128 (which is not necessarily the same as what our $DISPLAY variable is.)
1129 Second, the screen number in the $DISPLAY passed to the subprocess should
1130 be the screen on which this particular hack is running -- not the display
1131 specification which the driver itself is using, since the driver ignores
1132 its screen number and manages all existing screens.
1134 Likewise, store a window ID in $XSCREENSAVER_WINDOW -- this will allow
1135 us to (eventually) run multiple hacks in Xinerama mode, where each hack
1136 has the same $DISPLAY but a different piece of glass.
1138 Display *dpy = DisplayOfScreen (screen);
1139 const char *odpy = DisplayString (dpy);
1140 char *ndpy = (char *) malloc (strlen(odpy) + 20);
1141 char *nssw = (char *) malloc (40);
1144 strcpy (ndpy, "DISPLAY=");
1145 s = ndpy + strlen(ndpy);
1148 /* We have to find the last colon since it is the boundary between
1149 hostname & screen - IPv6 numeric format addresses may have many
1150 colons before that point, and DECnet addresses always have two colons */
1151 c = strrchr(s,':'); /* skip to last colon */
1152 if (c != NULL) s = c+1;
1153 while (isdigit(*s)) s++; /* skip over dpy number */
1154 while (*s == '.') s++; /* skip over dot */
1155 if (s[-1] != '.') *s++ = '.'; /* put on a dot */
1156 sprintf(s, "%d", screen_number (screen)); /* put on screen number */
1158 sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX", (unsigned long) saver_window);
1160 /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
1161 any more, right? It's not Posix, but everyone seems to have it. */
1168 /* don't free ndpy/nssw -- some implementations of putenv (BSD 4.4,
1169 glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
1170 do not. So we must leak it (and/or the previous setting). Yay.
1172 #endif /* HAVE_PUTENV */
1179 get_best_gl_visual (saver_info *si, Screen *screen)
1185 int errin = -1, errout = -1;
1191 av[ac++] = "xscreensaver-gl-helper";
1196 perror ("error creating pipe:");
1203 if (!si->prefs.verbose_p)
1207 perror ("error creating pipe:");
1212 errout = errfds [1];
1215 block_sigchld(); /* This blocks it in the parent and child, to avoid
1216 racing. It is never unblocked in the child before
1217 the child exits, but that doesn't matter.
1220 switch ((int) (forked = fork ()))
1224 sprintf (buf, "%s: couldn't fork", blurb());
1226 saver_exit (si, 1, 0);
1230 close (in); /* don't need this one */
1231 close (ConnectionNumber (si->dpy)); /* close display fd */
1233 if (dup2 (out, STDOUT_FILENO) < 0) /* pipe stdout */
1235 perror ("could not dup() a new stdout:");
1239 if (! si->prefs.verbose_p)
1242 if (dup2 (errout, STDERR_FILENO) < 0)
1244 perror ("could not dup() a new stderr:");
1249 hack_subproc_environment (screen, 0); /* set $DISPLAY */
1251 execvp (av[0], av); /* shouldn't return. */
1253 if (errno != ENOENT /* || si->prefs.verbose_p */ )
1255 /* Ignore "no such file or directory" errors.
1256 Issue all other exec errors, though. */
1257 sprintf (buf, "%s: running %s", blurb(), av[0]);
1260 exit (1); /* exits fork */
1266 int wait_status = 0;
1268 FILE *f = fdopen (in, "r");
1269 unsigned long v = 0;
1272 close (out); /* don't need this one */
1275 if (! fgets (buf, sizeof(buf)-1, f))
1279 if (! si->prefs.verbose_p)
1285 /* Wait for the child to die. */
1286 waitpid (-1, &wait_status, 0);
1288 unblock_sigchld(); /* child is dead and waited, unblock now. */
1290 if (1 == sscanf (buf, "0x%lx %c", &v, &c))
1295 if (si->prefs.verbose_p)
1297 int L = strlen(buf);
1298 fprintf (stderr, "%s: %s did not report a GL visual!\n",
1301 if (L && buf[L-1] == '\n')
1304 fprintf (stderr, "%s: %s said: \"%s\"\n",
1305 blurb(), av[0], buf);
1311 Visual *v = id_to_visual (screen, result);
1312 if (si->prefs.verbose_p)
1313 fprintf (stderr, "%s: %d: %s: GL visual is 0x%X%s.\n",
1314 blurb(), screen_number (screen),
1316 (v == DefaultVisualOfScreen (screen)
1317 ? " (default)" : ""));
1328 /* Restarting the xscreensaver process from scratch. */
1330 static char **saved_argv;
1333 save_argv (int argc, char **argv)
1335 saved_argv = (char **) calloc (argc+2, sizeof (char *));
1336 saved_argv [argc] = 0;
1339 int i = strlen (argv [argc]) + 1;
1340 saved_argv [argc] = (char *) malloc (i);
1341 memcpy (saved_argv [argc], argv [argc], i);
1346 /* Re-execs the process with the arguments in saved_argv. Does not return.
1349 restart_process (saver_info *si)
1353 shutdown_stderr (si);
1354 if (si->prefs.verbose_p)
1357 fprintf (stderr, "%s: re-executing", blurb());
1358 for (i = 0; saved_argv[i]; i++)
1359 fprintf (stderr, " %s", saved_argv[i]);
1360 fprintf (stderr, "\n");
1362 describe_uids (si, stderr);
1363 fprintf (stderr, "\n");
1367 execvp (saved_argv [0], saved_argv); /* shouldn't return */
1370 sprintf (buf, "%s: could not restart process", blurb());