Print this page
5433 at(1) doesn't properly handle being invoked from a path containing spaces
Reviewed by: Gary Mills <gary_mills@fastmail.fm>

@@ -99,10 +99,11 @@
 static void atime(struct tm *, struct tm *);
 static int not_this_project(char *);
 static char *mkjobname(time_t);
 static time_t parse_time(char *);
 static time_t gtime(struct tm *);
+static void escapestr(const char *);
 void atabort(char *)__NORETURN;
 void yyerror(void);
 extern int yyparse(void);
 
 extern void     audit_at_delete(char *, char *, int);

@@ -544,10 +545,27 @@
         tv = 60 * tv + tptr->tm_sec;
         return (tv);
 }
 
 /*
+ * Escape a string to be used inside the job shell script.
+ */
+static void
+escapestr(const char *str)
+{
+        char c;
+        (void) putchar('\'');
+        while ((c = *str++) != '\0') {
+                if (c != '\'')
+                        (void) putchar(c);
+                else
+                        (void) fputs("'\\''", stdout); /* ' -> '\'' */
+        }
+        (void) putchar('\'');
+}
+
+/*
  * make job file from proto + stdin
  */
 static void
 copy(char *jobfile, FILE *inputfile, int when)
 {

@@ -631,16 +649,16 @@
                                 (void) printf(": project: %d\n", project);
                 }
         }
 
         for (ep = environ; *ep; ep++) {
-                if (strchr(*ep, '\'') != NULL)
-                        continue;
                 if ((val = strchr(*ep, '=')) == NULL)
                         continue;
                 *val++ = '\0';
-                printf("export %s; %s='%s'\n", *ep, *ep, val);
+                (void) printf("export %s; %s=", *ep, *ep);
+                escapestr(val);
+                (void) putchar('\n');
                 *--val = '=';
         }
         if ((pfp = fopen(pname1, "r")) == NULL &&
             (pfp = fopen(pname, "r")) == NULL)
                 atabort("no prototype");

@@ -676,11 +694,11 @@
                         }
                         /* change back afterwards */
                         if (seteuid(effeusr) < 0) {
                                 atabort(CANTCHUID);
                         }
-                        printf("%s", dirbuf);
+                        escapestr(dirbuf);
                         break;
                 case 'm':
                         printf("%o", um);
                         break;
                 case '<':