/* * at time mon day * at time wday * at time wday 'week' * */ /*! Modified by PLWard, USGS 10/30/80 for csh and mail options */ #include #include #include #include #include #define MAIL "Mail" #define CD "cd" #define RM "/bin/rm" #define PWD "/bin/pwd" #define PAST "/usr/spool/at/past" #define THISDAY "/usr/spool/at" #define HOUR 100 #define HALFDAY (12*HOUR) #define DAY (24*HOUR) int sendmail = 1; /* default to send mail = 1, else = 0. */ char *days[] = { "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", }; struct monstr { char *mname; int mlen; } months[] = { { "january", 31 }, { "february", 28 }, { "march", 31 }, { "april", 30 }, { "may", 31 }, { "june", 30 }, { "july", 31 }, { "august", 31 }, { "september", 30 }, { "october", 31 }, { "november", 30 }, { "december", 31 }, { 0, 0 }, }; char fname[100]; char fileout[100]; char temp[15]; int utime; /* requested time in grains */ int now; /* when is it */ int uday; /* day of year to be done */ int uyear; /* year */ int today; /* day of year today */ FILE *file; FILE *ifile; char **environ; char *prefix(); FILE *popen(); struct passwd *user; main(argc, argv) char **argv; { extern onintr(); register c; char pwbuf[100]; FILE *pwfil; int larg; int csh; int i,eq; char *tmp; char **ep; char *cp; if(argv[1][0] == '-'){ sendmail=sendmail ? 0 : 1; for(i=2;i<=argc;i++)argv[i-1]=argv[i]; argc--; } /* argv[1] is the user's time: e.g., 3AM */ /* argv[2] is a month name or day of week */ /* argv[3] is day of month or 'week' */ /* another argument might be an input file */ if (argc < 2) { fprintf(stderr, "at: arg count\n"); exit(1); } makeutime(argv[1]); larg = makeuday(argc,argv)+1; if (uday==today && larg<=2 && utime<=now) uday++; c = uyear%4==0? 366: 365; if (uday >= c) { uday -= c; uyear++; } filename(THISDAY, uyear, uday, utime); /* Create file and then change uids */ close(creat(fname,0755)); chown(fname,getuid(),getgid()); /* fix so that root can use at */ setuid(getuid()); user=getpwuid(getuid()); ifile = stdin; if (argc > larg) ifile = fopen(argv[larg], "r"); else argv[larg]="from stdin"; if (ifile == NULL) { fprintf(stderr, "at: cannot open input: %s\n", argv[larg]); exit(1); } if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, onintr); file = fopen(fname, "w"); if (file == NULL) { fprintf(stderr, "at: cannot open file in %s.\n",THISDAY); exit(1); } /* Decide if this is a cshell file */ if(ifile == stdin){ tmp=getenv("SHELL"); csh = (strcmp(tmp+strlen(tmp)-3,"csh")==0) ? 1 : 0; } else { csh = ((c=getc(ifile)) == '#') ? 1 : 0; fseek(ifile,0,0); } if (csh) fprintf(file,"#at:cshell\n"); if ((pwfil = popen(PWD, "r")) == NULL) { fprintf(stderr, "at: can't execute pwd\n"); exit(1); } fgets(pwbuf, 100, pwfil); pclose(pwfil); fprintf(file, "%s %s",CD, pwbuf); c=umask(0); umask(c); fprintf(file,"umask %.1o\n",c); if (environ) { ep = environ; while (*ep){ for (tmp = *ep, cp = "TERMCAP"; *tmp==*cp; tmp++,cp++); if (*cp == 0 && *tmp== '=') { ep++; continue; } if (csh) fprintf(file,"setenv "); for(tmp = *ep ; *tmp != '=' ; tmp++) putc(*tmp,file); if (csh) putc(' ', file); else putc(*tmp,file); putc('\'', file); for (tmp++; *tmp; tmp++) { if (*tmp == '\'') putc('\\', file); putc(*tmp, file); } putc('\'', file); putc('\n',file); ep++; } if (csh) fprintf(file,"source %s/.cshrc\n",getenv("HOME")); } fprintf(file,"echo 'Began executing at' `date`\n"); while((c = getc(ifile)) != EOF) { putc(c, file); } fprintf(file,"%s %s\n",CD,PAST); fprintf(file,"echo 'Done executing at' `date`\n"); if(sendmail)fprintf(file,"%s -s 'at: ran program %s.' %s < %s\n", MAIL,argv[larg],user->pw_name,fileout); fprintf(file,"%s %s\n",RM,fileout); exit(0); } makeutime(pp) char *pp; { register val; register char *p; /* p points to a user time */ p = pp; val = 0; while(isdigit(*p)) { val = val*10+(*p++ -'0'); } if (p-pp < 3) val *= HOUR; for (;;) { switch(*p) { case ':': ++p; if (isdigit(*p)) { if (isdigit(p[1])) { val +=(10* *p + p[1] - 11*'0'); p += 2; continue; } } fprintf(stderr, "at: bad time format:\n"); exit(1); case 'A': case 'a': if (val >= HALFDAY+HOUR) val = DAY+1; /* illegal */ if (val >= HALFDAY && val <(HALFDAY+HOUR)) val -= HALFDAY; break; case 'P': case 'p': if (val >= HALFDAY+HOUR) val = DAY+1; /* illegal */ if (val < HALFDAY) val += HALFDAY; break; case 'n': case 'N': val = HALFDAY; break; case 'M': case 'm': val = 0; break; case '\0': case ' ': /* 24 hour time */ if (val == DAY) val -= DAY; break; default: fprintf(stderr, "at: bad time format\n"); exit(1); } break; } if (val < 0 || val >= DAY) { fprintf(stderr, "at: time out of range\n"); exit(1); } if (val%HOUR >= 60) { fprintf(stderr, "at: illegal minute field\n"); exit(1); } utime = val; } makeuday(argc,argv) char **argv; { /* the presumption is that argv[2], argv[3] are either month day OR weekday [week]. Returns either 2 or 3 as last argument used */ /* first of all, what's today */ long tm; int found = -1; char **ps; struct tm *detail, *localtime(); struct monstr *pt; time(&tm); detail = localtime(&tm); uday = today = detail->tm_yday; uyear = detail->tm_year; now = detail->tm_hour*100+detail->tm_min; if (argc<=2) return(1); /* is the next argument a month name ? */ for (pt=months; pt->mname; pt++) { if (prefix(argv[2], pt->mname)) { if (found<0) found = pt-months; else { fprintf(stderr, "at: ambiguous month\n"); exit(1); } } } if (found>=0) { if (argc<=3) return(2); uday = atoi(argv[3]) - 1; if (uday<0) { fprintf(stderr, "at: illegal day\n"); exit(1); } while(--found>=0) uday += months[found].mlen; if (detail->tm_year%4==0 && uday>59) uday += 1; return(3); } /* not a month, try day of week */ found = -1; for (ps=days; pstm_wday; if (uday<=0) uday += 7; uday += today; if (argc>3 && strcmp("week", argv[3])==0) { uday += 7; return(3); } return(2); } char * prefix(begin, full) char *begin, *full; { int c; while (c = *begin++) { if (isupper(c)) c = tolower(c); if (*full != c) return(0); else full++; } return(full); } filename(dir, y, d, t) char *dir; { register i; for (i=0; ; i += 53) { sprintf(temp,"%02d.%03d.%04d.%02d",y,d,t,(getpid()+i)%100); sprintf(fname,"%s/%s",dir,temp); temp[0]='M'; sprintf(fileout,"%s/%s",PAST,temp); if (access(fname, 0) == -1) return; } } onintr() { unlink(fname); exit(1); }