|
|
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.