1*8220Smckusick static char sccsid[] = "@(#)netdaemon.c 4.2 (Berkeley) 09/12/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; 48*8220Smckusick 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 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 } 88*8220Smckusick 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.*/ 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 */ 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 */ 1458193Smckusick netsend(){ 1468193Smckusick static long lasttime = 0; 1478193Smckusick static char nleft = 1; 1488193Smckusick long lFileLen,diff; 1498193Smckusick double drate; 1508193Smckusick register unsigned 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]; 156*8220Smckusick 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; 165*8220Smckusick rewinddir(dir); 1668193Smckusick lFileLen = 10000000L; 1678193Smckusick nleft = 0; 168*8220Smckusick while((dp = readdir(dir)) != NULL){ 169*8220Smckusick if(dp->d_name[0] != 'c' 170*8220Smckusick || dp->d_name[1] != 'f' 171*8220Smckusick || dp->d_name[2] != remote 172*8220Smckusick || stat(dp->d_name,&statbuf) < 0 1738193Smckusick || statbuf.st_mode == 0) 1748193Smckusick continue; 175*8220Smckusick dp->d_name[0] = 'd'; 176*8220Smckusick 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 188*8220Smckusick debug("sending large file %s\n", dp->d_name ); 1898193Smckusick } 1908193Smckusick #endif DONTHOLDBIG 1918193Smckusick if(lFileLen > filesize){ 1928193Smckusick lFileLen = filesize; 193*8220Smckusick 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 */ 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 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 } 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 # ifndef V6 4398193Smckusick RENICE0(); 4408193Smckusick # endif V6 4418193Smckusick #ifdef CCV7 4428193Smckusick /* make sure the spawned child has it's own 4438193Smckusick group process to avoid the nasty 4448193Smckusick "try again" message 4458193Smckusick */ 4468193Smckusick setpgrp(); 4478193Smckusick #endif CCV7 4488193Smckusick execl(netcmd,"net","-x","-m",longname(hd.hd_mchto), 4498193Smckusick "-s",tempfile,0); 4508193Smckusick error("%s: %s",netcmd,sys_errlist[errno]); 4518193Smckusick exit(EX_UNAVAILABLE); 4528193Smckusick } 4538193Smckusick wait(&rcode); 4548193Smckusick unlink(tempfile); 4558193Smckusick rcode >>= 8; 4568193Smckusick if(rcode != 0) 4578193Smckusick error("pass-thru rcode %d"); 4588193Smckusick debug("passthru to %c code %c rcode %d", 4598193Smckusick hd.hd_mchto,hd.hd_code,rcode); 4608193Smckusick return(1); 4618193Smckusick } 4628193Smckusick } 4638193Smckusick if(length > 0){error("file too short"); return(-1); } 4648193Smckusick rcvfinish = gettime(); 4658193Smckusick 4668193Smckusick while((pid = fork()) == -1)sleep(2); 4678193Smckusick if(pid > 0){ 4688193Smckusick wait(&dummy); 4698193Smckusick return(1); /* normal return */ 4708193Smckusick } 4718193Smckusick /* this is a child, who will go ahead and execute the command */ 4728193Smckusick /* running uid=0 at this point */ 4738193Smckusick # ifndef V6 4748193Smckusick RENICE0(); 4758193Smckusick # endif V6 4768193Smckusick /* nice(0 set back to 0 */ 4778193Smckusick #ifdef CCV7 4788193Smckusick /* separate group process */ 4798193Smckusick setpgrp(); 4808193Smckusick #endif CCV7 4818193Smckusick 4828193Smckusick while((pid = fork()) == -1)sleep(2); 4838193Smckusick if(pid != 0)exit(EX_OK); 4848193Smckusick 4858193Smckusick /* child process which forks and waits */ 4868193Smckusick mktemp(resfile); 4878193Smckusick while((pid = fork()) == -1)sleep(2); 4888193Smckusick if(pid == 0){ 4898193Smckusick /* child */ 4908193Smckusick strcpy(status.loginshell,Bsh); 4918193Smckusick frommach = hd.hd_mchfrom; 4928193Smckusick n = check(&hd,(hd.hd_code == 'q')); 4938193Smckusick if(!n)errormsg(TRUE,&hd,NULL, 4948193Smckusick "Bad remote login/password '%s'",hd.hd_snto); 4958193Smckusick temp = fopen(resfile,"w"); 4968193Smckusick if(temp == NULL) 4978193Smckusick errormsg(TRUE,&hd,NULL, 4988193Smckusick "Create file %s: %s",resfile,sys_errlist[errno]); 4998193Smckusick fclose(temp); 5008193Smckusick chmod(resfile,0600); 5018193Smckusick mchown(resfile,status.muid,status.mgid); 5028193Smckusick if(sin) 5038193Smckusick mchown(tempfile,status.muid,status.mgid); 5048193Smckusick else tempfile[0] = 0; 5058193Smckusick setgid(status.mgid); 5068193Smckusick setuid(status.muid); 5078193Smckusick /* after this point our gid, uid is the target user's */ 5088193Smckusick excmd(&hd,resfile,tempfile); 5098193Smckusick } 5108193Smckusick /* parent */ 5118193Smckusick wait(&rcode); 5128193Smckusick rcode = (((rcode&077400) >>8) &0177); 5138193Smckusick /* 5148193Smckusick fclose(stdin); 5158193Smckusick fclose(stdout); 5168193Smckusick fclose(stderr); 5178193Smckusick */ 5188193Smckusick if(sin)unlink(tempfile); 5198193Smckusick /* 5208193Smckusick now send something back to the sender 5218193Smckusick unless this was a response (file or message) 5228193Smckusick */ 5238193Smckusick if((hd.hd_code == 'q' || hd.hd_code == 'y') 5248193Smckusick && (hd.hd_srespfile[0] || !hd.hd_fnonotify)) 5258193Smckusick sndresponse(&hd,rcode); 5268193Smckusick unlink(resfile); 5278193Smckusick s = ctime(&rcvfinish); 5288193Smckusick s += 4; 5298193Smckusick s[strlen(s) -8] = 0; 5308193Smckusick diff = rcvfinish - otime; 5318193Smckusick if(diff < 1)diff = 1; /* avoid dividing by zero */ 5328193Smckusick dump.bytetot += olength; 5338193Smckusick dump.elaptot += diff; 5348193Smckusick sprintf(buf,"%s rcv %c:%-8s (%s)", 5358193Smckusick s,hd.hd_mchfrom,hd.hd_snfrom,hd.hd_snto); 5368193Smckusick addtolog(remote,"%s C: %s\n",buf,hd.hd_scmdvirt); 5378193Smckusick addtopublic("%s R: %d C: %s\n",buf,rcode,hd.hd_scmdvirt); 5388193Smckusick nt = rcvfinish - hd.hd_ltimesent; 5398193Smckusick buf[0] = 0; 5408193Smckusick if(nt > 0L)sprintf(buf," took (%s)",comptime(nt)); 5418193Smckusick # ifndef NOFP 5428193Smckusick r = olength; 5438193Smckusick r = r/diff; 5448193Smckusick addtolog(remote,"\t\tR: %d%s %ldb %ldsec %4.1fb/sec\n", 5458193Smckusick rcode,buf,olength,diff,r); 5468193Smckusick r = dump.braw; 5478193Smckusick r = r/diff; 5488193Smckusick addtolog(remote,"\t\t%4.1frb/sec %4.1f%% use\n",r,(r/linechars())*100L); 5498193Smckusick # else NOFP 5508193Smckusick addtolog(remote,"\t\tR: %d%s %ldb %ldsec\n", 5518193Smckusick rcode,buf,olength,diff); 5528193Smckusick # endif NOFP 5538193Smckusick exit(EX_OK); 5548193Smckusick /*UNREACHED*/ 5558193Smckusick } 5568193Smckusick long linechars(){ 5578193Smckusick if(netd.dp_inspeed == 13)return(960L); 5588193Smckusick else return(120L); 5598193Smckusick } 5608193Smckusick /* 5618193Smckusick execute the user's command 5628193Smckusick this procedure is executed with uid, gid of the user 5638193Smckusick */ 5648193Smckusick excmd(phd,tempresfile,tempinfile) 5658193Smckusick register struct header *phd; 5668193Smckusick char *tempresfile, *tempinfile; 5678193Smckusick { 5688193Smckusick FILE *fd; 5698193Smckusick int i, uid; 5708193Smckusick register char *s, c; 5718193Smckusick 5728193Smckusick uid = getuid(); 5738193Smckusick uid = uidmask(uid); 5748193Smckusick status.muid = uidmask(status.muid); 5758193Smckusick if(uid != status.muid)error("setuid fails"); 5768193Smckusick debug("uid: %u, gid: %u\n",uid,status.mgid); 5778193Smckusick /* check for allowed root commands, for security reasons */ 5788193Smckusick if(uid == SUPERUSER){ 5798193Smckusick s = phd->hd_scmdact; 5808193Smckusick while(*s && *s != ' ')s++; 5818193Smckusick c = *s; 5828193Smckusick *s = 0; 5838193Smckusick /* these are the only commands root may execute */ 5848193Smckusick if(strcmp(phd->hd_scmdact,"cat") != 0 5858193Smckusick && strcmp(phd->hd_scmdact,MWRITECMD) != 0 5868193Smckusick && strcmp(phd->hd_scmdact,"/bin/cat") != 0 5878193Smckusick && strcmp(phd->hd_scmdact,"netrm") != 0 5888193Smckusick && strcmp(phd->hd_scmdact,"/usr/lib/tq") != 0 5898193Smckusick && strcmp(phd->hd_scmdact,"/usr/cc/lib/tq") != 0 5908193Smckusick && strcmp(phd->hd_scmdact,"/usr/lib/rtrrm") != 0 5918193Smckusick && strcmp(phd->hd_scmdact,"/usr/cc/lib/rtrrm") != 0 5928193Smckusick && strcmp(phd->hd_scmdact,"lpr") != 0) 5938193Smckusick errormsg(TRUE,phd,tempresfile, 5948193Smckusick "Not allowed to execute '%s' as root", 5958193Smckusick phd->hd_scmdact); 5968193Smckusick *s = c; 5978193Smckusick } 5988193Smckusick if(chdir(status.dir) < 0) 5998193Smckusick errormsg(TRUE,phd,tempresfile, 6008193Smckusick "chdir %s: %s",status.dir,sys_errlist[errno]); 6018193Smckusick setenv(status.dir); /* set up v7 environment */ 6028193Smckusick if(tempinfile[0])mreopen(TRUE,phd,tempresfile,tempinfile,"r",stdin); 6038193Smckusick else if(phd->hd_sinfile[0])mreopen(TRUE,phd,tempresfile,phd->hd_sinfile,"r",stdin); 6048193Smckusick else mreopen(TRUE,phd,tempresfile,"/dev/null","r",stdin); 6058193Smckusick if(phd->hd_code == 's' && phd->hd_soutfile[0]){ 6068193Smckusick if(stat(phd->hd_soutfile,&statbuf) < 0 6078193Smckusick || getsize(&statbuf) != 0) 6088193Smckusick errormsg(FALSE,phd,tempresfile,"Bad result file '%s'",phd->hd_soutfile); 6098193Smckusick mreopen(TRUE,phd,tempresfile,phd->hd_soutfile,"w",stdout); 6108193Smckusick } 6118193Smckusick else if(phd->hd_soutfile[0]){ 6128193Smckusick fd = fopen(phd->hd_soutfile,"w"); 6138193Smckusick if(fd == NULL) 6148193Smckusick errormsg(TRUE,phd,tempresfile,"Open file %s: %s", 6158193Smckusick phd->hd_soutfile,sys_errlist[errno]); 6168193Smckusick fclose(fd); 6178193Smckusick mreopen(TRUE,phd,tempresfile,phd->hd_soutfile,"w",stdout); 6188193Smckusick } 6198193Smckusick else mreopen(TRUE,phd,tempresfile,tempresfile,"a",stdout); 6208193Smckusick debug("exec '%s'\n",phd->hd_scmdact); 6218193Smckusick if(debugflg == 0){ 6228193Smckusick /* cheat */ 6238193Smckusick close(2); 6248193Smckusick dup(1); 6258193Smckusick /* 6268193Smckusick mreopen(TRUE,phd,tempresfile,tempresfile,"a",stderr); 6278193Smckusick */ 6288193Smckusick } 6298193Smckusick for(i=3;i<15;i++)close(i); 6308193Smckusick if(strcmp(phd->hd_scmdact,"cat") == 0 6318193Smckusick || strcmp(phd->hd_scmdact,"/bin/cat") == 0)excat(); 6328193Smckusick do { 6338193Smckusick mexecl(status.loginshell,"sh","-c",phd->hd_scmdact,0); 6348193Smckusick sleep(2); 6358193Smckusick } while(errno == ETXTBSY); 6368193Smckusick perror(status.loginshell); 6378193Smckusick exit(EX_UNAVAILABLE); 6388193Smckusick } 6398193Smckusick /* 6408193Smckusick send back a response 6418193Smckusick 6428193Smckusick if errormsg was called the resfile should be unlinked, 6438193Smckusick to avoid two messages being sent there 6448193Smckusick */ 6458193Smckusick sndresponse(phd,rcode) 6468193Smckusick unsigned rcode; 6478193Smckusick struct header *phd; 6488193Smckusick { 6498193Smckusick char cmdstr[BUFSIZ], buf[BUFSIZ]; 6508193Smckusick int dummy; 6518193Smckusick long maxfile = MAXFILELARGE; 6528193Smckusick /* send response back if a response file 6538193Smckusick was given or if mail/write is allowed */ 6548193Smckusick if(stat(resfile,&statbuf) < 0){ 6558193Smckusick error("%s %s",resfile,sys_errlist[errno]); 6568193Smckusick return; 6578193Smckusick } 6588193Smckusick if(getsize(&statbuf) >= maxfile){ 6598193Smckusick errormsg(TRUE,phd,"Result file too large - not sent"); 6608193Smckusick return; 6618193Smckusick } 6628193Smckusick if(getsize(&statbuf) == 0){ 6638193Smckusick /* response file specified, no output generated */ 6648193Smckusick if(phd->hd_srespfile[0] != 0)return; 6658193Smckusick /* quiet option - no output and a rcode of 0 */ 6668193Smckusick if(rcode == 0 && phd->hd_fquiet)return; 6678193Smckusick } 6688193Smckusick /* use both old and new mwrite parm lists */ 6698193Smckusick 6708193Smckusick if(phd->hd_srespfile[0]) 6718193Smckusick sprintf(cmdstr,"-o %s cat",phd->hd_srespfile); 6728193Smckusick else sprintf(cmdstr, 6738193Smckusick "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -c \"'%s'\" -y %s -e %ld -r %d", 6748193Smckusick MWRITECMD, phd->hd_snfrom,phd->hd_sttyname,phd->hd_lttytime, 6758193Smckusick phd->hd_mchto,phd->hd_snto, phd->hd_scmdvirt,phd->hd_ltimesent-TIMEBASE, 6768193Smckusick phd->hd_addrfrom, phd->hd_addrto, phd->hd_lttytime, 6778193Smckusick phd->hd_scmdvirt, phd->hd_sttyname, phd->hd_ltimesent-TIMEBASE, rcode); 6788193Smckusick 6798193Smckusick sprintf(buf,"%s -m%c -z -b -l %s -s %s -c response %s", 6808193Smckusick netcmd,phd->hd_mchfrom,phd->hd_snfrom,resfile,cmdstr); 6818193Smckusick dummy = system(buf); /* execute command buf */ 6828193Smckusick } 6838193Smckusick 6848193Smckusick /* 6858193Smckusick 6868193Smckusick excat 6878193Smckusick does nothing more than copy standard input to standard 6888193Smckusick output, like the cat command, but reports write errors. 6898193Smckusick Uses getc and putc rather than fwrite and fread because 6908193Smckusick the latter call getc and putc. 6918193Smckusick */ 6928193Smckusick excat(){ 6938193Smckusick register int n; 6948193Smckusick char buf[BUFSIZ]; 6958193Smckusick 6968193Smckusick errno = 0; 6978193Smckusick while((n = read(0,buf,BUFSIZ)) > 0){ 6988193Smckusick if(write(1,buf,n) != n){ 6998193Smckusick perror("filecat: stdout"); 7008193Smckusick exit(EX_OSFILE); 7018193Smckusick } 7028193Smckusick } 7038193Smckusick if(errno){ 7048193Smckusick perror("filecat: stdin"); 7058193Smckusick exit(EX_OSFILE); 7068193Smckusick } 7078193Smckusick exit(EX_OK); 7088193Smckusick } 7098193Smckusick /* returns errors for netrcv() */ 7108193Smckusick static readhd(phd) 7118193Smckusick register struct header *phd; 7128193Smckusick { 7138193Smckusick char cflag, sbuf[BUFSIZ], parmlist[PARMLIST], *cptr; 7148193Smckusick int i, code; 7158193Smckusick code = mgetc(); 7168193Smckusick phd->hd_mchto = mgetc(); 7178193Smckusick if(code != 'q' && code != 'y' && code != 'w' && code != 's'){ 7188193Smckusick error("bad code"); 7198193Smckusick return(-1); 7208193Smckusick } 7218193Smckusick phd->hd_code = code; 7228193Smckusick for(i = 0; i < MAXINX; i++) 7238193Smckusick if(phd->hd_mchto == inxtoch(i)) break; 7248193Smckusick if(i >= MAXINX){ 7258193Smckusick error("bad phd->hd_mchto"); 7268193Smckusick return(-1); 7278193Smckusick } 7288193Smckusick if(phd->hd_mchto != local)return(-3); /* being forwarded through us */ 7298193Smckusick phd->hd_mchfrom = mgetc(); 7308193Smckusick phd->hd_vmajor = mgetc(); 7318193Smckusick phd->hd_vminor = mgetc(); 7328193Smckusick i = 0; 7338193Smckusick i += mgets(phd->hd_snto,NS); 7348193Smckusick i += mgets(phd->hd_spasswd,20); 7358193Smckusick i += mgets(phd->hd_sinfile,FNS); 7368193Smckusick i += mgets(phd->hd_soutfile,FNS); 7378193Smckusick i += mgets(phd->hd_srespfile,FNS); 7388193Smckusick i += mgets(phd->hd_snfrom,NS); 7398193Smckusick 7408193Smckusick /* addrfrom is the person who sent this to us, 7418193Smckusick addrto is the person who received the command, i.e. 7428193Smckusick addrto is on this machine */ 7438193Smckusick if(phd->hd_snfrom[0] == 0)strcpy(phd->hd_snfrom,"root"); 7448193Smckusick sprintf(phd->hd_addrfrom, "%s:%s",longname(phd->hd_mchfrom),phd->hd_snfrom); 7458193Smckusick sprintf(phd->hd_addrto, "%s:%s",longname(phd->hd_mchto),phd->hd_snto); 7468193Smckusick 7478193Smckusick i += mgets(phd->hd_sttyname,20); 7488193Smckusick if(phd->hd_sttyname[0] == 0)strcpy(phd->hd_sttyname,"/dev/ttyx"); 7498193Smckusick cflag = mgetc(); 7508193Smckusick if(!phd->hd_mchfrom || !phd->hd_code || !cflag || !phd->hd_vmajor || !phd->hd_vminor){ 7518193Smckusick error("mgetc fails"); 7528193Smckusick return(-1); 7538193Smckusick } 7548193Smckusick 7558193Smckusick cflag -= 'a'; 7568193Smckusick phd->hd_fnonotify = (cflag & F_NONOTIFY); 7578193Smckusick phd->hd_fquiet = (cflag & F_QUIET); 7588193Smckusick 7598193Smckusick phd->hd_vmajor -= 'a'; 7608193Smckusick phd->hd_vminor -= 'a'; 7618193Smckusick 7628193Smckusick i += mgets(sbuf,BUFSIZ); 7638193Smckusick phd->hd_lttytime = 0; 7648193Smckusick sscanf(sbuf,"%lo",&phd->hd_lttytime); 7658193Smckusick 7668193Smckusick i += mgets(parmlist,PARMLIST); 7678193Smckusick #ifdef CRN 7688193Smckusick cptr = parmlist; 7698193Smckusick while( *cptr != '(' ) 7708193Smckusick cptr++; 7718193Smckusick *cptr = '\0'; 7728193Smckusick strcpy( phd->hd_ijobno, parmlist ); 7738193Smckusick *cptr = '('; 7748193Smckusick #else CRN 7758193Smckusick strcpy( phd->hd_ijobno, "XYZZ" ); 7768193Smckusick #endif CRN 7778193Smckusick /* keep variable parameter list in crn slot */ 7788193Smckusick parseparmlist(parmlist); 7798193Smckusick 7808193Smckusick i += mgets(sbuf,BUFSIZ); /* time sent */ 7818193Smckusick sscanf(sbuf,"%ld",&phd->hd_ltimesent); 7828193Smckusick phd->hd_ltimesent += TIMEBASE; 7838193Smckusick i += mgetcmd(phd->hd_scmdact); 7848193Smckusick i += mgetcmd(phd->hd_scmdvirt); 7858193Smckusick if(i != 0){error("mgets fails"); return(-1);} 7868193Smckusick if(phd->hd_scmdvirt[0] == 0)strcpy(phd->hd_scmdvirt,phd->hd_scmdact); 7878193Smckusick return(0); 7888193Smckusick } 7898193Smckusick /* 7908193Smckusick check() -- verify login name and password 7918193Smckusick phd = login,passwd 7928193Smckusick fverify = 1 if password must check 7938193Smckusick Returns 1 if password is ok, 0 if not. 7948193Smckusick */ 7958193Smckusick check(phd,fverify) /* 1 if OK, 0 if not */ 7968193Smckusick register struct header *phd; 7978193Smckusick int fverify; 7988193Smckusick { 7998193Smckusick char *sencpasswd, *u, *nullstr = ""; 8008193Smckusick struct passwd *pwd; 8018193Smckusick #ifdef CRN 8028193Smckusick struct gecos *gcos; 8038193Smckusick #endif CRN 8048193Smckusick if(phd->hd_snto[0] == 0)return(!fverify); 8058193Smckusick debug("check: phd->hd_snto = %s\n", phd->hd_snto ); 8068193Smckusick if(!goodacctname(phd->hd_snto))return(!fverify); 8078193Smckusick pwd = getpwnam(phd->hd_snto); 8088193Smckusick debug("got pwd=%d, pwd->pw_passwd = %s\n",pwd, pwd->pw_passwd); 8098193Smckusick if(pwd == NULL)return(!fverify); 8108193Smckusick if(*phd->hd_spasswd)sencpasswd = crypt(phd->hd_spasswd,pwd->pw_passwd); 8118193Smckusick else sencpasswd = nullstr; 8128193Smckusick debug("check: passwd(rcvd)=%s, passwd(file) = %s, passwd(encrypt)=%s\n", phd->hd_spasswd, pwd->pw_passwd, sencpasswd ); 8138193Smckusick 8148193Smckusick status.muid = guid(pwd->pw_uid,pwd->pw_gid); 8158193Smckusick status.mgid = pwd->pw_gid; 8168193Smckusick #ifdef CRN 8178193Smckusick if( (gcos=pwgecos( pwd->pw_gecos )) == NULL ) 8188193Smckusick strcpy( status.jobno, MAGICCRN ); 8198193Smckusick else 8208193Smckusick strcpy( status.jobno, gcos->gc_crn ); 8218193Smckusick #else CRN 8228193Smckusick strcpy( status.jobno, "XYZZ"); 8238193Smckusick #endif CRN 8248193Smckusick strcpy(status.dir,pwd->pw_dir); 8258193Smckusick strcpy(status.loginshell,pwd->pw_shell); 8268193Smckusick u = status.loginshell; 8278193Smckusick if(u[0] == 0 || strcmp("/bin/sbash",u) == 0)strcpy(u,Bsh); 8288193Smckusick 8298193Smckusick getpwdf(pwd); 8308193Smckusick /* ignore network passwd */ 8318193Smckusick /* acct is not a pair, acct is not "network", passwd is incorrect, 8328193Smckusick and verification is requested => passwd not ok */ 8338193Smckusick if(!facctpaircheck(phd) && strcmp(phd->hd_snto,"network") != 0 8348193Smckusick && strcmp(pwd->pw_passwd,sencpasswd) != 0 && fverify) 8358193Smckusick return(0); 8368193Smckusick return(1); /* otherwise passwd ok */ 8378193Smckusick } 8388193Smckusick mread(b,n) 8398193Smckusick register int n; { 8408193Smckusick if(length <= 0)return(0); 8418193Smckusick if(length < n)n = length; 8428193Smckusick n = nread(b,n); 8438193Smckusick if(n != BROKENREAD)length -= n; 8448193Smckusick return(n); 8458193Smckusick } 8468193Smckusick char mgetc(){ /* returns 0 if fail */ 8478193Smckusick register char c; 8488193Smckusick register int n; 8498193Smckusick char buf[3]; 8508193Smckusick if((n=nread(buf,3)) == BROKENREAD)return(0); 8518193Smckusick if(n != 3){error("bad read %d",n); return(0); } 8528193Smckusick c = buf[0]; 8538193Smckusick if(buf[1] != ' ' && buf[1] != ':'){error("Bad char %c",buf[1]); return(0); } 8548193Smckusick length -= 3; 8558193Smckusick if(length < 0){error("length wrong2 %ld",length); return(0); } 8568193Smckusick return(c); 8578193Smckusick } 8588193Smckusick /* read in string over the network wire */ 8598193Smckusick /* put string in s, max length is maxlen */ 8608193Smckusick mgets(s,maxlen) /* returns 0 if ok, 1 if not */ 8618193Smckusick int maxlen; 8628193Smckusick register char *s; { 8638193Smckusick register char *q; 8648193Smckusick register int n; 8658193Smckusick char c; 8668193Smckusick q = s; 8678193Smckusick for(;;) { 8688193Smckusick if((n=nread(&c,1)) == BROKENREAD){ 8698193Smckusick *s = 0; 8708193Smckusick error("mgets %s",s); 8718193Smckusick return(1); 8728193Smckusick } 8738193Smckusick if(n == 0)break; 8748193Smckusick if(c == '\\'){ 8758193Smckusick if((n=nread(&c,1)) == BROKENREAD){ 8768193Smckusick *s = 0; 8778193Smckusick error("mgets %s",s); 8788193Smckusick return(1); 8798193Smckusick } 8808193Smckusick if(n == 0)break; 8818193Smckusick } 8828193Smckusick if(c == ' ')break; 8838193Smckusick if(maxlen-- > 0) *s++ = c; 8848193Smckusick } 8858193Smckusick *s = 0; 8868193Smckusick if(nread(&c,1) == BROKENREAD){ 8878193Smckusick error("mgets %s",s); 8888193Smckusick return(1); 8898193Smckusick } 8908193Smckusick length -= (s - q + 2); 8918193Smckusick if(length < 0){error("length wrong1 %ld %s",length,q); return(-1); } 8928193Smckusick if(maxlen < 0) 8938193Smckusick error("mgets - string too long"); 8948193Smckusick return(0); 8958193Smckusick } 8968193Smckusick mgetcmd(s) /* returns 0 if succeed, 1 otherwise */ 8978193Smckusick char *s; { 8988193Smckusick int i,n; 8998193Smckusick char c; 9008193Smckusick i = 0; 9018193Smckusick for(;;){ 9028193Smckusick if((n=nread(&c,1)) == BROKENREAD){ 9038193Smckusick s[i] = 0; 9048193Smckusick error("mgetcmd %s",s); 9058193Smckusick return(1); 9068193Smckusick } 9078193Smckusick if(n <= 0 || c == '\n')break; 9088193Smckusick if(c == '\\'){ 9098193Smckusick if(nread(&c,1) == BROKENREAD){ 9108193Smckusick s[i] = 0; 9118193Smckusick error("mgetcmd %s",s); 9128193Smckusick return(1); 9138193Smckusick } 9148193Smckusick length--; 9158193Smckusick } 9168193Smckusick s[i++] = c; 9178193Smckusick length--; 9188193Smckusick } 9198193Smckusick s[i] = 0; 9208193Smckusick length--; 9218193Smckusick return(0); 9228193Smckusick } 9238193Smckusick increment(s) 9248193Smckusick char *s; { 9258193Smckusick int i; 9268193Smckusick char *p; 9278193Smckusick i = strlen(s) - 1; 9288193Smckusick while(s[i] == '9')i--; 9298193Smckusick if(s[i] < '0' || s[i] > '9'){ 9308193Smckusick p = s+i+1; 9318193Smckusick while(*p)*p++ = '0'; 9328193Smckusick return; 9338193Smckusick } 9348193Smckusick (s[i])++; 9358193Smckusick i++; 9368193Smckusick while(s[i])s[i++] = '0'; 9378193Smckusick return; 9388193Smckusick } 9398193Smckusick /* gather 24-hour stats and mail to STATADDR */ 9408193Smckusick /* should also gather stats on # error msgs */ 9418193Smckusick dumpit(currt) 9428193Smckusick long currt; { 9438193Smckusick register struct dumpstruc *p = &dump; 9448193Smckusick register int ntot; 9458193Smckusick long elapt; 9468193Smckusick double cputime,utime,stime,bs,rawbs; 9478193Smckusick char *sstartt; 9488193Smckusick FILE *fdm; 9498193Smckusick char froma[30]; 9508193Smckusick struct tms tbf; 9518193Smckusick 9528193Smckusick /* if STATADDR is a file, the mail program this call will 9538193Smckusick ultimately execute must be able to deal with it, 9548193Smckusick and the remote mail program must be able to write on the 9558193Smckusick file, i.e. mode 666 */ 9568193Smckusick sprintf(froma,"%s=>",longname(local)); 9578193Smckusick strcat(froma,longname(remote)); 9588193Smckusick fdm = mailopen(STATADDR,froma,1,0); 9598193Smckusick if(fdm == NULL)return; 9608193Smckusick 9618193Smckusick /* calculate times */ 9628193Smckusick elapt = currt - dump.longtime; 9638193Smckusick ntot = p->nnetcp + p->nnetmail + p->nsmail + p->nnetlpr 9648193Smckusick + p->nresp + p->nnet; 9658193Smckusick sstartt = ctime(&dump.longtime) + 4; 9668193Smckusick sstartt[strlen(sstartt) - 9] = 0; 9678193Smckusick 9688193Smckusick times(&tbf); 9698193Smckusick # ifndef NOFP 9708193Smckusick utime = tbf.tms_utime + tbf.tms_cutime; 9718193Smckusick stime = tbf.tms_stime + tbf.tms_cstime; 9728193Smckusick cputime = utime + stime; 9738193Smckusick if(elapt > 0)cputime = (cputime/elapt) * 100.0; 9748193Smckusick else cputime = 0.0; 9758193Smckusick utime = utime/60.0; 9768193Smckusick stime = stime/60.0; 9778193Smckusick cputime = cputime/60.0; 9788193Smckusick bs = p->bytetot; 9798193Smckusick if(p->elaptot > 0)bs = bs /p->elaptot; 9808193Smckusick else bs = 0.0; 9818193Smckusick # endif NOFP 9828193Smckusick 9838193Smckusick /* print out the statistics */ 9848193Smckusick fprintf(fdm,"Subject: %s, %s, time %s\n", 9858193Smckusick froma,sstartt, comptime(elapt)); 9868193Smckusick fprintf(fdm,"Command summary:\n"); 9878193Smckusick fprintf(fdm,"\t# sent %d\t# pass_thru %d\t# rcv %d:\t# netcp %d\n", 9888193Smckusick p->nsend,p->npass,ntot,p->nnetcp); 9898193Smckusick fprintf(fdm,"\t# netlpr %d\t# netmail %d\t# sendbmail %d\t# resp %d\n", 9908193Smckusick p->nnetlpr,p->nnetmail,p->nsmail,p->nresp); 9918193Smckusick fprintf(fdm,"Protocol summary:\n"); 9928193Smckusick fprintf(fdm,"\t# pk_sent %d\t# pk_rcv %d\t# b_sent %ld\t# b_rcv %ld\n", 9938193Smckusick p->npacksent,p->npackrcv,p->nbytesent, p->nbytercv); 9948193Smckusick fprintf(fdm, 9958193Smckusick "\t# send_fails %d\t# retrans %d\t# abn %d\t\t# cksum_errs %d\n", 9968193Smckusick p->nsendfail,p->nretrans, p->nabnormal,p->ncksum); 9978193Smckusick # ifndef NOFP 9988193Smckusick fprintf(fdm,"Load:\tuser %4.1f\tsys %4.1f\tpct %5.2f\trate %6.1f\n", 9998193Smckusick utime,stime,cputime,bs); 10008193Smckusick rawbs = p->brawtot*100L; 10018193Smckusick rawbs = rawbs / linechars(); 10028193Smckusick fprintf(fdm,"\trawbytes %ld\tuse %4.1f\n", p->brawtot,rawbs); 10038193Smckusick # endif NOFP 10048193Smckusick mailclose(fdm); 10058193Smckusick 10068193Smckusick /* reset counters */ 10078193Smckusick p->nbytesent = p->nbytercv = p->elaptot = p->bytetot = 0L; 10088193Smckusick p->nretrans = p->nloop = p->nabnormal = p->ncksum = 0; 10098193Smckusick p->npacksent = p->npackrcv = p->nnetcp = p->nnetmail = 0; 10108193Smckusick p->nsmail = p->nnetlpr = p->nnet = p->npass = 0; 10118193Smckusick p->nsend = p->nsendfail = 0; 10128193Smckusick dump.longtime = currt; 10138193Smckusick } 10148193Smckusick /* returns 1 if n is ok, 0 if not */ 10158193Smckusick goodacctname(n) 10168193Smckusick char *n; { 10178193Smckusick int i; 10188193Smckusick i = -1; 10198193Smckusick while(btable[++i].bname) 10208193Smckusick if(strcmp(btable[i].bname,n) == 0 && 10218193Smckusick local == btable[i].bmach)return(0); 10228193Smckusick return(1); 10238193Smckusick } 10248193Smckusick demask(s) 10258193Smckusick register char *s; { 10268193Smckusick /* 10278193Smckusick static char buf[20]; 10288193Smckusick char skey[30]; 10298193Smckusick makeuukey(skey,status.login,local); 10308193Smckusick strcpy(s,nbsdecrypt(s,skey,buf)); 10318193Smckusick */ 10328193Smckusick while(*s){ 10338193Smckusick *s &= 0177; /* strip quote bites */ 10348193Smckusick *s++ ^= 040; /* invert upper-lower */ 10358193Smckusick } 10368193Smckusick } 10378193Smckusick /*VARARGS0*/ 10388193Smckusick mreopen(fsendtofmach,phd,sfn,a,b,c){ 10398193Smckusick /* simply handles errors by giving error msg */ 10408193Smckusick if(freopen(a,b,c) == NULL) 10418193Smckusick errormsg(fsendtofmach,phd,sfn,"%s: %s",a,sys_errlist[errno]); 10428193Smckusick } 10438193Smckusick /* 10448193Smckusick addtopub(string, args) 10458193Smckusick 10468193Smckusick add a message to the public logfile /usr/net/logfile. 10478193Smckusick note that the file must be writeable by everyone 10488193Smckusick if error messages from the netrcv subroutine 10498193Smckusick such as chdir errors are to be noticed. 10508193Smckusick */ 10518193Smckusick /*VARARGS0*/ 10528193Smckusick addtopublic(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n) 10538193Smckusick char *s; 10548193Smckusick { 10558193Smckusick static FILE *log = NULL; 10568193Smckusick if(log == NULL){ 10578193Smckusick if(stat(publogfile,&statbuf) < 0)return; 10588193Smckusick log = fopen(publogfile,"a"); 10598193Smckusick if(log == NULL)return; 10608193Smckusick } 10618193Smckusick fseek(log,0L,2); 10628193Smckusick fprintf(log,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n); 10638193Smckusick fflush(log); 10648193Smckusick } 10658193Smckusick /* set up a dummy environment for v7 /bin/sh */ 10668193Smckusick setenv(home) 10678193Smckusick char *home; { 10688193Smckusick static char *env[3],benv[2][50]; 10698193Smckusick env[0] = benv[0]; 10708193Smckusick env[1] = benv[1]; 10718193Smckusick #ifdef CCV7 10728193Smckusick strcpy( env[0], "PATH=:.:/usr/cc/bin:/usr/ucb/bin" ); 10738193Smckusick #else CCV7 10748193Smckusick strcpy(env[0],"PATH=:/bin:/usr/bin"); 10758193Smckusick #endif CCV7 10768193Smckusick sprintf(env[1],"HOME=%s",home); 10778193Smckusick env[2] = 0; 10788193Smckusick environ = env; 10798193Smckusick } 10808193Smckusick /* 10818193Smckusick errormsg(fsendtofmach,phd,sfn,"string",arg(s)) 10828193Smckusick 10838193Smckusick Sends error message to user. 10848193Smckusick If fsendtofmach=TRUE, send to phd->hd_mchfrom, otherwise 10858193Smckusick send to phd->hd_mchto. 10868193Smckusick Also, if error occured during return of a "response", 10878193Smckusick send to local machine. 10888193Smckusick 10898193Smckusick Note that errormsg can be called by the netrcv subroutine 10908193Smckusick after the setuid() call to the specific user, so the 10918193Smckusick user must be able to get off an error msg back to him, 10928193Smckusick and to write in the two log files. 10938193Smckusick Can't use -w,-x,-y,-z for the net cmd because must be root for those. 10948193Smckusick 10958193Smckusick If sfn != NULL, then unlink sfn before exiting. 10968193Smckusick */ 10978193Smckusick /*VARARGS0*/ 10988193Smckusick errormsg(fsendtofmach,phd,sfn,s,a,b,c,d,e,f,g,h) 10998193Smckusick char fsendtofmach; 11008193Smckusick struct header *phd; 11018193Smckusick char *sfn,*s; 11028193Smckusick { 11038193Smckusick int rcode; 11048193Smckusick char errstr[BUFSIZ], cmdstr[BUFSIZ], rcmd[BUFSIZ]; 11058193Smckusick char toadd[FNS], fromadd[FNS], mchto, mchfrom; 11068193Smckusick char snto[FNS], snfrom[FNS]; 11078193Smckusick 11088193Smckusick if(phd->hd_sttyname[0] == 0)strcpy(phd->hd_sttyname,"/dev/ttyx"); 11098193Smckusick /* will send to toadd, from fromadd */ 11108193Smckusick if(!fsendtofmach || strcmp(phd->hd_scmdvirt,"response") == 0){ 11118193Smckusick /* send to tomach mach, thus send to toaddr. */ 11128193Smckusick /* if this is an error during a response, send to local mach. */ 11138193Smckusick strcpy(toadd, phd->hd_addrto); 11148193Smckusick strcpy(fromadd,phd->hd_addrfrom); 11158193Smckusick } 11168193Smckusick else { /* send to remote mach, thus send back to addrfrom*/ 11178193Smckusick strcpy(toadd, phd->hd_addrfrom); 11188193Smckusick strcpy(fromadd,phd->hd_addrto); 11198193Smckusick } 11208193Smckusick sprintf(errstr,"Error: "); 11218193Smckusick sprintf(cmdstr,s,a,b,c,d,e,f,g,h); 11228193Smckusick strcat(errstr,cmdstr); 11238193Smckusick strcat(errstr,"\n"); 11248193Smckusick addtolog(remote,errstr); 11258193Smckusick addtopublic(errstr); 11268193Smckusick 11278193Smckusick mchto = MchSFromAddr(snto,toadd); 11288193Smckusick mchfrom = MchSFromAddr(snfrom,fromadd); 11298193Smckusick 11308193Smckusick sprintf(rcmd, 11318193Smckusick "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -y %s -c \"'%s'\" -e %ld", 11328193Smckusick MWRITECMD, snto, phd->hd_sttyname, phd->hd_lttytime, 11338193Smckusick local, snfrom,phd->hd_scmdvirt, phd->hd_ltimesent-TIMEBASE, 11348193Smckusick toadd, fromadd, phd->hd_lttytime, phd->hd_sttyname, phd->hd_scmdvirt, 11358193Smckusick phd->hd_ltimesent-TIMEBASE); 11368193Smckusick 11378193Smckusick if(mchto == local) 11388193Smckusick sprintf(cmdstr, "echo \"%s\" | %s", errstr,rcmd); 11398193Smckusick else 11408193Smckusick sprintf(cmdstr, 11418193Smckusick "echo \"%s\" | %s -m%c -b -c errormessage -l network - %s", 11428193Smckusick errstr,netcmd,mchto,rcmd); 11438193Smckusick rcode = system(cmdstr); 11448193Smckusick debug( "errormsg: cmdstr = %s\n", cmdstr ); 11458193Smckusick debug( "errormsg: rcode = %d\n", rcode ); 11468193Smckusick if(sfn != NULL)unlink(sfn); 11478193Smckusick exit(EX_USAGE); 11488193Smckusick } 11498193Smckusick handlekill(){ /* SIGTERM signal */ 11508193Smckusick long t; 11518193Smckusick /* 11528193Smckusick t = gettime(); 11538193Smckusick dumpit(t); 11548193Smckusick */ 11558193Smckusick # ifdef NETLDISC 11568193Smckusick /* turn off net line discipline if possible */ 11578193Smckusick netd.dp_linedis = 0; 11588193Smckusick ioctl(netd.dp_linefd,TIOCSETD,&netd.dp_linedis); 11598193Smckusick close(netd.dp_linefd); 11608193Smckusick printf("Network line discipline turned off.\n"); 11618193Smckusick # endif NETLDISC 11628193Smckusick exit(EX_OK); /* kill myself */ 11638193Smckusick } 11648193Smckusick 11658193Smckusick /* check a request to see if it is an acct pair */ 11668193Smckusick /* returns 1 if it is, 0 if not */ 11678193Smckusick static facctpaircheck(phd) 11688193Smckusick register struct header *phd; 11698193Smckusick { 11708193Smckusick return(0); 11718193Smckusick } 11728193Smckusick 1173