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