|
|
1.1 root 1: /*
2: The daemon program that runs the network.
3:
4: netdaemon mach readfd writefd
5:
6: Must be started by root.
7: */
8:
9: # include "defs.h"
10:
11: /* global variables */
12: extern char **environ;
13: short masterseqno, lastseqno;
14: struct dumpstruc dump;
15: struct bstruct btable[];
16: int onlyuid;
17:
18: /* local variables */
19: static long length;
20: static char nsendfail;
21: static FILE *dir;
22: static char header[] = "ABCDE";
23: static char tempfile[]= TEMPFILE;
24: static char publogfile[]= PUBLOGFILE;
25: static char dumpfile[]= DUMPFILE;
26: static char namefile[]= NAMEFILE;
27: static struct stat statbuf;
28: static struct direct dirbuf;
29: int handlekill();
30: static char frommach;
31: static char buf[BUFSIZ];
32: /* addrfrom is the person who sent this to us,
33: addrto is the person who received the command, i.e.
34: addrto is on this machine */
35: static char addrto[BUFSIZ], addrfrom[BUFSIZ];
36:
37: main(argc,argv)
38: char **argv; {
39: register int i;
40: long ltime,t;
41:
42: signal(SIGTRM,handlekill);
43: debugflg = DBV;
44: setupdaemon(argc,argv);
45: /* now running alone as a daemon */
46: /*
47: for(i=0; i<15; i++)close(i);
48: signal(SIGHUP,SIG_IGN);
49: signal(SIGQUIT,SIG_IGN);
50: signal(SIGINT,SIG_IGN);
51: */
52: senddir[strlen(senddir)-1] = remote; /* choose dir */
53: if(chdir(senddir) < 0){
54: perror(senddir);
55: exit(1);
56: }
57: dir = fopen(senddir,"r");
58: if(dir == NULL){
59: perror(senddir);
60: exit(1);
61: }
62: mktemp(tempfile);
63: tempfile[strlen(tempfile) - 7] = remote;
64: ltime = gettime();
65: sprintf(buf,"net restarted to %s %d %s",longname(remote),
66: getpid(),ctime(<ime));
67: dump.longtime = dump.shorttime = ltime;
68: addtolog(remote,buf);
69: addtodump(remote,buf);
70: addtopublic(buf);
71: fprintf(stderr,buf);
72: if(!debugflg)fclose(stderr);
73: sendpurge();
74: nsendfail = 0;
75: for(;;){ /* begin reading file */
76: debug("daemon %c %d\nreceive",remote,getpid());
77: i = getreset();
78: dump.waittime = 0L;
79: if(i == BROKENREAD){
80: if(nsendfail < NSEND) netsend();
81: else nsendfail++;
82: }
83: else {
84: i = netrcv();
85: if(i >= 0){
86: nsendfail = 0; /* it sent, it is up */
87: dump.waittot += dump.waittime;
88: }
89: if(i == -1)dump.nabnormal++;
90: }
91: t = gettime();
92: if(t - dump.shorttime > SAMPL)pload(t);
93: if(t - dump.longtime > BIGSAMPL)dumpit(t);
94: dump.nloop++;
95: /* count up to NSEND, sending, then wait NSEND */
96: if(nsendfail >= NSEND*2)nsendfail = 0;
97: }
98: }
99: netsend(){
100: static long lasttime = 0;
101: static char nleft = 1;
102: long lFileLen,diff;
103: double drate;
104: int uid,uidBest;
105: char *sdate,*sn,*swait;
106: long ot,nt,filesize;
107: register int i;
108: char stemp[20];
109: static char jname[FNS];
110:
111: debug("ck send");
112: if(stat(senddir,&statbuf) < 0){
113: error("%s %s",senddir,sys_errlist[errno]);
114: return;
115: }
116: if(statbuf.st_mtime == lasttime && nleft == 0)return; /* no need to search */
117: lasttime = statbuf.st_mtime;
118: fseek(dir,0L,0);
119: lFileLen = 10000000L;
120: nleft = 0;
121: while(fread(&dirbuf,1,sizeof dirbuf,dir) == sizeof dirbuf){
122: if(dirbuf.d_ino == 0
123: || dirbuf.d_name[0] != 'c'
124: || dirbuf.d_name[1] != 'f'
125: || dirbuf.d_name[2] != remote
126: || stat(dirbuf.d_name,&statbuf) < 0
127: || statbuf.st_mode == 0)
128: continue;
129: dirbuf.d_name[0] = 'd';
130: if(stat(dirbuf.d_name,&statbuf) < 0 || statbuf.st_mode == 0)
131: continue;
132: uid = guid(statbuf.st_uid,statbuf.st_gid);
133: if(onlyuid != 0 && uid != onlyuid && uid != SUPERUSER)continue;
134: nleft++;
135: filesize = getsize(&statbuf);
136: if(lFileLen > filesize){
137: lFileLen = filesize;
138: for(i=0; i<DIRSIZ; i++)
139: jname[i] = dirbuf.d_name[i];
140: uidBest = uid;
141: }
142: }
143: if(lFileLen == 10000000L)return;
144: strcpy(stemp,jname);
145: stemp[0] = 'c';
146: sn = SnFromUid(uidBest);
147: if(sn == NULL){
148: addtolog(remote,"Unknown userid %d\n",uidBest);
149: return;
150: }
151: addtolog(remote,"^S %s %c: %s ",sn,remote,jname+2);
152: ot = gettime();
153: dump.waittime = 0L;
154: if(send(jname) == 0)return;
155: nt = gettime();
156: dump.waittot += dump.waittime;
157: filesize = getsize(&statbuf);
158: unlink(jname);
159: unlink(stemp);
160: diff = nt - ot;
161: if(diff < 1)diff = 1; /* avoid dividing by zero */
162: sdate = ctime(&nt)+4;
163: sdate[strlen(sdate) -9] = 0;
164: drate = (double)filesize / (double)diff;
165: swait = comptime(ot - statbuf.st_mtime);
166: jname[3] = jname[2];
167: addtolog(remote,"^T%c(%s, %ldb, %ldsec, %4.1fb/sec, w %s)\n",
168: remote,sdate,filesize, diff,drate, swait);
169: addtopublic("%s: sent %-8s to %c (%s, %ld b, wait %s)\n",
170: sdate,sn,remote,jname+3,filesize,swait);
171: dump.nsend++;
172: dump.bytetot += filesize;
173: dump.elaptot += diff;
174: /* add this users name to /usr/net/usernames */
175: addtoname(sn);
176: }
177: send(jname)
178: char *jname;
179: { /* push those bytes */
180: /* returns 0 if send fails, 1 otherwise */
181: register int n;
182: int i;
183: long lsize;
184: char mbuf[BUFSIZ];
185: register char *p;
186: FILE *jfile;
187:
188: debug("send %s",jname);
189: if(stat(jname,&statbuf) < 0)goto sfail;
190: lsize = getsize(&statbuf);
191: if(lsize < MINSIZE){ /* all files are at least this long */
192: unlink(jname);
193: jname[0] = 'c';
194: unlink(jname);
195: return(1);
196: }
197: jfile = fopen(jname,"r");
198: if(jfile == NULL)goto sfail;
199: strcpy(mbuf,header);
200: i = strlen(header);
201: p = (char *)&lsize;
202: lsize = fixuplong(lsize);
203: mbuf[i] = *p++;
204: mbuf[i+1] = *p++;
205: mbuf[i+2] = *p++;
206: mbuf[i+3] = *p++;
207: i = i + 4;
208: sendreset();
209: masterseqno = 1;
210: lastseqno = 0;
211: if(xwrite(mbuf,1,i) == WRITEFAIL)goto bwrite;
212: while((n=fread(buf,1,BLOCKSIZE,jfile)) > 0)
213: if(xwrite(buf,1,n) == WRITEFAIL)goto bwrite;
214: fclose(jfile);
215: debug("end send");
216: nsendfail = 0;
217: return(1);
218: bwrite:
219: nsendfail++;
220: dump.nsendfail++;
221: fclose(jfile);
222: addtolog(remote,"^F%c\n",remote);
223: return(0);
224: sfail:
225: error("%s: %s",jname,sys_errlist[errno]);
226: dump.nsendfail++;
227: return(0);
228: }
229: netrcv(){
230: /* returns -2 in normal fail, -1 in abnormal fail, >= 0 otherwise */
231: char code, sin;
232: char tmach, fmach;
233: char mgetc(), cflag, *s;
234: register int n,i;
235: char vmajor, vminor, c;
236: int rcode, dummy, pid, uid;
237: char buf1[BUFSIZ], cmdstr[BUFSIZ];
238: static char parmlist[PARMLIST];
239: long timesent,otime,olength,diff,rcvfinish,nt,maxfile = MAXFILE;
240: double r;
241: static char resp[FNS], infile[FNS], outfile[FNS];
242: static char hbuf[10];
243: static FILE *temp;
244:
245: n = nread(hbuf,1,strlen(header));
246: if(n == BROKENREAD)return(-2);
247: if(n != strlen(header) || strcmp(header,hbuf) != 0){
248: error("wrong head %d %s",n,hbuf);
249: return(-1);
250: }
251: n = nread(&length,1,4);
252: if(n == BROKENREAD)return(-2);
253: if(n != 4){
254: error("bad length nread %d",n);
255: return(-1);
256: }
257: length = fixuplong(length);
258: olength = length;
259: otime = gettime();
260: debug("length = %ld\n",length);
261: i = 0;
262:
263: /*
264: begin parsing header
265:
266: from local to remote (requests)
267: code net option reason
268: q normal request
269: y -y simply skips login check (used by netlpr)
270:
271: from remote to local
272: code net option reason
273: w -w message to be written/mailed back
274: s -z normal response
275: */
276:
277: code = mgetc();
278: tmach = mgetc();
279: if(tmach < 'a' || 'z' < tmach){
280: error("bad tmach");
281: return(-1);
282: }
283: if(tmach != local)goto forw; /* being forwarded through us */
284: fmach = mgetc();
285: vmajor = mgetc();
286: vminor = mgetc();
287: i += mgets(status.login,NS);
288: i += mgets(status.mpasswd,20);
289: demask(status.mpasswd);
290: i += mgets(infile,FNS);
291: i += mgets(outfile,FNS);
292: i += mgets(resp,FNS);
293: i += mgets(status.localname,NS);
294:
295: /* addrfrom is the person who sent this to us,
296: addrto is the person who received the command, i.e.
297: addrto is on this machine */
298: if(status.localname[0] == 0)strcpy(status.localname,"root");
299: sprintf(addrfrom, "%s:%s",longname(fmach),status.localname);
300: sprintf(addrto, "%s:%s",longname(tmach),status.login);
301:
302: i += mgets(status.sTtyname,20);
303: if(status.sTtyname[0] == 0)strcpy(status.sTtyname,"/dev/ttyx");
304: cflag = mgetc();
305: if(!fmach || !code || !cflag || !vmajor || !vminor){
306: error("mgetc fails");
307: return(-1);
308: }
309: cflag -= 'a';
310: vmajor -= 'a';
311: vminor -= 'a';
312: if(vmajor != VMAJOR || vminor != VMINOR){
313: /*
314: error("versions dont agree (%d,%d) vs. (%d,%d) remote",
315: VMAJOR,VMINOR,vmajor,vminor);
316: return(-1);
317: */
318: }
319: i += mgets(buf,BUFSIZ);
320: status.lTtytime = 0;
321: sscanf(buf,"%lo",&status.lTtytime);
322:
323: i += mgets(parmlist,PARMLIST);
324: status.jobno = atoi(parmlist);
325: /* keep variable parameter list in jobno slot */
326: parseparmlist(parmlist);
327:
328: i += mgets(buf1,BUFSIZ); /* time sent */
329: sscanf(buf1,"%ld",×ent);
330: i += mgetcmd(status.sCmdAct);
331: i += mgetcmd(status.sCmdVirt);
332: if(i != 0){error("mgets fails"); return(-1);}
333: if(status.sCmdVirt[0] == 0)strcpy(status.sCmdVirt,status.sCmdAct);
334: s = status.sCmdVirt;
335: while(*s && *s != ' ')s++;
336: c = *s;
337: *s = 0;
338: if(strcmp(status.sCmdVirt,"netlpr") == 0)dump.nnetlpr++;
339: else if(strcmp(status.sCmdVirt,"netmail") == 0)dump.nnetmail++;
340: else if(strcmp(status.sCmdVirt,"mail") == 0)dump.nsmail++;
341: else if(strcmp(status.sCmdVirt,"netcp") == 0)dump.nnetcp++;
342: else if(strcmp(status.sCmdVirt,"response") == 0)dump.nresp++;
343: else dump.nnet++;
344: *s = c;
345: debug("%c %c %c (%c,%c) %s %s %s %s (%s) %s %c %lo %d %s\n",
346: code,tmach,fmach,vmajor+'a',vminor+'a',status.login,
347: infile,outfile,resp,status.localname,
348: status.sTtyname,cflag+'a',status.lTtytime,status.jobno,status.sCmdAct);
349:
350:
351: /* any chars left are data */
352: forw:
353: sin = 0;
354: if(length > 0){ /* make a temp input file */
355: increment(tempfile);
356: temp = fopen(tempfile,"w");
357: if(temp == NULL){
358: error("%s %s",tempfile,sys_errlist[errno]);
359: return(-1);
360: }
361: chmod(tempfile,0600);
362: if(tmach != local)fprintf(temp,"%c :%c :",code,tmach);
363: while((n = mread(buf,1,BLOCKSIZE)) > 0)
364: if(fwrite(buf,1,n,temp) != n){
365: error("%s %s",tempfile,sys_errlist[errno]);
366: fclose(temp);
367: unlink(tempfile);
368: return(-1);
369: };
370: fclose(temp);
371: if(n == BROKENREAD || length > 0){
372: unlink(tempfile);
373: return(-2);
374: }
375: sin = 1;
376: if(tmach != local){
377: diff = gettime() - otime;
378: if(diff < 1)diff = 1; /* avoid dividing by 0 */
379: r = olength;
380: r = r/diff;
381: addtolog(remote,"^P(to %c, %ldb, %ldsec, %4.1fb/sec)\n",
382: tmach,olength,diff,r);
383: dump.npass++;
384: dump.bytetot += olength;
385: dump.elaptot += diff;
386: while((pid = fork()) == -1)sleep(2);
387: if(pid == 0){
388: execl(netcmd,"net","-x","-m",longname(tmach),
389: "-s",tempfile,buf,0);
390: exit(1);
391: }
392: wait(&dummy);
393: unlink(tempfile);
394: return(1);
395: }
396: }
397: if(length > 0){error("file too short"); return(-1); }
398: rcvfinish = gettime();
399:
400: while((pid = fork()) == -1)sleep(2);
401: if(pid > 0){
402: wait(&dummy);
403: return(1); /* normal return */
404: }
405:
406: while((pid = fork()) == -1)sleep(2);
407: if(pid != 0)exit(0);
408:
409: /* child process which forks and waits */
410: mktemp(resfile);
411: while((pid = fork()) == -1)sleep(2);
412: if(pid == 0){
413: /* child */
414: strcpy(status.loginshell,Bsh);
415: frommach = fmach;
416: n = check(status.login,status.mpasswd,(code == 'q'));
417: if(!n)errormsg(fmach,"Bad remote login/password '%s'",status.login);
418: temp = fopen(resfile,"w");
419: if(temp == NULL)
420: errormsg(fmach,"creat %s %s",resfile,sys_errlist[errno]);
421: chmod(resfile,0600);
422: fclose(temp);
423: mchown(resfile,status.muid,status.mgid);
424: if(sin)
425: mchown(tempfile,status.muid,status.mgid);
426: setuid(status.muid);
427: setgid(status.mgid);
428: uid = getuid();
429: uid = uidmask(uid);
430: status.muid = uidmask(status.muid);
431: if(uid != status.muid)error("setuid fails");
432: debug("uid: %o\n",uid);
433: /* check for allowed root commands, for security reasons */
434: if(uid == SUPERUSER){
435: s = status.sCmdAct;
436: while(*s && *s != ' ')s++;
437: c = *s;
438: *s = 0;
439: /* these are the only commands root may execute */
440: if(strcmp(status.sCmdAct,"cat") != 0
441: && strcmp(status.sCmdAct,CATCMD) != 0
442: && strcmp(status.sCmdAct,FILECAT) != 0
443: && strcmp(status.sCmdAct,MWRITECMD) != 0
444: && strcmp(status.sCmdAct,"/usr/lib/tq") != 0
445: && strcmp(status.sCmdAct,"/usr/lib/rtrrm") != 0
446: && strcmp(status.sCmdAct,"lpr") != 0)
447: errormsg(fmach,
448: "Not allowed to execute '%s' as root",
449: status.sCmdAct);
450: *s = c;
451: }
452: if(chdir(status.dir) < 0)
453: errormsg(fmach,"chdir %s %s",status.dir,sys_errlist[errno]);
454: setenv(status.dir); /* set up v7 environment */
455: if(sin)mreopen(fmach,tempfile,"r",stdin);
456: else if(infile[0])mreopen(fmach,infile,"r",stdin);
457: else mreopen(fmach,"/dev/null","r",stdin);
458: if(code == 's' && outfile[0]){
459: if(stat(outfile,&statbuf) < 0
460: || getsize(&statbuf) != 0
461: || !(statbuf.st_mode&0600))
462: errormsg(local,"Bad result file '%s'",outfile);
463: mreopen(fmach,outfile,"w",stdout);
464: }
465: else if(outfile[0]){
466: temp = fopen(outfile,"w");
467: if(temp == NULL)
468: errormsg(fmach,"fopen %s %s",outfile,sys_errlist[errno]);
469: fclose(temp);
470: mreopen(fmach,outfile,"w",stdout);
471: }
472: else mreopen(fmach,resfile,"a",stdout);
473: debug("exec '%s'\n",status.sCmdAct);
474: if(debugflg == 0){
475: /* cheat */
476: close(2);
477: dup(1);
478: /*
479: mreopen(fmach,resfile,"a",stderr);
480: */
481: }
482: for(i=3;i<15;i++)close(i);
483: do {
484: mexecl(status.loginshell,"sh","-c",status.sCmdAct,0);
485: sleep(2);
486: } while(errno == ETXTBSY);
487: exit(1);
488: }
489: /* parent */
490: wait(&rcode);
491: rcode >>= 8;
492: /*
493: fclose(stdin);
494: fclose(stdout);
495: fclose(stderr);
496: */
497: if(sin)unlink(tempfile);
498: /*
499: now send something back to the sender
500: unless this was a response (file or message)
501: */
502: if((code == 'q' || code == 'y') && (resp[0] || !(cflag&F_NONOTIFY))){
503: /* send response back if a response file
504: was given or if mail/write is allowed */
505: /* should give an error message for non-zero return codes */
506: if(stat(resfile,&statbuf) < 0){
507: error("%s %s",resfile,sys_errlist[errno]);
508: goto next;
509: }
510: /* allow larger files between the Ingres machines */
511: if(machtype[local - 'a'] == M_INGRES
512: && machtype[remote - 'a'] == M_INGRES)
513: maxfile = MAXFILELARGE;
514: if(getsize(&statbuf) >= maxfile){
515: errormsg(fmach,"Result file too large - not sent");
516: goto next;
517: }
518: if(getsize(&statbuf) == 0){
519: /* response file specified, no output generated */
520: if(resp[0] != 0) goto next;
521: /* quiet option - no output and a rcode of 0 */
522: if(rcode == 0 && (cflag&F_QUIET))goto next;
523: }
524: /* use both old and new mwrite parm lists */
525:
526: if(resp[0])sprintf(cmdstr,"-o %s %s",resp,CATCMD);
527: else sprintf(cmdstr,
528: "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -c \"'%s'\" -y %s -e %ld -r %d",
529: MWRITECMD, status.localname,status.sTtyname,status.lTtytime,tmach,status.login, status.sCmdVirt,timesent,
530: addrfrom, addrto, status.lTtytime, status.sCmdVirt, status.sTtyname, timesent, rcode);
531: sprintf(buf,"%s -m%c -z -b -l %s -s %s -c response %s",
532: netcmd,fmach,status.localname,resfile,cmdstr);
533: dummy = system(buf); /* execute command buf */
534: }
535: next:
536: unlink(resfile);
537: s = ctime(&rcvfinish);
538: s += 4;
539: s[strlen(s) -8] = 0;
540: diff = rcvfinish - otime;
541: if(diff < 1)diff = 1; /* avoid dividing by zero */
542: r = olength;
543: r = r/diff;
544: dump.bytetot += olength;
545: dump.elaptot += diff;
546: sprintf(buf,"%s rcv %c:%-8s (%s)",
547: s,fmach,status.localname,status.login);
548: addtolog(remote,"%s C: %s\n",buf,status.sCmdVirt);
549: addtopublic("%s R: %d C: %s\n",buf,rcode,status.sCmdVirt);
550: nt = rcvfinish - timesent - TIMEBASE;
551: buf[0] = 0;
552: if(nt > 0L)sprintf(buf," took (%s)",comptime(nt));
553: addtolog(remote,"\t\tR: %d%s %ldb %ldsec %4.1fb/sec\n",
554: rcode,buf,olength,diff,r);
555: exit(0);
556: /*UNREACHED*/
557: }
558:
559: /*
560: check() -- verify login name and password
561: snTo = login,
562: pass = passwd,
563: verify = 1 if password must check
564: Returns 1 if password is ok, 0 if not.
565: */
566: check(snTo,pass,verify) /* 1 if OK, 0 if not */
567: int verify;
568: char *snTo, *pass; {
569: int ver;
570: char *s, *u, *nullstr = "";
571: struct passwd *pwd;
572: ver = (verify == 0); /* ver is true if password verification
573: was not requested */
574: if(snTo[0] == 0)return(ver);
575: if(!goodacctname(snTo))return(ver);
576: pwd = getpwnam(snTo);
577: if(pwd == NULL)return(ver);
578: # ifndef NEWPROT
579: if(machtype[local-'a'] == M_CC && machtype[frommach-'a'] == M_CC)
580: s = pass;
581: else
582: # endif
583: if(*pass)s = crypt(pass,pwd->pw_passwd);
584: else s = nullstr;
585: status.muid = guid(pwd->pw_uid,pwd->pw_gid);
586: status.mgid = pwd->pw_gid;
587: if(isdigit(pwd->pw_gecos[0]))status.jobno = atoi(pwd->pw_gecos);
588: else status.jobno = 32767;
589: strcpy(status.dir,pwd->pw_dir);
590: strcpy(status.loginshell,pwd->pw_shell);
591: u = status.loginshell;
592: if(u[0] == 0 /* || strcmp("sh",u+strlen(u)-2) != 0 */) strcpy(u,Bsh);
593:
594: getpwdf(pwd);
595: /* ignore network passwd */
596: if(!spacct(status.login,s,status.localname,status.muid,status.mgid)
597: && strcmp(pwd->pw_passwd,s) && verify)
598: return(0);
599: return(1);
600: }
601: mread(b,i,n)
602: register int n; {
603: if(length <= 0)return(0);
604: if(length < n)n = length;
605: n = nread(b,i,n);
606: if(n != BROKENREAD)length -= n;
607: return(n);
608: }
609: char mgetc(){ /* returns 0 if fail */
610: register char c;
611: register int n;
612: char buf[3];
613: if((n=nread(buf,1,3)) == BROKENREAD)return(0);
614: if(n != 3){error("bad read %d",n); return(0); }
615: c = buf[0];
616: if(buf[1] != ' ' && buf[1] != ':'){error("Bad char %c",buf[1]); return(0); }
617: length -= 3;
618: if(length < 0){error("length wrong2 %ld",length); return(0); }
619: return(c);
620: }
621: /* read in string over the network wire */
622: /* put string in s, max length is maxlen */
623: mgets(s,maxlen) /* returns 0 if ok, 1 if not */
624: int maxlen;
625: register char *s; {
626: register char *q;
627: register int n;
628: char c;
629: q = s;
630: for(;;) {
631: if((n=nread(&c,1,1)) == BROKENREAD){
632: *s = 0;
633: error("mgets %s",s);
634: return(1);
635: }
636: if(n == 0)break;
637: if(c == '\\'){
638: if((n=nread(&c,1,1)) == BROKENREAD){
639: *s = 0;
640: error("mgets %s",s);
641: return(1);
642: }
643: if(n == 0)break;
644: }
645: if(c == ' ')break;
646: if(maxlen-- > 0) *s++ = c;
647: }
648: *s = 0;
649: if(nread(&c,1,1) == BROKENREAD){
650: error("mgets %s",s);
651: return(1);
652: }
653: length -= (s - q + 2);
654: if(length < 0){error("length wrong1 %ld %s",length,q); return(-1); }
655: if(maxlen < 0)
656: error("mgets - string too long");
657: return(0);
658: }
659: mgetcmd(s) /* returns 0 if succeed, 1 otherwise */
660: char *s; {
661: int i,n;
662: char c;
663: i = 0;
664: for(;;){
665: if((n=nread(&c,1,1)) == BROKENREAD){
666: s[i] = 0;
667: error("mgetcmd %s",s);
668: return(1);
669: }
670: if(n <= 0 || c == '\n')break;
671: if(c == '\\'){
672: if(nread(&c,1,1) == BROKENREAD){
673: s[i] = 0;
674: error("mgetcmd %s",s);
675: return(1);
676: }
677: length--;
678: }
679: s[i++] = c;
680: length--;
681: }
682: s[i] = 0;
683: length--;
684: return(0);
685: }
686: increment(s)
687: char *s; {
688: int i;
689: char *p;
690: i = strlen(s) - 1;
691: while(s[i] == '9')i--;
692: if(s[i] < '0' || s[i] > '9'){
693: p = s+i+1;
694: while(*p)*p++ = '0';
695: return;
696: }
697: (s[i])++;
698: i++;
699: while(s[i])s[i++] = '0';
700: return;
701: }
702: pload(currt)
703: long currt; {
704: struct tms tbf;
705: static long out = 0L, ocut = 0L, ost = 0L, ocst = 0L;
706: long u, s, elapt;
707: double br,r,ru,rs;
708: char *str,buf[BUFSIZ];
709: currt = gettime();
710: elapt = currt - dump.shorttime;
711: times(&tbf);
712: u = tbf.tms_utime-out + tbf.tms_cutime-ocut;
713: s = tbf.tms_stime-ost + tbf.tms_cstime-ocst;
714: dump.outime += u;
715: dump.ostime += s;
716: r = u + s;
717: if(elapt > 0)r = (r/elapt)*100.0;
718: else r = 0.0;
719: /* adjust to be seconds */
720: r = r/60.0;
721: ru = u/60.0;
722: rs = s/60.0;
723: str = ctime(&currt);
724: str[strlen(str) - 5] = 0;
725: sprintf(buf,"%s (%s):\t%4.1fu\t%4.1fs\t%5.2f\t%s\n",
726: str,longname(remote),ru,rs,r,comptime(elapt));
727: addtodump(remote,"%s",buf);
728: br = dump.bytetot;
729: if(dump.elaptot > 0)br = br/dump.elaptot;
730: else br = 0.0;
731: addtodump(remote, "\tTrans.\t%.6ld bytes\t%4.1f bytes/sec\t%s",
732: dump.bytetot,br,comptime(dump.elaptot));
733: addtodump(remote," %s\n",comptime(dump.waittot));
734: dump.shorttime = currt;
735: dump.waittot = dump.elaptot = dump.bytetot = 0L;
736: out = tbf.tms_utime;
737: ocut = tbf.tms_cutime;
738: ost = tbf.tms_stime;
739: ocst = tbf.tms_cstime;
740: sprintf(buf,"%s %c",NETQSTAT,remote);
741: system(buf); /* gather stats on netq len. */
742: }
743: /* should also gather stats on # error msgs */
744: dumpit(currt)
745: long currt; {
746: register int ntot;
747: long elapt;
748: double r,ru,rs;
749: register struct dumpstruc *p = &dump;
750: register char *tt;
751: tt = ctime(&currt);
752: tt[strlen(tt) - 9] = 0;
753: elapt = currt - dump.longtime;
754: r = dump.outime + dump.ostime;
755: if(elapt > 0)r = (r/elapt) * 100.0;
756: else r = 0.0;
757: ru = dump.outime/60.0;
758: rs = dump.ostime/60.0;
759: r = r/60.0;
760: dump.longtime = dump.shorttime;
761: ntot = p->nnetcp + p->nnetmail + p->nsmail + p->nnetlpr
762: + p->nresp + p->nnet;
763: addtodump(remote,"Daily statisics\t(%s):\nSummary:\n",tt);
764: addtodump(remote,"\t# sent %d\t# pass-thru %d\t# rcv %d:\t# netcp %d\n",
765: p->nsend,p->npass,ntot,p->nnetcp);
766: addtodump(remote,"\t# netlpr %d\t# netmail %d\t# sendmail %d\t# resp %d\n",
767: p->nnetlpr,p->nnetmail,p->nsmail,p->nresp);
768: addtodump(remote,"Protocol summary:\n");
769: addtodump(remote,"\t# pk sent %d\t# pk rcv %d\t# b sent %ld\t# b rcv %ld\n",
770: p->npacksent,p->npackrcv,p->nbytesent, p->nbytercv);
771: addtodump(remote,
772: "\t# send fails %d\t# retrans %d\t# abn %d\t\t# cksum errs %d\n",
773: p->nsendfail,p->nretrans, p->nabnormal,p->ncksum);
774: addtodump(remote,"Load:\t\t\t\t%4.1fu\t%4.1fs\t%5.2f%%\t%s\n",
775: ru,rs,r,comptime(elapt));
776: p->nbytesent = p->nbytercv = p->outime = p->ostime = 0L;
777: p->nretrans = p->nloop = p->nabnormal = p->ncksum = 0;
778: p->npacksent = p->npackrcv = p->nnetcp = p->nnetmail = 0;
779: p->nsmail = p->nnetlpr = p->nnet = p->npass = 0;
780: p->nsend = p->nsendfail = 0;
781: }
782: /* returns 1 if n is ok, 0 if not */
783: goodacctname(n)
784: char *n; {
785: int i;
786: i = -1;
787: while(btable[++i].bname)
788: if(strcmp(btable[i].bname,n) == 0 &&
789: local == btable[i].bmach)return(0);
790: return(1);
791: }
792: demask(s)
793: register char *s; {
794: # ifdef NEWPROT
795: static char buf[20];
796: strcpy(s,nbsdecrypt(s,THEKEY,buf));
797: # else
798: while(*s){
799: *s &= 0177; /* strip quote bites */
800: *s++ ^= 040; /* invert upper-lower */
801: }
802: # endif
803: }
804: /*VARARGS0*/
805: mreopen(f,a,b,c){
806: /* simply handles errors by giving error msg */
807: if(freopen(a,b,c) == NULL)errormsg(f,"%s: %s",a,sys_errlist[errno]);
808: }
809: /*
810: addtopub(string, args)
811:
812: add a message to the public logfile /usr/net/logfile.
813: note that the file must be writeable by everyone
814: if error messages from the netrcv subroutine
815: such as chdir errors are to be noticed.
816: */
817: /*VARARGS0*/
818: addtopublic(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n)
819: char *s;
820: {
821: static FILE *log = NULL;
822: if(log == NULL){
823: if(stat(publogfile,&statbuf) < 0)return;
824: log = fopen(publogfile,"a");
825: if(log == NULL)return;
826: }
827: fseek(log,0L,2);
828: fprintf(log,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n);
829: fflush(log);
830: }
831: /*VARARGS0*/
832: addtodump(mach,str,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t,u)
833: char *str;
834: {
835: static FILE *log = NULL;
836: dumpfile[strlen(dumpfile)-1] = mach;
837: if(log == NULL){
838: if(stat(dumpfile,&statbuf) < 0)return;
839: log = fopen(dumpfile,"a");
840: if(log == NULL)return;
841: }
842: fseek(log,0L,2);
843: fprintf(log,str,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t,u);
844: fflush(log);
845: }
846: /* set up a dummy environment for v7 /bin/sh */
847: setenv(home)
848: char *home; {
849: static char *env[3],benv[2][50];
850: env[0] = benv[0];
851: env[1] = benv[1];
852: strcpy(env[0],"PATH=:/bin:/usr/bin");
853: sprintf(env[1],"HOME=%s",home);
854: env[2] = 0;
855: environ = env;
856: }
857: /* errormsg- sends error message to user-
858: may be on local or remote machine.
859: Sends to addrfrom if fmach != local,
860: or to addrto if fmach=local, on the assumption
861: that addrfrom is where it came from and addrto is where it
862: was destined on this machine. The only time fmach=local is
863: if the result file is screwed up.
864:
865: Note that errormsg can be called by the netrcv subroutine
866: after the setuid() call to the specific user, so the
867: user must be able to get off an error msg back to him,
868: and to write in the two log files.
869: Can't use -w,-x,-y,-z for the net cmd because must be root for those.
870: */
871: /*VARARGS0*/
872: errormsg(fmach,s,a,b,c,d,e,f,g,h)
873: char *s;
874: {
875: int rcode;
876: char errstr[BUFSIZ], cmdstr[BUFSIZ], rcmd[BUFSIZ];
877: char toadd[FNS], fromadd[FNS], mchto, mchfrom;
878:
879: if(fmach < 'a' || 'z' < fmach)fmach = local;
880: if(status.sTtyname[0] == 0)strcpy(status.sTtyname,"/dev/ttyx");
881: /* will send to toadd, from fromadd */
882: if(fmach == local || strcmp(status.sCmdVirt,"response") == 0){
883: /* send to local mach, thus send to toaddr. */
884: /* if this is an error during a response, send to local mach. */
885: strcpy(toadd, addrto);
886: strcpy(fromadd,addrfrom);
887: }
888: else { /* send to remote mach, thus send back to addrfrom*/
889: strcpy(toadd, addrfrom);
890: strcpy(fromadd,addrto);
891: }
892: sprintf(errstr,"Error: ");
893: sprintf(cmdstr,s,a,b,c,d,e,f,g,h);
894: strcat(errstr,cmdstr);
895: strcat(errstr,"\n");
896: addtolog(remote,errstr);
897: addtopublic(errstr);
898:
899: mchto = MchSFromAddr(status.localname,toadd);
900: mchfrom = MchSFromAddr(status.login, fromadd);
901:
902: sprintf(rcmd,
903: "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -y %s -c \"'%s'\" -e %ld",
904: MWRITECMD,
905: status.localname, status.sTtyname, status.lTtytime, local, status.login,status.sCmdVirt, gettime(),
906: toadd, fromadd, status.lTtytime, status.sTtyname, status.sCmdVirt, gettime());
907: if(fmach == local)
908: sprintf(cmdstr, "echo \"%s\" | %s", errstr,rcmd);
909: else sprintf(cmdstr,
910: "echo \"%s\" | %s -m%c -b -c errormessage -l network - %s",
911: errstr,netcmd,fmach,rcmd);
912: rcode = system(cmdstr);
913: exit(1);
914: }
915: handlekill(){ /* SIGTRM signal */
916: long t;
917: addtodump(remote,"Netdaemon terminated.\n");
918: t = gettime();
919: pload(t);
920: dumpit(t);
921: exit(0); /* kill myself */
922: }
923: spacct(log,pass,localname,luid,lgid) /* returns 1 if login ok, 0 if not */
924: char *log,*pass,*localname; {
925: long lt;
926: int u,g;
927: if(strcmp(log,"network") == 0)return(1);
928: /* experimental */
929: # ifdef SPACCT
930: if(strcmp(log,localname) == 0 && luid != 0 && lgid == 0
931: && isdigit(pass[0]) && (
932: strcmp(log,"source") == 0
933: || strcmp(log,"daemon") == 0)
934: ){
935: /* login name is same on both machines, userid is group 0,
936: non-root, the password is numeric
937: and the login name is one of a select few */
938: lt = atol(pass);
939: u = (lt & 0177777);
940: g = (lt >> 16);
941: if((luid == u) && (lgid == g))return(1);
942: }
943: # endif
944: return(0);
945: }
946: /* add the user's name to our name list */
947: /*VARARGS0*/
948: addtoname(name)
949: char *name;
950: {
951: static FILE *log = NULL;
952: if(name == NULL ||
953: name[0] == 0 ||
954: strcmp(name,"root") == 0 ||
955: strcmp(name,"network") == 0 ||
956: strcmp(name,"schmidt") == 0)return;
957: if(log == NULL){
958: if(stat(namefile,&statbuf) < 0)return;
959: log = fopen(namefile,"a");
960: if(log == NULL)return;
961: }
962: fseek(log,0L,2);
963: fprintf(log,"%s:%s\n",longname(local),name);
964: fflush(log);
965: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.