1: #include "uucp.h" 2: #include <sys/types.h> 3: #include <sys/stat.h> 4: 5: 6: struct Proto { 7: char P_id; 8: int (*P_turnon)(); 9: int (*P_rdmsg)(); 10: int (*P_wrmsg)(); 11: int (*P_rddata)(); 12: int (*P_wrdata)(); 13: int (*P_turnoff)(); 14: }; 15: 16: 17: extern int gturnon(), gturnoff(); 18: extern int grdmsg(), grddata(); 19: extern int gwrmsg(), gwrdata(); 20: extern int imsg(); 21: extern int omsg(); 22: 23: struct Proto Ptbl[]={ 24: 'g', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff, 25: '\0' 26: }; 27: 28: int (*Rdmsg)()=imsg, (*Rddata)(); 29: int (*Wrmsg)()=omsg, (*Wrdata)(); 30: int (*Turnon)(), (*Turnoff)(); 31: 32: 33: #define YES "Y" 34: #define NO "N" 35: #define Y 'Y' 36: #define N 'N' 37: 38: 39: #define XUUCP 'X' /* execute uucp (string) */ 40: #define SLTPTCL 'P' /* select protocol (string) */ 41: #define USEPTCL 'U' /* use protocol (character) */ 42: #define RCVFILE 'R' /* receive file (string) */ 43: #define SNDFILE 'S' /* send file (string) */ 44: #define RQSTCMPT 'C' /* request complete (string - yes | no) */ 45: #define HUP 'H' /* ready to hangup (string - yes | no) */ 46: 47: 48: #define W_TYPE wrkvec[0] 49: #define W_FILE1 wrkvec[1] 50: #define W_FILE2 wrkvec[2] 51: #define W_USER wrkvec[3] 52: #define W_OPTNS wrkvec[4] 53: #define W_DFILE wrkvec[5] 54: #define W_MODE wrkvec[6] 55: 56: #define RMESG(m, s) if (rmesg(m, s) != 0) return(FAIL); 57: #define RAMESG(s) if (rmesg('\0', s) != 0) return(FAIL) 58: #define WMESG(m, s) if(wmesg(m, s) != 0) return(FAIL) 59: 60: char Wfile[MAXFULLNAME] = {'\0'}; 61: char Dfile[MAXFULLNAME]; 62: 63: /******* 64: * cntrl(role, wkpre) 65: * int role; 66: * char *wkpre; 67: * 68: * cntrl - this routine will execute the conversation 69: * between the two machines after both programs are 70: * running. 71: * 72: * return codes 73: * SUCCESS - ok 74: * FAIL - failed 75: */ 76: 77: cntrl(role, wkpre) 78: int role; 79: char *wkpre; 80: { 81: char msg[BUFSIZ], rqstr[BUFSIZ]; 82: FILE *fp; 83: int filemode; 84: struct stat stbuf; 85: char filename[MAXFULLNAME], wrktype, *wrkvec[20]; 86: extern (*Rdmsg)(), (*Wrmsg)(); 87: extern char *index(), *lastpart(); 88: int status = 1, i; 89: int ret; 90: static int pnum, tmpnum = 0; 91: 92: pnum = getpid(); 93: top: 94: DEBUG(4, "*** TOP *** - role=%d, ", role); 95: if (role == MASTER) { 96: /* get work */ 97: if ((i = gtwvec(Wfile, Spool, wkpre, wrkvec)) == 0) { 98: WMESG(HUP, ""); 99: RMESG(HUP, msg); 100: goto process; 101: } 102: wrktype = W_TYPE[0]; 103: 104: DEBUG(4, "wrktype %c, ", wrktype); 105: if (wrktype == XUUCP) { 106: int n; 107: msg[0] = '\0'; 108: for (n = 1; n < i; n++) { 109: strcat(msg, " "); 110: strcat(msg, wrkvec[n]); 111: } 112: sprintf(rqstr, "X %s", msg); 113: logent(rqstr, "REQUEST"); 114: goto sendmsg; 115: } 116: 117: ASSERT(i > 4, "ARG COUNT - %d\n", i); 118: sprintf(msg, " %s %s %s %s %s %s", 119: W_FILE1, W_FILE2, W_USER, 120: W_OPTNS, W_DFILE, W_MODE); 121: strcpy(User, W_USER); 122: ASSERT(strlen(User) <= 10, "User - %s\n", User); 123: sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1, 124: W_FILE2, W_USER); 125: logent(rqstr, "REQUEST"); 126: DEBUG(4, "User - %s\n", User); 127: if (wrktype == SNDFILE ) { 128: strcpy(filename, W_FILE1); 129: expfile(filename); 130: if (chkpth(User, "", filename)) { 131: /* access denied */ 132: logent("DENIED", "ACCESS"); 133: unlink(W_DFILE); 134: unlink(Wfile); 135: goto top; 136: } 137: 138: strcpy(Dfile, W_DFILE); 139: if ((fp = fopen(Dfile, "r")) == NULL 140: && (fp = fopen(filename, "r")) == NULL) { 141: /* can not read data file */ 142: logent("CAN'T READ DATA", "FAILED"); 143: unlink(Wfile); 144: unlink(Dfile); 145: goto top; 146: } 147: } 148: 149: if (wrktype == RCVFILE) { 150: strcpy(filename, W_FILE2); 151: expfile(filename); 152: if (chkpth(User, "", filename) 153: || chkperm(filename, User, index(W_OPTNS, 'd'))) { 154: /* access denied */ 155: logent("DENIED", "ACCESS"); 156: unlink(Wfile); 157: goto top; 158: } 159: sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++); 160: if ((fp = fopen(Dfile, "w")) == NULL) { 161: /* can not create temp */ 162: logent("CAN'T CREATE TM", "FAILED"); 163: unlink(Wfile); 164: unlink(Dfile); 165: goto top; 166: } 167: chmod(Dfile, 0666); 168: } 169: sendmsg: 170: DEBUG(4, "wrktype - %c, ", wrktype); 171: DEBUG(4, " fileno - %d\n", fileno(fp)); 172: WMESG(wrktype, msg); 173: RMESG(wrktype, msg); 174: goto process; 175: } 176: 177: /* role is slave */ 178: RAMESG(msg); 179: goto process; 180: 181: process: 182: DEBUG(4, " PROCESS: msg - %s\n", msg); 183: switch (msg[0]) { 184: 185: case RQSTCMPT: 186: DEBUG(4, "%s\n", "RQSTCMPT:"); 187: logent((msg[1] == 'N') ? "FAILED" : "SUCCEEDED", "REQUEST"); 188: if (role == MASTER) { 189: notify(W_OPTNS, W_USER, W_FILE1, Rmtname, 190: (msg[1] == N) ? "failed" : "succeeded"); 191: } 192: goto top; 193: 194: case HUP: 195: DEBUG(4, "%s\n", "HUP:"); 196: if (msg[1] == Y) { 197: WMESG(HUP, YES); 198: (*Turnoff)(); 199: Rdmsg = imsg; 200: Wrmsg = omsg; 201: return(0); 202: } 203: 204: if (msg[1] == N) { 205: ASSERT(role == MASTER, 206: "role - %d", role); 207: role = SLAVE; 208: goto top; 209: } 210: 211: /* get work */ 212: if (!iswrk(Wfile, "chk", Spool, wkpre)) { 213: WMESG(HUP, YES); 214: RMESG(HUP, msg); 215: goto process; 216: } 217: 218: WMESG(HUP, NO); 219: role = MASTER; 220: goto top; 221: 222: case XUUCP: 223: if (role == MASTER) { 224: unlink(Wfile); 225: goto top; 226: } 227: 228: /* slave part */ 229: i = getargs(msg, wrkvec); 230: strcpy(filename, W_FILE1); 231: if (index(filename, ';') != NULL 232: || index(W_FILE2, ';') != NULL 233: || i < 3) { 234: WMESG(XUUCP, NO); 235: goto top; 236: } 237: expfile(filename); 238: if (chkpth("", Rmtname, filename)) { 239: WMESG(XUUCP, NO); 240: logent("XUUCP DENIED", filename); 241: goto top; 242: } 243: sprintf(rqstr, "%s %s", filename, W_FILE2); 244: xuucp(rqstr); 245: WMESG(XUUCP, YES); 246: goto top; 247: 248: case SNDFILE: 249: /* MASTER section of SNDFILE */ 250: 251: DEBUG(4, "%s\n", "SNDFILE:"); 252: if (msg[1] == N) { 253: logent("DENIED", "REQUEST"); 254: ASSERT(role == MASTER, 255: "role - %d", role); 256: fclose(fp); 257: unlink(W_DFILE); 258: unlink(Wfile); 259: goto top; 260: } 261: 262: if (msg[1] == Y) { 263: /* send file */ 264: ASSERT(role == MASTER, 265: "role - %d", role); 266: ret = (*Wrdata)(fp, Ofn); 267: fclose(fp); 268: if (ret != 0) 269: return(FAIL); 270: unlink(W_DFILE); 271: RMESG(RQSTCMPT, msg); 272: goto process; 273: } 274: 275: /* SLAVE section of SNDFILE */ 276: ASSERT(role == SLAVE, 277: "role - %d", role); 278: 279: /* request to receive file */ 280: /* check permissions */ 281: i = getargs(msg, wrkvec); 282: ASSERT(i > 4, "ARG COUNT - %d\n", i); 283: sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1, 284: W_FILE2, W_USER); 285: logent(rqstr, "REQUESTED"); 286: DEBUG(4, "msg - %s\n", msg); 287: DEBUG(4, "W_FILE2 - %s\n", W_FILE2); 288: strcpy(filename, W_FILE2); 289: expfile(filename); 290: if (chkpth("", Rmtname, filename) 291: || chkperm(filename, Loginuser, index(W_OPTNS, 'd'))) { 292: WMESG(SNDFILE, NO); 293: logent("DENIED", "PERMISSION"); 294: goto top; 295: } 296: if (isdir(filename)) { 297: strcat(filename, "/"); 298: strcat(filename, lastpart(W_FILE1)); 299: } 300: strcpy(User, W_USER); 301: ASSERT(strlen(User) <= 10, "User - %s\n", User); 302: 303: DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname); 304: sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++); 305: if((fp = fopen(Dfile, "w")) == NULL) { 306: WMESG(SNDFILE, NO); 307: logent("CAN'T OPEN", "DENIED"); 308: unlink(Dfile); 309: goto top; 310: } 311: chmod(Dfile, 0666); 312: 313: WMESG(SNDFILE, YES); 314: ret = (*Rddata)(Ifn, fp); 315: fclose(fp); 316: if (ret != 0) 317: return(FAIL); 318: /* copy to user directory */ 319: status = xmv(Dfile, filename); 320: WMESG(RQSTCMPT, status ? NO : YES); 321: logent(status ? "FAILED" : "SUCCEEDED", "COPY"); 322: sscanf(W_MODE, "%o", &filemode); 323: DEBUG(4, "mode - %o\n", filemode); 324: if (filemode <= 0) 325: filemode = 0666; 326: if (status == 0) { 327: filemode |= 0666; 328: chmod(filename, filemode | 0666); 329: } 330: goto top; 331: 332: case RCVFILE: 333: /* MASTER section of RCVFILE */ 334: 335: DEBUG(4, "%s\n", "RCVFILE:"); 336: if (msg[1] == N) { 337: logent("REQUEST", "DENIED"); 338: ASSERT(role == MASTER, 339: "role - %d", role); 340: unlink(Wfile); 341: fclose(fp); 342: goto top; 343: } 344: 345: if (msg[1] == Y) { 346: /* receive file */ 347: ASSERT(role == MASTER, 348: "role - %d", role); 349: ret = (*Rddata)(Ifn, fp); 350: fclose(fp); 351: if (ret != 0) 352: return(FAIL); 353: /* copy to user directory */ 354: if (isdir(filename)) { 355: strcat(filename, "/"); 356: strcat(filename, lastpart(W_FILE1)); 357: } 358: status = xmv(Dfile, filename); 359: WMESG(RQSTCMPT, status ? NO : YES); 360: logent(status ? "FAILED" : "SUCCEEDED", "COPY"); 361: notify(W_OPTNS, W_USER, filename, Rmtname, 362: status ? "failed" : "succeeded"); 363: sscanf(&msg[2], "%o", &filemode); 364: DEBUG(4, "mode - %o\n", filemode); 365: if (filemode <= 0) 366: filemode = 0666; 367: if (status == 0) { 368: unlink(Dfile); 369: filemode |= 0666; 370: chmod(filename, filemode | 0666); 371: } 372: goto top; 373: } 374: 375: /* SLAVE section of RCVFILE */ 376: ASSERT(role == SLAVE, 377: "role - %d", role); 378: 379: /* request to send file */ 380: strcpy(rqstr, msg); 381: logent(rqstr, "REQUESTED"); 382: 383: /* check permissions */ 384: i = getargs(msg, wrkvec); 385: ASSERT(i > 3, "ARG COUNT - %d\n", i); 386: DEBUG(4, "msg - %s\n", msg); 387: DEBUG(4, "W_FILE1 - %s\n", W_FILE1); 388: strcpy(filename, W_FILE1); 389: expfile(filename); 390: if (isdir(filename)) { 391: strcat(filename, "/"); 392: strcat(filename, lastpart(W_FILE2)); 393: } 394: strcpy(User, W_USER); 395: ASSERT(strlen(User) <= 10, "User - %s\n", User); 396: if (chkpth("", Rmtname, filename) != 0) { 397: WMESG(RCVFILE, NO); 398: logent("DENIED", "PERMISSION"); 399: goto top; 400: } 401: DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname); 402: 403: if ((fp = fopen(filename, "r")) == NULL) { 404: WMESG(RCVFILE, NO); 405: logent("CAN'T OPEN", "DENIED"); 406: goto top; 407: } 408: 409: /* ok to send file */ 410: ret = stat(filename, &stbuf); 411: ASSERT(ret != -1, "STAT FAILED %s", filename); 412: sprintf(msg, "%s %o", YES, stbuf.st_mode & 0777); 413: WMESG(RCVFILE, msg); 414: ret = (*Wrdata)(fp, Ofn); 415: fclose(fp); 416: if (ret != 0) 417: return(FAIL); 418: RMESG(RQSTCMPT, msg); 419: goto process; 420: } 421: return(FAIL); 422: } 423: 424: 425: /*** 426: * rmesg(c, msg) read message 'c' 427: * char *msg, c; 428: * 429: * return code: 0 | FAIL 430: */ 431: 432: rmesg(c, msg) 433: char *msg, c; 434: { 435: char str[50]; 436: 437: DEBUG(4, "rmesg - '%c' ", c); 438: if ((*Rdmsg)(msg, Ifn) != 0) { 439: DEBUG(4, "got %s\n", "FAIL"); 440: sprintf(str, "expected '%c' got FAIL", c); 441: logent(str, "BAD READ"); 442: return(FAIL); 443: } 444: if (c != '\0' && msg[0] != c) { 445: DEBUG(4, "got %s\n", msg); 446: sprintf(str, "expected '%c' got %.25s", c, msg); 447: logent(str, "BAD READ"); 448: return(FAIL); 449: } 450: DEBUG(4, "got %.25s\n", msg); 451: return(0); 452: } 453: 454: 455: /*** 456: * wmesg(m, s) write a message (type m) 457: * char *s, m; 458: * 459: * return codes: 0 - ok | FAIL - ng 460: */ 461: 462: wmesg(m, s) 463: char *s, m; 464: { 465: DEBUG(4, "wmesg '%c'", m); 466: DEBUG(4, "%.25s\n", s); 467: return((*Wrmsg)(m, s, Ofn)); 468: } 469: 470: 471: /*** 472: * notify(options, user, file, sys, stwork) mail results of copy 473: * char *options, *user, *file, *sys, *stword); 474: * 475: * return codes: none 476: */ 477: 478: notify(options, user, file, sys, stword) 479: char *options, *user, *file, *sys, *stword; 480: { 481: char str[200]; 482: if (index(options, 'm') == NULL) 483: return; 484: sprintf(str, "file %s, system %s, copy %s\n", file, sys, stword); 485: mailst(user, str); 486: return; 487: } 488: 489: 490: /*** 491: * startup(role) 492: * int role; 493: * 494: * startup - this routine will converse with the remote 495: * machine, agree upon a protocol (if possible) and start the 496: * protocol. 497: * 498: * return codes: 499: * SUCCESS - successful protocol selection 500: * FAIL - can't find common or open failed 501: */ 502: 503: startup(role) 504: int role; 505: { 506: extern (*Rdmsg)(), (*Wrmsg)(); 507: extern imsg(), omsg(); 508: extern char *blptcl(), fptcl(); 509: char msg[BUFSIZ], str[BUFSIZ]; 510: 511: Rdmsg = imsg; 512: Wrmsg = omsg; 513: if (role == MASTER) { 514: RMESG(SLTPTCL, msg); 515: if ((str[0] = fptcl(&msg[1])) == NULL) { 516: /* no protocol match */ 517: WMESG(USEPTCL, NO); 518: return(FAIL); 519: } 520: str[1] = '\0'; 521: WMESG(USEPTCL, str); 522: if (stptcl(str) != 0) 523: return(FAIL); 524: DEBUG(4, "protocol %s\n", str); 525: return(SUCCESS); 526: } 527: else { 528: WMESG(SLTPTCL, blptcl(str)); 529: RMESG(USEPTCL, msg); 530: if (msg[1] == N) { 531: return(FAIL); 532: } 533: 534: if (stptcl(&msg[1]) != 0) 535: return(FAIL); 536: DEBUG(4, "Protocol %s\n", msg); 537: return(SUCCESS); 538: } 539: } 540: 541: 542: /******* 543: * char 544: * fptcl(str) 545: * char *str; 546: * 547: * fptcl - this routine will choose a protocol from 548: * the input string (str) and return the found letter. 549: * 550: * return codes: 551: * '\0' - no acceptable protocol 552: * any character - the chosen protocol 553: */ 554: 555: char 556: fptcl(str) 557: char *str; 558: { 559: struct Proto *p; 560: extern char *index(); 561: 562: for (p = Ptbl; p->P_id != '\0'; p++) { 563: if (index(str, p->P_id) != NULL) { 564: return(p->P_id); 565: } 566: } 567: 568: return('\0'); 569: } 570: 571: 572: /*** 573: * char * 574: * blptcl(str) 575: * char *str; 576: * 577: * blptcl - this will build a string of the 578: * letters of the available protocols and return 579: * the string (str). 580: * 581: * return: 582: * a pointer to string (str) 583: */ 584: 585: char * 586: blptcl(str) 587: char *str; 588: { 589: struct Proto *p; 590: char *s; 591: 592: for (p = Ptbl, s = str; (*s++ = p->P_id) != '\0'; p++); 593: return(str); 594: } 595: 596: /*** 597: * stptcl(c) 598: * char *c; 599: * 600: * stptcl - this routine will set up the six routines 601: * (Rdmsg, Wrmsg, Rddata, Wrdata, Turnon, Turnoff) for the 602: * desired protocol. 603: * 604: * return codes: 605: * SUCCESS - ok 606: * FAIL - no find or failed to open 607: * 608: */ 609: 610: stptcl(c) 611: char *c; 612: { 613: struct Proto *p; 614: 615: for (p = Ptbl; p->P_id != '\0'; p++) { 616: if (*c == p->P_id) { 617: /* found protocol - set routines */ 618: Rdmsg = p->P_rdmsg; 619: Wrmsg = p->P_wrmsg; 620: Rddata = p->P_rddata; 621: Wrdata = p->P_wrdata; 622: Turnon = p->P_turnon; 623: Turnoff = p->P_turnoff; 624: if ((*Turnon)() != 0) 625: return(FAIL); 626: DEBUG(4, "Proto started %c\n", *c); 627: return(SUCCESS); 628: } 629: } 630: DEBUG(4, "Proto start-fail %c\n", *c); 631: return(FAIL); 632: }