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: }

Defined functions

cleanup defined in line 666; used 22 times
dbg_signal defined in line 743; used 2 times
main defined in line 84; used 1 times
onintr defined in line 723; used 6 times
pskip defined in line 886; used 3 times
setdebug defined in line 765; used 6 times
timeout defined in line 873; used 4 times

Defined variables

Hupvec defined in line 660; used 4 times
Pipebuf defined in line 32; used 2 times
ReverseRole defined in line 63; used 1 times
Role defined in line 64; used 15 times
Savettyb defined in line 77; used 15 times
Sjbuf defined in line 31; used 11 times
Stattext defined in line 35; used 3 times
Stattype defined in line 47; used 3 times
onesys defined in line 65; used 6 times
sccsid defined in line 2; never used
ttyn defined in line 67; used 8 times
turntime defined in line 66; used 4 times

Defined macros

DBG_CLEAN defined in line 61; used 3 times
DBG_PERM defined in line 60; used 6 times
DBG_TEMP defined in line 59; used 2 times
NOGETPEER defined in line 28; used 4 times
Last modified: 1986-04-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2238
Valid CSS Valid XHTML 1.0 Strict