Annotation of 3BSD/cmd/net/netdaemon.c, revision 1.1.1.1

1.1       root        1: /*
                      2:        The daemon program that runs the network.
                      3: 
                      4:        netdaemon mach readfd writefd
                      5: 
                      6:        Must be started by root.
                      7: */
                      8: 
                      9: # include "defs.h"
                     10: 
                     11: /* global variables */
                     12: extern char **environ;
                     13: short masterseqno, lastseqno;
                     14: struct dumpstruc dump;
                     15: struct bstruct btable[];
                     16: int onlyuid;
                     17: 
                     18: /* local variables */
                     19: static long length;
                     20: static char nsendfail;
                     21: static FILE *dir;
                     22: static char header[] =                 "ABCDE";
                     23: static char tempfile[]=        TEMPFILE;
                     24: static char publogfile[]=      PUBLOGFILE;
                     25: static char dumpfile[]=        DUMPFILE;
                     26: static char namefile[]=        NAMEFILE;
                     27: static struct stat statbuf;
                     28: static struct direct dirbuf;
                     29: int handlekill();
                     30: static char frommach;
                     31: static char buf[BUFSIZ];
                     32: /* addrfrom is the person who sent this to us,
                     33:    addrto is the person who received the command, i.e.
                     34:    addrto is on this machine */
                     35: static char addrto[BUFSIZ], addrfrom[BUFSIZ];
                     36: 
                     37: main(argc,argv)
                     38:   char **argv; {
                     39:        register int i;
                     40:        long ltime,t;
                     41: 
                     42:        signal(SIGTRM,handlekill);
                     43:        debugflg = DBV;
                     44:        setupdaemon(argc,argv);
                     45:        /* now running alone as a daemon */
                     46:                /*
                     47:                for(i=0; i<15; i++)close(i);
                     48:                signal(SIGHUP,SIG_IGN);
                     49:                signal(SIGQUIT,SIG_IGN);
                     50:                signal(SIGINT,SIG_IGN);
                     51:                */
                     52:        senddir[strlen(senddir)-1] = remote;            /* choose dir */
                     53:        if(chdir(senddir) < 0){
                     54:                perror(senddir);
                     55:                exit(1);
                     56:                }
                     57:        dir = fopen(senddir,"r");
                     58:        if(dir == NULL){
                     59:                perror(senddir);
                     60:                exit(1);
                     61:                }
                     62:        mktemp(tempfile);
                     63:        tempfile[strlen(tempfile) - 7] = remote;
                     64:        ltime = gettime();
                     65:        sprintf(buf,"net restarted to %s %d %s",longname(remote),
                     66:                getpid(),ctime(&ltime));
                     67:        dump.longtime = dump.shorttime = ltime;
                     68:        addtolog(remote,buf);
                     69:        addtodump(remote,buf);
                     70:        addtopublic(buf);
                     71:        fprintf(stderr,buf);
                     72:        if(!debugflg)fclose(stderr);
                     73:        sendpurge();
                     74:        nsendfail = 0;
                     75:        for(;;){        /* begin reading file */
                     76:                debug("daemon %c %d\nreceive",remote,getpid());
                     77:                i = getreset();
                     78:                dump.waittime = 0L;
                     79:                if(i == BROKENREAD){
                     80:                        if(nsendfail < NSEND) netsend();
                     81:                        else nsendfail++;
                     82:                        }
                     83:                else {
                     84:                        i = netrcv();
                     85:                        if(i >= 0){
                     86:                                nsendfail = 0;  /* it sent, it is up */
                     87:                                dump.waittot += dump.waittime;
                     88:                                }
                     89:                        if(i == -1)dump.nabnormal++;
                     90:                        }
                     91:                t = gettime();
                     92:                if(t - dump.shorttime > SAMPL)pload(t);
                     93:                if(t - dump.longtime > BIGSAMPL)dumpit(t);
                     94:                dump.nloop++;
                     95:                /* count up to NSEND, sending, then wait NSEND */
                     96:                if(nsendfail >= NSEND*2)nsendfail = 0;  
                     97:                }
                     98:        }
                     99: netsend(){
                    100:        static long lasttime = 0;
                    101:        static char nleft = 1;
                    102:        long lFileLen,diff;
                    103:        double drate;
                    104:        int uid,uidBest;
                    105:        char *sdate,*sn,*swait;
                    106:        long ot,nt,filesize;
                    107:        register int i;
                    108:        char stemp[20];
                    109:        static char jname[FNS];
                    110: 
                    111:        debug("ck send");
                    112:        if(stat(senddir,&statbuf) < 0){
                    113:                error("%s %s",senddir,sys_errlist[errno]);
                    114:                return;
                    115:                }
                    116:        if(statbuf.st_mtime == lasttime && nleft == 0)return;   /* no need to search */
                    117:        lasttime = statbuf.st_mtime;
                    118:        fseek(dir,0L,0);
                    119:        lFileLen = 10000000L;
                    120:        nleft = 0;
                    121:        while(fread(&dirbuf,1,sizeof dirbuf,dir) == sizeof dirbuf){
                    122:                if(dirbuf.d_ino == 0
                    123:                   || dirbuf.d_name[0] != 'c'
                    124:                   || dirbuf.d_name[1] != 'f'
                    125:                   || dirbuf.d_name[2] != remote
                    126:                   || stat(dirbuf.d_name,&statbuf) < 0
                    127:                   || statbuf.st_mode == 0)
                    128:                        continue;
                    129:                dirbuf.d_name[0] = 'd';
                    130:                if(stat(dirbuf.d_name,&statbuf) < 0 || statbuf.st_mode == 0)
                    131:                        continue;
                    132:                uid = guid(statbuf.st_uid,statbuf.st_gid);
                    133:                if(onlyuid != 0 && uid != onlyuid && uid != SUPERUSER)continue;
                    134:                nleft++;
                    135:                filesize = getsize(&statbuf);
                    136:                if(lFileLen > filesize){
                    137:                        lFileLen = filesize;
                    138:                        for(i=0; i<DIRSIZ; i++)
                    139:                                jname[i] = dirbuf.d_name[i];
                    140:                        uidBest = uid;
                    141:                }
                    142:        }
                    143:        if(lFileLen == 10000000L)return;
                    144:        strcpy(stemp,jname);
                    145:        stemp[0] = 'c';
                    146:        sn = SnFromUid(uidBest);
                    147:        if(sn == NULL){
                    148:                addtolog(remote,"Unknown userid %d\n",uidBest);
                    149:                return;
                    150:        }
                    151:        addtolog(remote,"^S %s %c: %s ",sn,remote,jname+2);
                    152:        ot = gettime();
                    153:        dump.waittime = 0L;
                    154:        if(send(jname) == 0)return;
                    155:        nt = gettime();
                    156:        dump.waittot += dump.waittime;
                    157:        filesize = getsize(&statbuf);
                    158:        unlink(jname);
                    159:        unlink(stemp);
                    160:        diff = nt - ot;
                    161:        if(diff < 1)diff = 1;           /* avoid dividing by zero */
                    162:        sdate = ctime(&nt)+4;
                    163:        sdate[strlen(sdate) -9] = 0;
                    164:        drate = (double)filesize / (double)diff;
                    165:        swait = comptime(ot - statbuf.st_mtime);
                    166:        jname[3] = jname[2];
                    167:        addtolog(remote,"^T%c(%s, %ldb, %ldsec, %4.1fb/sec, w %s)\n",
                    168:                remote,sdate,filesize, diff,drate, swait);
                    169:        addtopublic("%s: sent %-8s to %c (%s, %ld b, wait %s)\n",
                    170:                sdate,sn,remote,jname+3,filesize,swait);
                    171:        dump.nsend++;
                    172:        dump.bytetot += filesize;
                    173:        dump.elaptot += diff;
                    174:        /* add this users name to /usr/net/usernames */
                    175:        addtoname(sn);
                    176:        }
                    177: send(jname)
                    178:        char *jname;
                    179: {      /* push those bytes */
                    180:        /* returns 0 if send fails, 1 otherwise */
                    181:        register int n;
                    182:        int i;
                    183:        long lsize;
                    184:        char mbuf[BUFSIZ];
                    185:        register char *p;
                    186:        FILE *jfile;
                    187: 
                    188:        debug("send %s",jname);
                    189:        if(stat(jname,&statbuf) < 0)goto sfail;
                    190:        lsize = getsize(&statbuf);
                    191:        if(lsize < MINSIZE){            /* all files are at least this long */
                    192:                unlink(jname);
                    193:                jname[0] = 'c';
                    194:                unlink(jname);
                    195:                return(1);
                    196:                }
                    197:        jfile = fopen(jname,"r");
                    198:        if(jfile == NULL)goto sfail;
                    199:        strcpy(mbuf,header);
                    200:        i = strlen(header);
                    201:        p = (char *)&lsize;
                    202:        lsize = fixuplong(lsize);
                    203:        mbuf[i] = *p++;
                    204:        mbuf[i+1] = *p++;
                    205:        mbuf[i+2] = *p++;
                    206:        mbuf[i+3] = *p++;
                    207:        i = i + 4;
                    208:        sendreset();
                    209:        masterseqno = 1;
                    210:        lastseqno = 0;
                    211:        if(xwrite(mbuf,1,i) == WRITEFAIL)goto bwrite;
                    212:        while((n=fread(buf,1,BLOCKSIZE,jfile)) > 0)
                    213:                if(xwrite(buf,1,n) == WRITEFAIL)goto bwrite;
                    214:        fclose(jfile);
                    215:        debug("end send");
                    216:        nsendfail = 0;
                    217:        return(1);
                    218: bwrite:
                    219:        nsendfail++;
                    220:        dump.nsendfail++;
                    221:        fclose(jfile);
                    222:        addtolog(remote,"^F%c\n",remote);
                    223:        return(0);
                    224: sfail:
                    225:        error("%s: %s",jname,sys_errlist[errno]);
                    226:        dump.nsendfail++;
                    227:        return(0);
                    228:        }
                    229: netrcv(){
                    230:        /* returns -2 in normal fail, -1 in abnormal fail, >= 0 otherwise */
                    231:        char code, sin;
                    232:        char tmach, fmach;
                    233:        char mgetc(), cflag, *s;
                    234:        register int n,i;
                    235:        char vmajor, vminor, c;
                    236:        int rcode, dummy, pid, uid;
                    237:        char buf1[BUFSIZ], cmdstr[BUFSIZ];
                    238:        static char parmlist[PARMLIST];
                    239:        long timesent,otime,olength,diff,rcvfinish,nt,maxfile = MAXFILE;
                    240:        double r;
                    241:        static char resp[FNS], infile[FNS], outfile[FNS];
                    242:        static char hbuf[10];
                    243:        static FILE *temp;
                    244: 
                    245:        n = nread(hbuf,1,strlen(header));
                    246:        if(n == BROKENREAD)return(-2);
                    247:        if(n != strlen(header) || strcmp(header,hbuf) != 0){
                    248:                error("wrong head %d %s",n,hbuf);
                    249:                return(-1);
                    250:                }
                    251:        n = nread(&length,1,4);
                    252:        if(n == BROKENREAD)return(-2);
                    253:        if(n != 4){
                    254:                error("bad length nread %d",n);
                    255:                return(-1);
                    256:                }
                    257:        length = fixuplong(length);
                    258:        olength = length;
                    259:        otime = gettime();
                    260:        debug("length = %ld\n",length);
                    261:        i = 0;
                    262: 
                    263: /* 
                    264:        begin parsing header
                    265: 
                    266:        from local to remote (requests)
                    267:        code    net option      reason
                    268:        q                       normal request
                    269:        y       -y              simply skips login check (used by netlpr)
                    270: 
                    271:        from remote to local
                    272:        code    net option      reason
                    273:        w       -w              message to be written/mailed back
                    274:        s       -z              normal response
                    275: */
                    276: 
                    277:        code = mgetc();
                    278:        tmach = mgetc();
                    279:        if(tmach < 'a' || 'z' < tmach){
                    280:                error("bad tmach");
                    281:                return(-1);
                    282:                }
                    283:        if(tmach != local)goto forw;    /* being forwarded through us */
                    284:        fmach = mgetc();
                    285:        vmajor = mgetc();
                    286:        vminor = mgetc();
                    287:        i += mgets(status.login,NS);
                    288:        i += mgets(status.mpasswd,20);
                    289:        demask(status.mpasswd);
                    290:        i += mgets(infile,FNS);
                    291:        i += mgets(outfile,FNS);
                    292:        i += mgets(resp,FNS);
                    293:        i += mgets(status.localname,NS);
                    294: 
                    295:        /* addrfrom is the person who sent this to us,
                    296:           addrto is the person who received the command, i.e.
                    297:           addrto is on this machine */
                    298:        if(status.localname[0] == 0)strcpy(status.localname,"root");
                    299:        sprintf(addrfrom,  "%s:%s",longname(fmach),status.localname);
                    300:        sprintf(addrto,    "%s:%s",longname(tmach),status.login);
                    301: 
                    302:        i += mgets(status.sTtyname,20);
                    303:        if(status.sTtyname[0] == 0)strcpy(status.sTtyname,"/dev/ttyx");
                    304:        cflag = mgetc();
                    305:        if(!fmach || !code || !cflag || !vmajor || !vminor){
                    306:                error("mgetc fails");
                    307:                return(-1);
                    308:                }
                    309:        cflag -= 'a';
                    310:        vmajor -= 'a';
                    311:        vminor -= 'a';
                    312:        if(vmajor != VMAJOR || vminor != VMINOR){
                    313:                /*
                    314:                error("versions dont agree (%d,%d) vs. (%d,%d) remote",
                    315:                        VMAJOR,VMINOR,vmajor,vminor);
                    316:                return(-1);
                    317:                */
                    318:                }
                    319:        i += mgets(buf,BUFSIZ);
                    320:        status.lTtytime = 0;
                    321:        sscanf(buf,"%lo",&status.lTtytime);
                    322: 
                    323:        i += mgets(parmlist,PARMLIST);
                    324:        status.jobno = atoi(parmlist);
                    325:        /* keep variable parameter list in jobno slot */
                    326:        parseparmlist(parmlist);
                    327: 
                    328:        i += mgets(buf1,BUFSIZ);                /* time sent */
                    329:        sscanf(buf1,"%ld",&timesent);
                    330:        i += mgetcmd(status.sCmdAct);
                    331:        i += mgetcmd(status.sCmdVirt);
                    332:        if(i != 0){error("mgets fails"); return(-1);}
                    333:        if(status.sCmdVirt[0] == 0)strcpy(status.sCmdVirt,status.sCmdAct);
                    334:        s = status.sCmdVirt;
                    335:        while(*s && *s != ' ')s++;
                    336:        c = *s;
                    337:        *s = 0;
                    338:        if(strcmp(status.sCmdVirt,"netlpr") == 0)dump.nnetlpr++;
                    339:        else if(strcmp(status.sCmdVirt,"netmail") == 0)dump.nnetmail++;
                    340:        else if(strcmp(status.sCmdVirt,"mail") == 0)dump.nsmail++;
                    341:        else if(strcmp(status.sCmdVirt,"netcp") == 0)dump.nnetcp++;
                    342:        else if(strcmp(status.sCmdVirt,"response") == 0)dump.nresp++;
                    343:        else dump.nnet++;
                    344:        *s = c;
                    345:        debug("%c %c %c (%c,%c) %s %s %s %s (%s) %s %c %lo %d %s\n",
                    346:                code,tmach,fmach,vmajor+'a',vminor+'a',status.login,
                    347:                infile,outfile,resp,status.localname,
                    348:                status.sTtyname,cflag+'a',status.lTtytime,status.jobno,status.sCmdAct);
                    349: 
                    350: 
                    351:        /* any chars left are data */
                    352: forw:
                    353:        sin = 0;
                    354:        if(length > 0){ /* make a temp input file */
                    355:                increment(tempfile);
                    356:                temp = fopen(tempfile,"w");
                    357:                if(temp == NULL){
                    358:                        error("%s %s",tempfile,sys_errlist[errno]);
                    359:                        return(-1);
                    360:                        }
                    361:                chmod(tempfile,0600);
                    362:                if(tmach != local)fprintf(temp,"%c :%c :",code,tmach);
                    363:                while((n = mread(buf,1,BLOCKSIZE)) > 0)
                    364:                        if(fwrite(buf,1,n,temp) != n){
                    365:                                error("%s %s",tempfile,sys_errlist[errno]);
                    366:                                fclose(temp);
                    367:                                unlink(tempfile);
                    368:                                return(-1);
                    369:                                };
                    370:                fclose(temp);
                    371:                if(n == BROKENREAD || length > 0){
                    372:                        unlink(tempfile);
                    373:                        return(-2);
                    374:                        }
                    375:                sin = 1;
                    376:                if(tmach != local){
                    377:                        diff = gettime() - otime;
                    378:                        if(diff < 1)diff = 1;   /* avoid dividing by 0 */
                    379:                        r = olength;
                    380:                        r = r/diff;
                    381:                        addtolog(remote,"^P(to %c, %ldb, %ldsec, %4.1fb/sec)\n",
                    382:                                tmach,olength,diff,r);
                    383:                        dump.npass++;
                    384:                        dump.bytetot += olength;
                    385:                        dump.elaptot += diff;
                    386:                        while((pid = fork()) == -1)sleep(2);
                    387:                        if(pid == 0){
                    388:                                execl(netcmd,"net","-x","-m",longname(tmach),
                    389:                                        "-s",tempfile,buf,0);
                    390:                                exit(1);
                    391:                                }
                    392:                        wait(&dummy);
                    393:                        unlink(tempfile);
                    394:                        return(1);
                    395:                        }
                    396:                }
                    397:        if(length > 0){error("file too short"); return(-1); }
                    398:        rcvfinish = gettime();
                    399: 
                    400:        while((pid = fork()) == -1)sleep(2);
                    401:        if(pid > 0){
                    402:                wait(&dummy);
                    403:                return(1);      /* normal return */
                    404:        }
                    405: 
                    406:        while((pid = fork()) == -1)sleep(2);
                    407:        if(pid != 0)exit(0);
                    408: 
                    409:        /* child process which forks and waits */
                    410:        mktemp(resfile);
                    411:        while((pid = fork()) == -1)sleep(2);
                    412:        if(pid == 0){
                    413:                /* child */
                    414:                strcpy(status.loginshell,Bsh);
                    415:                frommach = fmach;
                    416:                n = check(status.login,status.mpasswd,(code == 'q'));
                    417:                if(!n)errormsg(fmach,"Bad remote login/password '%s'",status.login);
                    418:                temp = fopen(resfile,"w");
                    419:                if(temp == NULL)
                    420:                        errormsg(fmach,"creat %s %s",resfile,sys_errlist[errno]);
                    421:                chmod(resfile,0600);
                    422:                fclose(temp);
                    423:                mchown(resfile,status.muid,status.mgid);
                    424:                if(sin)
                    425:                        mchown(tempfile,status.muid,status.mgid);
                    426:                setuid(status.muid);
                    427:                setgid(status.mgid);
                    428:                uid = getuid();
                    429:                uid = uidmask(uid);
                    430:                status.muid = uidmask(status.muid);
                    431:                if(uid != status.muid)error("setuid fails");
                    432:                debug("uid: %o\n",uid);
                    433:                /* check for allowed root commands, for security reasons */
                    434:                if(uid == SUPERUSER){
                    435:                        s = status.sCmdAct;
                    436:                        while(*s && *s != ' ')s++;
                    437:                        c = *s;
                    438:                        *s = 0;
                    439:                        /* these are the only commands root may execute */
                    440:                        if(strcmp(status.sCmdAct,"cat")            != 0
                    441:                        && strcmp(status.sCmdAct,CATCMD)           != 0
                    442:                        && strcmp(status.sCmdAct,FILECAT)          != 0
                    443:                        && strcmp(status.sCmdAct,MWRITECMD)        != 0
                    444:                        && strcmp(status.sCmdAct,"/usr/lib/tq")    != 0
                    445:                        && strcmp(status.sCmdAct,"/usr/lib/rtrrm") != 0
                    446:                        && strcmp(status.sCmdAct,"lpr")            != 0)
                    447:                                errormsg(fmach,
                    448:                                        "Not allowed to execute '%s' as root",
                    449:                                        status.sCmdAct);
                    450:                        *s = c;
                    451:                        }
                    452:                if(chdir(status.dir) < 0)
                    453:                        errormsg(fmach,"chdir %s %s",status.dir,sys_errlist[errno]);
                    454:                setenv(status.dir);     /* set up v7 environment */
                    455:                if(sin)mreopen(fmach,tempfile,"r",stdin);
                    456:                else if(infile[0])mreopen(fmach,infile,"r",stdin);
                    457:                else mreopen(fmach,"/dev/null","r",stdin);
                    458:                if(code == 's' && outfile[0]){
                    459:                        if(stat(outfile,&statbuf) < 0
                    460:                           || getsize(&statbuf) != 0
                    461:                           || !(statbuf.st_mode&0600))
                    462:                                errormsg(local,"Bad result file '%s'",outfile);
                    463:                        mreopen(fmach,outfile,"w",stdout);
                    464:                        }
                    465:                else if(outfile[0]){
                    466:                        temp = fopen(outfile,"w");
                    467:                        if(temp == NULL)
                    468:                                errormsg(fmach,"fopen %s %s",outfile,sys_errlist[errno]);
                    469:                        fclose(temp);
                    470:                        mreopen(fmach,outfile,"w",stdout);
                    471:                        }
                    472:                else mreopen(fmach,resfile,"a",stdout);
                    473:                debug("exec '%s'\n",status.sCmdAct);
                    474:                if(debugflg == 0){
                    475:                        /* cheat */
                    476:                        close(2);
                    477:                        dup(1);
                    478:                        /*
                    479:                        mreopen(fmach,resfile,"a",stderr);
                    480:                        */
                    481:                        }
                    482:                for(i=3;i<15;i++)close(i);
                    483:                do {
                    484:                        mexecl(status.loginshell,"sh","-c",status.sCmdAct,0);
                    485:                        sleep(2);
                    486:                        } while(errno == ETXTBSY);
                    487:                exit(1);
                    488:                }
                    489:        /* parent */
                    490:        wait(&rcode);
                    491:        rcode >>= 8;
                    492:        /*
                    493:        fclose(stdin);
                    494:        fclose(stdout);
                    495:        fclose(stderr);
                    496:        */
                    497:        if(sin)unlink(tempfile);
                    498:        /* 
                    499:           now send something back to the sender 
                    500:           unless this was a response (file or message)
                    501:        */
                    502:        if((code == 'q' || code == 'y') && (resp[0] || !(cflag&F_NONOTIFY))){
                    503:                /* send response back if a response file
                    504:                was given or if mail/write is allowed */
                    505:                /* should give an error message for non-zero return codes */
                    506:                if(stat(resfile,&statbuf) < 0){
                    507:                        error("%s %s",resfile,sys_errlist[errno]);
                    508:                        goto next;
                    509:                        }
                    510:                /* allow larger files between the Ingres machines */
                    511:                if(machtype[local  - 'a'] == M_INGRES
                    512:                && machtype[remote - 'a'] == M_INGRES)
                    513:                        maxfile = MAXFILELARGE;
                    514:                if(getsize(&statbuf) >= maxfile){
                    515:                        errormsg(fmach,"Result file too large - not sent");
                    516:                        goto next;
                    517:                        }
                    518:                if(getsize(&statbuf) == 0){
                    519:                        /* response file specified, no output generated */
                    520:                        if(resp[0] != 0) goto next;
                    521:                        /* quiet option - no output and a rcode of 0 */
                    522:                        if(rcode == 0 && (cflag&F_QUIET))goto next;
                    523:                }
                    524:                /* use both old and new mwrite parm lists */
                    525: 
                    526:                if(resp[0])sprintf(cmdstr,"-o %s %s",resp,CATCMD);
                    527:                else sprintf(cmdstr,
                    528: "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -c \"'%s'\" -y %s -e %ld -r %d",
                    529: MWRITECMD, status.localname,status.sTtyname,status.lTtytime,tmach,status.login, status.sCmdVirt,timesent,
                    530: addrfrom, addrto, status.lTtytime, status.sCmdVirt, status.sTtyname, timesent, rcode);
                    531:                sprintf(buf,"%s -m%c -z -b -l %s -s %s -c response %s",
                    532:                        netcmd,fmach,status.localname,resfile,cmdstr);
                    533:                dummy = system(buf);            /* execute command buf */
                    534:                }
                    535: next:
                    536:        unlink(resfile);
                    537:        s = ctime(&rcvfinish);
                    538:        s += 4;
                    539:        s[strlen(s) -8] = 0;
                    540:        diff = rcvfinish - otime;
                    541:        if(diff < 1)diff = 1;           /* avoid dividing by zero */
                    542:        r = olength;
                    543:        r = r/diff;
                    544:        dump.bytetot += olength;
                    545:        dump.elaptot += diff;
                    546:        sprintf(buf,"%s rcv  %c:%-8s (%s)",
                    547:                s,fmach,status.localname,status.login);
                    548:        addtolog(remote,"%s C: %s\n",buf,status.sCmdVirt);
                    549:        addtopublic("%s R: %d C: %s\n",buf,rcode,status.sCmdVirt);
                    550:        nt = rcvfinish - timesent - TIMEBASE;
                    551:        buf[0] = 0;
                    552:        if(nt > 0L)sprintf(buf," took (%s)",comptime(nt));
                    553:        addtolog(remote,"\t\tR: %d%s %ldb %ldsec %4.1fb/sec\n",
                    554:                rcode,buf,olength,diff,r);
                    555:        exit(0);
                    556:        /*UNREACHED*/
                    557:        }
                    558: 
                    559: /* 
                    560:    check() -- verify login name and password
                    561:    snTo    = login,
                    562:    pass    = passwd,
                    563:    verify  = 1 if password must check
                    564:    Returns 1 if password is ok, 0 if not.
                    565: */
                    566: check(snTo,pass,verify)        /* 1 if OK, 0 if not */
                    567:   int verify;
                    568:   char *snTo, *pass; {
                    569:        int ver;
                    570:        char *s, *u, *nullstr = "";
                    571:        struct passwd *pwd;
                    572:        ver = (verify == 0);            /* ver is true if password verification
                    573:                                                was not requested */
                    574:        if(snTo[0] == 0)return(ver);
                    575:        if(!goodacctname(snTo))return(ver);
                    576:        pwd = getpwnam(snTo);
                    577:        if(pwd == NULL)return(ver);
                    578: # ifndef NEWPROT
                    579:        if(machtype[local-'a'] == M_CC && machtype[frommach-'a'] == M_CC)
                    580:                s = pass;
                    581:        else
                    582: # endif
                    583:        if(*pass)s = crypt(pass,pwd->pw_passwd);
                    584:        else s = nullstr;
                    585:        status.muid = guid(pwd->pw_uid,pwd->pw_gid);
                    586:        status.mgid = pwd->pw_gid;
                    587:        if(isdigit(pwd->pw_gecos[0]))status.jobno = atoi(pwd->pw_gecos);
                    588:        else status.jobno = 32767;
                    589:        strcpy(status.dir,pwd->pw_dir);
                    590:        strcpy(status.loginshell,pwd->pw_shell);
                    591:        u = status.loginshell;
                    592:        if(u[0] == 0 /* || strcmp("sh",u+strlen(u)-2) != 0 */) strcpy(u,Bsh);
                    593: 
                    594:        getpwdf(pwd);
                    595:        /* ignore network passwd */
                    596:        if(!spacct(status.login,s,status.localname,status.muid,status.mgid)
                    597:        && strcmp(pwd->pw_passwd,s) && verify)
                    598:                return(0);
                    599:        return(1);
                    600:        }
                    601: mread(b,i,n)
                    602:   register int n; {
                    603:        if(length <= 0)return(0);
                    604:        if(length < n)n = length;
                    605:        n = nread(b,i,n);
                    606:        if(n != BROKENREAD)length -= n;
                    607:        return(n);
                    608:        }
                    609: char mgetc(){                  /* returns 0 if fail */
                    610:        register char c;
                    611:        register int n;
                    612:        char buf[3];
                    613:        if((n=nread(buf,1,3)) == BROKENREAD)return(0);
                    614:        if(n != 3){error("bad read %d",n); return(0); }
                    615:        c = buf[0];
                    616:        if(buf[1] != ' ' && buf[1] != ':'){error("Bad char %c",buf[1]); return(0); }
                    617:        length -= 3;
                    618:        if(length < 0){error("length wrong2 %ld",length); return(0); }
                    619:        return(c);
                    620:        }
                    621: /* read in string over the network wire */
                    622: /* put string in s, max length is maxlen */
                    623: mgets(s,maxlen)                        /* returns 0 if ok, 1 if not */
                    624:   int maxlen;
                    625:   register char *s; {
                    626:        register char *q;
                    627:        register int n;
                    628:        char c;
                    629:        q = s;
                    630:        for(;;) {
                    631:                if((n=nread(&c,1,1)) == BROKENREAD){
                    632:                        *s = 0;
                    633:                        error("mgets %s",s);
                    634:                        return(1);
                    635:                        }
                    636:                if(n == 0)break;
                    637:                if(c == '\\'){
                    638:                        if((n=nread(&c,1,1)) == BROKENREAD){
                    639:                                *s = 0;
                    640:                                error("mgets %s",s);
                    641:                                return(1);
                    642:                                }
                    643:                        if(n == 0)break;
                    644:                        }
                    645:                if(c == ' ')break;
                    646:                if(maxlen-- > 0) *s++ = c;
                    647:                }
                    648:        *s = 0;
                    649:        if(nread(&c,1,1) == BROKENREAD){
                    650:                error("mgets %s",s);
                    651:                return(1);
                    652:                }
                    653:        length -= (s - q + 2);
                    654:        if(length < 0){error("length wrong1 %ld %s",length,q); return(-1); }
                    655:        if(maxlen < 0)
                    656:                error("mgets - string too long");
                    657:        return(0);
                    658:        }
                    659: mgetcmd(s)                     /* returns 0 if succeed, 1 otherwise */
                    660:   char *s; {
                    661:        int i,n;
                    662:        char c;
                    663:        i = 0;
                    664:        for(;;){
                    665:                if((n=nread(&c,1,1)) == BROKENREAD){
                    666:                        s[i] = 0;
                    667:                        error("mgetcmd %s",s);
                    668:                        return(1);
                    669:                        }
                    670:                if(n <= 0 || c == '\n')break;
                    671:                if(c == '\\'){
                    672:                        if(nread(&c,1,1) == BROKENREAD){
                    673:                                s[i] = 0;
                    674:                                error("mgetcmd %s",s);
                    675:                                return(1);
                    676:                                }
                    677:                        length--;
                    678:                        }
                    679:                s[i++] = c;
                    680:                length--;
                    681:                }
                    682:        s[i] = 0;
                    683:        length--;
                    684:        return(0);
                    685:        }
                    686: increment(s)
                    687:  char *s; {
                    688:        int i;
                    689:        char *p;
                    690:        i = strlen(s) - 1;
                    691:        while(s[i] == '9')i--;
                    692:        if(s[i] < '0' || s[i] > '9'){
                    693:                p = s+i+1;
                    694:                while(*p)*p++ = '0';
                    695:                return;
                    696:                }
                    697:        (s[i])++;
                    698:        i++;
                    699:        while(s[i])s[i++] = '0';
                    700:        return;
                    701:        }
                    702: pload(currt)
                    703: long currt; {
                    704:        struct tms tbf;
                    705:        static long out = 0L, ocut = 0L, ost = 0L, ocst = 0L;
                    706:        long u, s, elapt;
                    707:        double br,r,ru,rs;
                    708:        char *str,buf[BUFSIZ];
                    709:        currt = gettime();
                    710:        elapt = currt - dump.shorttime;
                    711:        times(&tbf);
                    712:        u = tbf.tms_utime-out + tbf.tms_cutime-ocut;
                    713:        s = tbf.tms_stime-ost + tbf.tms_cstime-ocst;
                    714:        dump.outime += u;
                    715:        dump.ostime += s;
                    716:        r = u + s;
                    717:        if(elapt > 0)r = (r/elapt)*100.0;
                    718:        else r = 0.0;
                    719:        /* adjust to be seconds */
                    720:        r = r/60.0;
                    721:        ru = u/60.0;
                    722:        rs = s/60.0;
                    723:        str = ctime(&currt);
                    724:        str[strlen(str) - 5] = 0;
                    725:        sprintf(buf,"%s (%s):\t%4.1fu\t%4.1fs\t%5.2f\t%s\n",
                    726:                str,longname(remote),ru,rs,r,comptime(elapt));
                    727:        addtodump(remote,"%s",buf);
                    728:        br = dump.bytetot;
                    729:        if(dump.elaptot > 0)br = br/dump.elaptot;
                    730:        else br = 0.0;
                    731:        addtodump(remote, "\tTrans.\t%.6ld bytes\t%4.1f bytes/sec\t%s",
                    732:                dump.bytetot,br,comptime(dump.elaptot));
                    733:        addtodump(remote," %s\n",comptime(dump.waittot));
                    734:        dump.shorttime = currt;
                    735:        dump.waittot = dump.elaptot = dump.bytetot = 0L;
                    736:        out = tbf.tms_utime;
                    737:        ocut = tbf.tms_cutime;
                    738:        ost = tbf.tms_stime;
                    739:        ocst = tbf.tms_cstime;
                    740:        sprintf(buf,"%s %c",NETQSTAT,remote);
                    741:        system(buf);                            /* gather stats on netq len. */
                    742:        }
                    743: /* should also gather stats on # error msgs */
                    744: dumpit(currt)
                    745:   long currt; {
                    746:        register int ntot;
                    747:        long elapt;
                    748:        double r,ru,rs;
                    749:        register struct dumpstruc *p = &dump;
                    750:        register char *tt;
                    751:        tt = ctime(&currt);
                    752:        tt[strlen(tt) - 9] = 0;
                    753:        elapt = currt - dump.longtime;
                    754:        r = dump.outime + dump.ostime;
                    755:        if(elapt > 0)r = (r/elapt) * 100.0;
                    756:        else r = 0.0;
                    757:        ru = dump.outime/60.0;
                    758:        rs = dump.ostime/60.0;
                    759:        r = r/60.0;
                    760:        dump.longtime = dump.shorttime;
                    761:        ntot = p->nnetcp + p->nnetmail + p->nsmail + p->nnetlpr
                    762:                + p->nresp + p->nnet;
                    763:        addtodump(remote,"Daily statisics\t(%s):\nSummary:\n",tt);
                    764:        addtodump(remote,"\t# sent %d\t# pass-thru %d\t# rcv %d:\t# netcp %d\n",
                    765:                p->nsend,p->npass,ntot,p->nnetcp);
                    766:        addtodump(remote,"\t# netlpr %d\t# netmail %d\t# sendmail %d\t# resp %d\n",
                    767:                p->nnetlpr,p->nnetmail,p->nsmail,p->nresp);
                    768:        addtodump(remote,"Protocol summary:\n");
                    769:        addtodump(remote,"\t# pk sent %d\t# pk rcv %d\t# b sent %ld\t# b rcv %ld\n",
                    770:                p->npacksent,p->npackrcv,p->nbytesent, p->nbytercv);
                    771:        addtodump(remote,
                    772:                "\t# send fails %d\t# retrans %d\t# abn %d\t\t# cksum errs %d\n",
                    773:                p->nsendfail,p->nretrans, p->nabnormal,p->ncksum);
                    774:        addtodump(remote,"Load:\t\t\t\t%4.1fu\t%4.1fs\t%5.2f%%\t%s\n",
                    775:                ru,rs,r,comptime(elapt));
                    776:        p->nbytesent = p->nbytercv = p->outime = p->ostime = 0L;
                    777:        p->nretrans = p->nloop = p->nabnormal = p->ncksum = 0;
                    778:        p->npacksent = p->npackrcv = p->nnetcp = p->nnetmail = 0;
                    779:        p->nsmail = p->nnetlpr = p->nnet = p->npass = 0;
                    780:        p->nsend = p->nsendfail = 0;
                    781:        }
                    782: /* returns 1 if n is ok, 0 if not */
                    783: goodacctname(n)
                    784:   char *n; {
                    785:        int i;
                    786:        i = -1;
                    787:        while(btable[++i].bname)
                    788:                if(strcmp(btable[i].bname,n) == 0 &&
                    789:                        local == btable[i].bmach)return(0);
                    790:        return(1);
                    791:        }
                    792: demask(s)
                    793:   register char *s; {
                    794: # ifdef NEWPROT
                    795:        static char buf[20];
                    796:        strcpy(s,nbsdecrypt(s,THEKEY,buf));
                    797: # else
                    798:        while(*s){
                    799:                *s &= 0177;             /* strip quote bites */
                    800:                *s++ ^= 040;            /* invert upper-lower */
                    801:                }
                    802: # endif
                    803:        }
                    804: /*VARARGS0*/
                    805: mreopen(f,a,b,c){
                    806: /* simply handles errors by giving error msg */
                    807:        if(freopen(a,b,c) == NULL)errormsg(f,"%s: %s",a,sys_errlist[errno]);
                    808:        }
                    809: /* 
                    810:        addtopub(string, args)
                    811: 
                    812:        add a message to the public logfile /usr/net/logfile.
                    813:        note that the file must be writeable by everyone
                    814:        if error messages from the netrcv subroutine
                    815:        such as chdir errors are to be noticed.
                    816: */
                    817: /*VARARGS0*/
                    818: addtopublic(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n)
                    819: char *s;
                    820: {
                    821:        static FILE *log = NULL;
                    822:        if(log == NULL){
                    823:                if(stat(publogfile,&statbuf) < 0)return;
                    824:                log = fopen(publogfile,"a");
                    825:                if(log == NULL)return;
                    826:                }
                    827:        fseek(log,0L,2);
                    828:        fprintf(log,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n);
                    829:        fflush(log);
                    830:        }
                    831: /*VARARGS0*/
                    832: addtodump(mach,str,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t,u)
                    833: char *str;
                    834: {
                    835:        static FILE *log = NULL;
                    836:        dumpfile[strlen(dumpfile)-1] = mach;
                    837:        if(log == NULL){
                    838:                if(stat(dumpfile,&statbuf) < 0)return;
                    839:                log = fopen(dumpfile,"a");
                    840:                if(log == NULL)return;
                    841:                }
                    842:        fseek(log,0L,2);
                    843:        fprintf(log,str,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t,u);
                    844:        fflush(log);
                    845:        }
                    846: /* set up a dummy environment for v7 /bin/sh */
                    847: setenv(home)
                    848:   char *home; {
                    849:        static char *env[3],benv[2][50];
                    850:        env[0] = benv[0];
                    851:        env[1] = benv[1];
                    852:        strcpy(env[0],"PATH=:/bin:/usr/bin");
                    853:        sprintf(env[1],"HOME=%s",home);
                    854:        env[2] = 0;
                    855:        environ = env;
                    856:        }
                    857: /* errormsg- sends error message to user-
                    858:    may be on local or remote machine.
                    859:    Sends to addrfrom if fmach != local,
                    860:    or to addrto if fmach=local, on the assumption
                    861:    that addrfrom is where it came from and addrto is where it
                    862:    was destined on this machine.  The only time fmach=local is
                    863:    if the result file is screwed up.
                    864: 
                    865:    Note that errormsg can be called by the netrcv subroutine
                    866:    after the setuid() call to the specific user, so the 
                    867:    user must be able to get off an error msg back to him,
                    868:    and to write in the two log files.
                    869:    Can't use -w,-x,-y,-z for the net cmd because must be root for those.
                    870: */
                    871: /*VARARGS0*/
                    872: errormsg(fmach,s,a,b,c,d,e,f,g,h)
                    873: char *s;
                    874: {
                    875:        int rcode;
                    876:        char errstr[BUFSIZ], cmdstr[BUFSIZ], rcmd[BUFSIZ];
                    877:        char toadd[FNS], fromadd[FNS], mchto, mchfrom;
                    878: 
                    879:        if(fmach < 'a' || 'z' < fmach)fmach = local;
                    880:        if(status.sTtyname[0] == 0)strcpy(status.sTtyname,"/dev/ttyx");
                    881:        /* will send to toadd, from fromadd */
                    882:        if(fmach == local || strcmp(status.sCmdVirt,"response") == 0){
                    883:                /* send to local mach, thus send to toaddr. */
                    884:                /* if this is an error during a response, send to local mach. */
                    885:                strcpy(toadd,  addrto);
                    886:                strcpy(fromadd,addrfrom);
                    887:        }
                    888:        else {          /* send to remote mach, thus send back to addrfrom*/
                    889:                strcpy(toadd,  addrfrom);
                    890:                strcpy(fromadd,addrto);
                    891:        }
                    892:        sprintf(errstr,"Error: ");
                    893:        sprintf(cmdstr,s,a,b,c,d,e,f,g,h);
                    894:        strcat(errstr,cmdstr);
                    895:        strcat(errstr,"\n");
                    896:        addtolog(remote,errstr);
                    897:        addtopublic(errstr);
                    898: 
                    899:        mchto =   MchSFromAddr(status.localname,toadd);
                    900:        mchfrom = MchSFromAddr(status.login,    fromadd);
                    901: 
                    902:        sprintf(rcmd,
                    903: "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -y %s -c \"'%s'\" -e %ld",
                    904:        MWRITECMD, 
                    905:        status.localname, status.sTtyname, status.lTtytime, local, status.login,status.sCmdVirt, gettime(),
                    906:        toadd, fromadd, status.lTtytime, status.sTtyname, status.sCmdVirt, gettime());
                    907:        if(fmach == local)
                    908:                sprintf(cmdstr, "echo \"%s\" | %s", errstr,rcmd);
                    909:        else sprintf(cmdstr,
                    910:        "echo \"%s\" | %s -m%c -b -c errormessage -l network - %s",
                    911:                errstr,netcmd,fmach,rcmd);
                    912:        rcode = system(cmdstr);
                    913:        exit(1);
                    914:        }
                    915: handlekill(){  /* SIGTRM signal */
                    916:        long t;
                    917:        addtodump(remote,"Netdaemon terminated.\n");
                    918:        t = gettime();
                    919:        pload(t);
                    920:        dumpit(t);
                    921:        exit(0);        /* kill myself */
                    922:        }
                    923: spacct(log,pass,localname,luid,lgid) /* returns 1 if login ok, 0 if not */
                    924: char *log,*pass,*localname; {
                    925:        long lt;
                    926:        int u,g;
                    927:        if(strcmp(log,"network") == 0)return(1);
                    928:        /* experimental */
                    929: # ifdef SPACCT
                    930:        if(strcmp(log,localname) == 0 && luid != 0 && lgid == 0
                    931:        && isdigit(pass[0]) &&  (
                    932:           strcmp(log,"source") == 0
                    933:        || strcmp(log,"daemon") == 0)
                    934:        ){
                    935:                /* login name is same on both machines, userid is group 0,
                    936:                non-root, the password is numeric
                    937:                and the login name is one of a select few */
                    938:                lt = atol(pass);
                    939:                u = (lt & 0177777);
                    940:                g = (lt >> 16);
                    941:                if((luid == u) && (lgid == g))return(1);
                    942:                }
                    943: # endif
                    944:        return(0);
                    945:        }
                    946: /* add the user's name to our name list */
                    947: /*VARARGS0*/
                    948: addtoname(name)
                    949: char *name;
                    950: {
                    951:        static FILE *log = NULL;
                    952:        if(name == NULL ||
                    953:           name[0] == 0 ||
                    954:           strcmp(name,"root") == 0 ||
                    955:           strcmp(name,"network") == 0 ||
                    956:           strcmp(name,"schmidt") == 0)return;
                    957:        if(log == NULL){
                    958:                if(stat(namefile,&statbuf) < 0)return;
                    959:                log = fopen(namefile,"a");
                    960:                if(log == NULL)return;
                    961:                }
                    962:        fseek(log,0L,2);
                    963:        fprintf(log,"%s:%s\n",longname(local),name);
                    964:        fflush(log);
                    965:        }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.