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