http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.02.tar.gz
[xscreensaver] / driver / demo-Gtk.c
index 3c83e8aba1049255ad7dd81a101326a0183b84ae..dc6f46551d0e898c2ce1a003ae71b538d22d92f9 100644 (file)
@@ -33,7 +33,9 @@
 #endif /* HAVE_UNAME */
 
 #include <stdio.h>
+#include <time.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 
 
 #include <signal.h>
 #include <string.h>
 #include <ctype.h>
 
+
+/* from exec.c */
+extern void exec_command (const char *shell, const char *command, int nice);
+
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
@@ -125,7 +131,6 @@ typedef struct {
   int subproc_timer_id;                /* timer to delay subproc launch */
   int subproc_check_timer_id;  /* timer to check whether it started up */
   int subproc_check_countdown;  /* how many more checks left */
-  int preview_nice_level;
 
   int *list_elt_to_hack_number;        /* table for sorting the hack list */
   int *hack_number_to_list_elt;        /* the inverse table */
@@ -1869,8 +1874,18 @@ populate_prefs_page (state *s)
   saver_preferences *p = &s->prefs;
   char str[100];
 
+  /* The file supports timeouts of less than a minute, but the GUI does
+     not, so throttle the values to be at least one minute (since "0" is
+     a bad rounding choice...)
+   */
+# define THROTTLE(NAME) if (p->NAME != 0 && p->NAME < 60000) p->NAME = 60000
+  THROTTLE (timeout);
+  THROTTLE (cycle);
+  THROTTLE (passwd_timeout);
+# undef THROTTLE
+
 # define FMT_MINUTES(NAME,N) \
-    sprintf (str, "%d", ((N) + 59) / (60 * 1000)); \
+    sprintf (str, "%d", (((N / 1000) + 59) / 60)); \
     gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, (NAME))), str)
 
 # define FMT_SECONDS(NAME,N) \
@@ -2007,6 +2022,10 @@ populate_popup_window (state *s)
   screenhack *hack = (hack_number >= 0 ? p->screenhacks[hack_number] : 0);
   char *doc_string = 0;
 
+  /* #### not in Gtk 1.2
+  gtk_label_set_selectable (doc);
+   */
+
 # ifdef HAVE_XML
   if (s->cdata)
     {
@@ -2783,38 +2802,6 @@ kill_preview_subproc (state *s)
 }
 
 
-static void
-exec_program (const char *cmd, int nice_level)
-{
-  char *av[1024];
-  int ac = 0;
-  char *token = strtok (strdup(cmd), " \t");
-  while (token)
-    {
-      av[ac++] = token;
-      token = strtok(0, " \t");
-    }
-  av[ac] = 0;
-
-  nice (nice_level - nice (0));
-
-  usleep (250000);  /* pause for 1/4th second before launching, to give the
-                       previous program time to die and flush its X buffer,
-                       so we don't get leftover turds on the window. */
-
-  execvp (av[0], av);                  /* shouldn't return. */
-
-  {
-    char buf [512];
-    sprintf (buf, "%s: could not execute \"%s\"", blurb(), av[0]);
-    perror (buf);
-  }
-  fflush(stderr);
-  fflush(stdout);
-  exit (1);    /* Note that this only exits a child fork.  */
-}
-
-
 /* Immediately and unconditionally launches the given process,
    after appending the -window-id option; sets running_preview_pid.
  */
@@ -2823,10 +2810,8 @@ launch_preview_subproc (state *s)
 {
   saver_preferences *p = &s->prefs;
   Window id;
-  Bool hairy_p;
-  char *new_cmd;
+  char *new_cmd = 0;
   pid_t forked;
-  int nice_level = nice (0) - p->nice_inferior;
   const char *cmd = s->desired_preview_cmd;
 
   GtkWidget *pr = name_to_widget (s, "preview");
@@ -2837,7 +2822,7 @@ launch_preview_subproc (state *s)
   if (s->preview_suppressed_p)
     {
       kill_preview_subproc (s);
-      return;
+      goto DONE;
     }
 
   new_cmd = malloc (strlen (cmd) + 40);
@@ -2855,22 +2840,12 @@ launch_preview_subproc (state *s)
       sprintf (new_cmd + strlen (new_cmd), " -window-id 0x%X", id);
     }
 
-  hairy_p = (new_cmd && !!strpbrk (new_cmd, "*?$&!<>[];`'\\\"="));
-  if (hairy_p)
-    {
-      /* Command requires a full shell?  Forget it. */
-      free (new_cmd);
-      new_cmd = 0;
-      if (s->debug_p)
-        fprintf (stderr, "%s: command is hairy: not previewing\n", blurb());
-    }
-
   kill_preview_subproc (s);
   if (! new_cmd)
     {
       s->running_preview_error_p = True;
       clear_preview_window (s);
-      return;
+      goto DONE;
     }
 
   switch ((int) (forked = fork ()))
@@ -2881,13 +2856,22 @@ launch_preview_subproc (state *s)
         sprintf (buf, "%s: couldn't fork", blurb());
         perror (buf);
         s->running_preview_error_p = True;
-        return;
+        goto DONE;
+        break;
       }
     case 0:
       {
         close (ConnectionNumber (GDK_DISPLAY()));
-        exec_program (new_cmd, nice_level);
-        abort();
+
+        usleep (250000);  /* pause for 1/4th second before launching, to give
+                             the previous program time to die and flush its X
+                             buffer, so we don't get leftover turds on the
+                             window. */
+
+        exec_command (p->shell, new_cmd, p->nice_inferior);
+        /* Don't bother printing an error message when we are unable to
+           exec subprocesses; we handle that by polling the pid later. */
+        exit (1);  /* exits child fork */
         break;
 
       default:
@@ -2907,6 +2891,10 @@ launch_preview_subproc (state *s)
     }
 
   schedule_preview_check (s);
+
+ DONE:
+  if (new_cmd) free (new_cmd);
+  new_cmd = 0;
 }
 
 
@@ -2933,6 +2921,11 @@ hack_environment (state *s)
   if (s->debug_p)
     fprintf (stderr, "%s: %s\n", blurb(), ndpy);
 
+  /* don't free(ndpy) -- some implementations of putenv (BSD 4.4, glibc
+     2.0) copy the argument, but some (libc4,5, glibc 2.1.2) do not.
+     So we must leak it (and/or the previous setting).  Yay.
+   */
+
   if (def_path && *def_path)
     {
       const char *opath = getenv("PATH");
@@ -2944,6 +2937,7 @@ hack_environment (state *s)
 
       if (putenv (npath))
        abort ();
+      /* do not free(npath) -- see above */
 
       if (s->debug_p)
         fprintf (stderr, "%s: added \"%s\" to $PATH\n", blurb(), def_path);
@@ -3170,7 +3164,7 @@ static void
 the_network_is_not_the_computer (state *s)
 {
   Display *dpy = GDK_DISPLAY();
-  char *rversion, *ruser, *rhost;
+  char *rversion = 0, *ruser = 0, *rhost = 0;
   char *luser, *lhost;
   char *msg = 0;
   struct passwd *p = getpwuid (getuid ());
@@ -3281,6 +3275,9 @@ the_network_is_not_the_computer (state *s)
   if (*msg)
     warning_dialog (s->toplevel_widget, msg, True, 1);
 
+  if (rversion) free (rversion);
+  if (ruser) free (ruser);
+  if (rhost) free (rhost);
   free (msg);
 }
 
@@ -3455,7 +3452,10 @@ main (int argc, char **argv)
   }
 
 #ifdef DEFAULT_ICONDIR  /* from -D on compile line */
-  add_pixmap_directory (DEFAULT_ICONDIR);
+  {
+    const char *dir = DEFAULT_ICONDIR;
+    if (*dir) add_pixmap_directory (dir);
+  }
 #endif
 
   /* This is gross, but Gtk understands --display and not -display...
@@ -3773,12 +3773,12 @@ main (int argc, char **argv)
       capplet = capplet_widget_new ();
 
       /* Make there be a "Close" button instead of "OK" and "Cancel" */
+# ifdef HAVE_CRAPPLET_IMMEDIATE
       capplet_widget_changes_are_immediate (CAPPLET_WIDGET (capplet));
+# endif /* HAVE_CRAPPLET_IMMEDIATE */
 
-# if 1
-        /* In crapplet-mode, take off the menubar. */
-        gtk_widget_hide (name_to_widget (s, "menubar"));
-# endif
+      /* In crapplet-mode, take off the menubar. */
+      gtk_widget_hide (name_to_widget (s, "menubar"));
 
       /* Reparent our top-level container to be a child of the capplet
          window.