Commit | Line | Data |
---|---|---|
ad787160 C |
1 | /* show.c - list messages */ |
2 | #ifndef lint | |
ed554bc5 | 3 | static char ident[] = "@(#)$Id: show.c,v 1.14 1993/10/26 20:09:21 jromine Exp $"; |
ad787160 C |
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; | |
ed554bc5 C |
339 | char *chset, |
340 | *cp, | |
ad787160 C |
341 | buf[BUFSIZ], |
342 | name[NAMESZ]; | |
343 | FILE *fp; | |
344 | ||
345 | if ((fp = fopen (msgnam, "r")) == NULL) | |
346 | return 0; | |
347 | ||
ed554bc5 C |
348 | if (!(chset = getenv ("MM_CHARSET"))) |
349 | chset = "us-ascii"; | |
350 | ||
ad787160 C |
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 out; | |
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 == '"') { | |
ed554bc5 | 425 | if (bp = index (++dp, '"')) |
ad787160 C |
426 | *bp = NULL; |
427 | } | |
428 | else | |
ed554bc5 C |
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; | |
ad787160 C |
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; | |
ed554bc5 C |
466 | result = !uleq (bp, "7bit") |
467 | && !uleq (bp, "8bit") | |
468 | && !uleq (bp, "binary"); | |
ad787160 C |
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 */ |