1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2014 Garrett D'Amore 23 */ 24 /* 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 30 /* All Rights Reserved */ 31 32 33 /* 34 35 * uucp file transfer program: 36 * to place a call to a remote machine, login, and 37 * copy files between the two machines. 38 39 */ 40 /* 41 * Added check to limit the total number of uucicos as defined 42 * in the Limits file. 43 * 44 * Added -f flag to "force execution", ignoring the limit on the 45 * number of uucicos. This will be used when invoking uucico from 46 * Uutry. 47 */ 48 49 #include "uucp.h" 50 #include "log.h" 51 52 #ifndef V7 53 #include <sys/mkdev.h> 54 #endif /* V7 */ 55 56 #ifdef TLI 57 #include <sys/tiuser.h> 58 #endif /* TLI */ 59 60 jmp_buf Sjbuf; 61 extern unsigned msgtime; 62 char uuxqtarg[MAXBASENAME] = {'\0'}; 63 int uuxqtflag = 0; 64 65 extern int (*Setup)(), (*Teardown)(); /* defined in interface.c */ 66 67 #define USAGE "Usage: %s [-x NUM] [-r [0|1]] -s SYSTEM -u USERID -d SPOOL -i INTERFACE [-f]\n" 68 extern void closedem(); 69 void cleanup(), cleanTM(); 70 71 extern int sysaccess(), guinfo(), eaccess(), countProcs(), interface(), 72 savline(), omsg(), restline(), imsg(), callok(), gnxseq(), 73 cmtseq(), conn(), startup(), cntrl(); 74 extern void setuucp(), fixline(), gename(), ulkseq(), pfEndfile(); 75 76 #ifdef NOSTRANGERS 77 static void checkrmt(); /* See if we want to talk to remote. */ 78 #endif /* NOSTRANGERS */ 79 80 extern char *Mytype; 81 82 static char *pskip(); 83 84 int 85 main(argc, argv, envp) 86 int argc; 87 char *argv[]; 88 char **envp; 89 { 90 91 extern void intrEXIT(), onintr(), timeout(); 92 extern void setservice(); 93 #ifndef ATTSVR3 94 void setTZ(); 95 #endif /* ATTSVR3 */ 96 int ret, seq, exitcode; 97 char file[NAMESIZE]; 98 char msg[BUFSIZ], *p, *q; 99 char xflag[6]; /* -xN N is single digit */ 100 char *ttyn; 101 char *iface; /* interface name */ 102 char cb[128]; 103 time_t ts, tconv; 104 char lockname[MAXFULLNAME]; 105 struct limits limitval; 106 int maxnumb; 107 int force = 0; /* set to force execution, ignoring uucico limit */ 108 char gradedir[2*NAMESIZE]; 109 110 /* Set locale environment variables local definitions */ 111 (void) setlocale(LC_ALL, ""); 112 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 113 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 114 #endif 115 (void) textdomain(TEXT_DOMAIN); 116 117 Ulimit = ulimit(1,0L); 118 Uid = getuid(); 119 Euid = geteuid(); /* this should be UUCPUID */ 120 if (Uid == 0) 121 setuid(UUCPUID); 122 Env = envp; 123 Role = SLAVE; 124 strcpy(Logfile, LOGCICO); 125 *Rmtname = NULLCHAR; 126 Ifn = Ofn = -1; /* must be set before signal handlers */ 127 128 closedem(); 129 time(&Nstat.t_qtime); 130 tconv = Nstat.t_start = Nstat.t_qtime; 131 strcpy(Progname, "uucico"); 132 setservice(Progname); 133 ret = sysaccess(EACCESS_SYSTEMS); 134 ASSERT(ret == 0, Ct_OPEN, "Systems", ret); 135 ret = sysaccess(EACCESS_DEVICES); 136 ASSERT(ret == 0, Ct_OPEN, "Devices", ret); 137 ret = sysaccess(EACCESS_DIALERS); 138 ASSERT(ret == 0, Ct_OPEN, "Dialers", ret); 139 Pchar = 'C'; 140 (void) signal(SIGILL, intrEXIT); 141 (void) signal(SIGTRAP, intrEXIT); 142 (void) signal(SIGIOT, intrEXIT); 143 (void) signal(SIGEMT, intrEXIT); 144 (void) signal(SIGFPE, intrEXIT); 145 (void) signal(SIGBUS, intrEXIT); 146 (void) signal(SIGSEGV, intrEXIT); 147 (void) signal(SIGSYS, intrEXIT); 148 if (signal(SIGPIPE, SIG_IGN) != SIG_IGN) /* This for sockets */ 149 (void) signal(SIGPIPE, intrEXIT); 150 (void) signal(SIGINT, onintr); 151 (void) signal(SIGHUP, onintr); 152 (void) signal(SIGQUIT, onintr); 153 (void) signal(SIGTERM, onintr); 154 #ifdef SIGUSR1 155 (void) signal(SIGUSR1, SIG_IGN); 156 #endif 157 #ifdef SIGUSR2 158 (void) signal(SIGUSR2, SIG_IGN); 159 #endif 160 #ifdef BSD4_2 161 (void) sigsetmask(sigblock(0) & ~(1 << (SIGALRM - 1))); 162 #endif /*BSD4_2*/ 163 164 pfInit(); 165 scInit("xfer"); 166 ret = guinfo(Euid, User); 167 ASSERT(ret == 0, "BAD UID ", "", ret); 168 strncpy(Uucp, User, NAMESIZE); 169 170 setuucp(User); 171 172 *xflag = NULLCHAR; 173 iface = "UNIX"; 174 175 while ((ret = getopt(argc, argv, "fd:c:r:s:x:u:i:")) != EOF) { 176 switch (ret) { 177 case 'd': 178 if ( eaccess(optarg, 01) != 0 ) { 179 (void) fprintf(stderr, gettext("%s: cannot" 180 " access spool directory %s\n"), 181 Progname, optarg); 182 exit(1); 183 } 184 Spool = optarg; 185 break; 186 case 'c': 187 Mytype = optarg; 188 break; 189 case 'f': 190 ++force; 191 break; 192 case 'r': 193 if ( (Role = atoi(optarg)) != MASTER && Role != SLAVE ) { 194 (void) fprintf(stderr, gettext("%s: bad value" 195 " '%s' for -r argument\n" USAGE), 196 Progname, optarg, Progname); 197 exit(1); 198 } 199 break; 200 case 's': 201 strncpy(Rmtname, optarg, MAXFULLNAME-1); 202 if (versys(Rmtname)) { 203 (void) fprintf(stderr, 204 gettext("%s: %s not in Systems file\n"), 205 Progname, optarg); 206 cleanup(101); 207 } 208 /* set args for possible xuuxqt call */ 209 strcpy(uuxqtarg, Rmtname); 210 /* if versys put a longer name in, truncate it again */ 211 Rmtname[MAXBASENAME] = '\0'; 212 break; 213 case 'x': 214 Debug = atoi(optarg); 215 if (Debug <= 0) 216 Debug = 1; 217 if (Debug > 9) 218 Debug = 9; 219 (void) sprintf(xflag, "-x%d", Debug); 220 break; 221 case 'u': 222 DEBUG(4, "Loginuser %s specified\n", optarg); 223 strncpy(Loginuser, optarg, NAMESIZE); 224 Loginuser[NAMESIZE - 1] = NULLCHAR; 225 break; 226 case 'i': 227 /* interface type */ 228 iface = optarg; 229 break; 230 default: 231 (void) fprintf(stderr, gettext(USAGE), Progname); 232 exit(1); 233 } 234 } 235 236 if (Role == MASTER || *Loginuser == NULLCHAR) { 237 ret = guinfo(Uid, Loginuser); 238 ASSERT(ret == 0, "BAD LOGIN_UID ", "", ret); 239 } 240 241 /* limit the total number of uucicos */ 242 if (force) { 243 DEBUG(4, "force flag set (ignoring uucico limit)\n%s", ""); 244 } else if (scanlimit("uucico", &limitval) == FAIL) { 245 DEBUG(1, "No limits for uucico in %s\n", LIMITS); 246 } else { 247 maxnumb = limitval.totalmax; 248 if (maxnumb < 0) { 249 DEBUG(4, "Non-positive limit for uucico in %s\n", LIMITS); 250 DEBUG(1, "No limits for uucico\n%s", ""); 251 } else { 252 DEBUG(4, "Uucico limit %d -- ", maxnumb); 253 (void) sprintf(lockname, "%s.", LOCKPRE); 254 if (countProcs(lockname, (maxnumb-1)) == FALSE) { 255 DEBUG(4, "exiting\n%s", ""); 256 cleanup(101); 257 } 258 DEBUG(4, "continuing\n%s", ""); 259 } 260 } 261 262 pfStrtConn((Role == MASTER) ? 'M' : 'S'); 263 if (Role == MASTER) { 264 if (*Rmtname == NULLCHAR) { 265 DEBUG(5, "No -s specified\n%s" , ""); 266 cleanup(101); 267 } 268 /* get Myname - it depends on who I'm calling--Rmtname */ 269 (void) mchFind(Rmtname); 270 myName(Myname); 271 if (EQUALSN(Rmtname, Myname, MAXBASENAME)) { 272 DEBUG(5, "This system specified: -sMyname: %s, ", Myname); 273 cleanup(101); 274 } 275 acInit("xfer"); 276 } 277 278 ASSERT(chdir(Spool) == 0, Ct_CHDIR, Spool, errno); 279 strcpy(Wrkdir, Spool); 280 281 scReqsys((Role == MASTER) ? Myname : Rmtname); /* log requestor system */ 282 283 if (Role == SLAVE) { 284 285 #ifndef ATTSVR3 286 setTZ(); 287 #endif /* ATTSVR3 */ 288 289 if (freopen(RMTDEBUG, "a", stderr) == 0) { 290 errent(Ct_OPEN, RMTDEBUG, errno, __FILE__, __LINE__); 291 freopen("/dev/null", "w", stderr); 292 } 293 if ( interface(iface) ) { 294 (void)fprintf(stderr, 295 "%s: invalid interface %s\n", Progname, iface); 296 cleanup(101); 297 } 298 /*master setup will be called from processdev()*/ 299 if ( (*Setup)( Role, &Ifn, &Ofn ) ) { 300 DEBUG(5, "SLAVE Setup failed%s", ""); 301 cleanup(101); 302 } 303 304 /* 305 * initial handshake 306 */ 307 (void) savline(); 308 fixline(Ifn, 0, D_ACU); 309 /* get MyName - use logFind to check PERMISSIONS file */ 310 (void) logFind(Loginuser, ""); 311 myName(Myname); 312 313 DEBUG(4,"cico.c: Myname - %s\n",Myname); 314 DEBUG(4,"cico.c: Loginuser - %s\n",Loginuser); 315 fflush(stderr); 316 Nstat.t_scall = times(&Nstat.t_tga); 317 (void) sprintf(msg, "here=%s", Myname); 318 omsg('S', msg, Ofn); 319 (void) signal(SIGALRM, timeout); 320 (void) alarm(msgtime); /* give slow machines a second chance */ 321 if (setjmp(Sjbuf)) { 322 323 /* 324 * timed out 325 */ 326 (void) restline(); 327 rmlock(CNULL); 328 exit(0); 329 } 330 for (;;) { 331 ret = imsg(msg, Ifn); 332 if (ret != 0) { 333 (void) alarm(0); 334 (void) restline(); 335 rmlock(CNULL); 336 exit(0); 337 } 338 if (msg[0] == 'S') 339 break; 340 } 341 Nstat.t_ecall = times(&Nstat.t_tga); 342 (void) alarm(0); 343 q = &msg[1]; 344 p = pskip(q); 345 strncpy(Rmtname, q, MAXBASENAME); 346 Rmtname[MAXBASENAME] = '\0'; 347 348 seq = 0; 349 while (p && *p == '-') { 350 q = pskip(p); 351 switch(*(++p)) { 352 case 'x': 353 Debug = atoi(++p); 354 if (Debug <= 0) 355 Debug = 1; 356 (void) sprintf(xflag, "-x%d", Debug); 357 break; 358 case 'Q': 359 seq = atoi(++p); 360 if (seq < 0) 361 seq = 0; 362 break; 363 #ifdef MAXGRADE 364 case 'v': /* version -- -vname=val or -vname */ 365 if (strncmp(++p, "grade=", 6) == 0 && 366 isalnum(p[6])) 367 MaxGrade = p[6]; 368 break; 369 #endif /* MAXGRADE */ 370 case 'R': 371 Restart++; 372 p++; 373 break; 374 case 'U': 375 SizeCheck++; 376 RemUlimit = strtol(++p, (char **) NULL,0); 377 break; 378 default: 379 break; 380 } 381 p = q; 382 } 383 DEBUG(4, "sys-%s\n", Rmtname); 384 if (strpbrk(Rmtname, Shchar) != NULL) { 385 DEBUG(4, "Bad remote system name '%s'\n", Rmtname); 386 logent(Rmtname, "BAD REMOTE SYSTEM NAME"); 387 omsg('R', "Bad remote system name", Ofn); 388 cleanup(101); 389 } 390 if (Restart) 391 CDEBUG(1,"Checkpoint Restart enabled\n%s", ""); 392 393 #ifdef NOSTRANGERS 394 checkrmt(); /* Do we know the remote system. */ 395 #else 396 (void) versys(Rmtname); /* in case the real name is longer */ 397 #endif /* NOSTRANGERS */ 398 399 (void) sprintf(lockname, "%ld", (long) getpid()); 400 if (umlock(LOCKPRE, lockname)) { 401 omsg('R', "LCK", Ofn); 402 cleanup(101); 403 } 404 405 /* validate login using PERMISSIONS file */ 406 if (logFind(Loginuser, Rmtname) == FAIL) { 407 scWrite(); /* log security violation */ 408 Uerror = SS_BAD_LOG_MCH; 409 logent(UERRORTEXT, "FAILED"); 410 systat(Rmtname, SS_BAD_LOG_MCH, UERRORTEXT, 411 Retrytime); 412 omsg('R', "LOGIN", Ofn); 413 cleanup(101); 414 } 415 416 ret = callBack(); 417 DEBUG(4,"return from callcheck: %s",ret ? "TRUE" : "FALSE"); 418 if (ret==TRUE) { 419 (void) signal(SIGINT, SIG_IGN); 420 (void) signal(SIGHUP, SIG_IGN); 421 omsg('R', "CB", Ofn); 422 logent("CALLBACK", "REQUIRED"); 423 /* 424 * set up for call back 425 */ 426 chremdir(Rmtname); 427 (void) sprintf(file, "%s/%c", Rmtname, D_QUEUE); 428 chremdir(file); 429 gename(CMDPRE, Rmtname, 'C', file); 430 (void) close(creat(file, CFILEMODE)); 431 if (callok(Rmtname) == SS_CALLBACK_LOOP) { 432 systat(Rmtname, SS_CALLBACK_LOOP, "CALL BACK - LOOP", Retrytime); 433 } else { 434 systat(Rmtname, SS_CALLBACK, "CALL BACK", Retrytime); 435 xuucico(Rmtname); 436 } 437 cleanup(101); 438 } 439 440 if (callok(Rmtname) == SS_SEQBAD) { 441 Uerror = SS_SEQBAD; 442 logent(UERRORTEXT, "PREVIOUS"); 443 omsg('R', "BADSEQ", Ofn); 444 cleanup(101); 445 } 446 447 if (gnxseq(Rmtname) == seq) { 448 if (Restart) { 449 if (SizeCheck) 450 (void) sprintf (msg, "OK -R -U0x%lx %s", 451 Ulimit, xflag); 452 else 453 (void) sprintf (msg, "OK -R %s", xflag); 454 omsg('R', msg, Ofn); 455 } else 456 omsg('R', "OK", Ofn); 457 (void) cmtseq(); 458 } else { 459 Uerror = SS_SEQBAD; 460 systat(Rmtname, SS_SEQBAD, UERRORTEXT, Retrytime); 461 logent(UERRORTEXT, "HANDSHAKE FAILED"); 462 ulkseq(); 463 omsg('R', "BADSEQ", Ofn); 464 cleanup(101); 465 } 466 ttyn = ttyname(Ifn); 467 if (ttyn != CNULL && *ttyn != NULLCHAR) { 468 struct stat ttysbuf; 469 if ( fstat(Ifn,&ttysbuf) == 0 ) 470 Dev_mode = ttysbuf.st_mode; 471 else 472 Dev_mode = R_DEVICEMODE; 473 if ( EQUALSN(ttyn,"/dev/",5) ) 474 strcpy(Dc, ttyn+5); 475 else 476 strcpy(Dc, ttyn); 477 chmod(ttyn, S_DEVICEMODE); 478 } else 479 strcpy(Dc, "notty"); 480 /* set args for possible xuuxqt call */ 481 strcpy(uuxqtarg, Rmtname); 482 } 483 484 strcpy(User, Uucp); 485 /* 486 * Ensure reasonable ulimit (MINULIMIT) 487 */ 488 489 #ifndef V7 490 { 491 long minulimit; 492 minulimit = ulimit(1, (long) 0); 493 ASSERT(minulimit >= MINULIMIT, "ULIMIT TOO SMALL", 494 Loginuser, (int) minulimit); 495 } 496 #endif 497 if (Role == MASTER && callok(Rmtname) != 0) { 498 logent("SYSTEM STATUS", "CAN NOT CALL"); 499 cleanup(101); 500 } 501 502 chremdir(Rmtname); 503 504 (void) strcpy(Wrkdir, RemSpool); 505 if (Role == MASTER) { 506 507 /* 508 * master part 509 */ 510 (void) signal(SIGINT, SIG_IGN); 511 (void) signal(SIGHUP, SIG_IGN); 512 (void) signal(SIGQUIT, SIG_IGN); 513 if (Ifn != -1 && Role == MASTER) { 514 (void) (*Write)(Ofn, EOTMSG, strlen(EOTMSG)); 515 (void) close(Ofn); 516 (void) close(Ifn); 517 Ifn = Ofn = -1; 518 rmlock(CNULL); 519 sleep(3); 520 } 521 522 /* 523 * Find the highest priority job grade that has 524 * jobs to do. This is needed to form the lock name. 525 */ 526 527 findgrade(RemSpool, JobGrade); 528 DEBUG(4, "Job grade to process - %s\n", JobGrade); 529 530 /* 531 * Lock the job grade if there is one to process. 532 */ 533 534 if (*JobGrade != NULLCHAR) { 535 (void) sprintf(gradedir, "%s/%s", Rmtname, JobGrade); 536 chremdir(gradedir); 537 538 (void) sprintf(lockname, "%.*s.%s", SYSNSIZE, Rmtname, JobGrade); 539 (void) sprintf(msg, "call to %s - process job grade %s ", 540 Rmtname, JobGrade); 541 if (umlock(LOCKPRE, lockname) != 0) { 542 logent(msg, "LOCKED"); 543 CDEBUG(1, "Currently Talking With %s\n", 544 Rmtname); 545 cleanup(100); 546 } 547 } else { 548 (void) sprintf(msg, "call to %s - no work", Rmtname); 549 } 550 551 Nstat.t_scall = times(&Nstat.t_tga); 552 Ofn = Ifn = conn(Rmtname); 553 Nstat.t_ecall = times(&Nstat.t_tga); 554 if (Ofn < 0) { 555 delock(LOCKPRE, lockname); 556 logent(UERRORTEXT, "CONN FAILED"); 557 systat(Rmtname, Uerror, UERRORTEXT, Retrytime); 558 cleanup(101); 559 } else { 560 logent(msg, "SUCCEEDED"); 561 ttyn = ttyname(Ifn); 562 if (ttyn != CNULL && *ttyn != NULLCHAR) { 563 struct stat ttysbuf; 564 if ( fstat(Ifn,&ttysbuf) == 0 ) 565 Dev_mode = ttysbuf.st_mode; 566 else 567 Dev_mode = R_DEVICEMODE; 568 chmod(ttyn, M_DEVICEMODE); 569 } 570 } 571 572 if (setjmp(Sjbuf)) { 573 delock(LOCKPRE, lockname); 574 Uerror = SS_LOGIN_FAILED; 575 logent(Rmtname, UERRORTEXT); 576 systat(Rmtname, SS_LOGIN_FAILED, 577 UERRORTEXT, Retrytime); 578 DEBUG(4, "%s - failed\n", UERRORTEXT); 579 cleanup(101); 580 } 581 (void) signal(SIGALRM, timeout); 582 /* give slow guys lots of time to thrash */ 583 (void) alarm(2 * msgtime); 584 for (;;) { 585 ret = imsg(msg, Ifn); 586 if (ret != 0) { 587 continue; /* try again */ 588 } 589 if (msg[0] == 'S') 590 break; 591 } 592 (void) alarm(0); 593 if(EQUALSN("here=", &msg[1], 5)){ 594 /* This may be a problem, we check up to MAXBASENAME 595 * characters now. The old comment was: 596 * this is a problem. We'd like to compare with an 597 * untruncated Rmtname but we fear incompatability. 598 * So we'll look at most 6 chars (at most). 599 */ 600 (void) pskip(&msg[6]); 601 if (!EQUALSN(&msg[6], Rmtname, MAXBASENAME)) { 602 delock(LOCKPRE, lockname); 603 Uerror = SS_WRONG_MCH; 604 logent(&msg[6], UERRORTEXT); 605 systat(Rmtname, SS_WRONG_MCH, UERRORTEXT, 606 Retrytime); 607 DEBUG(4, "%s - failed\n", UERRORTEXT); 608 cleanup(101); 609 } 610 } 611 CDEBUG(1,"Login Successful: System=%s\n",&msg[6]); 612 seq = gnxseq(Rmtname); 613 (void) sprintf(msg, "%s -Q%d -R -U0x%lx %s", 614 Myname, seq, Ulimit, xflag); 615 #ifdef MAXGRADE 616 if (MaxGrade != NULLCHAR) { 617 p = strchr(msg, NULLCHAR); 618 sprintf(p, " -vgrade=%c", MaxGrade); 619 } 620 #endif /* MAXGRADE */ 621 omsg('S', msg, Ofn); 622 (void) alarm(msgtime); /* give slow guys some thrash time */ 623 for (;;) { 624 ret = imsg(msg, Ifn); 625 DEBUG(4, "msg-%s\n", msg); 626 if (ret != 0) { 627 (void) alarm(0); 628 delock(LOCKPRE, lockname); 629 ulkseq(); 630 cleanup(101); 631 } 632 if (msg[0] == 'R') 633 break; 634 } 635 (void) alarm(0); 636 637 /* check for rejects from remote */ 638 Uerror = 0; 639 if (EQUALS(&msg[1], "LCK")) 640 Uerror = SS_RLOCKED; 641 else if (EQUALS(&msg[1], "LOGIN")) 642 Uerror = SS_RLOGIN; 643 else if (EQUALS(&msg[1], "CB")) 644 Uerror = (callBack() ? SS_CALLBACK_LOOP : SS_CALLBACK); 645 else if (EQUALS(&msg[1], "You are unknown to me")) 646 Uerror = SS_RUNKNOWN; 647 else if (EQUALS(&msg[1], "BADSEQ")) 648 Uerror = SS_SEQBAD; 649 else if (!EQUALSN(&msg[1], "OK", 2)) 650 Uerror = SS_UNKNOWN_RESPONSE; 651 if (Uerror) { 652 delock(LOCKPRE, lockname); 653 systat(Rmtname, Uerror, UERRORTEXT, Retrytime); 654 logent(UERRORTEXT, "HANDSHAKE FAILED"); 655 CDEBUG(1, "HANDSHAKE FAILED: %s\n", UERRORTEXT); 656 ulkseq(); 657 cleanup(101); 658 } 659 (void) cmtseq(); 660 661 /* 662 * See if we have any additional parameters on the OK 663 */ 664 665 if (strlen(&msg[3])) { 666 p = pskip(&msg[3]); 667 while (p && *p == '-') { 668 q = pskip(p); 669 switch(*(++p)) { 670 case 'R': 671 Restart++; 672 p++; 673 break; 674 case 'U': 675 SizeCheck++; 676 RemUlimit = strtol(++p, (char **) NULL, 0); 677 break; 678 case 'x': 679 if (!Debug) { 680 Debug = atoi(++p); 681 if (Debug <= 0) 682 Debug = 1; 683 } 684 break; 685 default: 686 break; 687 } 688 p = q; 689 } 690 } 691 692 } 693 DEBUG(4, " Rmtname %s, ", Rmtname); 694 DEBUG(4, " Restart %s, ", (Restart ? "YES" : "NO")); 695 DEBUG(4, "Role %s, ", Role ? "MASTER" : "SLAVE"); 696 DEBUG(4, "Ifn - %d, ", Ifn); 697 DEBUG(4, "Loginuser - %s\n", Loginuser); 698 699 /* alarm/setjmp added here due to experience with uucico 700 * hanging for hours in imsg(). 701 */ 702 if (setjmp(Sjbuf)) { 703 delock(LOCKPRE, lockname); 704 logent("startup", "TIMEOUT"); 705 DEBUG(4, "%s - timeout\n", "startup"); 706 cleanup(101); 707 } 708 (void) alarm(MAXSTART); 709 ret = startup(); 710 (void) alarm(0); 711 712 if (ret != SUCCESS) { 713 delock(LOCKPRE, lockname); 714 logent("startup", "FAILED"); 715 Uerror = SS_STARTUP; 716 CDEBUG(1, "%s\n", UERRORTEXT); 717 systat(Rmtname, Uerror, UERRORTEXT, Retrytime); 718 exitcode = 101; 719 } else { 720 pfConnected(Rmtname, Dc); 721 acConnected(Rmtname, Dc); 722 logent("startup", "OK"); 723 systat(Rmtname, SS_INPROGRESS, UTEXT(SS_INPROGRESS),Retrytime); 724 Nstat.t_sftp = times(&Nstat.t_tga); 725 726 exitcode = cntrl(); 727 Nstat.t_eftp = times(&Nstat.t_tga); 728 DEBUG(4, "cntrl - %d\n", exitcode); 729 (void) signal(SIGINT, SIG_IGN); 730 (void) signal(SIGHUP, SIG_IGN); 731 (void) signal(SIGALRM, timeout); 732 733 if (exitcode == 0) { 734 (void) time(&ts); 735 (void) sprintf(cb, "conversation complete %s %ld", 736 Dc, ts - tconv); 737 logent(cb, "OK"); 738 systat(Rmtname, SS_OK, UTEXT(SS_OK), Retrytime); 739 740 } else { 741 logent("conversation complete", "FAILED"); 742 systat(Rmtname, SS_CONVERSATION, 743 UTEXT(SS_CONVERSATION), Retrytime); 744 } 745 (void) alarm(msgtime); /* give slow guys some thrash time */ 746 omsg('O', "OOOOO", Ofn); 747 CDEBUG(4, "send OO %d,", ret); 748 if (!setjmp(Sjbuf)) { 749 for (;;) { 750 omsg('O', "OOOOO", Ofn); 751 ret = imsg(msg, Ifn); 752 if (ret != 0) 753 break; 754 if (msg[0] == 'O') 755 break; 756 } 757 } 758 (void) alarm(0); 759 } 760 cleanup(exitcode); 761 /*NOTREACHED*/ 762 return (0); 763 } 764 765 /* 766 * clean and exit with "code" status 767 */ 768 void 769 cleanup(code) 770 int code; 771 { 772 (void) signal(SIGINT, SIG_IGN); 773 (void) signal(SIGHUP, SIG_IGN); 774 rmlock(CNULL); 775 closedem(); 776 alarm(msgtime); /* Start timer in case closes hang. */ 777 if (setjmp(Sjbuf) == 0) 778 (*Teardown)( Role, Ifn, Ofn ); 779 alarm(0); /* Turn off timer. */ 780 DEBUG(4, "exit code %d\n", code); 781 CDEBUG(1, "Conversation Complete: Status %s\n\n", 782 code ? "FAILED" : "SUCCEEDED"); 783 784 cleanTM(); 785 if ((code == 0) && (uuxqtflag == 1)) 786 xuuxqt(uuxqtarg); 787 exit(code); 788 } 789 790 short TM_cnt = 0; 791 char TM_name[MAXNAMESIZE]; 792 793 void 794 cleanTM() 795 { 796 int i; 797 char tm_name[MAXNAMESIZE]; 798 799 DEBUG(7,"TM_cnt: %d\n",TM_cnt); 800 for(i=0; i < TM_cnt; i++) { 801 (void) sprintf(tm_name, "%s.%3.3d", TM_name, i); 802 DEBUG(7, "tm_name: %s\n", tm_name); 803 unlink(tm_name); 804 } 805 return; 806 } 807 808 void 809 TMname(file, pnum) 810 char *file; 811 pid_t pnum; 812 { 813 814 (void) sprintf(file, "%s/TM.%.5ld.%.3d", RemSpool, (long) pnum, TM_cnt); 815 if (TM_cnt == 0) 816 (void) sprintf(TM_name, "%s/TM.%.5ld", RemSpool, (long) pnum); 817 DEBUG(7, "TMname(%s)\n", file); 818 TM_cnt++; 819 return; 820 } 821 822 /* 823 * intrrupt - remove locks and exit 824 */ 825 void 826 onintr(inter) 827 int inter; 828 { 829 char str[30]; 830 /* I'm putting a test for zero here because I saw it happen 831 * and don't know how or why, but it seemed to then loop 832 * here for ever? 833 */ 834 if (inter == 0) 835 exit(99); 836 (void) signal(inter, SIG_IGN); 837 (void) sprintf(str, "SIGNAL %d", inter); 838 logent(str, "CAUGHT"); 839 pfEndfile("PARTIAL FILE"); 840 acEnd(PARTIAL); /*stop collecting accounting log */ 841 cleanup(inter); 842 } 843 844 void 845 intrEXIT(inter) 846 int inter; 847 { 848 char cb[20]; 849 850 (void) sprintf(cb, "SIGNAL %d", inter); 851 logent("INTREXIT", cb); 852 (void) signal(SIGIOT, SIG_DFL); 853 (void) signal(SIGILL, SIG_DFL); 854 rmlock(CNULL); 855 closedem(); 856 (void) setuid(Uid); 857 abort(); 858 } 859 860 /* 861 * catch SIGALRM routine 862 */ 863 void 864 timeout() 865 { 866 longjmp(Sjbuf, 1); 867 } 868 869 /* skip to next field */ 870 static char * 871 pskip(p) 872 char *p; 873 { 874 if ((p = strchr(p, ' ')) != CNULL) 875 do 876 *p++ = NULLCHAR; 877 while (*p == ' '); 878 return(p); 879 } 880 881 void 882 closedem() 883 { 884 int i, maxfiles; 885 886 #ifdef ATTSVR3 887 maxfiles = ulimit(4,0); 888 #else /* !ATTSVR3 */ 889 #ifdef BSD4_2 890 maxfiles = getdtablesize(); 891 #else /* BSD4_2 */ 892 maxfiles = _NFILE; 893 #endif /* BSD4_2 */ 894 #endif /* ATTSVR3 */ 895 896 for ( i = 3; i < maxfiles; i++ ) 897 if ( i != Ifn && i != Ofn && i != fileno(stderr) ) 898 (void) close(i); 899 return; 900 } 901 902 #ifndef ATTSVR3 903 904 /* 905 * setTZ() 906 * 907 * if login "shell" is uucico (i.e., Role == SLAVE), must set 908 * timezone env variable TZ. otherwise will default to EST. 909 */ 910 911 #define LINELEN 81 912 913 void 914 setTZ() 915 { 916 static char buf[LINELEN], *bp; 917 extern char *fgets(); 918 FILE *tzfp; 919 extern FILE *fopen(); 920 int i; 921 extern int fclose(), strncmp(); 922 923 if ( (tzfp = fopen("/etc/default/init","r")) == (FILE *)NULL ) 924 return; 925 while ( (bp = fgets(buf,LINELEN,tzfp)) != (char *)NULL ) { 926 while ( isspace(*bp) ) 927 ++bp; 928 if ( strncmp(bp, "TZ=", 3) == 0 ) { 929 for ( i = strlen(bp) - 1; i > 0 && isspace(*(bp+i)); --i ) 930 *(bp+i) = '\0'; 931 putenv(bp); 932 (void)fclose(tzfp); 933 return; 934 } 935 } 936 (void)fclose(tzfp); 937 return; 938 } 939 #endif /* ATTSVR3 */ 940 941 #ifdef NOSTRANGERS 942 /* 943 * Function: checkrmt 944 * 945 * If NOSTRANGERS is defined, see if the remote system is in our systems 946 * file. If it is not, execute NOSTRANGERS and then reject the call. 947 */ 948 949 static void 950 checkrmt () 951 952 { 953 char ** eVarPtr; /* Pointer to environment variable. */ 954 char msgbuf[BUFSIZ]; /* Place to build messages. */ 955 pid_t procid; /* ID of Nostranger process. */ 956 static char * safePath = PATH; 957 int status; /* Exit status of child. */ 958 pid_t waitrv; /* Return value from wait system call. */ 959 960 /* here's the place to look the remote system up in the Systems file. 961 * If the command NOSTRANGERS is executable and 962 * If they're not in my file then hang up */ 963 964 if (versys(Rmtname) && (access(NOSTRANGERS, 1) == 0)) { 965 sprintf(msgbuf, "Invoking %s for %%s\n", NOSTRANGERS); 966 DEBUG(4, msgbuf, Rmtname); 967 968 /* 969 * Ignore hangup in case remote goes away before we can 970 * finish logging. 971 */ 972 973 (void) signal(SIGHUP, SIG_IGN); 974 omsg('R', "You are unknown to me", Ofn); 975 scWrite(); /* log unknown remote system */ 976 procid = fork(); 977 if ( procid == 0 ) { 978 /* 979 * Before execing the no strangers program, there is 980 * a security aspect to consider. If NOSTRANGERS is 981 * not a full path name, then the PATH environment 982 * variable will provide places to look for the file. 983 * To be safe, we will set the PATH environment 984 * variable before we do the exec. 985 */ 986 987 /* Find PATH in current environment and change it. */ 988 989 for (eVarPtr = Env; *eVarPtr != CNULL; eVarPtr++) { 990 if (PREFIX("PATH=", *eVarPtr)) 991 *eVarPtr = safePath; 992 } 993 execlp( NOSTRANGERS, "stranger", Rmtname, (char *) 0); 994 sprintf(msgbuf, "Execlp of %s failed with errno=%%d\n", 995 NOSTRANGERS); 996 DEBUG(4, msgbuf, errno); 997 perror(gettext("cico.c: execlp NOSTRANGERS failed")); 998 cleanup(errno); 999 } else if (procid < 0) { 1000 perror(gettext("cico.c: execlp NOSTRANGERS failed")); 1001 cleanup(errno); 1002 } else { 1003 while ((waitrv = wait(&status)) != procid) 1004 if (waitrv == -1 && errno != EINTR) 1005 cleanup(errno); 1006 sprintf(msgbuf, "%s exit status was %%#x\n", 1007 NOSTRANGERS); 1008 DEBUG(4, msgbuf, status); 1009 } 1010 cleanup(101); 1011 } 1012 } 1013 #endif /* NOSTRANGERS */