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