|
|
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 rflg; ! 66: char dflg; ! 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, "rd")) != EOF) { ! 88: switch (c) { ! 89: ! 90: case 'r': ! 91: rflg = 1; ! 92: break; ! 93: ! 94: case 'd': ! 95: dflg = 1; ! 96: break; ! 97: ! 98: default: ! 99: errflg = 1; ! 100: break; ! 101: } ! 102: } ! 103: ! 104: if (errflg) { ! 105: fprintf (stderr, "usage: at [-rd] 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 (rflg && !dflg) { ! 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 (rflg || dflg) { ! 142: char prefix[50]; ! 143: sprintf (prefix, "%.2d.%.3d.%.4d", uyear, uday, utime); ! 144: if (rflg) { ! 145: if (readdir (prefix, prfile) == 0) ! 146: exit (0); ! 147: if (dflg) ! 148: putchar ('\n'); ! 149: } ! 150: ! 151: if (dflg) { ! 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 either 2 or 3 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 (uday == today && utime < now) ! 364: { ! 365: fprintf(stderr, "at: Warning: time specified is past; assuming next year....\n"); ! 366: ++uyear; ! 367: } ! 368: return(3); ! 369: } ! 370: /* not a month, try day of week */ ! 371: found = -1; ! 372: for (ps=days; ps<days+7; ps++) { ! 373: if (prefix(argv[2], *ps)) { ! 374: if (found<0) ! 375: found = ps-days; ! 376: else { ! 377: fprintf(stderr, "at: ambiguous day of week\n"); ! 378: exit(1); ! 379: } ! 380: } ! 381: } ! 382: if (found<0) ! 383: return(1); ! 384: /* find next day of this sort */ ! 385: uday = found - detail->tm_wday; ! 386: if (uday<=0) ! 387: uday += 7; ! 388: uday += today; ! 389: /* Bogus... ! 390: if (detail->tm_year%4==0 && uday>59) ! 391: uday += 1; ! 392: */ ! 393: if (argc>3 && strcmp("week", argv[3])==0) { ! 394: uday += 7; ! 395: return(3); ! 396: } ! 397: return(2); ! 398: } ! 399: ! 400: char * ! 401: prefix(begin, full) ! 402: char *begin, *full; ! 403: { ! 404: int c; ! 405: while (c = *begin++) { ! 406: if (isupper(c)) ! 407: c = tolower(c); ! 408: if (*full != c) ! 409: return(0); ! 410: else ! 411: full++; ! 412: } ! 413: return(full); ! 414: } ! 415: ! 416: filename(dir, y, d, t) ! 417: char *dir; ! 418: { ! 419: register i; ! 420: ! 421: for (i=0; ; i += 53) { ! 422: sprintf(fname, "%s/%.2d.%.3d.%.4d.%.2d", dir, y, d, t, ! 423: (getpid()+i)%100); ! 424: if (access(fname, 0) == -1) ! 425: return; ! 426: } ! 427: } ! 428: ! 429: onintr() ! 430: { ! 431: unlink(fname); ! 432: exit(1); ! 433: } ! 434: ! 435: /* hand "fn" all path names in spool directory starting with "prefix" */ ! 436: int ! 437: readdir(prefix, fn) ! 438: char *prefix; ! 439: void (*fn)(); ! 440: { ! 441: struct dir dbuf; ! 442: register FILE *f; ! 443: register int count = 0; ! 444: ! 445: f = fopen (THISDAY, "r"); ! 446: if (f == NULL) { ! 447: fprintf (stderr, "cannot open %s\n", THISDAY); ! 448: return; ! 449: } ! 450: ! 451: while (fread (&dbuf, sizeof dbuf, 1, f) == 1) { ! 452: if (dbuf.d_ino != 0 && dbuf.d_name[0] != '.' ! 453: && strncmp (dbuf.d_name, prefix, strlen(prefix)) == 0) { ! 454: char file[sizeof (THISDAY) + DIRSIZ + 1]; ! 455: struct stat sb; ! 456: strcpy (file, THISDAY); ! 457: strcat (file, "/"); ! 458: strncat (file, dbuf.d_name, DIRSIZ); ! 459: if (stat (file, &sb) >= 0 && sb.st_uid == getuid()) { ! 460: count++; ! 461: (*fn) (file); ! 462: } ! 463: } ! 464: } ! 465: ! 466: fclose (f); ! 467: ! 468: if (count == 0) ! 469: fprintf (stderr, "no items\n"); ! 470: } ! 471: ! 472: /* ! 473: * return pointer to (static) area containing date and time ! 474: * for activation of file, or argument if invalid format. ! 475: */ ! 476: char * ! 477: pathdate (path) ! 478: char *path; ! 479: { ! 480: int month, mday, yday, year, tm, junk; ! 481: register int i; ! 482: register char *p, *q; ! 483: static char res[50]; ! 484: ! 485: /* point p at last component of path name */ ! 486: p = q = path; ! 487: while (*q) ! 488: if (*q++ == '/') ! 489: p = q; ! 490: ! 491: /* break out the fields */ ! 492: if (sscanf(p, "%2d.%3d.%4d.%2d", &year, &yday, &tm, &junk) != 4) ! 493: return path; ! 494: ! 495: /* determine the month and day of month */ ! 496: month = 0; ! 497: mday = yday + 1; ! 498: while (months[month].mlen && mday > months[month].mlen) { ! 499: mday -= months[month].mlen; ! 500: month++; ! 501: } ! 502: ! 503: /* check for impossible date */ ! 504: if (++month > 12) ! 505: return path; ! 506: ! 507: /* check for leap year */ ! 508: if (month > 2 && year % 4 == 0 && --mday <= 0) { ! 509: mday = months[--month - 1].mlen; ! 510: if (month == 2) ! 511: mday++; ! 512: } ! 513: ! 514: /* build the result */ ! 515: sprintf (res, "%.2d:%.2d %d/%d/%d", tm/100, tm%100, month, mday, year); ! 516: return res; ! 517: } ! 518: ! 519: void ! 520: prdir (path) ! 521: register char *path; ! 522: { ! 523: printf ("%s\n", pathdate (path)); ! 524: } ! 525: ! 526: void ! 527: prfile (path) ! 528: register char *path; ! 529: { ! 530: register FILE *f; ! 531: ! 532: printf ("\n%s:", pathdate (path)); ! 533: f = fopen (path, "r"); ! 534: if (f == NULL) { ! 535: fprintf (stderr, " cannot open %s\n", path); ! 536: } else { ! 537: register int c; ! 538: printf ("\n\n"); ! 539: while ((c = getc(f)) != EOF) ! 540: putchar (c); ! 541: } ! 542: fclose (f); ! 543: } ! 544: ! 545: void ! 546: delfile(path) ! 547: register char *path; ! 548: { ! 549: if (unlink(path) < 0) ! 550: fprintf (stderr, "cannot delete %s\n", path); ! 551: else ! 552: fprintf (stderr, "delete %s\n", pathdate(path)); ! 553: } ! 554: char * ! 555: idend(s) ! 556: char *s; ! 557: { ! 558: while(*s && *s!='=' && *s!='(') ! 559: s++; ! 560: return s; ! 561: } ! 562: /* print a shell variable with quoting */ ! 563: void ! 564: vprint (f, str) ! 565: register FILE *f; ! 566: register char *str; ! 567: { ! 568: if(*idend(str)=='(') /* function; the shell's already quoted it right */ ! 569: fputs(str, f); ! 570: else ! 571: while (*str) { ! 572: if (strchr (" \t\b\n\f$\\[]*?'\"`&|#()^<>;", *str)) ! 573: putc ('\\', f); ! 574: putc (*str++, f); ! 575: } ! 576: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.