1*8193Smckusick static char sccsid[] = "@(#)netdaemon.c 4.1 (Berkeley) 09/12/82"; 2*8193Smckusick 3*8193Smckusick /* sccs id variable */ 4*8193Smckusick static char *netdaemon_sid = "@(#)netdaemon.c 1.10"; 5*8193Smckusick 6*8193Smckusick /* 7*8193Smckusick 8*8193Smckusick The daemon program that runs the network. 9*8193Smckusick 10*8193Smckusick Usage: 11*8193Smckusick netdaemon -m mach [-r readfd] [-w writefd] [-d] [-h] 12*8193Smckusick [-os] [-or] [-ou num] [-p len] [-8] [-l] 13*8193Smckusick 14*8193Smckusick Must be started by root. 15*8193Smckusick Options: 16*8193Smckusick -d turn debugging on 17*8193Smckusick -h use high-speed link (not implemented yet) 18*8193Smckusick -l don't use net line discipline, even if available 19*8193Smckusick -m mach remote machine is mach (required) 20*8193Smckusick -os only send 21*8193Smckusick -or only receive 22*8193Smckusick -ou num only send things with uid = num 23*8193Smckusick -p num length of packet 24*8193Smckusick -r num if simulute w/pipes, read from num 25*8193Smckusick -w num if simulate w/pipes, write on num 26*8193Smckusick */ 27*8193Smckusick 28*8193Smckusick # include "defs.h" 29*8193Smckusick /* take a time, adjust to be in PST, and divide by no of secs in a day */ 30*8193Smckusick /* adjust by 10 mins, and day is considered to begin at 3AM */ 31*8193Smckusick /* (6*3600 = 21600) + 17400 = 39000 */ 32*8193Smckusick /* number of seconds in a day, usually 86400L */ 33*8193Smckusick # define nsecday 86400L 34*8193Smckusick /* number of days since time began */ 35*8193Smckusick # define numdays(S) ((S - 39000L)/nsecday) 36*8193Smckusick /* set my priority to normal */ 37*8193Smckusick # define RENICE0() { if (getuid() == 0) { nice(-40); nice(20); nice(0); } } 38*8193Smckusick 39*8193Smckusick /* global variables */ 40*8193Smckusick extern char **environ; 41*8193Smckusick struct dumpstruc dump; 42*8193Smckusick struct bstruct btable[]; 43*8193Smckusick struct daemonparms netd; 44*8193Smckusick struct userinfo status; 45*8193Smckusick 46*8193Smckusick /* local variables */ 47*8193Smckusick static long length; 48*8193Smckusick static FILE *dir; 49*8193Smckusick /* static char sheader[] = "ABCDE"; */ 50*8193Smckusick static char tempfile[]= TEMPFILE; 51*8193Smckusick static char publogfile[]= PUBLOGFILE; 52*8193Smckusick static struct stat statbuf; 53*8193Smckusick static struct direct dirbuf; 54*8193Smckusick int handlekill(); 55*8193Smckusick static char frommach; 56*8193Smckusick long linechars(); 57*8193Smckusick 58*8193Smckusick main(argc,argv) 59*8193Smckusick char **argv; { 60*8193Smckusick register int i; 61*8193Smckusick long ltime,t; 62*8193Smckusick char buf[100]; 63*8193Smckusick 64*8193Smckusick nice(-1); 65*8193Smckusick if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 66*8193Smckusick signal(SIGHUP, handlekill); 67*8193Smckusick if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 68*8193Smckusick signal(SIGQUIT, handlekill); 69*8193Smckusick if (signal(SIGINT, SIG_IGN) != SIG_IGN) 70*8193Smckusick signal(SIGINT, handlekill); 71*8193Smckusick if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 72*8193Smckusick signal(SIGTERM, handlekill); 73*8193Smckusick debugflg = DBV; 74*8193Smckusick setupdaemon(argc,argv); 75*8193Smckusick /* now running alone as a daemon */ 76*8193Smckusick /* 77*8193Smckusick for(i=0; i<15; i++)close(i); 78*8193Smckusick signal(SIGHUP,SIG_IGN); 79*8193Smckusick signal(SIGQUIT,SIG_IGN); 80*8193Smckusick signal(SIGINT,SIG_IGN); 81*8193Smckusick */ 82*8193Smckusick /* set the umask to a reasonable value */ 83*8193Smckusick umask( 022 ); 84*8193Smckusick senddir[strlen(senddir)-1] = remote; /* choose dir */ 85*8193Smckusick if(chdir(senddir) < 0){ 86*8193Smckusick perror(senddir); 87*8193Smckusick exit(EX_OSFILE); 88*8193Smckusick } 89*8193Smckusick dir = fopen(senddir,"r"); 90*8193Smckusick if(dir == NULL){ 91*8193Smckusick perror(senddir); 92*8193Smckusick exit(EX_OSFILE); 93*8193Smckusick } 94*8193Smckusick mktemp(tempfile); 95*8193Smckusick tempfile[strlen(tempfile) - 7] = remote; 96*8193Smckusick ltime = gettime(); 97*8193Smckusick if(ltime == 0L) 98*8193Smckusick fprintf(stderr,"The network says 'The clock is set wrong.'\n"); 99*8193Smckusick sprintf(buf,"net restarted to %s %d %s",longname(remote), 100*8193Smckusick getpid(),ctime(<ime)); 101*8193Smckusick dump.longtime = ltime; 102*8193Smckusick dump.lastndays = numdays(ltime); 103*8193Smckusick addtolog(remote,buf); 104*8193Smckusick addtopublic(buf); 105*8193Smckusick fprintf(stderr,buf); 106*8193Smckusick if(!debugflg)fclose(stderr); 107*8193Smckusick sendpurge(); 108*8193Smckusick mainloop(); 109*8193Smckusick /* never returns */ 110*8193Smckusick } 111*8193Smckusick /* the main loop of the daemon, alternatively rcv then send, if poss.*/ 112*8193Smckusick mainloop(){ 113*8193Smckusick register int i; 114*8193Smckusick 115*8193Smckusick for(;;){ /* begin reading file */ 116*8193Smckusick debug("daemon %c %d\n",remote,getpid()); 117*8193Smckusick /* first receive */ 118*8193Smckusick if(netd.dp_sndorcv >= 0){ /* if we can receive */ 119*8193Smckusick i = netrcv(); 120*8193Smckusick if(i == -1)dump.nabnormal++; 121*8193Smckusick } 122*8193Smckusick /* now look to send */ 123*8193Smckusick if(netd.dp_sndorcv <= 0) /* if we can send */ 124*8193Smckusick netsend(); 125*8193Smckusick /* print out statistics if the right time */ 126*8193Smckusick printstat(); 127*8193Smckusick dump.nloop++; 128*8193Smckusick } 129*8193Smckusick } 130*8193Smckusick /* this code is a little strange because some machines 131*8193Smckusick seem to have trouble having the date set, and time() 132*8193Smckusick returns 0 until somebody remembers to set the date */ 133*8193Smckusick printstat(){ 134*8193Smckusick long thisndays, thistime; 135*8193Smckusick thistime = gettime(); 136*8193Smckusick thisndays = numdays(thistime); 137*8193Smckusick if(dump.longtime == 0L){ 138*8193Smckusick dump.longtime = thistime; 139*8193Smckusick dump.lastndays = thisndays; 140*8193Smckusick return; 141*8193Smckusick } 142*8193Smckusick if(thisndays == dump.lastndays + 1L) dumpit(thistime); 143*8193Smckusick dump.lastndays = thisndays; 144*8193Smckusick } 145*8193Smckusick /* look for files to send */ 146*8193Smckusick netsend(){ 147*8193Smckusick static long lasttime = 0; 148*8193Smckusick static char nleft = 1; 149*8193Smckusick long lFileLen,diff; 150*8193Smckusick double drate; 151*8193Smckusick register unsigned uid,uidBest; 152*8193Smckusick char *sdate,*sn,*swait; 153*8193Smckusick long ot,nt,filesize; 154*8193Smckusick register int i; 155*8193Smckusick char stemp[20]; 156*8193Smckusick static char jname[FNS]; 157*8193Smckusick 158*8193Smckusick debug("ck send"); 159*8193Smckusick if(stat(senddir,&statbuf) < 0){ 160*8193Smckusick error("%s %s",senddir,sys_errlist[errno]); 161*8193Smckusick return; 162*8193Smckusick } 163*8193Smckusick if(statbuf.st_mtime == lasttime && nleft == 0)return; /* no need to search */ 164*8193Smckusick lasttime = statbuf.st_mtime; 165*8193Smckusick fseek(dir,0L,0); 166*8193Smckusick lFileLen = 10000000L; 167*8193Smckusick nleft = 0; 168*8193Smckusick while(fread(&dirbuf,1,sizeof dirbuf,dir) == sizeof dirbuf){ 169*8193Smckusick if(dirbuf.d_ino == 0 170*8193Smckusick || dirbuf.d_name[0] != 'c' 171*8193Smckusick || dirbuf.d_name[1] != 'f' 172*8193Smckusick || dirbuf.d_name[2] != remote 173*8193Smckusick || stat(dirbuf.d_name,&statbuf) < 0 174*8193Smckusick || statbuf.st_mode == 0) 175*8193Smckusick continue; 176*8193Smckusick dirbuf.d_name[0] = 'd'; 177*8193Smckusick if(stat(dirbuf.d_name,&statbuf) < 0 || statbuf.st_mode == 0) 178*8193Smckusick continue; 179*8193Smckusick uid = guid(statbuf.st_uid,statbuf.st_gid); 180*8193Smckusick if(netd.dp_onlyuid != 0 && uid != netd.dp_onlyuid && uid != SUPERUSER 181*8193Smckusick && uid != NUID)continue; 182*8193Smckusick nleft++; 183*8193Smckusick filesize = getsize(&statbuf); 184*8193Smckusick #ifndef DONTHOLDBIG 185*8193Smckusick if( (filesize > MAXDAYFILE) && day() ) { 186*8193Smckusick if( !debugflg ) 187*8193Smckusick continue; 188*8193Smckusick else 189*8193Smckusick debug("sending large file %s\n", dirbuf.d_name ); 190*8193Smckusick } 191*8193Smckusick #endif DONTHOLDBIG 192*8193Smckusick if(lFileLen > filesize){ 193*8193Smckusick lFileLen = filesize; 194*8193Smckusick for(i=0; i<DIRSIZ; i++) 195*8193Smckusick jname[i] = dirbuf.d_name[i]; 196*8193Smckusick uidBest = uid; 197*8193Smckusick } 198*8193Smckusick # ifdef MAXSENDQ 199*8193Smckusick if(nleft > MAXSENDQ)break; 200*8193Smckusick # endif MAXSENDQ 201*8193Smckusick } 202*8193Smckusick if(lFileLen == 10000000L)return; 203*8193Smckusick strcpy(stemp,jname); 204*8193Smckusick stemp[0] = 'c'; 205*8193Smckusick sn = SnFromUid(uidBest); 206*8193Smckusick if(sn == NULL){ 207*8193Smckusick addtolog(remote,"Unknown userid %d\n",uidBest); 208*8193Smckusick addtolog(remote,"Removing %s\n",stemp); 209*8193Smckusick unlink(stemp); 210*8193Smckusick return; 211*8193Smckusick } 212*8193Smckusick addtolog(remote,"^S %s %c: %s ",sn,remote,jname+2); 213*8193Smckusick ot = gettime(); 214*8193Smckusick if(send(jname) == 0)return; 215*8193Smckusick nt = gettime(); 216*8193Smckusick filesize = getsize(&statbuf); 217*8193Smckusick unlink(jname); 218*8193Smckusick unlink(stemp); 219*8193Smckusick diff = nt - ot; 220*8193Smckusick if(diff < 1)diff = 1; /* avoid dividing by zero */ 221*8193Smckusick sdate = ctime(&nt)+4; 222*8193Smckusick sdate[strlen(sdate) -9] = 0; 223*8193Smckusick swait = comptime(ot - statbuf.st_mtime); 224*8193Smckusick jname[3] = jname[2]; 225*8193Smckusick # ifndef NOFP 226*8193Smckusick drate = (double)filesize / (double)diff; 227*8193Smckusick addtolog(remote,"^T%c(%s, %ldb, %ldsec, %4.1fb/sec, w %s)\n", 228*8193Smckusick remote,sdate,filesize, diff,drate, swait); 229*8193Smckusick # else NOFP 230*8193Smckusick addtolog(remote,"^T%c(%s, %ldb, %ldsec, w %s)\n", 231*8193Smckusick remote,sdate,filesize, diff,swait); 232*8193Smckusick # endif NOFP 233*8193Smckusick addtopublic("%s: sent %-8s to %s (%s, %ld b, wait %s)\n", 234*8193Smckusick sdate,sn,longname(remote),jname+3,filesize,swait); 235*8193Smckusick dump.nsend++; 236*8193Smckusick dump.bytetot += filesize; 237*8193Smckusick dump.elaptot += diff; 238*8193Smckusick } 239*8193Smckusick 240*8193Smckusick /* 241*8193Smckusick day() returns 1 if the time is between 6AM and 12PM 242*8193Smckusick */ 243*8193Smckusick day() 244*8193Smckusick { 245*8193Smckusick int hour; 246*8193Smckusick long t; 247*8193Smckusick char *ctime(); 248*8193Smckusick 249*8193Smckusick time( &t ); 250*8193Smckusick sscanf( ctime( &t ), "%*s%*s%*s%2d", &hour ); 251*8193Smckusick if( (hour>=0) && (hour<6) ) 252*8193Smckusick return( 0 ); /* night */ 253*8193Smckusick else 254*8193Smckusick return( 1 ); /* day */ 255*8193Smckusick } 256*8193Smckusick 257*8193Smckusick send(jname) 258*8193Smckusick char *jname; 259*8193Smckusick { /* push those bytes */ 260*8193Smckusick /* returns 0 if send fails, 1 otherwise */ 261*8193Smckusick register int n; 262*8193Smckusick int i; 263*8193Smckusick long lsize; 264*8193Smckusick char mbuf[20], buf[MAXNBUF]; 265*8193Smckusick register char *p; 266*8193Smckusick register FILE *jfile; 267*8193Smckusick 268*8193Smckusick debug("send %s",jname); 269*8193Smckusick if(stat(jname,&statbuf) < 0)goto sfail; 270*8193Smckusick lsize = getsize(&statbuf); 271*8193Smckusick if(lsize < MINSIZE){ /* all files are at least this long */ 272*8193Smckusick unlink(jname); 273*8193Smckusick jname[0] = 'c'; 274*8193Smckusick unlink(jname); 275*8193Smckusick return(1); 276*8193Smckusick } 277*8193Smckusick jfile = fopen(jname,"r"); 278*8193Smckusick if(jfile == NULL)goto sfail; 279*8193Smckusick /* 280*8193Smckusick strcpy(mbuf,sheader); 281*8193Smckusick i = strlen(sheader); 282*8193Smckusick p = (char *)&lsize; 283*8193Smckusick lsize = fixuplong(lsize); 284*8193Smckusick mbuf[i] = *p++; 285*8193Smckusick mbuf[i+1] = *p++; 286*8193Smckusick mbuf[i+2] = *p++; 287*8193Smckusick mbuf[i+3] = *p++; 288*8193Smckusick i = i + 4; 289*8193Smckusick sendreset(); 290*8193Smckusick */ 291*8193Smckusick initseqno(); 292*8193Smckusick sprintf(mbuf,"|%08ld|",lsize); 293*8193Smckusick i = 10; 294*8193Smckusick if(xwrite(mbuf,i) == WRITEFAIL)goto bwrite; 295*8193Smckusick while((n=read(fileno(jfile),buf,MAXNBUF)) > 0) 296*8193Smckusick if(xwrite(buf,n) == WRITEFAIL)goto bwrite; 297*8193Smckusick fclose(jfile); 298*8193Smckusick debug("end send"); 299*8193Smckusick return(1); 300*8193Smckusick bwrite: 301*8193Smckusick dump.nsendfail++; 302*8193Smckusick fclose(jfile); 303*8193Smckusick addtolog(remote,"^F%c\n",remote); 304*8193Smckusick return(0); 305*8193Smckusick sfail: 306*8193Smckusick error("%s: %s",jname,sys_errlist[errno]); 307*8193Smckusick dump.nsendfail++; 308*8193Smckusick return(0); 309*8193Smckusick } 310*8193Smckusick netrcv(){ 311*8193Smckusick /* returns -2 in normal fail, -1 in abnormal fail, >= 0 otherwise */ 312*8193Smckusick char sin; 313*8193Smckusick char mgetc(), *s; 314*8193Smckusick register int n; 315*8193Smckusick char c; 316*8193Smckusick int i, dummy, pid; 317*8193Smckusick unsigned rcode; 318*8193Smckusick long otime,olength,diff,rcvfinish,nt; 319*8193Smckusick double r; 320*8193Smckusick char hbuf[20], buf[MAXNBUF]; 321*8193Smckusick register FILE *temp; 322*8193Smckusick static struct header hd; 323*8193Smckusick 324*8193Smckusick initseqno(); 325*8193Smckusick /* 326*8193Smckusick n = nread(hbuf,strlen(sheader)); 327*8193Smckusick if(n == BROKENREAD)return(-2); 328*8193Smckusick if(n != strlen(sheader) || strcmp(sheader,hbuf) != 0){ 329*8193Smckusick error("wrong head %d %s",n,hbuf); 330*8193Smckusick return(-1); 331*8193Smckusick } 332*8193Smckusick n = nread(&length,4); 333*8193Smckusick length = fixuplong(length); 334*8193Smckusick */ 335*8193Smckusick n = nread(hbuf,10); 336*8193Smckusick if(n == BROKENREAD)return(-2); 337*8193Smckusick if(n != 10){ 338*8193Smckusick error("bad length nread %d",n); 339*8193Smckusick return(-1); 340*8193Smckusick } 341*8193Smckusick hbuf[10] = 0; 342*8193Smckusick if(hbuf[0] != '|' || hbuf[9] != '|'){ 343*8193Smckusick error("poor format %s",hbuf); 344*8193Smckusick return(-1); 345*8193Smckusick } 346*8193Smckusick hbuf[9] = 0; 347*8193Smckusick length = atol(hbuf+1); 348*8193Smckusick if(length < 0 || length > 100000000L){ 349*8193Smckusick error("bad length %ld",length); 350*8193Smckusick return(-1); 351*8193Smckusick } 352*8193Smckusick dump.braw = 4; 353*8193Smckusick olength = length; 354*8193Smckusick otime = gettime(); 355*8193Smckusick debug("length = %ld\n",length); 356*8193Smckusick 357*8193Smckusick /* 358*8193Smckusick begin parsing header 359*8193Smckusick 360*8193Smckusick from local to remote (requests) 361*8193Smckusick code net option reason 362*8193Smckusick q normal request 363*8193Smckusick y -y simply skips login check (used by netlpr) 364*8193Smckusick 365*8193Smckusick from remote to local 366*8193Smckusick code net option reason 367*8193Smckusick w -w message to be written/mailed back 368*8193Smckusick s -z normal response 369*8193Smckusick */ 370*8193Smckusick 371*8193Smckusick i = readhd(&hd); 372*8193Smckusick if(i == -3)goto forw; /* being forwarded thru us */ 373*8193Smckusick if(i != 0)return(i); 374*8193Smckusick 375*8193Smckusick strcpy(status.login, hd.hd_snto); 376*8193Smckusick strcpy(status.localname,hd.hd_snfrom); 377*8193Smckusick 378*8193Smckusick demask(hd.hd_spasswd); 379*8193Smckusick 380*8193Smckusick s = hd.hd_scmdvirt; 381*8193Smckusick while(*s && *s != ' ')s++; 382*8193Smckusick c = *s; 383*8193Smckusick *s = 0; 384*8193Smckusick if(strcmp(hd.hd_scmdvirt,"netlpr") == 0)dump.nnetlpr++; 385*8193Smckusick else if(strcmp(hd.hd_scmdvirt,"netmail") == 0)dump.nnetmail++; 386*8193Smckusick else if(strcmp(hd.hd_scmdvirt,"mail") == 0)dump.nsmail++; 387*8193Smckusick else if(strcmp(hd.hd_scmdvirt,"netcp") == 0)dump.nnetcp++; 388*8193Smckusick else if(strcmp(hd.hd_scmdvirt,"response") == 0)dump.nresp++; 389*8193Smckusick else dump.nnet++; 390*8193Smckusick *s = c; 391*8193Smckusick 392*8193Smckusick printhd(&hd); 393*8193Smckusick 394*8193Smckusick /* any chars left are data */ 395*8193Smckusick forw: 396*8193Smckusick sin = 0; 397*8193Smckusick if(length > 0){ /* make a temp input file */ 398*8193Smckusick increment(tempfile); 399*8193Smckusick temp = fopen(tempfile,"w"); 400*8193Smckusick if(temp == NULL){ 401*8193Smckusick error("%s %s",tempfile,sys_errlist[errno]); 402*8193Smckusick return(-1); 403*8193Smckusick } 404*8193Smckusick chmod(tempfile,0600); 405*8193Smckusick if(hd.hd_mchto != local){ 406*8193Smckusick fprintf(temp,"%c :%c :",hd.hd_code,hd.hd_mchto); 407*8193Smckusick fflush(temp); 408*8193Smckusick } 409*8193Smckusick /* this is the loop to read in all the data */ 410*8193Smckusick while((n = mread(buf,MAXNBUF)) > 0) 411*8193Smckusick if(write(fileno(temp),buf,n) != n){ 412*8193Smckusick error("%s %s",tempfile,sys_errlist[errno]); 413*8193Smckusick fclose(temp); 414*8193Smckusick unlink(tempfile); 415*8193Smckusick return(-1); 416*8193Smckusick }; 417*8193Smckusick fclose(temp); 418*8193Smckusick if(n == BROKENREAD || length > 0){ 419*8193Smckusick unlink(tempfile); 420*8193Smckusick return(-2); 421*8193Smckusick } 422*8193Smckusick sin = 1; 423*8193Smckusick if(hd.hd_mchto != local){ 424*8193Smckusick diff = gettime() - otime; 425*8193Smckusick if(diff < 1)diff = 1; /* avoid dividing by 0 */ 426*8193Smckusick # ifndef NOFP 427*8193Smckusick r = olength; 428*8193Smckusick r = r/diff; 429*8193Smckusick addtolog(remote,"^P(to %c, %ldb, %ldsec, %4.1fb/sec)\n", 430*8193Smckusick hd.hd_mchto,olength,diff,r); 431*8193Smckusick # else NOFP 432*8193Smckusick addtolog(remote,"^P(to %c, %ldb, %ldsec)\n", 433*8193Smckusick hd.hd_mchto,olength,diff); 434*8193Smckusick # endif NOFP 435*8193Smckusick dump.npass++; 436*8193Smckusick dump.bytetot += olength; 437*8193Smckusick dump.elaptot += diff; 438*8193Smckusick while((pid = fork()) == -1)sleep(2); 439*8193Smckusick if(pid == 0){ 440*8193Smckusick # ifndef V6 441*8193Smckusick RENICE0(); 442*8193Smckusick # endif V6 443*8193Smckusick #ifdef CCV7 444*8193Smckusick /* make sure the spawned child has it's own 445*8193Smckusick group process to avoid the nasty 446*8193Smckusick "try again" message 447*8193Smckusick */ 448*8193Smckusick setpgrp(); 449*8193Smckusick #endif CCV7 450*8193Smckusick execl(netcmd,"net","-x","-m",longname(hd.hd_mchto), 451*8193Smckusick "-s",tempfile,0); 452*8193Smckusick error("%s: %s",netcmd,sys_errlist[errno]); 453*8193Smckusick exit(EX_UNAVAILABLE); 454*8193Smckusick } 455*8193Smckusick wait(&rcode); 456*8193Smckusick unlink(tempfile); 457*8193Smckusick rcode >>= 8; 458*8193Smckusick if(rcode != 0) 459*8193Smckusick error("pass-thru rcode %d"); 460*8193Smckusick debug("passthru to %c code %c rcode %d", 461*8193Smckusick hd.hd_mchto,hd.hd_code,rcode); 462*8193Smckusick return(1); 463*8193Smckusick } 464*8193Smckusick } 465*8193Smckusick if(length > 0){error("file too short"); return(-1); } 466*8193Smckusick rcvfinish = gettime(); 467*8193Smckusick 468*8193Smckusick while((pid = fork()) == -1)sleep(2); 469*8193Smckusick if(pid > 0){ 470*8193Smckusick wait(&dummy); 471*8193Smckusick return(1); /* normal return */ 472*8193Smckusick } 473*8193Smckusick /* this is a child, who will go ahead and execute the command */ 474*8193Smckusick /* running uid=0 at this point */ 475*8193Smckusick # ifndef V6 476*8193Smckusick RENICE0(); 477*8193Smckusick # endif V6 478*8193Smckusick /* nice(0 set back to 0 */ 479*8193Smckusick #ifdef CCV7 480*8193Smckusick /* separate group process */ 481*8193Smckusick setpgrp(); 482*8193Smckusick #endif CCV7 483*8193Smckusick 484*8193Smckusick while((pid = fork()) == -1)sleep(2); 485*8193Smckusick if(pid != 0)exit(EX_OK); 486*8193Smckusick 487*8193Smckusick /* child process which forks and waits */ 488*8193Smckusick mktemp(resfile); 489*8193Smckusick while((pid = fork()) == -1)sleep(2); 490*8193Smckusick if(pid == 0){ 491*8193Smckusick /* child */ 492*8193Smckusick strcpy(status.loginshell,Bsh); 493*8193Smckusick frommach = hd.hd_mchfrom; 494*8193Smckusick n = check(&hd,(hd.hd_code == 'q')); 495*8193Smckusick if(!n)errormsg(TRUE,&hd,NULL, 496*8193Smckusick "Bad remote login/password '%s'",hd.hd_snto); 497*8193Smckusick temp = fopen(resfile,"w"); 498*8193Smckusick if(temp == NULL) 499*8193Smckusick errormsg(TRUE,&hd,NULL, 500*8193Smckusick "Create file %s: %s",resfile,sys_errlist[errno]); 501*8193Smckusick fclose(temp); 502*8193Smckusick chmod(resfile,0600); 503*8193Smckusick mchown(resfile,status.muid,status.mgid); 504*8193Smckusick if(sin) 505*8193Smckusick mchown(tempfile,status.muid,status.mgid); 506*8193Smckusick else tempfile[0] = 0; 507*8193Smckusick setgid(status.mgid); 508*8193Smckusick setuid(status.muid); 509*8193Smckusick /* after this point our gid, uid is the target user's */ 510*8193Smckusick excmd(&hd,resfile,tempfile); 511*8193Smckusick } 512*8193Smckusick /* parent */ 513*8193Smckusick wait(&rcode); 514*8193Smckusick rcode = (((rcode&077400) >>8) &0177); 515*8193Smckusick /* 516*8193Smckusick fclose(stdin); 517*8193Smckusick fclose(stdout); 518*8193Smckusick fclose(stderr); 519*8193Smckusick */ 520*8193Smckusick if(sin)unlink(tempfile); 521*8193Smckusick /* 522*8193Smckusick now send something back to the sender 523*8193Smckusick unless this was a response (file or message) 524*8193Smckusick */ 525*8193Smckusick if((hd.hd_code == 'q' || hd.hd_code == 'y') 526*8193Smckusick && (hd.hd_srespfile[0] || !hd.hd_fnonotify)) 527*8193Smckusick sndresponse(&hd,rcode); 528*8193Smckusick unlink(resfile); 529*8193Smckusick s = ctime(&rcvfinish); 530*8193Smckusick s += 4; 531*8193Smckusick s[strlen(s) -8] = 0; 532*8193Smckusick diff = rcvfinish - otime; 533*8193Smckusick if(diff < 1)diff = 1; /* avoid dividing by zero */ 534*8193Smckusick dump.bytetot += olength; 535*8193Smckusick dump.elaptot += diff; 536*8193Smckusick sprintf(buf,"%s rcv %c:%-8s (%s)", 537*8193Smckusick s,hd.hd_mchfrom,hd.hd_snfrom,hd.hd_snto); 538*8193Smckusick addtolog(remote,"%s C: %s\n",buf,hd.hd_scmdvirt); 539*8193Smckusick addtopublic("%s R: %d C: %s\n",buf,rcode,hd.hd_scmdvirt); 540*8193Smckusick nt = rcvfinish - hd.hd_ltimesent; 541*8193Smckusick buf[0] = 0; 542*8193Smckusick if(nt > 0L)sprintf(buf," took (%s)",comptime(nt)); 543*8193Smckusick # ifndef NOFP 544*8193Smckusick r = olength; 545*8193Smckusick r = r/diff; 546*8193Smckusick addtolog(remote,"\t\tR: %d%s %ldb %ldsec %4.1fb/sec\n", 547*8193Smckusick rcode,buf,olength,diff,r); 548*8193Smckusick r = dump.braw; 549*8193Smckusick r = r/diff; 550*8193Smckusick addtolog(remote,"\t\t%4.1frb/sec %4.1f%% use\n",r,(r/linechars())*100L); 551*8193Smckusick # else NOFP 552*8193Smckusick addtolog(remote,"\t\tR: %d%s %ldb %ldsec\n", 553*8193Smckusick rcode,buf,olength,diff); 554*8193Smckusick # endif NOFP 555*8193Smckusick exit(EX_OK); 556*8193Smckusick /*UNREACHED*/ 557*8193Smckusick } 558*8193Smckusick long linechars(){ 559*8193Smckusick if(netd.dp_inspeed == 13)return(960L); 560*8193Smckusick else return(120L); 561*8193Smckusick } 562*8193Smckusick /* 563*8193Smckusick execute the user's command 564*8193Smckusick this procedure is executed with uid, gid of the user 565*8193Smckusick */ 566*8193Smckusick excmd(phd,tempresfile,tempinfile) 567*8193Smckusick register struct header *phd; 568*8193Smckusick char *tempresfile, *tempinfile; 569*8193Smckusick { 570*8193Smckusick FILE *fd; 571*8193Smckusick int i, uid; 572*8193Smckusick register char *s, c; 573*8193Smckusick 574*8193Smckusick uid = getuid(); 575*8193Smckusick uid = uidmask(uid); 576*8193Smckusick status.muid = uidmask(status.muid); 577*8193Smckusick if(uid != status.muid)error("setuid fails"); 578*8193Smckusick debug("uid: %u, gid: %u\n",uid,status.mgid); 579*8193Smckusick /* check for allowed root commands, for security reasons */ 580*8193Smckusick if(uid == SUPERUSER){ 581*8193Smckusick s = phd->hd_scmdact; 582*8193Smckusick while(*s && *s != ' ')s++; 583*8193Smckusick c = *s; 584*8193Smckusick *s = 0; 585*8193Smckusick /* these are the only commands root may execute */ 586*8193Smckusick if(strcmp(phd->hd_scmdact,"cat") != 0 587*8193Smckusick && strcmp(phd->hd_scmdact,MWRITECMD) != 0 588*8193Smckusick && strcmp(phd->hd_scmdact,"/bin/cat") != 0 589*8193Smckusick && strcmp(phd->hd_scmdact,"netrm") != 0 590*8193Smckusick && strcmp(phd->hd_scmdact,"/usr/lib/tq") != 0 591*8193Smckusick && strcmp(phd->hd_scmdact,"/usr/cc/lib/tq") != 0 592*8193Smckusick && strcmp(phd->hd_scmdact,"/usr/lib/rtrrm") != 0 593*8193Smckusick && strcmp(phd->hd_scmdact,"/usr/cc/lib/rtrrm") != 0 594*8193Smckusick && strcmp(phd->hd_scmdact,"lpr") != 0) 595*8193Smckusick errormsg(TRUE,phd,tempresfile, 596*8193Smckusick "Not allowed to execute '%s' as root", 597*8193Smckusick phd->hd_scmdact); 598*8193Smckusick *s = c; 599*8193Smckusick } 600*8193Smckusick if(chdir(status.dir) < 0) 601*8193Smckusick errormsg(TRUE,phd,tempresfile, 602*8193Smckusick "chdir %s: %s",status.dir,sys_errlist[errno]); 603*8193Smckusick setenv(status.dir); /* set up v7 environment */ 604*8193Smckusick if(tempinfile[0])mreopen(TRUE,phd,tempresfile,tempinfile,"r",stdin); 605*8193Smckusick else if(phd->hd_sinfile[0])mreopen(TRUE,phd,tempresfile,phd->hd_sinfile,"r",stdin); 606*8193Smckusick else mreopen(TRUE,phd,tempresfile,"/dev/null","r",stdin); 607*8193Smckusick if(phd->hd_code == 's' && phd->hd_soutfile[0]){ 608*8193Smckusick if(stat(phd->hd_soutfile,&statbuf) < 0 609*8193Smckusick || getsize(&statbuf) != 0) 610*8193Smckusick errormsg(FALSE,phd,tempresfile,"Bad result file '%s'",phd->hd_soutfile); 611*8193Smckusick mreopen(TRUE,phd,tempresfile,phd->hd_soutfile,"w",stdout); 612*8193Smckusick } 613*8193Smckusick else if(phd->hd_soutfile[0]){ 614*8193Smckusick fd = fopen(phd->hd_soutfile,"w"); 615*8193Smckusick if(fd == NULL) 616*8193Smckusick errormsg(TRUE,phd,tempresfile,"Open file %s: %s", 617*8193Smckusick phd->hd_soutfile,sys_errlist[errno]); 618*8193Smckusick fclose(fd); 619*8193Smckusick mreopen(TRUE,phd,tempresfile,phd->hd_soutfile,"w",stdout); 620*8193Smckusick } 621*8193Smckusick else mreopen(TRUE,phd,tempresfile,tempresfile,"a",stdout); 622*8193Smckusick debug("exec '%s'\n",phd->hd_scmdact); 623*8193Smckusick if(debugflg == 0){ 624*8193Smckusick /* cheat */ 625*8193Smckusick close(2); 626*8193Smckusick dup(1); 627*8193Smckusick /* 628*8193Smckusick mreopen(TRUE,phd,tempresfile,tempresfile,"a",stderr); 629*8193Smckusick */ 630*8193Smckusick } 631*8193Smckusick for(i=3;i<15;i++)close(i); 632*8193Smckusick if(strcmp(phd->hd_scmdact,"cat") == 0 633*8193Smckusick || strcmp(phd->hd_scmdact,"/bin/cat") == 0)excat(); 634*8193Smckusick do { 635*8193Smckusick mexecl(status.loginshell,"sh","-c",phd->hd_scmdact,0); 636*8193Smckusick sleep(2); 637*8193Smckusick } while(errno == ETXTBSY); 638*8193Smckusick perror(status.loginshell); 639*8193Smckusick exit(EX_UNAVAILABLE); 640*8193Smckusick } 641*8193Smckusick /* 642*8193Smckusick send back a response 643*8193Smckusick 644*8193Smckusick if errormsg was called the resfile should be unlinked, 645*8193Smckusick to avoid two messages being sent there 646*8193Smckusick */ 647*8193Smckusick sndresponse(phd,rcode) 648*8193Smckusick unsigned rcode; 649*8193Smckusick struct header *phd; 650*8193Smckusick { 651*8193Smckusick char cmdstr[BUFSIZ], buf[BUFSIZ]; 652*8193Smckusick int dummy; 653*8193Smckusick long maxfile = MAXFILELARGE; 654*8193Smckusick /* send response back if a response file 655*8193Smckusick was given or if mail/write is allowed */ 656*8193Smckusick if(stat(resfile,&statbuf) < 0){ 657*8193Smckusick error("%s %s",resfile,sys_errlist[errno]); 658*8193Smckusick return; 659*8193Smckusick } 660*8193Smckusick if(getsize(&statbuf) >= maxfile){ 661*8193Smckusick errormsg(TRUE,phd,"Result file too large - not sent"); 662*8193Smckusick return; 663*8193Smckusick } 664*8193Smckusick if(getsize(&statbuf) == 0){ 665*8193Smckusick /* response file specified, no output generated */ 666*8193Smckusick if(phd->hd_srespfile[0] != 0)return; 667*8193Smckusick /* quiet option - no output and a rcode of 0 */ 668*8193Smckusick if(rcode == 0 && phd->hd_fquiet)return; 669*8193Smckusick } 670*8193Smckusick /* use both old and new mwrite parm lists */ 671*8193Smckusick 672*8193Smckusick if(phd->hd_srespfile[0]) 673*8193Smckusick sprintf(cmdstr,"-o %s cat",phd->hd_srespfile); 674*8193Smckusick else sprintf(cmdstr, 675*8193Smckusick "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -c \"'%s'\" -y %s -e %ld -r %d", 676*8193Smckusick MWRITECMD, phd->hd_snfrom,phd->hd_sttyname,phd->hd_lttytime, 677*8193Smckusick phd->hd_mchto,phd->hd_snto, phd->hd_scmdvirt,phd->hd_ltimesent-TIMEBASE, 678*8193Smckusick phd->hd_addrfrom, phd->hd_addrto, phd->hd_lttytime, 679*8193Smckusick phd->hd_scmdvirt, phd->hd_sttyname, phd->hd_ltimesent-TIMEBASE, rcode); 680*8193Smckusick 681*8193Smckusick sprintf(buf,"%s -m%c -z -b -l %s -s %s -c response %s", 682*8193Smckusick netcmd,phd->hd_mchfrom,phd->hd_snfrom,resfile,cmdstr); 683*8193Smckusick dummy = system(buf); /* execute command buf */ 684*8193Smckusick } 685*8193Smckusick 686*8193Smckusick /* 687*8193Smckusick 688*8193Smckusick excat 689*8193Smckusick does nothing more than copy standard input to standard 690*8193Smckusick output, like the cat command, but reports write errors. 691*8193Smckusick Uses getc and putc rather than fwrite and fread because 692*8193Smckusick the latter call getc and putc. 693*8193Smckusick */ 694*8193Smckusick excat(){ 695*8193Smckusick register int n; 696*8193Smckusick char buf[BUFSIZ]; 697*8193Smckusick 698*8193Smckusick errno = 0; 699*8193Smckusick while((n = read(0,buf,BUFSIZ)) > 0){ 700*8193Smckusick if(write(1,buf,n) != n){ 701*8193Smckusick perror("filecat: stdout"); 702*8193Smckusick exit(EX_OSFILE); 703*8193Smckusick } 704*8193Smckusick } 705*8193Smckusick if(errno){ 706*8193Smckusick perror("filecat: stdin"); 707*8193Smckusick exit(EX_OSFILE); 708*8193Smckusick } 709*8193Smckusick exit(EX_OK); 710*8193Smckusick } 711*8193Smckusick /* returns errors for netrcv() */ 712*8193Smckusick static readhd(phd) 713*8193Smckusick register struct header *phd; 714*8193Smckusick { 715*8193Smckusick char cflag, sbuf[BUFSIZ], parmlist[PARMLIST], *cptr; 716*8193Smckusick int i, code; 717*8193Smckusick code = mgetc(); 718*8193Smckusick phd->hd_mchto = mgetc(); 719*8193Smckusick if(code != 'q' && code != 'y' && code != 'w' && code != 's'){ 720*8193Smckusick error("bad code"); 721*8193Smckusick return(-1); 722*8193Smckusick } 723*8193Smckusick phd->hd_code = code; 724*8193Smckusick for(i = 0; i < MAXINX; i++) 725*8193Smckusick if(phd->hd_mchto == inxtoch(i)) break; 726*8193Smckusick if(i >= MAXINX){ 727*8193Smckusick error("bad phd->hd_mchto"); 728*8193Smckusick return(-1); 729*8193Smckusick } 730*8193Smckusick if(phd->hd_mchto != local)return(-3); /* being forwarded through us */ 731*8193Smckusick phd->hd_mchfrom = mgetc(); 732*8193Smckusick phd->hd_vmajor = mgetc(); 733*8193Smckusick phd->hd_vminor = mgetc(); 734*8193Smckusick i = 0; 735*8193Smckusick i += mgets(phd->hd_snto,NS); 736*8193Smckusick i += mgets(phd->hd_spasswd,20); 737*8193Smckusick i += mgets(phd->hd_sinfile,FNS); 738*8193Smckusick i += mgets(phd->hd_soutfile,FNS); 739*8193Smckusick i += mgets(phd->hd_srespfile,FNS); 740*8193Smckusick i += mgets(phd->hd_snfrom,NS); 741*8193Smckusick 742*8193Smckusick /* addrfrom is the person who sent this to us, 743*8193Smckusick addrto is the person who received the command, i.e. 744*8193Smckusick addrto is on this machine */ 745*8193Smckusick if(phd->hd_snfrom[0] == 0)strcpy(phd->hd_snfrom,"root"); 746*8193Smckusick sprintf(phd->hd_addrfrom, "%s:%s",longname(phd->hd_mchfrom),phd->hd_snfrom); 747*8193Smckusick sprintf(phd->hd_addrto, "%s:%s",longname(phd->hd_mchto),phd->hd_snto); 748*8193Smckusick 749*8193Smckusick i += mgets(phd->hd_sttyname,20); 750*8193Smckusick if(phd->hd_sttyname[0] == 0)strcpy(phd->hd_sttyname,"/dev/ttyx"); 751*8193Smckusick cflag = mgetc(); 752*8193Smckusick if(!phd->hd_mchfrom || !phd->hd_code || !cflag || !phd->hd_vmajor || !phd->hd_vminor){ 753*8193Smckusick error("mgetc fails"); 754*8193Smckusick return(-1); 755*8193Smckusick } 756*8193Smckusick 757*8193Smckusick cflag -= 'a'; 758*8193Smckusick phd->hd_fnonotify = (cflag & F_NONOTIFY); 759*8193Smckusick phd->hd_fquiet = (cflag & F_QUIET); 760*8193Smckusick 761*8193Smckusick phd->hd_vmajor -= 'a'; 762*8193Smckusick phd->hd_vminor -= 'a'; 763*8193Smckusick 764*8193Smckusick i += mgets(sbuf,BUFSIZ); 765*8193Smckusick phd->hd_lttytime = 0; 766*8193Smckusick sscanf(sbuf,"%lo",&phd->hd_lttytime); 767*8193Smckusick 768*8193Smckusick i += mgets(parmlist,PARMLIST); 769*8193Smckusick #ifdef CRN 770*8193Smckusick cptr = parmlist; 771*8193Smckusick while( *cptr != '(' ) 772*8193Smckusick cptr++; 773*8193Smckusick *cptr = '\0'; 774*8193Smckusick strcpy( phd->hd_ijobno, parmlist ); 775*8193Smckusick *cptr = '('; 776*8193Smckusick #else CRN 777*8193Smckusick strcpy( phd->hd_ijobno, "XYZZ" ); 778*8193Smckusick #endif CRN 779*8193Smckusick /* keep variable parameter list in crn slot */ 780*8193Smckusick parseparmlist(parmlist); 781*8193Smckusick 782*8193Smckusick i += mgets(sbuf,BUFSIZ); /* time sent */ 783*8193Smckusick sscanf(sbuf,"%ld",&phd->hd_ltimesent); 784*8193Smckusick phd->hd_ltimesent += TIMEBASE; 785*8193Smckusick i += mgetcmd(phd->hd_scmdact); 786*8193Smckusick i += mgetcmd(phd->hd_scmdvirt); 787*8193Smckusick if(i != 0){error("mgets fails"); return(-1);} 788*8193Smckusick if(phd->hd_scmdvirt[0] == 0)strcpy(phd->hd_scmdvirt,phd->hd_scmdact); 789*8193Smckusick return(0); 790*8193Smckusick } 791*8193Smckusick /* 792*8193Smckusick check() -- verify login name and password 793*8193Smckusick phd = login,passwd 794*8193Smckusick fverify = 1 if password must check 795*8193Smckusick Returns 1 if password is ok, 0 if not. 796*8193Smckusick */ 797*8193Smckusick check(phd,fverify) /* 1 if OK, 0 if not */ 798*8193Smckusick register struct header *phd; 799*8193Smckusick int fverify; 800*8193Smckusick { 801*8193Smckusick char *sencpasswd, *u, *nullstr = ""; 802*8193Smckusick struct passwd *pwd; 803*8193Smckusick #ifdef CRN 804*8193Smckusick struct gecos *gcos; 805*8193Smckusick #endif CRN 806*8193Smckusick if(phd->hd_snto[0] == 0)return(!fverify); 807*8193Smckusick debug("check: phd->hd_snto = %s\n", phd->hd_snto ); 808*8193Smckusick if(!goodacctname(phd->hd_snto))return(!fverify); 809*8193Smckusick pwd = getpwnam(phd->hd_snto); 810*8193Smckusick debug("got pwd=%d, pwd->pw_passwd = %s\n",pwd, pwd->pw_passwd); 811*8193Smckusick if(pwd == NULL)return(!fverify); 812*8193Smckusick if(*phd->hd_spasswd)sencpasswd = crypt(phd->hd_spasswd,pwd->pw_passwd); 813*8193Smckusick else sencpasswd = nullstr; 814*8193Smckusick debug("check: passwd(rcvd)=%s, passwd(file) = %s, passwd(encrypt)=%s\n", phd->hd_spasswd, pwd->pw_passwd, sencpasswd ); 815*8193Smckusick 816*8193Smckusick status.muid = guid(pwd->pw_uid,pwd->pw_gid); 817*8193Smckusick status.mgid = pwd->pw_gid; 818*8193Smckusick #ifdef CRN 819*8193Smckusick if( (gcos=pwgecos( pwd->pw_gecos )) == NULL ) 820*8193Smckusick strcpy( status.jobno, MAGICCRN ); 821*8193Smckusick else 822*8193Smckusick strcpy( status.jobno, gcos->gc_crn ); 823*8193Smckusick #else CRN 824*8193Smckusick strcpy( status.jobno, "XYZZ"); 825*8193Smckusick #endif CRN 826*8193Smckusick strcpy(status.dir,pwd->pw_dir); 827*8193Smckusick strcpy(status.loginshell,pwd->pw_shell); 828*8193Smckusick u = status.loginshell; 829*8193Smckusick if(u[0] == 0 || strcmp("/bin/sbash",u) == 0)strcpy(u,Bsh); 830*8193Smckusick 831*8193Smckusick getpwdf(pwd); 832*8193Smckusick /* ignore network passwd */ 833*8193Smckusick /* acct is not a pair, acct is not "network", passwd is incorrect, 834*8193Smckusick and verification is requested => passwd not ok */ 835*8193Smckusick if(!facctpaircheck(phd) && strcmp(phd->hd_snto,"network") != 0 836*8193Smckusick && strcmp(pwd->pw_passwd,sencpasswd) != 0 && fverify) 837*8193Smckusick return(0); 838*8193Smckusick return(1); /* otherwise passwd ok */ 839*8193Smckusick } 840*8193Smckusick mread(b,n) 841*8193Smckusick register int n; { 842*8193Smckusick if(length <= 0)return(0); 843*8193Smckusick if(length < n)n = length; 844*8193Smckusick n = nread(b,n); 845*8193Smckusick if(n != BROKENREAD)length -= n; 846*8193Smckusick return(n); 847*8193Smckusick } 848*8193Smckusick char mgetc(){ /* returns 0 if fail */ 849*8193Smckusick register char c; 850*8193Smckusick register int n; 851*8193Smckusick char buf[3]; 852*8193Smckusick if((n=nread(buf,3)) == BROKENREAD)return(0); 853*8193Smckusick if(n != 3){error("bad read %d",n); return(0); } 854*8193Smckusick c = buf[0]; 855*8193Smckusick if(buf[1] != ' ' && buf[1] != ':'){error("Bad char %c",buf[1]); return(0); } 856*8193Smckusick length -= 3; 857*8193Smckusick if(length < 0){error("length wrong2 %ld",length); return(0); } 858*8193Smckusick return(c); 859*8193Smckusick } 860*8193Smckusick /* read in string over the network wire */ 861*8193Smckusick /* put string in s, max length is maxlen */ 862*8193Smckusick mgets(s,maxlen) /* returns 0 if ok, 1 if not */ 863*8193Smckusick int maxlen; 864*8193Smckusick register char *s; { 865*8193Smckusick register char *q; 866*8193Smckusick register int n; 867*8193Smckusick char c; 868*8193Smckusick q = s; 869*8193Smckusick for(;;) { 870*8193Smckusick if((n=nread(&c,1)) == BROKENREAD){ 871*8193Smckusick *s = 0; 872*8193Smckusick error("mgets %s",s); 873*8193Smckusick return(1); 874*8193Smckusick } 875*8193Smckusick if(n == 0)break; 876*8193Smckusick if(c == '\\'){ 877*8193Smckusick if((n=nread(&c,1)) == BROKENREAD){ 878*8193Smckusick *s = 0; 879*8193Smckusick error("mgets %s",s); 880*8193Smckusick return(1); 881*8193Smckusick } 882*8193Smckusick if(n == 0)break; 883*8193Smckusick } 884*8193Smckusick if(c == ' ')break; 885*8193Smckusick if(maxlen-- > 0) *s++ = c; 886*8193Smckusick } 887*8193Smckusick *s = 0; 888*8193Smckusick if(nread(&c,1) == BROKENREAD){ 889*8193Smckusick error("mgets %s",s); 890*8193Smckusick return(1); 891*8193Smckusick } 892*8193Smckusick length -= (s - q + 2); 893*8193Smckusick if(length < 0){error("length wrong1 %ld %s",length,q); return(-1); } 894*8193Smckusick if(maxlen < 0) 895*8193Smckusick error("mgets - string too long"); 896*8193Smckusick return(0); 897*8193Smckusick } 898*8193Smckusick mgetcmd(s) /* returns 0 if succeed, 1 otherwise */ 899*8193Smckusick char *s; { 900*8193Smckusick int i,n; 901*8193Smckusick char c; 902*8193Smckusick i = 0; 903*8193Smckusick for(;;){ 904*8193Smckusick if((n=nread(&c,1)) == BROKENREAD){ 905*8193Smckusick s[i] = 0; 906*8193Smckusick error("mgetcmd %s",s); 907*8193Smckusick return(1); 908*8193Smckusick } 909*8193Smckusick if(n <= 0 || c == '\n')break; 910*8193Smckusick if(c == '\\'){ 911*8193Smckusick if(nread(&c,1) == BROKENREAD){ 912*8193Smckusick s[i] = 0; 913*8193Smckusick error("mgetcmd %s",s); 914*8193Smckusick return(1); 915*8193Smckusick } 916*8193Smckusick length--; 917*8193Smckusick } 918*8193Smckusick s[i++] = c; 919*8193Smckusick length--; 920*8193Smckusick } 921*8193Smckusick s[i] = 0; 922*8193Smckusick length--; 923*8193Smckusick return(0); 924*8193Smckusick } 925*8193Smckusick increment(s) 926*8193Smckusick char *s; { 927*8193Smckusick int i; 928*8193Smckusick char *p; 929*8193Smckusick i = strlen(s) - 1; 930*8193Smckusick while(s[i] == '9')i--; 931*8193Smckusick if(s[i] < '0' || s[i] > '9'){ 932*8193Smckusick p = s+i+1; 933*8193Smckusick while(*p)*p++ = '0'; 934*8193Smckusick return; 935*8193Smckusick } 936*8193Smckusick (s[i])++; 937*8193Smckusick i++; 938*8193Smckusick while(s[i])s[i++] = '0'; 939*8193Smckusick return; 940*8193Smckusick } 941*8193Smckusick /* gather 24-hour stats and mail to STATADDR */ 942*8193Smckusick /* should also gather stats on # error msgs */ 943*8193Smckusick dumpit(currt) 944*8193Smckusick long currt; { 945*8193Smckusick register struct dumpstruc *p = &dump; 946*8193Smckusick register int ntot; 947*8193Smckusick long elapt; 948*8193Smckusick double cputime,utime,stime,bs,rawbs; 949*8193Smckusick char *sstartt; 950*8193Smckusick FILE *fdm; 951*8193Smckusick char froma[30]; 952*8193Smckusick struct tms tbf; 953*8193Smckusick 954*8193Smckusick /* if STATADDR is a file, the mail program this call will 955*8193Smckusick ultimately execute must be able to deal with it, 956*8193Smckusick and the remote mail program must be able to write on the 957*8193Smckusick file, i.e. mode 666 */ 958*8193Smckusick sprintf(froma,"%s=>",longname(local)); 959*8193Smckusick strcat(froma,longname(remote)); 960*8193Smckusick fdm = mailopen(STATADDR,froma,1,0); 961*8193Smckusick if(fdm == NULL)return; 962*8193Smckusick 963*8193Smckusick /* calculate times */ 964*8193Smckusick elapt = currt - dump.longtime; 965*8193Smckusick ntot = p->nnetcp + p->nnetmail + p->nsmail + p->nnetlpr 966*8193Smckusick + p->nresp + p->nnet; 967*8193Smckusick sstartt = ctime(&dump.longtime) + 4; 968*8193Smckusick sstartt[strlen(sstartt) - 9] = 0; 969*8193Smckusick 970*8193Smckusick times(&tbf); 971*8193Smckusick # ifndef NOFP 972*8193Smckusick utime = tbf.tms_utime + tbf.tms_cutime; 973*8193Smckusick stime = tbf.tms_stime + tbf.tms_cstime; 974*8193Smckusick cputime = utime + stime; 975*8193Smckusick if(elapt > 0)cputime = (cputime/elapt) * 100.0; 976*8193Smckusick else cputime = 0.0; 977*8193Smckusick utime = utime/60.0; 978*8193Smckusick stime = stime/60.0; 979*8193Smckusick cputime = cputime/60.0; 980*8193Smckusick bs = p->bytetot; 981*8193Smckusick if(p->elaptot > 0)bs = bs /p->elaptot; 982*8193Smckusick else bs = 0.0; 983*8193Smckusick # endif NOFP 984*8193Smckusick 985*8193Smckusick /* print out the statistics */ 986*8193Smckusick fprintf(fdm,"Subject: %s, %s, time %s\n", 987*8193Smckusick froma,sstartt, comptime(elapt)); 988*8193Smckusick fprintf(fdm,"Command summary:\n"); 989*8193Smckusick fprintf(fdm,"\t# sent %d\t# pass_thru %d\t# rcv %d:\t# netcp %d\n", 990*8193Smckusick p->nsend,p->npass,ntot,p->nnetcp); 991*8193Smckusick fprintf(fdm,"\t# netlpr %d\t# netmail %d\t# sendbmail %d\t# resp %d\n", 992*8193Smckusick p->nnetlpr,p->nnetmail,p->nsmail,p->nresp); 993*8193Smckusick fprintf(fdm,"Protocol summary:\n"); 994*8193Smckusick fprintf(fdm,"\t# pk_sent %d\t# pk_rcv %d\t# b_sent %ld\t# b_rcv %ld\n", 995*8193Smckusick p->npacksent,p->npackrcv,p->nbytesent, p->nbytercv); 996*8193Smckusick fprintf(fdm, 997*8193Smckusick "\t# send_fails %d\t# retrans %d\t# abn %d\t\t# cksum_errs %d\n", 998*8193Smckusick p->nsendfail,p->nretrans, p->nabnormal,p->ncksum); 999*8193Smckusick # ifndef NOFP 1000*8193Smckusick fprintf(fdm,"Load:\tuser %4.1f\tsys %4.1f\tpct %5.2f\trate %6.1f\n", 1001*8193Smckusick utime,stime,cputime,bs); 1002*8193Smckusick rawbs = p->brawtot*100L; 1003*8193Smckusick rawbs = rawbs / linechars(); 1004*8193Smckusick fprintf(fdm,"\trawbytes %ld\tuse %4.1f\n", p->brawtot,rawbs); 1005*8193Smckusick # endif NOFP 1006*8193Smckusick mailclose(fdm); 1007*8193Smckusick 1008*8193Smckusick /* reset counters */ 1009*8193Smckusick p->nbytesent = p->nbytercv = p->elaptot = p->bytetot = 0L; 1010*8193Smckusick p->nretrans = p->nloop = p->nabnormal = p->ncksum = 0; 1011*8193Smckusick p->npacksent = p->npackrcv = p->nnetcp = p->nnetmail = 0; 1012*8193Smckusick p->nsmail = p->nnetlpr = p->nnet = p->npass = 0; 1013*8193Smckusick p->nsend = p->nsendfail = 0; 1014*8193Smckusick dump.longtime = currt; 1015*8193Smckusick } 1016*8193Smckusick /* returns 1 if n is ok, 0 if not */ 1017*8193Smckusick goodacctname(n) 1018*8193Smckusick char *n; { 1019*8193Smckusick int i; 1020*8193Smckusick i = -1; 1021*8193Smckusick while(btable[++i].bname) 1022*8193Smckusick if(strcmp(btable[i].bname,n) == 0 && 1023*8193Smckusick local == btable[i].bmach)return(0); 1024*8193Smckusick return(1); 1025*8193Smckusick } 1026*8193Smckusick demask(s) 1027*8193Smckusick register char *s; { 1028*8193Smckusick /* 1029*8193Smckusick static char buf[20]; 1030*8193Smckusick char skey[30]; 1031*8193Smckusick makeuukey(skey,status.login,local); 1032*8193Smckusick strcpy(s,nbsdecrypt(s,skey,buf)); 1033*8193Smckusick */ 1034*8193Smckusick while(*s){ 1035*8193Smckusick *s &= 0177; /* strip quote bites */ 1036*8193Smckusick *s++ ^= 040; /* invert upper-lower */ 1037*8193Smckusick } 1038*8193Smckusick } 1039*8193Smckusick /*VARARGS0*/ 1040*8193Smckusick mreopen(fsendtofmach,phd,sfn,a,b,c){ 1041*8193Smckusick /* simply handles errors by giving error msg */ 1042*8193Smckusick if(freopen(a,b,c) == NULL) 1043*8193Smckusick errormsg(fsendtofmach,phd,sfn,"%s: %s",a,sys_errlist[errno]); 1044*8193Smckusick } 1045*8193Smckusick /* 1046*8193Smckusick addtopub(string, args) 1047*8193Smckusick 1048*8193Smckusick add a message to the public logfile /usr/net/logfile. 1049*8193Smckusick note that the file must be writeable by everyone 1050*8193Smckusick if error messages from the netrcv subroutine 1051*8193Smckusick such as chdir errors are to be noticed. 1052*8193Smckusick */ 1053*8193Smckusick /*VARARGS0*/ 1054*8193Smckusick addtopublic(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n) 1055*8193Smckusick char *s; 1056*8193Smckusick { 1057*8193Smckusick static FILE *log = NULL; 1058*8193Smckusick if(log == NULL){ 1059*8193Smckusick if(stat(publogfile,&statbuf) < 0)return; 1060*8193Smckusick log = fopen(publogfile,"a"); 1061*8193Smckusick if(log == NULL)return; 1062*8193Smckusick } 1063*8193Smckusick fseek(log,0L,2); 1064*8193Smckusick fprintf(log,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n); 1065*8193Smckusick fflush(log); 1066*8193Smckusick } 1067*8193Smckusick /* set up a dummy environment for v7 /bin/sh */ 1068*8193Smckusick setenv(home) 1069*8193Smckusick char *home; { 1070*8193Smckusick static char *env[3],benv[2][50]; 1071*8193Smckusick env[0] = benv[0]; 1072*8193Smckusick env[1] = benv[1]; 1073*8193Smckusick #ifdef CCV7 1074*8193Smckusick strcpy( env[0], "PATH=:.:/usr/cc/bin:/usr/ucb/bin" ); 1075*8193Smckusick #else CCV7 1076*8193Smckusick strcpy(env[0],"PATH=:/bin:/usr/bin"); 1077*8193Smckusick #endif CCV7 1078*8193Smckusick sprintf(env[1],"HOME=%s",home); 1079*8193Smckusick env[2] = 0; 1080*8193Smckusick environ = env; 1081*8193Smckusick } 1082*8193Smckusick /* 1083*8193Smckusick errormsg(fsendtofmach,phd,sfn,"string",arg(s)) 1084*8193Smckusick 1085*8193Smckusick Sends error message to user. 1086*8193Smckusick If fsendtofmach=TRUE, send to phd->hd_mchfrom, otherwise 1087*8193Smckusick send to phd->hd_mchto. 1088*8193Smckusick Also, if error occured during return of a "response", 1089*8193Smckusick send to local machine. 1090*8193Smckusick 1091*8193Smckusick Note that errormsg can be called by the netrcv subroutine 1092*8193Smckusick after the setuid() call to the specific user, so the 1093*8193Smckusick user must be able to get off an error msg back to him, 1094*8193Smckusick and to write in the two log files. 1095*8193Smckusick Can't use -w,-x,-y,-z for the net cmd because must be root for those. 1096*8193Smckusick 1097*8193Smckusick If sfn != NULL, then unlink sfn before exiting. 1098*8193Smckusick */ 1099*8193Smckusick /*VARARGS0*/ 1100*8193Smckusick errormsg(fsendtofmach,phd,sfn,s,a,b,c,d,e,f,g,h) 1101*8193Smckusick char fsendtofmach; 1102*8193Smckusick struct header *phd; 1103*8193Smckusick char *sfn,*s; 1104*8193Smckusick { 1105*8193Smckusick int rcode; 1106*8193Smckusick char errstr[BUFSIZ], cmdstr[BUFSIZ], rcmd[BUFSIZ]; 1107*8193Smckusick char toadd[FNS], fromadd[FNS], mchto, mchfrom; 1108*8193Smckusick char snto[FNS], snfrom[FNS]; 1109*8193Smckusick 1110*8193Smckusick if(phd->hd_sttyname[0] == 0)strcpy(phd->hd_sttyname,"/dev/ttyx"); 1111*8193Smckusick /* will send to toadd, from fromadd */ 1112*8193Smckusick if(!fsendtofmach || strcmp(phd->hd_scmdvirt,"response") == 0){ 1113*8193Smckusick /* send to tomach mach, thus send to toaddr. */ 1114*8193Smckusick /* if this is an error during a response, send to local mach. */ 1115*8193Smckusick strcpy(toadd, phd->hd_addrto); 1116*8193Smckusick strcpy(fromadd,phd->hd_addrfrom); 1117*8193Smckusick } 1118*8193Smckusick else { /* send to remote mach, thus send back to addrfrom*/ 1119*8193Smckusick strcpy(toadd, phd->hd_addrfrom); 1120*8193Smckusick strcpy(fromadd,phd->hd_addrto); 1121*8193Smckusick } 1122*8193Smckusick sprintf(errstr,"Error: "); 1123*8193Smckusick sprintf(cmdstr,s,a,b,c,d,e,f,g,h); 1124*8193Smckusick strcat(errstr,cmdstr); 1125*8193Smckusick strcat(errstr,"\n"); 1126*8193Smckusick addtolog(remote,errstr); 1127*8193Smckusick addtopublic(errstr); 1128*8193Smckusick 1129*8193Smckusick mchto = MchSFromAddr(snto,toadd); 1130*8193Smckusick mchfrom = MchSFromAddr(snfrom,fromadd); 1131*8193Smckusick 1132*8193Smckusick sprintf(rcmd, 1133*8193Smckusick "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -y %s -c \"'%s'\" -e %ld", 1134*8193Smckusick MWRITECMD, snto, phd->hd_sttyname, phd->hd_lttytime, 1135*8193Smckusick local, snfrom,phd->hd_scmdvirt, phd->hd_ltimesent-TIMEBASE, 1136*8193Smckusick toadd, fromadd, phd->hd_lttytime, phd->hd_sttyname, phd->hd_scmdvirt, 1137*8193Smckusick phd->hd_ltimesent-TIMEBASE); 1138*8193Smckusick 1139*8193Smckusick if(mchto == local) 1140*8193Smckusick sprintf(cmdstr, "echo \"%s\" | %s", errstr,rcmd); 1141*8193Smckusick else 1142*8193Smckusick sprintf(cmdstr, 1143*8193Smckusick "echo \"%s\" | %s -m%c -b -c errormessage -l network - %s", 1144*8193Smckusick errstr,netcmd,mchto,rcmd); 1145*8193Smckusick rcode = system(cmdstr); 1146*8193Smckusick debug( "errormsg: cmdstr = %s\n", cmdstr ); 1147*8193Smckusick debug( "errormsg: rcode = %d\n", rcode ); 1148*8193Smckusick if(sfn != NULL)unlink(sfn); 1149*8193Smckusick exit(EX_USAGE); 1150*8193Smckusick } 1151*8193Smckusick handlekill(){ /* SIGTERM signal */ 1152*8193Smckusick long t; 1153*8193Smckusick /* 1154*8193Smckusick t = gettime(); 1155*8193Smckusick dumpit(t); 1156*8193Smckusick */ 1157*8193Smckusick # ifdef NETLDISC 1158*8193Smckusick /* turn off net line discipline if possible */ 1159*8193Smckusick netd.dp_linedis = 0; 1160*8193Smckusick ioctl(netd.dp_linefd,TIOCSETD,&netd.dp_linedis); 1161*8193Smckusick close(netd.dp_linefd); 1162*8193Smckusick printf("Network line discipline turned off.\n"); 1163*8193Smckusick # endif NETLDISC 1164*8193Smckusick exit(EX_OK); /* kill myself */ 1165*8193Smckusick } 1166*8193Smckusick 1167*8193Smckusick /* check a request to see if it is an acct pair */ 1168*8193Smckusick /* returns 1 if it is, 0 if not */ 1169*8193Smckusick static facctpaircheck(phd) 1170*8193Smckusick register struct header *phd; 1171*8193Smckusick { 1172*8193Smckusick return(0); 1173*8193Smckusick } 1174*8193Smckusick 1175