diff options
Diffstat (limited to 'utils/textclient.c')
-rw-r--r-- | utils/textclient.c | 129 |
1 files changed, 112 insertions, 17 deletions
diff --git a/utils/textclient.c b/utils/textclient.c index fe40928..4a4c895 100644 --- a/utils/textclient.c +++ b/utils/textclient.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2012-2016 Jamie Zawinski <jwz@jwz.org> +/* xscreensaver, Copyright © 2012-2021 Jamie Zawinski <jwz@jwz.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -22,7 +22,7 @@ #include "utils.h" -#if !defined(USE_IPHONE) && !defined(HAVE_ANDROID) /* whole file */ +#if !defined(HAVE_IPHONE) && !defined(HAVE_ANDROID) /* whole file */ #include "textclient.h" #include "resources.h" @@ -117,6 +117,72 @@ escape_str (char *s, const char *src) } #endif + +/* Let's see if we're able to fork and exec at all. Thanks, macOS. + */ +static Bool +selftest (void) +{ + static Bool done = False; + pid_t pid; + char buf [255]; + if (done) return True; + + pid = fork (); + switch ((int) pid) + { + case -1: + sprintf (buf, "%s: textclient: selftest: couldn't fork", progname); + perror (buf); + return False; + + case 0: /* child */ + { + char * const av[] = { "/bin/sh", "-c", "true", 0 }; + execvp (av[0], av); + exit (1); /* exits child fork */ + break; + } + + default: /* parent */ + { + int status = -1; + int i; + /* Busy-loops are bad mmmmkayyyy */ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 100000L; /* 0.1 sec */ + for (i = 0; i < 50; i++) { /* 5 sec max */ + pid_t pid2 = waitpid (pid, &status, 0); + if (pid == pid2) break; + (void) select (0, 0, 0, 0, &tv); + } + + if (status != 0) + { +# ifdef DEBUG + fprintf (stderr, "%s: selftest: textclient: status %d\n", + progname, status); +# endif + return False; + } + else + { +# ifdef DEBUG + fprintf (stderr, "%s: textclient: selftest ok\n", progname); +# endif + done = True; + } + break; + } + } + + return True; +} + + +static void start_timer (text_data *d); + static void launch_text_generator (text_data *d) { @@ -142,6 +208,15 @@ launch_text_generator (text_data *d) char *cmd = s = malloc ((strlen(oprogram)) * 2 + 100); # endif + if (!selftest()) + { + if (!d->out_buffer || !*d->out_buffer) + d->out_buffer = "Can't exec; Gatekeeper problem?\r\n\r\n"; + start_timer (d); + free (cmd); + return; + } + strcpy (s, "( "); strcat (s, oprogram); s += strlen (s); @@ -204,26 +279,39 @@ launch_text_generator (text_data *d) free (text_mode); } - strcpy (s, text_mode_flag); - s += strlen (s); - - if (value_res) + /* If the 'program' resource already has a text-mode option in it, + don't override that! 'gltext' does this. */ + if (! (strstr (cmd, " --date") || + strstr (cmd, " --text") || + strstr (cmd, " --file") || + strstr (cmd, " --url") || + strstr (cmd, " --program"))) { - size_t old_s = s - cmd; - char *value = get_string_resource (d->dpy, value_res, ""); - if (!value) - value = strdup(""); - cmd = realloc(cmd, cmd_capacity + strlen(value) * 2); - s = cmd + old_s; - *s = ' '; - ++s; - s = escape_str(s, value); - free(value); + strcpy (s, text_mode_flag); + s += strlen (s); + + if (value_res) + { + size_t old_s = s - cmd; + char *value = get_string_resource (d->dpy, value_res, ""); + if (!value) + value = strdup(""); + cmd = realloc(cmd, cmd_capacity + strlen(value) * 2); + s = cmd + old_s; + *s = ' '; + ++s; + s = escape_str(s, value); + free(value); + } } # endif /* HAVE_COCOA */ } +# if 1 strcpy (s, " ) 2>&1"); +# else + strcpy (s, " )"); +# endif # ifdef DEBUG fprintf (stderr, "%s: textclient: launch %s: %s\n", progname, @@ -477,6 +565,13 @@ textclient_open (Display *dpy) d->program = get_string_resource (dpy, "program", "Program"); + /* Just in case the resource is blank, e.g. gltext. */ + if (!d->program || !*d->program || !strcmp(d->program, "(default)")) + { + if (d->program) free (d->program); + d->program = strdup ("xscreensaver-text"); + } + # ifdef HAVE_FORKPTY /* Kludge for MacOS standalone mode: see OSX/SaverRunner.m. */ @@ -670,4 +765,4 @@ textclient_putc (text_data *d, XKeyEvent *k) return False; } -#endif /* !USE_IPHONE -- whole file */ +#endif /* !HAVE_IPHONE -- whole file */ |