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