home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / net / netdaemon.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  21KB  |  824 lines

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