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