1: #ifndef lint 2: static char sccsid[] = "@(#)cntrl.c 5.8 (Berkeley) 1/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: }