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