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