Bell 32V development
[unix-history] / usr / src / cmd / at.c
CommitLineData
3b600ead
TL
1/*
2 * at time mon day
3 * at time wday
4 * at time wday 'week'
5 *
6 */
7#include <stdio.h>
8#include <ctype.h>
9#include <time.h>
10#include <signal.h>
11
12#define HOUR 100
13#define HALFDAY (12*HOUR)
14#define DAY (24*HOUR)
15#define THISDAY "/usr/spool/at"
16
17char *days[] = {
18 "sunday",
19 "monday",
20 "tuesday",
21 "wednesday",
22 "thursday",
23 "friday",
24 "saturday",
25};
26
27struct monstr {
28 char *mname;
29 int mlen;
30} months[] = {
31 { "january", 31 },
32 { "february", 28 },
33 { "march", 31 },
34 { "april", 30 },
35 { "may", 31 },
36 { "june", 30 },
37 { "july", 31 },
38 { "august", 31 },
39 { "september", 30 },
40 { "october", 31 },
41 { "november", 30 },
42 { "december", 31 },
43 { 0, 0 },
44};
45
46char fname[100];
47int utime; /* requested time in grains */
48int now; /* when is it */
49int uday; /* day of year to be done */
50int uyear; /* year */
51int today; /* day of year today */
52FILE *file;
53FILE *ifile;
54char **environ;
55char *prefix();
56FILE *popen();
57
58main(argc, argv)
59char **argv;
60{
61 extern onintr();
62 register c;
63 char pwbuf[100];
64 FILE *pwfil;
65 int larg;
66
67 /* argv[1] is the user's time: e.g., 3AM */
68 /* argv[2] is a month name or day of week */
69 /* argv[3] is day of month or 'week' */
70 /* another argument might be an input file */
71 if (argc < 2) {
72 fprintf(stderr, "at: arg count\n");
73 exit(1);
74 }
75 makeutime(argv[1]);
76 larg = makeuday(argc,argv)+1;
77 if (uday==today && larg<=2 && utime<=now)
78 uday++;
79 c = uyear%4==0? 366: 365;
80 if (uday >= c) {
81 uday -= c;
82 uyear++;
83 }
84 filename(THISDAY, uyear, uday, utime);
85 ifile = stdin;
86 if (argc > larg)
87 ifile = fopen(argv[larg], "r");
88 if (ifile == NULL) {
89 fprintf(stderr, "at: cannot open input: %s\n", argv[larg]);
90 exit(1);
91 }
92 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
93 signal(SIGINT, onintr);
94 file = fopen(fname, "a");
95 chmod(fname, 0644);
96 if (file == NULL) {
97 fprintf(stderr, "at: cannot open memo file\n");
98 exit(1);
99 }
100 if ((pwfil = popen("pwd", "r")) == NULL) {
101 fprintf(stderr, "at: can't execute pwd\n");
102 exit(1);
103 }
104 fgets(pwbuf, 100, pwfil);
105 pclose(pwfil);
106 fprintf(file, "cd %s", pwbuf);
107 if (environ) {
108 char **ep = environ;
109 while(*ep)
110 fprintf(file, "%s\n", *ep++);
111 }
112 while((c = getc(ifile)) != EOF) {
113 putc(c, file);
114 }
115 exit(0);
116}
117
118makeutime(pp)
119char *pp;
120{
121 register val;
122 register char *p;
123
124 /* p points to a user time */
125 p = pp;
126 val = 0;
127 while(isdigit(*p)) {
128 val = val*10+(*p++ -'0');
129 }
130 if (p-pp < 3)
131 val *= HOUR;
132
133 for (;;) {
134 switch(*p) {
135
136 case ':':
137 ++p;
138 if (isdigit(*p)) {
139 if (isdigit(p[1])) {
140 val +=(10* *p + p[1] - 11*'0');
141 p += 2;
142 continue;
143 }
144 }
145 fprintf(stderr, "at: bad time format:\n");
146 exit(1);
147
148 case 'A':
149 case 'a':
150 if (val >= HALFDAY+HOUR)
151 val = DAY+1; /* illegal */
152 if (val >= HALFDAY && val <(HALFDAY+HOUR))
153 val -= HALFDAY;
154 break;
155
156 case 'P':
157 case 'p':
158 if (val >= HALFDAY+HOUR)
159 val = DAY+1; /* illegal */
160 if (val < HALFDAY)
161 val += HALFDAY;
162 break;
163
164 case 'n':
165 case 'N':
166 val = HALFDAY;
167 break;
168
169 case 'M':
170 case 'm':
171 val = 0;
172 break;
173
174
175 case '\0':
176 case ' ':
177 /* 24 hour time */
178 if (val == DAY)
179 val -= DAY;
180 break;
181
182 default:
183 fprintf(stderr, "at: bad time format\n");
184 exit(1);
185
186 }
187 break;
188 }
189 if (val < 0 || val >= DAY) {
190 fprintf(stderr, "at: time out of range\n");
191 exit(1);
192 }
193 if (val%HOUR >= 60) {
194 fprintf(stderr, "at: illegal minute field\n");
195 exit(1);
196 }
197 utime = val;
198}
199
200
201makeuday(argc,argv)
202char **argv;
203{
204 /* the presumption is that argv[2], argv[3] are either
205 month day OR weekday [week]. Returns either 2 or 3 as last
206 argument used */
207 /* first of all, what's today */
208 long tm;
209 int found = -1;
210 char **ps;
211 struct tm *detail, *localtime();
212 struct monstr *pt;
213
214 time(&tm);
215 detail = localtime(&tm);
216 uday = today = detail->tm_yday;
217 uyear = detail->tm_year;
218 now = detail->tm_hour*100+detail->tm_min;
219 if (argc<=2)
220 return(1);
221 /* is the next argument a month name ? */
222 for (pt=months; pt->mname; pt++) {
223 if (prefix(argv[2], pt->mname)) {
224 if (found<0)
225 found = pt-months;
226 else {
227 fprintf(stderr, "at: ambiguous month\n");
228 exit(1);
229 }
230 }
231 }
232 if (found>=0) {
233 if (argc<=3)
234 return(2);
235 uday = atoi(argv[3]) - 1;
236 if (uday<0) {
237 fprintf(stderr, "at: illegal day\n");
238 exit(1);
239 }
240 while(--found>=0)
241 uday += months[found].mlen;
242 if (detail->tm_year%4==0 && uday>59)
243 uday += 1;
244 return(3);
245 }
246 /* not a month, try day of week */
247 found = -1;
248 for (ps=days; ps<days+7; ps++) {
249 if (prefix(argv[2], *ps)) {
250 if (found<0)
251 found = ps-days;
252 else {
253 fprintf(stderr, "at: ambiguous day of week\n");
254 exit(1);
255 }
256 }
257 }
258 if (found<0)
259 return(1);
260 /* find next day of this sort */
261 uday = found - detail->tm_wday;
262 if (uday<=0)
263 uday += 7;
264 uday += today;
265 if (argc>3 && strcmp("week", argv[3])==0) {
266 uday += 7;
267 return(3);
268 }
269 return(2);
270}
271
272char *
273prefix(begin, full)
274char *begin, *full;
275{
276 int c;
277 while (c = *begin++) {
278 if (isupper(c))
279 c = tolower(c);
280 if (*full != c)
281 return(0);
282 else
283 full++;
284 }
285 return(full);
286}
287
288filename(dir, y, d, t)
289char *dir;
290{
291 register i;
292
293 for (i=0; ; i += 53) {
294 sprintf(fname, "%s/%02d.%03d.%04d.%02d", dir, y, d, t,
295 (getpid()+i)%100);
296 if (access(fname, 0) == -1)
297 return;
298 }
299}
300
301onintr()
302{
303 unlink(fname);
304 exit(1);
305}