BSD 4_3 release
[unix-history] / usr / src / usr.bin / uucp / cico.c
CommitLineData
ce5db1eb 1#ifndef lint
95f51977 2static char sccsid[] = "@(#)cico.c 5.14 (Berkeley) 4/14/86";
ce5db1eb
SL
3#endif
4
ce5db1eb 5#include <signal.h>
4b31fbb4 6#include "uucp.h"
ce5db1eb 7#include <setjmp.h>
88db71e9 8#ifdef USG
ce5db1eb
SL
9#include <termio.h>
10#endif
88db71e9 11#ifndef USG
ce5db1eb
SL
12#include <sgtty.h>
13#endif
88db71e9
RC
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"
ce5db1eb 22
4b31fbb4
JB
23#if defined(VMS) && defined(BSDTCP)
24#define NOGETPEER
25#endif
26
27#ifdef BSD2_9
28#define NOGETPEER
29#endif
30
ce5db1eb 31jmp_buf Sjbuf;
88db71e9
RC
32jmp_buf Pipebuf;
33
34/* call fail text */
ce5db1eb
SL
35char *Stattext[] = {
36 "",
37 "BAD SYSTEM",
88db71e9 38 "WRONG TIME TO CALL",
ce5db1eb
SL
39 "SYSTEM LOCKED",
40 "NO DEVICE",
2af814a5 41 "CALL FAILED",
ce5db1eb
SL
42 "LOGIN FAILED",
43 "BAD SEQUENCE"
88db71e9 44};
ce5db1eb 45
88db71e9
RC
46/* call fail codes */
47int Stattype[] = {
48 0,
49 0,
50 SS_WRONGTIME,
51 0,
52 SS_NODEVICE,
53 SS_FAIL,
54 SS_FAIL,
55 SS_BADSEQ
56};
ce5db1eb 57
2af814a5
JB
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 */
ce5db1eb 62
88db71e9 63int ReverseRole = 0;
88db71e9
RC
64int Role = SLAVE;
65int onesys = 0;
1a85e9d2 66int turntime = 30 * 60; /* 30 minutes expressed in seconds */
2af814a5 67char *ttyn = NULL;
88db71e9 68extern int LocalOnly;
2af814a5 69extern int errno;
1a85e9d2
RC
70extern char MaxGrade, DefMaxGrade;
71extern char Myfullname[];
88db71e9
RC
72
73#ifdef USG
ce5db1eb
SL
74struct termio Savettyb;
75#endif
88db71e9 76#ifndef USG
ce5db1eb
SL
77struct sgttyb Savettyb;
78#endif
79
2af814a5
JB
80/*
81 * this program is used to place a call to a
ce5db1eb
SL
82 * remote machine, login, and copy files between the two machines.
83 */
ce5db1eb 84main(argc, argv)
2af814a5 85int argc;
ce5db1eb
SL
86register char *argv[];
87{
88 register int ret;
89 int seq;
ce5db1eb 90 char wkpre[NAMESIZE], file[NAMESIZE];
2af814a5 91 char msg[MAXFULLNAME], *q;
ce5db1eb 92 register char *p;
2af814a5 93 extern onintr(), timeout(), dbg_signal();
ce5db1eb 94 extern char *pskip();
a534f0fb 95 char rflags[MAXFULLNAME];
4b31fbb4 96#ifdef NOGETPEER
88db71e9 97 u_long Hostnumber = 0;
4b31fbb4 98#endif NOGETPEER
ce5db1eb
SL
99
100 strcpy(Progname, "uucico");
ce5db1eb 101
2ae50b97
JB
102#ifdef BSD4_2
103 sigsetmask(0); /* in case we inherit blocked signals */
104#endif BSD4_2
ce5db1eb
SL
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 */
2af814a5 110 signal(SIGFPE, dbg_signal);
ce5db1eb
SL
111 ret = guinfo(getuid(), User, msg);
112 strcpy(Loginuser, User);
4b31fbb4 113 uucpname(Myname);
88db71e9 114 ASSERT(ret == 0, "BAD UID", CNULL, ret);
ce5db1eb 115
2af814a5
JB
116 setbuf (stderr, CNULL);
117
118 rflags[0] = '\0';
ce5db1eb
SL
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;
ce5db1eb 127 case 'g':
1a85e9d2
RC
128 case 'p':
129 MaxGrade = DefMaxGrade = argv[1][2];
ce5db1eb 130 break;
ce5db1eb
SL
131 case 'r':
132 Role = atoi(&argv[1][2]);
133 break;
88db71e9
RC
134 case 'R':
135 ReverseRole++;
136 Role = MASTER;
137 break;
ce5db1eb 138 case 's':
4b31fbb4
JB
139 strncpy(Rmtname, &argv[1][2], MAXBASENAME);
140 Rmtname[MAXBASENAME] = '\0';
ce5db1eb
SL
141 if (Rmtname[0] != '\0')
142 onesys = 1;
143 break;
144 case 'x':
ce5db1eb
SL
145 Debug = atoi(&argv[1][2]);
146 if (Debug <= 0)
147 Debug = 1;
2af814a5 148 strcat(rflags, argv[1]);
ce5db1eb 149 break;
1a85e9d2
RC
150 case 't':
151 turntime = atoi(&argv[1][2])*60;/* minutes to seconds */
152 break;
88db71e9
RC
153 case 'L': /* local calls only */
154 LocalOnly++;
155 break;
4b31fbb4 156#ifdef NOGETPEER
88db71e9
RC
157 case 'h':
158 Hostnumber = inet_addr(&argv[1][2]);
159 break;
4b31fbb4 160#endif NOGETPEER
ce5db1eb 161 default:
88db71e9 162 printf("unknown flag %s (ignored)\n", argv[1]);
ce5db1eb
SL
163 break;
164 }
165 --argc; argv++;
166 }
167
88db71e9 168 while (argc > 1) {
2af814a5 169 fprintf(stderr, "unknown argument %s (ignored)\n", argv[1]);
88db71e9
RC
170 --argc; argv++;
171 }
ce5db1eb 172
f18f4128
JB
173 if (Debug && Role == MASTER)
174 chkdebug();
175
01af9d69 176 /* Try to run as uucp */
88db71e9
RC
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);
ce5db1eb 187 }
88db71e9
RC
188#endif TIOCNOTTY
189#ifdef BSD4_2
7ebaa22e 190 if (getpgrp(0) == 0) { /* We have no controlling terminal */
88db71e9
RC
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
2af814a5 199 if (Debug) {
2af814a5
JB
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 */
ce5db1eb 208 if (Role == SLAVE) {
88db71e9 209 /* check for /etc/nologin */
01af9d69 210 if (access(NOLOGIN, 0) == 0) {
88db71e9 211 logent(NOLOGIN, "UUCICO SHUTDOWN");
4b31fbb4 212 if (Debug > 4)
88db71e9
RC
213 logent("DEBUGGING", "continuing anyway");
214 else
215 cleanup(1);
216 }
2af814a5
JB
217 Ifn = 0;
218 Ofn = 1;
88db71e9
RC
219#ifdef TCPIP
220 /*
221 * Determine if we are on TCPIP
222 */
2af814a5 223 if (isatty(Ifn) < 0) {
88db71e9
RC
224 IsTcpIp = 1;
225 DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
4b31fbb4
JB
226 } else
227 IsTcpIp = 0;
88db71e9 228#endif TCPIP
ce5db1eb
SL
229 /* initial handshake */
230 onesys = 1;
88db71e9
RC
231 if (!IsTcpIp) {
232#ifdef USG
2af814a5 233 ret = ioctl(Ifn, TCGETA, &Savettyb);
ce5db1eb
SL
234 Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7;
235 Savettyb.c_oflag |= OPOST;
236 Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
88db71e9 237#else !USG
2af814a5 238 ret = ioctl(Ifn, TIOCGETP, &Savettyb);
ce5db1eb
SL
239 Savettyb.sg_flags |= ECHO;
240 Savettyb.sg_flags &= ~RAW;
88db71e9 241#endif !USG
2af814a5 242 ttyn = ttyname(Ifn);
ce5db1eb 243 }
ce5db1eb 244 fixmode(Ifn);
2af814a5
JB
245
246 /*
247 * Initial Message -- tell them we're here, and who we are.
248 */
1a85e9d2 249 sprintf(msg, "here=%s", Myfullname);
88db71e9 250 omsg('S', msg, Ofn);
ce5db1eb
SL
251 signal(SIGALRM, timeout);
252 alarm(MAXMSGTIME);
253 if (setjmp(Sjbuf)) {
254 /* timed out */
88db71e9
RC
255 if (!IsTcpIp) {
256#ifdef USG
2af814a5
JB
257 ret = ioctl(Ifn, TCSETA, &Savettyb);
258
4b31fbb4 259#else !USG
2af814a5 260 ret = ioctl(Ifn, TIOCSETP, &Savettyb);
4b31fbb4 261#endif !USG
ce5db1eb 262 }
88db71e9 263 cleanup(0);
ce5db1eb
SL
264 }
265 for (;;) {
266 ret = imsg(msg, Ifn);
2af814a5 267 if (ret != SUCCESS) {
ce5db1eb 268 alarm(0);
88db71e9
RC
269 if (!IsTcpIp) {
270#ifdef USG
2af814a5 271 ret = ioctl(Ifn, TCSETA, &Savettyb);
4b31fbb4 272#else !USG
2af814a5 273 ret = ioctl(Ifn, TIOCSETP, &Savettyb);
4b31fbb4 274#endif !USG
ce5db1eb 275 }
88db71e9 276 cleanup(0);
ce5db1eb
SL
277 }
278 if (msg[0] == 'S')
279 break;
280 }
281 alarm(0);
282 q = &msg[1];
283 p = pskip(q);
4b31fbb4
JB
284 strncpy(Rmtname, q, MAXBASENAME);
285 Rmtname[MAXBASENAME] = '\0';
2af814a5
JB
286
287 /*
288 * Now that we know who they are, give the audit file the right
289 * name.
290 */
291 setdebug (DBG_PERM);
ce5db1eb 292 DEBUG(4, "sys-%s\n", Rmtname);
a534f0fb 293 /* The versys will also do an alias on the incoming name */
4b31fbb4 294 if (versys(&Rmtname)) {
a534f0fb
JB
295 /* If we don't know them, we won't talk to them... */
296#ifdef NOSTRANGERS
4b31fbb4
JB
297 logent(Rmtname, "UNKNOWN HOST");
298 omsg('R', "You are unknown to me", Ofn);
299 cleanup(0);
4b31fbb4 300#endif NOSTRANGERS
a534f0fb 301 }
88db71e9
RC
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();
2af814a5 310 int fromlen;
88db71e9 311 struct sockaddr_in from;
01af9d69 312 extern char PhoneNumber[];
88db71e9 313
4b31fbb4
JB
314#ifdef NOGETPEER
315 from.sin_addr.s_addr = Hostnumber;
316 from.sin_family = AF_INET;
317#else !NOGETPEER
2af814a5
JB
318 fromlen = sizeof(from);
319 if (getpeername(Ifn, &from, &fromlen) < 0) {
88db71e9
RC
320 logent(Rmtname, "NOT A TCP CONNECTION");
321 omsg('R', "NOT TCP", Ofn);
322 cleanup(0);
323 }
4b31fbb4 324#endif !NOGETPEER
88db71e9
RC
325 hp = gethostbyaddr(&from.sin_addr,
326 sizeof (struct in_addr), from.sin_family);
2af814a5 327 if (hp == NULL) {
88db71e9
RC
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 }
2af814a5 337 if (Debug > 99)
88db71e9 338 logent(Rmtname,"Request from IP-Host name =");
01af9d69
JB
339 /*
340 * The following is to determine if the name given us by
341 * the Remote uucico matches any of the names
88db71e9
RC
342 * given its network number (remote machine) in our
343 * host table.
01af9d69
JB
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.
88db71e9 351 */
01af9d69
JB
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) {
88db71e9
RC
354 if (Debug > 99)
355 logent(q,"Found in host Tables");
01af9d69
JB
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);
88db71e9
RC
363 }
364 }
365#endif BSDTCP
366
2af814a5 367 if (mlock(Rmtname)) {
ce5db1eb
SL
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 */
88db71e9 377 systat(Rmtname, SS_CALLBACK, "CALLING BACK");
ce5db1eb
SL
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)) {
ce5db1eb 387 case 'x':
2af814a5
JB
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 }
ce5db1eb
SL
399 break;
400 case 'Q':
401 seq = atoi(++p);
402 break;
1a85e9d2
RC
403 case 'p':
404 MaxGrade = DefMaxGrade = *++p;
405 DEBUG(4, "MaxGrade set to %c\n", MaxGrade);
406 break;
4b31fbb4
JB
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;
ce5db1eb
SL
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 }
88db71e9 424#ifdef GNXSEQ
ce5db1eb
SL
425 if ((ret = gnxseq(Rmtname)) == seq) {
426 omsg('R', "OK", Ofn);
427 cmtseq();
88db71e9
RC
428 } else {
429#else !GNXSEQ
430 if (seq == 0)
431 omsg('R', "OK", Ofn);
ce5db1eb 432 else {
88db71e9 433#endif !GNXSEQ
ce5db1eb 434 systat(Rmtname, Stattype[7], Stattext[7]);
4b31fbb4 435 logent("BAD SEQ", "FAILED HANDSHAKE");
88db71e9 436#ifdef GNXSEQ
ce5db1eb 437 ulkseq();
88db71e9 438#endif GNXSEQ
ce5db1eb
SL
439 omsg('R', "BADSEQ", Ofn);
440 cleanup(0);
441 }
ce5db1eb
SL
442 if (ttyn != NULL)
443 chmod(ttyn, 0600);
444 }
88db71e9 445
ce5db1eb 446loop:
88db71e9
RC
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 }
ce5db1eb
SL
455 if (!onesys) {
456 ret = gnsys(Rmtname, Spool, CMDPRE);
2af814a5 457 setdebug(DBG_PERM);
ce5db1eb
SL
458 if (ret == FAIL)
459 cleanup(100);
4b31fbb4 460 if (ret == SUCCESS)
ce5db1eb 461 cleanup(0);
88db71e9 462 } else if (Role == MASTER && callok(Rmtname) != 0) {
ce5db1eb
SL
463 logent("SYSTEM STATUS", "CAN NOT CALL");
464 cleanup(0);
465 }
466
4b31fbb4 467 sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
ce5db1eb 468
88db71e9
RC
469 signal(SIGINT, SIG_IGN);
470 signal(SIGQUIT, SIG_IGN);
ce5db1eb 471 if (Role == MASTER) {
88db71e9 472 /* check for /etc/nologin */
01af9d69 473 if (access(NOLOGIN, 0) == 0) {
88db71e9 474 logent(NOLOGIN, "UUCICO SHUTDOWN");
4b31fbb4 475 if (Debug > 4)
88db71e9
RC
476 logent("DEBUGGING", "continuing anyway");
477 else
478 cleanup(1);
479 }
ce5db1eb 480 /* master part */
ce5db1eb 481 signal(SIGHUP, SIG_IGN);
ce5db1eb
SL
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);
01af9d69 492 if (mlock(Rmtname) != SUCCESS) {
ce5db1eb 493 logent(msg, "LOCKED");
88db71e9 494 US_SST(us_s_lock);
ce5db1eb
SL
495 goto next;
496 }
497 Ofn = Ifn = conn(Rmtname);
498 if (Ofn < 0) {
88db71e9
RC
499 if (Ofn != CF_TIME)
500 logent(msg, _FAILED);
501 /* avoid excessive 'wrong time' info */
4b31fbb4 502 if (Stattype[-Ofn] != SS_WRONGTIME){
88db71e9
RC
503 systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]);
504 US_SST(-Ofn);
505 UB_SST(-Ofn);
506 }
ce5db1eb 507 goto next;
88db71e9 508 } else {
ce5db1eb 509 logent(msg, "SUCCEEDED");
88db71e9
RC
510 US_SST(us_s_cok);
511 UB_SST(ub_ok);
512 }
513#ifdef TCPIP
514 /*
515 * Determine if we are on TCPIP
516 */
2af814a5 517 if (isatty(Ifn) == 0) {
88db71e9
RC
518 IsTcpIp = 1;
519 DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
4b31fbb4
JB
520 } else
521 IsTcpIp = 0;
88db71e9
RC
522#endif
523
ce5db1eb
SL
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);
88db71e9
RC
532 logent("imsg 1", _FAILED);
533 goto Failure;
ce5db1eb
SL
534 }
535 if (msg[0] == 'S')
536 break;
537 }
538 alarm(MAXMSGTIME);
88db71e9 539#ifdef GNXSEQ
ce5db1eb 540 seq = gnxseq(Rmtname);
88db71e9
RC
541#else !GNXSEQ
542 seq = 0;
543#endif !GNXSEQ
1a85e9d2 544 if (MaxGrade != '\177') {
4b31fbb4 545 DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade);
9313cec6
JB
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);
ce5db1eb
SL
550 omsg('S', msg, Ofn);
551 for (;;) {
552 ret = imsg(msg, Ifn);
553 DEBUG(4, "msg-%s\n", msg);
88db71e9 554 if (ret != SUCCESS) {
ce5db1eb 555 alarm(0);
88db71e9 556#ifdef GNXSEQ
ce5db1eb 557 ulkseq();
88db71e9
RC
558#endif GNXSEQ
559 logent("imsg 2", _FAILED);
560 goto Failure;
ce5db1eb
SL
561 }
562 if (msg[0] == 'R')
563 break;
564 }
565 alarm(0);
566 if (msg[1] == 'B') {
567 /* bad sequence */
4b31fbb4 568 logent("BAD SEQ", "FAILED HANDSHAKE");
88db71e9
RC
569 US_SST(us_s_hand);
570 systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]);
571#ifdef GNXSEQ
ce5db1eb 572 ulkseq();
88db71e9 573#endif GNXSEQ
ce5db1eb
SL
574 goto next;
575 }
576 if (strcmp(&msg[1], "OK") != SAME) {
4b31fbb4 577 logent(&msg[1], "FAILED HANDSHAKE");
88db71e9
RC
578 US_SST(us_s_hand);
579#ifdef GNXSEQ
ce5db1eb 580 ulkseq();
88db71e9
RC
581#endif GNXSEQ
582 systat(Rmtname, SS_INPROGRESS,
583 strcmp(&msg[1], "CB") == SAME?
4b31fbb4 584 "AWAITING CALLBACK": "FAILED HANDSHAKE");
ce5db1eb
SL
585 goto next;
586 }
88db71e9 587#ifdef GNXSEQ
ce5db1eb 588 cmtseq();
88db71e9 589#endif GNXSEQ
ce5db1eb 590 }
88db71e9 591 DEBUG(1, "Rmtname %s, ", Rmtname);
ce5db1eb
SL
592 DEBUG(1, "Role %s, ", Role ? "MASTER" : "SLAVE");
593 DEBUG(1, "Ifn - %d, ", Ifn);
594 DEBUG(1, "Loginuser - %s\n", Loginuser);
595
2af814a5
JB
596 ttyn = ttyname(Ifn);
597
ce5db1eb 598 alarm(MAXMSGTIME);
1a85e9d2 599 if (ret=setjmp(Sjbuf))
ce5db1eb
SL
600 goto Failure;
601 ret = startup(Role);
602 alarm(0);
603 if (ret != SUCCESS) {
88db71e9 604 logent("startup", _FAILED);
ce5db1eb 605Failure:
88db71e9 606 US_SST(us_s_start);
1a85e9d2
RC
607 systat(Rmtname, SS_FAIL, ret > 0 ? "CONVERSATION FAILED" :
608 "STARTUP FAILED");
ce5db1eb 609 goto next;
88db71e9 610 } else {
2af814a5
JB
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");
88db71e9 619 US_SST(us_s_gress);
ce5db1eb
SL
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);
88db71e9 626 if (ret == SUCCESS) {
ce5db1eb 627 logent("conversation complete", "OK");
88db71e9 628 US_SST(us_s_ok);
ce5db1eb
SL
629 rmstat(Rmtname);
630
88db71e9
RC
631 } else {
632 logent("conversation complete", _FAILED);
633 US_SST(us_s_cf);
634 systat(Rmtname, SS_FAIL, "CONVERSATION FAILED");
ce5db1eb
SL
635 }
636 alarm(MAXMSGTIME);
ce5db1eb
SL
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);
88db71e9
RC
649 clsacu();
650 rmlock(CNULL);
ce5db1eb
SL
651 }
652next:
653 if (!onesys) {
654 goto loop;
655 }
656 cleanup(0);
657}
658
88db71e9 659#ifndef USG
ce5db1eb
SL
660struct sgttyb Hupvec;
661#endif
662
2af814a5
JB
663/*
664 * cleanup and exit with "code" status
ce5db1eb 665 */
ce5db1eb
SL
666cleanup(code)
667register int code;
668{
ce5db1eb
SL
669 signal(SIGINT, SIG_IGN);
670 signal(SIGHUP, SIG_IGN);
671 rmlock(CNULL);
2af814a5 672 sleep(5); /* Wait for any pending output */
ce5db1eb
SL
673 clsacu();
674 logcls();
675 if (Role == SLAVE) {
88db71e9
RC
676 if (!IsTcpIp) {
677#ifdef USG
ce5db1eb 678 Savettyb.c_cflag |= HUPCL;
4b31fbb4 679 (void) ioctl(0, TCSETA, &Savettyb);
88db71e9 680#else !USG
4b31fbb4 681 (void) ioctl(0, TIOCHPCL, STBNULL);
1a85e9d2 682#ifdef TIOCSDTR
4b31fbb4 683 (void) ioctl(0, TIOCCDTR, STBNULL);
1a85e9d2 684 sleep(2);
4b31fbb4 685 (void) ioctl(0, TIOCSDTR, STBNULL);
1a85e9d2 686#else !TIOCSDTR
4b31fbb4 687 (void) ioctl(0, TIOCGETP, &Hupvec);
ce5db1eb
SL
688 Hupvec.sg_ispeed = B0;
689 Hupvec.sg_ospeed = B0;
4b31fbb4 690 (void) ioctl(0, TIOCSETP, &Hupvec);
2af814a5 691#endif !TIOCSDTR
ce5db1eb 692 sleep(2);
4b31fbb4 693 (void) ioctl(0, TIOCSETP, &Savettyb);
88db71e9 694 /* make *sure* exclusive access is off */
4b31fbb4 695 (void) ioctl(0, TIOCNXCL, STBNULL);
88db71e9 696#endif !USG
ce5db1eb 697 }
ce5db1eb
SL
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 }
1a85e9d2
RC
707#ifdef DIALINOUT
708 /* reenable logins on dialout */
709 reenable();
710#endif DIALINOUT
ce5db1eb
SL
711 if (code == 0)
712 xuuxqt();
88db71e9
RC
713 else
714 DEBUG(1, "exit code %d\n", code);
2af814a5 715 setdebug (DBG_CLEAN);
ce5db1eb
SL
716 exit(code);
717}
718
2af814a5
JB
719/*
720 * on interrupt - remove locks and exit
ce5db1eb
SL
721 */
722
723onintr(inter)
724register int inter;
725{
726 char str[30];
727 signal(inter, SIG_IGN);
728 sprintf(str, "SIGNAL %d", inter);
729 logent(str, "CAUGHT");
88db71e9 730 US_SST(us_s_intr);
4b31fbb4 731 if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME))
88db71e9
RC
732 systat(Rmtname, SS_FAIL, str);
733 if (inter == SIGPIPE && !onesys)
734 longjmp(Pipebuf, 1);
ce5db1eb
SL
735 cleanup(inter);
736}
737
ce5db1eb
SL
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 */
2af814a5 743dbg_signal()
ce5db1eb 744{
2af814a5
JB
745 Debug = (Debug == 0) ? 30 : 0;
746 setdebug(DBG_PERM);
747 if (Debug > 0)
748 logent("Signal Enabled", "DEBUG");
ce5db1eb
SL
749}
750
751
2af814a5
JB
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.
ce5db1eb 760 *
2af814a5
JB
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.
ce5db1eb 764 */
2af814a5
JB
765setdebug(parm)
766int parm;
ce5db1eb 767{
2af814a5
JB
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 */
ce5db1eb 772
2af814a5
JB
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 }
ce5db1eb 793 return;
2af814a5 794 }
ce5db1eb 795
2af814a5
JB
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}
ce5db1eb 869
4b31fbb4 870/*
2af814a5 871 * catch SIGALRM routine
ce5db1eb 872 */
ce5db1eb
SL
873timeout()
874{
4b31fbb4
JB
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 }
88db71e9 882 }
ce5db1eb
SL
883 longjmp(Sjbuf, 1);
884}
885
886static char *
887pskip(p)
888register char *p;
889{
88db71e9 890 while(*p && *p != ' ')
ce5db1eb 891 ++p;
4b31fbb4 892 while(*p && *p == ' ')
88db71e9
RC
893 *p++ = 0;
894 return p;
ce5db1eb 895}