]> diplodocus.org Git - nmh/blob - uip/mhlistsbr.c
Quiet lock warning.
[nmh] / uip / mhlistsbr.c
1
2 /*
3 * mhlistsbr.c -- routines to list information about the
4 * -- contents of MIME messages
5 *
6 * $Id$
7 *
8 * This code is Copyright (c) 2002, by the authors of nmh. See the
9 * COPYRIGHT file in the root directory of the nmh distribution for
10 * complete copyright information.
11 */
12
13 #include <h/mh.h>
14 #include <fcntl.h>
15 #include <h/signals.h>
16 #include <errno.h>
17 #include <signal.h>
18 #include <h/mts.h>
19 #include <h/tws.h>
20 #include <h/mime.h>
21 #include <h/mhparse.h>
22
23 extern int errno;
24
25 /* mhmisc.c */
26 int part_ok (CT, int);
27 int type_ok (CT, int);
28 void flush_errors (void);
29
30 /*
31 * prototypes
32 */
33 void list_all_messages (CT *, int, int, int, int);
34 int list_switch (CT, int, int, int, int);
35 int list_content (CT, int, int, int, int);
36
37 /*
38 * static prototypes
39 */
40 static void list_single_message (CT, int, int, int);
41 static int list_debug (CT);
42 static int list_multi (CT, int, int, int, int);
43 static int list_partial (CT, int, int, int, int);
44 static int list_external (CT, int, int, int, int);
45 static int list_application (CT, int, int, int, int);
46 static int list_encoding (CT);
47
48
49 /*
50 * various formats for -list option
51 */
52 #define LSTFMT1 "%4s %-5s %-24s %5s %-36s\n"
53 #define LSTFMT2a "%4d "
54 #define LSTFMT2b "%-5s %-24.24s "
55 #define LSTFMT2c1 "%5lu"
56 #define LSTFMT2c2 "%4lu%c"
57 #define LSTFMT2c3 "huge "
58 #define LSTFMT2c4 " "
59 #define LSTFMT2d1 " %-36.36s"
60 #define LSTFMT2d2 "\t %-65.65s\n"
61
62
63 /*
64 * Top level entry point to list group of messages
65 */
66
67 void
68 list_all_messages (CT *cts, int headers, int realsize, int verbose, int debug)
69 {
70 CT ct, *ctp;
71
72 if (headers)
73 printf (LSTFMT1, "msg", "part", "type/subtype", "size", "description");
74
75 for (ctp = cts; *ctp; ctp++) {
76 ct = *ctp;
77 list_single_message (ct, realsize, verbose, debug);
78 }
79
80 flush_errors ();
81 }
82
83
84 /*
85 * Entry point to list a single message
86 */
87
88 static void
89 list_single_message (CT ct, int realsize, int verbose, int debug)
90 {
91 if (type_ok (ct, 1)) {
92 umask (ct->c_umask);
93 list_switch (ct, 1, realsize, verbose, debug);
94 if (ct->c_fp) {
95 fclose (ct->c_fp);
96 ct->c_fp = NULL;
97 }
98 if (ct->c_ceclosefnx)
99 (*ct->c_ceclosefnx) (ct);
100 }
101 }
102
103
104 /*
105 * Primary switching routine to list information about a content
106 */
107
108 int
109 list_switch (CT ct, int toplevel, int realsize, int verbose, int debug)
110 {
111 switch (ct->c_type) {
112 case CT_MULTIPART:
113 return list_multi (ct, toplevel, realsize, verbose, debug);
114 break;
115
116 case CT_MESSAGE:
117 switch (ct->c_subtype) {
118 case MESSAGE_PARTIAL:
119 return list_partial (ct, toplevel, realsize, verbose, debug);
120 break;
121
122 case MESSAGE_EXTERNAL:
123 return list_external (ct, toplevel, realsize, verbose, debug);
124 break;
125
126 case MESSAGE_RFC822:
127 default:
128 return list_content (ct, toplevel, realsize, verbose, debug);
129 break;
130 }
131 break;
132
133 case CT_TEXT:
134 case CT_AUDIO:
135 case CT_IMAGE:
136 case CT_VIDEO:
137 return list_content (ct, toplevel, realsize, verbose, debug);
138 break;
139
140 case CT_APPLICATION:
141 return list_application (ct, toplevel, realsize, verbose, debug);
142 break;
143
144 default:
145 /* list_debug (ct); */
146 adios (NULL, "unknown content type %d", ct->c_type);
147 break;
148 }
149
150 return 0; /* NOT REACHED */
151 }
152
153
154 #define empty(s) ((s) ? (s) : "")
155
156 /*
157 * Method for listing information about a simple/generic content
158 */
159
160 int
161 list_content (CT ct, int toplevel, int realsize, int verbose, int debug)
162 {
163 unsigned long size;
164 char *cp, buffer[BUFSIZ];
165 CI ci = &ct->c_ctinfo;
166
167 printf (toplevel > 0 ? LSTFMT2a : toplevel < 0 ? "part " : " ",
168 atoi (r1bindex (empty (ct->c_file), '/')));
169 snprintf (buffer, sizeof(buffer), "%s/%s", empty (ci->ci_type),
170 empty (ci->ci_subtype));
171 printf (LSTFMT2b, empty (ct->c_partno), buffer);
172
173 if (ct->c_cesizefnx && realsize)
174 size = (*ct->c_cesizefnx) (ct);
175 else
176 size = ct->c_end - ct->c_begin;
177
178 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
179 for (cp = " KMGT"; size > 9999; size >>= 10)
180 if (!*++cp)
181 break;
182
183 /* print size of this body part */
184 switch (*cp) {
185 case ' ':
186 if (size > 0 || ct->c_encoding != CE_EXTERNAL)
187 printf (LSTFMT2c1, size);
188 else
189 printf (LSTFMT2c4);
190 break;
191
192 default:
193 printf (LSTFMT2c2, size, *cp);
194 break;
195
196 case '\0':
197 printf (LSTFMT2c3);
198 }
199
200 /* print Content-Description */
201 if (ct->c_descr) {
202 char *dp;
203
204 dp = trimcpy (cp = add (ct->c_descr, NULL));
205 free (cp);
206 printf (LSTFMT2d1, dp);
207 free (dp);
208 }
209
210 printf ("\n");
211
212 /*
213 * If verbose, print any RFC-822 comments in the
214 * Content-Type line.
215 */
216 if (verbose && ci->ci_comment) {
217 char *dp;
218
219 dp = trimcpy (cp = add (ci->ci_comment, NULL));
220 free (cp);
221 snprintf (buffer, sizeof(buffer), "(%s)", dp);
222 free (dp);
223 printf (LSTFMT2d2, buffer);
224 }
225
226 if (debug)
227 list_debug (ct);
228
229 return OK;
230 }
231
232
233 /*
234 * Print debugging information about a content
235 */
236
237 static int
238 list_debug (CT ct)
239 {
240 char **ap, **ep;
241 CI ci = &ct->c_ctinfo;
242
243 fflush (stdout);
244 fprintf (stderr, " partno \"%s\"\n", empty (ct->c_partno));
245
246 /* print MIME-Version line */
247 if (ct->c_vrsn)
248 fprintf (stderr, " %s:%s\n", VRSN_FIELD, ct->c_vrsn);
249
250 /* print Content-Type line */
251 if (ct->c_ctline)
252 fprintf (stderr, " %s:%s\n", TYPE_FIELD, ct->c_ctline);
253
254 /* print parsed elements of content type */
255 fprintf (stderr, " type \"%s\"\n", empty (ci->ci_type));
256 fprintf (stderr, " subtype \"%s\"\n", empty (ci->ci_subtype));
257 fprintf (stderr, " comment \"%s\"\n", empty (ci->ci_comment));
258 fprintf (stderr, " magic \"%s\"\n", empty (ci->ci_magic));
259
260 /* print parsed parameters attached to content type */
261 fprintf (stderr, " parameters\n");
262 for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++)
263 fprintf (stderr, " %s=\"%s\"\n", *ap, *ep);
264
265 /* print internal flags for type/subtype */
266 fprintf (stderr, " type 0x%x subtype 0x%x params 0x%x\n",
267 ct->c_type, ct->c_subtype, (unsigned int) ct->c_ctparams);
268
269 fprintf (stderr, " showproc \"%s\"\n", empty (ct->c_showproc));
270 fprintf (stderr, " termproc \"%s\"\n", empty (ct->c_termproc));
271 fprintf (stderr, " storeproc \"%s\"\n", empty (ct->c_storeproc));
272
273 /* print transfer encoding information */
274 if (ct->c_celine)
275 fprintf (stderr, " %s:%s", ENCODING_FIELD, ct->c_celine);
276
277 /* print internal flags for transfer encoding */
278 fprintf (stderr, " transfer encoding 0x%x params 0x%x\n",
279 ct->c_encoding, (unsigned int) ct->c_cefile);
280
281 /* print Content-ID */
282 if (ct->c_id)
283 fprintf (stderr, " %s:%s", ID_FIELD, ct->c_id);
284
285 /* print Content-Description */
286 if (ct->c_descr)
287 fprintf (stderr, " %s:%s", DESCR_FIELD, ct->c_descr);
288
289 fprintf (stderr, " read fp 0x%x file \"%s\" begin %ld end %ld\n",
290 (unsigned int) ct->c_fp, empty (ct->c_file),
291 ct->c_begin, ct->c_end);
292
293 /* print more information about transfer encoding */
294 list_encoding (ct);
295
296 return OK;
297 }
298
299 #undef empty
300
301
302 /*
303 * list content information for type "multipart"
304 */
305
306 static int
307 list_multi (CT ct, int toplevel, int realsize, int verbose, int debug)
308 {
309 struct multipart *m = (struct multipart *) ct->c_ctparams;
310 struct part *part;
311
312 /* list the content for toplevel of this multipart */
313 list_content (ct, toplevel, realsize, verbose, debug);
314
315 /* now list for all the subparts */
316 for (part = m->mp_parts; part; part = part->mp_next) {
317 CT p = part->mp_part;
318
319 if (part_ok (p, 1) && type_ok (p, 1))
320 list_switch (p, 0, realsize, verbose, debug);
321 }
322
323 return OK;
324 }
325
326
327 /*
328 * list content information for type "message/partial"
329 */
330
331 static int
332 list_partial (CT ct, int toplevel, int realsize, int verbose, int debug)
333 {
334 struct partial *p = (struct partial *) ct->c_ctparams;
335
336 list_content (ct, toplevel, realsize, verbose, debug);
337 if (verbose) {
338 printf ("\t [message %s, part %d", p->pm_partid, p->pm_partno);
339 if (p->pm_maxno)
340 printf (" of %d", p->pm_maxno);
341 printf ("]\n");
342 }
343
344 return OK;
345 }
346
347
348 /*
349 * list content information for type "message/external"
350 */
351
352 static int
353 list_external (CT ct, int toplevel, int realsize, int verbose, int debug)
354 {
355 struct exbody *e = (struct exbody *) ct->c_ctparams;
356
357 /*
358 * First list the information for the
359 * message/external content itself.
360 */
361 list_content (ct, toplevel, realsize, verbose, debug);
362
363 if (verbose) {
364 if (e->eb_name)
365 printf ("\t name=\"%s\"\n", e->eb_name);
366 if (e->eb_dir)
367 printf ("\t directory=\"%s\"\n", e->eb_dir);
368 if (e->eb_site)
369 printf ("\t site=\"%s\"\n", e->eb_site);
370 if (e->eb_server)
371 printf ("\t server=\"%s\"\n", e->eb_server);
372 if (e->eb_subject)
373 printf ("\t subject=\"%s\"\n", e->eb_subject);
374
375 /* This must be defined */
376 printf ("\t access-type=\"%s\"\n", e->eb_access);
377
378 if (e->eb_mode)
379 printf ("\t mode=\"%s\"\n", e->eb_mode);
380 if (e->eb_permission)
381 printf ("\t permission=\"%s\"\n", e->eb_permission);
382
383 if (e->eb_flags == NOTOK)
384 printf ("\t [service unavailable]\n");
385 }
386
387 /*
388 * Now list the information for the external content
389 * to which this content points.
390 */
391 list_content (e->eb_content, 0, realsize, verbose, debug);
392
393 return OK;
394 }
395
396
397 /*
398 * list content information for type "application"
399 */
400
401 static int
402 list_application (CT ct, int toplevel, int realsize, int verbose, int debug)
403 {
404 list_content (ct, toplevel, realsize, verbose, debug);
405 if (verbose) {
406 char **ap, **ep;
407 CI ci = &ct->c_ctinfo;
408
409 for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++)
410 printf ("\t %s=\"%s\"\n", *ap, *ep);
411 }
412
413 return OK;
414 }
415
416
417 /*
418 * list information about the Content-Transfer-Encoding
419 * used by a content.
420 */
421
422 static int
423 list_encoding (CT ct)
424 {
425 CE ce;
426
427 if ((ce = ct->c_cefile))
428 fprintf (stderr, " decoded fp 0x%x file \"%s\"\n",
429 (unsigned int) ce->ce_fp, ce->ce_file ? ce->ce_file : "");
430
431 return OK;
432 }