1 /* subprocs.c --- choosing, spawning, and killing screenhacks.
2 * xscreensaver, Copyright (c) 1991-2015 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 if (block_sigchld_handler <= 0)
393 if (block_sigchld_handler <= 1) /* only unblock if count going to 0 */
395 #ifdef HAVE_SIGACTION
399 memset(&sa, 0, sizeof (sa));
400 sa.sa_handler = SIG_DFL;
401 sigaction(SIGPIPE, &sa, NULL);
403 sigemptyset(&child_set);
404 sigaddset(&child_set, SIGCHLD);
405 sigprocmask(SIG_UNBLOCK, &child_set, 0);
407 #else /* !HAVE_SIGACTION */
408 signal(SIGPIPE, SIG_DFL);
409 #endif /* !HAVE_SIGACTION */
412 block_sigchld_handler--;
416 kill_job (saver_info *si, pid_t pid, int signal)
418 saver_preferences *p = &si->prefs;
419 struct screenhack_job *job;
424 if (in_signal_handler_p)
425 /* This function should not be called from the signal handler. */
428 block_sigchld(); /* we control the horizontal... */
430 job = find_job (pid);
433 job->status == job_killed)
436 fprintf (stderr, "%s: no child %ld to signal!\n",
437 blurb(), (long) pid);
442 case SIGTERM: job->status = job_killed; break;
444 /* #### there must be a way to do this on VMS... */
445 case SIGSTOP: job->status = job_stopped; break;
446 case SIGCONT: job->status = job_running; break;
452 fprintf (stderr, "%s: %d: %s pid %lu (%s)\n",
453 blurb(), job->screen,
454 (job->status == job_killed ? "killing" :
455 job->status == job_stopped ? "suspending" : "resuming"),
456 (unsigned long) job->pid,
459 status = kill (job->pid, signal);
461 if (p->verbose_p && status < 0)
465 "%s: %d: child process %lu (%s) was already dead.\n",
466 blurb(), job->screen, (unsigned long) job->pid, job->name);
470 sprintf (buf, "%s: %d: couldn't kill child process %lu (%s)",
471 blurb(), job->screen, (unsigned long) job->pid, job->name);
476 await_dying_children (si);
480 if (block_sigchld_handler < 0)
490 sigchld_handler (int sig)
492 saver_info *si = global_si_kludge; /* I hate C so much... */
493 in_signal_handler_p++;
495 if (si->prefs.debug_p)
497 /* Don't call fprintf() from signal handlers, as it might malloc.
498 fprintf(stderr, "%s: got SIGCHLD%s\n", blurb(),
499 (block_sigchld_handler ? " (blocked)" : ""));
501 write_string (STDERR_FILENO, blurb());
502 write_string (STDERR_FILENO, ": got SIGCHLD");
504 if (block_sigchld_handler)
505 write_string (STDERR_FILENO, " (blocked)\n");
507 write_string (STDERR_FILENO, "\n");
510 if (block_sigchld_handler < 0)
512 else if (block_sigchld_handler == 0)
515 await_dying_children (si);
520 in_signal_handler_p--;
528 await_dying_children (saver_info *si)
536 kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED);
538 if (si->prefs.debug_p)
540 if (kid < 0 && errno)
542 /* Don't call fprintf() from signal handlers, as it might malloc.
543 fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", blurb(),
546 write_string (STDERR_FILENO, blurb());
547 write_string (STDERR_FILENO, ": waitpid(-1) ==> ");
548 write_long (STDERR_FILENO, (long) kid);
549 write_string (STDERR_FILENO, " (");
550 write_long (STDERR_FILENO, (long) errno);
551 write_string (STDERR_FILENO, ")\n");
555 /* Don't call fprintf() from signal handlers, as it might malloc.
556 fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", blurb(),
559 write_string (STDERR_FILENO, blurb());
560 write_string (STDERR_FILENO, ": waitpid(-1) ==> ");
561 write_long (STDERR_FILENO, (long) kid);
562 write_string (STDERR_FILENO, "\n");
566 /* 0 means no more children to reap.
567 -1 means error -- except "interrupted system call" isn't a "real"
568 error, so if we get that, we should just try again. */
570 (kid < 0 && errno != EINTR))
573 describe_dead_child (si, kid, wait_status);
579 describe_dead_child (saver_info *si, pid_t kid, int wait_status)
582 saver_preferences *p = &si->prefs;
583 struct screenhack_job *job = find_job (kid);
584 const char *name = job ? job->name : "<unknown>";
585 int screen_no = job ? job->screen : 0;
587 if (WIFEXITED (wait_status))
589 int exit_status = WEXITSTATUS (wait_status);
591 /* Treat exit code as a signed 8-bit quantity. */
592 if (exit_status & 0x80) exit_status |= ~0xFF;
594 /* One might assume that exiting with non-0 means something went wrong.
595 But that loser xswarm exits with the code that it was killed with, so
596 it *always* exits abnormally. Treat abnormal exits as "normal" (don't
597 mention them) if we've just killed the subprocess. But mention them
598 if they happen on their own.
602 (p->verbose_p || job->status != job_killed)))
604 /* Don't call fprintf() from signal handlers, as it might malloc.
606 "%s: %d: child pid %lu (%s) exited abnormally (code %d).\n",
607 blurb(), screen_no, (unsigned long) kid, name, exit_status);
609 write_string (STDERR_FILENO, blurb());
610 write_string (STDERR_FILENO, ": ");
611 write_long (STDERR_FILENO, (long) screen_no);
612 write_string (STDERR_FILENO, ": child pid ");
613 write_long (STDERR_FILENO, (long) kid);
614 write_string (STDERR_FILENO, " (");
615 write_string (STDERR_FILENO, name);
616 write_string (STDERR_FILENO, ") exited abnormally (code ");
617 write_long (STDERR_FILENO, (long) exit_status);
618 write_string (STDERR_FILENO, ").\n");
620 else if (p->verbose_p)
622 /* Don't call fprintf() from signal handlers, as it might malloc.
623 fprintf (stderr, "%s: %d: child pid %lu (%s) exited normally.\n",
624 blurb(), screen_no, (unsigned long) kid, name);
626 write_string (STDERR_FILENO, blurb());
627 write_string (STDERR_FILENO, ": ");
628 write_long (STDERR_FILENO, (long) screen_no);
629 write_string (STDERR_FILENO, ": child pid ");
630 write_long (STDERR_FILENO, (long) kid);
631 write_string (STDERR_FILENO, " (");
632 write_string (STDERR_FILENO, name);
633 write_string (STDERR_FILENO, ") exited normally.\n");
637 job->status = job_dead;
639 else if (WIFSIGNALED (wait_status))
643 job->status != job_killed ||
644 WTERMSIG (wait_status) != SIGTERM)
646 /* Don't call fprintf() from signal handlers, as it might malloc.
647 fprintf (stderr, "%s: %d: child pid %lu (%s) terminated with %s.\n",
648 blurb(), screen_no, (unsigned long) kid, name,
649 signal_name (WTERMSIG(wait_status)));
651 write_string (STDERR_FILENO, blurb());
652 write_string (STDERR_FILENO, ": ");
653 write_long (STDERR_FILENO, (long) screen_no);
654 write_string (STDERR_FILENO, ": child pid ");
655 write_long (STDERR_FILENO, (long) kid);
656 write_string (STDERR_FILENO, " (");
657 write_string (STDERR_FILENO, name);
658 write_string (STDERR_FILENO, ") terminated with signal ");
659 write_long (STDERR_FILENO, WTERMSIG(wait_status));
660 write_string (STDERR_FILENO, ".\n");
664 job->status = job_dead;
666 else if (WIFSTOPPED (wait_status))
670 /* Don't call fprintf() from signal handlers, as it might malloc.
671 fprintf (stderr, "%s: child pid %lu (%s) stopped with %s.\n",
672 blurb(), (unsigned long) kid, name,
673 signal_name (WSTOPSIG (wait_status)));
675 write_string (STDERR_FILENO, blurb());
676 write_string (STDERR_FILENO, ": ");
677 write_long (STDERR_FILENO, (long) screen_no);
678 write_string (STDERR_FILENO, ": child pid ");
679 write_long (STDERR_FILENO, (long) kid);
680 write_string (STDERR_FILENO, " (");
681 write_string (STDERR_FILENO, name);
682 write_string (STDERR_FILENO, ") stopped with signal ");
683 write_long (STDERR_FILENO, WSTOPSIG(wait_status));
684 write_string (STDERR_FILENO, ".\n");
688 job->status = job_stopped;
692 /* Don't call fprintf() from signal handlers, as it might malloc.
693 fprintf (stderr, "%s: child pid %lu (%s) died in a mysterious way!",
694 blurb(), (unsigned long) kid, name);
696 write_string (STDERR_FILENO, blurb());
697 write_string (STDERR_FILENO, ": ");
698 write_long (STDERR_FILENO, (long) screen_no);
699 write_string (STDERR_FILENO, ": child pid ");
700 write_long (STDERR_FILENO, (long) kid);
701 write_string (STDERR_FILENO, " (");
702 write_string (STDERR_FILENO, name);
703 write_string (STDERR_FILENO, ") died in a mysterious way!");
705 job->status = job_dead;
708 /* Clear out the pid so that screenhack_running_p() knows it's dead.
710 if (!job || job->status == job_dead)
711 for (i = 0; i < si->nscreens; i++)
713 saver_screen_info *ssi = &si->screens[i];
720 static void await_dying_children (saver_info *si) { return; }
729 # ifdef HAVE_SIGACTION /* Thanks to Tom Kelly <tom@ancilla.toronto.on.ca> */
731 static Bool sigchld_initialized_p = 0;
732 if (!sigchld_initialized_p)
734 struct sigaction action, old;
736 action.sa_handler = sigchld_handler;
737 sigemptyset(&action.sa_mask);
740 if (sigaction(SIGCHLD, &action, &old) < 0)
743 sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
746 sigchld_initialized_p = True;
749 # else /* !HAVE_SIGACTION */
751 if (((long) signal (SIGCHLD, sigchld_handler)) == -1L)
754 sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
757 # endif /* !HAVE_SIGACTION */
766 select_visual_of_hack (saver_screen_info *ssi, screenhack *hack)
768 saver_info *si = ssi->global;
769 saver_preferences *p = &si->prefs;
772 if (hack->visual && *hack->visual)
773 selected = select_visual(ssi, hack->visual);
775 selected = select_visual(ssi, 0);
777 if (!selected && (p->verbose_p || si->demoing_p))
780 ? "%s: warning, no \"%s\" visual for \"%s\".\n"
781 : "%s: no \"%s\" visual; skipping \"%s\".\n"),
783 (hack->visual && *hack->visual ? hack->visual : "???"),
791 print_path_error (const char *program)
794 char *cmd = strdup (program);
795 char *token = strchr (cmd, ' ');
797 if (token) *token = 0;
798 sprintf (buf, "%s: could not execute \"%.100s\"", blurb(), cmd);
802 if (errno == ENOENT &&
803 (token = getenv("PATH")))
807 # define PATH_MAX MAXPATHLEN
809 # define PATH_MAX 2048
813 fprintf (stderr, "\n");
815 # if defined(HAVE_GETCWD)
816 if (! getcwd (path, sizeof(path)))
818 # elif defined(HAVE_GETWD)
822 fprintf (stderr, " Current directory is: %s\n", path);
823 fprintf (stderr, " PATH is:\n");
824 token = strtok (strdup(token), ":");
827 fprintf (stderr, " %s\n", token);
828 token = strtok(0, ":");
830 fprintf (stderr, "\n");
835 /* Executes the command in another process.
836 Command may be any single command acceptable to /bin/sh.
837 It may include wildcards, but no semicolons.
838 If successful, the pid of the other process is returned.
839 Otherwise, -1 is returned and an error may have been
843 fork_and_exec (saver_screen_info *ssi, const char *command)
845 saver_info *si = ssi->global;
846 saver_preferences *p = &si->prefs;
849 switch ((int) (forked = fork ()))
854 sprintf (buf, "%s: couldn't fork", blurb());
860 close (ConnectionNumber (si->dpy)); /* close display fd */
861 limit_subproc_memory (p->inferior_memory_limit, p->verbose_p);
862 hack_subproc_environment (ssi->screen, ssi->screensaver_window);
865 fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n",
866 blurb(), ssi->number, command,
867 (unsigned long) getpid ());
869 exec_command (p->shell, command, p->nice_inferior);
871 /* If that returned, we were unable to exec the subprocess.
872 Print an error message, if desired.
874 if (! p->ignore_uninstalled_p)
875 print_path_error (command);
877 exit (1); /* exits child fork */
880 default: /* parent */
881 (void) make_job (forked, ssi->number, command);
890 spawn_screenhack (saver_screen_info *ssi)
892 saver_info *si = ssi->global;
893 saver_preferences *p = &si->prefs;
896 if (!monitor_powered_on_p (si))
898 if (si->prefs.verbose_p)
900 "%s: %d: X says monitor has powered down; "
901 "not launching a hack.\n", blurb(), ssi->number);
905 if (p->screenhacks_count)
916 if (p->screenhacks_count < 1)
918 /* No hacks at all */
921 else if (p->screenhacks_count == 1)
923 /* Exactly one hack in the list */
926 else if (si->selection_mode == -1)
928 /* Select the next hack, wrapping. */
929 new_hack = (ssi->current_hack + 1) % p->screenhacks_count;
931 else if (si->selection_mode == -2)
933 /* Select the previous hack, wrapping. */
934 if (ssi->current_hack < 0)
935 new_hack = p->screenhacks_count - 1;
937 new_hack = ((ssi->current_hack + p->screenhacks_count - 1)
938 % p->screenhacks_count);
940 else if (si->selection_mode > 0)
942 /* Select a specific hack, by number (via the ACTIVATE command.) */
943 new_hack = ((si->selection_mode - 1) % p->screenhacks_count);
946 else if (p->mode == ONE_HACK &&
947 p->selected_hack >= 0)
949 /* Select a specific hack, by number (via "One Saver" mode.) */
950 new_hack = p->selected_hack;
953 else if (p->mode == BLANK_ONLY || p->mode == DONT_BLANK)
957 else if (p->mode == RANDOM_HACKS_SAME &&
960 /* Use the same hack that's running on screen 0.
961 (Assumes this function was called on screen 0 first.)
963 new_hack = si->screens[0].current_hack;
965 else /* (p->mode == RANDOM_HACKS) */
967 /* Select a random hack (but not the one we just ran.) */
968 while ((new_hack = random () % p->screenhacks_count)
969 == ssi->current_hack)
973 if (new_hack < 0) /* don't run a hack */
975 ssi->current_hack = -1;
976 if (si->selection_mode < 0)
977 si->selection_mode = 0;
981 ssi->current_hack = new_hack;
982 hack = p->screenhacks[ssi->current_hack];
984 /* If the hack is disabled, or there is no visual for this hack,
985 then try again (move forward, or backward, or re-randomize.)
986 Unless this hack was specified explicitly, in which case,
990 select_visual_of_hack (ssi, hack);
994 !on_path_p (hack->command) ||
995 !select_visual_of_hack (ssi, hack)))
997 if (++retry_count > (p->screenhacks_count*4))
999 /* Uh, oops. Odds are, there are no suitable visuals,
1000 and we're looping. Give up. (This is totally lame,
1001 what we should do is make a list of suitable hacks at
1002 the beginning, then only loop over them.)
1006 "%s: %d: no programs enabled, or no suitable visuals.\n",
1007 blurb(), ssi->number);
1014 /* Turn off "next" and "prev" modes now, but "demo" mode is only
1015 turned off by explicit action.
1017 if (si->selection_mode < 0)
1018 si->selection_mode = 0;
1020 forked = fork_and_exec (ssi, hack->command);
1021 switch ((int) forked)
1023 case -1: /* fork failed */
1024 case 0: /* child fork (can't happen) */
1025 sprintf (buf, "%s: couldn't fork", blurb());
1027 restore_real_vroot (si);
1028 saver_exit (si, 1, "couldn't fork");
1037 store_saver_status (si); /* store current hack number */
1042 kill_screenhack (saver_screen_info *ssi)
1044 saver_info *si = ssi->global;
1046 kill_job (si, ssi->pid, SIGTERM);
1052 suspend_screenhack (saver_screen_info *ssi, Bool suspend_p)
1054 #ifdef SIGSTOP /* older VMS doesn't have it... */
1055 saver_info *si = ssi->global;
1057 kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT));
1058 #endif /* SIGSTOP */
1062 /* Called when we're exiting abnormally, to kill off the subproc. */
1064 emergency_kill_subproc (saver_info *si)
1068 signal (SIGCHLD, SIG_IGN);
1069 #endif /* SIGCHLD */
1071 for (i = 0; i < si->nscreens; i++)
1073 saver_screen_info *ssi = &si->screens[i];
1076 kill_job (si, ssi->pid, SIGTERM);
1083 screenhack_running_p (saver_info *si)
1085 Bool any_running_p = False;
1087 for (i = 0; i < si->nscreens; i++)
1089 saver_screen_info *ssi = &si->screens[i];
1090 if (ssi->pid) any_running_p = True;
1092 return any_running_p;
1096 /* Environment variables. */
1099 /* Modifies $PATH in the current environment, so that if DEFAULT_PATH_PREFIX
1100 is defined, the xscreensaver daemon will search that directory for hacks.
1103 hack_environment (saver_info *si)
1105 #if defined(HAVE_PUTENV) && defined(DEFAULT_PATH_PREFIX)
1106 static const char *def_path = DEFAULT_PATH_PREFIX;
1107 if (def_path && *def_path)
1109 const char *opath = getenv("PATH");
1111 if (! opath) opath = "/bin:/usr/bin"; /* WTF */
1112 npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20);
1113 strcpy (npath, "PATH=");
1114 strcat (npath, def_path);
1115 strcat (npath, ":");
1116 strcat (npath, opath);
1121 /* don't free (npath) -- some implementations of putenv (BSD 4.4,
1122 glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
1123 do not. So we must leak it (and/or the previous setting). Yay.
1126 #endif /* HAVE_PUTENV && DEFAULT_PATH_PREFIX */
1131 hack_subproc_environment (Screen *screen, Window saver_window)
1133 /* Store $DISPLAY into the environment, so that the $DISPLAY variable that
1134 the spawned processes inherit is correct. First, it must be on the same
1135 host and display as the value of -display passed in on our command line
1136 (which is not necessarily the same as what our $DISPLAY variable is.)
1137 Second, the screen number in the $DISPLAY passed to the subprocess should
1138 be the screen on which this particular hack is running -- not the display
1139 specification which the driver itself is using, since the driver ignores
1140 its screen number and manages all existing screens.
1142 Likewise, store a window ID in $XSCREENSAVER_WINDOW -- this will allow
1143 us to (eventually) run multiple hacks in Xinerama mode, where each hack
1144 has the same $DISPLAY but a different piece of glass.
1146 Display *dpy = DisplayOfScreen (screen);
1147 const char *odpy = DisplayString (dpy);
1148 char *ndpy = (char *) malloc (strlen(odpy) + 20);
1149 char *nssw = (char *) malloc (40);
1152 strcpy (ndpy, "DISPLAY=");
1153 s = ndpy + strlen(ndpy);
1156 /* We have to find the last colon since it is the boundary between
1157 hostname & screen - IPv6 numeric format addresses may have many
1158 colons before that point, and DECnet addresses always have two colons */
1159 c = strrchr(s,':'); /* skip to last colon */
1160 if (c != NULL) s = c+1;
1161 while (isdigit(*s)) s++; /* skip over dpy number */
1162 while (*s == '.') s++; /* skip over dot */
1163 if (s[-1] != '.') *s++ = '.'; /* put on a dot */
1164 sprintf(s, "%d", screen_number (screen)); /* put on screen number */
1166 sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX", (unsigned long) saver_window);
1168 /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
1169 any more, right? It's not Posix, but everyone seems to have it. */
1176 /* don't free ndpy/nssw -- some implementations of putenv (BSD 4.4,
1177 glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
1178 do not. So we must leak it (and/or the previous setting). Yay.
1180 #endif /* HAVE_PUTENV */
1187 get_best_gl_visual (saver_info *si, Screen *screen)
1193 int errin = -1, errout = -1;
1199 av[ac++] = "xscreensaver-gl-helper";
1204 perror ("error creating pipe:");
1211 if (!si->prefs.verbose_p)
1215 perror ("error creating pipe:");
1220 errout = errfds [1];
1223 block_sigchld(); /* This blocks it in the parent and child, to avoid
1224 racing. It is never unblocked in the child before
1225 the child exits, but that doesn't matter.
1228 switch ((int) (forked = fork ()))
1232 sprintf (buf, "%s: couldn't fork", blurb());
1234 saver_exit (si, 1, 0);
1238 close (in); /* don't need this one */
1239 close (ConnectionNumber (si->dpy)); /* close display fd */
1241 if (dup2 (out, STDOUT_FILENO) < 0) /* pipe stdout */
1243 perror ("could not dup() a new stdout:");
1247 if (! si->prefs.verbose_p)
1250 if (dup2 (errout, STDERR_FILENO) < 0)
1252 perror ("could not dup() a new stderr:");
1257 hack_subproc_environment (screen, 0); /* set $DISPLAY */
1259 execvp (av[0], av); /* shouldn't return. */
1261 if (errno != ENOENT /* || si->prefs.verbose_p */ )
1263 /* Ignore "no such file or directory" errors.
1264 Issue all other exec errors, though. */
1265 sprintf (buf, "%s: running %s", blurb(), av[0]);
1268 exit (1); /* exits fork */
1274 int wait_status = 0;
1276 FILE *f = fdopen (in, "r");
1277 unsigned long v = 0;
1280 close (out); /* don't need this one */
1283 if (! fgets (buf, sizeof(buf)-1, f))
1287 if (! si->prefs.verbose_p)
1293 /* Wait for the child to die. */
1294 waitpid (-1, &wait_status, 0);
1296 unblock_sigchld(); /* child is dead and waited, unblock now. */
1298 if (1 == sscanf (buf, "0x%lx %c", &v, &c))
1303 if (si->prefs.verbose_p)
1305 int L = strlen(buf);
1306 fprintf (stderr, "%s: %s did not report a GL visual!\n",
1309 if (L && buf[L-1] == '\n')
1312 fprintf (stderr, "%s: %s said: \"%s\"\n",
1313 blurb(), av[0], buf);
1319 Visual *v = id_to_visual (screen, result);
1320 if (si->prefs.verbose_p)
1321 fprintf (stderr, "%s: %d: %s: GL visual is 0x%X%s.\n",
1322 blurb(), screen_number (screen),
1324 (v == DefaultVisualOfScreen (screen)
1325 ? " (default)" : ""));
1336 /* Restarting the xscreensaver process from scratch. */
1338 static char **saved_argv;
1341 save_argv (int argc, char **argv)
1343 saved_argv = (char **) calloc (argc+2, sizeof (char *));
1344 saved_argv [argc] = 0;
1347 int i = strlen (argv [argc]) + 1;
1348 saved_argv [argc] = (char *) malloc (i);
1349 memcpy (saved_argv [argc], argv [argc], i);
1354 /* Re-execs the process with the arguments in saved_argv. Does not return.
1357 restart_process (saver_info *si)
1361 shutdown_stderr (si);
1362 if (si->prefs.verbose_p)
1365 fprintf (stderr, "%s: re-executing", blurb());
1366 for (i = 0; saved_argv[i]; i++)
1367 fprintf (stderr, " %s", saved_argv[i]);
1368 fprintf (stderr, "\n");
1370 describe_uids (si, stderr);
1371 fprintf (stderr, "\n");
1375 execvp (saved_argv [0], saved_argv); /* shouldn't return */
1378 sprintf (buf, "%s: could not restart process", blurb());