1 /* subprocs.c --- choosing, spawning, and killing screenhacks.
2 * xscreensaver, Copyright (c) 1991-2006 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... */
488 if (si->prefs.debug_p)
490 /* Don't call fprintf() from signal handlers, as it might malloc.
491 fprintf(stderr, "%s: got SIGCHLD%s\n", blurb(),
492 (block_sigchld_handler ? " (blocked)" : ""));
494 write_string (STDERR_FILENO, blurb());
495 write_string (STDERR_FILENO, ": got SIGCHLD");
497 if (block_sigchld_handler)
498 write_string (STDERR_FILENO, " (blocked)\n");
500 write_string (STDERR_FILENO, "\n");
503 if (block_sigchld_handler < 0)
505 else if (block_sigchld_handler == 0)
508 await_dying_children (si);
520 await_dying_children (saver_info *si)
528 kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED);
530 if (si->prefs.debug_p)
532 if (kid < 0 && errno)
534 /* Don't call fprintf() from signal handlers, as it might malloc.
535 fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", blurb(),
538 write_string (STDERR_FILENO, blurb());
539 write_string (STDERR_FILENO, ": waitpid(-1) ==> ");
540 write_long (STDERR_FILENO, (long) kid);
541 write_string (STDERR_FILENO, " (");
542 write_long (STDERR_FILENO, (long) errno);
543 write_string (STDERR_FILENO, ")\n");
547 /* Don't call fprintf() from signal handlers, as it might malloc.
548 fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", blurb(),
551 write_string (STDERR_FILENO, blurb());
552 write_string (STDERR_FILENO, ": waitpid(-1) ==> ");
553 write_long (STDERR_FILENO, (long) kid);
554 write_string (STDERR_FILENO, "\n");
558 /* 0 means no more children to reap.
559 -1 means error -- except "interrupted system call" isn't a "real"
560 error, so if we get that, we should just try again. */
562 (kid < 0 && errno != EINTR))
565 describe_dead_child (si, kid, wait_status);
571 describe_dead_child (saver_info *si, pid_t kid, int wait_status)
574 saver_preferences *p = &si->prefs;
575 struct screenhack_job *job = find_job (kid);
576 const char *name = job ? job->name : "<unknown>";
577 int screen_no = job ? job->screen : 0;
579 if (WIFEXITED (wait_status))
581 int exit_status = WEXITSTATUS (wait_status);
583 /* Treat exit code as a signed 8-bit quantity. */
584 if (exit_status & 0x80) exit_status |= ~0xFF;
586 /* One might assume that exiting with non-0 means something went wrong.
587 But that loser xswarm exits with the code that it was killed with, so
588 it *always* exits abnormally. Treat abnormal exits as "normal" (don't
589 mention them) if we've just killed the subprocess. But mention them
590 if they happen on their own.
594 (p->verbose_p || job->status != job_killed)))
596 /* Don't call fprintf() from signal handlers, as it might malloc.
598 "%s: %d: child pid %lu (%s) exited abnormally (code %d).\n",
599 blurb(), screen_no, (unsigned long) kid, name, exit_status);
601 write_string (STDERR_FILENO, blurb());
602 write_string (STDERR_FILENO, ": ");
603 write_long (STDERR_FILENO, (long) screen_no);
604 write_string (STDERR_FILENO, ": child pid ");
605 write_long (STDERR_FILENO, (long) kid);
606 write_string (STDERR_FILENO, " (");
607 write_string (STDERR_FILENO, name);
608 write_string (STDERR_FILENO, ") exited abnormally (code ");
609 write_long (STDERR_FILENO, (long) exit_status);
610 write_string (STDERR_FILENO, ").\n");
612 else if (p->verbose_p)
614 /* Don't call fprintf() from signal handlers, as it might malloc.
615 fprintf (stderr, "%s: %d: child pid %lu (%s) exited normally.\n",
616 blurb(), screen_no, (unsigned long) kid, name);
618 write_string (STDERR_FILENO, blurb());
619 write_string (STDERR_FILENO, ": ");
620 write_long (STDERR_FILENO, (long) screen_no);
621 write_string (STDERR_FILENO, ": child pid ");
622 write_long (STDERR_FILENO, (long) kid);
623 write_string (STDERR_FILENO, " (");
624 write_string (STDERR_FILENO, name);
625 write_string (STDERR_FILENO, ") exited normally.\n");
629 job->status = job_dead;
631 else if (WIFSIGNALED (wait_status))
635 job->status != job_killed ||
636 WTERMSIG (wait_status) != SIGTERM)
638 /* Don't call fprintf() from signal handlers, as it might malloc.
639 fprintf (stderr, "%s: %d: child pid %lu (%s) terminated with %s.\n",
640 blurb(), screen_no, (unsigned long) kid, name,
641 signal_name (WTERMSIG(wait_status)));
643 write_string (STDERR_FILENO, blurb());
644 write_string (STDERR_FILENO, ": ");
645 write_long (STDERR_FILENO, (long) screen_no);
646 write_string (STDERR_FILENO, ": child pid ");
647 write_long (STDERR_FILENO, (long) kid);
648 write_string (STDERR_FILENO, " (");
649 write_string (STDERR_FILENO, name);
650 write_string (STDERR_FILENO, ") terminated with signal ");
651 write_long (STDERR_FILENO, WTERMSIG(wait_status));
652 write_string (STDERR_FILENO, ".\n");
656 job->status = job_dead;
658 else if (WIFSTOPPED (wait_status))
662 /* Don't call fprintf() from signal handlers, as it might malloc.
663 fprintf (stderr, "%s: child pid %lu (%s) stopped with %s.\n",
664 blurb(), (unsigned long) kid, name,
665 signal_name (WSTOPSIG (wait_status)));
667 write_string (STDERR_FILENO, blurb());
668 write_string (STDERR_FILENO, ": ");
669 write_long (STDERR_FILENO, (long) screen_no);
670 write_string (STDERR_FILENO, ": child pid ");
671 write_long (STDERR_FILENO, (long) kid);
672 write_string (STDERR_FILENO, " (");
673 write_string (STDERR_FILENO, name);
674 write_string (STDERR_FILENO, ") stopped with signal ");
675 write_long (STDERR_FILENO, WSTOPSIG(wait_status));
676 write_string (STDERR_FILENO, ".\n");
680 job->status = job_stopped;
684 /* Don't call fprintf() from signal handlers, as it might malloc.
685 fprintf (stderr, "%s: child pid %lu (%s) died in a mysterious way!",
686 blurb(), (unsigned long) kid, name);
688 write_string (STDERR_FILENO, blurb());
689 write_string (STDERR_FILENO, ": ");
690 write_long (STDERR_FILENO, (long) screen_no);
691 write_string (STDERR_FILENO, ": child pid ");
692 write_long (STDERR_FILENO, (long) kid);
693 write_string (STDERR_FILENO, " (");
694 write_string (STDERR_FILENO, name);
695 write_string (STDERR_FILENO, ") died in a mysterious way!");
697 job->status = job_dead;
700 /* Clear out the pid so that screenhack_running_p() knows it's dead.
702 if (!job || job->status == job_dead)
703 for (i = 0; i < si->nscreens; i++)
705 saver_screen_info *ssi = &si->screens[i];
712 static void await_dying_children (saver_info *si) { return; }
721 # ifdef HAVE_SIGACTION /* Thanks to Tom Kelly <tom@ancilla.toronto.on.ca> */
723 static Bool sigchld_initialized_p = 0;
724 if (!sigchld_initialized_p)
726 struct sigaction action, old;
728 action.sa_handler = sigchld_handler;
729 sigemptyset(&action.sa_mask);
732 if (sigaction(SIGCHLD, &action, &old) < 0)
735 sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
738 sigchld_initialized_p = True;
741 # else /* !HAVE_SIGACTION */
743 if (((long) signal (SIGCHLD, sigchld_handler)) == -1L)
746 sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
749 # endif /* !HAVE_SIGACTION */
758 select_visual_of_hack (saver_screen_info *ssi, screenhack *hack)
760 saver_info *si = ssi->global;
761 saver_preferences *p = &si->prefs;
764 if (hack->visual && *hack->visual)
765 selected = select_visual(ssi, hack->visual);
767 selected = select_visual(ssi, 0);
769 if (!selected && (p->verbose_p || si->demoing_p))
772 ? "%s: warning, no \"%s\" visual for \"%s\".\n"
773 : "%s: no \"%s\" visual; skipping \"%s\".\n"),
775 (hack->visual && *hack->visual ? hack->visual : "???"),
783 print_path_error (const char *program)
786 char *cmd = strdup (program);
787 char *token = strchr (cmd, ' ');
789 if (token) *token = 0;
790 sprintf (buf, "%s: could not execute \"%.100s\"", blurb(), cmd);
794 if (errno == ENOENT &&
795 (token = getenv("PATH")))
799 # define PATH_MAX MAXPATHLEN
801 # define PATH_MAX 2048
805 fprintf (stderr, "\n");
807 # if defined(HAVE_GETCWD)
808 if (! getcwd (path, sizeof(path)))
810 # elif defined(HAVE_GETWD)
814 fprintf (stderr, " Current directory is: %s\n", path);
815 fprintf (stderr, " PATH is:\n");
816 token = strtok (strdup(token), ":");
819 fprintf (stderr, " %s\n", token);
820 token = strtok(0, ":");
822 fprintf (stderr, "\n");
827 /* Executes the command in another process.
828 Command may be any single command acceptable to /bin/sh.
829 It may include wildcards, but no semicolons.
830 If successful, the pid of the other process is returned.
831 Otherwise, -1 is returned and an error may have been
835 fork_and_exec (saver_screen_info *ssi, const char *command)
837 saver_info *si = ssi->global;
838 saver_preferences *p = &si->prefs;
841 switch ((int) (forked = fork ()))
846 sprintf (buf, "%s: couldn't fork", blurb());
852 close (ConnectionNumber (si->dpy)); /* close display fd */
853 limit_subproc_memory (p->inferior_memory_limit, p->verbose_p);
854 hack_subproc_environment (ssi); /* set $DISPLAY */
857 fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n",
858 blurb(), ssi->number, command,
859 (unsigned long) getpid ());
861 exec_command (p->shell, command, p->nice_inferior);
863 /* If that returned, we were unable to exec the subprocess.
864 Print an error message, if desired.
866 if (! p->ignore_uninstalled_p)
867 print_path_error (command);
869 exit (1); /* exits child fork */
872 default: /* parent */
873 (void) make_job (forked, ssi->number, command);
882 spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p)
884 saver_info *si = ssi->global;
885 saver_preferences *p = &si->prefs;
886 raise_window (si, first_time_p, True, False);
889 if (p->screenhacks_count)
900 if (p->screenhacks_count < 1)
902 /* No hacks at all */
905 else if (p->screenhacks_count == 1)
907 /* Exactly one hack in the list */
910 else if (si->selection_mode == -1)
912 /* Select the next hack, wrapping. */
913 new_hack = (ssi->current_hack + 1) % p->screenhacks_count;
915 else if (si->selection_mode == -2)
917 /* Select the previous hack, wrapping. */
918 if (ssi->current_hack < 0)
919 new_hack = p->screenhacks_count - 1;
921 new_hack = ((ssi->current_hack + p->screenhacks_count - 1)
922 % p->screenhacks_count);
924 else if (si->selection_mode > 0)
926 /* Select a specific hack, by number (via the ACTIVATE command.) */
927 new_hack = ((si->selection_mode - 1) % p->screenhacks_count);
930 else if (p->mode == ONE_HACK &&
931 p->selected_hack >= 0)
933 /* Select a specific hack, by number (via "One Saver" mode.) */
934 new_hack = p->selected_hack;
937 else if (p->mode == BLANK_ONLY || p->mode == DONT_BLANK)
941 else if (p->mode == RANDOM_HACKS_SAME &&
944 /* Use the same hack that's running on screen 0.
945 (Assumes this function was called on screen 0 first.)
947 new_hack = si->screens[0].current_hack;
949 else /* (p->mode == RANDOM_HACKS) */
951 /* Select a random hack (but not the one we just ran.) */
952 while ((new_hack = random () % p->screenhacks_count)
953 == ssi->current_hack)
957 if (new_hack < 0) /* don't run a hack */
959 ssi->current_hack = -1;
960 if (si->selection_mode < 0)
961 si->selection_mode = 0;
965 ssi->current_hack = new_hack;
966 hack = p->screenhacks[ssi->current_hack];
968 /* If the hack is disabled, or there is no visual for this hack,
969 then try again (move forward, or backward, or re-randomize.)
970 Unless this hack was specified explicitly, in which case,
974 select_visual_of_hack (ssi, hack);
978 !on_path_p (hack->command) ||
979 !select_visual_of_hack (ssi, hack)))
981 if (++retry_count > (p->screenhacks_count*4))
983 /* Uh, oops. Odds are, there are no suitable visuals,
984 and we're looping. Give up. (This is totally lame,
985 what we should do is make a list of suitable hacks at
986 the beginning, then only loop over them.)
990 "%s: %d: no programs enabled, or no suitable visuals.\n",
991 blurb(), ssi->number);
998 /* Turn off "next" and "prev" modes now, but "demo" mode is only
999 turned off by explicit action.
1001 if (si->selection_mode < 0)
1002 si->selection_mode = 0;
1004 forked = fork_and_exec (ssi, hack->command);
1005 switch ((int) forked)
1007 case -1: /* fork failed */
1008 case 0: /* child fork (can't happen) */
1009 sprintf (buf, "%s: couldn't fork", blurb());
1011 restore_real_vroot (si);
1012 saver_exit (si, 1, "couldn't fork");
1024 spawn_screenhack (saver_info *si, Bool first_time_p)
1026 if (monitor_powered_on_p (si))
1029 for (i = 0; i < si->nscreens; i++)
1031 saver_screen_info *ssi = &si->screens[i];
1032 spawn_screenhack_1 (ssi, first_time_p);
1035 else if (si->prefs.verbose_p)
1037 "%s: X says monitor has powered down; "
1038 "not launching a hack.\n", blurb());
1040 store_saver_status (si); /* store current hack numbers */
1045 kill_screenhack (saver_info *si)
1048 for (i = 0; i < si->nscreens; i++)
1050 saver_screen_info *ssi = &si->screens[i];
1052 kill_job (si, ssi->pid, SIGTERM);
1059 suspend_screenhack (saver_info *si, Bool suspend_p)
1061 #ifdef SIGSTOP /* older VMS doesn't have it... */
1063 for (i = 0; i < si->nscreens; i++)
1065 saver_screen_info *ssi = &si->screens[i];
1067 kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT));
1069 #endif /* SIGSTOP */
1073 /* Called when we're exiting abnormally, to kill off the subproc. */
1075 emergency_kill_subproc (saver_info *si)
1079 signal (SIGCHLD, SIG_IGN);
1080 #endif /* SIGCHLD */
1082 for (i = 0; i < si->nscreens; i++)
1084 saver_screen_info *ssi = &si->screens[i];
1087 kill_job (si, ssi->pid, SIGTERM);
1094 screenhack_running_p (saver_info *si)
1096 Bool any_running_p = False;
1098 for (i = 0; i < si->nscreens; i++)
1100 saver_screen_info *ssi = &si->screens[i];
1101 if (ssi->pid) any_running_p = True;
1103 return any_running_p;
1107 /* Environment variables. */
1110 /* Modifies $PATH in the current environment, so that if DEFAULT_PATH_PREFIX
1111 is defined, the xscreensaver daemon will search that directory for hacks.
1114 hack_environment (saver_info *si)
1116 #if defined(HAVE_PUTENV) && defined(DEFAULT_PATH_PREFIX)
1117 static const char *def_path = DEFAULT_PATH_PREFIX;
1118 if (def_path && *def_path)
1120 const char *opath = getenv("PATH");
1121 char *npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20);
1122 strcpy (npath, "PATH=");
1123 strcat (npath, def_path);
1124 strcat (npath, ":");
1125 strcat (npath, opath);
1130 /* don't free (npath) -- some implementations of putenv (BSD 4.4,
1131 glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
1132 do not. So we must leak it (and/or the previous setting). Yay.
1135 #endif /* HAVE_PUTENV && DEFAULT_PATH_PREFIX */
1140 hack_subproc_environment (saver_screen_info *ssi)
1142 /* Store $DISPLAY into the environment, so that the $DISPLAY variable that
1143 the spawned processes inherit is correct. First, it must be on the same
1144 host and display as the value of -display passed in on our command line
1145 (which is not necessarily the same as what our $DISPLAY variable is.)
1146 Second, the screen number in the $DISPLAY passed to the subprocess should
1147 be the screen on which this particular hack is running -- not the display
1148 specification which the driver itself is using, since the driver ignores
1149 its screen number and manages all existing screens.
1151 Likewise, store a window ID in $XSCREENSAVER_WINDOW -- this will allow
1152 us to (eventually) run multiple hacks in Xinerama mode, where each hack
1153 has the same $DISPLAY but a different piece of glass.
1155 saver_info *si = ssi->global;
1156 const char *odpy = DisplayString (si->dpy);
1157 char *ndpy = (char *) malloc (strlen(odpy) + 20);
1158 char *nssw = (char *) malloc (40);
1161 strcpy (ndpy, "DISPLAY=");
1162 s = ndpy + strlen(ndpy);
1165 /* We have to find the last colon since it is the boundary between
1166 hostname & screen - IPv6 numeric format addresses may have many
1167 colons before that point, and DECnet addresses always have two colons */
1168 c = strrchr(s,':'); /* skip to last colon */
1169 if (c != NULL) s = c+1;
1170 while (isdigit(*s)) s++; /* skip over dpy number */
1171 while (*s == '.') s++; /* skip over dot */
1172 if (s[-1] != '.') *s++ = '.'; /* put on a dot */
1173 sprintf(s, "%d", ssi->real_screen_number); /* put on screen number */
1175 sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX",
1176 (unsigned long) ssi->screensaver_window);
1178 /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
1179 any more, right? It's not Posix, but everyone seems to have it. */
1186 /* don't free ndpy/nssw -- some implementations of putenv (BSD 4.4,
1187 glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
1188 do not. So we must leak it (and/or the previous setting). Yay.
1190 #endif /* HAVE_PUTENV */
1197 get_best_gl_visual (saver_screen_info *ssi)
1199 saver_info *si = ssi->global;
1208 av[ac++] = "xscreensaver-gl-helper";
1213 perror ("error creating pipe:");
1220 switch ((int) (forked = fork ()))
1224 sprintf (buf, "%s: couldn't fork", blurb());
1226 saver_exit (si, 1, 0);
1232 close (in); /* don't need this one */
1233 close (ConnectionNumber (si->dpy)); /* close display fd */
1235 if (dup2 (out, stdout_fd) < 0) /* pipe stdout */
1237 perror ("could not dup() a new stdout:");
1240 hack_subproc_environment (ssi); /* set $DISPLAY */
1242 execvp (av[0], av); /* shouldn't return. */
1244 if (errno != ENOENT || si->prefs.verbose_p)
1246 /* Ignore "no such file or directory" errors, unless verbose.
1247 Issue all other exec errors, though. */
1248 sprintf (buf, "%s: running %s", blurb(), av[0]);
1251 exit (1); /* exits fork */
1257 int wait_status = 0;
1259 FILE *f = fdopen (in, "r");
1260 unsigned long v = 0;
1263 close (out); /* don't need this one */
1266 if (! fgets (buf, sizeof(buf)-1, f))
1270 /* Wait for the child to die. */
1271 waitpid (-1, &wait_status, 0);
1273 if (1 == sscanf (buf, "0x%lx %c", &v, &c))
1278 if (si->prefs.verbose_p)
1280 int L = strlen(buf);
1281 fprintf (stderr, "%s: %s did not report a GL visual!\n",
1284 if (L && buf[L-1] == '\n')
1287 fprintf (stderr, "%s: %s said: \"%s\"\n",
1288 blurb(), av[0], buf);
1294 Visual *v = id_to_visual (ssi->screen, result);
1295 if (si->prefs.verbose_p)
1296 fprintf (stderr, "%s: %d: %s: GL visual is 0x%X%s.\n",
1297 blurb(), ssi->number,
1299 (v == ssi->default_visual ? " (default)" : ""));
1310 /* Restarting the xscreensaver process from scratch. */
1312 static char **saved_argv;
1315 save_argv (int argc, char **argv)
1317 saved_argv = (char **) calloc (argc+2, sizeof (char *));
1318 saved_argv [argc] = 0;
1321 int i = strlen (argv [argc]) + 1;
1322 saved_argv [argc] = (char *) malloc (i);
1323 memcpy (saved_argv [argc], argv [argc], i);
1328 /* Re-execs the process with the arguments in saved_argv. Does not return.
1331 restart_process (saver_info *si)
1335 shutdown_stderr (si);
1336 if (si->prefs.verbose_p)
1339 fprintf (stderr, "%s: re-executing", blurb());
1340 for (i = 0; saved_argv[i]; i++)
1341 fprintf (stderr, " %s", saved_argv[i]);
1342 fprintf (stderr, "\n");
1344 describe_uids (si, stderr);
1345 fprintf (stderr, "\n");
1349 execvp (saved_argv [0], saved_argv); /* shouldn't return */
1352 sprintf (buf, "%s: could not restart process", blurb());