BSD 3 development
[unix-history] / usr / src / cmd / at.c
CommitLineData
1c237237
BJ
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();
56char *getenv();
57FILE *popen();
58
59main(argc, argv)
60char **argv;
61{
62 extern onintr();
63 register c;
64 char pwbuf[100];
65 FILE *pwfil;
66 int larg;
67 char *tmp;
68
69 /* argv[1] is the user's time: e.g., 3AM */
70 /* argv[2] is a month name or day of week */
71 /* argv[3] is day of month or 'week' */
72 /* another argument might be an input file */
73 if (argc < 2) {
74 fprintf(stderr, "at: arg count\n");
75 exit(1);
76 }
77 makeutime(argv[1]);
78 larg = makeuday(argc,argv)+1;
79 if (uday==today && larg<=2 && utime<=now)
80 uday++;
81 c = uyear%4==0? 366: 365;
82 if (uday >= c) {
83 uday -= c;
84 uyear++;
85 }
86 filename(THISDAY, uyear, uday, utime);
87 ifile = stdin;
88 if (argc > larg)
89 ifile = fopen(argv[larg], "r");
90 if (ifile == NULL) {
91 fprintf(stderr, "at: cannot open input: %s\n", argv[larg]);
92 exit(1);
93 }
94 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
95 signal(SIGINT, onintr);
96 file = fopen(fname, "a");
97 chmod(fname, 0644);
98 chown(fname,getuid(),getgid());
99 if (file == NULL) {
100 fprintf(stderr, "at: cannot open memo file\n");
101 exit(1);
102 }
103 if ((pwfil = popen("pwd", "r")) == NULL) {
104 fprintf(stderr, "at: can't execute pwd\n");
105 exit(1);
106 }
107 fgets(pwbuf, 100, pwfil);
108 pclose(pwfil);
109 fprintf(file, "cd %s", pwbuf);
110 if (environ) {
111 char **ep = environ;
112 while(*ep)
113 {
114 fprintf(file, "%s\nexport ", *ep);
115 for(tmp = *ep ; *tmp != '=' ; tmp++) putc(*tmp,file);
116 putc('\n',file);
117 ep++;
118 }
119 }
120 /* see if the SHELL variable in the current enviroment is /bin/csh
121 * and in that case, use the csh as the shell
122 */
123 if(strcmp(getenv("SHELL"), "/bin/csh") == 0)
124 fprintf(file, "%s\n", "csh << 'xxFUNNYxx'");
125 while((c = getc(ifile)) != EOF) {
126 putc(c, file);
127 }
128 if(strcmp(getenv("SHELL"), "/bin/csh") == 0)
129 fprintf(file, "%s\n", "xxFUNNYxx");
130 exit(0);
131}
132
133makeutime(pp)
134char *pp;
135{
136 register val;
137 register char *p;
138
139 /* p points to a user time */
140 p = pp;
141 val = 0;
142 while(isdigit(*p)) {
143 val = val*10+(*p++ -'0');
144 }
145 if (p-pp < 3)
146 val *= HOUR;
147
148 for (;;) {
149 switch(*p) {
150
151 case ':':
152 ++p;
153 if (isdigit(*p)) {
154 if (isdigit(p[1])) {
155 val +=(10* *p + p[1] - 11*'0');
156 p += 2;
157 continue;
158 }
159 }
160 fprintf(stderr, "at: bad time format:\n");
161 exit(1);
162
163 case 'A':
164 case 'a':
165 if (val >= HALFDAY+HOUR)
166 val = DAY+1; /* illegal */
167 if (val >= HALFDAY && val <(HALFDAY+HOUR))
168 val -= HALFDAY;
169 break;
170
171 case 'P':
172 case 'p':
173 if (val >= HALFDAY+HOUR)
174 val = DAY+1; /* illegal */
175 if (val < HALFDAY)
176 val += HALFDAY;
177 break;
178
179 case 'n':
180 case 'N':
181 val = HALFDAY;
182 break;
183
184 case 'M':
185 case 'm':
186 val = 0;
187 break;
188
189
190 case '\0':
191 case ' ':
192 /* 24 hour time */
193 if (val == DAY)
194 val -= DAY;
195 break;
196
197 default:
198 fprintf(stderr, "at: bad time format\n");
199 exit(1);
200
201 }
202 break;
203 }
204 if (val < 0 || val >= DAY) {
205 fprintf(stderr, "at: time out of range\n");
206 exit(1);
207 }
208 if (val%HOUR >= 60) {
209 fprintf(stderr, "at: illegal minute field\n");
210 exit(1);
211 }
212 utime = val;
213}
214
215
216makeuday(argc,argv)
217char **argv;
218{
219 /* the presumption is that argv[2], argv[3] are either
220 month day OR weekday [week]. Returns either 2 or 3 as last
221 argument used */
222 /* first of all, what's today */
223 long tm;
224 int found = -1;
225 char **ps;
226 struct tm *detail, *localtime();
227 struct monstr *pt;
228
229 time(&tm);
230 detail = localtime(&tm);
231 uday = today = detail->tm_yday;
232 uyear = detail->tm_year;
233 now = detail->tm_hour*100+detail->tm_min;
234 if (argc<=2)
235 return(1);
236 /* is the next argument a month name ? */
237 for (pt=months; pt->mname; pt++) {
238 if (prefix(argv[2], pt->mname)) {
239 if (found<0)
240 found = pt-months;
241 else {
242 fprintf(stderr, "at: ambiguous month\n");
243 exit(1);
244 }
245 }
246 }
247 if (found>=0) {
248 if (argc<=3)
249 return(2);
250 uday = atoi(argv[3]) - 1;
251 if (uday<0) {
252 fprintf(stderr, "at: illegal day\n");
253 exit(1);
254 }
255 while(--found>=0)
256 uday += months[found].mlen;
257 if (detail->tm_year%4==0 && uday>59)
258 uday += 1;
259 return(3);
260 }
261 /* not a month, try day of week */
262 found = -1;
263 for (ps=days; ps<days+7; ps++) {
264 if (prefix(argv[2], *ps)) {
265 if (found<0)
266 found = ps-days;
267 else {
268 fprintf(stderr, "at: ambiguous day of week\n");
269 exit(1);
270 }
271 }
272 }
273 if (found<0)
274 return(1);
275 /* find next day of this sort */
276 uday = found - detail->tm_wday;
277 if (uday<=0)
278 uday += 7;
279 uday += today;
280 if (argc>3 && strcmp("week", argv[3])==0) {
281 uday += 7;
282 return(3);
283 }
284 return(2);
285}
286
287char *
288prefix(begin, full)
289char *begin, *full;
290{
291 int c;
292 while (c = *begin++) {
293 if (isupper(c))
294 c = tolower(c);
295 if (*full != c)
296 return(0);
297 else
298 full++;
299 }
300 return(full);
301}
302
303filename(dir, y, d, t)
304char *dir;
305{
306 register i;
307
308 for (i=0; ; i += 53) {
309 sprintf(fname, "%s/%02d.%03d.%04d.%02d", dir, y, d, t,
310 (getpid()+i)%100);
311 if (access(fname, 0) == -1)
312 return;
313 }
314}
315
316onintr()
317{
318 unlink(fname);
319 exit(1);
320}