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