#define HUNK 32
char *cmd;
char *root;
int debug;
int giveup = 2*24*60*60;
int load;
int limit;
/* the current directory */
Dir *dirbuf;
long ndirbuf = 0;
int nfiles;
char *curdir;
char *runqlog = "runq";
int *pidlist;
char **badsys; /* array of recalcitrant systems */
int nbad;
int npid = 50;
int sflag; /* single thread per directory */
int aflag; /* all directories */
int Eflag; /* ignore E.xxxxxx dates */
int Rflag; /* no giving up, ever */
/* error file (may have) appeared after we read the directory */
/* stomp on data file in case of phase error */
remove(file(name, 'D'));
remove(file(name, 'E'));
}
/*
* like trylock, but we've already got the lock on fd,
* and don't want an L. lock file.
*/
static Mlock *
keeplockalive(char *path, int fd)
{
char buf[1];
Mlock *l;
/* fork process to keep lock alive until sysunlock(l) */
switch(l->pid = rfork(RFPROC)){
default:
break;
case 0:
fd = l->fd;
for(;;){
sleep(1000*60);
if(pread(fd, buf, 1, 0) < 0)
break;
}
_exits(0);
}
return l;
}
/*
* try a message
*/
void
dofile(Dir *dp)
{
Dir *d;
int dfd, ac, dtime, efd, pid, i, etime;
char *buf, *cp, **av;
Waitmsg *wm;
Biobuf *b;
Mlock *l = nil;
if(debug)
fprint(2, "dofile %s\n", dp->name);
/*
* if no data file or empty control or data file, just clean up
* the empty control file must be 15 minutes old, to minimize the
* chance of a race.
*/
d = dirstat(file(dp->name, 'D'));
if(d == nil){
syslog(0, runqlog, "no data file for %s", dp->name);
remmatch(dp->name);
return;
}
if(dp->length == 0){
if(time(0)-dp->mtime > 15*60){
syslog(0, runqlog, "empty ctl file for %s", dp->name);
remmatch(dp->name);
}
return;
}
dtime = d->mtime;
free(d);
/*
* retry times depend on the age of the errors file
*/
if(!Eflag && (d = dirstat(file(dp->name, 'E'))) != nil){
etime = d->mtime;
free(d);
if(etime - dtime < 60*60){
/* up to the first hour, try every 15 minutes */
if(time(0) - etime < 15*60)
return;
} else {
/* after the first hour, try once an hour */
if(time(0) - etime < 60*60)
return;
}
}
/*
* open control and data
*/
b = sysopen(file(dp->name, 'C'), "rl", 0660);
if(b == 0) {
if(debug)
fprint(2, "can't open %s: %r\n", file(dp->name, 'C'));
return;
}
dfd = open(file(dp->name, 'D'), OREAD);
if(dfd < 0){
if(debug)
fprint(2, "can't open %s: %r\n", file(dp->name, 'D'));
Bterm(b);
sysunlockfile(Bfildes(b));
return;
}
/*
* make arg list
* - read args into (malloc'd) buffer
* - malloc a vector and copy pointers to args into it
*/
buf = malloc(dp->length+1);
if(buf == 0){
warning("buffer allocation", 0);
Bterm(b);
sysunlockfile(Bfildes(b));
close(dfd);
return;
}
if(Bread(b, buf, dp->length) != dp->length){
warning("reading control file %s\n", dp->name);
Bterm(b);
sysunlockfile(Bfildes(b));
close(dfd);
free(buf);
return;
}
buf[dp->length] = 0;
av = malloc(2*sizeof(char*));
if(av == 0){
warning("argv allocation", 0);
close(dfd);
free(buf);
Bterm(b);
sysunlockfile(Bfildes(b));
return;
}
for(ac = 1, cp = buf; *cp; ac++){
while(isspace(*cp))
*cp++ = 0;
if(*cp == 0)
break;
/*
* Ken's fs, for example, gives us 5 minutes of inactivity before
* the lock goes stale, so we have to keep reading it.
*/
l = keeplockalive(file(dp->name, 'C'), Bfildes(b));
/*
* send back the mail with an error message
*
* return 0 if successful
*/
int
returnmail(char **av, char *name, char *msg)
{
char buf[256], attachment[Pathlen], *sender;
int i, fd, pfd[2];
long n;
Waitmsg *wm;
String *s;