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