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