ftp://ftp.krokus.ru/pub/OpenBSD/distfiles/xscreensaver-5.01.tar.gz
[xscreensaver] / driver / subprocs.c
1 /* subprocs.c --- choosing, spawning, and killing screenhacks.
2  * xscreensaver, Copyright (c) 1991-2006 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   sigset_t child_set;
364   sigemptyset (&child_set);
365   sigaddset (&child_set, SIGCHLD);
366   sigaddset (&child_set, SIGPIPE);
367   sigprocmask (SIG_BLOCK, &child_set, 0);
368 #endif /* HAVE_SIGACTION */
369
370   block_sigchld_handler++;
371
372 #ifdef HAVE_SIGACTION
373   return child_set;
374 #else  /* !HAVE_SIGACTION */
375   return 0;
376 #endif /* !HAVE_SIGACTION */
377 }
378
379 void
380 unblock_sigchld (void)
381 {
382 #ifdef HAVE_SIGACTION
383   sigset_t child_set;
384   sigemptyset(&child_set);
385   sigaddset(&child_set, SIGCHLD);
386   sigaddset(&child_set, SIGPIPE);
387   sigprocmask(SIG_UNBLOCK, &child_set, 0);
388 #endif /* HAVE_SIGACTION */
389
390   block_sigchld_handler--;
391 }
392
393 static int
394 kill_job (saver_info *si, pid_t pid, int signal)
395 {
396   saver_preferences *p = &si->prefs;
397   struct screenhack_job *job;
398   int status = -1;
399
400   clean_job_list();
401
402   if (block_sigchld_handler)
403     /* This function should not be called from the signal handler. */
404     abort();
405
406   block_sigchld();                      /* we control the horizontal... */
407
408   job = find_job (pid);
409   if (!job ||
410       !job->pid ||
411       job->status == job_killed)
412     {
413       if (p->verbose_p)
414         fprintf (stderr, "%s: no child %ld to signal!\n",
415                  blurb(), (long) pid);
416       goto DONE;
417     }
418
419   switch (signal) {
420   case SIGTERM: job->status = job_killed;  break;
421 #ifdef SIGSTOP
422     /* #### there must be a way to do this on VMS... */
423   case SIGSTOP: job->status = job_stopped; break;
424   case SIGCONT: job->status = job_running; break;
425 #endif /* SIGSTOP */
426   default: abort();
427   }
428
429   if (p->verbose_p)
430     fprintf (stderr, "%s: %d: %s pid %lu (%s)\n",
431              blurb(), job->screen,
432              (job->status == job_killed  ? "killing" :
433               job->status == job_stopped ? "suspending" : "resuming"),
434              (unsigned long) job->pid,
435              job->name);
436
437   status = kill (job->pid, signal);
438
439   if (p->verbose_p && status < 0)
440     {
441       if (errno == ESRCH)
442         fprintf (stderr,
443                  "%s: %d: child process %lu (%s) was already dead.\n",
444                  blurb(), job->screen, (unsigned long) job->pid, job->name);
445       else
446         {
447           char buf [1024];
448           sprintf (buf, "%s: %d: couldn't kill child process %lu (%s)",
449                    blurb(), job->screen, (unsigned long) job->pid, job->name);
450           perror (buf);
451         }
452     }
453
454   await_dying_children (si);
455
456  DONE:
457   unblock_sigchld();
458   if (block_sigchld_handler < 0)
459     abort();
460
461   clean_job_list();
462   return status;
463 }
464
465
466 #ifdef SIGCHLD
467 static RETSIGTYPE
468 sigchld_handler (int sig)
469 {
470   saver_info *si = global_si_kludge;    /* I hate C so much... */
471
472   if (si->prefs.debug_p)
473     {
474       /* Don't call fprintf() from signal handlers, as it might malloc.
475       fprintf(stderr, "%s: got SIGCHLD%s\n", blurb(),
476             (block_sigchld_handler ? " (blocked)" : ""));
477       */
478       write_string (STDERR_FILENO, blurb());
479       write_string (STDERR_FILENO, ": got SIGCHLD");
480
481       if (block_sigchld_handler)
482         write_string (STDERR_FILENO, " (blocked)\n");
483       else
484         write_string (STDERR_FILENO, "\n");
485     }
486
487   if (block_sigchld_handler < 0)
488     abort();
489   else if (block_sigchld_handler == 0)
490     {
491       block_sigchld();
492       await_dying_children (si);
493       unblock_sigchld();
494     }
495
496   init_sigchld();
497 }
498 #endif /* SIGCHLD */
499
500
501 #ifndef VMS
502
503 static void
504 await_dying_children (saver_info *si)
505 {
506   while (1)
507     {
508       int wait_status = 0;
509       pid_t kid;
510
511       errno = 0;
512       kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED);
513
514       if (si->prefs.debug_p)
515         {
516           if (kid < 0 && errno)
517             {
518               /* Don't call fprintf() from signal handlers, as it might malloc.
519               fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", blurb(),
520                        (long) kid, errno);
521                */
522               write_string (STDERR_FILENO, blurb());
523               write_string (STDERR_FILENO, ": waitpid(-1) ==> ");
524               write_long   (STDERR_FILENO, (long) kid);
525               write_string (STDERR_FILENO, " (");
526               write_long   (STDERR_FILENO, (long) errno);
527               write_string (STDERR_FILENO, ")\n");
528             }
529           else
530             {
531               /* Don't call fprintf() from signal handlers, as it might malloc.
532               fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", blurb(),
533                        (long) kid);
534                */
535               write_string (STDERR_FILENO, blurb());
536               write_string (STDERR_FILENO, ": waitpid(-1) ==> ");
537               write_long   (STDERR_FILENO, (long) kid);
538               write_string (STDERR_FILENO, "\n");
539             }
540         }
541
542       /* 0 means no more children to reap.
543          -1 means error -- except "interrupted system call" isn't a "real"
544          error, so if we get that, we should just try again. */
545       if (kid == 0 ||
546           (kid < 0 && errno != EINTR))
547         break;
548
549       describe_dead_child (si, kid, wait_status);
550     }
551 }
552
553
554 static void
555 describe_dead_child (saver_info *si, pid_t kid, int wait_status)
556 {
557   int i;
558   saver_preferences *p = &si->prefs;
559   struct screenhack_job *job = find_job (kid);
560   const char *name = job ? job->name : "<unknown>";
561   int screen_no = job ? job->screen : 0;
562
563   if (WIFEXITED (wait_status))
564     {
565       int exit_status = WEXITSTATUS (wait_status);
566
567       /* Treat exit code as a signed 8-bit quantity. */
568       if (exit_status & 0x80) exit_status |= ~0xFF;
569
570       /* One might assume that exiting with non-0 means something went wrong.
571          But that loser xswarm exits with the code that it was killed with, so
572          it *always* exits abnormally.  Treat abnormal exits as "normal" (don't
573          mention them) if we've just killed the subprocess.  But mention them
574          if they happen on their own.
575        */
576       if (!job ||
577           (exit_status != 0 &&
578            (p->verbose_p || job->status != job_killed)))
579         {
580           /* Don't call fprintf() from signal handlers, as it might malloc.
581           fprintf (stderr,
582                    "%s: %d: child pid %lu (%s) exited abnormally (code %d).\n",
583                    blurb(), screen_no, (unsigned long) kid, name, exit_status);
584            */
585           write_string (STDERR_FILENO, blurb());
586           write_string (STDERR_FILENO, ": ");
587           write_long   (STDERR_FILENO, (long) screen_no);
588           write_string (STDERR_FILENO, ": child pid ");
589           write_long   (STDERR_FILENO, (long) kid);
590           write_string (STDERR_FILENO, " (");
591           write_string (STDERR_FILENO, name);
592           write_string (STDERR_FILENO, ") exited abnormally (code ");
593           write_long   (STDERR_FILENO, (long) exit_status);
594           write_string (STDERR_FILENO, ").\n"); 
595         }
596       else if (p->verbose_p)
597         {
598           /* Don't call fprintf() from signal handlers, as it might malloc.
599           fprintf (stderr, "%s: %d: child pid %lu (%s) exited normally.\n",
600                    blurb(), screen_no, (unsigned long) kid, name);
601            */
602           write_string (STDERR_FILENO, blurb());
603           write_string (STDERR_FILENO, ": ");
604           write_long   (STDERR_FILENO, (long) screen_no);
605           write_string (STDERR_FILENO, ": child pid ");
606           write_long   (STDERR_FILENO, (long) kid);
607           write_string (STDERR_FILENO, " (");
608           write_string (STDERR_FILENO, name);
609           write_string (STDERR_FILENO, ") exited normally.\n");
610         }
611
612       if (job)
613         job->status = job_dead;
614     }
615   else if (WIFSIGNALED (wait_status))
616     {
617       if (p->verbose_p ||
618           !job ||
619           job->status != job_killed ||
620           WTERMSIG (wait_status) != SIGTERM)
621         {
622           /* Don't call fprintf() from signal handlers, as it might malloc.
623           fprintf (stderr, "%s: %d: child pid %lu (%s) terminated with %s.\n",
624                    blurb(), screen_no, (unsigned long) kid, name,
625                    signal_name (WTERMSIG(wait_status)));
626            */
627           write_string (STDERR_FILENO, blurb());
628           write_string (STDERR_FILENO, ": ");
629           write_long   (STDERR_FILENO, (long) screen_no);
630           write_string (STDERR_FILENO, ": child pid ");
631           write_long   (STDERR_FILENO, (long) kid);
632           write_string (STDERR_FILENO, " (");
633           write_string (STDERR_FILENO, name);
634           write_string (STDERR_FILENO, ") terminated with signal ");
635           write_long   (STDERR_FILENO, WTERMSIG(wait_status));
636           write_string (STDERR_FILENO, ".\n");
637         }
638
639       if (job)
640         job->status = job_dead;
641     }
642   else if (WIFSTOPPED (wait_status))
643     {
644       if (p->verbose_p)
645         {
646           /* Don't call fprintf() from signal handlers, as it might malloc.
647           fprintf (stderr, "%s: child pid %lu (%s) stopped with %s.\n",
648                    blurb(), (unsigned long) kid, name,
649                    signal_name (WSTOPSIG (wait_status)));
650            */
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, ") stopped with signal ");
659           write_long   (STDERR_FILENO, WSTOPSIG(wait_status));
660           write_string (STDERR_FILENO, ".\n");
661         }
662
663       if (job)
664         job->status = job_stopped;
665     }
666   else
667     {
668       /* Don't call fprintf() from signal handlers, as it might malloc.
669       fprintf (stderr, "%s: child pid %lu (%s) died in a mysterious way!",
670                blurb(), (unsigned long) kid, name);
671        */
672       write_string (STDERR_FILENO, blurb());
673       write_string (STDERR_FILENO, ": ");
674       write_long   (STDERR_FILENO, (long) screen_no);
675       write_string (STDERR_FILENO, ": child pid ");
676       write_long   (STDERR_FILENO, (long) kid);
677       write_string (STDERR_FILENO, " (");
678       write_string (STDERR_FILENO, name);
679       write_string (STDERR_FILENO, ") died in a mysterious way!");
680       if (job)
681         job->status = job_dead;
682     }
683
684   /* Clear out the pid so that screenhack_running_p() knows it's dead.
685    */
686   if (!job || job->status == job_dead)
687     for (i = 0; i < si->nscreens; i++)
688       {
689         saver_screen_info *ssi = &si->screens[i];
690         if (kid == ssi->pid)
691           ssi->pid = 0;
692       }
693 }
694
695 #else  /* VMS */
696 static void await_dying_children (saver_info *si) { return; }
697 #endif /* VMS */
698
699
700 void
701 init_sigchld (void)
702 {
703 #ifdef SIGCHLD
704
705 # ifdef HAVE_SIGACTION  /* Thanks to Tom Kelly <tom@ancilla.toronto.on.ca> */
706
707   static Bool sigchld_initialized_p = 0;
708   if (!sigchld_initialized_p)
709     {
710       struct sigaction action, old;
711
712       action.sa_handler = sigchld_handler;
713       sigemptyset(&action.sa_mask);
714       action.sa_flags = 0;
715
716       if (sigaction(SIGCHLD, &action, &old) < 0)
717         {
718           char buf [255];
719           sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
720           perror (buf);
721         }
722       sigchld_initialized_p = True;
723     }
724
725 # else  /* !HAVE_SIGACTION */
726
727   if (((long) signal (SIGCHLD, sigchld_handler)) == -1L)
728     {
729       char buf [255];
730       sprintf (buf, "%s: couldn't catch SIGCHLD", blurb());
731       perror (buf);
732     }
733 # endif /* !HAVE_SIGACTION */
734 #endif /* SIGCHLD */
735 }
736
737
738
739 \f
740
741 static Bool
742 select_visual_of_hack (saver_screen_info *ssi, screenhack *hack)
743 {
744   saver_info *si = ssi->global;
745   saver_preferences *p = &si->prefs;
746   Bool selected;
747
748   if (hack->visual && *hack->visual)
749     selected = select_visual(ssi, hack->visual);
750   else
751     selected = select_visual(ssi, 0);
752
753   if (!selected && (p->verbose_p || si->demoing_p))
754     fprintf (stderr,
755              (si->demoing_p
756               ? "%s: warning, no \"%s\" visual for \"%s\".\n"
757               : "%s: no \"%s\" visual; skipping \"%s\".\n"),
758              blurb(),
759              (hack->visual && *hack->visual ? hack->visual : "???"),
760              hack->command);
761
762   return selected;
763 }
764
765
766 static void
767 print_path_error (const char *program)
768 {
769   char buf [512];
770   char *cmd = strdup (program);
771   char *token = strchr (cmd, ' ');
772
773   if (token) *token = 0;
774   sprintf (buf, "%s: could not execute \"%.100s\"", blurb(), cmd);
775   free (cmd);
776   perror (buf);
777
778   if (errno == ENOENT &&
779       (token = getenv("PATH")))
780     {
781 # ifndef PATH_MAX
782 #  ifdef MAXPATHLEN
783 #   define PATH_MAX MAXPATHLEN
784 #  else
785 #   define PATH_MAX 2048
786 #  endif
787 # endif
788       char path[PATH_MAX];
789       fprintf (stderr, "\n");
790       *path = 0;
791 # if defined(HAVE_GETCWD)
792       if (! getcwd (path, sizeof(path)))
793         *path = 0;
794 # elif defined(HAVE_GETWD)
795       getwd (path);
796 # endif
797       if (*path)
798         fprintf (stderr, "    Current directory is: %s\n", path);
799       fprintf (stderr, "    PATH is:\n");
800       token = strtok (strdup(token), ":");
801       while (token)
802         {
803           fprintf (stderr, "        %s\n", token);
804           token = strtok(0, ":");
805         }
806       fprintf (stderr, "\n");
807     }
808 }
809
810
811 /* Executes the command in another process.
812    Command may be any single command acceptable to /bin/sh.
813    It may include wildcards, but no semicolons.
814    If successful, the pid of the other process is returned.
815    Otherwise, -1 is returned and an error may have been
816    printed to stderr.
817  */
818 pid_t
819 fork_and_exec (saver_screen_info *ssi, const char *command)
820 {
821   saver_info *si = ssi->global;
822   saver_preferences *p = &si->prefs;
823   pid_t forked;
824
825   switch ((int) (forked = fork ()))
826     {
827     case -1:
828       {
829         char buf [255];
830         sprintf (buf, "%s: couldn't fork", blurb());
831         perror (buf);
832         break;
833       }
834
835     case 0:
836       close (ConnectionNumber (si->dpy));       /* close display fd */
837       limit_subproc_memory (p->inferior_memory_limit, p->verbose_p);
838       hack_subproc_environment (ssi);           /* set $DISPLAY */
839
840       if (p->verbose_p)
841         fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n",
842                  blurb(), ssi->number, command,
843                  (unsigned long) getpid ());
844
845       exec_command (p->shell, command, p->nice_inferior);
846
847       /* If that returned, we were unable to exec the subprocess.
848          Print an error message, if desired.
849        */
850       if (! p->ignore_uninstalled_p)
851         print_path_error (command);
852
853       exit (1);  /* exits child fork */
854       break;
855
856     default:    /* parent */
857       (void) make_job (forked, ssi->number, command);
858       break;
859     }
860
861   return forked;
862 }
863
864
865 static void
866 spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p)
867 {
868   saver_info *si = ssi->global;
869   saver_preferences *p = &si->prefs;
870   raise_window (si, first_time_p, True, False);
871   XFlush (si->dpy);
872
873   if (p->screenhacks_count)
874     {
875       screenhack *hack;
876       pid_t forked;
877       char buf [255];
878       int new_hack = -1;
879       int retry_count = 0;
880       Bool force = False;
881
882     AGAIN:
883
884       if (p->screenhacks_count < 1)
885         {
886           /* No hacks at all */
887           new_hack = -1;
888         }
889       else if (p->screenhacks_count == 1)
890         {
891           /* Exactly one hack in the list */
892           new_hack = 0;
893         }
894       else if (si->selection_mode == -1)
895         {
896           /* Select the next hack, wrapping. */
897           new_hack = (ssi->current_hack + 1) % p->screenhacks_count;
898         }
899       else if (si->selection_mode == -2)
900         {
901           /* Select the previous hack, wrapping. */
902           if (ssi->current_hack < 0)
903             new_hack = p->screenhacks_count - 1;
904           else
905             new_hack = ((ssi->current_hack + p->screenhacks_count - 1)
906                         % p->screenhacks_count);
907         }
908       else if (si->selection_mode > 0)
909         {
910           /* Select a specific hack, by number (via the ACTIVATE command.) */
911           new_hack = ((si->selection_mode - 1) % p->screenhacks_count);
912           force = True;
913         }
914       else if (p->mode == ONE_HACK &&
915                p->selected_hack >= 0)
916         {
917           /* Select a specific hack, by number (via "One Saver" mode.) */
918           new_hack = p->selected_hack;
919           force = True;
920         }
921       else if (p->mode == BLANK_ONLY || p->mode == DONT_BLANK)
922         {
923           new_hack = -1;
924         }
925       else if (p->mode == RANDOM_HACKS_SAME &&
926                ssi->number != 0)
927         {
928           /* Use the same hack that's running on screen 0.
929              (Assumes this function was called on screen 0 first.)
930            */
931           new_hack = si->screens[0].current_hack;
932         }
933       else  /* (p->mode == RANDOM_HACKS) */
934         {
935           /* Select a random hack (but not the one we just ran.) */
936           while ((new_hack = random () % p->screenhacks_count)
937                  == ssi->current_hack)
938             ;
939         }
940
941       if (new_hack < 0)   /* don't run a hack */
942         {
943           ssi->current_hack = -1;
944           if (si->selection_mode < 0)
945             si->selection_mode = 0;
946           return;
947         }
948
949       ssi->current_hack = new_hack;
950       hack = p->screenhacks[ssi->current_hack];
951
952       /* If the hack is disabled, or there is no visual for this hack,
953          then try again (move forward, or backward, or re-randomize.)
954          Unless this hack was specified explicitly, in which case,
955          use it regardless.
956        */
957       if (force)
958         select_visual_of_hack (ssi, hack);
959         
960       if (!force &&
961           (!hack->enabled_p ||
962            !on_path_p (hack->command) ||
963            !select_visual_of_hack (ssi, hack)))
964         {
965           if (++retry_count > (p->screenhacks_count*4))
966             {
967               /* Uh, oops.  Odds are, there are no suitable visuals,
968                  and we're looping.  Give up.  (This is totally lame,
969                  what we should do is make a list of suitable hacks at
970                  the beginning, then only loop over them.)
971               */
972               if (p->verbose_p)
973                 fprintf(stderr,
974                       "%s: %d: no programs enabled, or no suitable visuals.\n",
975                         blurb(), ssi->number);
976               return;
977             }
978           else
979             goto AGAIN;
980         }
981
982       /* Turn off "next" and "prev" modes now, but "demo" mode is only
983          turned off by explicit action.
984        */
985       if (si->selection_mode < 0)
986         si->selection_mode = 0;
987
988       forked = fork_and_exec (ssi, hack->command);
989       switch ((int) forked)
990         {
991         case -1: /* fork failed */
992         case 0:  /* child fork (can't happen) */
993           sprintf (buf, "%s: couldn't fork", blurb());
994           perror (buf);
995           restore_real_vroot (si);
996           saver_exit (si, 1, "couldn't fork");
997           break;
998
999         default:
1000           ssi->pid = forked;
1001           break;
1002         }
1003     }
1004 }
1005
1006
1007 void
1008 spawn_screenhack (saver_info *si, Bool first_time_p)
1009 {
1010   if (monitor_powered_on_p (si))
1011     {
1012       int i;
1013       for (i = 0; i < si->nscreens; i++)
1014         {
1015           saver_screen_info *ssi = &si->screens[i];
1016           spawn_screenhack_1 (ssi, first_time_p);
1017         }
1018     }
1019   else if (si->prefs.verbose_p)
1020     fprintf (stderr,
1021              "%s: X says monitor has powered down; "
1022              "not launching a hack.\n", blurb());
1023
1024   store_saver_status (si);  /* store current hack numbers */
1025 }
1026
1027
1028 void
1029 kill_screenhack (saver_info *si)
1030 {
1031   int i;
1032   for (i = 0; i < si->nscreens; i++)
1033     {
1034       saver_screen_info *ssi = &si->screens[i];
1035       if (ssi->pid)
1036         kill_job (si, ssi->pid, SIGTERM);
1037       ssi->pid = 0;
1038     }
1039 }
1040
1041
1042 void
1043 suspend_screenhack (saver_info *si, Bool suspend_p)
1044 {
1045 #ifdef SIGSTOP  /* older VMS doesn't have it... */
1046   int i;
1047   for (i = 0; i < si->nscreens; i++)
1048     {
1049       saver_screen_info *ssi = &si->screens[i];
1050       if (ssi->pid)
1051         kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT));
1052     }
1053 #endif /* SIGSTOP */
1054 }
1055
1056
1057 /* Called when we're exiting abnormally, to kill off the subproc. */
1058 void
1059 emergency_kill_subproc (saver_info *si)
1060 {
1061   int i;
1062 #ifdef SIGCHLD
1063   signal (SIGCHLD, SIG_IGN);
1064 #endif /* SIGCHLD */
1065
1066   for (i = 0; i < si->nscreens; i++)
1067     {
1068       saver_screen_info *ssi = &si->screens[i];
1069       if (ssi->pid)
1070         {
1071           kill_job (si, ssi->pid, SIGTERM);
1072           ssi->pid = 0;
1073         }
1074     }
1075 }
1076
1077 Bool
1078 screenhack_running_p (saver_info *si)
1079 {
1080   Bool any_running_p = False;
1081   int i;
1082   for (i = 0; i < si->nscreens; i++)
1083     {
1084       saver_screen_info *ssi = &si->screens[i];
1085       if (ssi->pid) any_running_p = True;
1086     }
1087   return any_running_p;
1088 }
1089
1090 \f
1091 /* Environment variables. */
1092
1093
1094 /* Modifies $PATH in the current environment, so that if DEFAULT_PATH_PREFIX
1095    is defined, the xscreensaver daemon will search that directory for hacks.
1096  */
1097 void
1098 hack_environment (saver_info *si)
1099 {
1100 #if defined(HAVE_PUTENV) && defined(DEFAULT_PATH_PREFIX)
1101   static const char *def_path = DEFAULT_PATH_PREFIX;
1102   if (def_path && *def_path)
1103     {
1104       const char *opath = getenv("PATH");
1105       char *npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20);
1106       strcpy (npath, "PATH=");
1107       strcat (npath, def_path);
1108       strcat (npath, ":");
1109       strcat (npath, opath);
1110
1111       if (putenv (npath))
1112         abort ();
1113
1114       /* don't free (npath) -- some implementations of putenv (BSD 4.4,
1115          glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
1116          do not.  So we must leak it (and/or the previous setting). Yay.
1117        */
1118     }
1119 #endif /* HAVE_PUTENV && DEFAULT_PATH_PREFIX */
1120 }
1121
1122
1123 void
1124 hack_subproc_environment (saver_screen_info *ssi)
1125 {
1126   /* Store $DISPLAY into the environment, so that the $DISPLAY variable that
1127      the spawned processes inherit is correct.  First, it must be on the same
1128      host and display as the value of -display passed in on our command line
1129      (which is not necessarily the same as what our $DISPLAY variable is.)
1130      Second, the screen number in the $DISPLAY passed to the subprocess should
1131      be the screen on which this particular hack is running -- not the display
1132      specification which the driver itself is using, since the driver ignores
1133      its screen number and manages all existing screens.
1134
1135      Likewise, store a window ID in $XSCREENSAVER_WINDOW -- this will allow
1136      us to (eventually) run multiple hacks in Xinerama mode, where each hack
1137      has the same $DISPLAY but a different piece of glass.
1138    */
1139   saver_info *si = ssi->global;
1140   const char *odpy = DisplayString (si->dpy);
1141   char *ndpy = (char *) malloc (strlen(odpy) + 20);
1142   char *nssw = (char *) malloc (40);
1143   char *s, *c;
1144
1145   strcpy (ndpy, "DISPLAY=");
1146   s = ndpy + strlen(ndpy);
1147   strcpy (s, odpy);
1148
1149   /* We have to find the last colon since it is the boundary between
1150      hostname & screen - IPv6 numeric format addresses may have many
1151      colons before that point, and DECnet addresses always have two colons */
1152   c = strrchr(s,':');                           /* skip to last colon */
1153   if (c != NULL) s = c+1;
1154   while (isdigit(*s)) s++;                      /* skip over dpy number */
1155   while (*s == '.') s++;                        /* skip over dot */
1156   if (s[-1] != '.') *s++ = '.';                 /* put on a dot */
1157   sprintf(s, "%d", ssi->real_screen_number);    /* put on screen number */
1158
1159   sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX",
1160            (unsigned long) ssi->screensaver_window);
1161
1162   /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
1163      any more, right?  It's not Posix, but everyone seems to have it. */
1164 #ifdef HAVE_PUTENV
1165   if (putenv (ndpy))
1166     abort ();
1167   if (putenv (nssw))
1168     abort ();
1169
1170   /* don't free ndpy/nssw -- some implementations of putenv (BSD 4.4,
1171      glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
1172      do not.  So we must leak it (and/or the previous setting). Yay.
1173    */
1174 #endif /* HAVE_PUTENV */
1175 }
1176
1177 \f
1178 /* GL crap */
1179
1180 Visual *
1181 get_best_gl_visual (saver_screen_info *ssi)
1182 {
1183   saver_info *si = ssi->global;
1184   pid_t forked;
1185   int fds [2];
1186   int in, out;
1187   char buf[1024];
1188
1189   char *av[10];
1190   int ac = 0;
1191
1192   av[ac++] = "xscreensaver-gl-helper";
1193   av[ac] = 0;
1194
1195   if (pipe (fds))
1196     {
1197       perror ("error creating pipe:");
1198       return 0;
1199     }
1200
1201   in = fds [0];
1202   out = fds [1];
1203
1204   switch ((int) (forked = fork ()))
1205     {
1206     case -1:
1207       {
1208         sprintf (buf, "%s: couldn't fork", blurb());
1209         perror (buf);
1210         saver_exit (si, 1, 0);
1211       }
1212     case 0:
1213       {
1214         int stdout_fd = 1;
1215
1216         close (in);  /* don't need this one */
1217         close (ConnectionNumber (si->dpy));     /* close display fd */
1218
1219         if (dup2 (out, stdout_fd) < 0)          /* pipe stdout */
1220           {
1221             perror ("could not dup() a new stdout:");
1222             return 0;
1223           }
1224         hack_subproc_environment (ssi);         /* set $DISPLAY */
1225
1226         execvp (av[0], av);                     /* shouldn't return. */
1227
1228         if (errno != ENOENT || si->prefs.verbose_p)
1229           {
1230             /* Ignore "no such file or directory" errors, unless verbose.
1231                Issue all other exec errors, though. */
1232             sprintf (buf, "%s: running %s", blurb(), av[0]);
1233             perror (buf);
1234           }
1235         exit (1);                               /* exits fork */
1236         break;
1237       }
1238     default:
1239       {
1240         int result = 0;
1241         int wait_status = 0;
1242
1243         FILE *f = fdopen (in, "r");
1244         unsigned long v = 0;
1245         char c;
1246
1247         close (out);  /* don't need this one */
1248
1249         *buf = 0;
1250         if (! fgets (buf, sizeof(buf)-1, f))
1251           *buf = 0;
1252         fclose (f);
1253
1254         /* Wait for the child to die. */
1255         waitpid (-1, &wait_status, 0);
1256
1257         if (1 == sscanf (buf, "0x%lx %c", &v, &c))
1258           result = (int) v;
1259
1260         if (result == 0)
1261           {
1262             if (si->prefs.verbose_p)
1263               {
1264                 int L = strlen(buf);
1265                 fprintf (stderr, "%s: %s did not report a GL visual!\n",
1266                          blurb(), av[0]);
1267
1268                 if (L && buf[L-1] == '\n')
1269                   buf[--L] = 0;
1270                 if (*buf)
1271                   fprintf (stderr, "%s: %s said: \"%s\"\n",
1272                            blurb(), av[0], buf);
1273               }
1274             return 0;
1275           }
1276         else
1277           {
1278             Visual *v = id_to_visual (ssi->screen, result);
1279             if (si->prefs.verbose_p)
1280               fprintf (stderr, "%s: %d: %s: GL visual is 0x%X%s.\n",
1281                        blurb(), ssi->number,
1282                        av[0], result,
1283                        (v == ssi->default_visual ? " (default)" : ""));
1284             return v;
1285           }
1286       }
1287     }
1288
1289   abort();
1290 }
1291
1292
1293 \f
1294 /* Restarting the xscreensaver process from scratch. */
1295
1296 static char **saved_argv;
1297
1298 void
1299 save_argv (int argc, char **argv)
1300 {
1301   saved_argv = (char **) calloc (argc+2, sizeof (char *));
1302   saved_argv [argc] = 0;
1303   while (argc--)
1304     {
1305       int i = strlen (argv [argc]) + 1;
1306       saved_argv [argc] = (char *) malloc (i);
1307       memcpy (saved_argv [argc], argv [argc], i);
1308     }
1309 }
1310
1311
1312 /* Re-execs the process with the arguments in saved_argv.  Does not return.
1313  */
1314 void
1315 restart_process (saver_info *si)
1316 {
1317   fflush (stdout);
1318   fflush (stderr);
1319   shutdown_stderr (si);
1320   if (si->prefs.verbose_p)
1321     {
1322       int i;
1323       fprintf (stderr, "%s: re-executing", blurb());
1324       for (i = 0; saved_argv[i]; i++)
1325         fprintf (stderr, " %s", saved_argv[i]);
1326       fprintf (stderr, "\n");
1327     }
1328   describe_uids (si, stderr);
1329   fprintf (stderr, "\n");
1330
1331   fflush (stdout);
1332   fflush (stderr);
1333   execvp (saved_argv [0], saved_argv);  /* shouldn't return */
1334   {
1335     char buf [512];
1336     sprintf (buf, "%s: could not restart process", blurb());
1337     perror(buf);
1338     fflush(stderr);
1339     abort();
1340   }
1341 }