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