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