|
|
1.1 root 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: #include <sys/types.h>
12: #include <sys/stat.h>
13: #include <dir.h>
14:
15: #define HOUR 100
16: #define HALFDAY (12*HOUR)
17: #define DAY (24*HOUR)
18: #define THISDAY "/usr/spool/at"
19:
20: char *days[] = {
21: "sunday",
22: "monday",
23: "tuesday",
24: "wednesday",
25: "thursday",
26: "friday",
27: "saturday",
28: };
29:
30: struct monstr {
31: char *mname;
32: int mlen;
33: } months[] = {
34: { "january", 31 },
35: { "february", 28 },
36: { "march", 31 },
37: { "april", 30 },
38: { "may", 31 },
39: { "june", 30 },
40: { "july", 31 },
41: { "august", 31 },
42: { "september", 30 },
43: { "october", 31 },
44: { "november", 30 },
45: { "december", 31 },
46: { 0, 0 },
47: };
48:
49: char fname[100];
50: int utime; /* requested time in grains */
51: int now; /* when is it */
52: int uday; /* day of year to be done */
53: int uyear; /* year */
54: int today; /* day of year today */
55: int thisyear; /* this year */
56: FILE *file;
57: FILE *ifile;
58: char **environ;
59: char *prefix();
60: char *idend();
61: char *strchr();
62: FILE *popen();
63:
64: extern int optind;
65: char lflg;
66: char rflg;
67: char errflg;
68:
69: void prdir(), prfile(), delfile(), vprint();
70: int readdir();
71: char *pathdate();
72:
73: #define EXP 10
74:
75: main(argc, argv)
76: char **argv;
77: {
78: extern onintr();
79: register c;
80: char pwbuf[100];
81: FILE *pwfil;
82: int larg;
83: static char stdbuf[BUFSIZ];
84:
85: setbuf (stdout, stdbuf);
86:
87: while ((c = getopt (argc, argv, "rl")) != EOF) {
88: switch (c) {
89:
90: case 'l':
91: lflg = 1;
92: break;
93:
94: case 'r':
95: rflg = 1;
96: break;
97:
98: default:
99: errflg = 1;
100: break;
101: }
102: }
103:
104: if (errflg) {
105: fprintf (stderr, "usage: at [lr] time [filename]\n");
106: exit (1);
107: }
108:
109: /* argv[optind] is the user's time: e.g., 3AM */
110: /* argv[optind+1] is a month name or day of week */
111: /* argv[optind+2] is day of month or 'week' */
112: /* another argument might be an input file */
113: if (argc < optind+1) {
114: if (lflg && !rflg) {
115: (void) readdir("", prdir);
116: exit (0);
117: }
118: fprintf(stderr, "at: arg count\n");
119: exit(1);
120: }
121: makeutime(argv[optind]);
122: larg = makeuday(argc-optind+1,argv+optind-1)+optind;
123: if (uday==today && larg<=optind+1 && utime<=now)
124: uday++;
125: c = uyear%4==0? 366: 365;
126: /*
127: The way makeuday is written, the following "if" is rarely
128: satisfied. This makes a problem, which is fixed below.
129: */
130: if (uday >= c) {
131: uday -= c;
132: uyear++;
133: }
134: /*
135: Due to problem described above, "at" schedules a Jan call in
136: Dec for LAST Jan. Line below fixes that.
137: */
138: if(uday<today && uyear==thisyear)
139: uyear++;
140:
141: if (lflg || rflg) {
142: char prefix[50];
143: sprintf (prefix, "%.2d.%.3d.%.4d", uyear, uday, utime);
144: if (lflg) {
145: if (readdir (prefix, prfile) == 0)
146: exit (0);
147: if (rflg)
148: putchar ('\n');
149: }
150:
151: if (rflg) {
152: (void) readdir (prefix, delfile);
153: }
154:
155: exit (0);
156: }
157:
158: filename(THISDAY, uyear, uday, utime);
159: /* Create file, then change UIDS */
160: close(creat(fname, 0644));
161: file = fopen(fname, "w");
162: if (file == NULL) {
163: fprintf(stderr, "at: cannot open memo file\n");
164: exit(1);
165: }
166: chown(fname, getuid(), getgid());
167: setuid(getuid());
168: ifile = stdin;
169: if (argc > larg)
170: ifile = fopen(argv[larg], "r");
171: if (ifile == NULL) {
172: fprintf(stderr, "at: cannot open input: %s\n", argv[larg]);
173: exit(1);
174: }
175: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
176: signal(SIGINT, onintr);
177: if ((pwfil = popen("pwd", "r")) == NULL) {
178: fprintf(stderr, "at: can't execute pwd\n");
179: exit(1);
180: }
181: fgets(pwbuf, 100, pwfil);
182: pclose(pwfil);
183: fprintf(file, "cd %s", pwbuf);
184: c = umask(0);
185: umask(c);
186: fprintf(file, "umask %#o\n", c);
187: if (environ) {
188: register int pass;
189: char *explist[EXP];
190: int explen[EXP];
191: register int exp = 0;
192: register int i;
193: for (pass = 1; pass <= 2; pass++) {
194: register char **ep;
195: for (ep = environ; *ep; ep++) {
196: if (pass == 1) {
197: vprint(file, *ep);
198: putc('\n', file);
199: } else {
200: char *ix;
201: ix = idend(*ep);
202: if (*ix) {
203: explen[exp] = ix-*ep;
204: explist[exp++] = *ep;
205: if (exp >= EXP) {
206: fprintf(file,"export");
207: for (i=0; i<EXP; i++) {
208: putc(' ',file);
209: fprintf(file, "%.*s",explen[i],explist[i]);
210: }
211: putc ('\n', file);
212: exp = 0;
213: }
214: }
215: }
216: }
217:
218: if (exp > 0) {
219: fprintf(file,"export");
220: for (i = 0; i < exp; i++) {
221: putc(' ',file);
222: fprintf(file, "%.*s",explen[i],explist[i]); }
223: putc ('\n', file);
224: }
225: }
226: }
227: while((c = getc(ifile)) != EOF) {
228: putc(c, file);
229: }
230: exit(0);
231: }
232:
233: makeutime(pp)
234: char *pp;
235: {
236: register val;
237: register char *p;
238:
239: /* p points to a user time */
240: p = pp;
241: val = 0;
242: while(isdigit(*p)) {
243: val = val*10+(*p++ -'0');
244: }
245: if (p-pp < 3)
246: val *= HOUR;
247:
248: for (;;) {
249: switch(*p) {
250:
251: case ':':
252: ++p;
253: if (isdigit(*p)) {
254: if (isdigit(p[1])) {
255: val +=(10* *p + p[1] - 11*'0');
256: p += 2;
257: continue;
258: }
259: }
260: fprintf(stderr, "at: bad time format:\n");
261: exit(1);
262:
263: case 'A':
264: case 'a':
265: if (val >= HALFDAY+HOUR)
266: val = DAY+1; /* illegal */
267: if (val >= HALFDAY && val <(HALFDAY+HOUR))
268: val -= HALFDAY;
269: break;
270:
271: case 'P':
272: case 'p':
273: if (val >= HALFDAY+HOUR)
274: val = DAY+1; /* illegal */
275: if (val < HALFDAY)
276: val += HALFDAY;
277: break;
278:
279: case 'n':
280: case 'N':
281: val = HALFDAY;
282: break;
283:
284: case 'M':
285: case 'm':
286: val = 0;
287: break;
288:
289:
290: case '\0':
291: case ' ':
292: /* 24 hour time */
293: if (val == DAY)
294: val -= DAY;
295: break;
296:
297: default:
298: fprintf(stderr, "at: bad time format\n");
299: exit(1);
300:
301: }
302: break;
303: }
304: if (val < 0 || val >= DAY) {
305: fprintf(stderr, "at: time out of range\n");
306: exit(1);
307: }
308: if (val%HOUR >= 60) {
309: fprintf(stderr, "at: illegal minute field\n");
310: exit(1);
311: }
312: utime = val;
313: }
314:
315:
316: makeuday(argc,argv)
317: char **argv;
318: {
319: /* the presumption is that argv[2], argv[3] are either
320: month day OR weekday [week]. Returns 2, 3, or 4 as last
321: argument used */
322: /* first of all, what's today */
323: long tm;
324: int found = -1;
325: char **ps;
326: struct tm *detail, *localtime();
327: struct monstr *pt;
328:
329: time(&tm);
330: detail = localtime(&tm);
331: uday = today = detail->tm_yday;
332: thisyear = uyear = detail->tm_year;
333: now = detail->tm_hour*100+detail->tm_min;
334: if (argc<=2)
335: return(1);
336: /* is the next argument a month name ? */
337: for (pt=months; pt->mname; pt++) {
338: if (prefix(argv[2], pt->mname)) {
339: if (found<0)
340: found = pt-months;
341: else {
342: fprintf(stderr, "at: ambiguous month\n");
343: exit(1);
344: }
345: }
346: }
347: if (found>=0) {
348: if (argc<=3)
349: return(2);
350: uday = atoi(argv[3]) - 1;
351: if (uday<0) {
352: fprintf(stderr, "at: illegal day\n");
353: exit(1);
354: }
355: if (found > 1 && detail->tm_year%4==0)
356: uday++; /* because next loop will include Feb */
357: while(--found>=0)
358: uday += months[found].mlen;
359: /* this is bogus...
360: if (detail->tm_year%4==0 && uday>59)
361: uday += 1;
362: */
363: if(argc>4) {
364: int t = atoi(argv[4])-1900;
365: if(t<100 && (t>uyear || t==uyear && (
366: uday>today || uday==today &&
367: utime>now))) {
368: uyear = t;
369: return(4);
370: }
371: }
372: if (uday == today && utime < now)
373: {
374: fprintf(stderr, "at: Warning: time specified is past; assuming next year....\n");
375: ++uyear;
376: }
377: return(3);
378: }
379: /* not a month, try day of week */
380: found = -1;
381: for (ps=days; ps<days+7; ps++) {
382: if (prefix(argv[2], *ps)) {
383: if (found<0)
384: found = ps-days;
385: else {
386: fprintf(stderr, "at: ambiguous day of week\n");
387: exit(1);
388: }
389: }
390: }
391: if (found<0)
392: return(1);
393: /* find next day of this sort */
394: uday = found - detail->tm_wday;
395: if (uday<=0)
396: uday += 7;
397: uday += today;
398: /* Bogus...
399: if (detail->tm_year%4==0 && uday>59)
400: uday += 1;
401: */
402: if (argc>3 && strcmp("week", argv[3])==0) {
403: uday += 7;
404: return(3);
405: }
406: return(2);
407: }
408:
409: char *
410: prefix(begin, full)
411: char *begin, *full;
412: {
413: int c;
414: while (c = *begin++) {
415: if (isupper(c))
416: c = tolower(c);
417: if (*full != c)
418: return(0);
419: else
420: full++;
421: }
422: return(full);
423: }
424:
425: filename(dir, y, d, t)
426: char *dir;
427: {
428: register i;
429:
430: for (i=0; ; i += 53) {
431: sprintf(fname, "%s/%.2d.%.3d.%.4d.%.2d", dir, y, d, t,
432: (getpid()+i)%100);
433: if (access(fname, 0) == -1)
434: return;
435: }
436: }
437:
438: onintr()
439: {
440: unlink(fname);
441: exit(1);
442: }
443:
444: /* hand "fn" all path names in spool directory starting with "prefix" */
445: int
446: readdir(prefix, fn)
447: char *prefix;
448: void (*fn)();
449: {
450: struct dir dbuf;
451: register FILE *f;
452: register int count = 0;
453:
454: f = fopen (THISDAY, "r");
455: if (f == NULL) {
456: fprintf (stderr, "cannot open %s\n", THISDAY);
457: return;
458: }
459:
460: while (fread (&dbuf, sizeof dbuf, 1, f) == 1) {
461: if (dbuf.d_ino != 0 && dbuf.d_name[0] != '.'
462: && strncmp (dbuf.d_name, prefix, strlen(prefix)) == 0) {
463: char file[sizeof (THISDAY) + DIRSIZ + 1];
464: struct stat sb;
465: strcpy (file, THISDAY);
466: strcat (file, "/");
467: strncat (file, dbuf.d_name, DIRSIZ);
468: if (stat (file, &sb) >= 0 && sb.st_uid == getuid()) {
469: count++;
470: (*fn) (file);
471: }
472: }
473: }
474:
475: fclose (f);
476:
477: if (count == 0)
478: fprintf (stderr, "no items\n");
479: }
480:
481: /*
482: * return pointer to (static) area containing date and time
483: * for activation of file, or argument if invalid format.
484: */
485: char *
486: pathdate (path)
487: char *path;
488: {
489: int month, mday, yday, year, tm, junk;
490: register int i;
491: register char *p, *q;
492: static char res[50];
493:
494: /* point p at last component of path name */
495: p = q = path;
496: while (*q)
497: if (*q++ == '/')
498: p = q;
499:
500: /* break out the fields */
501: if (sscanf(p, "%2d.%3d.%4d.%2d", &year, &yday, &tm, &junk) != 4)
502: return path;
503:
504: /* determine the month and day of month */
505: month = 0;
506: mday = yday + 1;
507: while (months[month].mlen && mday > months[month].mlen) {
508: mday -= months[month].mlen;
509: month++;
510: }
511:
512: /* check for impossible date */
513: if (++month > 12)
514: return path;
515:
516: /* check for leap year */
517: if (month > 2 && year % 4 == 0 && --mday <= 0) {
518: mday = months[--month - 1].mlen;
519: if (month == 2)
520: mday++;
521: }
522:
523: /* build the result */
524: sprintf (res, "%.4d %s %d 19%d",
525: tm, months[month-1].mname, mday, year);
526: return res;
527: }
528:
529: void
530: prdir (path)
531: register char *path;
532: {
533: printf ("%s\n", pathdate (path));
534: }
535:
536: void
537: prfile (path)
538: register char *path;
539: {
540: register FILE *f;
541:
542: printf ("\n%s:", pathdate (path));
543: f = fopen (path, "r");
544: if (f == NULL) {
545: fprintf (stderr, " cannot open %s\n", path);
546: } else {
547: register int c;
548: printf ("\n\n");
549: while ((c = getc(f)) != EOF)
550: putchar (c);
551: }
552: fclose (f);
553: }
554:
555: void
556: delfile(path)
557: register char *path;
558: {
559: if (unlink(path) < 0)
560: fprintf (stderr, "cannot remove %s\n", path);
561: else
562: fprintf (stderr, "remove %s\n", pathdate(path));
563: }
564: char *
565: idend(s)
566: char *s;
567: {
568: while(*s && *s!='=' && *s!='(')
569: s++;
570: return s;
571: }
572: /* print a shell variable with quoting */
573: void
574: vprint (f, str)
575: register FILE *f;
576: register char *str;
577: {
578: if(*idend(str)=='(') /* function; the shell's already quoted it right */
579: fputs(str, f);
580: else
581: while (*str) {
582: if (strchr (" \t\b\n\f$\\[]*?'\"`&|#()^<>;", *str))
583: putc ('\\', f);
584: putc (*str++, f);
585: }
586: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.