73
71
extern saver_info *global_si_kludge; /* I hate C so much... */
76
nice_subproc (int nice_level)
81
#if defined(HAVE_NICE)
83
int old_nice = nice (0);
84
int n = nice_level - old_nice;
86
if (nice (n) == -1 && errno != 0)
89
sprintf (buf, "%s: nice(%d) failed", blurb(), n);
93
#elif defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS)
94
if (setpriority (PRIO_PROCESS, getpid(), nice_level) != 0)
97
sprintf (buf, "%s: setpriority(PRIO_PROCESS, %lu, %d) failed",
98
blurb(), (unsigned long) getpid(), nice_level);
103
"%s: don't know how to change process priority on this system.\n",
110
74
/* RLIMIT_AS (called RLIMIT_VMEM on some systems) controls the maximum size
111
75
of a process's address space, i.e., the maximal brk(2) and mmap(2) values.
112
76
Setting this lets you put a cap on how much memory a process can allocate.
78
Except the "and mmap()" part kinda makes this useless, since many GL
79
implementations end up using mmap() to pull the whole frame buffer into
80
memory (or something along those lines) making it appear processes are
81
using hundreds of megabytes when in fact they're using very little, and
82
we end up capping their mallocs prematurely. YAY!
114
84
#if defined(RLIMIT_VMEM) && !defined(RLIMIT_AS)
115
85
# define RLIMIT_AS RLIMIT_VMEM
163
139
#endif /* HAVE_SETRLIMIT && RLIMIT_AS */
171
exec_simple_command (const char *command)
175
char *token = strtok (strdup(command), " \t");
179
token = strtok(0, " \t");
183
execvp (av[0], av); /* shouldn't return. */
187
sprintf (buf, "%s: could not execute \"%s\"", blurb(), av[0]);
190
if (errno == ENOENT &&
191
(token = getenv("PATH")))
195
# define PATH_MAX MAXPATHLEN
197
# define PATH_MAX 2048
201
fprintf (stderr, "\n");
203
# if defined(HAVE_GETCWD)
204
getcwd (path, sizeof(path));
205
# elif defined(HAVE_GETWD)
209
fprintf (stderr, " Current directory is: %s\n", path);
210
fprintf (stderr, " PATH is:\n");
211
token = strtok (strdup(token), ":");
214
fprintf (stderr, " %s\n", token);
215
token = strtok(0, ":");
217
fprintf (stderr, "\n");
222
exit (1); /* Note that this only exits a child fork. */
227
exec_complex_command (const char *shell, const char *command)
231
char *command2 = (char *) malloc (strlen (command) + 10);
234
const char *after_vars;
236
/* Skip leading whitespace.
238
while (*command == ' ' || *command == '\t')
241
/* If the string has a series of tokens with "=" in them at them, set
242
`after_vars' to point into the string after those tokens and any
243
trailing whitespace. Otherwise, after_vars == command.
245
after_vars = command;
246
for (s = command; *s; s++)
248
if (*s == '=') got_eq = 1;
253
while (*s == ' ' || *s == '\t')
264
strncat (command2, command, after_vars - command);
265
strcat (command2, "exec ");
266
strcat (command2, after_vars);
268
/* We have now done these transformations:
269
"foo -x -y" ==> "exec foo -x -y"
270
"BLAT=foop foo -x" ==> "BLAT=foop exec foo -x"
271
"BLAT=foop A=b foo -x" ==> "BLAT=foop A=b exec foo -x"
275
/* Invoke the shell as "/bin/sh -c 'exec prog -arg -arg ...'" */
276
av [ac++] = (char *) shell;
278
av [ac++] = command2;
281
execvp (av[0], av); /* shouldn't return. */
285
sprintf (buf, "%s: execvp(\"%s\") failed", blurb(), av[0]);
289
exit (1); /* Note that this only exits a child fork. */
296
exec_vms_command (const char *command)
301
exit (1); /* Note that this only exits a child fork. */
308
exec_screenhack (saver_info *si, const char *command)
310
/* I don't believe what a sorry excuse for an operating system UNIX is!
312
- I want to spawn a process.
313
- I want to know it's pid so that I can kill it.
314
- I would like to receive a message when it dies of natural causes.
315
- I want the spawned process to have user-specified arguments.
317
If shell metacharacters are present (wildcards, backquotes, etc), the
318
only way to parse those arguments is to run a shell to do the parsing
321
And the only way to know the pid of the process is to fork() and exec()
322
it in the spawned side of the fork.
324
But if you're running a shell to parse your arguments, this gives you
325
the pid of the *shell*, not the pid of the *process* that you're
326
actually interested in, which is an *inferior* of the shell. This also
327
means that the SIGCHLD you get applies to the shell, not its inferior.
328
(Why isn't that sufficient? I don't remember any more, but it turns
331
So, the only solution, when metacharacters are present, is to force the
332
shell to exec() its inferior. What a fucking hack! We prepend "exec "
333
to the command string, and hope it doesn't contain unquoted semicolons
334
or ampersands (we don't search for them, because we don't want to
335
prohibit their use in quoted strings (messages, for example) and parsing
336
out the various quote characters is too much of a pain.)
338
(Actually, Clint Wong <clint@jts.com> points out that process groups
339
might be used to take care of this problem; this may be worth considering
340
some day, except that, 1: this code works now, so why fix it, and 2: from
341
what I've seen in Emacs, dealing with process groups isn't especially
344
saver_preferences *p = &si->prefs;
347
Bool hairy_p = !!strpbrk (command, "*?$&!<>[];`'\\\"=");
348
/* note: = is in the above because of the sh syntax "FOO=bar cmd". */
350
if (getuid() == (uid_t) 0 || geteuid() == (uid_t) 0)
352
/* If you're thinking of commenting this out, think again.
353
If you do so, you will open a security hole. Mail jwz
354
so that he may enlighten you as to the error of your ways.
356
fprintf (stderr, "%s: we're still running as root! Disaster!\n",
358
saver_exit (si, 1, 0);
362
fprintf (stderr, "%s: spawning \"%s\" in pid %lu%s.\n",
363
blurb(), command, (unsigned long) getpid (),
364
(hairy_p ? " (via shell)" : ""));
367
/* If it contains any shell metacharacters, do it the hard way,
368
and fork a shell to parse the arguments for us. */
369
exec_complex_command (p->shell, command);
371
/* Otherwise, we can just exec the program directly. */
372
exec_simple_command (command);
376
fprintf (stderr, "%s: spawning \"%s\" in pid %lu.\n",
377
blurb(), command, getpid());
378
exec_vms_command (command);
381
abort(); /* that shouldn't have returned. */
386
143
/* Management of child processes, and de-zombification.
596
368
default: abort();
601
fprintf (stderr, "%s: %s pid %lu.\n", blurb(),
602
(signal == SIGTERM ? "killing" :
603
signal == SIGSTOP ? "suspending" :
604
signal == SIGCONT ? "resuming" : "signalling"),
605
(unsigned long) job->pid);
608
fprintf (stderr, "%s: %s pid %lu.\n", blurb(), "killing",
609
(unsigned long) job->pid);
610
#endif /* !SIGSTOP */
372
fprintf (stderr, "%s: %d: %s pid %lu (%s)\n",
373
blurb(), job->screen,
374
(job->status == job_killed ? "killing" :
375
job->status == job_stopped ? "suspending" : "resuming"),
376
(unsigned long) job->pid,
612
379
status = kill (job->pid, signal);
614
381
if (p->verbose_p && status < 0)
616
383
if (errno == ESRCH)
617
fprintf (stderr, "%s: child process %lu (%s) was already dead.\n",
618
blurb(), job->pid, job->name);
385
"%s: %d: child process %lu (%s) was already dead.\n",
386
blurb(), job->screen, (unsigned long) job->pid, job->name);
622
sprintf (buf, "%s: couldn't kill child process %lu (%s)",
623
blurb(), job->pid, job->name);
390
sprintf (buf, "%s: %d: couldn't kill child process %lu (%s)",
391
blurb(), job->screen, (unsigned long) job->pid, job->name);
615
print_path_error (const char *program)
618
char *cmd = strdup (program);
619
char *token = strchr (cmd, ' ');
621
if (token) *token = 0;
622
sprintf (buf, "%s: could not execute \"%.100s\"", blurb(), cmd);
626
if (errno == ENOENT &&
627
(token = getenv("PATH")))
631
# define PATH_MAX MAXPATHLEN
633
# define PATH_MAX 2048
637
fprintf (stderr, "\n");
639
# if defined(HAVE_GETCWD)
640
getcwd (path, sizeof(path));
641
# elif defined(HAVE_GETWD)
645
fprintf (stderr, " Current directory is: %s\n", path);
646
fprintf (stderr, " PATH is:\n");
647
token = strtok (strdup(token), ":");
650
fprintf (stderr, " %s\n", token);
651
token = strtok(0, ":");
653
fprintf (stderr, "\n");
658
/* Executes the command in another process.
659
Command may be any single command acceptable to /bin/sh.
660
It may include wildcards, but no semicolons.
661
If successful, the pid of the other process is returned.
662
Otherwise, -1 is returned and an error may have been
666
fork_and_exec (saver_screen_info *ssi, const char *command)
668
saver_info *si = ssi->global;
669
saver_preferences *p = &si->prefs;
672
switch ((int) (forked = fork ()))
677
sprintf (buf, "%s: couldn't fork", blurb());
683
close (ConnectionNumber (si->dpy)); /* close display fd */
684
limit_subproc_memory (p->inferior_memory_limit, p->verbose_p);
685
hack_subproc_environment (ssi); /* set $DISPLAY */
688
fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n",
689
blurb(), ssi->number, command,
690
(unsigned long) getpid ());
692
exec_command (p->shell, command, p->nice_inferior);
694
/* If that returned, we were unable to exec the subprocess.
695
Print an error message, if desired.
697
if (! p->ignore_uninstalled_p)
698
print_path_error (command);
700
exit (1); /* exits child fork */
703
default: /* parent */
704
(void) make_job (forked, ssi->number, command);
846
713
spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p)
848
715
saver_info *si = ssi->global;
855
722
screenhack *hack;
859
726
int retry_count = 0;
860
727
Bool force = False;
864
if (p->screenhacks_count == 1)
865
/* If there is only one hack in the list, there is no choice. */
731
if (p->screenhacks_count < 1)
733
/* No hacks at all */
736
else if (p->screenhacks_count == 1)
738
/* Exactly one hack in the list */
868
741
else if (si->selection_mode == -1)
869
/* Select the next hack, wrapping. */
870
new_hack = (ssi->current_hack + 1) % p->screenhacks_count;
743
/* Select the next hack, wrapping. */
744
new_hack = (ssi->current_hack + 1) % p->screenhacks_count;
872
746
else if (si->selection_mode == -2)
873
/* Select the previous hack, wrapping. */
874
new_hack = ((ssi->current_hack + p->screenhacks_count - 1)
875
% p->screenhacks_count);
748
/* Select the previous hack, wrapping. */
749
if (ssi->current_hack < 0)
750
new_hack = p->screenhacks_count - 1;
752
new_hack = ((ssi->current_hack + p->screenhacks_count - 1)
753
% p->screenhacks_count);
877
755
else if (si->selection_mode > 0)
878
/* Select a specific hack, by number. No negotiation. */
757
/* Select a specific hack, by number (via the ACTIVATE command.) */
880
758
new_hack = ((si->selection_mode - 1) % p->screenhacks_count);
761
else if (p->mode == ONE_HACK &&
762
p->selected_hack >= 0)
764
/* Select a specific hack, by number (via "One Saver" mode.) */
765
new_hack = p->selected_hack;
768
else if (p->mode == BLANK_ONLY || p->mode == DONT_BLANK)
772
else if (p->mode == RANDOM_HACKS_SAME &&
775
/* Use the same hack that's running on screen 0.
776
(Assumes this function was called on screen 0 first.)
778
ssi->current_hack = si->screens[0].current_hack;
780
else /* (p->mode == RANDOM_HACKS) */
885
782
/* Select a random hack (but not the one we just ran.) */
886
783
while ((new_hack = random () % p->screenhacks_count)
1183
1096
/* Wait for the child to die. */
1184
1097
waitpid (-1, &wait_status, 0);
1186
if (1 == sscanf (buf, "0x%x %c", &v, &c))
1099
if (1 == sscanf (buf, "0x%lx %c", &v, &c))
1187
1100
result = (int) v;
1189
1102
if (result == 0)
1191
1104
if (si->prefs.verbose_p)
1192
fprintf (stderr, "%s: %s did not report a GL visual!\n",
1106
int L = strlen(buf);
1107
fprintf (stderr, "%s: %s did not report a GL visual!\n",
1110
if (L && buf[L-1] == '\n')
1113
fprintf (stderr, "%s: %s said: \"%s\"\n",
1114
blurb(), av[0], buf);
1198
1120
Visual *v = id_to_visual (ssi->screen, result);
1199
1121
if (si->prefs.verbose_p)
1200
fprintf (stderr, "%s: %s says the GL visual is 0x%X%s.\n",
1201
blurb(), av[0], result,
1202
(v == ssi->default_visual ? " (the default)" : ""));
1122
fprintf (stderr, "%s: %d: %s: GL visual is 0x%X%s.\n",
1123
blurb(), ssi->number,
1125
(v == ssi->default_visual ? " (default)" : ""));
1231
/* Re-execs the process with the arguments in saved_argv.
1232
Does not return unless there was an error.
1154
/* Re-execs the process with the arguments in saved_argv. Does not return.
1235
1157
restart_process (saver_info *si)
1161
shutdown_stderr (si);
1237
1162
if (si->prefs.verbose_p)
1240
fprintf (real_stderr, "%s: re-executing", blurb());
1165
fprintf (stderr, "%s: re-executing", blurb());
1241
1166
for (i = 0; saved_argv[i]; i++)
1242
fprintf (real_stderr, " %s", saved_argv[i]);
1243
fprintf (real_stderr, "\n");
1167
fprintf (stderr, " %s", saved_argv[i]);
1168
fprintf (stderr, "\n");
1245
describe_uids (si, real_stderr);
1246
fprintf (real_stderr, "\n");
1170
describe_uids (si, stderr);
1171
fprintf (stderr, "\n");
1248
fflush (real_stdout);
1249
fflush (real_stderr);
1250
1175
execvp (saved_argv [0], saved_argv); /* shouldn't return */
1252
1177
char buf [512];
1253
1178
sprintf (buf, "%s: could not restart process", blurb());
1255
1180
fflush(stderr);