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: 17: char *days[] = { 18: "sunday", 19: "monday", 20: "tuesday", 21: "wednesday", 22: "thursday", 23: "friday", 24: "saturday", 25: }; 26: 27: struct 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: 46: char fname[100]; 47: int utime; /* requested time in grains */ 48: int now; /* when is it */ 49: int uday; /* day of year to be done */ 50: int uyear; /* year */ 51: int today; /* day of year today */ 52: FILE *file; 53: FILE *ifile; 54: char **environ; 55: char *prefix(); 56: FILE *popen(); 57: 58: main(argc, argv) 59: char **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: 118: makeutime(pp) 119: char *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: 201: makeuday(argc,argv) 202: char **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: 272: char * 273: prefix(begin, full) 274: char *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: 288: filename(dir, y, d, t) 289: char *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: 301: onintr() 302: { 303: unlink(fname); 304: exit(1); 305: }