http://www.tienza.es/crux/src/www.jwz.org/xscreensaver/xscreensaver-5.05.tar.gz
[xscreensaver] / driver / subprocs.c
1 /* subprocs.c --- choosing, spawning, and killing screenhacks.
2  * xscreensaver, Copyright (c) 1991-2008 Jamie Zawinski <jwz@jwz.org>
3  *
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 
10  * implied warranty.
11  */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <ctype.h>
18 #include <stdio.h>
19 #include <string.h>
20
21 #include <X11/Xlib.h>           /* not used for much... */
22
23 #ifndef ESRCH
24 # include <errno.h>
25 #endif
26
27 #include <sys/time.h>           /* sys/resource.h needs this for timeval */
28 #include <sys/param.h>          /* for PATH_MAX */
29
30 #ifdef HAVE_SYS_WAIT_H
31 # include <sys/wait.h>          /* for waitpid() and associated macros */
32 #endif
33
34 #ifdef HAVE_SETRLIMIT
35 # include <sys/resource.h>      /* for setrlimit() and RLIMIT_AS */
36 #endif
37
38 #ifdef VMS
39 # include <processes.h>
40 # include <unixio.h>            /* for close */
41 # include <unixlib.h>           /* for getpid */
42 # define pid_t int
43 # define fork  vfork
44 #endif /* VMS */
45
46 #include <signal.h>             /* for the signal names */
47
48 #if !defined(SIGCHLD) && defined(SIGCLD)
49 # define SIGCHLD SIGCLD
50 #endif
51
52 #if 0 /* putenv() is declared in stdlib.h on modern linux systems. */
53 #ifdef HAVE_PUTENV
54 extern int putenv (/* const char * */); /* getenv() is in stdlib.h... */
55 #endif
56 #endif
57
58 extern int kill (pid_t, int);           /* signal() is in sys/signal.h... */
59
60 /* This file doesn't need the Xt headers, so stub these types out... */
61 #undef XtPointer
62 #define XtAppContext void*
63 #define XrmDatabase  void*
64 #define XtIntervalId void*
65 #define XtPointer    void*
66 #define Widget       void*
67
68 #include "xscreensaver.h"
69 #include "exec.h"
70 #include "yarandom.h"
71 #include "visual.h"    /* for id_to_visual() */
72
73 extern saver_info *global_si_kludge;    /* I hate C so much... */
74
75
76 /* Used when printing error/debugging messages from signal handlers.
77  */
78 static const char *
79 no_malloc_number_to_string (long num)
80 {
81   static char string[128] = "";
82   int num_digits;
83   Bool negative_p = False;
84
85   num_digits = 0;
86
87   if (num == 0)
88     return "0";
89
90   if (num < 0)
91     {
92       negative_p = True;
93       num = -num;
94     }
95
96   while ((num > 0) && (num_digits < sizeof(string) - 1))
97     {
98       int digit;
99       digit = (int) num % 10;
100       num_digits++;
101       string[sizeof(string) - 1 - num_digits] = digit + '0';
102       num /= 10;
103     }
104
105   if (negative_p)
106     {
107       num_digits++;
108       string[sizeof(string) - 1 - num_digits] = '-';
109     }
110
111   return string + sizeof(string) - 1 - num_digits;
112 }
113
114 /* Like write(), but runs strlen() on the arg to get the length. */
115 static int
116 write_string (int fd, const char *str)
117 {
118   return write (fd, str, strlen (str));
119 }
120
121 static int
122 write_long (int fd, long n)
123 {
124   const char *str = no_malloc_number_to_string (n);
125   return write_string (fd, str);
126 }
127
128
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.
132
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!
138  */
139 #if defined(RLIMIT_VMEM) && !defined(RLIMIT_AS)
140 # define RLIMIT_AS RLIMIT_VMEM
141 #endif
142
143 static void
144 limit_subproc_memory (int address_space_limit, Bool verbose_p)
145 {
146
147 /* This has caused way more problems than it has solved...
148    Let's just completely ignore the "memoryLimit" option now.
149  */
150 #undef HAVE_SETRLIMIT
151
152 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_AS)
153   struct rlimit r;
154
155   if (address_space_limit < 10 * 1024)  /* let's not be crazy */
156     return;
157
158   if (getrlimit (RLIMIT_AS, &r) != 0)
159     {
160       char buf [512];
161       sprintf (buf, "%s: getrlimit(RLIMIT_AS) failed", blurb());
162       perror (buf);
163       return;
164     }
165
166   r.rlim_cur = address_space_limit;
167
168   if (setrlimit (RLIMIT_AS, &r) != 0)
169     {
170       char buf [512];
171       sprintf (buf, "%s: setrlimit(RLIMIT_AS, {%lu, %lu}) failed",
172                blurb(), r.rlim_cur, r.rlim_max);
173       perror (buf);
174       return;
175     }
176
177   if (verbose_p)
178     {
179       int i = address_space_limit;
180       char buf[100];
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);
187       else
188         sprintf(buf, "%d bytes", i);
189
190       fprintf (stderr, "%s: limited pid %lu address space to %s.\n",
191                blurb(), (unsigned long) getpid (), buf);
192     }
193
194 #endif /* HAVE_SETRLIMIT && RLIMIT_AS */
195 }
196
197 \f
198 /* Management of child processes, and de-zombification.
199  */
200
201 enum job_status {
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. */
209 };
210
211 struct screenhack_job {
212   char *name;
213   pid_t pid;
214   int screen;
215   enum job_status status;
216   struct screenhack_job *next;
217 };
218
219 static struct screenhack_job *jobs = 0;
220
221 /* for debugging -- nothing calls this, but it's useful to invoke from gdb.
222  */
223 void show_job_list (void);
224
225 void
226 show_job_list (void)
227 {
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",
232              (long) job->pid,
233              job->screen,
234              (job->status == job_running ? "running" :
235               job->status == job_stopped ? "stopped" :
236               job->status == job_killed  ? " killed" :
237               job->status == job_dead    ? "   dead" : "    ???"),
238              job->name);
239   fprintf (stderr, "\n");
240 }
241
242
243 static void clean_job_list (void);
244
245 static struct screenhack_job *
246 make_job (pid_t pid, int screen, const char *cmd)
247 {
248   struct screenhack_job *job = (struct screenhack_job *) malloc (sizeof(*job));
249
250   static char name [1024];
251   const char *in = cmd;
252   char *out = name;
253   int got_eq = 0;
254   int first = 1;
255
256   clean_job_list();
257
258  AGAIN:
259   while (isspace(*in)) in++;            /* skip whitespace */
260   while (!isspace(*in) && *in != ':') {
261     if (*in == '=') got_eq = 1;
262     *out++ = *in++;                     /* snarf first token */
263   }
264
265   if (got_eq)                           /* if the first token was FOO=bar */
266     {                                   /* then get the next token instead. */
267       got_eq = 0;
268       out = name;
269       first = 0;
270       goto AGAIN;
271     }
272
273   while (isspace(*in)) in++;            /* skip whitespace */
274   *out = 0;
275
276   job->name = strdup(name);
277   job->pid = pid;
278   job->screen = screen;
279   job->status = job_running;
280   job->next = jobs;
281   jobs = job;
282
283   return jobs;
284 }
285
286
287 static void
288 free_job (struct screenhack_job *job)
289 {
290   if (!job)
291     return;
292   else if (job == jobs)
293     jobs = jobs->next;
294   else
295     {
296       struct screenhack_job *job2, *prev;
297       for (prev = 0, job2 = jobs;
298            job2;
299            prev = job2, job2 = job2->next)
300         if (job2 == job)
301           {
302             prev->next = job->next;
303             break;
304           }
305     }
306   free(job->name);
307   free(job);
308 }
309
310
311 /* Cleans out dead jobs from the jobs list -- this must only be called
312    from the main thread, not from a signal handler. 
313  */
314 static void
315 clean_job_list (void)
316 {
317   struct screenhack_job *job, *prev, *next;
318   for (prev = 0, job = jobs, next = (job ? job->next : 0);
319        job;
320        prev = job, job = next, next = (job ? job->next : 0))
321     {
322       if (job->status == job_dead)
323         {
324           if (prev)
325             prev->next = next;
326           free_job (job);
327           job = prev;
328         }
329     }
330 }
331
332
333 static struct screenhack_job *
334 find_job (pid_t pid)
335 {
336   struct screenhack_job *job;
337   for (job = jobs; job; job = job->next)
338     if (job->pid == pid)
339       return job;
340   return 0;
341 }
342
343 static void await_dying_children (saver_info *si);
344 #ifndef VMS
345 static void describe_dead_child (saver_info *, pid_t, int wait_status);
346 #endif
347
348
349 /* Semaphore to temporarily turn the SIGCHLD handler into a no-op.
350    Don't alter this directly -- use block_sigchld() / unblock_sigchld().
351  */
352 static int block_sigchld_handler = 0;
353
354
355 #ifdef HAVE_SIGACTION
356  sigset_t
357 #else  /* !HAVE_SIGACTION */
358  int
359 #endif /* !HAVE_SIGACTION */
360 block_sigchld (void)
361 {
362 #ifdef HAVE_SIGACTION
363   struct sigaction sa;
364   sigset_t child_set;
365
366   memset (&sa, 0, sizeof (sa));
367   sa.sa_handler = SIG_IGN;
368   sigaction (SIGPIPE, &sa, NULL);
369
370   sigemptyset (&child_set);
371   sigaddset (&child_set, SIGCHLD);
372   sigprocmask (SIG_BLOCK, &child_set, 0);
373
374 #else  /* !HAVE_SIGACTION */
375   signal (SIGPIPE, SIG_IGN);
376 #endif /* !HAVE_SIGACTION */
377
378   block_sigchld_handler++;
379
380 #ifdef HAVE_SIGACTION
381   return child_set;
382 #else  /* !HAVE_SIGACTION */
383   return 0;
384 #endif /* !HAVE_SIGACTION */
385 }
386
387 void
388 unblock_sigchld (void)
389 {
390 #ifdef HAVE_SIGACTION
391   struct sigaction sa;
392   sigset_t child_set;
393
394   memset(&sa, 0, sizeof (sa));
395   sa.sa_handler = SIG_DFL;
396   sigaction(SIGPIPE, &sa, NULL);
397
398   sigemptyset(&child_set);
399   sigaddset(&child_set, SIGCHLD);
400   sigprocmask(SIG_UNBLOCK, &child_set, 0);
401
402 #else /* !HAVE_SIGACTION */
403   signal(SIGPIPE, SIG_DFL);
404 #endif /* !HAVE_SIGACTION */
405
406   block_sigchld_handler--;
407 }
408
409 static int
410 kill_job (saver_info *si, pid_t pid, int signal)
411 {
412   saver_preferences *p = &si->prefs;
413   struct screenhack_job *job;
414   int status = -1;
415
416   clean_job_list();
417
418   if (block_sigchld_handler)
419     /* This function should not be called from the signal handler. */
420     abort();
421
422   block_sigchld();                      /* we control the horizontal... */
423
424   job = find_job (pid);
425   if (!job ||
426       !job->pid ||
427       job->status == job_killed)
428     {
429       if (p->verbose_p)
430         fprintf (stderr, "%s: no child %ld to signal!\n",
431                  blurb(), (long) pid);
432       goto DONE;
433     }
434
435   switch (signal) {
436   case SIGTERM: job->status = job_killed;  break;
437 #ifdef SIGSTOP
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;
441 #endif /* SIGSTOP */
442   default: abort();
443   }
444
445   if (p->verbose_p)
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,
451              job->name);
452
453   status = kill (job->pid, signal);
454
455   if (p->verbose_p && status < 0)
456     {
457       if (errno == ESRCH)
458         fprintf (stderr,
459                  "%s: %d: child process %lu (%s) was already dead.\n",
460                  blurb(), job->screen, (unsigned long) job->pid, job->name);
461       else
462         {
463           char buf [1024];
464           sprintf (buf, "%s: %d: couldn't kill child process %lu (%s)",
465                    blurb(), job->screen, (unsigned long) job->pid, job->name);
466           perror (buf);
467         }
468     }
469
470   await_dying_children (si);
471
472  DONE:
473   unblock_sigchld();
474   if (block_sigchld_handler < 0)
475     abort();
476
477   clean_job_list();
478   return status;
479 }
480
481
482 #ifdef SIGCHLD
483 static RETSIGTYPE
484 sigchld_handler (int sig)
485 {
486   saver_info *si = global_si_kludge;    /* I hate C so much... */
487
488   if (si->prefs.debug_p)
489     {
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)" : ""));
493       */
494       write_string (STDERR_FILENO, blurb());
495       write_string (STDERR_FILENO, ": got SIGCHLD");
496
497       if (block_sigchld_handler)
498         write_string (STDERR_FILENO, " (blocked)\n");
499       else
500         write_string (STDERR_FILENO, "\n");
501     }
502
503   if (block_sigchld_handler < 0)
504     abort();
505   else if (block_sigchld_handler == 0)
506     {
507       block_sigchld();
508       await_dying_children (si);
509       unblock_sigchld();
510     }
511
512   init_sigchld();
513 }
514 #endif /* SIGCHLD */
515
516
517 #ifndef VMS
518
519 static void
520 await_dying_children (saver_info *si)
521 {
522   while (1)
523     {
524       int wait_status = 0;
525       pid_t kid;
526
527       errno = 0;
528       kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED);
529
530       if (si->prefs.debug_p)
531         {
532           if (kid < 0 && errno)
533             {
534               /* Don't call fprintf() from signal handlers, as it might malloc.
535               fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", blurb(),
536                        (long) kid, errno);
537                */
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");
544             }
545           else
546             {
547               /* Don't call fprintf() from signal handlers, as it might malloc.
548               fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", blurb(),
549                        (long) kid);
550                */
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");
555             }
556         }
557
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. */
561       if (kid == 0 ||
562           (kid < 0 && errno != EINTR))
563         break;
564
565       describe_dead_child (si, kid, wait_status);
566     }
567 }
568
569
570 static void
571 describe_dead_child (saver_info *si, pid_t kid, int wait_status)
572 {
573   int i;
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;
578
579   if (WIFEXITED (wait_status))
580     {
581       int exit_status = WEXITSTATUS (wait_status);
582
583       /* Treat exit code as a signed 8-bit quantity. */
584       if (exit_status & 0x80) exit_status |= ~0xFF;
585
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.
591        */
592       if (!job ||
593           (exit_status != 0 &&
594            (p->verbose_p || job->status != job_killed)))
595         {
596           /* Don't call fprintf() from signal handlers, as it might malloc.
597           fprintf (stderr,
598                    "%s: %d: child pid %lu (%s) exited abnormally (code %d).\n",
599                    blurb(), screen_no, (unsigned long) kid, name, exit_status);
600            */
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"); 
611         }
612       else if (p->verbose_p)
613         {
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);
617            */
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");
626         }
627
628       if (job)
629         job->status = job_dead;
630     }
631   else if (WIFSIGNALED (wait_status))
632     {
633       if (p->verbose_p ||
634           !job ||
635           job->status != job_killed ||
636           WTERMSIG (wait_status) != SIGTERM)
637         {
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)));
642            */
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");
653         }
654
655       if (job)
656         job->status = job_dead;
657     }
658   else if (WIFSTOPPED (wait_status))
659     {
660       if (p->verbose_p)
661         {
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)));
666            */
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");
677         }
678
679       if (job)
680         job->status = job_stopped;
681     }
682   else
683     {
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);
687        */
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!");
696       if (job)
697         job->status = job_dead;
698     }
699
700   /* Clear out the pid so that screenhack_running_p() knows it's dead.
701    */
702   if (!job || job->status == job_dead)
703     for (i = 0; i < si->nscreens; i++)
704       {
705         saver_screen_info *ssi = &si->screens[i];
706         if (kid == ssi->pid)
707           ssi->pid = 0;
708       }
709 }
710
711 #else  /* VMS */
712 static void await_dying_children (saver_info *si) { return; }
713 #endif /* VMS */
714
715
716 void
717 init_sigchld (void)
718 {
719 #ifdef SIGCHLD
720
721 # ifdef HAVE_SIGACTION  /* Thanks to Tom Kelly <tom@ancilla.toronto.on.ca> */
722
723   static Bool sigchld_initialized_p = 0;
724   if (!sigchld_initialized_p)
725     {
726       struct sigaction action, old;
727
728       action.sa_handler = sigchld_handler;
729       sigemptyset(&action.sa_mask);
730       action.sa_flags = 0;
731
732       if (sigaction(SIGCHLD, &action, &old) < 0)
733         {
734           char buf [255];
735           sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
736           perror (buf);
737         }
738       sigchld_initialized_p = True;
739     }
740
741 # else  /* !HAVE_SIGACTION */
742
743   if (((long) signal (SIGCHLD, sigchld_handler)) == -1L)
744     {
745       char buf [255];
746       sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
747       perror (buf);
748     }
749 # endif /* !HAVE_SIGACTION */
750 #endif /* SIGCHLD */
751 }
752
753
754
755 \f
756
757 static Bool
758 select_visual_of_hack (saver_screen_info *ssi, screenhack *hack)
759 {
760   saver_info *si = ssi->global;
761   saver_preferences *p = &si->prefs;
762   Bool selected;
763
764   if (hack->visual && *hack->visual)
765     selected = select_visual(ssi, hack->visual);
766   else
767     selected = select_visual(ssi, 0);
768
769   if (!selected && (p->verbose_p || si->demoing_p))
770     fprintf (stderr,
771              (si->demoing_p
772               ? "%s: warning, no \"%s\" visual for \"%s\".\n"
773               : "%s: no \"%s\" visual; skipping \"%s\".\n"),
774              blurb(),
775              (hack->visual && *hack->visual ? hack->visual : "???"),
776              hack->command);
777
778   return selected;
779 }
780
781
782 static void
783 print_path_error (const char *program)
784 {
785   char buf [512];
786   char *cmd = strdup (program);
787   char *token = strchr (cmd, ' ');
788
789   if (token) *token = 0;
790   sprintf (buf, "%s: could not execute \"%.100s\"", blurb(), cmd);
791   free (cmd);
792   perror (buf);
793
794   if (errno == ENOENT &&
795       (token = getenv("PATH")))
796     {
797 # ifndef PATH_MAX
798 #  ifdef MAXPATHLEN
799 #   define PATH_MAX MAXPATHLEN
800 #  else
801 #   define PATH_MAX 2048
802 #  endif
803 # endif
804       char path[PATH_MAX];
805       fprintf (stderr, "\n");
806       *path = 0;
807 # if defined(HAVE_GETCWD)
808       if (! getcwd (path, sizeof(path)))
809         *path = 0;
810 # elif defined(HAVE_GETWD)
811       getwd (path);
812 # endif
813       if (*path)
814         fprintf (stderr, "    Current directory is: %s\n", path);
815       fprintf (stderr, "    PATH is:\n");
816       token = strtok (strdup(token), ":");
817       while (token)
818         {
819           fprintf (stderr, "        %s\n", token);
820           token = strtok(0, ":");
821         }
822       fprintf (stderr, "\n");
823     }
824 }
825
826
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
832    printed to stderr.
833  */
834 pid_t
835 fork_and_exec (saver_screen_info *ssi, const char *command)
836 {
837   saver_info *si = ssi->global;
838   saver_preferences *p = &si->prefs;
839   pid_t forked;
840
841   switch ((int) (forked = fork ()))
842     {
843     case -1:
844       {
845         char buf [255];
846         sprintf (buf, "%s: couldn't fork", blurb());
847         perror (buf);
848         break;
849       }
850
851     case 0:
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 */
855
856       if (p->verbose_p)
857         fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n",
858                  blurb(), ssi->number, command,
859                  (unsigned long) getpid ());
860
861       exec_command (p->shell, command, p->nice_inferior);
862
863       /* If that returned, we were unable to exec the subprocess.
864          Print an error message, if desired.
865        */
866       if (! p->ignore_uninstalled_p)
867         print_path_error (command);
868
869       exit (1);  /* exits child fork */
870       break;
871
872     default:    /* parent */
873       (void) make_job (forked, ssi->number, command);
874       break;
875     }
876
877   return forked;
878 }
879
880
881 static void
882 spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p)
883 {
884   saver_info *si = ssi->global;
885   saver_preferences *p = &si->prefs;
886   raise_window (si, first_time_p, True, False);
887   XFlush (si->dpy);
888
889   if (p->screenhacks_count)
890     {
891       screenhack *hack;
892       pid_t forked;
893       char buf [255];
894       int new_hack = -1;
895       int retry_count = 0;
896       Bool force = False;
897
898     AGAIN:
899
900       if (p->screenhacks_count < 1)
901         {
902           /* No hacks at all */
903           new_hack = -1;
904         }
905       else if (p->screenhacks_count == 1)
906         {
907           /* Exactly one hack in the list */
908           new_hack = 0;
909         }
910       else if (si->selection_mode == -1)
911         {
912           /* Select the next hack, wrapping. */
913           new_hack = (ssi->current_hack + 1) % p->screenhacks_count;
914         }
915       else if (si->selection_mode == -2)
916         {
917           /* Select the previous hack, wrapping. */
918           if (ssi->current_hack < 0)
919             new_hack = p->screenhacks_count - 1;
920           else
921             new_hack = ((ssi->current_hack + p->screenhacks_count - 1)
922                         % p->screenhacks_count);
923         }
924       else if (si->selection_mode > 0)
925         {
926           /* Select a specific hack, by number (via the ACTIVATE command.) */
927           new_hack = ((si->selection_mode - 1) % p->screenhacks_count);
928           force = True;
929         }
930       else if (p->mode == ONE_HACK &&
931                p->selected_hack >= 0)
932         {
933           /* Select a specific hack, by number (via "One Saver" mode.) */
934           new_hack = p->selected_hack;
935           force = True;
936         }
937       else if (p->mode == BLANK_ONLY || p->mode == DONT_BLANK)
938         {
939           new_hack = -1;
940         }
941       else if (p->mode == RANDOM_HACKS_SAME &&
942                ssi->number != 0)
943         {
944           /* Use the same hack that's running on screen 0.
945              (Assumes this function was called on screen 0 first.)
946            */
947           new_hack = si->screens[0].current_hack;
948         }
949       else  /* (p->mode == RANDOM_HACKS) */
950         {
951           /* Select a random hack (but not the one we just ran.) */
952           while ((new_hack = random () % p->screenhacks_count)
953                  == ssi->current_hack)
954             ;
955         }
956
957       if (new_hack < 0)   /* don't run a hack */
958         {
959           ssi->current_hack = -1;
960           if (si->selection_mode < 0)
961             si->selection_mode = 0;
962           return;
963         }
964
965       ssi->current_hack = new_hack;
966       hack = p->screenhacks[ssi->current_hack];
967
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,
971          use it regardless.
972        */
973       if (force)
974         select_visual_of_hack (ssi, hack);
975         
976       if (!force &&
977           (!hack->enabled_p ||
978            !on_path_p (hack->command) ||
979            !select_visual_of_hack (ssi, hack)))
980         {
981           if (++retry_count > (p->screenhacks_count*4))
982             {
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.)
987               */
988               if (p->verbose_p)
989                 fprintf(stderr,
990                       "%s: %d: no programs enabled, or no suitable visuals.\n",
991                         blurb(), ssi->number);
992               return;
993             }
994           else
995             goto AGAIN;
996         }
997
998       /* Turn off "next" and "prev" modes now, but "demo" mode is only
999          turned off by explicit action.
1000        */
1001       if (si->selection_mode < 0)
1002         si->selection_mode = 0;
1003
1004       forked = fork_and_exec (ssi, hack->command);
1005       switch ((int) forked)
1006         {
1007         case -1: /* fork failed */
1008         case 0:  /* child fork (can't happen) */
1009           sprintf (buf, "%s: couldn't fork", blurb());
1010           perror (buf);
1011           restore_real_vroot (si);
1012           saver_exit (si, 1, "couldn't fork");
1013           break;
1014
1015         default:
1016           ssi->pid = forked;
1017           break;
1018         }
1019     }
1020 }
1021
1022
1023 void
1024 spawn_screenhack (saver_info *si, Bool first_time_p)
1025 {
1026   if (monitor_powered_on_p (si))
1027     {
1028       int i;
1029       for (i = 0; i < si->nscreens; i++)
1030         {
1031           saver_screen_info *ssi = &si->screens[i];
1032           spawn_screenhack_1 (ssi, first_time_p);
1033         }
1034     }
1035   else if (si->prefs.verbose_p)
1036     fprintf (stderr,
1037              "%s: X says monitor has powered down; "
1038              "not launching a hack.\n", blurb());
1039
1040   store_saver_status (si);  /* store current hack numbers */
1041 }
1042
1043
1044 void
1045 kill_screenhack (saver_info *si)
1046 {
1047   int i;
1048   for (i = 0; i < si->nscreens; i++)
1049     {
1050       saver_screen_info *ssi = &si->screens[i];
1051       if (ssi->pid)
1052         kill_job (si, ssi->pid, SIGTERM);
1053       ssi->pid = 0;
1054     }
1055 }
1056
1057
1058 void
1059 suspend_screenhack (saver_info *si, Bool suspend_p)
1060 {
1061 #ifdef SIGSTOP  /* older VMS doesn't have it... */
1062   int i;
1063   for (i = 0; i < si->nscreens; i++)
1064     {
1065       saver_screen_info *ssi = &si->screens[i];
1066       if (ssi->pid)
1067         kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT));
1068     }
1069 #endif /* SIGSTOP */
1070 }
1071
1072
1073 /* Called when we're exiting abnormally, to kill off the subproc. */
1074 void
1075 emergency_kill_subproc (saver_info *si)
1076 {
1077   int i;
1078 #ifdef SIGCHLD
1079   signal (SIGCHLD, SIG_IGN);
1080 #endif /* SIGCHLD */
1081
1082   for (i = 0; i < si->nscreens; i++)
1083     {
1084       saver_screen_info *ssi = &si->screens[i];
1085       if (ssi->pid)
1086         {
1087           kill_job (si, ssi->pid, SIGTERM);
1088           ssi->pid = 0;
1089         }
1090     }
1091 }
1092
1093 Bool
1094 screenhack_running_p (saver_info *si)
1095 {
1096   Bool any_running_p = False;
1097   int i;
1098   for (i = 0; i < si->nscreens; i++)
1099     {
1100       saver_screen_info *ssi = &si->screens[i];
1101       if (ssi->pid) any_running_p = True;
1102     }
1103   return any_running_p;
1104 }
1105
1106 \f
1107 /* Environment variables. */
1108
1109
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.
1112  */
1113 void
1114 hack_environment (saver_info *si)
1115 {
1116 #if defined(HAVE_PUTENV) && defined(DEFAULT_PATH_PREFIX)
1117   static const char *def_path = DEFAULT_PATH_PREFIX;
1118   if (def_path && *def_path)
1119     {
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);
1126
1127       if (putenv (npath))
1128         abort ();
1129
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.
1133        */
1134     }
1135 #endif /* HAVE_PUTENV && DEFAULT_PATH_PREFIX */
1136 }
1137
1138
1139 void
1140 hack_subproc_environment (saver_screen_info *ssi)
1141 {
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.
1150
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.
1154    */
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);
1159   char *s, *c;
1160
1161   strcpy (ndpy, "DISPLAY=");
1162   s = ndpy + strlen(ndpy);
1163   strcpy (s, odpy);
1164
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 */
1174
1175   sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX",
1176            (unsigned long) ssi->screensaver_window);
1177
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. */
1180 #ifdef HAVE_PUTENV
1181   if (putenv (ndpy))
1182     abort ();
1183   if (putenv (nssw))
1184     abort ();
1185
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.
1189    */
1190 #endif /* HAVE_PUTENV */
1191 }
1192
1193 \f
1194 /* GL crap */
1195
1196 Visual *
1197 get_best_gl_visual (saver_screen_info *ssi)
1198 {
1199   saver_info *si = ssi->global;
1200   pid_t forked;
1201   int fds [2];
1202   int in, out;
1203   char buf[1024];
1204
1205   char *av[10];
1206   int ac = 0;
1207
1208   av[ac++] = "xscreensaver-gl-helper";
1209   av[ac] = 0;
1210
1211   if (pipe (fds))
1212     {
1213       perror ("error creating pipe:");
1214       return 0;
1215     }
1216
1217   in = fds [0];
1218   out = fds [1];
1219
1220   switch ((int) (forked = fork ()))
1221     {
1222     case -1:
1223       {
1224         sprintf (buf, "%s: couldn't fork", blurb());
1225         perror (buf);
1226         saver_exit (si, 1, 0);
1227       }
1228     case 0:
1229       {
1230         int stdout_fd = 1;
1231
1232         close (in);  /* don't need this one */
1233         close (ConnectionNumber (si->dpy));     /* close display fd */
1234
1235         if (dup2 (out, stdout_fd) < 0)          /* pipe stdout */
1236           {
1237             perror ("could not dup() a new stdout:");
1238             return 0;
1239           }
1240         hack_subproc_environment (ssi);         /* set $DISPLAY */
1241
1242         execvp (av[0], av);                     /* shouldn't return. */
1243
1244         if (errno != ENOENT /* || si->prefs.verbose_p */ )
1245           {
1246             /* Ignore "no such file or directory" errors.
1247                Issue all other exec errors, though. */
1248             sprintf (buf, "%s: running %s", blurb(), av[0]);
1249             perror (buf);
1250           }
1251         exit (1);                               /* exits fork */
1252         break;
1253       }
1254     default:
1255       {
1256         int result = 0;
1257         int wait_status = 0;
1258
1259         FILE *f = fdopen (in, "r");
1260         unsigned long v = 0;
1261         char c;
1262
1263         close (out);  /* don't need this one */
1264
1265         *buf = 0;
1266         if (! fgets (buf, sizeof(buf)-1, f))
1267           *buf = 0;
1268         fclose (f);
1269
1270         /* Wait for the child to die. */
1271         waitpid (-1, &wait_status, 0);
1272
1273         if (1 == sscanf (buf, "0x%lx %c", &v, &c))
1274           result = (int) v;
1275
1276         if (result == 0)
1277           {
1278             if (si->prefs.verbose_p)
1279               {
1280                 int L = strlen(buf);
1281                 fprintf (stderr, "%s: %s did not report a GL visual!\n",
1282                          blurb(), av[0]);
1283
1284                 if (L && buf[L-1] == '\n')
1285                   buf[--L] = 0;
1286                 if (*buf)
1287                   fprintf (stderr, "%s: %s said: \"%s\"\n",
1288                            blurb(), av[0], buf);
1289               }
1290             return 0;
1291           }
1292         else
1293           {
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,
1298                        av[0], result,
1299                        (v == ssi->default_visual ? " (default)" : ""));
1300             return v;
1301           }
1302       }
1303     }
1304
1305   abort();
1306 }
1307
1308
1309 \f
1310 /* Restarting the xscreensaver process from scratch. */
1311
1312 static char **saved_argv;
1313
1314 void
1315 save_argv (int argc, char **argv)
1316 {
1317   saved_argv = (char **) calloc (argc+2, sizeof (char *));
1318   saved_argv [argc] = 0;
1319   while (argc--)
1320     {
1321       int i = strlen (argv [argc]) + 1;
1322       saved_argv [argc] = (char *) malloc (i);
1323       memcpy (saved_argv [argc], argv [argc], i);
1324     }
1325 }
1326
1327
1328 /* Re-execs the process with the arguments in saved_argv.  Does not return.
1329  */
1330 void
1331 restart_process (saver_info *si)
1332 {
1333   fflush (stdout);
1334   fflush (stderr);
1335   shutdown_stderr (si);
1336   if (si->prefs.verbose_p)
1337     {
1338       int i;
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");
1343     }
1344   describe_uids (si, stderr);
1345   fprintf (stderr, "\n");
1346
1347   fflush (stdout);
1348   fflush (stderr);
1349   execvp (saved_argv [0], saved_argv);  /* shouldn't return */
1350   {
1351     char buf [512];
1352     sprintf (buf, "%s: could not restart process", blurb());
1353     perror(buf);
1354     fflush(stderr);
1355     abort();
1356   }
1357 }