17dd7cddfSDavid du Colombier #include "common.h" 23e12c5d1SDavid du Colombier #include <ctype.h> 33e12c5d1SDavid du Colombier 43e12c5d1SDavid du Colombier void doalldirs(void); 53e12c5d1SDavid du Colombier void dodir(char*); 63e12c5d1SDavid du Colombier void dofile(Dir*); 73e12c5d1SDavid du Colombier void rundir(char*); 83e12c5d1SDavid du Colombier char* file(char*, char); 93e12c5d1SDavid du Colombier void warning(char*, void*); 103e12c5d1SDavid du Colombier void error(char*, void*); 113e12c5d1SDavid du Colombier int returnmail(char**, char*, char*); 127dd7cddfSDavid du Colombier void logit(char*, char*, char**); 137dd7cddfSDavid du Colombier void doload(int); 143e12c5d1SDavid du Colombier 153e12c5d1SDavid du Colombier #define HUNK 32 163e12c5d1SDavid du Colombier char *cmd; 173e12c5d1SDavid du Colombier char *root; 183e12c5d1SDavid du Colombier int debug; 197dd7cddfSDavid du Colombier int giveup = 2*24*60*60; 207dd7cddfSDavid du Colombier int load; 2114414594SDavid du Colombier int limit; 22219b2ee8SDavid du Colombier 23219b2ee8SDavid du Colombier /* the current directory */ 24219b2ee8SDavid du Colombier Dir *dirbuf; 25219b2ee8SDavid du Colombier long ndirbuf = 0; 26219b2ee8SDavid du Colombier int nfiles; 277dd7cddfSDavid du Colombier char *curdir; 28219b2ee8SDavid du Colombier 297dd7cddfSDavid du Colombier char *runqlog = "runq"; 30219b2ee8SDavid du Colombier 317dd7cddfSDavid du Colombier int *pidlist; 327dd7cddfSDavid du Colombier char **badsys; /* array of recalcitrant systems */ 337dd7cddfSDavid du Colombier int nbad; 347dd7cddfSDavid du Colombier int npid = 50; 357dd7cddfSDavid du Colombier int sflag; /* single thread per directory */ 367dd7cddfSDavid du Colombier int aflag; /* all directories */ 377dd7cddfSDavid du Colombier int Eflag; /* ignore E.xxxxxx dates */ 383e12c5d1SDavid du Colombier 393e12c5d1SDavid du Colombier void 403e12c5d1SDavid du Colombier usage(void) 413e12c5d1SDavid du Colombier { 4214414594SDavid du Colombier fprint(2, "usage: runq [-adsE] [-q dir] [-l load] [-t time] [-r nfiles] [-n nprocs] q-root cmd\n"); 433e12c5d1SDavid du Colombier exits(""); 443e12c5d1SDavid du Colombier } 453e12c5d1SDavid du Colombier 463e12c5d1SDavid du Colombier void 47219b2ee8SDavid du Colombier main(int argc, char **argv) 483e12c5d1SDavid du Colombier { 497dd7cddfSDavid du Colombier char *qdir, *x; 503e12c5d1SDavid du Colombier 517dd7cddfSDavid du Colombier qdir = 0; 523e12c5d1SDavid du Colombier 53219b2ee8SDavid du Colombier ARGBEGIN{ 547dd7cddfSDavid du Colombier case 'l': 557dd7cddfSDavid du Colombier x = ARGF(); 567dd7cddfSDavid du Colombier if(x == 0) 577dd7cddfSDavid du Colombier usage(); 587dd7cddfSDavid du Colombier load = atoi(x); 597dd7cddfSDavid du Colombier if(load < 0) 607dd7cddfSDavid du Colombier load = 0; 617dd7cddfSDavid du Colombier break; 627dd7cddfSDavid du Colombier case 'E': 637dd7cddfSDavid du Colombier Eflag++; 647dd7cddfSDavid du Colombier break; 653e12c5d1SDavid du Colombier case 'a': 667dd7cddfSDavid du Colombier aflag++; 673e12c5d1SDavid du Colombier break; 683e12c5d1SDavid du Colombier case 'd': 69219b2ee8SDavid du Colombier debug++; 703e12c5d1SDavid du Colombier break; 7114414594SDavid du Colombier case 'r': 7214414594SDavid du Colombier limit = atoi(ARGF()); 7314414594SDavid du Colombier break; 747dd7cddfSDavid du Colombier case 's': 757dd7cddfSDavid du Colombier sflag++; 767dd7cddfSDavid du Colombier break; 77219b2ee8SDavid du Colombier case 't': 78219b2ee8SDavid du Colombier giveup = 60*60*atoi(ARGF()); 79219b2ee8SDavid du Colombier break; 807dd7cddfSDavid du Colombier case 'q': 817dd7cddfSDavid du Colombier qdir = ARGF(); 827dd7cddfSDavid du Colombier if(qdir == 0) 837dd7cddfSDavid du Colombier usage(); 847dd7cddfSDavid du Colombier break; 857dd7cddfSDavid du Colombier case 'n': 867dd7cddfSDavid du Colombier npid = atoi(ARGF()); 877dd7cddfSDavid du Colombier if(npid == 0) 887dd7cddfSDavid du Colombier usage(); 897dd7cddfSDavid du Colombier break; 90219b2ee8SDavid du Colombier }ARGEND; 91219b2ee8SDavid du Colombier 92219b2ee8SDavid du Colombier if(argc != 2) 933e12c5d1SDavid du Colombier usage(); 94219b2ee8SDavid du Colombier 957dd7cddfSDavid du Colombier pidlist = malloc(npid*sizeof(*pidlist)); 967dd7cddfSDavid du Colombier if(pidlist == 0) 977dd7cddfSDavid du Colombier error("can't malloc", 0); 987dd7cddfSDavid du Colombier 997dd7cddfSDavid du Colombier if(aflag == 0 && qdir == 0) { 1007dd7cddfSDavid du Colombier qdir = getuser(); 1017dd7cddfSDavid du Colombier if(qdir == 0) 1027dd7cddfSDavid du Colombier error("unknown user", 0); 1037dd7cddfSDavid du Colombier } 104219b2ee8SDavid du Colombier root = argv[0]; 105219b2ee8SDavid du Colombier cmd = argv[1]; 1063e12c5d1SDavid du Colombier 1073e12c5d1SDavid du Colombier if(chdir(root) < 0) 1083e12c5d1SDavid du Colombier error("can't cd to %s", root); 1093e12c5d1SDavid du Colombier 1107dd7cddfSDavid du Colombier doload(1); 1117dd7cddfSDavid du Colombier if(aflag) 1123e12c5d1SDavid du Colombier doalldirs(); 1133e12c5d1SDavid du Colombier else 1147dd7cddfSDavid du Colombier dodir(qdir); 1157dd7cddfSDavid du Colombier doload(0); 1163e12c5d1SDavid du Colombier exits(0); 1173e12c5d1SDavid du Colombier } 1183e12c5d1SDavid du Colombier 1193e12c5d1SDavid du Colombier int 1203e12c5d1SDavid du Colombier emptydir(char *name) 1213e12c5d1SDavid du Colombier { 1223e12c5d1SDavid du Colombier int fd; 1233e12c5d1SDavid du Colombier long n; 1249a747e4fSDavid du Colombier char buf[2048]; 1253e12c5d1SDavid du Colombier 1263e12c5d1SDavid du Colombier fd = open(name, OREAD); 1273e12c5d1SDavid du Colombier if(fd < 0) 1283e12c5d1SDavid du Colombier return 1; 1299a747e4fSDavid du Colombier n = read(fd, buf, sizeof(buf)); 1303e12c5d1SDavid du Colombier close(fd); 1317dd7cddfSDavid du Colombier if(n <= 0) { 1327dd7cddfSDavid du Colombier if(debug) 1337dd7cddfSDavid du Colombier fprint(2, "removing directory %s\n", name); 1347dd7cddfSDavid du Colombier syslog(0, runqlog, "rmdir %s", name); 1357dd7cddfSDavid du Colombier sysremove(name); 1363e12c5d1SDavid du Colombier return 1; 1377dd7cddfSDavid du Colombier } 1383e12c5d1SDavid du Colombier return 0; 1393e12c5d1SDavid du Colombier } 1403e12c5d1SDavid du Colombier 1417dd7cddfSDavid du Colombier int 1427dd7cddfSDavid du Colombier forkltd(void) 1437dd7cddfSDavid du Colombier { 1447dd7cddfSDavid du Colombier int i; 1457dd7cddfSDavid du Colombier int pid; 1467dd7cddfSDavid du Colombier 1477dd7cddfSDavid du Colombier for(i = 0; i < npid; i++){ 1487dd7cddfSDavid du Colombier if(pidlist[i] <= 0) 1497dd7cddfSDavid du Colombier break; 1507dd7cddfSDavid du Colombier } 1517dd7cddfSDavid du Colombier 1527dd7cddfSDavid du Colombier while(i >= npid){ 1539a747e4fSDavid du Colombier pid = waitpid(); 1547dd7cddfSDavid du Colombier if(pid < 0){ 1557dd7cddfSDavid du Colombier syslog(0, runqlog, "forkltd confused"); 1567dd7cddfSDavid du Colombier exits(0); 1577dd7cddfSDavid du Colombier } 1587dd7cddfSDavid du Colombier 1597dd7cddfSDavid du Colombier for(i = 0; i < npid; i++) 1607dd7cddfSDavid du Colombier if(pidlist[i] == pid) 1617dd7cddfSDavid du Colombier break; 1627dd7cddfSDavid du Colombier } 1637dd7cddfSDavid du Colombier pidlist[i] = fork(); 1647dd7cddfSDavid du Colombier return pidlist[i]; 1657dd7cddfSDavid du Colombier } 1667dd7cddfSDavid du Colombier 1673e12c5d1SDavid du Colombier /* 1687dd7cddfSDavid du Colombier * run all user directories, must be bootes (or root on unix) to do this 1693e12c5d1SDavid du Colombier */ 1703e12c5d1SDavid du Colombier void 1713e12c5d1SDavid du Colombier doalldirs(void) 1723e12c5d1SDavid du Colombier { 1739a747e4fSDavid du Colombier Dir *db; 1743e12c5d1SDavid du Colombier int fd; 1753e12c5d1SDavid du Colombier long i, n; 1763e12c5d1SDavid du Colombier 1777dd7cddfSDavid du Colombier 1783e12c5d1SDavid du Colombier fd = open(".", OREAD); 1793e12c5d1SDavid du Colombier if(fd == -1){ 1803e12c5d1SDavid du Colombier warning("reading %s", root); 1813e12c5d1SDavid du Colombier return; 1823e12c5d1SDavid du Colombier } 1839a747e4fSDavid du Colombier n = sysdirreadall(fd, &db); 1849a747e4fSDavid du Colombier if(n > 0){ 1853e12c5d1SDavid du Colombier for(i=0; i<n; i++){ 1869a747e4fSDavid du Colombier if(db[i].qid.type & QTDIR){ 1873e12c5d1SDavid du Colombier if(emptydir(db[i].name)) 1883e12c5d1SDavid du Colombier continue; 1897dd7cddfSDavid du Colombier switch(forkltd()){ 1903e12c5d1SDavid du Colombier case -1: 1917dd7cddfSDavid du Colombier syslog(0, runqlog, "out of procs"); 1927dd7cddfSDavid du Colombier doload(0); 1937dd7cddfSDavid du Colombier exits(0); 1943e12c5d1SDavid du Colombier case 0: 1957dd7cddfSDavid du Colombier if(sysdetach() < 0) 1967dd7cddfSDavid du Colombier error("%r", 0); 1973e12c5d1SDavid du Colombier dodir(db[i].name); 1983e12c5d1SDavid du Colombier exits(0); 1993e12c5d1SDavid du Colombier default: 2003e12c5d1SDavid du Colombier break; 2013e12c5d1SDavid du Colombier } 2023e12c5d1SDavid du Colombier } 2033e12c5d1SDavid du Colombier } 2049a747e4fSDavid du Colombier free(db); 2053e12c5d1SDavid du Colombier } 2063e12c5d1SDavid du Colombier close(fd); 2073e12c5d1SDavid du Colombier } 2083e12c5d1SDavid du Colombier 2093e12c5d1SDavid du Colombier /* 2103e12c5d1SDavid du Colombier * cd to a user directory and run it 2113e12c5d1SDavid du Colombier */ 2123e12c5d1SDavid du Colombier void 2133e12c5d1SDavid du Colombier dodir(char *name) 2143e12c5d1SDavid du Colombier { 2157dd7cddfSDavid du Colombier curdir = name; 2167dd7cddfSDavid du Colombier 2173e12c5d1SDavid du Colombier if(chdir(name) < 0){ 2183e12c5d1SDavid du Colombier warning("cd to %s", name); 2193e12c5d1SDavid du Colombier return; 2203e12c5d1SDavid du Colombier } 2213e12c5d1SDavid du Colombier if(debug) 2223e12c5d1SDavid du Colombier fprint(2, "running %s\n", name); 2233e12c5d1SDavid du Colombier rundir(name); 2243e12c5d1SDavid du Colombier chdir(".."); 2253e12c5d1SDavid du Colombier } 2263e12c5d1SDavid du Colombier 2273e12c5d1SDavid du Colombier /* 2283e12c5d1SDavid du Colombier * run the current directory 2293e12c5d1SDavid du Colombier */ 2303e12c5d1SDavid du Colombier void 2313e12c5d1SDavid du Colombier rundir(char *name) 2323e12c5d1SDavid du Colombier { 2333e12c5d1SDavid du Colombier int fd; 234219b2ee8SDavid du Colombier long i; 2353e12c5d1SDavid du Colombier 2367dd7cddfSDavid du Colombier if(aflag && sflag) 2377dd7cddfSDavid du Colombier fd = sysopenlocked(".", OREAD); 2387dd7cddfSDavid du Colombier else 2393e12c5d1SDavid du Colombier fd = open(".", OREAD); 2403e12c5d1SDavid du Colombier if(fd == -1){ 2413e12c5d1SDavid du Colombier warning("reading %s", name); 2423e12c5d1SDavid du Colombier return; 2433e12c5d1SDavid du Colombier } 2449a747e4fSDavid du Colombier nfiles = sysdirreadall(fd, &dirbuf); 2459a747e4fSDavid du Colombier if(nfiles > 0){ 246219b2ee8SDavid du Colombier for(i=0; i<nfiles; i++){ 247219b2ee8SDavid du Colombier if(dirbuf[i].name[0]!='C' || dirbuf[i].name[1]!='.') 248219b2ee8SDavid du Colombier continue; 249219b2ee8SDavid du Colombier dofile(&dirbuf[i]); 250219b2ee8SDavid du Colombier } 2519a747e4fSDavid du Colombier free(dirbuf); 2529a747e4fSDavid du Colombier } 2537dd7cddfSDavid du Colombier if(aflag && sflag) 2547dd7cddfSDavid du Colombier sysunlockfile(fd); 2557dd7cddfSDavid du Colombier else 2567dd7cddfSDavid du Colombier close(fd); 257219b2ee8SDavid du Colombier } 258219b2ee8SDavid du Colombier 259219b2ee8SDavid du Colombier /* 260219b2ee8SDavid du Colombier * free files matching name in the current directory 261219b2ee8SDavid du Colombier */ 262219b2ee8SDavid du Colombier void 263219b2ee8SDavid du Colombier remmatch(char *name) 264219b2ee8SDavid du Colombier { 265219b2ee8SDavid du Colombier long i; 266219b2ee8SDavid du Colombier 2677dd7cddfSDavid du Colombier syslog(0, runqlog, "removing %s/%s", curdir, name); 2687dd7cddfSDavid du Colombier 269219b2ee8SDavid du Colombier for(i=0; i<nfiles; i++){ 270219b2ee8SDavid du Colombier if(strcmp(&dirbuf[i].name[1], &name[1]) == 0) 2717dd7cddfSDavid du Colombier sysremove(dirbuf[i].name); 272219b2ee8SDavid du Colombier } 273219b2ee8SDavid du Colombier 274219b2ee8SDavid du Colombier /* error file (may have) appeared after we read the directory */ 2757dd7cddfSDavid du Colombier /* stomp on data file in case of phase error */ 2767dd7cddfSDavid du Colombier sysremove(file(name, 'D')); 2777dd7cddfSDavid du Colombier sysremove(file(name, 'E')); 2783e12c5d1SDavid du Colombier } 2793e12c5d1SDavid du Colombier 2803e12c5d1SDavid du Colombier /* 2813e12c5d1SDavid du Colombier * try a message 2823e12c5d1SDavid du Colombier */ 2833e12c5d1SDavid du Colombier void 2843e12c5d1SDavid du Colombier dofile(Dir *dp) 2853e12c5d1SDavid du Colombier { 2869a747e4fSDavid du Colombier Dir *d; 2879a747e4fSDavid du Colombier int dfd, ac, dtime, efd, pid, i, etime; 2887dd7cddfSDavid du Colombier char *buf, *cp, **av; 2899a747e4fSDavid du Colombier Waitmsg *wm; 2907dd7cddfSDavid du Colombier Biobuf *b; 2913e12c5d1SDavid du Colombier 2923e12c5d1SDavid du Colombier if(debug) 2933e12c5d1SDavid du Colombier fprint(2, "dofile %s\n", dp->name); 2943e12c5d1SDavid du Colombier /* 29514414594SDavid du Colombier * if no data file or empty control or data file, just clean up 29614414594SDavid du Colombier * the empty control file must be 15 minutes old, to minimize the 29714414594SDavid du Colombier * chance of a race. 2983e12c5d1SDavid du Colombier */ 2999a747e4fSDavid du Colombier d = dirstat(file(dp->name, 'D')); 3009a747e4fSDavid du Colombier if(d == nil){ 3017dd7cddfSDavid du Colombier syslog(0, runqlog, "no data file for %s", dp->name); 302219b2ee8SDavid du Colombier remmatch(dp->name); 3033e12c5d1SDavid du Colombier return; 3043e12c5d1SDavid du Colombier } 30514414594SDavid du Colombier if(dp->length == 0){ 30614414594SDavid du Colombier if(time(0)-dp->mtime > 15*60){ 30714414594SDavid du Colombier syslog(0, runqlog, "empty ctl file for %s", dp->name); 30814414594SDavid du Colombier remmatch(dp->name); 30914414594SDavid du Colombier } 31014414594SDavid du Colombier return; 31114414594SDavid du Colombier } 3129a747e4fSDavid du Colombier dtime = d->mtime; 3139a747e4fSDavid du Colombier free(d); 3143e12c5d1SDavid du Colombier 3153e12c5d1SDavid du Colombier /* 3163e12c5d1SDavid du Colombier * retry times depend on the age of the errors file 3173e12c5d1SDavid du Colombier */ 3189a747e4fSDavid du Colombier if(!Eflag && (d = dirstat(file(dp->name, 'E'))) != nil){ 3199a747e4fSDavid du Colombier etime = d->mtime; 3209a747e4fSDavid du Colombier free(d); 3219a747e4fSDavid du Colombier if(etime - dtime < 60*60){ 3223e12c5d1SDavid du Colombier /* up to the first hour, try every 15 minutes */ 3239a747e4fSDavid du Colombier if(time(0) - etime < 15*60) 3243e12c5d1SDavid du Colombier return; 3253e12c5d1SDavid du Colombier } else { 3263e12c5d1SDavid du Colombier /* after the first hour, try once an hour */ 3279a747e4fSDavid du Colombier if(time(0) - etime < 60*60) 3283e12c5d1SDavid du Colombier return; 3293e12c5d1SDavid du Colombier } 3309a747e4fSDavid du Colombier 3313e12c5d1SDavid du Colombier } 3323e12c5d1SDavid du Colombier 3333e12c5d1SDavid du Colombier /* 3343e12c5d1SDavid du Colombier * open control and data 3353e12c5d1SDavid du Colombier */ 3367dd7cddfSDavid du Colombier b = sysopen(file(dp->name, 'C'), "rl", 0660); 3377dd7cddfSDavid du Colombier if(b == 0) { 3387dd7cddfSDavid du Colombier if(debug) 3397dd7cddfSDavid du Colombier fprint(2, "can't open %s: %r\n", file(dp->name, 'C')); 3403e12c5d1SDavid du Colombier return; 3417dd7cddfSDavid du Colombier } 3423e12c5d1SDavid du Colombier dfd = open(file(dp->name, 'D'), OREAD); 3433e12c5d1SDavid du Colombier if(dfd < 0){ 3447dd7cddfSDavid du Colombier if(debug) 3457dd7cddfSDavid du Colombier fprint(2, "can't open %s: %r\n", file(dp->name, 'D')); 3467dd7cddfSDavid du Colombier Bterm(b); 3477dd7cddfSDavid du Colombier sysunlockfile(Bfildes(b)); 3483e12c5d1SDavid du Colombier return; 3493e12c5d1SDavid du Colombier } 3503e12c5d1SDavid du Colombier 3513e12c5d1SDavid du Colombier /* 3523e12c5d1SDavid du Colombier * make arg list 3533e12c5d1SDavid du Colombier * - read args into (malloc'd) buffer 3543e12c5d1SDavid du Colombier * - malloc a vector and copy pointers to args into it 3553e12c5d1SDavid du Colombier */ 3563e12c5d1SDavid du Colombier buf = malloc(dp->length+1); 3577dd7cddfSDavid du Colombier if(buf == 0){ 3587dd7cddfSDavid du Colombier warning("buffer allocation", 0); 3597dd7cddfSDavid du Colombier Bterm(b); 3607dd7cddfSDavid du Colombier sysunlockfile(Bfildes(b)); 3617dd7cddfSDavid du Colombier close(dfd); 3627dd7cddfSDavid du Colombier return; 3637dd7cddfSDavid du Colombier } 3647dd7cddfSDavid du Colombier if(Bread(b, buf, dp->length) != dp->length){ 3653e12c5d1SDavid du Colombier warning("reading control file %s\n", dp->name); 3667dd7cddfSDavid du Colombier Bterm(b); 3677dd7cddfSDavid du Colombier sysunlockfile(Bfildes(b)); 3687dd7cddfSDavid du Colombier close(dfd); 3697dd7cddfSDavid du Colombier free(buf); 3707dd7cddfSDavid du Colombier return; 3713e12c5d1SDavid du Colombier } 3723e12c5d1SDavid du Colombier buf[dp->length] = 0; 3737dd7cddfSDavid du Colombier av = malloc(2*sizeof(char*)); 3747dd7cddfSDavid du Colombier if(av == 0){ 3757dd7cddfSDavid du Colombier warning("argv allocation", 0); 3767dd7cddfSDavid du Colombier close(dfd); 3777dd7cddfSDavid du Colombier free(buf); 3787dd7cddfSDavid du Colombier Bterm(b); 3797dd7cddfSDavid du Colombier sysunlockfile(Bfildes(b)); 3807dd7cddfSDavid du Colombier return; 3813e12c5d1SDavid du Colombier } 3823e12c5d1SDavid du Colombier for(ac = 1, cp = buf; *cp; ac++){ 3833e12c5d1SDavid du Colombier while(isspace(*cp)) 3843e12c5d1SDavid du Colombier *cp++ = 0; 3857dd7cddfSDavid du Colombier if(*cp == 0) 3867dd7cddfSDavid du Colombier break; 3877dd7cddfSDavid du Colombier 3887dd7cddfSDavid du Colombier av = realloc(av, (ac+2)*sizeof(char*)); 3897dd7cddfSDavid du Colombier if(av == 0){ 3907dd7cddfSDavid du Colombier warning("argv allocation", 0); 3917dd7cddfSDavid du Colombier close(dfd); 3927dd7cddfSDavid du Colombier free(buf); 3937dd7cddfSDavid du Colombier Bterm(b); 3947dd7cddfSDavid du Colombier sysunlockfile(Bfildes(b)); 3957dd7cddfSDavid du Colombier return; 3967dd7cddfSDavid du Colombier } 3973e12c5d1SDavid du Colombier av[ac] = cp; 3987dd7cddfSDavid du Colombier while(*cp && !isspace(*cp)){ 3997dd7cddfSDavid du Colombier if(*cp++ == '"'){ 4003e12c5d1SDavid du Colombier while(*cp && *cp != '"') 4013e12c5d1SDavid du Colombier cp++; 4023e12c5d1SDavid du Colombier if(*cp) 4033e12c5d1SDavid du Colombier cp++; 4043e12c5d1SDavid du Colombier } 4053e12c5d1SDavid du Colombier } 4067dd7cddfSDavid du Colombier } 4077dd7cddfSDavid du Colombier av[0] = cmd; 4083e12c5d1SDavid du Colombier av[ac] = 0; 4093e12c5d1SDavid du Colombier 41080ee5cbfSDavid du Colombier if(!Eflag &&time(0) - dtime > giveup){ 4117dd7cddfSDavid du Colombier if(returnmail(av, dp->name, "Giveup") == 0) 412219b2ee8SDavid du Colombier remmatch(dp->name); 4137dd7cddfSDavid du Colombier else { 4147dd7cddfSDavid du Colombier if(time(0) - dtime < giveup + 2*60*60) 4157dd7cddfSDavid du Colombier logit("returnmail failed", dp->name, av); 4167dd7cddfSDavid du Colombier if(time(0) - dtime > giveup + 24*60*60) 4177dd7cddfSDavid du Colombier remmatch(dp->name); 4187dd7cddfSDavid du Colombier } 4197dd7cddfSDavid du Colombier goto done; 4207dd7cddfSDavid du Colombier } 4217dd7cddfSDavid du Colombier 4227dd7cddfSDavid du Colombier for(i = 0; i < nbad; i++){ 4237dd7cddfSDavid du Colombier if(strcmp(av[3], badsys[i]) == 0) 4247dd7cddfSDavid du Colombier goto done; 425219b2ee8SDavid du Colombier } 426219b2ee8SDavid du Colombier 4273e12c5d1SDavid du Colombier /* 4283e12c5d1SDavid du Colombier * transfer 4293e12c5d1SDavid du Colombier */ 4307dd7cddfSDavid du Colombier pid = fork(); 4317dd7cddfSDavid du Colombier switch(pid){ 4323e12c5d1SDavid du Colombier case -1: 4337dd7cddfSDavid du Colombier sysunlockfile(Bfildes(b)); 4347dd7cddfSDavid du Colombier syslog(0, runqlog, "out of procs"); 4357dd7cddfSDavid du Colombier exits(0); 4363e12c5d1SDavid du Colombier case 0: 4377dd7cddfSDavid du Colombier if(debug) { 4387dd7cddfSDavid du Colombier fprint(2, "Starting %s", cmd); 4397dd7cddfSDavid du Colombier for(ac = 0; av[ac]; ac++) 4407dd7cddfSDavid du Colombier fprint(2, " %s", av[ac]); 4417dd7cddfSDavid du Colombier fprint(2, "\n"); 4427dd7cddfSDavid du Colombier } 4437dd7cddfSDavid du Colombier logit("execing", dp->name, av); 4443e12c5d1SDavid du Colombier close(0); 4453e12c5d1SDavid du Colombier dup(dfd, 0); 4467dd7cddfSDavid du Colombier close(dfd); 4473e12c5d1SDavid du Colombier close(2); 4487dd7cddfSDavid du Colombier efd = open(file(dp->name, 'E'), OWRITE); 4493e12c5d1SDavid du Colombier if(efd < 0) 4503e12c5d1SDavid du Colombier efd = create(file(dp->name, 'E'), OWRITE, 0664); 4513e12c5d1SDavid du Colombier if(efd < 0) 4523e12c5d1SDavid du Colombier exits(""); 4533e12c5d1SDavid du Colombier seek(efd, 0, 2); 4543e12c5d1SDavid du Colombier exec(cmd, av); 4553e12c5d1SDavid du Colombier error("can't exec %s", cmd); 4563e12c5d1SDavid du Colombier break; 4573e12c5d1SDavid du Colombier default: 4589a747e4fSDavid du Colombier for(;;){ 4599a747e4fSDavid du Colombier wm = wait(); 4609a747e4fSDavid du Colombier if(wm == nil) 4619a747e4fSDavid du Colombier error("wait failed: %r", ""); 4629a747e4fSDavid du Colombier if(wm->pid == pid) 4639a747e4fSDavid du Colombier break; 4649a747e4fSDavid du Colombier free(wm); 4659a747e4fSDavid du Colombier } 4669a747e4fSDavid du Colombier 4679a747e4fSDavid du Colombier if(wm->msg[0]){ 4683e12c5d1SDavid du Colombier if(debug) 4699a747e4fSDavid du Colombier fprint(2, "[%d] wm->msg == %s\n", getpid(), wm->msg); 4709a747e4fSDavid du Colombier if(strstr(wm->msg, "Retry")==0){ 4713e12c5d1SDavid du Colombier /* return the message and remove it */ 4729a747e4fSDavid du Colombier if(returnmail(av, dp->name, wm->msg) == 0) 473219b2ee8SDavid du Colombier remmatch(dp->name); 4743e12c5d1SDavid du Colombier } else { 4757dd7cddfSDavid du Colombier /* add sys to bad list and try again later */ 4767dd7cddfSDavid du Colombier nbad++; 4777dd7cddfSDavid du Colombier badsys = realloc(badsys, nbad*sizeof(char*)); 4787dd7cddfSDavid du Colombier badsys[nbad-1] = strdup(av[3]); 4793e12c5d1SDavid du Colombier } 4803e12c5d1SDavid du Colombier } else { 4813e12c5d1SDavid du Colombier /* it worked remove the message */ 482219b2ee8SDavid du Colombier remmatch(dp->name); 4833e12c5d1SDavid du Colombier } 4849a747e4fSDavid du Colombier free(wm); 4853e12c5d1SDavid du Colombier 4863e12c5d1SDavid du Colombier } 4877dd7cddfSDavid du Colombier done: 4887dd7cddfSDavid du Colombier Bterm(b); 4897dd7cddfSDavid du Colombier sysunlockfile(Bfildes(b)); 4907dd7cddfSDavid du Colombier free(buf); 4917dd7cddfSDavid du Colombier free(av); 4923e12c5d1SDavid du Colombier close(dfd); 4933e12c5d1SDavid du Colombier } 4943e12c5d1SDavid du Colombier 4957dd7cddfSDavid du Colombier 4963e12c5d1SDavid du Colombier /* 4973e12c5d1SDavid du Colombier * return a name starting with the given character 4983e12c5d1SDavid du Colombier */ 4993e12c5d1SDavid du Colombier char* 5003e12c5d1SDavid du Colombier file(char *name, char type) 5013e12c5d1SDavid du Colombier { 5029a747e4fSDavid du Colombier static char nname[Elemlen+1]; 5033e12c5d1SDavid du Colombier 5049a747e4fSDavid du Colombier strncpy(nname, name, Elemlen); 5059a747e4fSDavid du Colombier nname[Elemlen] = 0; 5063e12c5d1SDavid du Colombier nname[0] = type; 5073e12c5d1SDavid du Colombier return nname; 5083e12c5d1SDavid du Colombier } 5093e12c5d1SDavid du Colombier 5103e12c5d1SDavid du Colombier /* 5113e12c5d1SDavid du Colombier * send back the mail with an error message 5123e12c5d1SDavid du Colombier * 5133e12c5d1SDavid du Colombier * return 0 if successful 5143e12c5d1SDavid du Colombier */ 5153e12c5d1SDavid du Colombier int 5163e12c5d1SDavid du Colombier returnmail(char **av, char *name, char *msg) 5173e12c5d1SDavid du Colombier { 5183e12c5d1SDavid du Colombier int pfd[2]; 5199a747e4fSDavid du Colombier Waitmsg *wm; 5203e12c5d1SDavid du Colombier int fd; 5213e12c5d1SDavid du Colombier char buf[256]; 5223e12c5d1SDavid du Colombier int i; 5233e12c5d1SDavid du Colombier long n; 5247dd7cddfSDavid du Colombier String *s; 5257dd7cddfSDavid du Colombier char *sender; 5263e12c5d1SDavid du Colombier 5277dd7cddfSDavid du Colombier if(av[1] == 0 || av[2] == 0){ 5287dd7cddfSDavid du Colombier logit("runq - dumping bad file", name, av); 5297dd7cddfSDavid du Colombier return 0; 5307dd7cddfSDavid du Colombier } 5317dd7cddfSDavid du Colombier 5327dd7cddfSDavid du Colombier s = unescapespecial(s_copy(av[2])); 5337dd7cddfSDavid du Colombier sender = s_to_c(s); 5347dd7cddfSDavid du Colombier 5357dd7cddfSDavid du Colombier if(!returnable(sender) || strcmp(sender, "postmaster") == 0) { 5367dd7cddfSDavid du Colombier logit("runq - dumping p to p mail", name, av); 5377dd7cddfSDavid du Colombier return 0; 5387dd7cddfSDavid du Colombier } 5393e12c5d1SDavid du Colombier 5403e12c5d1SDavid du Colombier if(pipe(pfd) < 0) 5413e12c5d1SDavid du Colombier return -1; 5423e12c5d1SDavid du Colombier 5437dd7cddfSDavid du Colombier switch(rfork(RFFDG|RFPROC|RFENVG)){ 5443e12c5d1SDavid du Colombier case -1: 5453e12c5d1SDavid du Colombier return -1; 5463e12c5d1SDavid du Colombier case 0: 5477dd7cddfSDavid du Colombier logit("returning", name, av); 5483e12c5d1SDavid du Colombier close(pfd[1]); 5493e12c5d1SDavid du Colombier close(0); 5503e12c5d1SDavid du Colombier dup(pfd[0], 0); 5513e12c5d1SDavid du Colombier close(pfd[0]); 5527dd7cddfSDavid du Colombier putenv("upasname", "/dev/null"); 5537dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/send", UPASBIN); 5547dd7cddfSDavid du Colombier execl(buf, "send", "-r", sender, 0); 5553e12c5d1SDavid du Colombier error("can't exec", 0); 5563e12c5d1SDavid du Colombier break; 5573e12c5d1SDavid du Colombier default: 5583e12c5d1SDavid du Colombier break; 5593e12c5d1SDavid du Colombier } 5603e12c5d1SDavid du Colombier 5613e12c5d1SDavid du Colombier close(pfd[0]); 562*3ff48bf5SDavid du Colombier fprint(pfd[1], "\n"); /* get out of headers */ 5633e12c5d1SDavid du Colombier if(av[1]){ 5647dd7cddfSDavid du Colombier fprint(pfd[1], "Your request ``%.20s ", av[1]); 5653e12c5d1SDavid du Colombier for(n = 3; av[n]; n++) 5663e12c5d1SDavid du Colombier fprint(pfd[1], "%s ", av[n]); 5673e12c5d1SDavid du Colombier } 5683e12c5d1SDavid du Colombier fprint(pfd[1], "'' failed (code %s).\nThe symptom was:\n\n", msg); 5693e12c5d1SDavid du Colombier fd = open(file(name, 'E'), OREAD); 5703e12c5d1SDavid du Colombier if(fd >= 0){ 5713e12c5d1SDavid du Colombier for(;;){ 5723e12c5d1SDavid du Colombier n = read(fd, buf, sizeof(buf)); 5733e12c5d1SDavid du Colombier if(n <= 0) 5743e12c5d1SDavid du Colombier break; 5753e12c5d1SDavid du Colombier if(write(pfd[1], buf, n) != n){ 5763e12c5d1SDavid du Colombier close(fd); 5773e12c5d1SDavid du Colombier goto out; 5783e12c5d1SDavid du Colombier } 5793e12c5d1SDavid du Colombier } 5803e12c5d1SDavid du Colombier close(fd); 5813e12c5d1SDavid du Colombier } 5823e12c5d1SDavid du Colombier fprint(pfd[1], "\nThe request began:\n\n"); 5833e12c5d1SDavid du Colombier fd = open(file(name, 'D'), OREAD); 5843e12c5d1SDavid du Colombier if(fd >= 0){ 5853e12c5d1SDavid du Colombier for(i=0; i<4*16; i++){ 5863e12c5d1SDavid du Colombier n = read(fd, buf, sizeof(buf)); 5873e12c5d1SDavid du Colombier if(n <= 0) 5883e12c5d1SDavid du Colombier break; 5893e12c5d1SDavid du Colombier if(write(pfd[1], buf, n) != n){ 5903e12c5d1SDavid du Colombier close(fd); 5913e12c5d1SDavid du Colombier goto out; 5923e12c5d1SDavid du Colombier } 5933e12c5d1SDavid du Colombier } 5943e12c5d1SDavid du Colombier close(fd); 5953e12c5d1SDavid du Colombier } 5963e12c5d1SDavid du Colombier close(pfd[1]); 5973e12c5d1SDavid du Colombier out: 5989a747e4fSDavid du Colombier wm = wait(); 5999a747e4fSDavid du Colombier if(wm == nil) 6009a747e4fSDavid du Colombier return -1; 6019a747e4fSDavid du Colombier i = wm->msg[0] ? -1 : 0; 6029a747e4fSDavid du Colombier free(wm); 6039a747e4fSDavid du Colombier return i; 6043e12c5d1SDavid du Colombier } 6053e12c5d1SDavid du Colombier 6063e12c5d1SDavid du Colombier /* 6073e12c5d1SDavid du Colombier * print a warning and continue 6083e12c5d1SDavid du Colombier */ 6093e12c5d1SDavid du Colombier void 6103e12c5d1SDavid du Colombier warning(char *f, void *a) 6113e12c5d1SDavid du Colombier { 6123e12c5d1SDavid du Colombier char err[65]; 6133e12c5d1SDavid du Colombier char buf[256]; 6143e12c5d1SDavid du Colombier 6159a747e4fSDavid du Colombier rerrstr(err, sizeof(err)); 6167dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), f, a); 6173e12c5d1SDavid du Colombier fprint(2, "runq: %s: %s\n", buf, err); 6183e12c5d1SDavid du Colombier } 6193e12c5d1SDavid du Colombier 6203e12c5d1SDavid du Colombier /* 6213e12c5d1SDavid du Colombier * print an error and die 6223e12c5d1SDavid du Colombier */ 6233e12c5d1SDavid du Colombier void 6243e12c5d1SDavid du Colombier error(char *f, void *a) 6253e12c5d1SDavid du Colombier { 6269a747e4fSDavid du Colombier char err[Errlen]; 6273e12c5d1SDavid du Colombier char buf[256]; 6283e12c5d1SDavid du Colombier 6299a747e4fSDavid du Colombier rerrstr(err, sizeof(err)); 6307dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), f, a); 6313e12c5d1SDavid du Colombier fprint(2, "runq: %s: %s\n", buf, err); 6323e12c5d1SDavid du Colombier exits(buf); 6333e12c5d1SDavid du Colombier } 6343e12c5d1SDavid du Colombier 6357dd7cddfSDavid du Colombier void 6367dd7cddfSDavid du Colombier logit(char *msg, char *file, char **av) 6377dd7cddfSDavid du Colombier { 6387dd7cddfSDavid du Colombier int n, m; 6397dd7cddfSDavid du Colombier char buf[256]; 6407dd7cddfSDavid du Colombier 6417dd7cddfSDavid du Colombier n = snprint(buf, sizeof(buf), "%s/%s: %s", curdir, file, msg); 6427dd7cddfSDavid du Colombier for(; *av; av++){ 6437dd7cddfSDavid du Colombier m = strlen(*av); 6447dd7cddfSDavid du Colombier if(n + m + 4 > sizeof(buf)) 6457dd7cddfSDavid du Colombier break; 6467dd7cddfSDavid du Colombier sprint(buf + n, " '%s'", *av); 6477dd7cddfSDavid du Colombier n += m + 3; 6487dd7cddfSDavid du Colombier } 6499a747e4fSDavid du Colombier syslog(0, runqlog, "%s", buf); 6507dd7cddfSDavid du Colombier } 6517dd7cddfSDavid du Colombier 6527dd7cddfSDavid du Colombier char *loadfile = ".runqload"; 6537dd7cddfSDavid du Colombier 6547dd7cddfSDavid du Colombier /* 6557dd7cddfSDavid du Colombier * load balancing 6567dd7cddfSDavid du Colombier */ 6577dd7cddfSDavid du Colombier void 6587dd7cddfSDavid du Colombier doload(int start) 6597dd7cddfSDavid du Colombier { 6607dd7cddfSDavid du Colombier int fd; 6617dd7cddfSDavid du Colombier char buf[32]; 6627dd7cddfSDavid du Colombier int i, n; 6637dd7cddfSDavid du Colombier Mlock *l; 6649a747e4fSDavid du Colombier Dir *d; 6657dd7cddfSDavid du Colombier 6667dd7cddfSDavid du Colombier if(load <= 0) 6677dd7cddfSDavid du Colombier return; 6687dd7cddfSDavid du Colombier 6697dd7cddfSDavid du Colombier if(chdir(root) < 0){ 6707dd7cddfSDavid du Colombier load = 0; 6717dd7cddfSDavid du Colombier return; 6727dd7cddfSDavid du Colombier } 6737dd7cddfSDavid du Colombier 6747dd7cddfSDavid du Colombier l = syslock(loadfile); 6757dd7cddfSDavid du Colombier fd = open(loadfile, ORDWR); 6767dd7cddfSDavid du Colombier if(fd < 0){ 6777dd7cddfSDavid du Colombier fd = create(loadfile, 0666, ORDWR); 6787dd7cddfSDavid du Colombier if(fd < 0){ 6797dd7cddfSDavid du Colombier load = 0; 6807dd7cddfSDavid du Colombier sysunlock(l); 6817dd7cddfSDavid du Colombier return; 6827dd7cddfSDavid du Colombier } 6837dd7cddfSDavid du Colombier } 6847dd7cddfSDavid du Colombier 6857dd7cddfSDavid du Colombier /* get current load */ 6867dd7cddfSDavid du Colombier i = 0; 6877dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf)-1); 6887dd7cddfSDavid du Colombier if(n >= 0){ 6897dd7cddfSDavid du Colombier buf[n] = 0; 6907dd7cddfSDavid du Colombier i = atoi(buf); 6917dd7cddfSDavid du Colombier } 6927dd7cddfSDavid du Colombier if(i < 0) 6937dd7cddfSDavid du Colombier i = 0; 6947dd7cddfSDavid du Colombier 6957dd7cddfSDavid du Colombier /* ignore load if file hasn't been changed in 30 minutes */ 6969a747e4fSDavid du Colombier d = dirfstat(fd); 6979a747e4fSDavid du Colombier if(d != nil){ 6989a747e4fSDavid du Colombier if(d->mtime + 30*60 < time(0)) 6997dd7cddfSDavid du Colombier i = 0; 7009a747e4fSDavid du Colombier free(d); 7019a747e4fSDavid du Colombier } 7027dd7cddfSDavid du Colombier 7037dd7cddfSDavid du Colombier /* if load already too high, give up */ 7047dd7cddfSDavid du Colombier if(start && i >= load){ 7057dd7cddfSDavid du Colombier sysunlock(l); 7067dd7cddfSDavid du Colombier exits(0); 7077dd7cddfSDavid du Colombier } 7087dd7cddfSDavid du Colombier 7097dd7cddfSDavid du Colombier /* increment/decrement load */ 7107dd7cddfSDavid du Colombier if(start) 7117dd7cddfSDavid du Colombier i++; 7127dd7cddfSDavid du Colombier else 7137dd7cddfSDavid du Colombier i--; 7147dd7cddfSDavid du Colombier seek(fd, 0, 0); 7157dd7cddfSDavid du Colombier fprint(fd, "%d\n", i); 7167dd7cddfSDavid du Colombier sysunlock(l); 7177dd7cddfSDavid du Colombier close(fd); 7187dd7cddfSDavid du Colombier } 719