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