static void get_screenhacks (saver_preferences *p);
+static char *format_command (const char *cmd, Bool wrap_p);
+
+
+static char *
+chase_symlinks (const char *file)
+{
+# ifdef HAVE_REALPATH
+ if (file)
+ {
+ char buf [2048];
+ if (realpath (file, buf))
+ return strdup (buf);
+
+ sprintf (buf, "%s: realpath", blurb());
+ perror(buf);
+ }
+# endif /* HAVE_REALPATH */
+ return 0;
+}
const char *
{
const char *name = init_file_name();
const char *suffix = ".tmp";
+
+ char *n2 = chase_symlinks (name);
+ if (n2) name = n2;
+
if (!name || !*name)
file = "";
else
strcpy(file, name);
strcat(file, suffix);
}
+
+ if (n2) free (n2);
}
if (file && *file)
if (!p->db) abort();
handle_entry (&p->db, key, value, name, line);
}
+ fclose (in);
free(buf);
p->init_file_date = write_date;
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 *v2 = v;
char *nl = 0;
int col;
- Bool do_visual_kludge = (!strcmp(key, "programs"));
- Bool do_wrap = do_visual_kludge;
- int tab = (do_visual_kludge ? 16 : 23);
- int tab2 = 3;
+ Bool programs_p = (!strcmp(key, "programs"));
+ int tab = (programs_p ? 32 : 16);
Bool first = True;
fprintf(out, "%s:", key);
while (1)
{
- char *s;
- Bool disabled_p = False;
-
- v2 = strip(v2);
+ if (!programs_p)
+ v2 = strip(v2);
nl = strchr(v2, '\n');
if (nl)
*nl = 0;
- if (do_visual_kludge && *v2 == '-')
- {
- disabled_p = True;
- v2++;
- v2 = strip(v2);
- }
-
- if (first && disabled_p)
- first = False;
+ 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 = tab_to (out, col, 75);
+ fprintf (out, " \\n\\\n");
col = 0;
}
- if (disabled_p)
- {
- fprintf(out, "-");
- col++;
- }
-
- s = (do_visual_kludge ? strpbrk(v2, " \t\n:") : 0);
- if (s && *s == ':')
- col = tab_to (out, col, tab2);
- else
- col = tab_to (out, col, tab);
+ if (!programs_p)
+ col = tab_to (out, col, tab);
- if (do_wrap &&
- strlen(v2) + col > 75)
+ if (programs_p &&
+ string_columns(v2, strlen (v2), col) + col > 75)
{
- int L = strlen(v2);
+ int L = strlen (v2);
int start = 0;
int end = start;
while (start < L)
while (v2[end] != ' ' && v2[end] != '\t' &&
v2[end] != '\n' && v2[end] != 0)
end++;
- if (col + (end - start) >= 74)
+ if (string_columns (v2 + start, (end - start), col) >= 74)
{
col = tab_to (out, col, 75);
fprintf(out, " \\\n");
start++;
}
+ col = string_columns (v2 + start, (end - start), col);
while (start < end)
- {
- fputc(v2[start++], out);
- col++;
- }
+ fputc(v2[start++], out);
}
}
else
{
fprintf (out, "%s", v2);
- col += strlen(v2);
+ col += string_columns(v2, strlen (v2), col);
}
if (nl)
free(v);
}
-void
-write_init_file (saver_preferences *p, const char *version_string)
+int
+write_init_file (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;
char *stderr_font;
FILE *out;
- if (!name) return;
+ if (!name) goto END;
+
+ if (n2) name = n2;
- if (p->verbose_p)
+ if (verbose_p)
fprintf (stderr, "%s: writing \"%s\".\n", blurb(), name);
unlink (tmp_name);
sprintf(buf, "%s: error writing \"%s\"", blurb(), name);
perror(buf);
free(buf);
- return;
+ 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.
+ 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;
- mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
+ 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));
tmp_name, (unsigned int) mode);
perror(buf);
free(buf);
- return;
+ goto END;
}
}
stderr_font = get_string_resource ("font", "Font");
i = 0;
- for (j = 0; j < p->screenhacks_count; j++)
- i += strlen(p->screenhacks[j]) + 2;
{
- char *ss = programs = (char *) malloc(i + 10);
+ 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 (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, p->screenhacks[j]);
+ strcat (ss, hack_strings[j]);
+ free (hack_strings[j]);
ss += strlen(ss);
*ss++ = '\n';
*ss = 0;
perror(buf);
unlink (tmp_name);
free(buf);
- return;
+ goto END;
}
if (rename (tmp_name, name) != 0)
perror(buf);
unlink (tmp_name);
free(buf);
- return;
+ goto END;
}
else
{
/* 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
perror(buf);
free(buf);
unlink (tmp_name);
- return;
+ goto END;
}
+
+ END:
+ if (n2) free (n2);
+ return status;
}
\f
*/
if (p->passwd_timeout <= 0) p->passwd_timeout = 30000; /* 30 secs */
if (p->timeout < 10000) p->timeout = 10000; /* 10 secs */
- if (p->cycle < 0) p->cycle = 0;
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->fade_p = False;
if (! p->fade_p) p->unfade_p = False;
- if (p->verbose_p && !p->fading_possible_p && (p->fade_p || p->unfade_p))
- {
- fprintf (stderr, "%s: there are no PseudoColor or GrayScale visuals.\n",
- blurb());
- fprintf (stderr, "%s: ignoring the request for fading/unfading.\n",
- blurb());
- }
-
- p->watchdog_timeout = p->cycle;
+ p->watchdog_timeout = p->cycle * 0.6;
if (p->watchdog_timeout < 30000) p->watchdog_timeout = 30000; /* 30 secs */
if (p->watchdog_timeout > 3600000) p->watchdog_timeout = 3600000; /* 1 hr */
/* Parsing the programs resource.
*/
-static char *
-reformat_hack (const char *hack)
+screenhack *
+parse_screenhack (const char *line)
{
- int i;
- const char *in = hack;
- int indent = 15;
- char *h2 = (char *) malloc(strlen(in) + indent + 2);
- char *out = h2;
- Bool disabled_p = False;
+ screenhack *h = (screenhack *) calloc (1, sizeof(*h));
+ const char *s;
- while (isspace(*in)) in++; /* skip whitespace */
+ h->enabled_p = True;
- if (*in == '-') /* Handle a leading "-". */
+ while (isspace(*line)) line++; /* skip whitespace */
+ if (*line == '-') /* handle "-" */
{
- in++;
- hack = in;
- *out++ = '-';
- *out++ = ' ';
- disabled_p = True;
- while (isspace(*in)) in++;
+ 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
{
- *out++ = ' ';
- *out++ = ' ';
+ 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 */
}
- while (*in && !isspace(*in) && *in != ':')
- *out++ = *in++; /* snarf first token */
- while (isspace(*in)) in++; /* skip whitespace */
-
- if (*in == ':')
- *out++ = *in++; /* copy colon */
- else
+ if (*line == '"') /* handle "name" */
{
- in = hack;
- out = h2 + 2; /* reset to beginning */
+ 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 */
}
- *out = 0;
+ h->command = format_command (line, False); /* handle command */
+ return h;
+}
+
+
+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);
+}
- while (isspace(*in)) in++; /* skip whitespace */
- for (i = strlen(h2); i < indent; i++) /* indent */
- *out++ = ' ';
- /* copy the rest of the line. */
+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"
switch (*in)
{
case '\'': case '"': case '`': case '\\':
- {
- /* Metachars are scary. Copy the rest of the line unchanged. */
- while (*in)
- *out++ = *in++;
- }
+ /* Metachars are scary. Copy the rest of the line unchanged. */
+ while (*in)
+ *out++ = *in++, col++;
break;
+
case ' ': case '\t':
- {
- while (*in == ' ' || *in == '\t')
- in++;
- *out++ = ' ';
- }
+ /* Squeeze all other whitespace down to one space. */
+ while (*in == ' ' || *in == '\t')
+ in++;
+ *out++ = ' ', col++;
break;
+
default:
- *out++ = *in++;
+ /* Copy other chars unchanged. */
+ *out++ = *in++, col++;
break;
}
}
+
+ *out = 0;
+
+ /* Strip trailing whitespace */
+ while (out > cmd2 && isspace (out[-1]))
+ *(--out) = 0;
+
+ return cmd2;
+}
+
+
+char *
+format_hack (screenhack *hack, Bool wrap_p)
+{
+ int tab = 32;
+ int size = (2 * (strlen(hack->command) +
+ (hack->visual ? strlen(hack->visual) : 0) +
+ (hack->name ? strlen(hack->name) : 0) +
+ tab));
+ char *h2 = (char *) malloc (size);
+ char *out = h2;
+ char *s;
+ int col = 0;
+
+ 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);
+ *out += strlen(out);
+ }
+ else
+ *out++ = ' ';
- /* strip trailing whitespace. */
- out = out-1;
- while (out > h2 && (*out == ' ' || *out == '\t' || *out == '\n'))
- *out-- = 0;
+ 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;
}
{
for (i = 0; i < p->screenhacks_count; i++)
if (p->screenhacks[i])
- free (p->screenhacks[i]);
+ free_screenhack (p->screenhacks[i]);
free(p->screenhacks);
p->screenhacks = 0;
}
i++;
i++;
- p->screenhacks = (char **) calloc (sizeof (char *), i+1);
+ p->screenhacks = (screenhack **) calloc (sizeof (screenhack *), i+1);
/* Iterate over the lines in `d' (the string with newlines)
and make new strings to stuff into the `screenhacks' array.
/* null terminate. */
d[end] = 0;
- p->screenhacks[p->screenhacks_count++] = reformat_hack (d + start);
+ p->screenhacks[p->screenhacks_count++] = parse_screenhack (d + start);
if (p->screenhacks_count >= i)
abort();