1 /*- 2 * Copyright (c) 1985, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)cntrl.c 8.1 (Berkeley) 06/06/93"; 10 #endif /* not lint */ 11 12 #include "uucp.h" 13 #include <sys/stat.h> 14 #include "uust.h" 15 16 extern int errno; 17 extern int turntime; 18 int willturn; 19 int HaveSentHup = 0; 20 21 struct Proto { 22 char P_id; 23 int (*P_turnon)(); 24 int (*P_rdmsg)(); 25 int (*P_wrmsg)(); 26 int (*P_rddata)(); 27 int (*P_wrdata)(); 28 int (*P_turnoff)(); 29 }; 30 31 extern int gturnon(), gturnoff(); 32 extern int grdmsg(), grddata(); 33 extern int gwrmsg(), gwrdata(); 34 extern int imsg(), omsg(), nullf(); 35 #ifdef TCPIP 36 extern int twrmsg(), trdmsg(); 37 extern int twrdata(), trddata(); 38 #endif TCPIP 39 #ifdef PAD 40 extern int fturnon(), fturnoff(); 41 extern int frdmsg(), frddata(); 42 extern int fwrmsg(), fwrdata(); 43 #endif PAD 44 45 struct Proto Ptbl[]={ 46 #ifdef TCPIP 47 't', nullf, trdmsg, twrmsg, trddata, twrdata, nullf, 48 #endif TCPIP 49 #ifdef PAD 50 'f', fturnon, frdmsg, fwrmsg, frddata, fwrdata, fturnoff, 51 #endif PAD 52 'g', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff, 53 '\0' 54 }; 55 56 int (*Imsg)() = imsg, (*Omsg)() = omsg; 57 58 int (*Rdmsg)()=imsg, (*Rddata)(); 59 int (*Wrmsg)()=omsg, (*Wrdata)(); 60 int (*Turnon)()=nullf, (*Turnoff)() = nullf; 61 62 struct timeb Now, LastTurned, LastCheckedNoLogin; 63 64 static char *YES = "Y"; 65 static char *NO = "N"; 66 67 int TransferSucceeded = 1; 68 69 /* failure messages */ 70 #define EM_MAX 6 71 #define EM_LOCACC "N1" /* local access to file denied */ 72 #define EM_RMTACC "N2" /* remote access to file/path denied */ 73 #define EM_BADUUCP "N3" /* a bad uucp command was generated */ 74 #define EM_NOTMP "N4" /* remote error - can't create temp */ 75 #define EM_RMTCP "N5" /* can't copy to remote directory - file in public */ 76 #define EM_LOCCP "N6" /* can't copy on local system */ 77 78 char *Em_msg[] = { 79 "COPY FAILED (reason not given by remote)", 80 "local access to file denied", 81 "remote access to path/file denied", 82 "system error - bad uucp command generated", 83 "remote system can't create temp file", 84 "can't copy to file/directory - file left in PUBDIR/user/file", 85 "can't copy to file/directory on local system - file left in PUBDIR/user/file" 86 }; 87 88 89 #define XUUCP 'X' /* execute uucp (string) */ 90 #define SLTPTCL 'P' /* select protocol (string) */ 91 #define USEPTCL 'U' /* use protocol (character) */ 92 #define RCVFILE 'R' /* receive file (string) */ 93 #define SNDFILE 'S' /* send file (string) */ 94 #define RQSTCMPT 'C' /* request complete (string - yes | no) */ 95 #define HUP 'H' /* ready to hangup (string - yes | no) */ 96 #define RESET 'X' /* reset line modes */ 97 98 #define W_TYPE wrkvec[0] 99 #define W_FILE1 wrkvec[1] 100 #define W_FILE2 wrkvec[2] 101 #define W_USER wrkvec[3] 102 #define W_OPTNS wrkvec[4] 103 #define W_DFILE wrkvec[5] 104 #define W_MODE wrkvec[6] 105 #define W_NUSER wrkvec[7] 106 107 #define XFRRATE 35000L 108 #define RMESG(m, s, n) if (rmesg(m, s, n) != 0) {(*Turnoff)(); return FAIL;} else 109 #define RAMESG(s, n) if (rmesg('\0', s, n) != 0) {(*Turnoff)(); return FAIL;} else 110 #define WMESG(m, s) if(wmesg(m, s) != 0) {(*Turnoff)(); return FAIL;} else 111 112 char Wfile[MAXFULLNAME] = {'\0'}; 113 char Dfile[MAXFULLNAME]; 114 115 /* 116 * To avoid a huge backlog of X. files, start uuxqt every so often. 117 */ 118 static int nXfiles = 0; /* number of X files since last uuxqt start */ 119 static char send_or_receive; 120 struct stat stbuf; 121 122 /* 123 * cntrl - this routine will execute the conversation 124 * between the two machines after both programs are 125 * running. 126 * 127 * return codes 128 * SUCCESS - ok 129 * FAIL - failed 130 */ 131 132 cntrl(role, wkpre) 133 int role; 134 char *wkpre; 135 { 136 char msg[BUFSIZ], rqstr[BUFSIZ]; 137 register FILE *fp; 138 int filemode; 139 char filename[MAXFULLNAME], wrktype, *wrkvec[20]; 140 extern (*Rdmsg)(), (*Wrmsg)(); 141 extern char *index(), *lastpart(); 142 int status = 1; 143 register int i, narg; 144 int mailopt, ntfyopt; 145 int ret; 146 static int pnum, tmpnum = 0; 147 extern int ReverseRole; 148 149 pnum = getpid(); 150 Wfile[0] = '\0'; 151 willturn = turntime > 0; 152 remaster: 153 #ifdef USG 154 time(&LastTurned.time); 155 LastTurned.millitm = 0; 156 #else !USG 157 ftime(&LastTurned); 158 #endif !USG 159 send_or_receive = RESET; 160 HaveSentHup = 0; 161 top: 162 for (i = 0; i < sizeof wrkvec / sizeof wrkvec[0]; i++) 163 wrkvec[i] = 0; 164 DEBUG(4, "*** TOP *** - role=%s\n", role ? "MASTER" : "SLAVE"); 165 setproctitle("%s: %s", Rmtname, role ? "MASTER" : "SLAVE"); 166 setupline(RESET); 167 if (Now.time > (LastCheckedNoLogin.time+60)) { 168 LastCheckedNoLogin = Now; 169 if (access(NOLOGIN, 0) == 0) { 170 logent(NOLOGIN, "UUCICO SHUTDOWN"); 171 if (Debug > 4) 172 logent("DEBUGGING", "continuing anyway"); 173 else { 174 WMESG(HUP, YES); 175 RMESG(HUP, msg, 1); 176 goto process; 177 } 178 } 179 } 180 if (role == MASTER) { 181 /* get work */ 182 if (ReverseRole || (narg = gtwvec(Wfile, Spool, wkpre, wrkvec)) == 0) { 183 ReverseRole = 0; 184 WMESG(HUP, ""); 185 RMESG(HUP, msg, 1); 186 goto process; 187 } 188 wrktype = W_TYPE[0]; 189 190 msg[0] = '\0'; 191 for (i = 1; i < narg; i++) { 192 strcat(msg, " "); 193 strcat(msg, wrkvec[i]); 194 } 195 196 if (wrktype == XUUCP) { 197 sprintf(rqstr, "X %s", msg); 198 logent(rqstr, "REQUEST"); 199 goto sendmsg; 200 } 201 mailopt = index(W_OPTNS, 'm') != NULL; 202 ntfyopt = index(W_OPTNS, 'n') != NULL; 203 204 if (narg < 5 || W_TYPE[1] != '\0') { 205 char *bnp; 206 bnp = rindex(Wfile, '/'); 207 sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile); 208 xmv(Wfile, rqstr); 209 syslog(LOG_WARNING, "%s CORRUPTED: %d args", Wfile, 210 narg); 211 Wfile[0] = '\0'; 212 goto top; 213 } 214 sprintf(User, "%.9s", W_USER); 215 sprintf(rqstr, "(%s %s %s %s)", W_TYPE, W_FILE1, 216 W_FILE2, W_USER); 217 logent(rqstr, "REQUEST"); 218 if (wrktype == SNDFILE ) { 219 strcpy(filename, W_FILE1); 220 i = expfile(filename); 221 DEBUG(4, "expfile type - %d, ", i); 222 if (i != 0 && chkpth(User, "", filename)) 223 goto e_access; 224 strcpy(Dfile, W_DFILE); 225 fp = NULL; 226 if (index(W_OPTNS, 'c') == NULL) { 227 fp = fopen(subfile(Dfile), "r"); 228 if (fp != NULL) 229 i = 0; 230 } 231 if (fp == NULL && 232 (fp = fopen(subfile(filename), "r")) == NULL) { 233 /* can not read data file */ 234 logent("CAN'T READ DATA", _FAILED); 235 TransferSucceeded = 1; /* else will keep sending */ 236 USRF(USR_LOCACC); 237 unlinkdf(Dfile); 238 lnotify(User, filename, "can't access"); 239 goto top; 240 } 241 /* if file exists but is not generally readable... */ 242 if (i != 0 && fstat(fileno(fp), &stbuf) == 0 243 && (stbuf.st_mode & ANYREAD) == 0) { 244 e_access:; 245 /* access denied */ 246 if (fp != NULL) { 247 fclose(fp); 248 fp = NULL; 249 } 250 TransferSucceeded = 1; /* else will keep sending */ 251 logent("DENIED", "ACCESS"); 252 USRF(USR_LOCACC); 253 unlinkdf(W_DFILE); 254 lnotify(User, filename, "access denied"); 255 goto top; 256 } 257 258 setupline(SNDFILE); 259 } 260 261 if (wrktype == RCVFILE) { 262 strcpy(filename, W_FILE2); 263 expfile(filename); 264 if (chkpth(User, "", filename) 265 || chkperm(filename, index(W_OPTNS, 'd'))) { 266 /* access denied */ 267 logent("DENIED", "ACCESS"); 268 TransferSucceeded = 1; /* else will keep trying */ 269 USRF(USR_LOCACC); 270 lnotify(User, filename, "access denied"); 271 goto top; 272 } 273 sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++); 274 if ((fp = fopen(subfile(Dfile), "w")) == NULL) { 275 /* can not create temp */ 276 logent("CAN'T CREATE TM", _FAILED); 277 USRF(USR_LNOTMP); 278 unlinkdf(Dfile); 279 goto top; 280 } 281 setupline(RCVFILE); 282 } 283 sendmsg: 284 DEBUG(4, "wrktype - %c\n", wrktype); 285 WMESG(wrktype, msg); 286 RMESG(wrktype, msg, 1); 287 goto process; 288 } 289 290 /* role is slave */ 291 RAMESG(msg, 1); 292 if (willturn < 0) 293 willturn = msg[0] == HUP; 294 295 process: 296 DEBUG(4, "PROCESS: msg - %s\n", msg); 297 switch (msg[0]) { 298 299 case RQSTCMPT: 300 DEBUG(4, "RQSTCMPT:\n", CNULL); 301 if (msg[1] == 'N') { 302 i = atoi(&msg[2]); 303 if (i<0 || i>EM_MAX) 304 i = 0; 305 USRF( 1 << i ); 306 logent(Em_msg[i], "REQUEST FAILED"); 307 TransferSucceeded = 1; /* He had his chance */ 308 } 309 if (msg[1] == 'Y') { 310 USRF(USR_COK); 311 TransferSucceeded = 1; 312 } 313 if (role == MASTER) 314 notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]); 315 316 if (msg[2] == 'M' && role == MASTER) { 317 extern int Nfiles; 318 WMESG(HUP, ""); 319 RMESG(HUP, msg, 1); 320 logent(Rmtname, "TURNAROUND"); 321 #ifdef USG 322 time(&LastTurned.time); 323 LastTurned.millitm = 0; 324 #else !USG 325 ftime(&LastTurned); 326 #endif !USG 327 Nfiles = 0; /* force rescan of queue for work */ 328 goto process; 329 } 330 goto top; 331 332 case HUP: 333 DEBUG(4, "HUP:\n", CNULL); 334 HaveSentHup = 1; 335 if (msg[1] == 'Y') { 336 if (role == MASTER) 337 WMESG(HUP, YES); 338 (*Turnoff)(); 339 Rdmsg = Imsg; 340 Wrmsg = Omsg; 341 return SUCCESS; 342 } 343 344 if (msg[1] == 'N') { 345 if (role != MASTER) { 346 syslog(LOG_ERR, "Wrong Role - HUP"); 347 cleanup(FAIL); 348 } 349 role = SLAVE; 350 goto remaster; 351 } 352 353 /* get work */ 354 if (!iswrk(Wfile, "chk", Spool, wkpre)) { 355 WMESG(HUP, YES); 356 RMESG(HUP, msg, 1); 357 goto process; 358 } 359 360 WMESG(HUP, NO); 361 /* 362 * want to create an orphan uuxqt, 363 * so a double-fork is needed. 364 */ 365 if (fork() == 0) { 366 xuuxqt(); 367 _exit(0); 368 } 369 wait((int *)0); 370 role = MASTER; 371 goto remaster; 372 373 case XUUCP: 374 if (role == MASTER) { 375 goto top; 376 } 377 378 /* slave part */ 379 i = getargs(msg, wrkvec, 20); 380 strcpy(filename, W_FILE1); 381 if (index(filename, ';') != NULL || index(W_FILE2, ';') != NULL 382 || i < 3) { 383 WMESG(XUUCP, NO); 384 goto top; 385 } 386 expfile(filename); 387 if (chkpth("", Rmtname, filename)) { 388 WMESG(XUUCP, NO); 389 logent("XUUCP DENIED", filename); 390 USRF(USR_XUUCP); 391 goto top; 392 } 393 sprintf(rqstr, "%s %s", filename, W_FILE2); 394 xuucp(rqstr); 395 WMESG(XUUCP, YES); 396 goto top; 397 398 case SNDFILE: 399 /* MASTER section of SNDFILE */ 400 401 DEBUG(4, "%s\n", "SNDFILE:"); 402 if (msg[1] == 'N') { 403 i = atoi(&msg[2]); 404 if (i < 0 || i > EM_MAX) 405 i = 0; 406 logent(Em_msg[i], "REQUEST FAILED"); 407 USRF( 1 << i ); 408 fclose(fp); 409 fp = NULL; 410 /* dont send him files he can't save */ 411 if (strcmp(&msg[1], EM_NOTMP) == 0) { 412 WMESG(HUP, ""); 413 RMESG(HUP, msg, 1); 414 goto process; 415 } 416 notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]); 417 if (role != MASTER) { 418 syslog(LOG_ERR, "Wrong Role - SN"); 419 cleanup(FAIL); 420 } 421 unlinkdf(W_DFILE); 422 goto top; 423 } 424 425 if (msg[1] == 'Y') { 426 /* send file */ 427 if (role != MASTER) { 428 syslog(LOG_ERR, "Wrong Role - SY"); 429 cleanup(FAIL); 430 } 431 if (fstat(fileno(fp), &stbuf) < 0) { 432 syslog(LOG_ERR, "stat(%s) failed: %m",filename); 433 cleanup(FAIL); 434 } 435 i = 1 + (int)(stbuf.st_size / XFRRATE); 436 if (send_or_receive != SNDFILE) { 437 send_or_receive = SNDFILE; 438 systat(Rmtname, SS_INPROGRESS, "SENDING"); 439 } 440 ret = (*Wrdata)(fp, Ofn); 441 fclose(fp); 442 fp = NULL; 443 if (ret != SUCCESS) { 444 (*Turnoff)(); 445 USRF(USR_CFAIL); 446 return FAIL; 447 } 448 RMESG(RQSTCMPT, msg, i); 449 unlinkdf(W_DFILE); 450 goto process; 451 } 452 453 /* SLAVE section of SNDFILE */ 454 if (role != SLAVE) { 455 syslog(LOG_ERR, "Wrong Role - SLAVE"); 456 cleanup(FAIL); 457 } 458 459 /* request to receive file */ 460 /* check permissions */ 461 i = getargs(msg, wrkvec, 20); 462 if (i < 5) { 463 char *bnp; 464 bnp = rindex(Wfile, '/'); 465 sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile); 466 xmv(Wfile, rqstr); 467 syslog(LOG_WARNING, "%s CORRUPTED: %d args", Wfile, i); 468 Wfile[0] = '\0'; 469 goto top; 470 } 471 sprintf(rqstr, "(%s %s %s %s)", W_TYPE, W_FILE1, W_FILE2, 472 W_USER); 473 logent(rqstr, "REQUESTED"); 474 DEBUG(4, "msg - %s\n", msg); 475 strcpy(filename, W_FILE2); 476 /* Run uuxqt occasionally */ 477 if (filename[0] == XQTPRE) { 478 if (++nXfiles > 10) { 479 nXfiles = 0; 480 /* 481 * want to create an orphan uuxqt, 482 * so a double-fork is needed. 483 */ 484 if (fork() == 0) { 485 xuuxqt(); 486 _exit(0); 487 } 488 wait((int *)0); 489 } 490 } 491 /* expand filename, i is set to 0 if this is 492 * is a vanilla spool file, so no stat(II)s are needed */ 493 i = expfile(filename); 494 DEBUG(4, "expfile type - %d\n", i); 495 if (i != 0) { 496 if (chkpth("", Rmtname, filename) 497 || chkperm(filename, index(W_OPTNS, 'd'))) { 498 WMESG(SNDFILE, EM_RMTACC); 499 logent("DENIED", "PERMISSION"); 500 goto top; 501 } 502 if (isdir(filename)) { 503 strcat(filename, "/"); 504 strcat(filename, lastpart(W_FILE1)); 505 } 506 } 507 sprintf(User, "%.9s", W_USER); 508 509 DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname); 510 /* speed things up by OKing file before 511 * creating TM file. If the TM file cannot be created, 512 * then the conversation bombs, but that seems reasonable, 513 * as there are probably serious problems then. 514 */ 515 WMESG(SNDFILE, YES); 516 sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++); 517 if((fp = fopen(subfile(Dfile), "w")) == NULL) { 518 /* WMESG(SNDFILE, EM_NOTMP);*/ 519 logent("CAN'T OPEN", "TM FILE"); 520 unlinkdf(Dfile); 521 (*Turnoff)(); 522 return FAIL; 523 } 524 525 if (send_or_receive != RCVFILE) { 526 send_or_receive = RCVFILE; 527 systat(Rmtname, SS_INPROGRESS, "RECEIVING"); 528 } 529 ret = (*Rddata)(Ifn, fp); 530 fflush(fp); 531 if (ferror(fp) || fclose(fp)) 532 ret = FAIL; 533 534 if (ret != SUCCESS) { 535 (void) unlinkdf(Dfile); 536 (*Turnoff)(); 537 return FAIL; 538 } 539 /* copy to user directory */ 540 ntfyopt = index(W_OPTNS, 'n') != NULL; 541 status = xmv(Dfile, filename); 542 543 if (willturn && Now.time > (LastTurned.time+turntime) 544 && iswrk(Wfile, "chk", Spool, wkpre)) { 545 WMESG(RQSTCMPT, status ? EM_RMTCP : "YM"); 546 willturn = -1; 547 } else 548 WMESG(RQSTCMPT, status ? EM_RMTCP : YES); 549 if (i == 0) 550 ; /* vanilla file, nothing to do */ 551 else if (status == 0) { 552 if (W_MODE == 0 || sscanf(W_MODE, "%o", &filemode) != 1) 553 filemode = BASEMODE; 554 chmod(subfile(filename), (filemode|BASEMODE)&0777); 555 arrived(ntfyopt, filename, W_NUSER, Rmtname, User); 556 } else { 557 logent(_FAILED, "COPY"); 558 status = putinpub(filename, Dfile, W_USER); 559 DEBUG(4, "->PUBDIR %d\n", status); 560 if (status == 0) 561 arrived(ntfyopt, filename, W_NUSER, Rmtname, User); 562 } 563 564 goto top; 565 566 case RCVFILE: 567 /* MASTER section of RCVFILE */ 568 569 DEBUG(4, "%s\n", "RCVFILE:"); 570 if (msg[1] == 'N') { 571 i = atoi(&msg[2]); 572 if (i < 0 || i > EM_MAX) 573 i = 0; 574 logent(Em_msg[i], "REQUEST FAILED"); 575 USRF( 1 << i ); 576 fclose(fp); 577 fp = NULL; 578 notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]); 579 if (role != MASTER) { 580 syslog(LOG_ERR, "Wrong Role - RN"); 581 cleanup(FAIL); 582 } 583 unlinkdf(Dfile); 584 goto top; 585 } 586 587 if (msg[1] == 'Y') { 588 /* receive file */ 589 if (role != MASTER) { 590 syslog(LOG_ERR, "Wrong Role - RY"); 591 cleanup(FAIL); 592 } 593 if (send_or_receive != RCVFILE) { 594 send_or_receive = RCVFILE; 595 systat(Rmtname, SS_INPROGRESS, "RECEIVING"); 596 } 597 ret = (*Rddata)(Ifn, fp); 598 fflush(fp); 599 if (ferror(fp) || fclose(fp)) 600 ret = FAIL; 601 if (ret != SUCCESS) { 602 unlinkdf(Dfile); 603 (*Turnoff)(); 604 USRF(USR_CFAIL); 605 return FAIL; 606 } 607 /* copy to user directory */ 608 if (isdir(filename)) { 609 strcat(filename, "/"); 610 strcat(filename, lastpart(W_FILE1)); 611 } 612 status = xmv(Dfile, filename); 613 WMESG(RQSTCMPT, status ? EM_RMTCP : YES); 614 notify(mailopt, W_USER, filename, Rmtname, 615 status ? EM_LOCCP : YES); 616 if (status == 0) { 617 sscanf(&msg[2], "%o", &filemode); 618 if (filemode <= 0) 619 filemode = BASEMODE; 620 chmod(subfile(filename), (filemode|BASEMODE)&0777); 621 USRF(USR_COK); 622 } else { 623 logent(_FAILED, "COPY"); 624 putinpub(filename, Dfile, W_USER); 625 USRF(USR_LOCCP); 626 } 627 if (msg[strlen(msg)-1] == 'M') { 628 extern int Nfiles; 629 WMESG(HUP, ""); 630 RMESG(HUP, msg, 1); 631 logent(Rmtname, "TURNAROUND"); 632 #ifdef USG 633 time(&LastTurned.time); 634 LastTurned.millitm = 0; 635 #else !USG 636 ftime(&LastTurned); 637 #endif !USG 638 Nfiles = 0; /* force rescan of queue for work */ 639 goto process; 640 } 641 goto top; 642 } 643 644 /* SLAVE section of RCVFILE */ 645 if (role != SLAVE) { 646 syslog(LOG_ERR, "Wrong Role - SLAVE RCV"); 647 cleanup(FAIL); 648 } 649 650 /* request to send file */ 651 sprintf(rqstr,"(%s)", msg); 652 logent(rqstr, "REQUESTED"); 653 654 /* check permissions */ 655 i = getargs(msg, wrkvec, 20); 656 if (i < 4) { 657 char *bnp; 658 bnp = rindex(Wfile, '/'); 659 sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile); 660 xmv(Wfile, rqstr); 661 syslog(LOG_WARNING, "%s CORRUPTED: %d args", Wfile, i); 662 Wfile[0] = '\0'; 663 goto top; 664 } 665 DEBUG(4, "msg - %s\n", msg); 666 DEBUG(4, "W_FILE1 - %s\n", W_FILE1); 667 strcpy(filename, W_FILE1); 668 expfile(filename); 669 if (isdir(filename)) { 670 strcat(filename, "/"); 671 strcat(filename, lastpart(W_FILE2)); 672 } 673 sprintf(User, "%.9s", W_USER); 674 if (chkpth("", Rmtname, filename) || anyread(filename)) { 675 WMESG(RCVFILE, EM_RMTACC); 676 logent("DENIED", "PERMISSION"); 677 goto top; 678 } 679 DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname); 680 681 if ((fp = fopen(subfile(filename), "r")) == NULL) { 682 WMESG(RCVFILE, EM_RMTACC); 683 logent("CAN'T OPEN", "DENIED"); 684 goto top; 685 } 686 687 /* ok to send file */ 688 if (fstat(fileno(fp), &stbuf) < 0) { 689 syslog(LOG_ERR, "stat(%s) failed: %m", filename); 690 cleanup(FAIL); 691 } 692 693 i = 1 + (int)(stbuf.st_size / XFRRATE); 694 if (willturn && Now.time > (LastTurned.time+turntime) 695 && iswrk(Wfile, "chk", Spool, wkpre)) { 696 willturn = -1; 697 } 698 sprintf(msg, "%s %o%s", YES, (int)stbuf.st_mode & 0777, 699 willturn < 0 ? " M" : ""); 700 WMESG(RCVFILE, msg); 701 if (send_or_receive != SNDFILE) { 702 send_or_receive = SNDFILE; 703 systat(Rmtname, SS_INPROGRESS, "SENDING"); 704 } 705 ret = (*Wrdata)(fp, Ofn); 706 fclose(fp); 707 if (ret != SUCCESS) { 708 (*Turnoff)(); 709 return FAIL; 710 } 711 RMESG(RQSTCMPT, msg, i); 712 goto process; 713 } 714 (*Turnoff)(); 715 return FAIL; 716 } 717 718 719 /* 720 * read message 'c'. try 'n' times 721 * 722 * return code: SUCCESS | FAIL 723 */ 724 rmesg(c, msg, n) 725 register char *msg, c; 726 register int n; 727 { 728 char str[MAXFULLNAME]; 729 730 DEBUG(4, "rmesg - '%c' ", c); 731 while ((*Rdmsg)(msg, Ifn) != SUCCESS) { 732 if (--n > 0) { 733 sprintf(str, "%d", n); 734 logent(str, "PATIENCE"); 735 continue; 736 } 737 DEBUG(4, "got FAIL\n", CNULL); 738 if (c != '\0') 739 sprintf(str, "expected '%c' got FAIL (%d)", c, errno); 740 else 741 sprintf(str, "expected ANY got FAIL (%d)", errno); 742 logent(str, "BAD READ"); 743 return FAIL; 744 } 745 if (c != '\0' && msg[0] != c) { 746 DEBUG(4, "got %s\n", msg); 747 sprintf(str, "expected '%c' got %s", c, msg); 748 logent(str, "BAD READ"); 749 return FAIL; 750 } 751 DEBUG(4, "got %s\n", msg); 752 return SUCCESS; 753 } 754 755 756 /* 757 * write a message (type m) 758 * 759 * return codes: SUCCESS - ok | FAIL - ng 760 */ 761 wmesg(m, s) 762 register char *s, m; 763 { 764 DEBUG(4, "wmesg '%c' ", m); 765 DEBUG(4, "%s\n", s); 766 return (*Wrmsg)(m, s, Ofn); 767 } 768 769 /* 770 * mail results of command 771 * 772 * return codes: none 773 */ 774 notify(mailopt, user, file, sys, msgcode) 775 char *user, *file, *sys, *msgcode; 776 { 777 char str[BUFSIZ]; 778 int i; 779 char *msg; 780 781 if (!mailopt && *msgcode == 'Y') 782 return; 783 if (*msgcode == 'Y') 784 msg = "copy succeeded"; 785 else { 786 i = atoi(msgcode + 1); 787 if (i < 1 || i > EM_MAX) 788 i = 0; 789 msg = Em_msg[i]; 790 } 791 sprintf(str, "file %s!%s -- %s\n", 792 sys,file, msg); 793 mailst(user, str, CNULL); 794 return; 795 } 796 797 /* 798 * local notify 799 * 800 * return code - none 801 */ 802 lnotify(user, file, mesg) 803 char *user, *file, *mesg; 804 { 805 char mbuf[200]; 806 sprintf(mbuf, "file %s!%s -- %s\n", Myname, file, mesg); 807 mailst(user, mbuf, CNULL); 808 return; 809 } 810 811 char UsingProtocol; 812 813 /* 814 * converse with the remote machine, agree upon a protocol (if possible) 815 * and start the protocol. 816 * 817 * return codes: 818 * SUCCESS - successful protocol selection 819 * FAIL - can't find common or open failed 820 */ 821 startup(role) 822 int role; 823 { 824 extern (*Rdmsg)(), (*Wrmsg)(); 825 extern char *blptcl(), fptcl(); 826 char msg[BUFSIZ], str[MAXFULLNAME]; 827 828 Rdmsg = Imsg; 829 Wrmsg = Omsg; 830 if (role == MASTER) { 831 RMESG(SLTPTCL, msg, 1); 832 if ((str[0] = fptcl(&msg[1])) == NULL) { 833 /* no protocol match */ 834 WMESG(USEPTCL, NO); 835 return FAIL; 836 } 837 str[1] = '\0'; 838 WMESG(USEPTCL, str); 839 if (stptcl(str) != 0) 840 return FAIL; 841 DEBUG(4, "protocol %s\n", str); 842 UsingProtocol = str[0]; 843 return SUCCESS; 844 } 845 else { 846 WMESG(SLTPTCL, blptcl(str)); 847 RMESG(USEPTCL, msg, 1); 848 if (msg[1] == 'N') { 849 return FAIL; 850 } 851 852 if (stptcl(&msg[1]) != 0) 853 return FAIL; 854 DEBUG(4, "Protocol %s\n", msg); 855 UsingProtocol = msg[1]; 856 return SUCCESS; 857 } 858 } 859 860 /* 861 * choose a protocol from the input string (str) and return the it 862 * 863 * return codes: 864 * '\0' - no acceptable protocol 865 * any character - the chosen protocol 866 */ 867 char 868 fptcl(str) 869 register char *str; 870 { 871 register struct Proto *p; 872 extern char LineType[]; 873 874 for (p = Ptbl; p->P_id != '\0'; p++) { 875 #ifdef TCPIP 876 /* Only use 't' on TCP/IP */ 877 if (p->P_id == 't' && strcmp("TCP", LineType)) 878 continue; 879 #endif TCPIP 880 #ifdef PAD 881 /* only use 'f' protocol on PAD */ 882 if (p->P_id == 'f' && strcmp("PAD", LineType)) 883 continue; 884 #endif PAD 885 if (index(str, p->P_id) != NULL) { 886 return p->P_id; 887 } 888 } 889 890 return '\0'; 891 } 892 893 /* 894 * build a string of the letters of the available protocols 895 */ 896 char * 897 blptcl(str) 898 register char *str; 899 { 900 register struct Proto *p; 901 register char *s; 902 903 for (p = Ptbl, s = str; (*s++ = p->P_id) != '\0'; p++) 904 ; 905 *s = '\0'; 906 return str; 907 } 908 909 /* 910 * this routine will set up the six routines 911 * (Rdmsg, Wrmsg, Rddata, Wrdata, Turnon, Turnoff) for the 912 * desired protocol. 913 * 914 * return codes: 915 * SUCCESS - ok 916 * FAIL - no find or failed to open 917 * 918 */ 919 stptcl(c) 920 register char *c; 921 { 922 register struct Proto *p; 923 924 for (p = Ptbl; p->P_id != '\0'; p++) { 925 if (*c == p->P_id) { 926 /* found protocol - set routines */ 927 Rdmsg = p->P_rdmsg; 928 Wrmsg = p->P_wrmsg; 929 Rddata = p->P_rddata; 930 Wrdata = p->P_wrdata; 931 Turnon = p->P_turnon; 932 Turnoff = p->P_turnoff; 933 if ((*Turnon)() != SUCCESS) 934 return FAIL; 935 DEBUG(4, "Proto started %c\n", *c); 936 return SUCCESS; 937 } 938 } 939 DEBUG(4, "Proto start-fail %c\n", *c); 940 return FAIL; 941 } 942 943 /* 944 * put file in public place. if successful, filename is modified 945 * 946 * return code SUCCESS | FAIL 947 */ 948 949 putinpub(file, tmp, user) 950 register char *file, *tmp, *user; 951 { 952 char fullname[MAXFULLNAME]; 953 char *lastpart(); 954 int status; 955 956 sprintf(fullname, "%s/%s/", PUBDIR, user); 957 if (mkdirs(fullname) != 0) { 958 /* can not make directories */ 959 DEBUG(1, "Cannot mkdirs(%s)\n", fullname); 960 return FAIL; 961 } 962 strcat(fullname, lastpart(file)); 963 status = xmv(tmp, fullname); 964 if (status == 0) { 965 strcpy(file, fullname); 966 chmod(subfile(fullname), BASEMODE); 967 } 968 return status; 969 } 970 971 /* 972 * unlink D. file 973 * 974 * return code - none 975 */ 976 977 unlinkdf(file) 978 register char *file; 979 { 980 if (strlen(file) > 6) 981 unlink(subfile(file)); 982 return; 983 } 984 985 /* 986 * notify receiver of arrived file 987 * 988 * return code - none 989 */ 990 arrived(opt, file, nuser, rmtsys, rmtuser) 991 char *file, *nuser, *rmtsys, *rmtuser; 992 { 993 char mbuf[200]; 994 995 if (!opt) 996 return; 997 sprintf(mbuf, "%s from %s!%s arrived\n", file, rmtsys, rmtuser); 998 mailst(nuser, mbuf, CNULL); 999 return; 1000 } 1001 1002 nullf() 1003 { 1004 return SUCCESS; 1005 } 1006