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

Defined functions

cleanup defined in line 667; used 22 times
dbg_signal defined in line 744; used 2 times
main defined in line 85; used 1 times
onintr defined in line 724; used 6 times
pskip defined in line 887; used 3 times
setdebug defined in line 766; used 6 times
timeout defined in line 874; used 4 times

Defined variables

Hupvec defined in line 661; used 4 times
Pipebuf defined in line 33; used 2 times
ReverseRole defined in line 64; used 1 times
Role defined in line 65; used 15 times
Savettyb defined in line 78; used 15 times
Sjbuf defined in line 32; used 11 times
Stattext defined in line 36; used 3 times
Stattype defined in line 48; used 3 times
onesys defined in line 66; used 6 times
sccsid defined in line 2; never used
ttyn defined in line 68; used 8 times
turntime defined in line 67; used 4 times

Defined macros

DBG_CLEAN defined in line 62; used 3 times
DBG_PERM defined in line 61; used 6 times
DBG_TEMP defined in line 60; used 2 times
NOGETPEER defined in line 29; used 4 times
Last modified: 1997-10-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6615
Valid CSS Valid XHTML 1.0 Strict