84 " at [-c|-k|-s] [-m] [-f file] [-p project] [-q queuename] "\
85 "timespec\n"\
86 " at -l [-p project] [-q queuename] [at_job_id...]\n"\
87 " at -r at_job_id ...\n"
88
89 #define FORMAT "%a %b %e %H:%M:%S %Y"
90
91 static int leap(int);
92 static int atoi_for2(char *);
93 static int check_queue(char *, int);
94 static int list_jobs(int, char **, int, int);
95 static int remove_jobs(int, char **, char *);
96 static void usage(void);
97 static void catch(int);
98 static void copy(char *, FILE *, int);
99 static void atime(struct tm *, struct tm *);
100 static int not_this_project(char *);
101 static char *mkjobname(time_t);
102 static time_t parse_time(char *);
103 static time_t gtime(struct tm *);
104 void atabort(char *)__NORETURN;
105 void yyerror(void);
106 extern int yyparse(void);
107
108 extern void audit_at_delete(char *, char *, int);
109 extern int audit_at_create(char *, int);
110 extern int audit_cron_is_anc_name(char *);
111 extern int audit_cron_delete_anc_file(char *, char *);
112
113 /*
114 * Error in getdate(3G)
115 */
116 static char *errlist[] = {
117 /* 0 */ "",
118 /* 1 */ "getdate: The DATEMSK environment variable is not set",
119 /* 2 */ "getdate: Error on \"open\" of the template file",
120 /* 3 */ "getdate: Error on \"stat\" of the template file",
121 /* 4 */ "getdate: The template file is not a regular file",
122 /* 5 */ "getdate: An error is encountered while reading the template",
123 /* 6 */ "getdate: Malloc(3C) failed",
529 * We call isleap since leap() adds
530 * 1900 onto any value passed
531 */
532
533 if (!leap(tptr->tm_year) && at.tm_mday == 29 && at.tm_mon == 1)
534 atabort("bad date - not a leap year");
535
536 if ((leap(tptr->tm_year)) && tptr->tm_mon >= 2)
537 ++tv;
538
539 for (i = 0; i < tptr->tm_mon; ++i)
540 tv += dmsize[i];
541 tv += tptr->tm_mday - 1;
542 tv = 24 * tv + tptr->tm_hour;
543 tv = 60 * tv + tptr->tm_min;
544 tv = 60 * tv + tptr->tm_sec;
545 return (tv);
546 }
547
548 /*
549 * make job file from proto + stdin
550 */
551 static void
552 copy(char *jobfile, FILE *inputfile, int when)
553 {
554 int c;
555 FILE *pfp;
556 char *shell;
557 char dirbuf[PATH_MAX + 1];
558 char line[LINE_MAX];
559 char **ep;
560 mode_t um;
561 char *val;
562 extern char **environ;
563 uid_t realusr, effeusr;
564 int ttyinput;
565 int ulimit_flag = 0;
566 struct rlimit rlp;
567 struct project prj, *pprj;
568 char pbuf[PROJECT_BUFSZ];
616 } else {
617 /*
618 * Check if current user is a member of current project.
619 * This check is done here to avoid setproject() failure
620 * later when the job gets executed. If current user does
621 * not belong to current project, user's default project
622 * will be used instead. This is achieved by not specifying
623 * the project (": project: <project>\n") in the job file.
624 */
625 if ((user = getuser(getuid())) == NULL)
626 atabort(INVALIDUSER);
627 project = getprojid();
628 pprj = getprojbyid(project, &prj, pbuf, sizeof (pbuf));
629 if (pprj != NULL) {
630 if (inproj(user, pprj->pj_name, pbuf2, sizeof (pbuf2)))
631 (void) printf(": project: %d\n", project);
632 }
633 }
634
635 for (ep = environ; *ep; ep++) {
636 if (strchr(*ep, '\'') != NULL)
637 continue;
638 if ((val = strchr(*ep, '=')) == NULL)
639 continue;
640 *val++ = '\0';
641 printf("export %s; %s='%s'\n", *ep, *ep, val);
642 *--val = '=';
643 }
644 if ((pfp = fopen(pname1, "r")) == NULL &&
645 (pfp = fopen(pname, "r")) == NULL)
646 atabort("no prototype");
647 /*
648 * Put in a line to run the proper shell using the rest of
649 * the file as input. Note that 'exec'ing the shell will
650 * cause sh() to leave a /tmp/sh### file around. (1053807)
651 */
652 printf("%s << '...the rest of this file is shell input'\n", shell);
653
654 um = umask(0);
655 while ((c = getc(pfp)) != EOF) {
656 if (c != '$')
657 putchar(c);
658 else switch (c = getc(pfp)) {
659 case EOF:
660 goto out;
661 case 'd':
662 /*
663 * Must obtain current working directory as the user
664 */
665
666 dirbuf[0] = '\0';
667 realusr = getuid();
668 effeusr = geteuid();
669 /* change euid for getcwd */
670 if (seteuid(realusr) < 0) {
671 atabort(CANTCHUID);
672 }
673 if (getcwd(dirbuf, sizeof (dirbuf)) == NULL) {
674 atabort(
675 "can't obtain current working directory");
676 }
677 /* change back afterwards */
678 if (seteuid(effeusr) < 0) {
679 atabort(CANTCHUID);
680 }
681 printf("%s", dirbuf);
682 break;
683 case 'm':
684 printf("%o", um);
685 break;
686 case '<':
687 if (ulimit_flag) {
688 if (getrlimit(RLIMIT_FSIZE, &rlp) == 0) {
689 if (rlp.rlim_cur == RLIM_INFINITY)
690 printf("ulimit unlimited\n");
691 else
692 printf("ulimit %lld\n",
693 rlp.rlim_cur / 512);
694 }
695 }
696 /*
697 * fix for 1113572 - use fputs() so that a
698 * newline isn't appended to the one returned
699 * with fgets(); 1099381 - prompt for input.
700 */
701 while (fgets(line, LINE_MAX, inputfile) != NULL) {
|
84 " at [-c|-k|-s] [-m] [-f file] [-p project] [-q queuename] "\
85 "timespec\n"\
86 " at -l [-p project] [-q queuename] [at_job_id...]\n"\
87 " at -r at_job_id ...\n"
88
89 #define FORMAT "%a %b %e %H:%M:%S %Y"
90
91 static int leap(int);
92 static int atoi_for2(char *);
93 static int check_queue(char *, int);
94 static int list_jobs(int, char **, int, int);
95 static int remove_jobs(int, char **, char *);
96 static void usage(void);
97 static void catch(int);
98 static void copy(char *, FILE *, int);
99 static void atime(struct tm *, struct tm *);
100 static int not_this_project(char *);
101 static char *mkjobname(time_t);
102 static time_t parse_time(char *);
103 static time_t gtime(struct tm *);
104 static void escapestr(const char *);
105 void atabort(char *)__NORETURN;
106 void yyerror(void);
107 extern int yyparse(void);
108
109 extern void audit_at_delete(char *, char *, int);
110 extern int audit_at_create(char *, int);
111 extern int audit_cron_is_anc_name(char *);
112 extern int audit_cron_delete_anc_file(char *, char *);
113
114 /*
115 * Error in getdate(3G)
116 */
117 static char *errlist[] = {
118 /* 0 */ "",
119 /* 1 */ "getdate: The DATEMSK environment variable is not set",
120 /* 2 */ "getdate: Error on \"open\" of the template file",
121 /* 3 */ "getdate: Error on \"stat\" of the template file",
122 /* 4 */ "getdate: The template file is not a regular file",
123 /* 5 */ "getdate: An error is encountered while reading the template",
124 /* 6 */ "getdate: Malloc(3C) failed",
530 * We call isleap since leap() adds
531 * 1900 onto any value passed
532 */
533
534 if (!leap(tptr->tm_year) && at.tm_mday == 29 && at.tm_mon == 1)
535 atabort("bad date - not a leap year");
536
537 if ((leap(tptr->tm_year)) && tptr->tm_mon >= 2)
538 ++tv;
539
540 for (i = 0; i < tptr->tm_mon; ++i)
541 tv += dmsize[i];
542 tv += tptr->tm_mday - 1;
543 tv = 24 * tv + tptr->tm_hour;
544 tv = 60 * tv + tptr->tm_min;
545 tv = 60 * tv + tptr->tm_sec;
546 return (tv);
547 }
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 /*
567 * make job file from proto + stdin
568 */
569 static void
570 copy(char *jobfile, FILE *inputfile, int when)
571 {
572 int c;
573 FILE *pfp;
574 char *shell;
575 char dirbuf[PATH_MAX + 1];
576 char line[LINE_MAX];
577 char **ep;
578 mode_t um;
579 char *val;
580 extern char **environ;
581 uid_t realusr, effeusr;
582 int ttyinput;
583 int ulimit_flag = 0;
584 struct rlimit rlp;
585 struct project prj, *pprj;
586 char pbuf[PROJECT_BUFSZ];
634 } else {
635 /*
636 * Check if current user is a member of current project.
637 * This check is done here to avoid setproject() failure
638 * later when the job gets executed. If current user does
639 * not belong to current project, user's default project
640 * will be used instead. This is achieved by not specifying
641 * the project (": project: <project>\n") in the job file.
642 */
643 if ((user = getuser(getuid())) == NULL)
644 atabort(INVALIDUSER);
645 project = getprojid();
646 pprj = getprojbyid(project, &prj, pbuf, sizeof (pbuf));
647 if (pprj != NULL) {
648 if (inproj(user, pprj->pj_name, pbuf2, sizeof (pbuf2)))
649 (void) printf(": project: %d\n", project);
650 }
651 }
652
653 for (ep = environ; *ep; ep++) {
654 if ((val = strchr(*ep, '=')) == NULL)
655 continue;
656 *val++ = '\0';
657 (void) printf("export %s; %s=", *ep, *ep);
658 escapestr(val);
659 (void) putchar('\n');
660 *--val = '=';
661 }
662 if ((pfp = fopen(pname1, "r")) == NULL &&
663 (pfp = fopen(pname, "r")) == NULL)
664 atabort("no prototype");
665 /*
666 * Put in a line to run the proper shell using the rest of
667 * the file as input. Note that 'exec'ing the shell will
668 * cause sh() to leave a /tmp/sh### file around. (1053807)
669 */
670 printf("%s << '...the rest of this file is shell input'\n", shell);
671
672 um = umask(0);
673 while ((c = getc(pfp)) != EOF) {
674 if (c != '$')
675 putchar(c);
676 else switch (c = getc(pfp)) {
677 case EOF:
678 goto out;
679 case 'd':
680 /*
681 * Must obtain current working directory as the user
682 */
683
684 dirbuf[0] = '\0';
685 realusr = getuid();
686 effeusr = geteuid();
687 /* change euid for getcwd */
688 if (seteuid(realusr) < 0) {
689 atabort(CANTCHUID);
690 }
691 if (getcwd(dirbuf, sizeof (dirbuf)) == NULL) {
692 atabort(
693 "can't obtain current working directory");
694 }
695 /* change back afterwards */
696 if (seteuid(effeusr) < 0) {
697 atabort(CANTCHUID);
698 }
699 escapestr(dirbuf);
700 break;
701 case 'm':
702 printf("%o", um);
703 break;
704 case '<':
705 if (ulimit_flag) {
706 if (getrlimit(RLIMIT_FSIZE, &rlp) == 0) {
707 if (rlp.rlim_cur == RLIM_INFINITY)
708 printf("ulimit unlimited\n");
709 else
710 printf("ulimit %lld\n",
711 rlp.rlim_cur / 512);
712 }
713 }
714 /*
715 * fix for 1113572 - use fputs() so that a
716 * newline isn't appended to the one returned
717 * with fgets(); 1099381 - prompt for input.
718 */
719 while (fgets(line, LINE_MAX, inputfile) != NULL) {
|