summaryrefslogtreecommitdiffstats
path: root/driver/prefs.c
diff options
context:
space:
mode:
authorSimon Rettberg2021-04-06 14:43:39 +0200
committerSimon Rettberg2021-04-07 13:38:37 +0200
commit38886de0c3e9ea5729ef23e4c653fa2822f52e8f (patch)
tree9b799c8c968a92cc77746a95e0e8bdd90b6b13c3 /driver/prefs.c
parentMaybe not remove, but ... (diff)
downloadxscreensaver-38886de0c3e9ea5729ef23e4c653fa2822f52e8f.tar.gz
xscreensaver-38886de0c3e9ea5729ef23e4c653fa2822f52e8f.tar.xz
xscreensaver-38886de0c3e9ea5729ef23e4c653fa2822f52e8f.zip
xscreensaver 6.00v28r1openslx
Diffstat (limited to 'driver/prefs.c')
-rw-r--r--driver/prefs.c1702
1 files changed, 39 insertions, 1663 deletions
diff --git a/driver/prefs.c b/driver/prefs.c
index b608738..a65b679 100644
--- a/driver/prefs.c
+++ b/driver/prefs.c
@@ -1,5 +1,5 @@
-/* dotfile.c --- management of the ~/.xscreensaver file.
- * xscreensaver, Copyright (c) 1998-2020 Jamie Zawinski <jwz@jwz.org>
+/* prefs.c --- reading and writing the ~/.xscreensaver file.
+ * xscreensaver, Copyright © 1998-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
@@ -14,311 +14,20 @@
# include "config.h"
#endif
-#include <stdlib.h>
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
#include <stdio.h>
-#include <ctype.h>
+#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/time.h>
-#include <sys/param.h> /* for PATH_MAX */
-#include <X11/Xlib.h>
-#include <X11/Xresource.h>
-
-#ifndef VMS
-# include <pwd.h>
-#else /* VMS */
-# include "vms-pwd.h"
-#endif /* VMS */
-
-
-/* This file doesn't need the Xt headers, so stub these types out... */
-#undef XtPointer
-#define XtAppContext void*
-#define XtIntervalId void*
-#define XtPointer void*
-#define Widget void*
-
-
-/* Just in case there's something pathological about stat.h... */
-#ifndef S_IRUSR
-# define S_IRUSR 00400
-#endif
-#ifndef S_IWUSR
-# define S_IWUSR 00200
-#endif
-#ifndef S_IXUSR
-# define S_IXUSR 00100
-#endif
-#ifndef S_IXGRP
-# define S_IXGRP 00010
-#endif
-#ifndef S_IXOTH
-# define S_IXOTH 00001
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
#endif
-
-#include "version.h"
+#include "blurb.h"
#include "prefs.h"
-#include "resources.h"
-
-/* don't use realpath() on fedora system */
-#ifdef _FORTIFY_SOURCE
-#undef HAVE_REALPATH
-#endif
-
-
-extern char *progname;
-extern char *progclass;
-extern const char *blurb (void);
-
-
-
-static void get_screenhacks (Display *, saver_preferences *);
-static char *format_command (const char *cmd, Bool wrap_p);
-static void merge_system_screenhacks (Display *, saver_preferences *,
- screenhack **system_list, int count);
-static void stop_the_insanity (saver_preferences *p);
-
-
-static char *
-chase_symlinks (const char *file)
-{
-# ifdef HAVE_REALPATH
- if (file)
- {
-# ifndef PATH_MAX
-# ifdef MAXPATHLEN
-# define PATH_MAX MAXPATHLEN
-# else
-# define PATH_MAX 2048
-# endif
-# endif
- char buf[PATH_MAX];
- if (realpath (file, buf))
- return strdup (buf);
-
-/* sprintf (buf, "%.100s: realpath %.200s", blurb(), file);
- perror(buf);*/
- }
-# endif /* HAVE_REALPATH */
- return 0;
-}
-
-
-static Bool
-i_am_a_nobody (uid_t uid)
-{
- struct passwd *p;
-
- p = getpwnam ("nobody");
- if (! p) p = getpwnam ("noaccess");
- if (! p) p = getpwnam ("daemon");
-
- if (! p) /* There is no nobody? */
- return False;
-
- return (uid == p->pw_uid);
-}
-
-
-const char *
-init_file_name (void)
-{
- static char *file = 0;
-
- if (!file)
- {
- uid_t uid = getuid ();
- const char *home = getenv("HOME");
-
- if (i_am_a_nobody (uid) || !home || !*home)
- {
- /* If we're running as nobody, then use root's .xscreensaver file
- (since ~root/.xscreensaver and ~nobody/.xscreensaver are likely
- to be different -- if we didn't do this, then xscreensaver-demo
- would appear to have no effect when the luser is running as root.)
- */
- struct passwd *p = getpwuid (uid);
- uid = 0;
- if (!p || !p->pw_name || !*p->pw_name)
- {
- fprintf (stderr, "%s: couldn't get user info of uid %d\n",
- blurb(), getuid ());
- }
- else if (!p->pw_dir || !*p->pw_dir)
- {
- fprintf (stderr, "%s: couldn't get home directory of \"%s\"\n",
- blurb(), (p->pw_name ? p->pw_name : "???"));
- }
- else
- {
- home = p->pw_dir;
- }
- }
- if (home && *home)
- {
- const char *name = ".xscreensaver";
- file = (char *) malloc(strlen(home) + strlen(name) + 2);
- strcpy(file, home);
- if (!*home || home[strlen(home)-1] != '/')
- strcat(file, "/");
- strcat(file, name);
- }
- else
- {
- file = "";
- }
- }
-
- if (file && *file)
- return file;
- else
- return 0;
-}
-
-
-static const char *
-init_file_tmp_name (void)
-{
- static char *file = 0;
- if (!file)
- {
- const char *name = init_file_name();
- const char *suffix = ".tmp";
-
- char *n2 = chase_symlinks (name);
- if (n2) name = n2;
- if (!name || !*name)
- file = "";
- else
- {
- file = (char *) malloc(strlen(name) + strlen(suffix) + 2);
- strcpy(file, name);
- strcat(file, suffix);
- }
-
- if (n2) free (n2);
- }
-
- if (file && *file)
- return file;
- else
- return 0;
-}
-
-static int
-get_byte_resource (Display *dpy, char *name, char *class)
-{
- char *s = get_string_resource (dpy, name, class);
- char *s2 = s;
- int n = 0;
- if (!s) return 0;
-
- while (isspace(*s2)) s2++;
- while (*s2 >= '0' && *s2 <= '9')
- {
- n = (n * 10) + (*s2 - '0');
- s2++;
- }
- while (isspace(*s2)) s2++;
- if (*s2 == 'k' || *s2 == 'K') n <<= 10;
- else if (*s2 == 'm' || *s2 == 'M') n <<= 20;
- else if (*s2 == 'g' || *s2 == 'G') n <<= 30;
- else if (*s2)
- {
- LOSE:
- fprintf (stderr, "%s: %s must be a number of bytes, not \"%s\".\n",
- progname, name, s);
- free (s);
- return 0;
- }
- s2++;
- if (*s2 == 'b' || *s2 == 'B') s2++;
- while (isspace(*s2)) s2++;
- if (*s2) goto LOSE;
-
- free (s);
- return n;
-}
-
-
-static const char * const prefs[] = {
- "timeout",
- "cycle",
- "lock",
- "lockVTs", /* not saved */
- "lockTimeout",
- "passwdTimeout",
- "visualID",
- "installColormap",
- "verbose",
- "timestamp",
- "splash",
- "splashDuration",
- "quad",
- "demoCommand",
- "prefsCommand",
- "newLoginCommand",
- "helpURL", /* not saved */
- "loadURL", /* not saved */
- "newLoginCommand", /* not saved */
- "externalUngrabCommand", /* not saved */
- "nice",
- "memoryLimit",
- "fade",
- "unfade",
- "fadeSeconds",
- "fadeTicks",
- "captureStderr",
- "captureStdout", /* not saved -- obsolete */
- "logFile", /* not saved */
- "ignoreUninstalledPrograms",
- "font",
- "dpmsEnabled",
- "dpmsQuickOff",
- "dpmsStandby",
- "dpmsSuspend",
- "dpmsOff",
- "dpmsFullThrottle",
- "grabDesktopImages",
- "grabVideoFrames",
- "chooseRandomImages",
- "imageDirectory",
- "mode",
- "selected",
- "textMode",
- "textLiteral",
- "textFile",
- "textProgram",
- "textURL",
- "",
- "programs",
- "",
- "pointerPollTime",
- "pointerHysteresis",
- "windowCreationTimeout",
- "initialDelay",
- "sgiSaverExtension", /* not saved -- obsolete */
- "mitSaverExtension", /* not saved -- obsolete */
- "xidleExtension", /* not saved -- obsolete */
- "GetViewPortIsFullOfLies",
- "procInterrupts",
- "xinputExtensionDev",
- "overlayStderr",
- "overlayTextBackground", /* not saved -- X resources only */
- "overlayTextForeground", /* not saved -- X resources only */
- "bourneShell", /* not saved -- X resources only */
- "authWarningSlack",
- 0
-};
static char *
strip (char *s)
@@ -336,85 +45,49 @@ strip (char *s)
return s;
}
-
-/* Reading
- */
-
-static int
-handle_entry (XrmDatabase *db, const char *key, const char *value,
- const char *filename, int line)
-{
- int i;
- for (i = 0; prefs[i]; i++)
- if (*prefs[i] && !strcasecmp(key, prefs[i]))
- {
- char *val = strdup(value);
- char *spec = (char *) malloc(strlen(progclass) + strlen(prefs[i]) +10);
- strcpy(spec, progclass);
- strcat(spec, ".");
- strcat(spec, prefs[i]);
-
- XrmPutStringResource (db, spec, val);
-
- free(spec);
- free(val);
- return 0;
- }
-
- fprintf(stderr, "%s: %s:%d: unknown option \"%s\"\n",
- blurb(), filename, line, key);
- return 1;
-}
-
-static int
-parse_init_file (saver_preferences *p)
+/* Parse the .xscreensaver or XScreenSaver.ad file and run the callback
+ for each key-value pair.
+*/
+int
+parse_init_file (const char *name,
+ void (*handler) (int lineno,
+ const char *key, const char *val,
+ void *closure),
+ void *closure)
{
- time_t write_date = 0;
- const char *name = init_file_name();
int line = 0;
struct stat st;
FILE *in;
int buf_size = 1024;
- char *buf;
+ char *buf = 0;
if (!name) return 0;
+ if (stat (name, &st) != 0) goto FAIL;
- if (stat(name, &st) != 0)
- {
- p->init_file_date = 0;
- return 0;
- }
+ buf = (char *) malloc (buf_size);
+ if (!buf) goto FAIL;
in = fopen(name, "r");
if (!in)
{
- char *buf = (char *) malloc(1024 + strlen(name));
- sprintf(buf, "%s: error reading \"%s\"", blurb(), name);
- perror(buf);
- free(buf);
- return -1;
+ sprintf (buf, "%s: error reading \"%.100s\"", blurb(), name);
+ perror (buf);
+ goto FAIL;
}
- if (fstat (fileno(in), &st) == 0)
+ if (fstat (fileno (in), &st) != 0)
{
- write_date = st.st_mtime;
- }
- else
- {
- char *buf = (char *) malloc(1024 + strlen(name));
- sprintf(buf, "%s: couldn't re-stat \"%s\"", blurb(), name);
- perror(buf);
- free(buf);
+ sprintf (buf, "%s: couldn't re-stat \"%.100s\"", blurb(), name);
+ perror (buf);
+ free (buf);
return -1;
}
- buf = (char *) malloc(buf_size);
-
while (fgets (buf, buf_size-1, in))
{
char *key, *value;
- int L = strlen(buf);
+ int L = strlen (buf);
line++;
while (L > 2 &&
@@ -427,13 +100,13 @@ parse_init_file (saver_preferences *p)
L -= 2;
}
buf_size += 1024;
- buf = (char *) realloc(buf, buf_size);
- if (!buf) exit(1);
+ buf = (char *) realloc (buf, buf_size);
+ if (!buf) goto FAIL;
line++;
if (!fgets (buf + L, buf_size-L-1, in))
break;
- L = strlen(buf);
+ L = strlen (buf);
}
/* Now handle other backslash escapes. */
@@ -455,7 +128,7 @@ parse_init_file (saver_preferences *p)
}
}
- key = strip(buf);
+ key = strip (buf);
if (*key == '#' || *key == '!' || *key == ';' ||
*key == '\n' || *key == 0)
@@ -464,1320 +137,23 @@ parse_init_file (saver_preferences *p)
value = strchr (key, ':');
if (!value)
{
- fprintf(stderr, "%s: %s:%d: unparsable line: %s\n", blurb(),
- name, line, key);
+ fprintf (stderr, "%s: %s:%d: unparsable line: %s\n", blurb(),
+ name, line, key);
continue;
}
else
{
*value++ = 0;
- value = strip(value);
+ value = strip (value);
}
- if (!p->db) abort();
- handle_entry (&p->db, key, value, name, line);
+ handler (line, key, value, closure);
}
fclose (in);
- free(buf);
-
- p->init_file_date = write_date;
+ free (buf);
return 0;
-}
-
-
-Bool
-init_file_changed_p (saver_preferences *p)
-{
- const char *name = init_file_name();
- struct stat st;
-
- if (!name) return False;
-
- if (stat(name, &st) != 0)
- return False;
-
- if (p->init_file_date == st.st_mtime)
- return False;
-
- return True;
-}
-
-
-/* Writing
- */
-
-static int
-tab_to (FILE *out, int from, int to)
-{
- int tab_width = 8;
- int to_mod = (to / tab_width) * tab_width;
- while (from < to_mod)
- {
- fprintf(out, "\t");
- from = (((from / tab_width) + 1) * tab_width);
- }
- while (from < to)
- {
- fprintf(out, " ");
- from++;
- }
- return from;
-}
-
-static char *
-stab_to (char *out, int from, int to)
-{
- int tab_width = 8;
- int to_mod = (to / tab_width) * tab_width;
- while (from < to_mod)
- {
- *out++ = '\t';
- from = (((from / tab_width) + 1) * tab_width);
- }
- while (from < to)
- {
- *out++ = ' ';
- from++;
- }
- return out;
-}
-
-static int
-string_columns (const char *string, int length, int start)
-{
- int tab_width = 8;
- int col = start;
- const char *end = string + length;
- while (string < end)
- {
- if (*string == '\n')
- col = 0;
- else if (*string == '\t')
- col = (((col / tab_width) + 1) * tab_width);
- else
- col++;
- string++;
- }
- return col;
-}
-
-
-static void
-write_entry (FILE *out, const char *key, const char *value)
-{
- char *v = strdup(value ? value : "");
- char *v2 = v;
- char *nl = 0;
- int col;
- Bool programs_p = (!strcmp(key, "programs"));
- int tab = (programs_p ? 32 : 16);
- Bool first = True;
-
- fprintf(out, "%s:", key);
- col = strlen(key) + 1;
-
- if (strlen(key) > 14)
- col = tab_to (out, col, 20);
-
- while (1)
- {
- if (!programs_p)
- v2 = strip(v2);
- nl = strchr(v2, '\n');
- if (nl)
- *nl = 0;
-
- if (first && programs_p)
- {
- col = tab_to (out, col, 77);
- fprintf (out, " \\\n");
- col = 0;
- }
-
- if (first)
- first = False;
- else
- {
- col = tab_to (out, col, 75);
- fprintf (out, " \\n\\\n");
- col = 0;
- }
-
- if (!programs_p)
- col = tab_to (out, col, tab);
-
- if (programs_p &&
- string_columns(v2, strlen (v2), col) + col > 75)
- {
- int L = strlen (v2);
- int start = 0;
- int end = start;
- while (start < L)
- {
- while (v2[end] == ' ' || v2[end] == '\t')
- end++;
- while (v2[end] != ' ' && v2[end] != '\t' &&
- v2[end] != '\n' && v2[end] != 0)
- end++;
- if (string_columns (v2 + start, (end - start), col) >= 74)
- {
- col = tab_to (out, col, 75);
- fprintf(out, " \\\n");
- col = tab_to (out, 0, tab + 2);
- while (v2[start] == ' ' || v2[start] == '\t')
- start++;
- }
-
- col = string_columns (v2 + start, (end - start), col);
- while (start < end)
- fputc(v2[start++], out);
- }
- }
- else
- {
- fprintf (out, "%s", v2);
- col += string_columns(v2, strlen (v2), col);
- }
-
- if (nl)
- v2 = nl + 1;
- else
- break;
- }
-
- fprintf(out, "\n");
- free(v);
-}
-
-int
-write_init_file (Display *dpy,
- saver_preferences *p, const char *version_string,
- Bool verbose_p)
-{
- int status = -1;
- const char *name = init_file_name();
- const char *tmp_name = init_file_tmp_name();
- char *n2 = chase_symlinks (name);
- struct stat st;
- int i, j;
-
- /* Kludge, since these aren't in the saver_preferences struct as strings...
- */
- char *visual_name;
- char *programs;
- Bool overlay_stderr_p;
- char *stderr_font;
- FILE *out;
-
- if (!name) goto END;
-
- if (n2) name = n2;
-
- /* Throttle the various timeouts to reasonable values before writing
- the file to disk. */
- stop_the_insanity (p);
-
-
- if (verbose_p)
- fprintf (stderr, "%s: writing \"%s\".\n", blurb(), name);
-
- unlink (tmp_name);
- out = fopen(tmp_name, "w");
- if (!out)
- {
- char *buf = (char *) malloc(1024 + strlen(name));
- sprintf(buf, "%s: error writing \"%s\"", blurb(), name);
- perror(buf);
- free(buf);
- goto END;
- }
-
- /* Give the new .xscreensaver file the same permissions as the old one;
- except ensure that it is readable and writable by owner, and not
- executable. Extra hack: if we're running as root, make the file
- be world-readable (so that the daemon, running as "nobody", will
- still be able to read it.)
- */
- if (stat(name, &st) == 0)
- {
- mode_t mode = st.st_mode;
- mode |= S_IRUSR | S_IWUSR; /* read/write by user */
- mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); /* executable by none */
-
- if (getuid() == (uid_t) 0) /* read by group/other */
- mode |= S_IRGRP | S_IROTH;
-
- if (fchmod (fileno(out), mode) != 0)
- {
- char *buf = (char *) malloc(1024 + strlen(name));
- sprintf (buf, "%s: error fchmodding \"%s\" to 0%o", blurb(),
- tmp_name, (unsigned int) mode);
- perror(buf);
- free(buf);
- goto END;
- }
- }
-
- /* Kludge, since these aren't in the saver_preferences struct... */
- visual_name = get_string_resource (dpy, "visualID", "VisualID");
- programs = 0;
- overlay_stderr_p = get_boolean_resource (dpy, "overlayStderr", "Boolean");
- stderr_font = get_string_resource (dpy, "font", "Font");
-
- i = 0;
- {
- char *ss;
- char **hack_strings = (char **)
- calloc (p->screenhacks_count, sizeof(char *));
-
- for (j = 0; j < p->screenhacks_count; j++)
- {
- hack_strings[j] = format_hack (dpy, p->screenhacks[j], True);
- i += strlen (hack_strings[j]);
- i += 2;
- }
-
- ss = programs = (char *) malloc(i + 10);
- *ss = 0;
- for (j = 0; j < p->screenhacks_count; j++)
- {
- strcat (ss, hack_strings[j]);
- free (hack_strings[j]);
- ss += strlen(ss);
- *ss++ = '\n';
- *ss = 0;
- }
- free (hack_strings);
- }
-
- {
- struct passwd *pw = getpwuid (getuid ());
- char *whoami = (pw && pw->pw_name && *pw->pw_name
- ? pw->pw_name
- : "<unknown>");
- time_t now = time ((time_t *) 0);
- char *timestr = (char *) ctime (&now);
- char *nl = (char *) strchr (timestr, '\n');
- if (nl) *nl = 0;
- fprintf (out,
- "# %s Preferences File\n"
- "# Written by %s %s for %s on %s.\n"
- "# https://www.jwz.org/xscreensaver/\n"
- "\n",
- progclass, progname, version_string, whoami, timestr);
- }
-
- for (j = 0; prefs[j]; j++)
- {
- char buf[255];
- const char *pr = prefs[j];
- enum pref_type { pref_str, pref_int, pref_bool, pref_byte, pref_time
- } type = pref_str;
- const char *s = 0;
- int i = 0;
- Bool b = False;
- Time t = 0;
-
- if (pr && !*pr)
- {
- fprintf(out, "\n");
- continue;
- }
-
-# undef CHECK
-# define CHECK(X) else if (!strcmp(pr, X))
- if (!pr || !*pr) ;
- CHECK("timeout") type = pref_time, t = p->timeout;
- CHECK("cycle") type = pref_time, t = p->cycle;
- CHECK("lock") type = pref_bool, b = p->lock_p;
- CHECK("lockVTs") continue; /* don't save, unused */
- CHECK("lockTimeout") type = pref_time, t = p->lock_timeout;
- CHECK("passwdTimeout") type = pref_time, t = p->passwd_timeout;
- CHECK("visualID") type = pref_str, s = visual_name;
- CHECK("installColormap") type = pref_bool, b = p->install_cmap_p;
- CHECK("verbose") type = pref_bool, b = p->verbose_p;
- CHECK("timestamp") type = pref_bool, b = p->timestamp_p;
- CHECK("splash") type = pref_bool, b = p->splash_p;
- CHECK("splashDuration") type = pref_time, t = p->splash_duration;
-# ifdef QUAD_MODE
- CHECK("quad") type = pref_bool, b = p->quad_p;
-# else /* !QUAD_MODE */
- CHECK("quad") continue; /* don't save */
-# endif /* !QUAD_MODE */
- CHECK("demoCommand") type = pref_str, s = p->demo_command;
- CHECK("prefsCommand") type = pref_str, s = p->prefs_command;
-/* CHECK("helpURL") type = pref_str, s = p->help_url; */
- CHECK("helpURL") continue; /* don't save */
-/* CHECK("loadURL") type = pref_str, s = p->load_url_command; */
- CHECK("loadURL") continue; /* don't save */
-/* CHECK("newLoginCommand") type = pref_str, s = p->new_login_command; */
- CHECK("newLoginCommand") continue; /* don't save */
- CHECK("externalUngrabCommand") continue; /* don't save */
- CHECK("nice") type = pref_int, i = p->nice_inferior;
- CHECK("memoryLimit") type = pref_byte, i = p->inferior_memory_limit;
- CHECK("fade") type = pref_bool, b = p->fade_p;
- CHECK("unfade") type = pref_bool, b = p->unfade_p;
- CHECK("fadeSeconds") type = pref_time, t = p->fade_seconds;
- CHECK("fadeTicks") type = pref_int, i = p->fade_ticks;
- CHECK("captureStderr") type = pref_bool, b = p->capture_stderr_p;
- CHECK("captureStdout") continue; /* don't save */
- CHECK("logFile") continue; /* don't save */
- CHECK("ignoreUninstalledPrograms")
- type = pref_bool, b = p->ignore_uninstalled_p;
-
- CHECK("font") type = pref_str, s = stderr_font;
-
- CHECK("dpmsEnabled") type = pref_bool, b = p->dpms_enabled_p;
- CHECK("dpmsQuickOff") type = pref_bool, b = p->dpms_quickoff_p;
- CHECK("dpmsStandby") type = pref_time, t = p->dpms_standby;
- CHECK("dpmsSuspend") type = pref_time, t = p->dpms_suspend;
- CHECK("dpmsOff") type = pref_time, t = p->dpms_off;
- CHECK("dpmsFullThrottle") continue; /* don't save */
-
- CHECK("grabDesktopImages") type =pref_bool, b = p->grab_desktop_p;
- CHECK("grabVideoFrames") type =pref_bool, b = p->grab_video_p;
- CHECK("chooseRandomImages")type =pref_bool, b = p->random_image_p;
- CHECK("imageDirectory") type =pref_str, s = p->image_directory;
-
- CHECK("mode") type = pref_str,
- s = (p->mode == ONE_HACK ? "one" :
- p->mode == BLANK_ONLY ? "blank" :
- p->mode == DONT_BLANK ? "off" :
- p->mode == RANDOM_HACKS_SAME
- ? "random-same"
- : "random");
- CHECK("selected") type = pref_int, i = p->selected_hack;
-
- CHECK("textMode") type = pref_str,
- s = (p->tmode == TEXT_URL ? "url" :
- p->tmode == TEXT_LITERAL ? "literal" :
- p->tmode == TEXT_FILE ? "file" :
- p->tmode == TEXT_PROGRAM ? "program" :
- "date");
- CHECK("textLiteral") type = pref_str, s = p->text_literal;
- CHECK("textFile") type = pref_str, s = p->text_file;
- CHECK("textProgram") type = pref_str, s = p->text_program;
- CHECK("textURL") type = pref_str, s = p->text_url;
-
- CHECK("programs") type = pref_str, s = programs;
- CHECK("pointerPollTime") type = pref_time, t = p->pointer_timeout;
- CHECK("pointerHysteresis")type = pref_int, i = p->pointer_hysteresis;
- CHECK("windowCreationTimeout")type=pref_time,t= p->notice_events_timeout;
- CHECK("initialDelay") type = pref_time, t = p->initial_delay;
- CHECK("sgiSaverExtension") continue; /* don't save */
- CHECK("mitSaverExtension") continue; /* don't save */
- CHECK("xidleExtension") continue; /* don't save */
- CHECK("procInterrupts") type = pref_bool, b = p->use_proc_interrupts;
- CHECK("xinputExtensionDev") type = pref_bool, b = p->use_xinput_extension;
- CHECK("GetViewPortIsFullOfLies") type = pref_bool,
- b = p->getviewport_full_of_lies_p;
- CHECK("overlayStderr") type = pref_bool, b = overlay_stderr_p;
- CHECK("overlayTextBackground") continue; /* don't save */
- CHECK("overlayTextForeground") continue; /* don't save */
- CHECK("bourneShell") continue; /* don't save */
- CHECK("authWarningSlack") type = pref_int, i = p->auth_warning_slack;
- else abort();
-# undef CHECK
-
- switch (type)
- {
- case pref_str:
- break;
- case pref_int:
- sprintf(buf, "%d", i);
- s = buf;
- break;
- case pref_bool:
- s = b ? "True" : "False";
- break;
- case pref_time:
- {
- unsigned int hour = 0, min = 0, sec = (unsigned int) (t/1000);
- if (sec >= 60)
- {
- min += (sec / 60);
- sec %= 60;
- }
- if (min >= 60)
- {
- hour += (min / 60);
- min %= 60;
- }
- sprintf (buf, "%u:%02u:%02u", hour, min, sec);
- s = buf;
- }
- break;
- case pref_byte:
- {
- if (i >= (1<<30) && i == ((i >> 30) << 30))
- sprintf(buf, "%dG", i >> 30);
- else if (i >= (1<<20) && i == ((i >> 20) << 20))
- sprintf(buf, "%dM", i >> 20);
- else if (i >= (1<<10) && i == ((i >> 10) << 10))
- sprintf(buf, "%dK", i >> 10);
- else
- sprintf(buf, "%d", i);
- s = buf;
- }
- break;
- default:
- abort();
- break;
- }
-
- if (pr && (!strcmp(pr, "mode") || !strcmp(pr, "textMode")))
- fprintf(out, "\n");
-
- write_entry (out, pr, s);
- }
-
- fprintf(out, "\n");
-
- if (visual_name) free(visual_name);
- if (stderr_font) free(stderr_font);
- if (programs) free(programs);
-
- if (fclose(out) == 0)
- {
- time_t write_date = 0;
-
- if (stat(tmp_name, &st) == 0)
- {
- write_date = st.st_mtime;
- }
- else
- {
- char *buf = (char *) malloc(1024 + strlen(tmp_name) + strlen(name));
- sprintf(buf, "%s: couldn't stat \"%s\"", blurb(), tmp_name);
- perror(buf);
- unlink (tmp_name);
- free(buf);
- goto END;
- }
-
- if (rename (tmp_name, name) != 0)
- {
- char *buf = (char *) malloc(1024 + strlen(tmp_name) + strlen(name));
- sprintf(buf, "%s: error renaming \"%s\" to \"%s\"",
- blurb(), tmp_name, name);
- perror(buf);
- unlink (tmp_name);
- free(buf);
- goto END;
- }
- else
- {
- p->init_file_date = write_date;
-
- /* Since the .xscreensaver file is used for IPC, let's try and make
- sure that the bits actually land on the disk right away. */
- sync ();
-
- status = 0; /* wrote and renamed successfully! */
- }
- }
- else
- {
- char *buf = (char *) malloc(1024 + strlen(name));
- sprintf(buf, "%s: error closing \"%s\"", blurb(), name);
- perror(buf);
- free(buf);
- unlink (tmp_name);
- goto END;
- }
-
- END:
- if (n2) free (n2);
- return status;
-}
-
-
-/* Parsing the resource database
- */
-
-void
-free_screenhack (screenhack *hack)
-{
- if (hack->visual) free (hack->visual);
- if (hack->name) free (hack->name);
- free (hack->command);
- memset (hack, 0, sizeof(*hack));
- free (hack);
-}
-
-static void
-free_screenhack_list (screenhack **list, int count)
-{
- int i;
- if (!list) return;
- for (i = 0; i < count; i++)
- if (list[i])
- free_screenhack (list[i]);
- free (list);
-}
-
-
-
-/* Populate `saver_preferences' with the contents of the resource database.
- Note that this may be called multiple times -- it is re-run each time
- the ~/.xscreensaver file is reloaded.
-
- This function can be very noisy, since it issues resource syntax errors
- and so on.
- */
-void
-load_init_file (Display *dpy, saver_preferences *p)
-{
- static Bool first_time = True;
-
- screenhack **system_default_screenhacks = 0;
- int system_default_screenhack_count = 0;
-
- if (first_time)
- {
- /* Get the programs resource before the .xscreensaver file has been
- parsed and merged into the resource database for the first time:
- this is the value of *programs from the app-defaults file.
- Then clear it out so that it will be parsed again later, after
- the init file has been read.
- */
- get_screenhacks (dpy, p);
- system_default_screenhacks = p->screenhacks;
- system_default_screenhack_count = p->screenhacks_count;
- p->screenhacks = 0;
- p->screenhacks_count = 0;
- }
-
- if (parse_init_file (p) != 0) /* file might have gone away */
- if (!first_time) return;
-
- first_time = False;
-
- p->xsync_p = get_boolean_resource (dpy, "synchronous", "Synchronous");
- p->verbose_p = get_boolean_resource (dpy, "verbose", "Boolean");
- p->timestamp_p = get_boolean_resource (dpy, "timestamp", "Boolean");
- p->lock_p = get_boolean_resource (dpy, "lock", "Boolean");
- p->fade_p = get_boolean_resource (dpy, "fade", "Boolean");
- p->unfade_p = get_boolean_resource (dpy, "unfade", "Boolean");
- p->fade_seconds = 1000 * get_seconds_resource (dpy, "fadeSeconds", "Time");
- p->fade_ticks = get_integer_resource (dpy, "fadeTicks", "Integer");
- p->install_cmap_p = get_boolean_resource (dpy, "installColormap", "Boolean");
- p->nice_inferior = get_integer_resource (dpy, "nice", "Nice");
- p->inferior_memory_limit = get_byte_resource (dpy, "memoryLimit",
- "MemoryLimit");
- p->splash_p = get_boolean_resource (dpy, "splash", "Boolean");
-# ifdef QUAD_MODE
- p->quad_p = get_boolean_resource (dpy, "quad", "Boolean");
-# endif
- p->capture_stderr_p = get_boolean_resource (dpy, "captureStderr", "Boolean");
- p->ignore_uninstalled_p = get_boolean_resource (dpy,
- "ignoreUninstalledPrograms",
- "Boolean");
-
- p->initial_delay = 1000 * get_seconds_resource (dpy, "initialDelay", "Time");
- p->splash_duration = 1000 * get_seconds_resource (dpy, "splashDuration", "Time");
- p->timeout = 1000 * get_minutes_resource (dpy, "timeout", "Time");
- p->lock_timeout = 1000 * get_minutes_resource (dpy, "lockTimeout", "Time");
- p->cycle = 1000 * get_minutes_resource (dpy, "cycle", "Time");
- p->passwd_timeout = 1000 * get_seconds_resource (dpy, "passwdTimeout", "Time");
- p->pointer_timeout = 1000 * get_seconds_resource (dpy, "pointerPollTime", "Time");
- p->pointer_hysteresis = get_integer_resource (dpy, "pointerHysteresis","Integer");
- p->notice_events_timeout = 1000*get_seconds_resource(dpy,
- "windowCreationTimeout",
- "Time");
-
- p->dpms_enabled_p = get_boolean_resource (dpy, "dpmsEnabled", "Boolean");
- p->dpms_quickoff_p = get_boolean_resource (dpy, "dpmsQuickOff", "Boolean");
- p->dpms_standby = 1000 * get_minutes_resource (dpy, "dpmsStandby", "Time");
- p->dpms_suspend = 1000 * get_minutes_resource (dpy, "dpmsSuspend", "Time");
- p->dpms_off = 1000 * get_minutes_resource (dpy, "dpmsOff", "Time");
- p->dpms_full_throttle_p = get_boolean_resource (dpy, "dpmsFullThrottle", "Boolean");
-
- p->grab_desktop_p = get_boolean_resource (dpy, "grabDesktopImages", "Boolean");
- p->grab_video_p = get_boolean_resource (dpy, "grabVideoFrames", "Boolean");
- p->random_image_p = get_boolean_resource (dpy, "chooseRandomImages", "Boolean");
- p->image_directory = get_string_resource (dpy,
- "imageDirectory",
- "ImageDirectory");
-
- p->text_literal = get_string_resource (dpy, "textLiteral", "TextLiteral");
- p->text_file = get_string_resource (dpy, "textFile", "TextFile");
- p->text_program = get_string_resource (dpy, "textProgram", "TextProgram");
- p->text_url = get_string_resource (dpy, "textURL", "TextURL");
-
- p->shell = get_string_resource (dpy, "bourneShell", "BourneShell");
-
- p->demo_command = get_string_resource(dpy, "demoCommand", "URL");
- p->prefs_command = get_string_resource(dpy, "prefsCommand", "URL");
- p->help_url = get_string_resource(dpy, "helpURL", "URL");
- p->load_url_command = get_string_resource(dpy, "loadURL", "LoadURL");
- p->new_login_command = get_string_resource(dpy,
- "newLoginCommand",
- "NewLoginCommand");
- p->external_ungrab_command = get_string_resource(dpy,
- "externalUngrabCommand",
- "ExternalUngrabCommand");
- p->auth_warning_slack = get_integer_resource(dpy, "authWarningSlack",
- "Integer");
-
- /* If "*splash" is unset, default to true. */
- {
- char *s = get_string_resource (dpy, "splash", "Boolean");
- if (s)
- free (s);
- else
- p->splash_p = True;
- }
-
- /* If "*grabDesktopImages" is unset, default to true. */
- {
- char *s = get_string_resource (dpy, "grabDesktopImages", "Boolean");
- if (s)
- free (s);
- else
- p->grab_desktop_p = True;
- }
-
- p->use_xidle_extension = get_boolean_resource (dpy, "xidleExtension","Boolean");
-#if 0 /* obsolete. */
- p->use_sgi_saver_extension = get_boolean_resource (dpy,
- "sgiSaverExtension",
- "Boolean");
-#endif
-#ifdef HAVE_XINPUT
- p->use_xinput_extension = get_boolean_resource (dpy, "xinputExtensionDev",
- "Boolean");
-#endif
-#if 0 /* broken and evil. */
- p->use_mit_saver_extension = get_boolean_resource (dpy,
- "mitSaverExtension",
- "Boolean");
-#endif
-
- p->use_proc_interrupts = get_boolean_resource (dpy,
- "procInterrupts", "Boolean");
-
- p->getviewport_full_of_lies_p =
- get_boolean_resource (dpy, "GetViewPortIsFullOfLies", "Boolean");
-
- get_screenhacks (dpy, p); /* Parse the "programs" resource. */
-
- {
- char *s = get_string_resource (dpy, "selected", "Integer");
- if (!s || !*s)
- p->selected_hack = -1;
- else
- p->selected_hack = get_integer_resource (dpy, "selected", "Integer");
- if (s) free (s);
- if (p->selected_hack < 0 || p->selected_hack >= p->screenhacks_count)
- p->selected_hack = -1;
- }
-
- {
- char *s = get_string_resource (dpy, "mode", "Mode");
- if (s && !strcasecmp (s, "one")) p->mode = ONE_HACK;
- else if (s && !strcasecmp (s, "blank")) p->mode = BLANK_ONLY;
- else if (s && !strcasecmp (s, "off")) p->mode = DONT_BLANK;
- else if (s && !strcasecmp (s, "random-same")) p->mode = RANDOM_HACKS_SAME;
- else p->mode = RANDOM_HACKS;
- if (s) free (s);
- }
-
- {
- char *s = get_string_resource (dpy, "textMode", "TextMode");
- if (s && !strcasecmp (s, "url")) p->tmode = TEXT_URL;
- else if (s && !strcasecmp (s, "literal")) p->tmode = TEXT_LITERAL;
- else if (s && !strcasecmp (s, "file")) p->tmode = TEXT_FILE;
- else if (s && !strcasecmp (s, "program")) p->tmode = TEXT_PROGRAM;
- else p->tmode = TEXT_DATE;
- if (s) free (s);
- }
-
- if (system_default_screenhack_count) /* note: first_time is also true */
- {
- merge_system_screenhacks (dpy, p, system_default_screenhacks,
- system_default_screenhack_count);
- free_screenhack_list (system_default_screenhacks,
- system_default_screenhack_count);
- system_default_screenhacks = 0;
- system_default_screenhack_count = 0;
- }
-
- if (p->debug_p)
- {
- p->xsync_p = True;
- p->verbose_p = True;
- p->timestamp_p = True;
- p->initial_delay = 0;
- }
-
- /* Throttle the various timeouts to reasonable values after reading the
- disk file. */
- stop_the_insanity (p);
-}
-
-
-/* If there are any hacks in the system-wide defaults that are not in
- the ~/.xscreensaver file, add the new ones to the end of the list.
- This does *not* actually save the file.
- */
-static void
-merge_system_screenhacks (Display *dpy, saver_preferences *p,
- screenhack **system_list, int system_count)
-{
- /* Yeah yeah, this is an N^2 operation, but I don't have hashtables handy,
- so fuck it. */
-
- int made_space = 0;
- int i;
- for (i = 0; i < system_count; i++)
- {
- int j;
- Bool matched_p = False;
-
- for (j = 0; j < p->screenhacks_count; j++)
- {
- char *name;
- if (!system_list[i]->name)
- system_list[i]->name = make_hack_name (dpy,
- system_list[i]->command);
-
- name = p->screenhacks[j]->name;
- if (!name)
- name = make_hack_name (dpy, p->screenhacks[j]->command);
-
- matched_p = !strcasecmp (name, system_list[i]->name);
-
- if (name != p->screenhacks[j]->name)
- free (name);
-
- if (matched_p)
- break;
- }
-
- if (!matched_p)
- {
- /* We have an entry in the system-wide list that is not in the
- user's .xscreensaver file. Add it to the end.
- Note that p->screenhacks is a single malloc block, not a
- linked list, so we have to realloc it.
- */
- screenhack *oh = system_list[i];
- screenhack *nh = (screenhack *) malloc (sizeof(screenhack));
-
- if (made_space == 0)
- {
- made_space = 10;
- p->screenhacks = (screenhack **)
- realloc (p->screenhacks,
- (p->screenhacks_count + made_space + 1)
- * sizeof(screenhack));
- if (!p->screenhacks) abort();
- }
-
- nh->enabled_p = oh->enabled_p;
- nh->visual = oh->visual ? strdup(oh->visual) : 0;
- nh->name = oh->name ? strdup(oh->name) : 0;
- nh->command = oh->command ? strdup(oh->command) : 0;
-
- p->screenhacks[p->screenhacks_count++] = nh;
- p->screenhacks[p->screenhacks_count] = 0;
- made_space--;
-
-#if 0
- fprintf (stderr, "%s: noticed new hack: %s\n", blurb(),
- (nh->name ? nh->name : make_hack_name (dpy, nh->command)));
-#endif
- }
- }
-}
-
-
-
-/* Parsing the programs resource.
- */
-
-screenhack *
-parse_screenhack (const char *line)
-{
- screenhack *h = (screenhack *) calloc (1, sizeof(*h));
- const char *s;
-
- h->enabled_p = True;
-
- while (isspace(*line)) line++; /* skip whitespace */
- if (*line == '-') /* handle "-" */
- {
- h->enabled_p = False;
- line++;
- while (isspace(*line)) line++; /* skip whitespace */
- }
-
- s = line; /* handle "visual:" */
- while (*line && *line != ':' && *line != '"' && !isspace(*line))
- line++;
- if (*line != ':')
- line = s;
- else
- {
- h->visual = (char *) malloc (line-s+1);
- strncpy (h->visual, s, line-s);
- h->visual[line-s] = 0;
- if (*line == ':') line++; /* skip ":" */
- while (isspace(*line)) line++; /* skip whitespace */
- }
-
- if (*line == '"') /* handle "name" */
- {
- line++;
- s = line;
- while (*line && *line != '"')
- line++;
- h->name = (char *) malloc (line-s+1);
- strncpy (h->name, s, line-s);
- h->name[line-s] = 0;
- if (*line == '"') line++; /* skip "\"" */
- while (isspace(*line)) line++; /* skip whitespace */
- }
-
- h->command = format_command (line, False); /* handle command */
- return h;
-}
-
-
-static char *
-format_command (const char *cmd, Bool wrap_p)
-{
- int tab = 30;
- int col = tab;
- char *cmd2 = (char *) calloc (1, 2 * (strlen (cmd) + 1));
- const char *in = cmd;
- char *out = cmd2;
- while (*in)
- {
- /* shrink all whitespace to one space, for the benefit of the "demo"
- mode display. We only do this when we can easily tell that the
- whitespace is not significant (no shell metachars).
- */
- switch (*in)
- {
- case '\'': case '"': case '`': case '\\':
- /* Metachars are scary. Copy the rest of the line unchanged. */
- while (*in)
- *out++ = *in++, col++;
- break;
-
- case ' ': case '\t':
- /* Squeeze all other whitespace down to one space. */
- while (*in == ' ' || *in == '\t')
- in++;
- *out++ = ' ', col++;
- break;
-
- default:
- /* Copy other chars unchanged. */
- *out++ = *in++, col++;
- break;
- }
- }
-
- *out = 0;
-
- /* Strip trailing whitespace */
- while (out > cmd2 && isspace (out[-1]))
- *(--out) = 0;
-
- return cmd2;
-}
-
-
-/* Returns a new string describing the shell command.
- This may be just the name of the program, capitalized.
- It also may be something from the resource database (gotten
- by looking for "hacks.XYZ.name", where XYZ is the program.)
- */
-char *
-make_hack_name (Display *dpy, const char *shell_command)
-{
- char *s = strdup (shell_command);
- char *s2;
- char res_name[255];
-
- for (s2 = s; *s2; s2++) /* truncate at first whitespace */
- if (isspace (*s2))
- {
- *s2 = 0;
- break;
- }
-
- s2 = strrchr (s, '/'); /* if pathname, take last component */
- if (s2)
- {
- s2 = strdup (s2+1);
- free (s);
- s = s2;
- }
-
- if (strlen (s) > 50) /* 51 is hereby defined as "unreasonable" */
- s[50] = 0;
-
- sprintf (res_name, "hacks.%s.name", s); /* resource? */
- s2 = get_string_resource (dpy, res_name, res_name);
- if (s2)
- {
- free (s);
- return s2;
- }
-
- for (s2 = s; *s2; s2++) /* if it has any capitals, return it */
- if (*s2 >= 'A' && *s2 <= 'Z')
- return s;
-
- if (s[0] >= 'a' && s[0] <= 'z') /* else cap it */
- s[0] -= 'a'-'A';
- if (s[0] == 'X' && s[1] >= 'a' && s[1] <= 'z') /* (magic leading X) */
- s[1] -= 'a'-'A';
- if (s[0] == 'G' && s[1] == 'l' &&
- s[2] >= 'a' && s[2] <= 'z') /* (magic leading GL) */
- s[1] -= 'a'-'A',
- s[2] -= 'a'-'A';
- return s;
-}
-
-
-char *
-format_hack (Display *dpy, screenhack *hack, Bool wrap_p)
-{
- int tab = 32;
- int size;
- char *h2, *out, *s;
- int col = 0;
-
- char *def_name = make_hack_name (dpy, hack->command);
-
- /* Don't ever write out a name for a hack if it's the same as the default.
- */
- if (hack->name && !strcmp (hack->name, def_name))
- {
- free (hack->name);
- hack->name = 0;
- }
- free (def_name);
-
- size = (2 * (strlen(hack->command) +
- (hack->visual ? strlen(hack->visual) : 0) +
- (hack->name ? strlen(hack->name) : 0) +
- tab));
- h2 = (char *) malloc (size);
- out = h2;
-
- if (!hack->enabled_p) *out++ = '-'; /* write disabled flag */
-
- if (hack->visual && *hack->visual) /* write visual name */
- {
- if (hack->enabled_p) *out++ = ' ';
- *out++ = ' ';
- strcpy (out, hack->visual);
- out += strlen (hack->visual);
- *out++ = ':';
- *out++ = ' ';
- }
-
- *out = 0;
- col = string_columns (h2, strlen (h2), 0);
-
- if (hack->name && *hack->name) /* write pretty name */
- {
- int L = (strlen (hack->name) + 2);
- if (L + col < tab)
- out = stab_to (out, col, tab - L - 2);
- else
- *out++ = ' ';
- *out++ = '"';
- strcpy (out, hack->name);
- out += strlen (hack->name);
- *out++ = '"';
- *out = 0;
-
- col = string_columns (h2, strlen (h2), 0);
- if (wrap_p && col >= tab)
- out = stab_to (out, col, 77);
- else
- *out++ = ' ';
-
- if (out >= h2+size) abort();
- }
-
- *out = 0;
- col = string_columns (h2, strlen (h2), 0);
- out = stab_to (out, col, tab); /* indent */
-
- if (out >= h2+size) abort();
- s = format_command (hack->command, wrap_p);
- strcpy (out, s);
- out += strlen (s);
- free (s);
- *out = 0;
-
- return h2;
-}
-
-
-static void
-get_screenhacks (Display *dpy, saver_preferences *p)
-{
- int i, j;
- int start = 0;
- int end = 0;
- int size;
- char *d;
-
- d = get_string_resource (dpy, "monoPrograms", "MonoPrograms");
- if (d && !*d) { free(d); d = 0; }
- if (!d)
- d = get_string_resource (dpy, "colorPrograms", "ColorPrograms");
- if (d && !*d) { free(d); d = 0; }
-
- if (d)
- {
- fprintf (stderr,
- "%s: the `monoPrograms' and `colorPrograms' resources are obsolete;\n\
- see the manual for details.\n", blurb());
- free(d);
- }
-
- d = get_string_resource (dpy, "programs", "Programs");
-
- free_screenhack_list (p->screenhacks, p->screenhacks_count);
- p->screenhacks = 0;
- p->screenhacks_count = 0;
-
- if (!d || !*d)
- return;
-
- size = strlen (d);
-
-
- /* Count up the number of newlines (which will be equal to or larger than
- one less than the number of hacks.)
- */
- for (i = j = 0; d[i]; i++)
- if (d[i] == '\n')
- j++;
- j++;
-
- p->screenhacks = (screenhack **) calloc (j + 1, sizeof (screenhack *));
-
- /* Iterate over the lines in `d' (the string with newlines)
- and make new strings to stuff into the `screenhacks' array.
- */
- p->screenhacks_count = 0;
- while (start < size)
- {
- /* skip forward over whitespace. */
- while (d[start] == ' ' || d[start] == '\t' || d[start] == '\n')
- start++;
-
- /* skip forward to newline or end of string. */
- end = start;
- while (d[end] != 0 && d[end] != '\n')
- end++;
-
- /* null terminate. */
- d[end] = 0;
-
- p->screenhacks[p->screenhacks_count++] = parse_screenhack (d + start);
- if (p->screenhacks_count >= i)
- abort();
-
- start = end+1;
- }
-
- free (d);
-
- if (p->screenhacks_count == 0)
- {
- free (p->screenhacks);
- p->screenhacks = 0;
- }
-}
-
-
-/* Make sure all the values in the preferences struct are sane.
- */
-static void
-stop_the_insanity (saver_preferences *p)
-{
- if (p->passwd_timeout <= 0) p->passwd_timeout = 30000; /* 30 secs */
- if (p->timeout < 15000) p->timeout = 15000; /* 15 secs */
- if (p->cycle != 0 && p->cycle < 2000) p->cycle = 2000; /* 2 secs */
- if (p->pointer_timeout <= 0) p->pointer_timeout = 5000; /* 5 secs */
- if (p->notice_events_timeout <= 0)
- p->notice_events_timeout = 10000; /* 10 secs */
- if (p->fade_seconds <= 0 || p->fade_ticks <= 0)
- p->fade_p = False;
- if (! p->fade_p) p->unfade_p = False;
-
- /* The DPMS settings may have the value 0.
- But if they are negative, or are a range less than 10 seconds,
- reset them to sensible defaults. (Since that must be a mistake.)
- */
- if (p->dpms_standby != 0 &&
- p->dpms_standby < 10 * 1000)
- p->dpms_standby = 2 * 60 * 60 * 1000; /* 2 hours */
- if (p->dpms_suspend != 0 &&
- p->dpms_suspend < 10 * 1000)
- p->dpms_suspend = 2 * 60 * 60 * 1000; /* 2 hours */
- if (p->dpms_off != 0 &&
- p->dpms_off < 10 * 1000)
- p->dpms_off = 4 * 60 * 60 * 1000; /* 4 hours */
-
- /* suspend may not be greater than off, unless off is 0.
- standby may not be greater than suspend, unless suspend is 0.
- */
- if (p->dpms_off != 0 &&
- p->dpms_suspend > p->dpms_off)
- p->dpms_suspend = p->dpms_off;
- if (p->dpms_suspend != 0 &&
- p->dpms_standby > p->dpms_suspend)
- p->dpms_standby = p->dpms_suspend;
-
- /* These fixes above ignores the case
- suspend = 0 and standby > off ...
- */
- if (p->dpms_off != 0 &&
- p->dpms_standby > p->dpms_off)
- p->dpms_standby = p->dpms_off;
-
-
- if (p->dpms_standby == 0 && /* if *all* are 0, then DPMS is disabled */
- p->dpms_suspend == 0 &&
- p->dpms_off == 0 &&
- !(p->dpms_quickoff_p) /* ... but we want to do DPMS quick off */
- )
- p->dpms_enabled_p = False;
-
-
- /* Set watchdog timeout to about half of the cycle timeout, but
- don't let it be faster than 1/2 minute or slower than 1 minute.
- */
- p->watchdog_timeout = p->cycle * 0.6;
- if (p->watchdog_timeout < 27000) p->watchdog_timeout = 27000; /* 27 secs */
- if (p->watchdog_timeout > 57000) p->watchdog_timeout = 57000; /* 57 secs */
-
- if (p->pointer_hysteresis < 0) p->pointer_hysteresis = 0;
-/* if (p->pointer_hysteresis > 100) p->pointer_hysteresis = 100; */
-
- if (p->auth_warning_slack < 0) p->auth_warning_slack = 0;
- if (p->auth_warning_slack > 300) p->auth_warning_slack = 300;
-}
-
-
-Bool
-senesculent_p (void)
-{
- /* If you are in here because you're planning on disabling this warning
- before redistributing my software, please don't.
-
- I sincerely request that you do one of the following:
-
- 1: leave this code intact and this warning in place, -OR-
-
- 2: Remove xscreensaver from your distribution.
-
- I would seriously prefer that you not distribute my software at all
- than that you distribute one version and then never update it for
- years.
-
- I am *constantly* getting email from users reporting bugs that have
- been fixed for literally years who have no idea that the software
- they are running is years out of date. Yes, it would be great if we
- lived in the ideal world where people checked that they were running
- the latest release before they report a bug, but we don't. To most
- people, "running the latest release" is synonymous with "running the
- latest release that my distro packages for me."
-
- When they even bother to tell me what version they're running, I
- say, "That version is three years old!", and they say "But this is
- the latest version my distro ships". Then I say, "your distro
- sucks", and they say "but I don't know how to compile from source,
- herp derp I eat paste", and *everybody* goes away unhappy.
-
- It wastes an enormous amount of my time, but worse than that, it
- does a grave disservice to the users, who are stuck experiencing
- bugs that are already fixed! These users think they are running the
- latest release, and they are not. They would like to be running the
- actual latest release, but they don't know how, because their distro
- makes that very difficult for them. It's terrible for everyone, and
- kind of makes me regret ever having released this software in the
- first place.
-
- So seriously. I ask that if you're planning on disabling this
- obsolescence warning, that you instead just remove xscreensaver from
- your distro entirely. Everybody will be happier that way. Check
- out gnome-screensaver instead, I understand it's really nice.
-
- Of course, my license allows you to ignore me and do whatever the
- fuck you want, but as the author, I hope you will have the common
- courtesy of complying with my request.
-
- Thank you!
-
- jwz, 2014, 2016, 2018.
-
- PS: In particular, since Debian refuses to upgrade software on any
- kind of rational timeline, I have asked that they stop shipping
- xscreensaver at all. They have refused. Instead of upgrading the
- software, they simply patched out this warning.
-
- If you want to witness the sad state of the open source peanut
- gallery, look no farther than the comments on my blog:
- http://jwz.org/b/yiYo
-
- Many of these people fall back on their go-to argument of, "If it is
- legal, it must be right." If you believe in that rhetorical device
- then you are a terrible person, and possibly a sociopath.
-
- There are also the armchair lawyers who say "Well, instead of
- *asking* people to do the right thing out of common courtesy, you
- should just change your license to prohibit them from acting
- amorally." Again, this is the answer of a sociopath, but that aside,
- if you devote even a second's thought to this you will realize that
- the end result of this would be for distros like Debian to just keep
- shipping the last version with the old license and then never
- upgrading it again -- which would be the worst possible outcome for
- everyone involved, most especially the users.
- */
- time_t now = time ((time_t *) 0); /* d */
- struct tm *tm = localtime (&now); /* o */
- const char *s = screensaver_id; /* n */
- char mon[4], year[5]; /* ' */
- int m, y, mrnths; /* t */
- s = strchr (s, ' '); if (!s) abort(); s++; /* */
- s = strchr (s, '('); if (!s) abort(); s++; /* d */
- s = strchr (s, '-'); if (!s) abort(); s++; /* o */
- strncpy (mon, s, 3); /* o */
- mon[3] = 0; /* */
- s = strchr (s, '-'); if (!s) abort(); s++; /* e */
- strncpy (year, s, 4); /* e */
- year[4] = 0; /* t */
- y = atoi (year); /* , */
- if (!strcmp(mon, "Jan")) m = 0; /* */
- else if (!strcmp(mon, "Feb")) m = 1; /* s */
- else if (!strcmp(mon, "Mar")) m = 2; /* t */
- else if (!strcmp(mon, "Apr")) m = 3; /* o */
- else if (!strcmp(mon, "May")) m = 4; /* p */
- else if (!strcmp(mon, "Jun")) m = 5; /* , */
- else if (!strcmp(mon, "Jul")) m = 6; /* */
- else if (!strcmp(mon, "Aug")) m = 7; /* s */
- else if (!strcmp(mon, "Sep")) m = 8; /* t */
- else if (!strcmp(mon, "Oct")) m = 9; /* a */
- else if (!strcmp(mon, "Nov")) m = 10; /* a */
- else if (!strcmp(mon, "Dec")) m = 11; /* a */
- else abort(); /* h */
- mrnths = ((((tm->tm_year + 1900) * 12) + tm->tm_mon) - /* h */
- (y * 12 + m)); /* h */
- /* p */
- return (mrnths >= 34); /* . */
+ FAIL:
+ if (buf) free (buf);
+ return -1;
}