ftp://ftp.smr.ru/pub/0/FreeBSD/releases/distfiles/xscreensaver-3.16.tar.gz
[xscreensaver] / driver / subprocs.c
index a9fec53c0bf5d512d0d35d0359951417fb0c9ad5..fcfdf897f7803bbea2ab9c0732dbb5146ef26a8b 100644 (file)
@@ -169,9 +169,49 @@ exec_complex_command (const char *shell, const char *command)
 {
   char *av[5];
   int ac = 0;
-  char *command2 = (char *) malloc (strlen (command) + 6);
-  memcpy (command2, "exec ", 5);
-  memcpy (command2 + 5, command, strlen (command) + 1);
+  char *command2 = (char *) malloc (strlen (command) + 10);
+  const char *s;
+  int got_eq = 0;
+  const char *after_vars;
+
+  /* Skip leading whitespace.
+   */
+  while (*command == ' ' || *command == '\t')
+    command++;
+
+  /* If the string has a series of tokens with "=" in them at them, set
+     `after_vars' to point into the string after those tokens and any
+     trailing whitespace.  Otherwise, after_vars == command.
+   */
+  after_vars = command;
+  for (s = command; *s; s++)
+    {
+      if (*s == '=') got_eq = 1;
+      else if (*s == ' ')
+        {
+          if (got_eq)
+            {
+              while (*s == ' ' || *s == '\t')
+                s++;
+              after_vars = s;
+              got_eq = 0;
+            }
+          else
+            break;
+        }
+    }
+
+  *command2 = 0;
+  strncat (command2, command, after_vars - command);
+  strcat (command2, "exec ");
+  strcat (command2, after_vars);
+
+  /* We have now done these transformations:
+     "foo -x -y"               ==>  "exec foo -x -y"
+     "BLAT=foop      foo -x"   ==>  "BLAT=foop      exec foo -x"
+     "BLAT=foop A=b  foo -x"   ==>  "BLAT=foop A=b  exec foo -x"
+   */
+
 
   /* Invoke the shell as "/bin/sh -c 'exec prog -arg -arg ...'" */
   av [ac++] = (char *) shell;
@@ -248,6 +288,17 @@ exec_screenhack (saver_info *si, const char *command)
   Bool hairy_p = !!strpbrk (command, "*?$&!<>[];`'\\\"=");
   /* note: = is in the above because of the sh syntax "FOO=bar cmd". */
 
+  if (getuid() == (uid_t) 0 || geteuid() == (uid_t) 0)
+    {
+      /* If you're thinking of commenting this out, think again.
+         If you do so, you will open a security hole.  Mail jwz
+         so that he may enlighten you as to the error of your ways.
+       */
+      fprintf (stderr, "%s: we're still running as root!  Disaster!\n",
+               blurb());
+      saver_exit (si, 1, 0);
+    }
+
   if (p->verbose_p)
     fprintf (stderr, "%s: spawning \"%s\" in pid %lu%s.\n",
             blurb(), command, (unsigned long) getpid (),
@@ -323,19 +374,32 @@ make_job (pid_t pid, const char *cmd)
   static char name [1024];
   const char *in = cmd;
   char *out = name;
+  int got_eq = 0;
+  int first = 1;
 
   clean_job_list();
 
+ AGAIN:
   while (isspace(*in)) in++;           /* skip whitespace */
-  while (!isspace(*in) && *in != ':')
+  while (!isspace(*in) && *in != ':') {
+    if (*in == '=') got_eq = 1;
     *out++ = *in++;                    /* snarf first token */
+  }
+
+  if (got_eq)                          /* if the first token was FOO=bar */
+    {                                  /* then get the next token instead. */
+      got_eq = 0;
+      out = name;
+      first = 0;
+      goto AGAIN;
+    }
+
   while (isspace(*in)) in++;           /* skip whitespace */
-  if (*in == ':')                      /* token was a visual name; skip it. */
+  if (first && *in == ':')             /* token was a visual name; skip it. */
     {
-      in++;
       out = name;
-      while (isspace(*in)) in++;               /* skip whitespace */
-      while (!isspace(*in)) *out++ = *in++;    /* snarf first token */
+      first = 0;
+      goto AGAIN;
     }
   *out = 0;
 
@@ -739,7 +803,7 @@ select_visual_of_hack (saver_screen_info *ssi, const char *hack)
               (si->demoing_p
                ? "%s: warning, no \"%s\" visual for \"%s\".\n"
                : "%s: no \"%s\" visual; skipping \"%s\".\n"),
-              blurb(), (vis ? vis : "???"), in);
+              blurb(), (*vis ? vis : "???"), in);
     }
 
   return selected;
@@ -800,6 +864,9 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p)
         Unless this hack was specified explicitly, in which case,
         use it regardless.
        */
+      if (force)
+        select_visual_of_hack (ssi, hack);
+        
       if (!force &&
          (!hack_enabled_p (hack) ||
           !select_visual_of_hack (ssi, hack)))