1 #ifndef lint 2 static char sccsid[] = "@(#)cntrl.c 5.10 (Berkeley) 02/24/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 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 || W_TYPE[1] != '\0') { 197 char *bnp; 198 bnp = rindex(Wfile, '/'); 199 sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile); 200 xmv(Wfile, rqstr); 201 assert("CMD FILE CORRUPTED", Wfile, narg); 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 unlinkdf(W_DFILE); 396 goto top; 397 } 398 399 if (msg[1] == 'Y') { 400 /* send file */ 401 ASSERT(role == MASTER, "WRONG ROLE - SY", CNULL, role); 402 ret = fstat(fileno(fp), &stbuf); 403 ASSERT(ret != -1, "STAT FAILED", filename, 0); 404 i = 1 + (int)(stbuf.st_size / XFRRATE); 405 if (send_or_receive != SNDFILE) { 406 send_or_receive = SNDFILE; 407 systat(Rmtname, SS_INPROGRESS, "SENDING"); 408 } 409 ret = (*Wrdata)(fp, Ofn); 410 fclose(fp); 411 fp = NULL; 412 if (ret != SUCCESS) { 413 (*Turnoff)(); 414 USRF(USR_CFAIL); 415 return FAIL; 416 } 417 RMESG(RQSTCMPT, msg, i); 418 unlinkdf(W_DFILE); 419 goto process; 420 } 421 422 /* SLAVE section of SNDFILE */ 423 ASSERT(role == SLAVE, "WRONG ROLE - SLAVE", CNULL, role); 424 425 /* request to receive file */ 426 /* check permissions */ 427 i = getargs(msg, wrkvec, 20); 428 if (i < 5) { 429 char *bnp; 430 bnp = rindex(Wfile, '/'); 431 sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile); 432 xmv(Wfile, rqstr); 433 assert("CMD FILE CORRUPTED",Wfile, i); 434 Wfile[0] = '\0'; 435 goto top; 436 } 437 sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1, W_FILE2, W_USER); 438 logent(rqstr, "REQUESTED"); 439 DEBUG(4, "msg - %s\n", msg); 440 strcpy(filename, W_FILE2); 441 /* Run uuxqt occasionally */ 442 if (filename[0] == XQTPRE) { 443 if (++nXfiles > 10) { 444 nXfiles = 0; 445 /* 446 * want to create an orphan uuxqt, 447 * so a double-fork is needed. 448 */ 449 if (fork() == 0) { 450 xuuxqt(); 451 _exit(0); 452 } 453 wait((int *)0); 454 } 455 } 456 /* expand filename, i is set to 0 if this is 457 * is a vanilla spool file, so no stat(II)s are needed */ 458 i = expfile(filename); 459 DEBUG(4, "expfile type - %d\n", i); 460 if (i != 0) { 461 if (chkpth("", Rmtname, filename) 462 || chkperm(filename, index(W_OPTNS, 'd'))) { 463 WMESG(SNDFILE, EM_RMTACC); 464 logent("DENIED", "PERMISSION"); 465 goto top; 466 } 467 if (isdir(filename)) { 468 strcat(filename, "/"); 469 strcat(filename, lastpart(W_FILE1)); 470 } 471 } 472 sprintf(User, "%.9s", W_USER); 473 474 DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname); 475 /* speed things up by OKing file before 476 * creating TM file. If the TM file cannot be created, 477 * then the conversation bombs, but that seems reasonable, 478 * as there are probably serious problems then. 479 */ 480 WMESG(SNDFILE, YES); 481 sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++); 482 if((fp = fopen(subfile(Dfile), "w")) == NULL) { 483 /* WMESG(SNDFILE, EM_NOTMP);*/ 484 logent("CAN'T OPEN", "TM FILE"); 485 unlinkdf(Dfile); 486 (*Turnoff)(); 487 return FAIL; 488 } 489 490 if (send_or_receive != RCVFILE) { 491 send_or_receive = RCVFILE; 492 systat(Rmtname, SS_INPROGRESS, "RECEIVING"); 493 } 494 ret = (*Rddata)(Ifn, fp); 495 fflush(fp); 496 if (ferror(fp) || fclose(fp)) 497 ret = FAIL; 498 499 if (ret != SUCCESS) { 500 (void) unlinkdf(Dfile); 501 (*Turnoff)(); 502 return FAIL; 503 } 504 /* copy to user directory */ 505 ntfyopt = index(W_OPTNS, 'n') != NULL; 506 status = xmv(Dfile, filename); 507 508 if (willturn && Now.time > (LastTurned.time+turntime) 509 && iswrk(Wfile, "chk", Spool, wkpre)) { 510 WMESG(RQSTCMPT, status ? EM_RMTCP : "YM"); 511 willturn = -1; 512 } else 513 WMESG(RQSTCMPT, status ? EM_RMTCP : YES); 514 if (i == 0) 515 ; /* vanilla file, nothing to do */ 516 else if (status == 0) { 517 if (W_MODE == 0 || sscanf(W_MODE, "%o", &filemode) != 1) 518 filemode = BASEMODE; 519 chmod(subfile(filename), (filemode|BASEMODE)&0777); 520 arrived(ntfyopt, filename, W_NUSER, Rmtname, User); 521 } else { 522 logent(_FAILED, "COPY"); 523 status = putinpub(filename, Dfile, W_USER); 524 DEBUG(4, "->PUBDIR %d\n", status); 525 if (status == 0) 526 arrived(ntfyopt, filename, W_NUSER, Rmtname, User); 527 } 528 529 goto top; 530 531 case RCVFILE: 532 /* MASTER section of RCVFILE */ 533 534 DEBUG(4, "%s\n", "RCVFILE:"); 535 if (msg[1] == 'N') { 536 i = atoi(&msg[2]); 537 if (i < 0 || i > EM_MAX) 538 i = 0; 539 logent(Em_msg[i], "REQUEST FAILED"); 540 USRF( 1 << i ); 541 fclose(fp); 542 fp = NULL; 543 notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]); 544 ASSERT(role == MASTER, "WRONG ROLE - RN", CNULL, role); 545 unlinkdf(Dfile); 546 goto top; 547 } 548 549 if (msg[1] == 'Y') { 550 /* receive file */ 551 ASSERT(role == MASTER, "WRONG ROLE - RY", CNULL, role); 552 if (send_or_receive != RCVFILE) { 553 send_or_receive = RCVFILE; 554 systat(Rmtname, SS_INPROGRESS, "RECEIVING"); 555 } 556 ret = (*Rddata)(Ifn, fp); 557 fflush(fp); 558 if (ferror(fp) || fclose(fp)) 559 ret = FAIL; 560 if (ret != SUCCESS) { 561 unlinkdf(Dfile); 562 (*Turnoff)(); 563 USRF(USR_CFAIL); 564 return FAIL; 565 } 566 /* copy to user directory */ 567 if (isdir(filename)) { 568 strcat(filename, "/"); 569 strcat(filename, lastpart(W_FILE1)); 570 } 571 status = xmv(Dfile, filename); 572 if (willturn && Now.time > (LastTurned.time+turntime) 573 && iswrk(Wfile, "chk", Spool, wkpre)) { 574 WMESG(RQSTCMPT, status ? EM_RMTCP : "YM"); 575 willturn = -1; 576 } else 577 WMESG(RQSTCMPT, status ? EM_RMTCP : YES); 578 notify(mailopt, W_USER, filename, Rmtname, 579 status ? EM_LOCCP : YES); 580 if (status == 0) { 581 sscanf(&msg[2], "%o", &filemode); 582 if (filemode <= 0) 583 filemode = BASEMODE; 584 chmod(subfile(filename), (filemode|BASEMODE)&0777); 585 USRF(USR_COK); 586 } else { 587 logent(_FAILED, "COPY"); 588 putinpub(filename, Dfile, W_USER); 589 USRF(USR_LOCCP); 590 } 591 goto top; 592 } 593 594 /* SLAVE section of RCVFILE */ 595 ASSERT(role == SLAVE, "WRONG ROLE - SLAVE RCV", CNULL, role); 596 597 /* request to send file */ 598 strcpy(rqstr, msg); 599 logent(rqstr, "REQUESTED"); 600 601 /* check permissions */ 602 i = getargs(msg, wrkvec, 20); 603 if (i < 4) { 604 char *bnp; 605 bnp = rindex(Wfile, '/'); 606 sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile); 607 xmv(Wfile, rqstr); 608 assert("CMD FILE CORRUPTED", Wfile, i); 609 Wfile[0] = '\0'; 610 goto top; 611 } 612 DEBUG(4, "msg - %s\n", msg); 613 DEBUG(4, "W_FILE1 - %s\n", W_FILE1); 614 strcpy(filename, W_FILE1); 615 expfile(filename); 616 if (isdir(filename)) { 617 strcat(filename, "/"); 618 strcat(filename, lastpart(W_FILE2)); 619 } 620 sprintf(User, "%.9s", W_USER); 621 if (chkpth("", Rmtname, filename) || anyread(filename)) { 622 WMESG(RCVFILE, EM_RMTACC); 623 logent("DENIED", "PERMISSION"); 624 goto top; 625 } 626 DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname); 627 628 if ((fp = fopen(subfile(filename), "r")) == NULL) { 629 WMESG(RCVFILE, EM_RMTACC); 630 logent("CAN'T OPEN", "DENIED"); 631 goto top; 632 } 633 634 /* ok to send file */ 635 ret = fstat(fileno(fp), &stbuf); 636 ASSERT(ret != -1, "STAT FAILED", filename, 0); 637 i = 1 + (int)(stbuf.st_size / XFRRATE); 638 sprintf(msg, "%s %o", YES, (int)stbuf.st_mode & 0777); 639 WMESG(RCVFILE, msg); 640 if (send_or_receive != SNDFILE) { 641 send_or_receive = SNDFILE; 642 systat(Rmtname, SS_INPROGRESS, "SENDING"); 643 } 644 ret = (*Wrdata)(fp, Ofn); 645 fclose(fp); 646 if (ret != SUCCESS) { 647 (*Turnoff)(); 648 return FAIL; 649 } 650 RMESG(RQSTCMPT, msg, i); 651 goto process; 652 } 653 (*Turnoff)(); 654 return FAIL; 655 } 656 657 658 /* 659 * read message 'c'. try 'n' times 660 * 661 * return code: SUCCESS | FAIL 662 */ 663 rmesg(c, msg, n) 664 register char *msg, c; 665 register int n; 666 { 667 char str[MAXFULLNAME]; 668 669 DEBUG(4, "rmesg - '%c' ", c); 670 while ((*Rdmsg)(msg, Ifn) != SUCCESS) { 671 if (--n > 0) { 672 sprintf(str, "%d", n); 673 logent(str, "PATIENCE"); 674 continue; 675 } 676 DEBUG(4, "got FAIL\n", CNULL); 677 if (c != '\0') 678 sprintf(str, "expected '%c' got FAIL (%d)", c, errno); 679 else 680 sprintf(str, "expected ANY got FAIL (%d)", errno); 681 logent(str, "BAD READ"); 682 return FAIL; 683 } 684 if (c != '\0' && msg[0] != c) { 685 DEBUG(4, "got %s\n", msg); 686 sprintf(str, "expected '%c' got %s", c, msg); 687 logent(str, "BAD READ"); 688 return FAIL; 689 } 690 DEBUG(4, "got %s\n", msg); 691 return SUCCESS; 692 } 693 694 695 /* 696 * write a message (type m) 697 * 698 * return codes: SUCCESS - ok | FAIL - ng 699 */ 700 wmesg(m, s) 701 register char *s, m; 702 { 703 DEBUG(4, "wmesg '%c' ", m); 704 DEBUG(4, "%s\n", s); 705 return (*Wrmsg)(m, s, Ofn); 706 } 707 708 /* 709 * mail results of command 710 * 711 * return codes: none 712 */ 713 notify(mailopt, user, file, sys, msgcode) 714 char *user, *file, *sys, *msgcode; 715 { 716 char str[BUFSIZ]; 717 int i; 718 char *msg; 719 720 if (!mailopt && *msgcode == 'Y') 721 return; 722 if (*msgcode == 'Y') 723 msg = "copy succeeded"; 724 else { 725 i = atoi(msgcode + 1); 726 if (i < 1 || i > EM_MAX) 727 i = 0; 728 msg = Em_msg[i]; 729 } 730 sprintf(str, "file %s!%s -- %s\n", 731 sys,file, msg); 732 mailst(user, str, CNULL); 733 return; 734 } 735 736 /* 737 * local notify 738 * 739 * return code - none 740 */ 741 lnotify(user, file, mesg) 742 char *user, *file, *mesg; 743 { 744 char mbuf[200]; 745 sprintf(mbuf, "file %s!%s -- %s\n", Myname, file, mesg); 746 mailst(user, mbuf, CNULL); 747 return; 748 } 749 750 char UsingProtocol; 751 752 /* 753 * converse with the remote machine, agree upon a protocol (if possible) 754 * and start the protocol. 755 * 756 * return codes: 757 * SUCCESS - successful protocol selection 758 * FAIL - can't find common or open failed 759 */ 760 startup(role) 761 int role; 762 { 763 extern (*Rdmsg)(), (*Wrmsg)(); 764 extern char *blptcl(), fptcl(); 765 char msg[BUFSIZ], str[MAXFULLNAME]; 766 767 Rdmsg = Imsg; 768 Wrmsg = Omsg; 769 if (role == MASTER) { 770 RMESG(SLTPTCL, msg, 1); 771 if ((str[0] = fptcl(&msg[1])) == NULL) { 772 /* no protocol match */ 773 WMESG(USEPTCL, NO); 774 return FAIL; 775 } 776 str[1] = '\0'; 777 WMESG(USEPTCL, str); 778 if (stptcl(str) != 0) 779 return FAIL; 780 DEBUG(4, "protocol %s\n", str); 781 UsingProtocol = str[0]; 782 return SUCCESS; 783 } 784 else { 785 WMESG(SLTPTCL, blptcl(str)); 786 RMESG(USEPTCL, msg, 1); 787 if (msg[1] == 'N') { 788 return FAIL; 789 } 790 791 if (stptcl(&msg[1]) != 0) 792 return FAIL; 793 DEBUG(4, "Protocol %s\n", msg); 794 UsingProtocol = msg[1]; 795 return SUCCESS; 796 } 797 } 798 799 /* 800 * choose a protocol from the input string (str) and return the it 801 * 802 * return codes: 803 * '\0' - no acceptable protocol 804 * any character - the chosen protocol 805 */ 806 char 807 fptcl(str) 808 register char *str; 809 { 810 register struct Proto *p; 811 extern char LineType[]; 812 813 for (p = Ptbl; p->P_id != '\0'; p++) { 814 #ifdef TCPIP 815 /* Only use 't' on TCP/IP */ 816 if (p->P_id == 't' && strcmp("TCP", LineType)) 817 continue; 818 #endif TCPIP 819 #ifdef PAD 820 /* only use 'f' protocol on PAD */ 821 if (p->P_id == 'f' && strcmp("PAD", LineType)) 822 continue; 823 #endif PAD 824 if (index(str, p->P_id) != NULL) { 825 return p->P_id; 826 } 827 } 828 829 return '\0'; 830 } 831 832 /* 833 * build a string of the letters of the available protocols 834 */ 835 char * 836 blptcl(str) 837 register char *str; 838 { 839 register struct Proto *p; 840 register char *s; 841 842 for (p = Ptbl, s = str; (*s++ = p->P_id) != '\0'; p++) 843 ; 844 *s = '\0'; 845 return str; 846 } 847 848 /* 849 * this routine will set up the six routines 850 * (Rdmsg, Wrmsg, Rddata, Wrdata, Turnon, Turnoff) for the 851 * desired protocol. 852 * 853 * return codes: 854 * SUCCESS - ok 855 * FAIL - no find or failed to open 856 * 857 */ 858 stptcl(c) 859 register char *c; 860 { 861 register struct Proto *p; 862 863 for (p = Ptbl; p->P_id != '\0'; p++) { 864 if (*c == p->P_id) { 865 /* found protocol - set routines */ 866 Rdmsg = p->P_rdmsg; 867 Wrmsg = p->P_wrmsg; 868 Rddata = p->P_rddata; 869 Wrdata = p->P_wrdata; 870 Turnon = p->P_turnon; 871 Turnoff = p->P_turnoff; 872 if ((*Turnon)() != SUCCESS) 873 return FAIL; 874 DEBUG(4, "Proto started %c\n", *c); 875 return SUCCESS; 876 } 877 } 878 DEBUG(4, "Proto start-fail %c\n", *c); 879 return FAIL; 880 } 881 882 /* 883 * put file in public place. if successful, filename is modified 884 * 885 * return code SUCCESS | FAIL 886 */ 887 888 putinpub(file, tmp, user) 889 register char *file, *tmp, *user; 890 { 891 char fullname[MAXFULLNAME]; 892 char *lastpart(); 893 int status; 894 895 sprintf(fullname, "%s/%s/", PUBDIR, user); 896 if (mkdirs(fullname) != 0) { 897 /* can not make directories */ 898 DEBUG(1, "Cannot mkdirs(%s)\n", fullname); 899 return FAIL; 900 } 901 strcat(fullname, lastpart(file)); 902 status = xmv(tmp, fullname); 903 if (status == 0) { 904 strcpy(file, fullname); 905 chmod(subfile(fullname), BASEMODE); 906 } 907 return status; 908 } 909 910 /* 911 * unlink D. file 912 * 913 * return code - none 914 */ 915 916 unlinkdf(file) 917 register char *file; 918 { 919 if (strlen(file) > 6) 920 unlink(subfile(file)); 921 return; 922 } 923 924 /* 925 * notify receiver of arrived file 926 * 927 * return code - none 928 */ 929 arrived(opt, file, nuser, rmtsys, rmtuser) 930 char *file, *nuser, *rmtsys, *rmtuser; 931 { 932 char mbuf[200]; 933 934 if (!opt) 935 return; 936 sprintf(mbuf, "%s from %s!%s arrived\n", file, rmtsys, rmtuser); 937 mailst(nuser, mbuf, CNULL); 938 return; 939 } 940 941 nullf() 942 { 943 return SUCCESS; 944 } 945