|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)cico.c 5.14 (Berkeley) 4/14/86";
3: #endif
4:
5: #include <signal.h>
6: #include "uucp.h"
7: #include <setjmp.h>
8: #ifdef USG
9: #include <termio.h>
10: #endif
11: #ifndef USG
12: #include <sgtty.h>
13: #endif
14: #ifdef BSDTCP
15: #include <netdb.h>
16: #include <netinet/in.h>
17: #include <sys/socket.h>
18: #endif BSDTCP
19: #include <sys/stat.h>
20: #include "uust.h"
21: #include "uusub.h"
22:
23: #if defined(VMS) && defined(BSDTCP)
24: #define NOGETPEER
25: #endif
26:
27: #ifdef BSD2_9
28: #define NOGETPEER
29: #endif
30:
31: jmp_buf Sjbuf;
32: jmp_buf Pipebuf;
33:
34: /* call fail text */
35: char *Stattext[] = {
36: "",
37: "BAD SYSTEM",
38: "WRONG TIME TO CALL",
39: "SYSTEM LOCKED",
40: "NO DEVICE",
41: "CALL FAILED",
42: "LOGIN FAILED",
43: "BAD SEQUENCE"
44: };
45:
46: /* call fail codes */
47: int Stattype[] = {
48: 0,
49: 0,
50: SS_WRONGTIME,
51: 0,
52: SS_NODEVICE,
53: SS_FAIL,
54: SS_FAIL,
55: SS_BADSEQ
56: };
57:
58: /* Arguments to setdebug(): */
59: #define DBG_TEMP 0 /* Create a temporary audit file */
60: #define DBG_PERM 1 /* Create a permanent audit file */
61: #define DBG_CLEAN 2 /* Cleanup, discard temp file */
62:
63: int ReverseRole = 0;
64: int Role = SLAVE;
65: int onesys = 0;
66: int turntime = 30 * 60; /* 30 minutes expressed in seconds */
67: char *ttyn = NULL;
68: extern int LocalOnly;
69: extern int errno;
70: extern char MaxGrade, DefMaxGrade;
71: extern char Myfullname[];
72:
73: #ifdef USG
74: struct termio Savettyb;
75: #endif
76: #ifndef USG
77: struct sgttyb Savettyb;
78: #endif
79:
80: /*
81: * this program is used to place a call to a
82: * remote machine, login, and copy files between the two machines.
83: */
84: main(argc, argv)
85: int argc;
86: register char *argv[];
87: {
88: register int ret;
89: int seq;
90: char wkpre[NAMESIZE], file[NAMESIZE];
91: char msg[MAXFULLNAME], *q;
92: register char *p;
93: extern onintr(), timeout(), dbg_signal();
94: extern char *pskip();
95: char rflags[MAXFULLNAME];
96: #ifdef NOGETPEER
97: u_long Hostnumber = 0;
98: #endif NOGETPEER
99:
100: strcpy(Progname, "uucico");
101:
102: #ifdef BSD4_2
103: sigsetmask(0); /* in case we inherit blocked signals */
104: #endif BSD4_2
105: signal(SIGINT, onintr);
106: signal(SIGHUP, onintr);
107: signal(SIGQUIT, onintr);
108: signal(SIGTERM, onintr);
109: signal(SIGPIPE, onintr); /* 4.1a tcp-ip stupidity */
110: signal(SIGFPE, dbg_signal);
111: ret = guinfo(getuid(), User, msg);
112: strcpy(Loginuser, User);
113: uucpname(Myname);
114: ASSERT(ret == 0, "BAD UID", CNULL, ret);
115:
116: setbuf (stderr, CNULL);
117:
118: rflags[0] = '\0';
119: umask(WFMASK);
120: strcpy(Rmtname, Myname);
121: Ifn = Ofn = -1;
122: while(argc>1 && argv[1][0] == '-'){
123: switch(argv[1][1]){
124: case 'd':
125: Spool = &argv[1][2];
126: break;
127: case 'g':
128: case 'p':
129: MaxGrade = DefMaxGrade = argv[1][2];
130: break;
131: case 'r':
132: Role = atoi(&argv[1][2]);
133: break;
134: case 'R':
135: ReverseRole++;
136: Role = MASTER;
137: break;
138: case 's':
139: strncpy(Rmtname, &argv[1][2], MAXBASENAME);
140: Rmtname[MAXBASENAME] = '\0';
141: if (Rmtname[0] != '\0')
142: onesys = 1;
143: break;
144: case 'x':
145: Debug = atoi(&argv[1][2]);
146: if (Debug <= 0)
147: Debug = 1;
148: strcat(rflags, argv[1]);
149: break;
150: case 't':
151: turntime = atoi(&argv[1][2])*60;/* minutes to seconds */
152: break;
153: case 'L': /* local calls only */
154: LocalOnly++;
155: break;
156: #ifdef NOGETPEER
157: case 'h':
158: Hostnumber = inet_addr(&argv[1][2]);
159: break;
160: #endif NOGETPEER
161: default:
162: printf("unknown flag %s (ignored)\n", argv[1]);
163: break;
164: }
165: --argc; argv++;
166: }
167:
168: while (argc > 1) {
169: fprintf(stderr, "unknown argument %s (ignored)\n", argv[1]);
170: --argc; argv++;
171: }
172:
173: if (Debug && Role == MASTER)
174: chkdebug();
175:
176: /* Try to run as uucp */
177: setgid(getegid());
178: setuid(geteuid());
179: #ifdef TIOCNOTTY
180: /*
181: * detach uucico from controlling terminal
182: * to defend against rlogind sending us a SIGKILL (!!!)
183: */
184: if (Role == MASTER && (ret = open("/dev/tty", 2)) >= 0) {
185: ioctl(ret, TIOCNOTTY, STBNULL);
186: close(ret);
187: }
188: #endif TIOCNOTTY
189: #ifdef BSD4_2
190: if (getpgrp(0) == 0) { /* We have no controlling terminal */
191: setpgrp(0, getpid());
192: }
193: #endif BSD4_2
194:
195: ret = subchdir(Spool);
196: ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret);
197: strcpy(Wrkdir, Spool);
198:
199: if (Debug) {
200: setdebug ((Role == SLAVE) ? DBG_TEMP : DBG_PERM);
201: if (Debug > 0)
202: logent ("Local Enabled", "DEBUG");
203: }
204:
205: /*
206: * First time through: If we're the slave, do initial checking.
207: */
208: if (Role == SLAVE) {
209: /* check for /etc/nologin */
210: if (access(NOLOGIN, 0) == 0) {
211: logent(NOLOGIN, "UUCICO SHUTDOWN");
212: if (Debug > 4)
213: logent("DEBUGGING", "continuing anyway");
214: else
215: cleanup(1);
216: }
217: Ifn = 0;
218: Ofn = 1;
219: #ifdef TCPIP
220: /*
221: * Determine if we are on TCPIP
222: */
223: if (isatty(Ifn) < 0) {
224: IsTcpIp = 1;
225: DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
226: } else
227: IsTcpIp = 0;
228: #endif TCPIP
229: /* initial handshake */
230: onesys = 1;
231: if (!IsTcpIp) {
232: #ifdef USG
233: ret = ioctl(Ifn, TCGETA, &Savettyb);
234: Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7;
235: Savettyb.c_oflag |= OPOST;
236: Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
237: #else !USG
238: ret = ioctl(Ifn, TIOCGETP, &Savettyb);
239: Savettyb.sg_flags |= ECHO;
240: Savettyb.sg_flags &= ~RAW;
241: #endif !USG
242: ttyn = ttyname(Ifn);
243: }
244: fixmode(Ifn);
245:
246: /*
247: * Initial Message -- tell them we're here, and who we are.
248: */
249: sprintf(msg, "here=%s", Myfullname);
250: omsg('S', msg, Ofn);
251: signal(SIGALRM, timeout);
252: alarm(MAXMSGTIME);
253: if (setjmp(Sjbuf)) {
254: /* timed out */
255: if (!IsTcpIp) {
256: #ifdef USG
257: ret = ioctl(Ifn, TCSETA, &Savettyb);
258:
259: #else !USG
260: ret = ioctl(Ifn, TIOCSETP, &Savettyb);
261: #endif !USG
262: }
263: cleanup(0);
264: }
265: for (;;) {
266: ret = imsg(msg, Ifn);
267: if (ret != SUCCESS) {
268: alarm(0);
269: if (!IsTcpIp) {
270: #ifdef USG
271: ret = ioctl(Ifn, TCSETA, &Savettyb);
272: #else !USG
273: ret = ioctl(Ifn, TIOCSETP, &Savettyb);
274: #endif !USG
275: }
276: cleanup(0);
277: }
278: if (msg[0] == 'S')
279: break;
280: }
281: alarm(0);
282: q = &msg[1];
283: p = pskip(q);
284: strncpy(Rmtname, q, MAXBASENAME);
285: Rmtname[MAXBASENAME] = '\0';
286:
287: /*
288: * Now that we know who they are, give the audit file the right
289: * name.
290: */
291: setdebug (DBG_PERM);
292: DEBUG(4, "sys-%s\n", Rmtname);
293: /* The versys will also do an alias on the incoming name */
294: if (versys(&Rmtname)) {
295: /* If we don't know them, we won't talk to them... */
296: #ifdef NOSTRANGERS
297: logent(Rmtname, "UNKNOWN HOST");
298: omsg('R', "You are unknown to me", Ofn);
299: cleanup(0);
300: #endif NOSTRANGERS
301: }
302: #ifdef BSDTCP
303: /* we must make sure they are really who they say they
304: * are. We compare the hostnumber with the number in the hosts
305: * table for the site they claim to be.
306: */
307: if (IsTcpIp) {
308: struct hostent *hp;
309: char *cpnt, *inet_ntoa();
310: int fromlen;
311: struct sockaddr_in from;
312: extern char PhoneNumber[];
313:
314: #ifdef NOGETPEER
315: from.sin_addr.s_addr = Hostnumber;
316: from.sin_family = AF_INET;
317: #else !NOGETPEER
318: fromlen = sizeof(from);
319: if (getpeername(Ifn, &from, &fromlen) < 0) {
320: logent(Rmtname, "NOT A TCP CONNECTION");
321: omsg('R', "NOT TCP", Ofn);
322: cleanup(0);
323: }
324: #endif !NOGETPEER
325: hp = gethostbyaddr(&from.sin_addr,
326: sizeof (struct in_addr), from.sin_family);
327: if (hp == NULL) {
328: /* security break or just old host table? */
329: logent(Rmtname, "UNKNOWN IP-HOST Name =");
330: cpnt = inet_ntoa(from.sin_addr),
331: logent(cpnt, "UNKNOWN IP-HOST Number =");
332: sprintf(wkpre, "%s/%s isn't in my host table",
333: Rmtname, cpnt);
334: omsg('R' ,wkpre ,Ofn);
335: cleanup(0);
336: }
337: if (Debug > 99)
338: logent(Rmtname,"Request from IP-Host name =");
339: /*
340: * The following is to determine if the name given us by
341: * the Remote uucico matches any of the names
342: * given its network number (remote machine) in our
343: * host table.
344: * We could check the aliases, but that won't work in
345: * all cases (like if you are running the domain
346: * server, where you don't get any aliases). The only
347: * reliable way I can think of that works in ALL cases
348: * is too look up the site in L.sys and see if the
349: * sitename matches what we would call him if we
350: * originated the call.
351: */
352: /* PhoneNumber contains the official network name of the host we are checking. (set in versys.c) */
353: if (sncncmp(PhoneNumber, hp->h_name, SYSNSIZE) == 0) {
354: if (Debug > 99)
355: logent(q,"Found in host Tables");
356: } else {
357: logent(hp->h_name, "FORGED HOSTNAME");
358: logent(inet_ntoa(from.sin_addr), "ORIGINATED AT");
359: logent(PhoneNumber, "SHOULD BE");
360: sprintf(wkpre, "You're not who you claim to be: %s != %s", hp->h_name, PhoneNumber);
361: omsg('R', wkpre, Ofn);
362: cleanup(0);
363: }
364: }
365: #endif BSDTCP
366:
367: if (mlock(Rmtname)) {
368: omsg('R', "LCK", Ofn);
369: cleanup(0);
370: }
371: else if (callback(Loginuser)) {
372: signal(SIGINT, SIG_IGN);
373: signal(SIGHUP, SIG_IGN);
374: omsg('R', "CB", Ofn);
375: logent("CALLBACK", "REQUIRED");
376: /* set up for call back */
377: systat(Rmtname, SS_CALLBACK, "CALLING BACK");
378: gename(CMDPRE, Rmtname, 'C', file);
379: close(creat(subfile(file), 0666));
380: xuucico(Rmtname);
381: cleanup(0);
382: }
383: seq = 0;
384: while (*p == '-') {
385: q = pskip(p);
386: switch(*(++p)) {
387: case 'x':
388: if (Debug == 0) {
389: Debug = atoi(++p);
390: if (Debug <= 0)
391: Debug = 1;
392: setdebug(DBG_PERM);
393: if (Debug > 0)
394: logent("Remote Enabled", "DEBUG");
395: } else {
396: DEBUG(1, "Remote debug request ignored\n",
397: CNULL);
398: }
399: break;
400: case 'Q':
401: seq = atoi(++p);
402: break;
403: case 'p':
404: MaxGrade = DefMaxGrade = *++p;
405: DEBUG(4, "MaxGrade set to %c\n", MaxGrade);
406: break;
407: case 'v':
408: if (strncmp(p, "grade", 5) == 0) {
409: p += 6;
410: MaxGrade = DefMaxGrade = *p++;
411: DEBUG(4, "MaxGrade set to %c\n", MaxGrade);
412: }
413: break;
414: default:
415: break;
416: }
417: p = q;
418: }
419: if (callok(Rmtname) == SS_BADSEQ) {
420: logent("BADSEQ", "PREVIOUS");
421: omsg('R', "BADSEQ", Ofn);
422: cleanup(0);
423: }
424: #ifdef GNXSEQ
425: if ((ret = gnxseq(Rmtname)) == seq) {
426: omsg('R', "OK", Ofn);
427: cmtseq();
428: } else {
429: #else !GNXSEQ
430: if (seq == 0)
431: omsg('R', "OK", Ofn);
432: else {
433: #endif !GNXSEQ
434: systat(Rmtname, Stattype[7], Stattext[7]);
435: logent("BAD SEQ", "FAILED HANDSHAKE");
436: #ifdef GNXSEQ
437: ulkseq();
438: #endif GNXSEQ
439: omsg('R', "BADSEQ", Ofn);
440: cleanup(0);
441: }
442: if (ttyn != NULL)
443: chmod(ttyn, 0600);
444: }
445:
446: loop:
447: if(setjmp(Pipebuf)) { /* come here on SIGPIPE */
448: clsacu();
449: close(Ofn);
450: close(Ifn);
451: Ifn = Ofn = -1;
452: rmlock(CNULL);
453: sleep(3);
454: }
455: if (!onesys) {
456: ret = gnsys(Rmtname, Spool, CMDPRE);
457: setdebug(DBG_PERM);
458: if (ret == FAIL)
459: cleanup(100);
460: if (ret == SUCCESS)
461: cleanup(0);
462: } else if (Role == MASTER && callok(Rmtname) != 0) {
463: logent("SYSTEM STATUS", "CAN NOT CALL");
464: cleanup(0);
465: }
466:
467: sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
468:
469: signal(SIGINT, SIG_IGN);
470: signal(SIGQUIT, SIG_IGN);
471: if (Role == MASTER) {
472: /* check for /etc/nologin */
473: if (access(NOLOGIN, 0) == 0) {
474: logent(NOLOGIN, "UUCICO SHUTDOWN");
475: if (Debug > 4)
476: logent("DEBUGGING", "continuing anyway");
477: else
478: cleanup(1);
479: }
480: /* master part */
481: signal(SIGHUP, SIG_IGN);
482: if (Ifn != -1 && Role == MASTER) {
483: write(Ofn, EOTMSG, strlen(EOTMSG));
484: clsacu();
485: close(Ofn);
486: close(Ifn);
487: Ifn = Ofn = -1;
488: rmlock(CNULL);
489: sleep(3);
490: }
491: sprintf(msg, "call to %s ", Rmtname);
492: if (mlock(Rmtname) != SUCCESS) {
493: logent(msg, "LOCKED");
494: US_SST(us_s_lock);
495: goto next;
496: }
497: Ofn = Ifn = conn(Rmtname);
498: if (Ofn < 0) {
499: if (Ofn != CF_TIME)
500: logent(msg, _FAILED);
501: /* avoid excessive 'wrong time' info */
502: if (Stattype[-Ofn] != SS_WRONGTIME){
503: systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]);
504: US_SST(-Ofn);
505: UB_SST(-Ofn);
506: }
507: goto next;
508: } else {
509: logent(msg, "SUCCEEDED");
510: US_SST(us_s_cok);
511: UB_SST(ub_ok);
512: }
513: #ifdef TCPIP
514: /*
515: * Determine if we are on TCPIP
516: */
517: if (isatty(Ifn) == 0) {
518: IsTcpIp = 1;
519: DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
520: } else
521: IsTcpIp = 0;
522: #endif
523:
524: if (setjmp(Sjbuf))
525: goto next;
526: signal(SIGALRM, timeout);
527: alarm(2 * MAXMSGTIME);
528: for (;;) {
529: ret = imsg(msg, Ifn);
530: if (ret != 0) {
531: alarm(0);
532: logent("imsg 1", _FAILED);
533: goto Failure;
534: }
535: if (msg[0] == 'S')
536: break;
537: }
538: alarm(MAXMSGTIME);
539: #ifdef GNXSEQ
540: seq = gnxseq(Rmtname);
541: #else !GNXSEQ
542: seq = 0;
543: #endif !GNXSEQ
544: if (MaxGrade != '\177') {
545: DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade);
546: sprintf(msg, "%s -Q%d -p%c -vgrade=%c %s",
547: Myname, seq, MaxGrade, MaxGrade, rflags);
548: } else
549: sprintf(msg, "%s -Q%d %s", Myname, seq, rflags);
550: omsg('S', msg, Ofn);
551: for (;;) {
552: ret = imsg(msg, Ifn);
553: DEBUG(4, "msg-%s\n", msg);
554: if (ret != SUCCESS) {
555: alarm(0);
556: #ifdef GNXSEQ
557: ulkseq();
558: #endif GNXSEQ
559: logent("imsg 2", _FAILED);
560: goto Failure;
561: }
562: if (msg[0] == 'R')
563: break;
564: }
565: alarm(0);
566: if (msg[1] == 'B') {
567: /* bad sequence */
568: logent("BAD SEQ", "FAILED HANDSHAKE");
569: US_SST(us_s_hand);
570: systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]);
571: #ifdef GNXSEQ
572: ulkseq();
573: #endif GNXSEQ
574: goto next;
575: }
576: if (strcmp(&msg[1], "OK") != SAME) {
577: logent(&msg[1], "FAILED HANDSHAKE");
578: US_SST(us_s_hand);
579: #ifdef GNXSEQ
580: ulkseq();
581: #endif GNXSEQ
582: systat(Rmtname, SS_INPROGRESS,
583: strcmp(&msg[1], "CB") == SAME?
584: "AWAITING CALLBACK": "FAILED HANDSHAKE");
585: goto next;
586: }
587: #ifdef GNXSEQ
588: cmtseq();
589: #endif GNXSEQ
590: }
591: DEBUG(1, "Rmtname %s, ", Rmtname);
592: DEBUG(1, "Role %s, ", Role ? "MASTER" : "SLAVE");
593: DEBUG(1, "Ifn - %d, ", Ifn);
594: DEBUG(1, "Loginuser - %s\n", Loginuser);
595:
596: ttyn = ttyname(Ifn);
597:
598: alarm(MAXMSGTIME);
599: if (ret=setjmp(Sjbuf))
600: goto Failure;
601: ret = startup(Role);
602: alarm(0);
603: if (ret != SUCCESS) {
604: logent("startup", _FAILED);
605: Failure:
606: US_SST(us_s_start);
607: systat(Rmtname, SS_FAIL, ret > 0 ? "CONVERSATION FAILED" :
608: "STARTUP FAILED");
609: goto next;
610: } else {
611: if (ttyn != NULL) {
612: char startupmsg[BUFSIZ];
613: extern int linebaudrate;
614: sprintf(startupmsg, "startup %s %d baud", &ttyn[5],
615: linebaudrate);
616: logent(startupmsg, "OK");
617: } else
618: logent("startup", "OK");
619: US_SST(us_s_gress);
620: systat(Rmtname, SS_INPROGRESS, "TALKING");
621: ret = cntrl(Role, wkpre);
622: DEBUG(1, "cntrl - %d\n", ret);
623: signal(SIGINT, SIG_IGN);
624: signal(SIGHUP, SIG_IGN);
625: signal(SIGALRM, timeout);
626: if (ret == SUCCESS) {
627: logent("conversation complete", "OK");
628: US_SST(us_s_ok);
629: rmstat(Rmtname);
630:
631: } else {
632: logent("conversation complete", _FAILED);
633: US_SST(us_s_cf);
634: systat(Rmtname, SS_FAIL, "CONVERSATION FAILED");
635: }
636: alarm(MAXMSGTIME);
637: DEBUG(4, "send OO %d,", ret);
638: if (!setjmp(Sjbuf)) {
639: for (;;) {
640: omsg('O', "OOOOO", Ofn);
641: ret = imsg(msg, Ifn);
642: if (ret != 0)
643: break;
644: if (msg[0] == 'O')
645: break;
646: }
647: }
648: alarm(0);
649: clsacu();
650: rmlock(CNULL);
651: }
652: next:
653: if (!onesys) {
654: goto loop;
655: }
656: cleanup(0);
657: }
658:
659: #ifndef USG
660: struct sgttyb Hupvec;
661: #endif
662:
663: /*
664: * cleanup and exit with "code" status
665: */
666: cleanup(code)
667: register int code;
668: {
669: signal(SIGINT, SIG_IGN);
670: signal(SIGHUP, SIG_IGN);
671: rmlock(CNULL);
672: sleep(5); /* Wait for any pending output */
673: clsacu();
674: logcls();
675: if (Role == SLAVE) {
676: if (!IsTcpIp) {
677: #ifdef USG
678: Savettyb.c_cflag |= HUPCL;
679: (void) ioctl(0, TCSETA, &Savettyb);
680: #else !USG
681: (void) ioctl(0, TIOCHPCL, STBNULL);
682: #ifdef TIOCSDTR
683: (void) ioctl(0, TIOCCDTR, STBNULL);
684: sleep(2);
685: (void) ioctl(0, TIOCSDTR, STBNULL);
686: #else !TIOCSDTR
687: (void) ioctl(0, TIOCGETP, &Hupvec);
688: Hupvec.sg_ispeed = B0;
689: Hupvec.sg_ospeed = B0;
690: (void) ioctl(0, TIOCSETP, &Hupvec);
691: #endif !TIOCSDTR
692: sleep(2);
693: (void) ioctl(0, TIOCSETP, &Savettyb);
694: /* make *sure* exclusive access is off */
695: (void) ioctl(0, TIOCNXCL, STBNULL);
696: #endif !USG
697: }
698: if (ttyn != NULL)
699: chmod(ttyn, 0600);
700: }
701: if (Ofn != -1) {
702: if (Role == MASTER)
703: write(Ofn, EOTMSG, strlen(EOTMSG));
704: close(Ifn);
705: close(Ofn);
706: }
707: #ifdef DIALINOUT
708: /* reenable logins on dialout */
709: reenable();
710: #endif DIALINOUT
711: if (code == 0)
712: xuuxqt();
713: else
714: DEBUG(1, "exit code %d\n", code);
715: setdebug (DBG_CLEAN);
716: exit(code);
717: }
718:
719: /*
720: * on interrupt - remove locks and exit
721: */
722:
723: onintr(inter)
724: register int inter;
725: {
726: char str[30];
727: signal(inter, SIG_IGN);
728: sprintf(str, "SIGNAL %d", inter);
729: logent(str, "CAUGHT");
730: US_SST(us_s_intr);
731: if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME))
732: systat(Rmtname, SS_FAIL, str);
733: if (inter == SIGPIPE && !onesys)
734: longjmp(Pipebuf, 1);
735: cleanup(inter);
736: }
737:
738: /*
739: * Catch a special signal
740: * (SIGFPE, ugh), and toggle debugging between 0 and 30.
741: * Handy for looking in on long running uucicos.
742: */
743: dbg_signal()
744: {
745: Debug = (Debug == 0) ? 30 : 0;
746: setdebug(DBG_PERM);
747: if (Debug > 0)
748: logent("Signal Enabled", "DEBUG");
749: }
750:
751:
752: /*
753: * Check debugging requests, and open RMTDEBUG audit file if necessary. If an
754: * audit file is needed, the parm argument indicates how to create the file:
755: *
756: * DBG_TEMP - Open a temporary file, with filename = RMTDEBUG/pid.
757: * DBG_PERM - Open a permanent audit file, filename = RMTDEBUG/Rmtname.
758: * If a temp file already exists, it is mv'ed to be permanent.
759: * DBG_CLEAN - Cleanup; unlink temp files.
760: *
761: * Restrictions - this code can only cope with one open debug file at a time.
762: * Each call creates a new file; if an old one of the same name exists it will
763: * be overwritten.
764: */
765: setdebug(parm)
766: int parm;
767: {
768: char buf[BUFSIZ]; /* Buffer for building filenames */
769: static char *temp = NULL; /* Ptr to temporary file name */
770: static int auditopen = 0; /* Set to 1 when we open a file */
771: struct stat stbuf; /* File status buffer */
772:
773: /*
774: * If movement or cleanup of a temp file is indicated, we do it no
775: * matter what.
776: */
777: if (temp != CNULL && parm == DBG_PERM) {
778: sprintf(buf, "%s/%s", RMTDEBUG, Rmtname);
779: unlink(buf);
780: if (link(temp, buf) != 0) {
781: Debug = 0;
782: assert("RMTDEBUG LINK FAIL", temp, errno);
783: cleanup(1);
784: }
785: parm = DBG_CLEAN;
786: }
787: if (parm == DBG_CLEAN) {
788: if (temp != CNULL) {
789: unlink(temp);
790: free(temp);
791: temp = CNULL;
792: }
793: return;
794: }
795:
796: if (Debug == 0)
797: return; /* Gotta be in debug to come here. */
798:
799: /*
800: * If we haven't opened a file already, we can just return if it's
801: * alright to use the stderr we came in with. We can if:
802: *
803: * Role == MASTER, and Stderr is a regular file, a TTY or a pipe.
804: *
805: * Caution: Detecting when stderr is a pipe is tricky, because the 4.2
806: * man page for fstat(2) disagrees with reality, and System V leaves it
807: * undefined, which means different implementations act differently.
808: */
809: if (!auditopen && Role == MASTER) {
810: if (isatty(fileno(stderr)))
811: return;
812: else if (fstat(fileno(stderr), &stbuf) == 0) {
813: #ifdef USG
814: /* Is Regular File or Fifo */
815: if ((stbuf.st_mode & 0060000) == 0)
816: return;
817: #else !USG
818: #ifdef BSD4_2
819: /* Is Regular File */
820: if ((stbuf.st_mode & S_IFMT) == S_IFREG ||
821: stbuf.st_mode == 0) /* Is a pipe */
822: return;
823: #else !BSD4_2
824: /* Is Regular File or Pipe */
825: if ((stbuf.st_mode & S_IFMT) == S_IFREG)
826: return;
827: #endif BSD4_2
828: #endif USG
829: }
830: }
831:
832: /*
833: * We need RMTDEBUG directory to do auditing. If the file doesn't exist,
834: * then we forget about debugging; if it exists but has improper owner-
835: * ship or modes, we gripe about it in ERRLOG.
836: */
837: if (stat(RMTDEBUG, &stbuf) != SUCCESS) {
838: Debug = 0;
839: return;
840: }
841: if ((geteuid() != stbuf.st_uid) || /* We must own it */
842: ((stbuf.st_mode & 0170700) != 040700)) { /* Directory, rwx */
843: Debug = 0;
844: assert("INVALID RMTDEBUG DIRECTORY:", RMTDEBUG, stbuf.st_mode);
845: return;
846: }
847:
848: if (parm == DBG_TEMP) {
849: sprintf(buf, "%s/%d", RMTDEBUG, getpid());
850: temp = malloc(strlen (buf) + 1);
851: if (temp == CNULL) {
852: Debug = 0;
853: assert("RMTDEBUG MALLOC ERROR:", temp, errno);
854: cleanup(1);
855: }
856: strcpy(temp, buf);
857: } else
858: sprintf(buf, "%s/%s", RMTDEBUG, Rmtname);
859:
860: unlink(buf);
861: if (freopen(buf, "w", stderr) != stderr) {
862: Debug = 0;
863: assert("FAILED RMTDEBUG FILE OPEN:", buf, errno);
864: cleanup(1);
865: }
866: setbuf(stderr, CNULL);
867: auditopen = 1;
868: }
869:
870: /*
871: * catch SIGALRM routine
872: */
873: timeout()
874: {
875: extern int HaveSentHup;
876: if (!HaveSentHup) {
877: logent(Rmtname, "TIMEOUT");
878: if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) {
879: US_SST(us_s_tmot);
880: systat(Rmtname, SS_FAIL, "TIMEOUT");
881: }
882: }
883: longjmp(Sjbuf, 1);
884: }
885:
886: static char *
887: pskip(p)
888: register char *p;
889: {
890: while(*p && *p != ' ')
891: ++p;
892: while(*p && *p == ' ')
893: *p++ = 0;
894: return p;
895: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.