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(int argc
, char **argv
, char **envp
)
28 int i
, c
, mask
, ltim
, year
, lday
= NODAY
;
29 char buf
[64], job
[30], pastjob
[35], *dp
, *sp
;
35 /*-------------------------------------------------------------------------*
36 * check arguments & pipe to "pwd" *
37 *-------------------------------------------------------------------------*/
38 if (argc
< 2 || argc
> 5) {
39 fprintf(stderr
, "Usage: %s time [month day] [file]\n", argv
[0]);
42 if ((ltim
= getltim(argv
[1])) == -1) {
43 fprintf(stderr
, "%s: wrong time specification\n", argv
[0]);
46 if ((argc
== 4 || argc
== 5) && (lday
= getlday(argv
[2], argv
[3])) == -1) {
47 fprintf(stderr
, "%s: wrong date specification\n", argv
[0]);
50 if ((argc
== 3 || argc
== 5) && open(argv
[argc
- 1], O_RDONLY
) == -1) {
51 fprintf(stderr
, "%s: cannot find: %s\n", argv
[0], argv
[argc
- 1]);
54 if (getcwd(pwd
, sizeof(pwd
)) == NULL
) {
55 fprintf(stderr
, "%s: cannot determine current directory: %s\n",
56 argv
[0], strerror(errno
));
60 /*-------------------------------------------------------------------------*
61 * determine execution time and create 'at' job file *
62 *-------------------------------------------------------------------------*/
66 if (lday
== NODAY
) { /* no [month day] given */
68 if (ltim
<= (p
->tm_hour
* 100 + p
->tm_min
)) {
70 if ((lday
== MAXDAYNR
&& (year
% 4)) || lday
== MAXDAYNR
+ 1) {
78 if (lday
< p
->tm_yday
||
79 (lday
== p
->tm_yday
&&
80 ltim
<= (p
->tm_hour
* 100 + p
->tm_min
))) {
82 if (lday
> LEAPDAY
) lday
--;
87 if (lday
> LEAPDAY
) lday
--;
88 if (lday
< p
->tm_yday
||
89 (lday
== p
->tm_yday
&&
90 ltim
<= (p
->tm_hour
* 100 + p
->tm_min
)))
94 if (lday
< ((lday
> LEAPDAY
) ? p
->tm_yday
+ 1 : p
->tm_yday
) ||
95 (lday
==((lday
> LEAPDAY
) ? p
->tm_yday
+ 1 : p
->tm_yday
) &&
96 ltim
<= (p
->tm_hour
* 100 + p
->tm_min
)))
98 else if (lday
> LEAPDAY
)
102 sprintf(job
, "/usr/spool/at/%02d.%03d.%04d.%02d",
103 year
% 100, lday
, ltim
, getpid() % 100);
104 sprintf(pastjob
, "/usr/spool/at/past/%02d.%03d.%04d.%02d",
105 year
% 100, lday
, ltim
, getpid() % 100);
107 if ((fp
= fopen(pastjob
, "w")) == NULL
) {
108 fprintf(stderr
, "%s: cannot create %s: %s\n",
109 argv
[0], pastjob
, strerror(errno
));
113 /*-------------------------------------------------------------------------*
114 * write environment and command(s) to 'at'job file *
115 *-------------------------------------------------------------------------*/
117 while ((sp
= envp
[i
++]) != NULL
) {
119 while ((c
= *sp
++) != '\0' && c
!= '=' && dp
< buf
+sizeof(buf
)-1)
121 if (c
!= '=') continue;
123 fprintf(fp
, "%s='", buf
);
126 fprintf(fp
, "'\\''");
131 fprintf(fp
, "'; export %s\n", buf
);
133 fprintf(fp
, "cd '%s'\n", pwd
);
134 fprintf(fp
, "umask %o\n", mask
);
135 if (argc
== 3 || argc
== 5)
136 fprintf(fp
, "%s\n", argv
[argc
- 1]);
137 else /* read from stdinput */
138 while ((c
= getchar()) != EOF
) putc(c
, fp
);
141 if (chown(pastjob
, getuid(), getgid()) == -1) {
142 fprintf(stderr
, "%s: cannot set ownership of %s: %s\n",
143 argv
[0], pastjob
, strerror(errno
));
148 if (rename(pastjob
, job
) == -1) {
149 fprintf(stderr
, "%s: cannot move %s to %s: %s\n",
150 argv
[0], pastjob
, job
, strerror(errno
));
154 printf("%s: %s created\n", argv
[0], job
);
156 /* Alert cron to the new situation. */
157 if ((fp
= fopen(CRONPID
, "r")) != NULL
) {
161 while ((c
= fgetc(fp
)) != EOF
&& c
!= '\n') {
162 if ((unsigned) (c
- '0') >= 10) { pid
= 0; break; }
163 pid
= 10*pid
+ (c
- '0');
164 if (pid
>= 30000) { pid
= 0; break; }
166 if (pid
> 1) kill((pid_t
) pid
, SIGHUP
);
171 /*-------------------------------------------------------------------------*
172 * getltim() return((time OK) ? daytime : -1) *
173 *-------------------------------------------------------------------------*/
176 if (t
[4] == '\0' && t
[3] >= '0' && t
[3] <= '9' &&
177 t
[2] >= '0' && t
[2] <= '5' && t
[1] >= '0' && t
[1] <= '9' &&
178 (t
[0] == '0' || t
[0] == '1' || (t
[1] <= '3' && t
[0] == '2')))
184 /*-------------------------------------------------------------------------*
185 * getlday() return ((date OK) ? yearday : -1) *
186 *-------------------------------------------------------------------------*/
187 int getlday(char *m
, char *d
)
190 static int cumday
[] = {0, 0, 31, 60, 91, 121, 152,
191 182, 213, 244, 274, 305, 335};
196 { "Jan", 31 }, { "Feb", 29 }, { "Mar", 31 }, { "Apr", 30 },
197 { "May", 31 }, { "Jun", 30 }, { "Jul", 31 }, { "Aug", 31 },
198 { "Sep", 30 }, { "Oct", 31 }, { "Nov", 30 }, { "Dec", 31 },
202 im
= (digitstring(m
)) ? atoi(m
) : 0;
204 for (i
= 1; i
< 13 && strcmp(m
, pc
->mon
) && im
!= i
; i
++, pc
++);
205 if (i
< 13 && (day
= (digitstring(d
)) ? atoi(d
) : 0) && day
<= pc
->dcnt
) {
206 if (!STARTDAY
) day
--;
207 return(day
+ cumday
[i
]);
214 int digitstring(char *s
)
216 while (*s
>= '0' && *s
<= '9') s
++;
217 return((*s
== '\0') ? 1 : 0);