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