1 /* at - run a command at a specified time Author: Jan Looyen */
15 #define STARTDAY 0 /* see ctime(3) */
16 #define LEAPDAY (STARTDAY+59)
17 #define MAXDAYNR (STARTDAY+365)
19 char CRONPID
[] = "/usr/run/cron.pid";
21 int main(int argc
, char **argv
, char **envp
);
23 int getlday(char *m
, char *d
);
24 int digitstring(char *s
);
26 int main(argc
, argv
, envp
)
30 int i
, c
, mask
, ltim
, year
, lday
= NODAY
;
31 char buf
[64], job
[30], pastjob
[35], *dp
, *sp
;
37 /*-------------------------------------------------------------------------*
38 * check arguments & pipe to "pwd" *
39 *-------------------------------------------------------------------------*/
40 if (argc
< 2 || argc
> 5) {
41 fprintf(stderr
, "Usage: %s time [month day] [file]\n", argv
[0]);
44 if ((ltim
= getltim(argv
[1])) == -1) {
45 fprintf(stderr
, "%s: wrong time specification\n", argv
[0]);
48 if ((argc
== 4 || argc
== 5) && (lday
= getlday(argv
[2], argv
[3])) == -1) {
49 fprintf(stderr
, "%s: wrong date specification\n", argv
[0]);
52 if ((argc
== 3 || argc
== 5) && open(argv
[argc
- 1], O_RDONLY
) == -1) {
53 fprintf(stderr
, "%s: cannot find: %s\n", argv
[0], argv
[argc
- 1]);
56 if (getcwd(pwd
, sizeof(pwd
)) == NULL
) {
57 fprintf(stderr
, "%s: cannot determine current directory: %s\n",
58 argv
[0], strerror(errno
));
62 /*-------------------------------------------------------------------------*
63 * determine execution time and create 'at' job file *
64 *-------------------------------------------------------------------------*/
68 if (lday
== NODAY
) { /* no [month day] given */
70 if (ltim
<= (p
->tm_hour
* 100 + p
->tm_min
)) {
72 if ((lday
== MAXDAYNR
&& (year
% 4)) || lday
== MAXDAYNR
+ 1) {
80 if (lday
< p
->tm_yday
||
81 (lday
== p
->tm_yday
&&
82 ltim
<= (p
->tm_hour
* 100 + p
->tm_min
))) {
84 if (lday
> LEAPDAY
) lday
--;
89 if (lday
> LEAPDAY
) lday
--;
90 if (lday
< p
->tm_yday
||
91 (lday
== p
->tm_yday
&&
92 ltim
<= (p
->tm_hour
* 100 + p
->tm_min
)))
96 if (lday
< ((lday
> LEAPDAY
) ? p
->tm_yday
+ 1 : p
->tm_yday
) ||
97 (lday
==((lday
> LEAPDAY
) ? p
->tm_yday
+ 1 : p
->tm_yday
) &&
98 ltim
<= (p
->tm_hour
* 100 + p
->tm_min
)))
100 else if (lday
> LEAPDAY
)
104 sprintf(job
, "/usr/spool/at/%02d.%03d.%04d.%02d",
105 year
% 100, lday
, ltim
, getpid() % 100);
106 sprintf(pastjob
, "/usr/spool/at/past/%02d.%03d.%04d.%02d",
107 year
% 100, lday
, ltim
, getpid() % 100);
109 if ((fp
= fopen(pastjob
, "w")) == NULL
) {
110 fprintf(stderr
, "%s: cannot create %s: %s\n",
111 argv
[0], pastjob
, strerror(errno
));
115 /*-------------------------------------------------------------------------*
116 * write environment and command(s) to 'at'job file *
117 *-------------------------------------------------------------------------*/
119 while ((sp
= envp
[i
++]) != NULL
) {
121 while ((c
= *sp
++) != '\0' && c
!= '=' && dp
< buf
+sizeof(buf
)-1)
123 if (c
!= '=') continue;
125 fprintf(fp
, "%s='", buf
);
128 fprintf(fp
, "'\\''");
133 fprintf(fp
, "'; export %s\n", buf
);
135 fprintf(fp
, "cd '%s'\n", pwd
);
136 fprintf(fp
, "umask %o\n", mask
);
137 if (argc
== 3 || argc
== 5)
138 fprintf(fp
, "%s\n", argv
[argc
- 1]);
139 else /* read from stdinput */
140 while ((c
= getchar()) != EOF
) putc(c
, fp
);
143 if (chown(pastjob
, getuid(), getgid()) == -1) {
144 fprintf(stderr
, "%s: cannot set ownership of %s: %s\n",
145 argv
[0], pastjob
, strerror(errno
));
150 if (rename(pastjob
, job
) == -1) {
151 fprintf(stderr
, "%s: cannot move %s to %s: %s\n",
152 argv
[0], pastjob
, job
, strerror(errno
));
156 printf("%s: %s created\n", argv
[0], job
);
158 /* Alert cron to the new situation. */
159 if ((fp
= fopen(CRONPID
, "r")) != NULL
) {
163 while ((c
= fgetc(fp
)) != EOF
&& c
!= '\n') {
164 if ((unsigned) (c
- '0') >= 10) { pid
= 0; break; }
165 pid
= 10*pid
+ (c
- '0');
166 if (pid
>= 30000) { pid
= 0; break; }
168 if (pid
> 1) kill((pid_t
) pid
, SIGHUP
);
173 /*-------------------------------------------------------------------------*
174 * getltim() return((time OK) ? daytime : -1) *
175 *-------------------------------------------------------------------------*/
179 if (t
[4] == '\0' && t
[3] >= '0' && t
[3] <= '9' &&
180 t
[2] >= '0' && t
[2] <= '5' && t
[1] >= '0' && t
[1] <= '9' &&
181 (t
[0] == '0' || t
[0] == '1' || (t
[1] <= '3' && t
[0] == '2')))
187 /*-------------------------------------------------------------------------*
188 * getlday() return ((date OK) ? yearday : -1) *
189 *-------------------------------------------------------------------------*/
194 static int cumday
[] = {0, 0, 31, 60, 91, 121, 152,
195 182, 213, 244, 274, 305, 335};
200 { "Jan", 31 }, { "Feb", 29 }, { "Mar", 31 }, { "Apr", 30 },
201 { "May", 31 }, { "Jun", 30 }, { "Jul", 31 }, { "Aug", 31 },
202 { "Sep", 30 }, { "Oct", 31 }, { "Nov", 30 }, { "Dec", 31 },
206 im
= (digitstring(m
)) ? atoi(m
) : 0;
208 for (i
= 1; i
< 13 && strcmp(m
, pc
->mon
) && im
!= i
; i
++, pc
++);
209 if (i
< 13 && (day
= (digitstring(d
)) ? atoi(d
) : 0) && day
<= pc
->dcnt
) {
210 if (!STARTDAY
) day
--;
211 return(day
+ cumday
[i
]);
221 while (*s
>= '0' && *s
<= '9') s
++;
222 return((*s
== '\0') ? 1 : 0);