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