1 static char *sccsid = "@(#)at.c 4.4 (Berkeley) 06/28/82"; 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 if (uday < today) 83 uyear++; 84 c = uyear%4==0? 366: 365; 85 if (uday >= c) { 86 uday -= c; 87 uyear++; 88 } 89 filename(THISDAY, uyear, uday, utime); 90 /* Create file, then change UIDS */ 91 close(creat(fname,0644)); 92 chown(fname,getuid(),getgid()); 93 setuid(getuid()); 94 ifile = stdin; 95 if (argc > larg) 96 ifile = fopen(argv[larg], "r"); 97 if (ifile == NULL) { 98 fprintf(stderr, "at: cannot open input: %s\n", argv[larg]); 99 exit(1); 100 } 101 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 102 signal(SIGINT, onintr); 103 file = fopen(fname, "w"); 104 if (file == NULL) { 105 fprintf(stderr, "at: cannot open memo file\n"); 106 exit(1); 107 } 108 if ((pwfil = popen("pwd", "r")) == NULL) { 109 fprintf(stderr, "at: can't execute pwd\n"); 110 exit(1); 111 } 112 fgets(pwbuf, 100, pwfil); 113 pclose(pwfil); 114 fprintf(file, "cd %s", pwbuf); 115 c = umask(0); 116 umask(c); 117 fprintf(file, "umask %.1o\n", c); 118 if (environ) { 119 char **ep = environ; 120 while(*ep) 121 { 122 char *cp; 123 for (tmp = *ep, cp = "TERMCAP"; *tmp==*cp; tmp++,cp++); 124 if (*cp == 0 && *tmp== '=') { 125 ep++; 126 continue; 127 } 128 for(tmp = *ep ; *tmp != '=' ; tmp++) putc(*tmp,file); 129 putc('=', file); 130 putc('\'', file); 131 for (tmp++; *tmp; tmp++) { 132 if (*tmp == '\'') 133 fputs("'\\''", file); 134 else 135 putc(*tmp, file); 136 } 137 putc('\'', file); 138 fprintf(file, "\nexport "); 139 for(tmp = *ep ; *tmp != '=' ; tmp++) putc(*tmp,file); 140 putc('\n',file); 141 ep++; 142 } 143 } 144 /* 145 * see if the SHELL variable in the current enviroment is /bin/csh 146 * and in that case, use the csh as the shell 147 */ 148 tmp = getenv("SHELL"); 149 if (strcmp(tmp+strlen(tmp)-3, "csh") == 0) 150 fprintf(file, "%s %s\n", tmp, "<< 'xxFUNNYxx'"); 151 while((c = getc(ifile)) != EOF) { 152 putc(c, file); 153 } 154 if (strcmp(tmp+strlen(tmp)-3, "csh") == 0) 155 fprintf(file, "%s\n", "xxFUNNYxx"); 156 exit(0); 157 } 158 159 makeutime(pp) 160 char *pp; 161 { 162 register val; 163 register char *p; 164 165 /* p points to a user time */ 166 p = pp; 167 val = 0; 168 while(isdigit(*p)) { 169 val = val*10+(*p++ -'0'); 170 } 171 if (p-pp < 3) 172 val *= HOUR; 173 174 for (;;) { 175 switch(*p) { 176 177 case ':': 178 ++p; 179 if (isdigit(*p)) { 180 if (isdigit(p[1])) { 181 val +=(10* *p + p[1] - 11*'0'); 182 p += 2; 183 continue; 184 } 185 } 186 fprintf(stderr, "at: bad time format:\n"); 187 exit(1); 188 189 case 'A': 190 case 'a': 191 if (val >= HALFDAY+HOUR) 192 val = DAY+1; /* illegal */ 193 if (val >= HALFDAY && val <(HALFDAY+HOUR)) 194 val -= HALFDAY; 195 break; 196 197 case 'P': 198 case 'p': 199 if (val >= HALFDAY+HOUR) 200 val = DAY+1; /* illegal */ 201 if (val < HALFDAY) 202 val += HALFDAY; 203 break; 204 205 case 'n': 206 case 'N': 207 val = HALFDAY; 208 break; 209 210 case 'M': 211 case 'm': 212 val = 0; 213 break; 214 215 216 case '\0': 217 case ' ': 218 /* 24 hour time */ 219 if (val == DAY) 220 val -= DAY; 221 break; 222 223 default: 224 fprintf(stderr, "at: bad time format\n"); 225 exit(1); 226 227 } 228 break; 229 } 230 if (val < 0 || val >= DAY) { 231 fprintf(stderr, "at: time out of range\n"); 232 exit(1); 233 } 234 if (val%HOUR >= 60) { 235 fprintf(stderr, "at: illegal minute field\n"); 236 exit(1); 237 } 238 utime = val; 239 } 240 241 242 makeuday(argc,argv) 243 char **argv; 244 { 245 /* the presumption is that argv[2], argv[3] are either 246 month day OR weekday [week]. Returns either 2 or 3 as last 247 argument used */ 248 /* first of all, what's today */ 249 long tm; 250 int found = -1; 251 char **ps; 252 struct tm *detail, *localtime(); 253 struct monstr *pt; 254 255 time(&tm); 256 detail = localtime(&tm); 257 uday = today = detail->tm_yday; 258 uyear = detail->tm_year; 259 now = detail->tm_hour*100+detail->tm_min; 260 if (argc<=2) 261 return(1); 262 /* is the next argument a month name ? */ 263 for (pt=months; pt->mname; pt++) { 264 if (prefix(argv[2], pt->mname)) { 265 if (found<0) 266 found = pt-months; 267 else { 268 fprintf(stderr, "at: ambiguous month\n"); 269 exit(1); 270 } 271 } 272 } 273 if (found>=0) { 274 if (argc<=3) 275 return(2); 276 uday = atoi(argv[3]) - 1; 277 if (uday<0) { 278 fprintf(stderr, "at: illegal day\n"); 279 exit(1); 280 } 281 while(--found>=0) 282 uday += months[found].mlen; 283 if (detail->tm_year%4==0 && uday>59) 284 uday += 1; 285 return(3); 286 } 287 /* not a month, try day of week */ 288 found = -1; 289 for (ps=days; ps<days+7; ps++) { 290 if (prefix(argv[2], *ps)) { 291 if (found<0) 292 found = ps-days; 293 else { 294 fprintf(stderr, "at: ambiguous day of week\n"); 295 exit(1); 296 } 297 } 298 } 299 if (found<0) 300 return(1); 301 /* find next day of this sort */ 302 uday = found - detail->tm_wday; 303 if (uday<=0) 304 uday += 7; 305 uday += today; 306 if (argc>3 && strcmp("week", argv[3])==0) { 307 uday += 7; 308 return(3); 309 } 310 return(2); 311 } 312 313 char * 314 prefix(begin, full) 315 char *begin, *full; 316 { 317 int c; 318 while (c = *begin++) { 319 if (isupper(c)) 320 c = tolower(c); 321 if (*full != c) 322 return(0); 323 else 324 full++; 325 } 326 return(full); 327 } 328 329 filename(dir, y, d, t) 330 char *dir; 331 { 332 register i; 333 334 for (i=0; ; i += 53) { 335 sprintf(fname, "%s/%02d.%03d.%04d.%02d", dir, y, d, t, 336 (getpid()+i)%100); 337 if (access(fname, 0) == -1) 338 return; 339 } 340 } 341 342 onintr() 343 { 344 unlink(fname); 345 exit(1); 346 } 347