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