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