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