1: /* 2: * at time mon day 3: * at time wday 4: * at time wday 'week' 5: * 6: */ 7: /*! Modified by PLWard, USGS 10/30/80 for csh and mail options */ 8: 9: #include <stdio.h> 10: #include <ctype.h> 11: #include <time.h> 12: #include <signal.h> 13: #include <pwd.h> 14: 15: #define MAIL "Mail" 16: #define CD "cd" 17: #define RM "/bin/rm" 18: #define PWD "/bin/pwd" 19: #define PAST "/usr/spool/at/past" 20: #define THISDAY "/usr/spool/at" 21: #define HOUR 100 22: #define HALFDAY (12*HOUR) 23: #define DAY (24*HOUR) 24: 25: int sendmail = 1; /* default to send mail = 1, else = 0. */ 26: 27: char *days[] = { 28: "sunday", 29: "monday", 30: "tuesday", 31: "wednesday", 32: "thursday", 33: "friday", 34: "saturday", 35: }; 36: 37: struct monstr { 38: char *mname; 39: int mlen; 40: } months[] = { 41: { "january", 31 }, 42: { "february", 28 }, 43: { "march", 31 }, 44: { "april", 30 }, 45: { "may", 31 }, 46: { "june", 30 }, 47: { "july", 31 }, 48: { "august", 31 }, 49: { "september", 30 }, 50: { "october", 31 }, 51: { "november", 30 }, 52: { "december", 31 }, 53: { 0, 0 }, 54: }; 55: 56: char fname[100]; 57: char fileout[100]; 58: char temp[15]; 59: int utime; /* requested time in grains */ 60: int now; /* when is it */ 61: int uday; /* day of year to be done */ 62: int uyear; /* year */ 63: int today; /* day of year today */ 64: FILE *file; 65: FILE *ifile; 66: char **environ; 67: char *prefix(); 68: FILE *popen(); 69: struct passwd *user; 70: 71: main(argc, argv) 72: char **argv; 73: { 74: extern onintr(); 75: register c; 76: char pwbuf[100]; 77: FILE *pwfil; 78: int larg; 79: int csh; 80: int i,eq; 81: char *tmp; 82: char **ep; 83: char *cp; 84: 85: if(argv[1][0] == '-'){ 86: sendmail=sendmail ? 0 : 1; 87: for(i=2;i<=argc;i++)argv[i-1]=argv[i]; 88: argc--; 89: } 90: /* argv[1] is the user's time: e.g., 3AM */ 91: /* argv[2] is a month name or day of week */ 92: /* argv[3] is day of month or 'week' */ 93: /* another argument might be an input file */ 94: if (argc < 2) { 95: fprintf(stderr, "at: arg count\n"); 96: exit(1); 97: } 98: makeutime(argv[1]); 99: larg = makeuday(argc,argv)+1; 100: if (uday==today && larg<=2 && utime<=now) 101: uday++; 102: c = uyear%4==0? 366: 365; 103: if (uday >= c) { 104: uday -= c; 105: uyear++; 106: } 107: filename(THISDAY, uyear, uday, utime); 108: /* Create file and then change uids */ 109: close(creat(fname,0755)); 110: chown(fname,getuid(),getgid()); 111: /* fix so that root can use at */ 112: setuid(getuid()); 113: user=getpwuid(getuid()); 114: ifile = stdin; 115: if (argc > larg) 116: ifile = fopen(argv[larg], "r"); 117: else argv[larg]="from stdin"; 118: if (ifile == NULL) { 119: fprintf(stderr, "at: cannot open input: %s\n", argv[larg]); 120: exit(1); 121: } 122: if (signal(SIGINT, SIG_IGN) != SIG_IGN) 123: signal(SIGINT, onintr); 124: file = fopen(fname, "w"); 125: if (file == NULL) { 126: fprintf(stderr, "at: cannot open file in %s.\n",THISDAY); 127: exit(1); 128: } 129: /* Decide if this is a cshell file */ 130: if(ifile == stdin){ 131: tmp=getenv("SHELL"); 132: csh = (strcmp(tmp+strlen(tmp)-3,"csh")==0) ? 1 : 0; 133: } 134: else { 135: csh = ((c=getc(ifile)) == '#') ? 1 : 0; 136: fseek(ifile,0,0); 137: } 138: if (csh) fprintf(file,"#at:cshell\n"); 139: if ((pwfil = popen(PWD, "r")) == NULL) { 140: fprintf(stderr, "at: can't execute pwd\n"); 141: exit(1); 142: } 143: fgets(pwbuf, 100, pwfil); 144: pclose(pwfil); 145: fprintf(file, "%s %s",CD, pwbuf); 146: c=umask(0); 147: umask(c); 148: fprintf(file,"umask %.1o\n",c); 149: if (environ) { 150: ep = environ; 151: while (*ep){ 152: for (tmp = *ep, cp = "TERMCAP"; *tmp==*cp; tmp++,cp++); 153: if (*cp == 0 && *tmp== '=') { 154: ep++; 155: continue; 156: } 157: if (csh) fprintf(file,"setenv "); 158: for(tmp = *ep ; *tmp != '=' ; tmp++) putc(*tmp,file); 159: if (csh) putc(' ', file); 160: else putc(*tmp,file); 161: putc('\'', file); 162: for (tmp++; *tmp; tmp++) { 163: if (*tmp == '\'') 164: putc('\\', file); 165: putc(*tmp, file); 166: } 167: putc('\'', file); 168: putc('\n',file); 169: ep++; 170: } 171: if (csh) fprintf(file,"source %s/.cshrc\n",getenv("HOME")); 172: } 173: fprintf(file,"echo 'Began executing at' `date`\n"); 174: while((c = getc(ifile)) != EOF) { 175: putc(c, file); 176: } 177: fprintf(file,"%s %s\n",CD,PAST); 178: fprintf(file,"echo 'Done executing at' `date`\n"); 179: if(sendmail)fprintf(file,"%s -s 'at: ran program %s.' %s < %s\n", 180: MAIL,argv[larg],user->pw_name,fileout); 181: fprintf(file,"%s %s\n",RM,fileout); 182: exit(0); 183: } 184: 185: makeutime(pp) 186: char *pp; 187: { 188: register val; 189: register char *p; 190: 191: /* p points to a user time */ 192: p = pp; 193: val = 0; 194: while(isdigit(*p)) { 195: val = val*10+(*p++ -'0'); 196: } 197: if (p-pp < 3) 198: val *= HOUR; 199: 200: for (;;) { 201: switch(*p) { 202: 203: case ':': 204: ++p; 205: if (isdigit(*p)) { 206: if (isdigit(p[1])) { 207: val +=(10* *p + p[1] - 11*'0'); 208: p += 2; 209: continue; 210: } 211: } 212: fprintf(stderr, "at: bad time format:\n"); 213: exit(1); 214: 215: case 'A': 216: case 'a': 217: if (val >= HALFDAY+HOUR) 218: val = DAY+1; /* illegal */ 219: if (val >= HALFDAY && val <(HALFDAY+HOUR)) 220: val -= HALFDAY; 221: break; 222: 223: case 'P': 224: case 'p': 225: if (val >= HALFDAY+HOUR) 226: val = DAY+1; /* illegal */ 227: if (val < HALFDAY) 228: val += HALFDAY; 229: break; 230: 231: case 'n': 232: case 'N': 233: val = HALFDAY; 234: break; 235: 236: case 'M': 237: case 'm': 238: val = 0; 239: break; 240: 241: 242: case '\0': 243: case ' ': 244: /* 24 hour time */ 245: if (val == DAY) 246: val -= DAY; 247: break; 248: 249: default: 250: fprintf(stderr, "at: bad time format\n"); 251: exit(1); 252: 253: } 254: break; 255: } 256: if (val < 0 || val >= DAY) { 257: fprintf(stderr, "at: time out of range\n"); 258: exit(1); 259: } 260: if (val%HOUR >= 60) { 261: fprintf(stderr, "at: illegal minute field\n"); 262: exit(1); 263: } 264: utime = val; 265: } 266: 267: 268: makeuday(argc,argv) 269: char **argv; 270: { 271: /* the presumption is that argv[2], argv[3] are either 272: month day OR weekday [week]. Returns either 2 or 3 as last 273: argument used */ 274: /* first of all, what's today */ 275: long tm; 276: int found = -1; 277: char **ps; 278: struct tm *detail, *localtime(); 279: struct monstr *pt; 280: 281: time(&tm); 282: detail = localtime(&tm); 283: uday = today = detail->tm_yday; 284: uyear = detail->tm_year; 285: now = detail->tm_hour*100+detail->tm_min; 286: if (argc<=2) 287: return(1); 288: /* is the next argument a month name ? */ 289: for (pt=months; pt->mname; pt++) { 290: if (prefix(argv[2], pt->mname)) { 291: if (found<0) 292: found = pt-months; 293: else { 294: fprintf(stderr, "at: ambiguous month\n"); 295: exit(1); 296: } 297: } 298: } 299: if (found>=0) { 300: if (argc<=3) 301: return(2); 302: uday = atoi(argv[3]) - 1; 303: if (uday<0) { 304: fprintf(stderr, "at: illegal day\n"); 305: exit(1); 306: } 307: while(--found>=0) 308: uday += months[found].mlen; 309: if (detail->tm_year%4==0 && uday>59) 310: uday += 1; 311: return(3); 312: } 313: /* not a month, try day of week */ 314: found = -1; 315: for (ps=days; ps<days+7; ps++) { 316: if (prefix(argv[2], *ps)) { 317: if (found<0) 318: found = ps-days; 319: else { 320: fprintf(stderr, "at: ambiguous day of week\n"); 321: exit(1); 322: } 323: } 324: } 325: if (found<0) 326: return(1); 327: /* find next day of this sort */ 328: uday = found - detail->tm_wday; 329: if (uday<=0) 330: uday += 7; 331: uday += today; 332: if (argc>3 && strcmp("week", argv[3])==0) { 333: uday += 7; 334: return(3); 335: } 336: return(2); 337: } 338: 339: char * 340: prefix(begin, full) 341: char *begin, *full; 342: { 343: int c; 344: while (c = *begin++) { 345: if (isupper(c)) 346: c = tolower(c); 347: if (*full != c) 348: return(0); 349: else 350: full++; 351: } 352: return(full); 353: } 354: 355: filename(dir, y, d, t) 356: char *dir; 357: { 358: register i; 359: 360: for (i=0; ; i += 53) { 361: sprintf(temp,"%02d.%03d.%04d.%02d",y,d,t,(getpid()+i)%100); 362: sprintf(fname,"%s/%s",dir,temp); 363: temp[0]='M'; 364: sprintf(fileout,"%s/%s",PAST,temp); 365: if (access(fname, 0) == -1) 366: return; 367: } 368: } 369: 370: onintr() 371: { 372: unlink(fname); 373: exit(1); 374: }