|
|
1.1 root 1: /* forw.c - forward messages */
2:
3: #include "../h/mh.h"
4: #include "../h/formatsbr.h"
5: #include "../zotnet/tws.h"
6: #include <stdio.h>
7: #include <sys/types.h>
8: #include <sys/stat.h>
9:
10:
11: #define IFMT "digest-issue-%s"
12: #define VFMT "digest-volume-%s"
13:
14: /* */
15:
16: static struct swit switches[] = {
17: #define ANNOSW 0
18: "annotate", 0,
19: #define NANNOSW 1
20: "noannotate", 0,
21:
22: #define DFOLDSW 2
23: "draftfolder +folder", 0,
24: #define DMSGSW 3
25: "draftmessage msg", 0,
26: #define NDFLDSW 4
27: "nodraftfolder", 0,
28:
29: #define EDITRSW 5
30: "editor editor", 0,
31: #define NEDITSW 6
32: "noedit", 0,
33:
34: #define FILTSW 7
35: "filter filterfile", 0,
36: #define FORMSW 8
37: "form formfile", 0,
38:
39: #define FRMTSW 9
40: "format", 5,
41: #define NFRMTSW 10
42: "noformat", 7,
43:
44: #define INPLSW 11
45: "inplace", 0,
46: #define NINPLSW 12
47: "noinplace", 0,
48:
49: #define DGSTSW 13
50: "digest list", 0,
51: #define ISSUESW 14
52: "issue number", 0,
53: #define VOLUMSW 15
54: "volume number", 0,
55:
56: #define WHATSW 16
57: "whatnowproc program", 0,
58: #define NWHATSW 17
59: "nowhatnowproc", 0,
60:
61: #define DASHSW 18
62: "dashmunging", 4,
63: #define NDASHSW 19
64: "nodashmunging", 6,
65:
66: #define HELPSW 20
67: "help", 4,
68:
69: #define FILESW 21
70: "file file", -4, /* interface from msh */
71:
72: #ifdef MHE
73: #define BILDSW 22
74: "build", -5, /* interface from mhe */
75: #endif MHE
76:
77: NULL, NULL
78: };
79:
80: /* */
81:
82: static struct swit aqrnl[] = {
83: #define NOSW 0
84: "quit", 0,
85: #define YESW 1
86: "replace", 0,
87: #define LISTDSW 2
88: "list", 0,
89: #define REFILSW 3
90: "refile +folder", 0,
91: #define NEWSW 4
92: "new", 0,
93:
94: NULL, NULL
95: };
96:
97:
98: static struct swit aqrl[] = {
99: "quit", 0,
100: "replace", 0,
101: "list", 0,
102: "refile +folder", 0,
103:
104: NULL, NULL
105: };
106:
107: /* */
108:
109: static char drft[BUFSIZ];
110:
111: static char delim3[] =
112: "\n------------------------------------------------------------\n\n";
113: static char delim4[] = "\n------------------------------\n\n";
114:
115:
116: static struct msgs *mp = NULL; /* used a lot */
117:
118:
119: long lseek(), time();
120:
121: static void mhl_draft(), copy_draft();
122: static int build_form();
123:
124: /* */
125:
126: /* ARGSUSED */
127:
128: main(argc, argv)
129: int argc;
130: char *argv[];
131: {
132: int msgp = 0,
133: anot = 0,
134: inplace = 0,
135: issue = 0,
136: volume = 0,
137: dashflg = 1,
138: #ifdef MHE
139: buildsw = 0,
140: #endif MHE
141: nedit = 0,
142: nwhat = 0,
143: i,
144: in,
145: out,
146: isdf = 0,
147: msgnum;
148: char *cp,
149: *cwd,
150: *maildir,
151: *dfolder = NULL,
152: *dmsg = NULL,
153: *digest = NULL,
154: *ed = NULL,
155: *file = NULL,
156: *filter = NULL,
157: *folder = NULL,
158: *form = NULL,
159: buf[100],
160: value[10],
161: **ap,
162: **argp,
163: *arguments[MAXARGS],
164: *msgs[MAXARGS];
165: struct stat st;
166:
167: invo_name = r1bindex (argv[0], '/');
168: if ((cp = m_find (invo_name)) != NULL) {
169: ap = brkstring (cp = getcpy (cp), " ", "\n");
170: ap = copyip (ap, arguments);
171: }
172: else
173: ap = arguments;
174: (void) copyip (argv + 1, ap);
175: argp = arguments;
176:
177: /* */
178:
179: while (cp = *argp++) {
180: if (*cp == '-')
181: switch (smatch (++cp, switches)) {
182: case AMBIGSW:
183: ambigsw (cp, switches);
184: done (1);
185: case UNKWNSW:
186: adios (NULLCP, "-%s unknown", cp);
187: case HELPSW:
188: (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
189: invo_name);
190: help (buf, switches);
191: done (1);
192:
193: case ANNOSW:
194: anot++;
195: continue;
196: case NANNOSW:
197: anot = 0;
198: continue;
199:
200: case EDITRSW:
201: if (!(ed = *argp++) || *ed == '-')
202: adios (NULLCP, "missing argument to %s", argp[-2]);
203: nedit = 0;
204: continue;
205: case NEDITSW:
206: nedit++;
207: continue;
208:
209: case WHATSW:
210: if (!(whatnowproc = *argp++) || *whatnowproc == '-')
211: adios (NULLCP, "missing argument to %s", argp[-2]);
212: nwhat = 0;
213: continue;
214: #ifdef MHE
215: case BILDSW:
216: buildsw++; /* fall... */
217: #endif MHE
218: case NWHATSW:
219: nwhat++;
220: continue;
221:
222: case FILESW:
223: if (file)
224: adios (NULLCP, "only one file at a time!");
225: if (!(cp = *argp++) || *cp == '-')
226: adios (NULLCP, "missing argument to %s", argp[-2]);
227: file = path (cp, TFILE);
228: continue;
229: case FILTSW:
230: if (!(cp = *argp++) || *cp == '-')
231: adios (NULLCP, "missing argument to %s", argp[-2]);
232: filter = getcpy (libpath (cp));
233: continue;
234: case FORMSW:
235: if (!(form = *argp++) || *form == '-')
236: adios (NULLCP, "missing argument to %s", argp[-2]);
237: continue;
238:
239: case FRMTSW:
240: filter = getcpy (libpath (mhlforward));
241: continue;
242: case NFRMTSW:
243: filter = NULL;
244: continue;
245:
246: case INPLSW:
247: inplace++;
248: continue;
249: case NINPLSW:
250: inplace = 0;
251: continue;
252:
253: case DGSTSW:
254: if (!(digest = *argp++) || *digest == '-')
255: adios (NULLCP, "missing argument to %s", argp[-2]);
256: continue;
257: case ISSUESW:
258: if (!(cp = *argp++) || *cp == '-')
259: adios (NULLCP, "missing argument to %s", argp[-2]);
260: if ((issue = atoi (cp)) < 1)
261: adios (NULLCP, "bad argument %s %s", argp[-2], cp);
262: continue;
263: case VOLUMSW:
264: if (!(cp = *argp++) || *cp == '-')
265: adios (NULLCP, "missing argument to %s", argp[-2]);
266: if ((volume = atoi (cp)) < 1)
267: adios (NULLCP, "bad argument %s %s", argp[-2], cp);
268: continue;
269:
270: case DFOLDSW:
271: if (dfolder)
272: adios (NULLCP, "only one draft folder at a time!");
273: if (!(cp = *argp++) || *cp == '-')
274: adios (NULLCP, "missing argument to %s", argp[-2]);
275: dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
276: *cp != '@' ? TFOLDER : TSUBCWF);
277: continue;
278: case DMSGSW:
279: if (dmsg)
280: adios (NULLCP, "only one draft message at a time!");
281: if (!(dmsg = *argp++) || *dmsg == '-')
282: adios (NULLCP, "missing argument to %s", argp[-2]);
283: continue;
284: case NDFLDSW:
285: dfolder = NULL;
286: isdf = NOTOK;
287: continue;
288:
289: case DASHSW:
290: dashflg++;
291: continue;
292: case NDASHSW:
293: dashflg = 0;
294: continue;
295: }
296: if (*cp == '+' || *cp == '@') {
297: if (folder)
298: adios (NULLCP, "only one folder at a time!");
299: else
300: folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
301: }
302: else
303: msgs[msgp++] = cp;
304: }
305:
306: /* */
307:
308: cwd = getcpy (pwd ());
309:
310: if (!m_find ("path"))
311: free (path ("./", TFOLDER));
312: if (file && (msgp || folder))
313: adios (NULLCP, "can't mix files and folders/msgs");
314:
315: try_it_again: ;
316: #ifndef MHE
317: (void) strcpy (drft, m_draft (dfolder, dmsg, NOUSE, &isdf));
318: if (stat (drft, &st) != NOTOK)
319: #else MHE
320: (void) strcpy (drft, buildsw ? m_maildir ("draft")
321: : m_draft (dfolder, NULLCP, NOUSE, &isdf));
322: if (!buildsw && stat (drft, &st) != NOTOK)
323: #endif MHE
324: {
325: printf ("Draft \"%s\" exists (%ld bytes).", drft, st.st_size);
326: for (i = LISTDSW; i != YESW;) {
327: if (!(argp = getans ("\nDisposition? ", isdf ? aqrnl : aqrl)))
328: done (1);
329: switch (i = smatch (*argp, isdf ? aqrnl : aqrl)) {
330: case NOSW:
331: done (0);
332: case NEWSW:
333: dmsg = NULL;
334: goto try_it_again;
335: case YESW:
336: break;
337: case LISTDSW:
338: (void) showfile (++argp, drft);
339: break;
340: case REFILSW:
341: if (refile (++argp, drft) == 0)
342: i = YESW;
343: break;
344: default:
345: advise (NULLCP, "say what?");
346: break;
347: }
348: }
349: }
350:
351: /* */
352:
353: if (file) {
354: anot = 0;
355: goto go_to_it;
356: }
357:
358: if (!msgp)
359: msgs[msgp++] = "cur";
360: if (!folder)
361: folder = m_getfolder ();
362: maildir = m_maildir (folder);
363:
364: if (chdir (maildir) == NOTOK)
365: adios (maildir, "unable to change directory to");
366: if (!(mp = m_gmsg (folder)))
367: adios (NULLCP, "unable to read folder %s", folder);
368: if (mp -> hghmsg == 0)
369: adios (NULLCP, "no messages in %s", folder);
370:
371: for (msgnum = 0; msgnum < msgp; msgnum++)
372: if (!m_convert (mp, msgs[msgnum]))
373: done (1);
374: m_setseq (mp);
375:
376: /* */
377:
378: go_to_it: ;
379: if (filter && access (filter, 04) == NOTOK)
380: adios (filter, "unable to read");
381:
382: if (digest) {
383: if (issue == 0) {
384: (void) sprintf (buf, IFMT, digest);
385: if (volume == 0
386: && (cp = m_find (buf))
387: && ((issue = atoi (cp)) < 0))
388: issue = 0;
389: issue++;
390: }
391: if (volume == 0)
392: (void) sprintf (buf, VFMT, digest);
393: if ((cp = m_find (buf)) == NULL || (volume = atoi (cp)) <= 0)
394: volume = 1;
395: if (!form)
396: form = digestcomps;
397: in = build_form (form, digest, volume, issue);
398: }
399: else
400: if (form) {
401: if ((in = open (libpath (form), 0)) == NOTOK)
402: adios (form, "unable to open form file");
403: }
404: else {
405: if ((in = open (libpath (forwcomps), 0)) == NOTOK)
406: adios (forwcomps, "unable to open default components file");
407: form = forwcomps;
408: }
409:
410: if ((out = creat (drft, m_gmprot ())) == NOTOK)
411: adios (drft, "unable to create");
412:
413: cpydata (in, out, form, drft);
414: (void) close (in);
415:
416: /* */
417:
418: if (file) {
419: if ((in = open (file, 0)) == NOTOK)
420: adios (file, "unable to open");
421: cpydata (in, out, file, drft);
422: (void) close (in);
423: (void) close (out);
424: goto edit_it;
425: }
426:
427: if (filter)
428: mhl_draft (out, digest, drft, filter, dashflg);
429: else
430: copy_draft (out, digest, drft);
431: (void) close (out);
432:
433: if (digest) {
434: (void) sprintf (buf, IFMT, digest);
435: (void) sprintf (value, "%d", issue);
436: m_replace (buf, getcpy (value));
437: (void) sprintf (buf, VFMT, digest);
438: (void) sprintf (value, "%d", volume);
439: m_replace (buf, getcpy (value));
440: }
441:
442: m_replace (pfolder, folder);
443: if (mp -> lowsel != mp -> curmsg)
444: m_setcur (mp, mp -> lowsel);
445: m_sync (mp);
446: m_update ();
447:
448: edit_it: ;
449: if (nwhat)
450: done (0);
451: (void) m_whatnow (ed, nedit, NOUSE, drft, NULLCP, 0, mp,
452: anot ? "Forwarded" : NULLCP, inplace, cwd);
453: done (1);
454: }
455:
456: /* */
457:
458: static void
459: mhl_draft(out, digest, file, filter, dashflg)
460: int out;
461: register char *digest, *file, *filter;
462: int dashflg;
463: {
464: int i,
465: child_id,
466: msgnum,
467: pd[2];
468: char *vec[MAXARGS];
469:
470: if (pipe (pd) == NOTOK)
471: adios ("pipe", "unable to create");
472:
473: vec[0] = r1bindex (mhlproc, '/');
474:
475: for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
476: sleep (5);
477: switch (child_id) {
478: case NOTOK:
479: adios ("fork", "unable to");
480:
481: case OK:
482: (void) close (pd[0]);
483: (void) dup2 (pd[1], 1);
484: (void) close (pd[1]);
485:
486: i = 1;
487: vec[i++] = "-forwall";
488: vec[i++] = "-form";
489: vec[i++] = filter;
490: if (digest) {
491: vec[i++] = "-digest";
492: vec[i++] = digest;
493: }
494: if (dashflg)
495: vec[i++] = "-dashmunging";
496: else
497: vec[i++] = "-nodashmunging";
498: if (mp -> numsel >= MAXARGS - i)
499: adios (NULLCP, "more than %d messages for %s exec",
500: vec[0], MAXARGS - i);
501: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
502: if (mp -> msgstats[msgnum] & SELECTED)
503: vec[i++] = getcpy (m_name (msgnum));
504: vec[i] = NULL;
505:
506: execvp (mhlproc, vec);
507: fprintf (stderr, "unable to exec ");
508: perror (mhlproc);
509: _exit (-1);
510:
511: default:
512: (void) close (pd[1]);
513: cpydata (pd[0], out, vec[0], file);
514: (void) close (pd[0]);
515: (void) pidXwait (child_id, mhlproc);
516: break;
517: }
518: }
519:
520: /* */
521:
522: static void
523: copy_draft(out, digest, file)
524: int out;
525: register char *digest, *file;
526: {
527: int fd,i,
528: msgcnt,
529: msgnum;
530: register char *bp,
531: *msgnam;
532: char buffer[BUFSIZ];
533:
534: msgcnt = 1;
535: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
536: if (mp -> msgstats[msgnum] & SELECTED) {
537: if (digest)
538: (void) strcpy (buffer,
539: msgnum == mp -> lowsel ? delim3 : delim4);
540: else {
541: (void) strcpy (bp = buffer, "\n-------"), bp += strlen (bp);
542: if (msgnum == mp -> lowsel)
543: (void) sprintf (bp, " Forwarded Message%s",
544: mp -> numsel > 1 ? "s" : "");
545: else
546: (void) sprintf (bp, " Message %d", msgcnt);
547: bp += strlen (bp);
548: (void) strcpy (bp, "\n\n");
549: }
550: (void) write (out, buffer, strlen (buffer));
551:
552: if ((fd = open (msgnam = m_name (msgnum), 0)) == NOTOK) {
553: admonish (msgnam, "unable to read message");
554: continue;
555: }
556: cpydgst (fd, out, msgnam, file);
557: (void) close (fd);
558:
559: msgcnt++;
560: }
561:
562: if (digest)
563: (void) strcpy (buffer, delim4);
564: else
565: (void) sprintf (buffer, "\n------- End of Forwarded Message%s\n\n",
566: mp -> numsel > 1 ? "s" : "");
567: (void) write (out, buffer, strlen (buffer));
568:
569: if (digest) {
570: (void) sprintf (buffer, "End of %s Digest\n", digest);
571: i = strlen (buffer);
572: for (bp = buffer + i; i > 1; i--)
573: *bp++ = '*';
574: *bp++ = '\n';
575: *bp = NULL;
576: (void) write (out, buffer, strlen (buffer));
577: }
578: }
579:
580: /* */
581:
582: static int
583: build_form(form, digest, volume, issue)
584: register char *form, *digest;
585: int volume, issue;
586: {
587: int in;
588: int fmtsize;
589: register char *nfs;
590: char *line,
591: tmpfil[BUFSIZ];
592: register FILE *tmp;
593: register struct comp *cptr;
594: struct format *fmt;
595: int dat[4];
596:
597: nfs = new_fs (form, NULLCP, NULLCP);
598: fmtsize = strlen (nfs) + 256;
599: (void) fmt_compile (nfs, &fmt);
600:
601: FINDCOMP (cptr, "digest");
602: if (cptr)
603: cptr->c_text = digest;
604: FINDCOMP (cptr, "date");
605: if (cptr)
606: cptr->c_text = getcpy(dtimenow ());
607:
608: dat[0] = issue;
609: dat[1] = volume;
610: dat[2] = 0;
611: dat[3] = fmtsize;
612:
613: (void) strcpy (tmpfil, m_tmpfil (invo_name));
614: if ((tmp = fopen (tmpfil, "w+")) == NULL)
615: adios (tmpfil, "unable to create");
616: (void) unlink (tmpfil);
617: if ((in = dup (fileno (tmp))) == NOTOK)
618: adios ("dup", "unable to");
619:
620: if ((line = malloc ((unsigned) fmtsize)) == NULLCP)
621: adios (NULLCP, "unable to allocate format line storage");
622: (void) fmtscan (fmt, line, fmtsize, dat);
623: (void) fputs (line, tmp);
624: (void) free (line);
625: if (fclose (tmp))
626: adios (tmpfil, "error writing");
627:
628: (void) lseek (in, 0L, 0);
629: return in;
630: }
631:
632: /*
633: * XXX We need to force WhatNow() to be linked in to get around
634: * library order problems
635: */
636: /* XXX don't bother if linking with the shared library */
637: #ifndef SHARED
638: static void
639: kludge()
640: {
641: WhatNow(0, (char **)0);
642: }
643: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.