BSD 4_1c_2 release
[unix-history] / usr / src / ucb / at.c
static char *sccsid = "@(#)at.c 4.4 (Berkeley) 6/28/82";
/*
* at time mon day
* at time wday
* at time wday 'week'
*
*/
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <signal.h>
#define HOUR 100
#define HALFDAY (12*HOUR)
#define DAY (24*HOUR)
#define THISDAY "/usr/spool/at"
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];
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();
char *getenv();
FILE *popen();
main(argc, argv)
char **argv;
{
extern onintr();
register c;
char pwbuf[100];
FILE *pwfil;
int larg;
char *tmp;
/* 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++;
if (uday < today)
uyear++;
c = uyear%4==0? 366: 365;
if (uday >= c) {
uday -= c;
uyear++;
}
filename(THISDAY, uyear, uday, utime);
/* Create file, then change UIDS */
close(creat(fname,0644));
chown(fname,getuid(),getgid());
setuid(getuid());
ifile = stdin;
if (argc > larg)
ifile = fopen(argv[larg], "r");
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 memo file\n");
exit(1);
}
if ((pwfil = popen("pwd", "r")) == NULL) {
fprintf(stderr, "at: can't execute pwd\n");
exit(1);
}
fgets(pwbuf, 100, pwfil);
pclose(pwfil);
fprintf(file, "cd %s", pwbuf);
c = umask(0);
umask(c);
fprintf(file, "umask %.1o\n", c);
if (environ) {
char **ep = environ;
while(*ep)
{
char *cp;
for (tmp = *ep, cp = "TERMCAP"; *tmp==*cp; tmp++,cp++);
if (*cp == 0 && *tmp== '=') {
ep++;
continue;
}
for(tmp = *ep ; *tmp != '=' ; tmp++) putc(*tmp,file);
putc('=', file);
putc('\'', file);
for (tmp++; *tmp; tmp++) {
if (*tmp == '\'')
fputs("'\\''", file);
else
putc(*tmp, file);
}
putc('\'', file);
fprintf(file, "\nexport ");
for(tmp = *ep ; *tmp != '=' ; tmp++) putc(*tmp,file);
putc('\n',file);
ep++;
}
}
/*
* see if the SHELL variable in the current enviroment is /bin/csh
* and in that case, use the csh as the shell
*/
tmp = getenv("SHELL");
if (strcmp(tmp+strlen(tmp)-3, "csh") == 0)
fprintf(file, "%s %s\n", tmp, "<< 'xxFUNNYxx'");
while((c = getc(ifile)) != EOF) {
putc(c, file);
}
if (strcmp(tmp+strlen(tmp)-3, "csh") == 0)
fprintf(file, "%s\n", "xxFUNNYxx");
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; ps<days+7; ps++) {
if (prefix(argv[2], *ps)) {
if (found<0)
found = ps-days;
else {
fprintf(stderr, "at: ambiguous day of week\n");
exit(1);
}
}
}
if (found<0)
return(1);
/* find next day of this sort */
uday = found - detail->tm_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(fname, "%s/%02d.%03d.%04d.%02d", dir, y, d, t,
(getpid()+i)%100);
if (access(fname, 0) == -1)
return;
}
}
onintr()
{
unlink(fname);
exit(1);
}