Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / show.c
1 /* show.c - list messages */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: show.c,v 1.15 1995/12/06 21:07:46 jromine Exp $";
4 #endif  /* lint */
5
6 #include "../h/mh.h"
7 #include <ctype.h>
8 #include <stdio.h>
9 #ifdef LOCALE
10 #include        <locale.h>
11 #endif
12
13 /* \f */
14
15 static struct swit switches[] = {
16 #define DRFTSW  0
17     "draft", 5,
18
19 #define FORMSW  1
20     "form formfile", 4,
21 #define PROGSW  2
22     "moreproc program", 4,
23 #define NPROGSW 3
24     "nomoreproc", 3,
25 #define LENSW   4
26     "length lines", 4,
27 #define WIDSW   5
28     "width columns", 4,
29
30 #define SHOWSW  6
31     "showproc program", 4,
32 #define NSHOWSW 7
33     "noshowproc", 3,
34
35 #define HEADSW  8
36     "header", 4,
37 #define NHEADSW 9
38     "noheader", 3,
39
40 #define FILESW  10
41     "file file", -4,            /* interface from showfile */
42
43 #define HELPSW  11
44     "help", 4,
45
46     NULL, 0
47 };
48
49 #ifdef  MIME
50 static int  nontext();
51 #endif
52
53 #define SHOW    0
54 #define NEXT    1
55 #define PREV    2
56
57 /* \f */
58
59 /* ARGSUSED */
60
61 main (argc, argv)
62 int     argc;
63 char  **argv;
64 {
65     int     draftsw = 0,
66             headersw = 1,
67             nshow = 0,
68             msgp = 0,
69             vecp = 1,
70             procp = 1,
71             isdf = 0,
72             mode = SHOW,
73             msgnum;
74     char   *cp,
75            *maildir,
76            *file = NULL,
77            *folder = NULL,
78            *proc,
79             buf[100],
80           **ap,
81           **argp,
82            *arguments[MAXARGS],
83            *msgs[MAXARGS],
84            *vec[MAXARGS];
85     struct msgs *mp;
86
87 #ifdef LOCALE
88         setlocale(LC_ALL, "");
89 #endif
90     invo_name = r1bindex (argv[0], '/');
91     if (uleq (invo_name, "next"))
92         mode = NEXT;
93     else
94         if (uleq (invo_name, "prev"))
95             mode = PREV;
96     if ((cp = m_find (invo_name)) != NULL) {
97         ap = brkstring (cp = getcpy (cp), " ", "\n");
98         ap = copyip (ap, arguments);
99     }
100     else
101         ap = arguments;
102     (void) copyip (argv + 1, ap);
103     argp = arguments;
104
105 /* \f */
106
107     while (cp = *argp++) {
108         if (*cp == '-')
109             switch (smatch (++cp, switches)) {
110                 case AMBIGSW: 
111                     ambigsw (cp, switches);
112                     done (1);
113                 case UNKWNSW: 
114                 case NPROGSW:
115                     vec[vecp++] = --cp;
116                     continue;
117                 case HELPSW: 
118                     (void) sprintf (buf,
119                            "%s [+folder] %s[switches] [switches for showproc]",
120                             invo_name, mode == SHOW ? "[msgs] ": "");
121                     help (buf, switches);
122                     done (1);
123
124                 case DRFTSW: 
125                     if (file)
126                         adios (NULLCP, "only one file at a time!");
127                     draftsw++;
128                     if (mode == SHOW)
129                         continue;
130             usage:  ;
131                     adios (NULLCP,
132                             "usage: %s [+folder] [switches] [switches for showproc]",
133                             invo_name);
134                 case FILESW: 
135                     if (mode != SHOW)
136                         goto usage;
137                     if (draftsw || file)
138                         adios (NULLCP, "only one file at a time!");
139                     if (!(cp = *argp++) || *cp == '-')
140                         adios (NULLCP, "missing argument to %s", argp[-2]);
141                     file = path (cp, TFILE);
142                     continue;
143
144                 case HEADSW: 
145                     headersw++;
146                     continue;
147                 case NHEADSW: 
148                     headersw = 0;
149                     continue;
150
151                 case FORMSW:
152                     vec[vecp++] = --cp;
153                     if (!(cp = *argp++) || *cp == '-')
154                         adios (NULLCP, "missing argument to %s", argp[-2]);
155                     vec[vecp++] = getcpy (libpath(cp));
156                     continue;
157
158                 case PROGSW:
159                 case LENSW:
160                 case WIDSW:
161                     vec[vecp++] = --cp;
162                     if (!(cp = *argp++) || *cp == '-')
163                         adios (NULLCP, "missing argument to %s", argp[-2]);
164                     vec[vecp++] = cp;
165                     continue;
166
167                 case SHOWSW: 
168                     if (!(showproc = *argp++) || *showproc == '-')
169                         adios (NULLCP, "missing argument to %s", argp[-2]);
170                     nshow = 0;
171                     continue;
172                 case NSHOWSW: 
173                     nshow++;
174                     continue;
175             }
176         if (*cp == '+' || *cp == '@') {
177             if (folder)
178                 adios (NULLCP, "only one folder at a time!");
179             else
180                 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
181         }
182         else
183             if (mode != SHOW)
184                 goto usage;
185             else
186                 msgs[msgp++] = cp;
187     }
188     procp = vecp;
189
190 /* \f */
191
192     if (!m_find ("path"))
193         free (path ("./", TFOLDER));
194
195     if (draftsw || file) {
196         if (msgp)
197             adios (NULLCP, "only one file at a time!");
198         vec[vecp++] = draftsw
199             ? getcpy (m_draft (folder, msgp ? msgs[0] : NULL, 1, &isdf))
200             : file;
201         goto go_to_it;
202     }
203
204 #ifdef  WHATNOW
205     if (!msgp && !folder && mode == SHOW && (cp = getenv ("mhdraft")) && *cp) {
206         draftsw++;
207         vec[vecp++] = cp;
208         goto go_to_it;
209     }
210 #endif  /* WHATNOW */
211
212     if (!msgp)
213         msgs[msgp++] = mode == NEXT ? "next" : mode == PREV ? "prev" : "cur";
214     if (!folder)
215         folder = m_getfolder ();
216     maildir = m_maildir (folder);
217
218     if (chdir (maildir) == NOTOK)
219         adios (maildir, "unable to change directory to");
220     if (!(mp = m_gmsg (folder)))
221         adios (NULLCP, "unable to read folder %s", folder);
222     if (mp -> hghmsg == 0)
223         adios (NULLCP, "no messages in %s", folder);
224
225     for (msgnum = 0; msgnum < msgp; msgnum++)
226         if (!m_convert (mp, msgs[msgnum]))
227             done (1);
228     for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
229         if (mp -> msgstats[msgnum] & SELECTED)
230             mp -> msgstats[msgnum] |= UNSEEN;
231     m_setseq (mp);
232     m_setvis (mp, 1);
233
234     if (mp -> numsel > MAXARGS - 2)
235         adios (NULLCP, "more than %d messages for show exec", MAXARGS - 2);
236     for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
237         if (mp -> msgstats[msgnum] & SELECTED)
238             vec[vecp++] = getcpy (m_name (msgnum));
239
240     m_replace (pfolder, folder);
241     if (mp -> hghsel != mp -> curmsg)
242         m_setcur (mp, mp -> hghsel);
243     m_sync (mp);
244     m_update ();
245
246     if (vecp == 2 && headersw)
247         printf ("(Message %s:%s)\n", folder, vec[1]);
248
249 /* \f */
250
251 go_to_it: ;
252     (void) fflush (stdout);
253
254     vec[vecp] = NULL;
255
256 #ifdef  MIME
257     if (!nshow && !getenv ("NOMHNPROC")) {
258         if (!(cp = m_find ("mhnproc")))
259             cp = "mhn";
260
261         if (draftsw || file) {
262             if (nontext (vec[vecp - 1])) {
263                 vec[vecp] = vec[vecp - 1];
264                 vec[vecp - 1] = "-file";
265                 vecp++;
266                 goto use_mmp;
267             }
268         }
269         else
270             for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
271                 if ((mp -> msgstats[msgnum] & SELECTED)
272                         && nontext (m_name (msgnum))) {
273 use_mmp: ;
274                     proc = cp;
275                     vec[vecp++] = "-show";
276                     vec[vecp] = NULL;
277                     goto finish;
278                 }
279     }
280 #endif  /* MIME */
281     if (nshow)
282         proc = "/bin/cat";
283     else {
284         if (folder && !draftsw && !file)
285             (void) m_putenv ("mhfolder", folder);
286         if (strcmp (r1bindex (showproc, '/'), "mhl") == 0) {
287             vec[0] = "mhl";
288             (void) mhl (vecp, vec);
289             done (0);
290         }
291         proc = showproc;
292     }
293
294     if (!draftsw
295             && !file
296             && chdir (maildir = concat (m_maildir (""), "/", NULLCP))
297             != NOTOK) {
298         mp -> foldpath = concat (mp -> foldpath, "/", NULLCP);
299         cp = ssequal (maildir, mp -> foldpath)
300             ? mp -> foldpath + strlen (maildir)
301             : mp -> foldpath;
302         for (msgnum = procp; msgnum < vecp; msgnum++)
303             vec[msgnum] = concat (cp, vec[msgnum], NULLCP);
304     }
305
306 finish:;
307     vec[0] = r1bindex (proc, '/');
308     execvp (proc, vec);
309     adios (proc, "unable to exec");
310 }
311
312 /* \f */
313
314 /* Cheat:  we are loaded with adrparse, which wants a routine called
315    OfficialName().  We call adrparse:getm() with the correct arguments
316    to prevent OfficialName() from being called.  Hence, the following
317    is to keep the loader happy.
318  */
319
320 char   *OfficialName (name)
321 register char  *name;
322 {
323     return name;
324 }
325
326 /* \f */
327
328 #ifdef MIME
329 #include "../h/mhn.h"
330
331
332 static int  nontext (msgnam)
333 char   *msgnam;
334 {
335     int     result,
336             state;
337     register char   *bp,
338                     *dp;
339     char   *chset,
340            *cp,
341             buf[BUFSIZ],
342             name[NAMESZ];
343     FILE   *fp;
344
345     if ((fp = fopen (msgnam, "r")) == NULL)
346         return 0;
347
348     if (!(chset = getenv ("MM_CHARSET")))
349         chset = "us-ascii";
350
351     for (state = FLD;;)
352         switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
353             case FLD:
354             case FLDPLUS:
355             case FLDEOF:
356                 if (uleq (name, TYPE_FIELD)) {
357                     int     passno;
358                     char     c;
359
360                     cp = add (buf, NULLCP);
361                     while (state == FLDPLUS) {
362                         state = m_getfld (state, name, buf, sizeof buf, fp);
363                         cp = add (buf, cp);
364                     }
365                     bp = cp;
366                     passno = 1;
367
368 again: ;
369                     for (; isspace (*bp); bp++)
370                         continue;
371                     if (*bp == '(') {
372                         int     i;
373
374                         for (bp++, i = 0;;) {
375                             switch (*bp++) {
376                                 case '\0':
377 invalid: ;
378                                     result = 0;
379                                     goto out;
380                                 case '\\':
381                                     if (*bp++ == '\0')
382                                         goto invalid;
383                                     continue;
384                                 case '(':
385                                     i++;
386                                     /* and fall... */
387                                 default:
388                                     continue;
389                                 case ')':
390                                     if (--i < 0)
391                                         break;
392                                 continue;
393                             }
394                             break;
395                         }
396                     }
397                     if (passno == 2) {
398                         if (*bp != '/')
399                             goto invalid;
400                         bp++;
401                         passno = 3;
402                         goto again;
403                     }
404                     for (dp = bp; istoken (*dp); dp++)
405                         continue;
406                     c = *dp, *dp = NULL;
407                     if (*bp == NULL)
408                         goto invalid;
409                     if (passno > 1) {
410                         if (result = !uleq (bp, "plain"))
411                             goto out;
412                         *dp = c;
413                         for (dp++; isspace (*dp); dp++)
414                             continue;
415                         if (result = !uprf (dp, "charset"))
416                             goto invalid;
417                         dp += sizeof "charset" - 1;
418                         while (isspace (*dp))
419                             dp++;
420                         if (*dp++ != '=')
421                             goto invalid;
422                         while (isspace (*dp))
423                             dp++;
424                         if (*dp == '"') {
425                             if (bp = index (++dp, '"'))
426                                 *bp = NULL;
427                         }
428                         else
429                             for (bp = dp; *bp; bp++)
430                                 if (isspace (*bp)) {
431                                     *bp = NULL;
432                                     break;
433                                 }
434                         if ((result = !uleq (dp, chset))
435                                 && uleq (dp, "us-ascii")
436                                 && uleq (chset, "iso-8859-1"))
437                             result = 0;
438                     }
439                     else
440                         if (!(result = !uleq (bp, "text"))) {
441                             *dp = c;
442                             bp = dp;
443                             passno = 2;
444                             goto again;
445                         }
446
447 out: ;
448                     free (cp);
449                     if (result) {
450                         (void) fclose (fp);
451                         return result;
452                     }
453                     break;
454                 }
455                 if (uleq (name, ENCODING_FIELD)) {
456                     cp = add (buf, NULLCP);
457                     while (state == FLDPLUS) {
458                         state = m_getfld (state, name, buf, sizeof buf, fp);
459                         cp = add (buf, cp);
460                     }
461                     for (bp = cp; isspace (*bp); bp++)
462                         continue;
463                     for (dp = bp; istoken (*dp); dp++)
464                         continue;
465                     *dp = NULL;
466                     result = !uleq (bp, "7bit")
467                                 && !uleq (bp, "8bit")
468                                 && !uleq (bp, "binary");
469
470                     free (cp);
471                     if (result) {
472                         (void) fclose (fp);
473                         return result;
474                     }
475                     break;
476                 }
477                 while (state == FLDPLUS)
478                     state = m_getfld (state, name, buf, sizeof buf, fp);
479                 break;
480
481             default:
482                 (void) fclose (fp);
483                 return 0;
484         }
485 }
486 #endif  /* MIME */