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>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/cron/at.c
          +++ new/usr/src/cmd/cron/at.c
↓ open down ↓ 93 lines elided ↑ open up ↑
  94   94  static int list_jobs(int, char **, int, int);
  95   95  static int remove_jobs(int, char **, char *);
  96   96  static void usage(void);
  97   97  static void catch(int);
  98   98  static void copy(char *, FILE *, int);
  99   99  static void atime(struct tm *, struct tm *);
 100  100  static int not_this_project(char *);
 101  101  static char *mkjobname(time_t);
 102  102  static time_t parse_time(char *);
 103  103  static time_t gtime(struct tm *);
      104 +static void escapestr(const char *);
 104  105  void atabort(char *)__NORETURN;
 105  106  void yyerror(void);
 106  107  extern int yyparse(void);
 107  108  
 108  109  extern void     audit_at_delete(char *, char *, int);
 109  110  extern int      audit_at_create(char *, int);
 110  111  extern int      audit_cron_is_anc_name(char *);
 111  112  extern int      audit_cron_delete_anc_file(char *, char *);
 112  113  
 113  114  /*
↓ open down ↓ 425 lines elided ↑ open up ↑
 539  540          for (i = 0; i < tptr->tm_mon; ++i)
 540  541                  tv += dmsize[i];
 541  542          tv += tptr->tm_mday - 1;
 542  543          tv = 24 * tv + tptr->tm_hour;
 543  544          tv = 60 * tv + tptr->tm_min;
 544  545          tv = 60 * tv + tptr->tm_sec;
 545  546          return (tv);
 546  547  }
 547  548  
 548  549  /*
      550 + * Escape a string to be used inside the job shell script.
      551 + */
      552 +static void
      553 +escapestr(const char *str)
      554 +{
      555 +        char c;
      556 +        (void) putchar('\'');
      557 +        while ((c = *str++) != '\0') {
      558 +                if (c != '\'')
      559 +                        (void) putchar(c);
      560 +                else
      561 +                        (void) fputs("'\\''", stdout); /* ' -> '\'' */
      562 +        }
      563 +        (void) putchar('\'');
      564 +}
      565 +
      566 +/*
 549  567   * make job file from proto + stdin
 550  568   */
 551  569  static void
 552  570  copy(char *jobfile, FILE *inputfile, int when)
 553  571  {
 554  572          int c;
 555  573          FILE *pfp;
 556  574          char *shell;
 557  575          char    dirbuf[PATH_MAX + 1];
 558  576          char    line[LINE_MAX];
↓ open down ↓ 67 lines elided ↑ open up ↑
 626  644                          atabort(INVALIDUSER);
 627  645                  project = getprojid();
 628  646                  pprj = getprojbyid(project, &prj, pbuf, sizeof (pbuf));
 629  647                  if (pprj != NULL) {
 630  648                          if (inproj(user, pprj->pj_name, pbuf2, sizeof (pbuf2)))
 631  649                                  (void) printf(": project: %d\n", project);
 632  650                  }
 633  651          }
 634  652  
 635  653          for (ep = environ; *ep; ep++) {
 636      -                if (strchr(*ep, '\'') != NULL)
 637      -                        continue;
 638  654                  if ((val = strchr(*ep, '=')) == NULL)
 639  655                          continue;
 640  656                  *val++ = '\0';
 641      -                printf("export %s; %s='%s'\n", *ep, *ep, val);
      657 +                (void) printf("export %s; %s=", *ep, *ep);
      658 +                escapestr(val);
      659 +                (void) putchar('\n');
 642  660                  *--val = '=';
 643  661          }
 644  662          if ((pfp = fopen(pname1, "r")) == NULL &&
 645  663              (pfp = fopen(pname, "r")) == NULL)
 646  664                  atabort("no prototype");
 647  665          /*
 648  666           * Put in a line to run the proper shell using the rest of
 649  667           * the file as input.  Note that 'exec'ing the shell will
 650  668           * cause sh() to leave a /tmp/sh### file around. (1053807)
 651  669           */
↓ open down ↓ 19 lines elided ↑ open up ↑
 671  689                                  atabort(CANTCHUID);
 672  690                          }
 673  691                          if (getcwd(dirbuf, sizeof (dirbuf)) == NULL) {
 674  692                                  atabort(
 675  693                                      "can't obtain current working directory");
 676  694                          }
 677  695                          /* change back afterwards */
 678  696                          if (seteuid(effeusr) < 0) {
 679  697                                  atabort(CANTCHUID);
 680  698                          }
 681      -                        printf("%s", dirbuf);
      699 +                        escapestr(dirbuf);
 682  700                          break;
 683  701                  case 'm':
 684  702                          printf("%o", um);
 685  703                          break;
 686  704                  case '<':
 687  705                          if (ulimit_flag) {
 688  706                                  if (getrlimit(RLIMIT_FSIZE, &rlp) == 0) {
 689  707                                          if (rlp.rlim_cur == RLIM_INFINITY)
 690  708                                                  printf("ulimit unlimited\n");
 691  709                                          else
↓ open down ↓ 297 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX