1: /* dropsbr.c - write to a mailbox */ 2: 3: #include <stdio.h> 4: #ifndef MMDFONLY 5: #include "../h/mh.h" 6: #include "../h/dropsbr.h" 7: #include "../zotnet/mts.h" 8: #else MMDFONLY 9: #include "dropsbr.h" 10: #include "strings.h" 11: #include "mmdfonly.h" 12: #endif MMDFONLY 13: #include <errno.h> 14: #include <sys/types.h> 15: #include <sys/stat.h> 16: 17: 18: #define MMDF 1 19: #define UUCP 2 20: 21: /* */ 22: 23: static int mbx_style = MMDF; 24: 25: 26: extern int errno; 27: 28: 29: long lseek (); 30: 31: /* */ 32: 33: int mbx_mmdf () { 34: int style = mbx_style; 35: 36: mbx_style = MMDF; 37: return style; 38: } 39: 40: 41: int mbx_uucp () { 42: int style = mbx_style; 43: 44: mbx_style = UUCP; 45: return style; 46: } 47: 48: /* */ 49: 50: int mbx_open (file, uid, gid, mode) 51: char *file; 52: int uid, 53: gid, 54: mode; 55: { 56: int clear, 57: fd; 58: 59: if ((fd = mbx_Xopen (file, uid, gid, mode, &clear)) == NOTOK) 60: return fd; 61: 62: if (!clear) 63: switch (mbx_style) { 64: case MMDF: 65: default: 66: if (mbx_chk (fd) == NOTOK) { 67: (void) close (fd); 68: return NOTOK; 69: } 70: break; 71: 72: case UUCP: 73: if (lseek (fd, 0L, 2) == (long) NOTOK) { 74: (void) close (fd); 75: return NOTOK; 76: } 77: break; 78: } 79: 80: return fd; 81: } 82: 83: /* */ 84: 85: int mbx_Xopen (file, uid, gid, mode, clear) 86: char *file; 87: int uid, 88: gid, 89: mode, 90: *clear; 91: { 92: register int j; 93: int count, 94: fd; 95: struct stat st; 96: 97: for (*clear = 0, count = 4, j = 0; count > 0; count--) 98: if ((fd = lkopen (file, 6)) == NOTOK) 99: switch (errno) { 100: case ENOENT: 101: if (mbx_create (file, uid, gid, mode) == NOTOK) 102: return NOTOK; 103: (*clear)++; 104: break; 105: 106: #ifdef BSD42 107: case EWOULDBLOCK: 108: #endif BSD42 109: case ETXTBSY: 110: j = errno; 111: sleep (5); 112: break; 113: 114: default: 115: return NOTOK; 116: } 117: else { 118: *clear = fstat (fd, &st) != NOTOK && st.st_size == 0L; 119: break; 120: } 121: 122: errno = j; 123: return fd; 124: } 125: 126: /* */ 127: 128: static int mbx_create (file, uid, gid, mode) 129: char *file; 130: int uid, 131: gid, 132: mode; 133: { 134: int fd; 135: 136: if ((fd = creat (file, 0600)) == NOTOK) 137: return NOTOK; 138: 139: (void) close (fd); 140: (void) chown (file, uid, gid); 141: (void) chmod (file, mode); 142: 143: return OK; 144: } 145: 146: 147: static int mbx_chk (fd) 148: int fd; 149: { 150: int count; 151: char ldelim[BUFSIZ]; 152: 153: count = strlen (mmdlm2); 154: 155: if (lseek (fd, (long) (-count), 2) == (long) NOTOK 156: || read (fd, ldelim, count) != count) 157: return NOTOK; 158: ldelim[count] = NULL; 159: 160: if (strcmp (ldelim, mmdlm2) 161: && write (fd, "\n", 1) != 1 162: && write (fd, mmdlm2, count) != count) 163: return NOTOK; 164: 165: return OK; 166: } 167: 168: /* */ 169: 170: int mbx_read (fp, pos, drops, noisy) 171: register FILE *fp; 172: register long pos; 173: struct drop **drops; 174: int noisy; 175: { 176: register int len, 177: size; 178: long ld1, 179: ld2; 180: register char *bp; 181: char buffer[BUFSIZ]; 182: register struct drop *cp, 183: *dp, 184: *ep, 185: *pp; 186: 187: pp = (struct drop *) calloc ((unsigned) (len = MAXFOLDER), sizeof *dp); 188: if (pp == NULL) { 189: if (noisy) 190: admonish (NULLCP, "unable to allocate drop storage"); 191: return NOTOK; 192: } 193: 194: ld1 = (long) strlen (mmdlm1); 195: ld2 = (long) strlen (mmdlm2); 196: 197: (void) fseek (fp, pos, 0); 198: for (ep = (dp = pp) + len - 1; fgets (buffer, sizeof buffer, fp);) { 199: size = 0; 200: if (strcmp (buffer, mmdlm1) == 0) 201: pos += ld1, dp -> d_start = pos; 202: else { 203: dp -> d_start = pos, pos += (long) strlen (buffer); 204: for (bp = buffer; *bp; bp++, size++) 205: if (*bp == '\n') 206: size++; 207: } 208: 209: while (fgets (buffer, sizeof buffer, fp) != NULL) 210: if (strcmp (buffer, mmdlm2) == 0) 211: break; 212: else { 213: pos += (long) strlen (buffer); 214: for (bp = buffer; *bp; bp++, size++) 215: if (*bp == '\n') 216: size++; 217: } 218: 219: if (dp -> d_start != pos) { 220: dp -> d_id = 0; 221: dp -> d_size = size; 222: dp -> d_stop = pos; 223: dp++; 224: } 225: pos += ld2; 226: 227: if (dp >= ep) { 228: register int curlen = dp - pp; 229: 230: cp = (struct drop *) realloc ((char *) pp, 231: (unsigned) (len += MAXFOLDER) * sizeof *pp); 232: if (cp == NULL) { 233: if (noisy) 234: admonish (NULLCP, "unable to allocate drop storage"); 235: free ((char *) pp); 236: return 0; 237: } 238: dp = cp + curlen, ep = (pp = cp) + len - 1; 239: } 240: } 241: 242: if (dp == pp) 243: free ((char *) pp); 244: else 245: *drops = pp; 246: return (dp - pp); 247: } 248: 249: /* */ 250: 251: int mbx_write (mailbox, md, fp, id, pos, stop, mapping, noisy) 252: char *mailbox; 253: register FILE *fp; 254: int md, 255: id, 256: mapping, 257: noisy; 258: register long pos, 259: stop; 260: { 261: register int i, 262: j, 263: size; 264: register long start, 265: off; 266: register char *cp; 267: char buffer[BUFSIZ]; 268: 269: off = lseek (md, 0L, 1); 270: j = strlen (mmdlm1); 271: if (write (md, mmdlm1, j) != j) 272: return NOTOK; 273: start = lseek (md, 0L, 1); 274: size = 0; 275: 276: (void) fseek (fp, pos, 0); 277: while (fgets (buffer, sizeof buffer, fp) != NULL && pos < stop) { 278: i = strlen (buffer); 279: for (j = 0; (j = stringdex (mmdlm1, buffer)) >= 0; buffer[j]++) 280: continue; 281: for (j = 0; (j = stringdex (mmdlm2, buffer)) >= 0; buffer[j]++) 282: continue; 283: if (write (md, buffer, i) != i) 284: return NOTOK; 285: pos += (long) i; 286: if (mapping) 287: for (cp = buffer; i-- > 0; size++) 288: if (*cp++ == '\n') 289: size++; 290: } 291: 292: stop = lseek (md, 0L, 1); 293: j = strlen (mmdlm2); 294: if (write (md, mmdlm2, j) != j) 295: return NOTOK; 296: if (mapping) 297: (void) map_write (mailbox, md, id, start, stop, off, size, noisy); 298: 299: return OK; 300: } 301: 302: /* */ 303: 304: int mbx_copy (mailbox, md, fd, mapping, text, noisy) 305: char *mailbox; 306: int md, 307: fd, 308: mapping, 309: noisy; 310: char *text; 311: { 312: register int i, 313: j, 314: size; 315: register long start, 316: stop, 317: pos; 318: register char *cp; 319: char buffer[BUFSIZ]; 320: register FILE *fp; 321: 322: pos = lseek (md, 0L, 1); 323: size = 0; 324: 325: switch (mbx_style) { 326: case MMDF: 327: default: 328: j = strlen (mmdlm1); 329: if (write (md, mmdlm1, j) != j) 330: return NOTOK; 331: start = lseek (md, 0L, 1); 332: 333: if (text) { 334: i = strlen (text); 335: if (write (md, text, i) != i) 336: return NOTOK; 337: for (cp = buffer; *cp++; size++) 338: if (*cp == '\n') 339: size++; 340: } 341: 342: while ((i = read (fd, buffer, sizeof buffer)) > 0) { 343: for (j = 0; 344: (j = stringdex (mmdlm1, buffer)) >= 0; 345: buffer[j]++) 346: continue; 347: for (j = 0; 348: (j = stringdex (mmdlm2, buffer)) >= 0; 349: buffer[j]++) 350: continue; 351: if (write (md, buffer, i) != i) 352: return NOTOK; 353: if (mapping) 354: for (cp = buffer; i-- > 0; size++) 355: if (*cp++ == '\n') 356: size++; 357: } 358: 359: stop = lseek (md, 0L, 1); 360: j = strlen (mmdlm2); 361: if (write (md, mmdlm2, j) != j) 362: return NOTOK; 363: if (mapping) 364: (void) map_write (mailbox, md, 0, start, stop, pos, size, noisy); 365: 366: return (i != NOTOK ? OK : NOTOK); 367: 368: case UUCP: /* I hate this... */ 369: if ((j = dup (fd)) == NOTOK) 370: return NOTOK; 371: if ((fp = fdopen (j, "r")) == NULL) { 372: (void) close (j); 373: return NOTOK; 374: } 375: start = lseek (md, 0L, 1); 376: 377: if (text) { 378: i = strlen (text); 379: if (write (md, text, i) != i) 380: return NOTOK; 381: for (cp = buffer; *cp++; size++) 382: if (*cp == '\n') 383: size++; 384: } 385: 386: for (j = 0; fgets (buffer, sizeof buffer, fp) != NULL; j++) { 387: if (j != 0 && strncmp (buffer, "From ", 5) == 0) { 388: (void) write (fd, ">", 1); 389: size++; 390: } 391: i = strlen (buffer); 392: if (write (md, buffer, i) != i) { 393: (void) fclose (fp); 394: return NOTOK; 395: } 396: if (mapping) 397: for (cp = buffer; i-- > 0; size++) 398: if (*cp++ == '\n') 399: size++; 400: } 401: 402: (void) fclose (fp); 403: (void) lseek (fd, 0L, 2); 404: stop = lseek (md, 0L, 1); 405: if (mapping) 406: (void) map_write (mailbox, md, 0, start, stop, pos, size, 407: noisy); 408: 409: return OK; 410: } 411: } 412: 413: /* */ 414: 415: int mbx_size (md, start, stop) 416: int md; 417: long start, 418: stop; 419: { 420: register int i, 421: fd; 422: register long pos; 423: register FILE *fp; 424: 425: if ((fd = dup (md)) == NOTOK || (fp = fdopen (fd, "r")) == NULL) { 426: if (fd != NOTOK) 427: (void) close (fd); 428: return NOTOK; 429: } 430: 431: (void) fseek (fp, start, 0); 432: for (i = 0, pos = stop - start; pos-- > 0; i++) 433: if (fgetc (fp) == '\n') 434: i++; 435: 436: (void) fclose (fp); 437: 438: return i; 439: } 440: 441: /* */ 442: 443: int mbx_close (mailbox, md) 444: char *mailbox; 445: int md; 446: { 447: (void) lkclose (md, mailbox); 448: 449: return OK; 450: } 451: 452: /* */ 453: 454: /* This function is performed implicitly by getbbent.c: 455: 456: bb -> bb_map = map_name (bb -> bb_file); 457: */ 458: 459: char *map_name (file) 460: register char *file; 461: { 462: register char *cp, 463: *dp; 464: static char buffer[BUFSIZ]; 465: 466: if ((dp = index (cp = r1bindex (file, '/'), '.')) == NULL) 467: dp = cp + strlen (cp); 468: if (cp == file) 469: (void) sprintf (buffer, ".%.*s%s", dp - cp, cp, ".map"); 470: else 471: (void) sprintf (buffer, "%.*s.%.*s%s", cp - file, file, dp - cp, 472: cp, ".map"); 473: 474: return buffer; 475: } 476: 477: /* */ 478: 479: int map_read (file, pos, drops, noisy) 480: char *file; 481: long pos; 482: struct drop **drops; 483: int noisy; 484: { 485: register int i, 486: md, 487: msgp; 488: register char *cp; 489: struct drop d; 490: register struct drop *mp, 491: *dp; 492: 493: if ((md = open (cp = map_name (file), 0)) == NOTOK 494: || map_chk (cp, md, mp = &d, pos, noisy)) { 495: if (md != NOTOK) 496: (void) close (md); 497: return 0; 498: } 499: 500: msgp = mp -> d_id; 501: dp = (struct drop *) calloc ((unsigned) msgp, sizeof *dp); 502: if (dp == NULL) { 503: (void) close (md); 504: return 0; 505: } 506: 507: (void) lseek (md, (long) sizeof *mp, 0); 508: if ((i = read (md, (char *) dp, msgp * sizeof *dp)) < sizeof *dp) { 509: i = 0; 510: free ((char *) dp); 511: } 512: else 513: *drops = dp; 514: 515: (void) close (md); 516: 517: return (i / sizeof *dp); 518: } 519: 520: /* */ 521: 522: int map_write (mailbox, md, id, start, stop, pos, size, noisy) 523: register char *mailbox; 524: int md, 525: id, 526: size, 527: noisy; 528: long start, 529: stop, 530: pos; 531: { 532: register int i; 533: int clear, 534: fd, 535: td; 536: char *file; 537: register struct drop *dp; 538: struct drop d1, 539: d2, 540: *rp; 541: register FILE *fp; 542: 543: if ((fd = map_open (file = map_name (mailbox), &clear, md)) == NOTOK) 544: return NOTOK; 545: 546: if (!clear && map_chk (file, fd, &d1, pos, noisy)) { 547: (void) unlink (file); 548: (void) mbx_close (file, fd); 549: if ((fd = map_open (file, &clear, md)) == NOTOK) 550: return NOTOK; 551: clear++; 552: } 553: 554: if (clear) { 555: if ((td = dup (md)) == NOTOK || (fp = fdopen (td, "r")) == NULL) { 556: if (noisy) 557: admonish (file, "unable to %s", td != NOTOK ? "fdopen" : "dup"); 558: if (td != NOTOK) 559: (void) close (td); 560: (void) mbx_close (file, fd); 561: return NOTOK; 562: } 563: 564: switch (i = mbx_read (fp, 0L, &rp, noisy)) { 565: case NOTOK: 566: (void) fclose (fp); 567: (void) mbx_close (file, fd); 568: return NOTOK; 569: 570: case OK: 571: break; 572: 573: default: 574: d1.d_id = 0; 575: for (dp = rp; i-- >0; dp++) { 576: if (dp -> d_start == start) 577: dp -> d_id = id; 578: (void) lseek (fd, (long) (++d1.d_id * sizeof *dp), 0); 579: if (write (fd, (char *) dp, sizeof *dp) != sizeof *dp) { 580: if (noisy) 581: admonish (file, "write error"); 582: (void) mbx_close (file, fd); 583: (void) fclose (fp); 584: return NOTOK; 585: } 586: } 587: free ((char *) rp); 588: break; 589: } 590: } 591: else { 592: dp = &d2; 593: dp -> d_id = id; 594: dp -> d_size = size ? size : mbx_size (fd, start, stop); 595: dp -> d_start = start; 596: dp -> d_stop = stop; 597: (void) lseek (fd, (long) (++d1.d_id * sizeof *dp), 0); 598: if (write (fd, (char *) dp, sizeof *dp) != sizeof *dp) { 599: if (noisy) 600: admonish (file, "write error"); 601: (void) mbx_close (file, fd); 602: return NOTOK; 603: } 604: } 605: 606: dp = &d1; 607: dp -> d_size = DRVRSN; 608: dp -> d_start = DRMAGIC; 609: dp -> d_stop = lseek (md, 0L, 1); 610: (void) lseek (fd, 0L, 0); 611: if (write (fd, (char *) dp, sizeof *dp) != sizeof *dp) { 612: if (noisy) 613: admonish (file, "write error"); 614: (void) mbx_close (file, fd); 615: return NOTOK; 616: } 617: 618: (void) mbx_close (file, fd); 619: 620: return OK; 621: } 622: 623: /* */ 624: 625: static int map_open (file, clear, md) 626: char *file; 627: int *clear, 628: md; 629: { 630: int mode; 631: struct stat st; 632: 633: mode = fstat (md, &st) != NOTOK ? (int) (st.st_mode & 0777) : m_gmprot (); 634: return mbx_Xopen (file, st.st_uid, st.st_gid, mode, clear); 635: } 636: 637: /* */ 638: 639: int map_chk (file, fd, dp, pos, noisy) 640: char *file; 641: int fd, 642: noisy; 643: register struct drop *dp; 644: long pos; 645: { 646: long count; 647: struct drop d; 648: register struct drop *dl; 649: 650: if (read (fd, (char *) dp, sizeof *dp) != sizeof *dp) { 651: #ifdef notdef 652: admonish (NULLCP, "%s: missing or partial index", file); 653: #endif notdef 654: return NOTOK; 655: } 656: if (dp -> d_size != DRVRSN) { 657: if (noisy) 658: admonish (NULLCP, "%s: version mismatch", file); 659: return NOTOK; 660: } 661: if (dp -> d_start != DRMAGIC) { 662: if (noisy) 663: admonish (NULLCP, "%s: bad magic number", file); 664: return NOTOK; 665: } 666: if (dp -> d_stop != pos) { 667: if (noisy && pos != 0L) 668: admonish (NULLCP, 669: "%s: pointer mismatch or incomplete index (%ld!=%ld)", 670: file, dp -> d_stop, pos); 671: return NOTOK; 672: } 673: 674: if ((long) ((dp -> d_id + 1) * sizeof *dp) != lseek (fd, 0L, 2)) { 675: if (noisy) 676: admonish (NULLCP, "%s: corrupt index(1)", file); 677: return NOTOK; 678: } 679: 680: dl = &d; 681: count = (long) strlen (mmdlm2); 682: (void) lseek (fd, (long) (dp -> d_id * sizeof *dp), 0); 683: if (read (fd, (char *) dl, sizeof *dl) != sizeof *dl 684: || (dl -> d_stop != dp -> d_stop 685: && dl -> d_stop + count != dp -> d_stop)) { 686: if (noisy) 687: admonish (NULLCP, "%s: corrupt index(2)", file); 688: return NOTOK; 689: } 690: 691: return OK; 692: }