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