1*8510Scomay static char sccsid[] = "@(#)netdaemon.c 4.5 (Berkeley) 10/13/82";
28193Smckusick
38193Smckusick /* sccs id variable */
48193Smckusick static char *netdaemon_sid = "@(#)netdaemon.c 1.10";
58193Smckusick
68193Smckusick /*
78193Smckusick
88193Smckusick The daemon program that runs the network.
98193Smckusick
108193Smckusick Usage:
118193Smckusick netdaemon -m mach [-r readfd] [-w writefd] [-d] [-h]
128193Smckusick [-os] [-or] [-ou num] [-p len] [-8] [-l]
138193Smckusick
148193Smckusick Must be started by root.
158193Smckusick Options:
168193Smckusick -d turn debugging on
178193Smckusick -h use high-speed link (not implemented yet)
188193Smckusick -l don't use net line discipline, even if available
198193Smckusick -m mach remote machine is mach (required)
208193Smckusick -os only send
218193Smckusick -or only receive
228193Smckusick -ou num only send things with uid = num
238193Smckusick -p num length of packet
248193Smckusick -r num if simulute w/pipes, read from num
258193Smckusick -w num if simulate w/pipes, write on num
268193Smckusick */
278193Smckusick
288193Smckusick # include "defs.h"
298193Smckusick /* take a time, adjust to be in PST, and divide by no of secs in a day */
308193Smckusick /* adjust by 10 mins, and day is considered to begin at 3AM */
318193Smckusick /* (6*3600 = 21600) + 17400 = 39000 */
328193Smckusick /* number of seconds in a day, usually 86400L */
338193Smckusick # define nsecday 86400L
348193Smckusick /* number of days since time began */
358193Smckusick # define numdays(S) ((S - 39000L)/nsecday)
368193Smckusick /* set my priority to normal */
378193Smckusick # define RENICE0() { if (getuid() == 0) { nice(-40); nice(20); nice(0); } }
388193Smckusick
398193Smckusick /* global variables */
408193Smckusick extern char **environ;
418193Smckusick struct dumpstruc dump;
428193Smckusick struct bstruct btable[];
438193Smckusick struct daemonparms netd;
448193Smckusick struct userinfo status;
458193Smckusick
468193Smckusick /* local variables */
478193Smckusick static long length;
488220Smckusick static DIR *dir;
498193Smckusick /* static char sheader[] = "ABCDE"; */
508193Smckusick static char tempfile[]= TEMPFILE;
518193Smckusick static char publogfile[]= PUBLOGFILE;
528193Smckusick static struct stat statbuf;
538193Smckusick int handlekill();
548193Smckusick static char frommach;
558193Smckusick long linechars();
568193Smckusick
main(argc,argv)578193Smckusick main(argc,argv)
588193Smckusick char **argv; {
598193Smckusick register int i;
608193Smckusick long ltime,t;
618193Smckusick char buf[100];
628193Smckusick
638193Smckusick nice(-1);
648193Smckusick if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
658193Smckusick signal(SIGHUP, handlekill);
668193Smckusick if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
678193Smckusick signal(SIGQUIT, handlekill);
688193Smckusick if (signal(SIGINT, SIG_IGN) != SIG_IGN)
698193Smckusick signal(SIGINT, handlekill);
708193Smckusick if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
718193Smckusick signal(SIGTERM, handlekill);
728193Smckusick debugflg = DBV;
738193Smckusick setupdaemon(argc,argv);
748193Smckusick /* now running alone as a daemon */
758193Smckusick /*
768193Smckusick for(i=0; i<15; i++)close(i);
778193Smckusick signal(SIGHUP,SIG_IGN);
788193Smckusick signal(SIGQUIT,SIG_IGN);
798193Smckusick signal(SIGINT,SIG_IGN);
808193Smckusick */
818193Smckusick /* set the umask to a reasonable value */
828193Smckusick umask( 022 );
838193Smckusick senddir[strlen(senddir)-1] = remote; /* choose dir */
848193Smckusick if(chdir(senddir) < 0){
858193Smckusick perror(senddir);
868193Smckusick exit(EX_OSFILE);
878193Smckusick }
888220Smckusick dir = opendir(senddir);
898193Smckusick if(dir == NULL){
908193Smckusick perror(senddir);
918193Smckusick exit(EX_OSFILE);
928193Smckusick }
938193Smckusick mktemp(tempfile);
948193Smckusick tempfile[strlen(tempfile) - 7] = remote;
958193Smckusick ltime = gettime();
968193Smckusick if(ltime == 0L)
978193Smckusick fprintf(stderr,"The network says 'The clock is set wrong.'\n");
988193Smckusick sprintf(buf,"net restarted to %s %d %s",longname(remote),
998193Smckusick getpid(),ctime(<ime));
1008193Smckusick dump.longtime = ltime;
1018193Smckusick dump.lastndays = numdays(ltime);
1028193Smckusick addtolog(remote,buf);
1038193Smckusick addtopublic(buf);
1048193Smckusick fprintf(stderr,buf);
1058193Smckusick if(!debugflg)fclose(stderr);
1068193Smckusick sendpurge();
1078193Smckusick mainloop();
1088193Smckusick /* never returns */
1098193Smckusick }
1108193Smckusick /* the main loop of the daemon, alternatively rcv then send, if poss.*/
mainloop()1118193Smckusick mainloop(){
1128193Smckusick register int i;
1138193Smckusick
1148193Smckusick for(;;){ /* begin reading file */
1158193Smckusick debug("daemon %c %d\n",remote,getpid());
1168193Smckusick /* first receive */
1178193Smckusick if(netd.dp_sndorcv >= 0){ /* if we can receive */
1188193Smckusick i = netrcv();
1198193Smckusick if(i == -1)dump.nabnormal++;
1208193Smckusick }
1218193Smckusick /* now look to send */
1228193Smckusick if(netd.dp_sndorcv <= 0) /* if we can send */
1238193Smckusick netsend();
1248193Smckusick /* print out statistics if the right time */
1258193Smckusick printstat();
1268193Smckusick dump.nloop++;
1278193Smckusick }
1288193Smckusick }
1298193Smckusick /* this code is a little strange because some machines
1308193Smckusick seem to have trouble having the date set, and time()
1318193Smckusick returns 0 until somebody remembers to set the date */
printstat()1328193Smckusick printstat(){
1338193Smckusick long thisndays, thistime;
1348193Smckusick thistime = gettime();
1358193Smckusick thisndays = numdays(thistime);
1368193Smckusick if(dump.longtime == 0L){
1378193Smckusick dump.longtime = thistime;
1388193Smckusick dump.lastndays = thisndays;
1398193Smckusick return;
1408193Smckusick }
1418193Smckusick if(thisndays == dump.lastndays + 1L) dumpit(thistime);
1428193Smckusick dump.lastndays = thisndays;
1438193Smckusick }
1448193Smckusick /* look for files to send */
netsend()1458193Smckusick netsend(){
1468193Smckusick static long lasttime = 0;
1478193Smckusick static char nleft = 1;
1488193Smckusick long lFileLen,diff;
1498193Smckusick double drate;
1508281Scomay register int uid,uidBest;
1518193Smckusick char *sdate,*sn,*swait;
1528193Smckusick long ot,nt,filesize;
1538193Smckusick register int i;
1548193Smckusick char stemp[20];
1558193Smckusick static char jname[FNS];
1568220Smckusick register struct direct *dp;
1578193Smckusick
1588193Smckusick debug("ck send");
1598193Smckusick if(stat(senddir,&statbuf) < 0){
1608193Smckusick error("%s %s",senddir,sys_errlist[errno]);
1618193Smckusick return;
1628193Smckusick }
1638193Smckusick if(statbuf.st_mtime == lasttime && nleft == 0)return; /* no need to search */
1648193Smckusick lasttime = statbuf.st_mtime;
1658220Smckusick rewinddir(dir);
1668193Smckusick lFileLen = 10000000L;
1678193Smckusick nleft = 0;
1688220Smckusick while((dp = readdir(dir)) != NULL){
1698220Smckusick if(dp->d_name[0] != 'c'
1708220Smckusick || dp->d_name[1] != 'f'
1718220Smckusick || dp->d_name[2] != remote
1728220Smckusick || stat(dp->d_name,&statbuf) < 0
1738193Smckusick || statbuf.st_mode == 0)
1748193Smckusick continue;
1758220Smckusick dp->d_name[0] = 'd';
1768220Smckusick if(stat(dp->d_name,&statbuf) < 0 || statbuf.st_mode == 0)
1778193Smckusick continue;
1788193Smckusick uid = guid(statbuf.st_uid,statbuf.st_gid);
1798193Smckusick if(netd.dp_onlyuid != 0 && uid != netd.dp_onlyuid && uid != SUPERUSER
1808193Smckusick && uid != NUID)continue;
1818193Smckusick nleft++;
1828193Smckusick filesize = getsize(&statbuf);
1838193Smckusick #ifndef DONTHOLDBIG
1848193Smckusick if( (filesize > MAXDAYFILE) && day() ) {
1858193Smckusick if( !debugflg )
1868193Smckusick continue;
1878193Smckusick else
1888220Smckusick debug("sending large file %s\n", dp->d_name );
1898193Smckusick }
1908193Smckusick #endif DONTHOLDBIG
1918193Smckusick if(lFileLen > filesize){
1928193Smckusick lFileLen = filesize;
1938220Smckusick strcpy(jname,dp->d_name);
1948193Smckusick uidBest = uid;
1958193Smckusick }
1968193Smckusick # ifdef MAXSENDQ
1978193Smckusick if(nleft > MAXSENDQ)break;
1988193Smckusick # endif MAXSENDQ
1998193Smckusick }
2008193Smckusick if(lFileLen == 10000000L)return;
2018193Smckusick strcpy(stemp,jname);
2028193Smckusick stemp[0] = 'c';
2038193Smckusick sn = SnFromUid(uidBest);
2048193Smckusick if(sn == NULL){
2058193Smckusick addtolog(remote,"Unknown userid %d\n",uidBest);
2068193Smckusick addtolog(remote,"Removing %s\n",stemp);
2078193Smckusick unlink(stemp);
2088193Smckusick return;
2098193Smckusick }
2108193Smckusick addtolog(remote,"^S %s %c: %s ",sn,remote,jname+2);
2118193Smckusick ot = gettime();
2128193Smckusick if(send(jname) == 0)return;
2138193Smckusick nt = gettime();
2148193Smckusick filesize = getsize(&statbuf);
2158193Smckusick unlink(jname);
2168193Smckusick unlink(stemp);
2178193Smckusick diff = nt - ot;
2188193Smckusick if(diff < 1)diff = 1; /* avoid dividing by zero */
2198193Smckusick sdate = ctime(&nt)+4;
2208193Smckusick sdate[strlen(sdate) -9] = 0;
2218193Smckusick swait = comptime(ot - statbuf.st_mtime);
2228193Smckusick jname[3] = jname[2];
2238193Smckusick # ifndef NOFP
2248193Smckusick drate = (double)filesize / (double)diff;
2258193Smckusick addtolog(remote,"^T%c(%s, %ldb, %ldsec, %4.1fb/sec, w %s)\n",
2268193Smckusick remote,sdate,filesize, diff,drate, swait);
2278193Smckusick # else NOFP
2288193Smckusick addtolog(remote,"^T%c(%s, %ldb, %ldsec, w %s)\n",
2298193Smckusick remote,sdate,filesize, diff,swait);
2308193Smckusick # endif NOFP
2318193Smckusick addtopublic("%s: sent %-8s to %s (%s, %ld b, wait %s)\n",
2328193Smckusick sdate,sn,longname(remote),jname+3,filesize,swait);
2338193Smckusick dump.nsend++;
2348193Smckusick dump.bytetot += filesize;
2358193Smckusick dump.elaptot += diff;
2368193Smckusick }
2378193Smckusick
2388193Smckusick /*
2398193Smckusick day() returns 1 if the time is between 6AM and 12PM
2408193Smckusick */
day()2418193Smckusick day()
2428193Smckusick {
2438193Smckusick int hour;
2448193Smckusick long t;
2458193Smckusick char *ctime();
2468193Smckusick
2478193Smckusick time( &t );
2488193Smckusick sscanf( ctime( &t ), "%*s%*s%*s%2d", &hour );
2498193Smckusick if( (hour>=0) && (hour<6) )
2508193Smckusick return( 0 ); /* night */
2518193Smckusick else
2528193Smckusick return( 1 ); /* day */
2538193Smckusick }
2548193Smckusick
send(jname)2558193Smckusick send(jname)
2568193Smckusick char *jname;
2578193Smckusick { /* push those bytes */
2588193Smckusick /* returns 0 if send fails, 1 otherwise */
2598193Smckusick register int n;
2608193Smckusick int i;
2618193Smckusick long lsize;
2628193Smckusick char mbuf[20], buf[MAXNBUF];
2638193Smckusick register char *p;
2648193Smckusick register FILE *jfile;
2658193Smckusick
2668193Smckusick debug("send %s",jname);
2678193Smckusick if(stat(jname,&statbuf) < 0)goto sfail;
2688193Smckusick lsize = getsize(&statbuf);
2698193Smckusick if(lsize < MINSIZE){ /* all files are at least this long */
2708193Smckusick unlink(jname);
2718193Smckusick jname[0] = 'c';
2728193Smckusick unlink(jname);
2738193Smckusick return(1);
2748193Smckusick }
2758193Smckusick jfile = fopen(jname,"r");
2768193Smckusick if(jfile == NULL)goto sfail;
2778193Smckusick /*
2788193Smckusick strcpy(mbuf,sheader);
2798193Smckusick i = strlen(sheader);
2808193Smckusick p = (char *)&lsize;
2818193Smckusick lsize = fixuplong(lsize);
2828193Smckusick mbuf[i] = *p++;
2838193Smckusick mbuf[i+1] = *p++;
2848193Smckusick mbuf[i+2] = *p++;
2858193Smckusick mbuf[i+3] = *p++;
2868193Smckusick i = i + 4;
2878193Smckusick sendreset();
2888193Smckusick */
2898193Smckusick initseqno();
2908193Smckusick sprintf(mbuf,"|%08ld|",lsize);
2918193Smckusick i = 10;
2928193Smckusick if(xwrite(mbuf,i) == WRITEFAIL)goto bwrite;
2938193Smckusick while((n=read(fileno(jfile),buf,MAXNBUF)) > 0)
2948193Smckusick if(xwrite(buf,n) == WRITEFAIL)goto bwrite;
2958193Smckusick fclose(jfile);
2968193Smckusick debug("end send");
2978193Smckusick return(1);
2988193Smckusick bwrite:
2998193Smckusick dump.nsendfail++;
3008193Smckusick fclose(jfile);
3018193Smckusick addtolog(remote,"^F%c\n",remote);
3028193Smckusick return(0);
3038193Smckusick sfail:
3048193Smckusick error("%s: %s",jname,sys_errlist[errno]);
3058193Smckusick dump.nsendfail++;
3068193Smckusick return(0);
3078193Smckusick }
netrcv()3088193Smckusick netrcv(){
3098193Smckusick /* returns -2 in normal fail, -1 in abnormal fail, >= 0 otherwise */
3108193Smckusick char sin;
3118193Smckusick char mgetc(), *s;
3128193Smckusick register int n;
3138193Smckusick char c;
3148193Smckusick int i, dummy, pid;
3158193Smckusick unsigned rcode;
3168193Smckusick long otime,olength,diff,rcvfinish,nt;
3178193Smckusick double r;
3188193Smckusick char hbuf[20], buf[MAXNBUF];
3198193Smckusick register FILE *temp;
3208193Smckusick static struct header hd;
3218193Smckusick
3228193Smckusick initseqno();
3238193Smckusick /*
3248193Smckusick n = nread(hbuf,strlen(sheader));
3258193Smckusick if(n == BROKENREAD)return(-2);
3268193Smckusick if(n != strlen(sheader) || strcmp(sheader,hbuf) != 0){
3278193Smckusick error("wrong head %d %s",n,hbuf);
3288193Smckusick return(-1);
3298193Smckusick }
3308193Smckusick n = nread(&length,4);
3318193Smckusick length = fixuplong(length);
3328193Smckusick */
3338193Smckusick n = nread(hbuf,10);
3348193Smckusick if(n == BROKENREAD)return(-2);
3358193Smckusick if(n != 10){
3368193Smckusick error("bad length nread %d",n);
3378193Smckusick return(-1);
3388193Smckusick }
3398193Smckusick hbuf[10] = 0;
3408193Smckusick if(hbuf[0] != '|' || hbuf[9] != '|'){
3418193Smckusick error("poor format %s",hbuf);
3428193Smckusick return(-1);
3438193Smckusick }
3448193Smckusick hbuf[9] = 0;
3458193Smckusick length = atol(hbuf+1);
3468193Smckusick if(length < 0 || length > 100000000L){
3478193Smckusick error("bad length %ld",length);
3488193Smckusick return(-1);
3498193Smckusick }
3508193Smckusick dump.braw = 4;
3518193Smckusick olength = length;
3528193Smckusick otime = gettime();
3538193Smckusick debug("length = %ld\n",length);
3548193Smckusick
3558193Smckusick /*
3568193Smckusick begin parsing header
3578193Smckusick
3588193Smckusick from local to remote (requests)
3598193Smckusick code net option reason
3608193Smckusick q normal request
3618193Smckusick y -y simply skips login check (used by netlpr)
3628193Smckusick
3638193Smckusick from remote to local
3648193Smckusick code net option reason
3658193Smckusick w -w message to be written/mailed back
3668193Smckusick s -z normal response
3678193Smckusick */
3688193Smckusick
3698193Smckusick i = readhd(&hd);
3708193Smckusick if(i == -3)goto forw; /* being forwarded thru us */
3718193Smckusick if(i != 0)return(i);
3728193Smckusick
3738193Smckusick strcpy(status.login, hd.hd_snto);
3748193Smckusick strcpy(status.localname,hd.hd_snfrom);
3758193Smckusick
3768193Smckusick demask(hd.hd_spasswd);
3778193Smckusick
3788193Smckusick s = hd.hd_scmdvirt;
3798193Smckusick while(*s && *s != ' ')s++;
3808193Smckusick c = *s;
3818193Smckusick *s = 0;
3828193Smckusick if(strcmp(hd.hd_scmdvirt,"netlpr") == 0)dump.nnetlpr++;
3838193Smckusick else if(strcmp(hd.hd_scmdvirt,"netmail") == 0)dump.nnetmail++;
3848193Smckusick else if(strcmp(hd.hd_scmdvirt,"mail") == 0)dump.nsmail++;
3858193Smckusick else if(strcmp(hd.hd_scmdvirt,"netcp") == 0)dump.nnetcp++;
3868193Smckusick else if(strcmp(hd.hd_scmdvirt,"response") == 0)dump.nresp++;
3878193Smckusick else dump.nnet++;
3888193Smckusick *s = c;
3898193Smckusick
3908193Smckusick printhd(&hd);
3918193Smckusick
3928193Smckusick /* any chars left are data */
3938193Smckusick forw:
3948193Smckusick sin = 0;
3958193Smckusick if(length > 0){ /* make a temp input file */
3968193Smckusick increment(tempfile);
3978193Smckusick temp = fopen(tempfile,"w");
3988193Smckusick if(temp == NULL){
3998193Smckusick error("%s %s",tempfile,sys_errlist[errno]);
4008193Smckusick return(-1);
4018193Smckusick }
4028193Smckusick chmod(tempfile,0600);
4038193Smckusick if(hd.hd_mchto != local){
4048193Smckusick fprintf(temp,"%c :%c :",hd.hd_code,hd.hd_mchto);
4058193Smckusick fflush(temp);
4068193Smckusick }
4078193Smckusick /* this is the loop to read in all the data */
4088193Smckusick while((n = mread(buf,MAXNBUF)) > 0)
4098193Smckusick if(write(fileno(temp),buf,n) != n){
4108193Smckusick error("%s %s",tempfile,sys_errlist[errno]);
4118193Smckusick fclose(temp);
4128193Smckusick unlink(tempfile);
4138193Smckusick return(-1);
4148193Smckusick };
4158193Smckusick fclose(temp);
4168193Smckusick if(n == BROKENREAD || length > 0){
4178193Smckusick unlink(tempfile);
4188193Smckusick return(-2);
4198193Smckusick }
4208193Smckusick sin = 1;
4218193Smckusick if(hd.hd_mchto != local){
4228193Smckusick diff = gettime() - otime;
4238193Smckusick if(diff < 1)diff = 1; /* avoid dividing by 0 */
4248193Smckusick # ifndef NOFP
4258193Smckusick r = olength;
4268193Smckusick r = r/diff;
4278193Smckusick addtolog(remote,"^P(to %c, %ldb, %ldsec, %4.1fb/sec)\n",
4288193Smckusick hd.hd_mchto,olength,diff,r);
4298193Smckusick # else NOFP
4308193Smckusick addtolog(remote,"^P(to %c, %ldb, %ldsec)\n",
4318193Smckusick hd.hd_mchto,olength,diff);
4328193Smckusick # endif NOFP
4338193Smckusick dump.npass++;
4348193Smckusick dump.bytetot += olength;
4358193Smckusick dump.elaptot += diff;
4368193Smckusick while((pid = fork()) == -1)sleep(2);
4378193Smckusick if(pid == 0){
4388193Smckusick RENICE0();
4398193Smckusick #ifdef CCV7
4408193Smckusick /* make sure the spawned child has it's own
4418193Smckusick group process to avoid the nasty
4428193Smckusick "try again" message
4438193Smckusick */
4448193Smckusick setpgrp();
4458193Smckusick #endif CCV7
4468193Smckusick execl(netcmd,"net","-x","-m",longname(hd.hd_mchto),
4478193Smckusick "-s",tempfile,0);
4488193Smckusick error("%s: %s",netcmd,sys_errlist[errno]);
4498193Smckusick exit(EX_UNAVAILABLE);
4508193Smckusick }
451*8510Scomay wait(&rcode);
4528193Smckusick unlink(tempfile);
4538193Smckusick rcode >>= 8;
4548193Smckusick if(rcode != 0)
455*8510Scomay error("pass-thru rcode %d", rcode);
4568193Smckusick debug("passthru to %c code %c rcode %d",
4578193Smckusick hd.hd_mchto,hd.hd_code,rcode);
4588193Smckusick return(1);
4598193Smckusick }
4608193Smckusick }
4618193Smckusick if(length > 0){error("file too short"); return(-1); }
4628193Smckusick rcvfinish = gettime();
4638193Smckusick
4648193Smckusick while((pid = fork()) == -1)sleep(2);
4658193Smckusick if(pid > 0){
466*8510Scomay wait(&dummy);
4678193Smckusick return(1); /* normal return */
4688193Smckusick }
4698193Smckusick /* this is a child, who will go ahead and execute the command */
4708193Smckusick /* running uid=0 at this point */
4718193Smckusick RENICE0();
4728193Smckusick /* nice(0 set back to 0 */
4738193Smckusick #ifdef CCV7
4748193Smckusick /* separate group process */
4758193Smckusick setpgrp();
4768193Smckusick #endif CCV7
4778193Smckusick
4788193Smckusick while((pid = fork()) == -1)sleep(2);
4798193Smckusick if(pid != 0)exit(EX_OK);
4808193Smckusick
4818193Smckusick /* child process which forks and waits */
4828193Smckusick mktemp(resfile);
4838193Smckusick while((pid = fork()) == -1)sleep(2);
4848193Smckusick if(pid == 0){
4858193Smckusick /* child */
4868193Smckusick strcpy(status.loginshell,Bsh);
4878193Smckusick frommach = hd.hd_mchfrom;
4888193Smckusick n = check(&hd,(hd.hd_code == 'q'));
4898193Smckusick if(!n)errormsg(TRUE,&hd,NULL,
4908193Smckusick "Bad remote login/password '%s'",hd.hd_snto);
4918193Smckusick temp = fopen(resfile,"w");
4928193Smckusick if(temp == NULL)
4938193Smckusick errormsg(TRUE,&hd,NULL,
4948193Smckusick "Create file %s: %s",resfile,sys_errlist[errno]);
4958193Smckusick fclose(temp);
4968193Smckusick chmod(resfile,0600);
4978193Smckusick mchown(resfile,status.muid,status.mgid);
4988193Smckusick if(sin)
4998193Smckusick mchown(tempfile,status.muid,status.mgid);
5008193Smckusick else tempfile[0] = 0;
5018193Smckusick setgid(status.mgid);
5028193Smckusick setuid(status.muid);
5038193Smckusick /* after this point our gid, uid is the target user's */
5048193Smckusick excmd(&hd,resfile,tempfile);
5058193Smckusick }
5068193Smckusick /* parent */
507*8510Scomay wait(&rcode);
5088193Smckusick rcode = (((rcode&077400) >>8) &0177);
5098193Smckusick /*
5108193Smckusick fclose(stdin);
5118193Smckusick fclose(stdout);
5128193Smckusick fclose(stderr);
5138193Smckusick */
5148193Smckusick if(sin)unlink(tempfile);
5158193Smckusick /*
5168193Smckusick now send something back to the sender
5178193Smckusick unless this was a response (file or message)
5188193Smckusick */
5198193Smckusick if((hd.hd_code == 'q' || hd.hd_code == 'y')
5208193Smckusick && (hd.hd_srespfile[0] || !hd.hd_fnonotify))
5218193Smckusick sndresponse(&hd,rcode);
5228193Smckusick unlink(resfile);
5238193Smckusick s = ctime(&rcvfinish);
5248193Smckusick s += 4;
5258193Smckusick s[strlen(s) -8] = 0;
5268193Smckusick diff = rcvfinish - otime;
5278193Smckusick if(diff < 1)diff = 1; /* avoid dividing by zero */
5288193Smckusick dump.bytetot += olength;
5298193Smckusick dump.elaptot += diff;
5308193Smckusick sprintf(buf,"%s rcv %c:%-8s (%s)",
5318193Smckusick s,hd.hd_mchfrom,hd.hd_snfrom,hd.hd_snto);
5328193Smckusick addtolog(remote,"%s C: %s\n",buf,hd.hd_scmdvirt);
5338193Smckusick addtopublic("%s R: %d C: %s\n",buf,rcode,hd.hd_scmdvirt);
5348193Smckusick nt = rcvfinish - hd.hd_ltimesent;
5358193Smckusick buf[0] = 0;
5368193Smckusick if(nt > 0L)sprintf(buf," took (%s)",comptime(nt));
5378193Smckusick # ifndef NOFP
5388193Smckusick r = olength;
5398193Smckusick r = r/diff;
5408193Smckusick addtolog(remote,"\t\tR: %d%s %ldb %ldsec %4.1fb/sec\n",
5418193Smckusick rcode,buf,olength,diff,r);
5428193Smckusick r = dump.braw;
5438193Smckusick r = r/diff;
5448193Smckusick addtolog(remote,"\t\t%4.1frb/sec %4.1f%% use\n",r,(r/linechars())*100L);
5458193Smckusick # else NOFP
5468193Smckusick addtolog(remote,"\t\tR: %d%s %ldb %ldsec\n",
5478193Smckusick rcode,buf,olength,diff);
5488193Smckusick # endif NOFP
5498193Smckusick exit(EX_OK);
5508193Smckusick /*UNREACHED*/
5518193Smckusick }
linechars()5528193Smckusick long linechars(){
5538193Smckusick if(netd.dp_inspeed == 13)return(960L);
5548193Smckusick else return(120L);
5558193Smckusick }
5568193Smckusick /*
5578193Smckusick execute the user's command
5588193Smckusick this procedure is executed with uid, gid of the user
5598193Smckusick */
excmd(phd,tempresfile,tempinfile)5608193Smckusick excmd(phd,tempresfile,tempinfile)
5618193Smckusick register struct header *phd;
5628193Smckusick char *tempresfile, *tempinfile;
5638193Smckusick {
5648193Smckusick FILE *fd;
5658193Smckusick int i, uid;
5668193Smckusick register char *s, c;
5678193Smckusick
5688193Smckusick uid = getuid();
5698193Smckusick uid = uidmask(uid);
5708193Smckusick status.muid = uidmask(status.muid);
5718193Smckusick if(uid != status.muid)error("setuid fails");
5728193Smckusick debug("uid: %u, gid: %u\n",uid,status.mgid);
5738193Smckusick /* check for allowed root commands, for security reasons */
5748193Smckusick if(uid == SUPERUSER){
5758193Smckusick s = phd->hd_scmdact;
5768193Smckusick while(*s && *s != ' ')s++;
5778193Smckusick c = *s;
5788193Smckusick *s = 0;
5798193Smckusick /* these are the only commands root may execute */
5808193Smckusick if(strcmp(phd->hd_scmdact,"cat") != 0
5818193Smckusick && strcmp(phd->hd_scmdact,MWRITECMD) != 0
5828193Smckusick && strcmp(phd->hd_scmdact,"/bin/cat") != 0
5838193Smckusick && strcmp(phd->hd_scmdact,"netrm") != 0
5848193Smckusick && strcmp(phd->hd_scmdact,"/usr/lib/tq") != 0
5858193Smckusick && strcmp(phd->hd_scmdact,"/usr/cc/lib/tq") != 0
5868193Smckusick && strcmp(phd->hd_scmdact,"/usr/lib/rtrrm") != 0
5878193Smckusick && strcmp(phd->hd_scmdact,"/usr/cc/lib/rtrrm") != 0
5888193Smckusick && strcmp(phd->hd_scmdact,"lpr") != 0)
5898193Smckusick errormsg(TRUE,phd,tempresfile,
5908193Smckusick "Not allowed to execute '%s' as root",
5918193Smckusick phd->hd_scmdact);
5928193Smckusick *s = c;
5938193Smckusick }
5948193Smckusick if(chdir(status.dir) < 0)
5958193Smckusick errormsg(TRUE,phd,tempresfile,
5968193Smckusick "chdir %s: %s",status.dir,sys_errlist[errno]);
5978193Smckusick setenv(status.dir); /* set up v7 environment */
5988193Smckusick if(tempinfile[0])mreopen(TRUE,phd,tempresfile,tempinfile,"r",stdin);
5998193Smckusick else if(phd->hd_sinfile[0])mreopen(TRUE,phd,tempresfile,phd->hd_sinfile,"r",stdin);
6008193Smckusick else mreopen(TRUE,phd,tempresfile,"/dev/null","r",stdin);
6018193Smckusick if(phd->hd_code == 's' && phd->hd_soutfile[0]){
6028193Smckusick if(stat(phd->hd_soutfile,&statbuf) < 0
6038193Smckusick || getsize(&statbuf) != 0)
6048193Smckusick errormsg(FALSE,phd,tempresfile,"Bad result file '%s'",phd->hd_soutfile);
6058193Smckusick mreopen(TRUE,phd,tempresfile,phd->hd_soutfile,"w",stdout);
6068193Smckusick }
6078193Smckusick else if(phd->hd_soutfile[0]){
6088193Smckusick fd = fopen(phd->hd_soutfile,"w");
6098193Smckusick if(fd == NULL)
6108193Smckusick errormsg(TRUE,phd,tempresfile,"Open file %s: %s",
6118193Smckusick phd->hd_soutfile,sys_errlist[errno]);
6128193Smckusick fclose(fd);
6138193Smckusick mreopen(TRUE,phd,tempresfile,phd->hd_soutfile,"w",stdout);
6148193Smckusick }
6158193Smckusick else mreopen(TRUE,phd,tempresfile,tempresfile,"a",stdout);
6168193Smckusick debug("exec '%s'\n",phd->hd_scmdact);
6178193Smckusick if(debugflg == 0){
6188193Smckusick /* cheat */
6198193Smckusick close(2);
6208193Smckusick dup(1);
6218193Smckusick /*
6228193Smckusick mreopen(TRUE,phd,tempresfile,tempresfile,"a",stderr);
6238193Smckusick */
6248193Smckusick }
6258193Smckusick for(i=3;i<15;i++)close(i);
6268193Smckusick if(strcmp(phd->hd_scmdact,"cat") == 0
6278193Smckusick || strcmp(phd->hd_scmdact,"/bin/cat") == 0)excat();
6288193Smckusick do {
6298193Smckusick mexecl(status.loginshell,"sh","-c",phd->hd_scmdact,0);
6308193Smckusick sleep(2);
6318193Smckusick } while(errno == ETXTBSY);
6328193Smckusick perror(status.loginshell);
6338193Smckusick exit(EX_UNAVAILABLE);
6348193Smckusick }
6358193Smckusick /*
6368193Smckusick send back a response
6378193Smckusick
6388193Smckusick if errormsg was called the resfile should be unlinked,
6398193Smckusick to avoid two messages being sent there
6408193Smckusick */
sndresponse(phd,rcode)6418193Smckusick sndresponse(phd,rcode)
6428193Smckusick unsigned rcode;
6438193Smckusick struct header *phd;
6448193Smckusick {
6458193Smckusick char cmdstr[BUFSIZ], buf[BUFSIZ];
6468193Smckusick int dummy;
6478193Smckusick long maxfile = MAXFILELARGE;
6488193Smckusick /* send response back if a response file
6498193Smckusick was given or if mail/write is allowed */
6508193Smckusick if(stat(resfile,&statbuf) < 0){
6518193Smckusick error("%s %s",resfile,sys_errlist[errno]);
6528193Smckusick return;
6538193Smckusick }
6548193Smckusick if(getsize(&statbuf) >= maxfile){
6558193Smckusick errormsg(TRUE,phd,"Result file too large - not sent");
6568193Smckusick return;
6578193Smckusick }
6588193Smckusick if(getsize(&statbuf) == 0){
6598193Smckusick /* response file specified, no output generated */
6608193Smckusick if(phd->hd_srespfile[0] != 0)return;
6618193Smckusick /* quiet option - no output and a rcode of 0 */
6628193Smckusick if(rcode == 0 && phd->hd_fquiet)return;
6638193Smckusick }
6648193Smckusick /* use both old and new mwrite parm lists */
6658193Smckusick
6668193Smckusick if(phd->hd_srespfile[0])
6678193Smckusick sprintf(cmdstr,"-o %s cat",phd->hd_srespfile);
6688193Smckusick else sprintf(cmdstr,
6698193Smckusick "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -c \"'%s'\" -y %s -e %ld -r %d",
6708193Smckusick MWRITECMD, phd->hd_snfrom,phd->hd_sttyname,phd->hd_lttytime,
6718193Smckusick phd->hd_mchto,phd->hd_snto, phd->hd_scmdvirt,phd->hd_ltimesent-TIMEBASE,
6728193Smckusick phd->hd_addrfrom, phd->hd_addrto, phd->hd_lttytime,
6738193Smckusick phd->hd_scmdvirt, phd->hd_sttyname, phd->hd_ltimesent-TIMEBASE, rcode);
6748193Smckusick
6758193Smckusick sprintf(buf,"%s -m%c -z -b -l %s -s %s -c response %s",
6768193Smckusick netcmd,phd->hd_mchfrom,phd->hd_snfrom,resfile,cmdstr);
6778193Smckusick dummy = system(buf); /* execute command buf */
6788193Smckusick }
6798193Smckusick
6808193Smckusick /*
6818193Smckusick
6828193Smckusick excat
6838193Smckusick does nothing more than copy standard input to standard
6848193Smckusick output, like the cat command, but reports write errors.
6858193Smckusick Uses getc and putc rather than fwrite and fread because
6868193Smckusick the latter call getc and putc.
6878193Smckusick */
excat()6888193Smckusick excat(){
6898193Smckusick register int n;
6908193Smckusick char buf[BUFSIZ];
6918193Smckusick
6928193Smckusick errno = 0;
6938193Smckusick while((n = read(0,buf,BUFSIZ)) > 0){
6948193Smckusick if(write(1,buf,n) != n){
6958193Smckusick perror("filecat: stdout");
6968193Smckusick exit(EX_OSFILE);
6978193Smckusick }
6988193Smckusick }
6998193Smckusick if(errno){
7008193Smckusick perror("filecat: stdin");
7018193Smckusick exit(EX_OSFILE);
7028193Smckusick }
7038193Smckusick exit(EX_OK);
7048193Smckusick }
7058193Smckusick /* returns errors for netrcv() */
readhd(phd)7068193Smckusick static readhd(phd)
7078193Smckusick register struct header *phd;
7088193Smckusick {
7098193Smckusick char cflag, sbuf[BUFSIZ], parmlist[PARMLIST], *cptr;
7108193Smckusick int i, code;
7118193Smckusick code = mgetc();
7128193Smckusick phd->hd_mchto = mgetc();
7138193Smckusick if(code != 'q' && code != 'y' && code != 'w' && code != 's'){
7148193Smckusick error("bad code");
7158193Smckusick return(-1);
7168193Smckusick }
7178193Smckusick phd->hd_code = code;
7188193Smckusick for(i = 0; i < MAXINX; i++)
7198193Smckusick if(phd->hd_mchto == inxtoch(i)) break;
7208193Smckusick if(i >= MAXINX){
7218193Smckusick error("bad phd->hd_mchto");
7228193Smckusick return(-1);
7238193Smckusick }
7248193Smckusick if(phd->hd_mchto != local)return(-3); /* being forwarded through us */
7258193Smckusick phd->hd_mchfrom = mgetc();
7268193Smckusick phd->hd_vmajor = mgetc();
7278193Smckusick phd->hd_vminor = mgetc();
7288193Smckusick i = 0;
7298193Smckusick i += mgets(phd->hd_snto,NS);
7308193Smckusick i += mgets(phd->hd_spasswd,20);
7318193Smckusick i += mgets(phd->hd_sinfile,FNS);
7328193Smckusick i += mgets(phd->hd_soutfile,FNS);
7338193Smckusick i += mgets(phd->hd_srespfile,FNS);
7348193Smckusick i += mgets(phd->hd_snfrom,NS);
7358193Smckusick
7368193Smckusick /* addrfrom is the person who sent this to us,
7378193Smckusick addrto is the person who received the command, i.e.
7388193Smckusick addrto is on this machine */
7398193Smckusick if(phd->hd_snfrom[0] == 0)strcpy(phd->hd_snfrom,"root");
7408193Smckusick sprintf(phd->hd_addrfrom, "%s:%s",longname(phd->hd_mchfrom),phd->hd_snfrom);
7418193Smckusick sprintf(phd->hd_addrto, "%s:%s",longname(phd->hd_mchto),phd->hd_snto);
7428193Smckusick
7438193Smckusick i += mgets(phd->hd_sttyname,20);
7448193Smckusick if(phd->hd_sttyname[0] == 0)strcpy(phd->hd_sttyname,"/dev/ttyx");
7458193Smckusick cflag = mgetc();
7468193Smckusick if(!phd->hd_mchfrom || !phd->hd_code || !cflag || !phd->hd_vmajor || !phd->hd_vminor){
7478193Smckusick error("mgetc fails");
7488193Smckusick return(-1);
7498193Smckusick }
7508193Smckusick
7518193Smckusick cflag -= 'a';
7528193Smckusick phd->hd_fnonotify = (cflag & F_NONOTIFY);
7538193Smckusick phd->hd_fquiet = (cflag & F_QUIET);
7548193Smckusick
7558193Smckusick phd->hd_vmajor -= 'a';
7568193Smckusick phd->hd_vminor -= 'a';
7578193Smckusick
7588193Smckusick i += mgets(sbuf,BUFSIZ);
7598193Smckusick phd->hd_lttytime = 0;
7608193Smckusick sscanf(sbuf,"%lo",&phd->hd_lttytime);
7618193Smckusick
7628193Smckusick i += mgets(parmlist,PARMLIST);
7638193Smckusick #ifdef CRN
7648193Smckusick cptr = parmlist;
7658193Smckusick while( *cptr != '(' )
7668193Smckusick cptr++;
7678193Smckusick *cptr = '\0';
7688193Smckusick strcpy( phd->hd_ijobno, parmlist );
7698193Smckusick *cptr = '(';
7708193Smckusick #else CRN
7718193Smckusick strcpy( phd->hd_ijobno, "XYZZ" );
7728193Smckusick #endif CRN
7738193Smckusick /* keep variable parameter list in crn slot */
7748193Smckusick parseparmlist(parmlist);
7758193Smckusick
7768193Smckusick i += mgets(sbuf,BUFSIZ); /* time sent */
7778193Smckusick sscanf(sbuf,"%ld",&phd->hd_ltimesent);
7788193Smckusick phd->hd_ltimesent += TIMEBASE;
7798193Smckusick i += mgetcmd(phd->hd_scmdact);
7808193Smckusick i += mgetcmd(phd->hd_scmdvirt);
7818193Smckusick if(i != 0){error("mgets fails"); return(-1);}
7828193Smckusick if(phd->hd_scmdvirt[0] == 0)strcpy(phd->hd_scmdvirt,phd->hd_scmdact);
7838193Smckusick return(0);
7848193Smckusick }
7858193Smckusick /*
7868193Smckusick check() -- verify login name and password
7878193Smckusick phd = login,passwd
7888193Smckusick fverify = 1 if password must check
7898193Smckusick Returns 1 if password is ok, 0 if not.
7908193Smckusick */
check(phd,fverify)7918193Smckusick check(phd,fverify) /* 1 if OK, 0 if not */
7928193Smckusick register struct header *phd;
7938193Smckusick int fverify;
7948193Smckusick {
7958193Smckusick char *sencpasswd, *u, *nullstr = "";
7968193Smckusick struct passwd *pwd;
7978193Smckusick #ifdef CRN
7988193Smckusick struct gecos *gcos;
7998193Smckusick #endif CRN
8008193Smckusick if(phd->hd_snto[0] == 0)return(!fverify);
8018193Smckusick debug("check: phd->hd_snto = %s\n", phd->hd_snto );
8028193Smckusick if(!goodacctname(phd->hd_snto))return(!fverify);
8038193Smckusick pwd = getpwnam(phd->hd_snto);
8048193Smckusick debug("got pwd=%d, pwd->pw_passwd = %s\n",pwd, pwd->pw_passwd);
8058193Smckusick if(pwd == NULL)return(!fverify);
8068193Smckusick if(*phd->hd_spasswd)sencpasswd = crypt(phd->hd_spasswd,pwd->pw_passwd);
8078193Smckusick else sencpasswd = nullstr;
8088193Smckusick debug("check: passwd(rcvd)=%s, passwd(file) = %s, passwd(encrypt)=%s\n", phd->hd_spasswd, pwd->pw_passwd, sencpasswd );
8098193Smckusick
8108193Smckusick status.muid = guid(pwd->pw_uid,pwd->pw_gid);
8118193Smckusick status.mgid = pwd->pw_gid;
8128193Smckusick #ifdef CRN
8138193Smckusick if( (gcos=pwgecos( pwd->pw_gecos )) == NULL )
8148193Smckusick strcpy( status.jobno, MAGICCRN );
8158193Smckusick else
8168193Smckusick strcpy( status.jobno, gcos->gc_crn );
8178193Smckusick #else CRN
8188193Smckusick strcpy( status.jobno, "XYZZ");
8198193Smckusick #endif CRN
8208193Smckusick strcpy(status.dir,pwd->pw_dir);
8218193Smckusick strcpy(status.loginshell,pwd->pw_shell);
8228193Smckusick u = status.loginshell;
8238193Smckusick if(u[0] == 0 || strcmp("/bin/sbash",u) == 0)strcpy(u,Bsh);
8248193Smckusick
8258193Smckusick getpwdf(pwd);
8268193Smckusick /* ignore network passwd */
8278193Smckusick /* acct is not a pair, acct is not "network", passwd is incorrect,
8288193Smckusick and verification is requested => passwd not ok */
8298193Smckusick if(!facctpaircheck(phd) && strcmp(phd->hd_snto,"network") != 0
8308193Smckusick && strcmp(pwd->pw_passwd,sencpasswd) != 0 && fverify)
8318193Smckusick return(0);
8328193Smckusick return(1); /* otherwise passwd ok */
8338193Smckusick }
mread(b,n)8348193Smckusick mread(b,n)
8358193Smckusick register int n; {
8368193Smckusick if(length <= 0)return(0);
8378193Smckusick if(length < n)n = length;
8388193Smckusick n = nread(b,n);
8398193Smckusick if(n != BROKENREAD)length -= n;
8408193Smckusick return(n);
8418193Smckusick }
mgetc()8428193Smckusick char mgetc(){ /* returns 0 if fail */
8438193Smckusick register char c;
8448193Smckusick register int n;
8458193Smckusick char buf[3];
8468193Smckusick if((n=nread(buf,3)) == BROKENREAD)return(0);
8478193Smckusick if(n != 3){error("bad read %d",n); return(0); }
8488193Smckusick c = buf[0];
8498193Smckusick if(buf[1] != ' ' && buf[1] != ':'){error("Bad char %c",buf[1]); return(0); }
8508193Smckusick length -= 3;
8518193Smckusick if(length < 0){error("length wrong2 %ld",length); return(0); }
8528193Smckusick return(c);
8538193Smckusick }
8548193Smckusick /* read in string over the network wire */
8558193Smckusick /* put string in s, max length is maxlen */
mgets(s,maxlen)8568193Smckusick mgets(s,maxlen) /* returns 0 if ok, 1 if not */
8578193Smckusick int maxlen;
8588193Smckusick register char *s; {
8598193Smckusick register char *q;
8608193Smckusick register int n;
8618193Smckusick char c;
8628193Smckusick q = s;
8638193Smckusick for(;;) {
8648193Smckusick if((n=nread(&c,1)) == BROKENREAD){
8658193Smckusick *s = 0;
8668193Smckusick error("mgets %s",s);
8678193Smckusick return(1);
8688193Smckusick }
8698193Smckusick if(n == 0)break;
8708193Smckusick if(c == '\\'){
8718193Smckusick if((n=nread(&c,1)) == BROKENREAD){
8728193Smckusick *s = 0;
8738193Smckusick error("mgets %s",s);
8748193Smckusick return(1);
8758193Smckusick }
8768193Smckusick if(n == 0)break;
8778193Smckusick }
8788193Smckusick if(c == ' ')break;
8798193Smckusick if(maxlen-- > 0) *s++ = c;
8808193Smckusick }
8818193Smckusick *s = 0;
8828193Smckusick if(nread(&c,1) == BROKENREAD){
8838193Smckusick error("mgets %s",s);
8848193Smckusick return(1);
8858193Smckusick }
8868193Smckusick length -= (s - q + 2);
8878193Smckusick if(length < 0){error("length wrong1 %ld %s",length,q); return(-1); }
8888193Smckusick if(maxlen < 0)
8898193Smckusick error("mgets - string too long");
8908193Smckusick return(0);
8918193Smckusick }
mgetcmd(s)8928193Smckusick mgetcmd(s) /* returns 0 if succeed, 1 otherwise */
8938193Smckusick char *s; {
8948193Smckusick int i,n;
8958193Smckusick char c;
8968193Smckusick i = 0;
8978193Smckusick for(;;){
8988193Smckusick if((n=nread(&c,1)) == BROKENREAD){
8998193Smckusick s[i] = 0;
9008193Smckusick error("mgetcmd %s",s);
9018193Smckusick return(1);
9028193Smckusick }
9038193Smckusick if(n <= 0 || c == '\n')break;
9048193Smckusick if(c == '\\'){
9058193Smckusick if(nread(&c,1) == BROKENREAD){
9068193Smckusick s[i] = 0;
9078193Smckusick error("mgetcmd %s",s);
9088193Smckusick return(1);
9098193Smckusick }
9108193Smckusick length--;
9118193Smckusick }
9128193Smckusick s[i++] = c;
9138193Smckusick length--;
9148193Smckusick }
9158193Smckusick s[i] = 0;
9168193Smckusick length--;
9178193Smckusick return(0);
9188193Smckusick }
increment(s)9198193Smckusick increment(s)
9208193Smckusick char *s; {
9218193Smckusick int i;
9228193Smckusick char *p;
9238193Smckusick i = strlen(s) - 1;
9248193Smckusick while(s[i] == '9')i--;
9258193Smckusick if(s[i] < '0' || s[i] > '9'){
9268193Smckusick p = s+i+1;
9278193Smckusick while(*p)*p++ = '0';
9288193Smckusick return;
9298193Smckusick }
9308193Smckusick (s[i])++;
9318193Smckusick i++;
9328193Smckusick while(s[i])s[i++] = '0';
9338193Smckusick return;
9348193Smckusick }
9358193Smckusick /* gather 24-hour stats and mail to STATADDR */
9368193Smckusick /* should also gather stats on # error msgs */
dumpit(currt)9378193Smckusick dumpit(currt)
9388193Smckusick long currt; {
9398193Smckusick register struct dumpstruc *p = &dump;
9408193Smckusick register int ntot;
9418193Smckusick long elapt;
9428193Smckusick double cputime,utime,stime,bs,rawbs;
9438193Smckusick char *sstartt;
9448193Smckusick FILE *fdm;
9458193Smckusick char froma[30];
9468193Smckusick struct tms tbf;
9478193Smckusick
9488193Smckusick /* if STATADDR is a file, the mail program this call will
9498193Smckusick ultimately execute must be able to deal with it,
9508193Smckusick and the remote mail program must be able to write on the
9518193Smckusick file, i.e. mode 666 */
9528193Smckusick sprintf(froma,"%s=>",longname(local));
9538193Smckusick strcat(froma,longname(remote));
9548193Smckusick fdm = mailopen(STATADDR,froma,1,0);
9558193Smckusick if(fdm == NULL)return;
9568193Smckusick
9578193Smckusick /* calculate times */
9588193Smckusick elapt = currt - dump.longtime;
9598193Smckusick ntot = p->nnetcp + p->nnetmail + p->nsmail + p->nnetlpr
9608193Smckusick + p->nresp + p->nnet;
9618193Smckusick sstartt = ctime(&dump.longtime) + 4;
9628193Smckusick sstartt[strlen(sstartt) - 9] = 0;
9638193Smckusick
9648193Smckusick times(&tbf);
9658193Smckusick # ifndef NOFP
9668193Smckusick utime = tbf.tms_utime + tbf.tms_cutime;
9678193Smckusick stime = tbf.tms_stime + tbf.tms_cstime;
9688193Smckusick cputime = utime + stime;
9698193Smckusick if(elapt > 0)cputime = (cputime/elapt) * 100.0;
9708193Smckusick else cputime = 0.0;
9718193Smckusick utime = utime/60.0;
9728193Smckusick stime = stime/60.0;
9738193Smckusick cputime = cputime/60.0;
9748193Smckusick bs = p->bytetot;
9758193Smckusick if(p->elaptot > 0)bs = bs /p->elaptot;
9768193Smckusick else bs = 0.0;
9778193Smckusick # endif NOFP
9788193Smckusick
9798193Smckusick /* print out the statistics */
9808193Smckusick fprintf(fdm,"Subject: %s, %s, time %s\n",
9818193Smckusick froma,sstartt, comptime(elapt));
9828193Smckusick fprintf(fdm,"Command summary:\n");
9838193Smckusick fprintf(fdm,"\t# sent %d\t# pass_thru %d\t# rcv %d:\t# netcp %d\n",
9848193Smckusick p->nsend,p->npass,ntot,p->nnetcp);
9858193Smckusick fprintf(fdm,"\t# netlpr %d\t# netmail %d\t# sendbmail %d\t# resp %d\n",
9868193Smckusick p->nnetlpr,p->nnetmail,p->nsmail,p->nresp);
9878193Smckusick fprintf(fdm,"Protocol summary:\n");
9888193Smckusick fprintf(fdm,"\t# pk_sent %d\t# pk_rcv %d\t# b_sent %ld\t# b_rcv %ld\n",
9898193Smckusick p->npacksent,p->npackrcv,p->nbytesent, p->nbytercv);
9908193Smckusick fprintf(fdm,
9918193Smckusick "\t# send_fails %d\t# retrans %d\t# abn %d\t\t# cksum_errs %d\n",
9928193Smckusick p->nsendfail,p->nretrans, p->nabnormal,p->ncksum);
9938193Smckusick # ifndef NOFP
9948193Smckusick fprintf(fdm,"Load:\tuser %4.1f\tsys %4.1f\tpct %5.2f\trate %6.1f\n",
9958193Smckusick utime,stime,cputime,bs);
9968193Smckusick rawbs = p->brawtot*100L;
9978193Smckusick rawbs = rawbs / linechars();
9988193Smckusick fprintf(fdm,"\trawbytes %ld\tuse %4.1f\n", p->brawtot,rawbs);
9998193Smckusick # endif NOFP
10008193Smckusick mailclose(fdm);
10018193Smckusick
10028193Smckusick /* reset counters */
10038193Smckusick p->nbytesent = p->nbytercv = p->elaptot = p->bytetot = 0L;
10048193Smckusick p->nretrans = p->nloop = p->nabnormal = p->ncksum = 0;
10058193Smckusick p->npacksent = p->npackrcv = p->nnetcp = p->nnetmail = 0;
10068193Smckusick p->nsmail = p->nnetlpr = p->nnet = p->npass = 0;
10078193Smckusick p->nsend = p->nsendfail = 0;
10088193Smckusick dump.longtime = currt;
10098193Smckusick }
10108193Smckusick /* returns 1 if n is ok, 0 if not */
goodacctname(n)10118193Smckusick goodacctname(n)
10128193Smckusick char *n; {
10138193Smckusick int i;
10148193Smckusick i = -1;
10158193Smckusick while(btable[++i].bname)
10168193Smckusick if(strcmp(btable[i].bname,n) == 0 &&
10178193Smckusick local == btable[i].bmach)return(0);
10188193Smckusick return(1);
10198193Smckusick }
demask(s)10208193Smckusick demask(s)
10218193Smckusick register char *s; {
10228193Smckusick /*
10238193Smckusick static char buf[20];
10248193Smckusick char skey[30];
10258193Smckusick makeuukey(skey,status.login,local);
10268193Smckusick strcpy(s,nbsdecrypt(s,skey,buf));
10278193Smckusick */
10288193Smckusick while(*s){
10298193Smckusick *s &= 0177; /* strip quote bites */
10308193Smckusick *s++ ^= 040; /* invert upper-lower */
10318193Smckusick }
10328193Smckusick }
10338193Smckusick /*VARARGS0*/
mreopen(fsendtofmach,phd,sfn,a,b,c)10348193Smckusick mreopen(fsendtofmach,phd,sfn,a,b,c){
10358193Smckusick /* simply handles errors by giving error msg */
10368193Smckusick if(freopen(a,b,c) == NULL)
10378193Smckusick errormsg(fsendtofmach,phd,sfn,"%s: %s",a,sys_errlist[errno]);
10388193Smckusick }
10398193Smckusick /*
10408193Smckusick addtopub(string, args)
10418193Smckusick
10428193Smckusick add a message to the public logfile /usr/net/logfile.
10438193Smckusick note that the file must be writeable by everyone
10448193Smckusick if error messages from the netrcv subroutine
10458193Smckusick such as chdir errors are to be noticed.
10468193Smckusick */
10478193Smckusick /*VARARGS0*/
addtopublic(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n)10488193Smckusick addtopublic(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n)
10498193Smckusick char *s;
10508193Smckusick {
10518193Smckusick static FILE *log = NULL;
10528193Smckusick if(log == NULL){
10538193Smckusick if(stat(publogfile,&statbuf) < 0)return;
10548193Smckusick log = fopen(publogfile,"a");
10558193Smckusick if(log == NULL)return;
10568193Smckusick }
10578193Smckusick fseek(log,0L,2);
10588193Smckusick fprintf(log,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n);
10598193Smckusick fflush(log);
10608193Smckusick }
10618193Smckusick /* set up a dummy environment for v7 /bin/sh */
setenv(home)10628193Smckusick setenv(home)
10638193Smckusick char *home; {
10648193Smckusick static char *env[3],benv[2][50];
10658193Smckusick env[0] = benv[0];
10668193Smckusick env[1] = benv[1];
10678193Smckusick #ifdef CCV7
10688193Smckusick strcpy( env[0], "PATH=:.:/usr/cc/bin:/usr/ucb/bin" );
10698193Smckusick #else CCV7
10708193Smckusick strcpy(env[0],"PATH=:/bin:/usr/bin");
10718193Smckusick #endif CCV7
10728193Smckusick sprintf(env[1],"HOME=%s",home);
10738193Smckusick env[2] = 0;
10748193Smckusick environ = env;
10758193Smckusick }
10768193Smckusick /*
10778193Smckusick errormsg(fsendtofmach,phd,sfn,"string",arg(s))
10788193Smckusick
10798193Smckusick Sends error message to user.
10808193Smckusick If fsendtofmach=TRUE, send to phd->hd_mchfrom, otherwise
10818193Smckusick send to phd->hd_mchto.
10828193Smckusick Also, if error occured during return of a "response",
10838193Smckusick send to local machine.
10848193Smckusick
10858193Smckusick Note that errormsg can be called by the netrcv subroutine
10868193Smckusick after the setuid() call to the specific user, so the
10878193Smckusick user must be able to get off an error msg back to him,
10888193Smckusick and to write in the two log files.
10898193Smckusick Can't use -w,-x,-y,-z for the net cmd because must be root for those.
10908193Smckusick
10918193Smckusick If sfn != NULL, then unlink sfn before exiting.
10928193Smckusick */
10938193Smckusick /*VARARGS0*/
errormsg(fsendtofmach,phd,sfn,s,a,b,c,d,e,f,g,h)10948193Smckusick errormsg(fsendtofmach,phd,sfn,s,a,b,c,d,e,f,g,h)
10958193Smckusick char fsendtofmach;
10968193Smckusick struct header *phd;
10978193Smckusick char *sfn,*s;
10988193Smckusick {
10998193Smckusick int rcode;
11008193Smckusick char errstr[BUFSIZ], cmdstr[BUFSIZ], rcmd[BUFSIZ];
11018193Smckusick char toadd[FNS], fromadd[FNS], mchto, mchfrom;
11028193Smckusick char snto[FNS], snfrom[FNS];
11038193Smckusick
11048193Smckusick if(phd->hd_sttyname[0] == 0)strcpy(phd->hd_sttyname,"/dev/ttyx");
11058193Smckusick /* will send to toadd, from fromadd */
11068193Smckusick if(!fsendtofmach || strcmp(phd->hd_scmdvirt,"response") == 0){
11078193Smckusick /* send to tomach mach, thus send to toaddr. */
11088193Smckusick /* if this is an error during a response, send to local mach. */
11098193Smckusick strcpy(toadd, phd->hd_addrto);
11108193Smckusick strcpy(fromadd,phd->hd_addrfrom);
11118193Smckusick }
11128193Smckusick else { /* send to remote mach, thus send back to addrfrom*/
11138193Smckusick strcpy(toadd, phd->hd_addrfrom);
11148193Smckusick strcpy(fromadd,phd->hd_addrto);
11158193Smckusick }
11168193Smckusick sprintf(errstr,"Error: ");
11178193Smckusick sprintf(cmdstr,s,a,b,c,d,e,f,g,h);
11188193Smckusick strcat(errstr,cmdstr);
11198193Smckusick strcat(errstr,"\n");
11208193Smckusick addtolog(remote,errstr);
11218193Smckusick addtopublic(errstr);
11228193Smckusick
11238193Smckusick mchto = MchSFromAddr(snto,toadd);
11248193Smckusick mchfrom = MchSFromAddr(snfrom,fromadd);
11258193Smckusick
11268193Smckusick sprintf(rcmd,
11278193Smckusick "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -y %s -c \"'%s'\" -e %ld",
11288193Smckusick MWRITECMD, snto, phd->hd_sttyname, phd->hd_lttytime,
11298193Smckusick local, snfrom,phd->hd_scmdvirt, phd->hd_ltimesent-TIMEBASE,
11308193Smckusick toadd, fromadd, phd->hd_lttytime, phd->hd_sttyname, phd->hd_scmdvirt,
11318193Smckusick phd->hd_ltimesent-TIMEBASE);
11328193Smckusick
11338193Smckusick if(mchto == local)
11348193Smckusick sprintf(cmdstr, "echo \"%s\" | %s", errstr,rcmd);
11358193Smckusick else
11368193Smckusick sprintf(cmdstr,
11378193Smckusick "echo \"%s\" | %s -m%c -b -c errormessage -l network - %s",
11388193Smckusick errstr,netcmd,mchto,rcmd);
11398193Smckusick rcode = system(cmdstr);
11408193Smckusick debug( "errormsg: cmdstr = %s\n", cmdstr );
11418193Smckusick debug( "errormsg: rcode = %d\n", rcode );
11428193Smckusick if(sfn != NULL)unlink(sfn);
11438193Smckusick exit(EX_USAGE);
11448193Smckusick }
handlekill()11458193Smckusick handlekill(){ /* SIGTERM signal */
11468193Smckusick long t;
11478193Smckusick /*
11488193Smckusick t = gettime();
11498193Smckusick dumpit(t);
11508193Smckusick */
11518193Smckusick # ifdef NETLDISC
11528193Smckusick /* turn off net line discipline if possible */
11538193Smckusick netd.dp_linedis = 0;
11548193Smckusick ioctl(netd.dp_linefd,TIOCSETD,&netd.dp_linedis);
11558193Smckusick close(netd.dp_linefd);
11568193Smckusick printf("Network line discipline turned off.\n");
11578193Smckusick # endif NETLDISC
11588193Smckusick exit(EX_OK); /* kill myself */
11598193Smckusick }
11608193Smckusick
11618193Smckusick /* check a request to see if it is an acct pair */
11628193Smckusick /* returns 1 if it is, 0 if not */
facctpaircheck(phd)11638193Smckusick static facctpaircheck(phd)
11648193Smckusick register struct header *phd;
11658193Smckusick {
11668193Smckusick return(0);
11678193Smckusick }
11688193Smckusick
1169