http://packetstorm.tacticalflex.com/UNIX/admin/xscreensaver-3.27.tar.gz
[xscreensaver] / driver / prefs.c
index 2b8be46d05b5a3a6b8dff8c7315beda2d2b08157..392394d1251f2e5fb293311c2f63a23568250f2e 100644 (file)
@@ -94,6 +94,22 @@ chase_symlinks (const char *file)
 }
 
 
+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)
 {
@@ -101,7 +117,18 @@ init_file_name (void)
 
   if (!file)
     {
-      struct passwd *p = getpwuid (getuid ());
+      uid_t uid = getuid ();
+      struct passwd *p = getpwuid (uid);
+
+      if (i_am_a_nobody (uid))
+        /* 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.)
+         */
+        uid = 0;
+
+      p = getpwuid (uid);
 
       if (!p || !p->pw_name || !*p->pw_name)
        {
@@ -533,9 +560,11 @@ write_entry (FILE *out, const char *key, const char *value)
   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);
@@ -555,7 +584,7 @@ write_init_file (saver_preferences *p, const char *version_string)
 
   if (n2) name = n2;
 
-  if (p->verbose_p)
+  if (verbose_p)
     fprintf (stderr, "%s: writing \"%s\".\n", blurb(), name);
 
   unlink (tmp_name);
@@ -571,13 +600,19 @@ write_init_file (saver_preferences *p, const char *version_string)
 
   /* 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));
@@ -777,6 +812,8 @@ write_init_file (saver_preferences *p, const char *version_string)
          /* 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
@@ -791,6 +828,7 @@ write_init_file (saver_preferences *p, const char *version_string)
 
  END:
   if (n2) free (n2);
+  return status;
 }
 
 \f