Added -nocontentid (and -contentid, for symmetry) switch to mhbuild. This allows...
[mmh] / uip / mhmisc.c
1
2 /*
3  * mhparse.c -- misc routines to process MIME messages
4  *
5  * $Id$
6  *
7  * This code is Copyright (c) 2002, by the authors of nmh.  See the
8  * COPYRIGHT file in the root directory of the nmh distribution for
9  * complete copyright information.
10  */
11
12 #include <h/mh.h>
13 #include <errno.h>
14 #include <h/mime.h>
15 #include <h/mhparse.h>
16 #include <h/utils.h>
17
18 extern int debugsw;
19
20 /*
21  * limit actions to specified parts or content types
22  */
23 int npart = 0;
24 int ntype = 0;
25 char *parts[NPARTS + 1];
26 char *types[NTYPES + 1];
27
28 int endian = 0;         /* little or big endian */
29 int userrs = 0;
30
31 static char *errs = NULL;
32
33
34 /*
35  * prototypes
36  */
37 int part_ok (CT, int);
38 int type_ok (CT, int);
39 void set_endian (void);
40 int make_intermediates (char *);
41 void content_error (char *, CT, char *, ...);
42 void flush_errors (void);
43
44
45 int
46 part_ok (CT ct, int sP)
47 {
48     char **ap;
49     int len;
50
51     if (npart == 0 || (ct->c_type == CT_MULTIPART && (sP || ct->c_subtype)))
52         return 1;
53
54     for (ap = parts; *ap; ap++) {
55         len = strlen(*ap);
56         if (!strncmp (*ap, ct->c_partno, len) &&
57                 (!ct->c_partno[len] || ct->c_partno[len] == '.' ))
58             return 1;
59     }
60
61     return 0;
62 }
63
64
65 int
66 type_ok (CT ct, int sP)
67 {
68     char **ap;
69     char buffer[BUFSIZ];
70     CI ci = &ct->c_ctinfo;
71
72     if (ntype == 0 || (ct->c_type == CT_MULTIPART && (sP || ct->c_subtype)))
73         return 1;
74
75     snprintf (buffer, sizeof(buffer), "%s/%s", ci->ci_type, ci->ci_subtype);
76     for (ap = types; *ap; ap++)
77         if (!strcasecmp (*ap, ci->ci_type) || !strcasecmp (*ap, buffer))
78             return 1;
79
80     return 0;
81 }
82
83
84 void
85 set_endian (void)
86 {
87     union {
88         long l;
89         char c[sizeof(long)];
90     } un;
91
92     un.l = 1;
93     endian = un.c[0] ? -1 : 1;
94     if (debugsw)
95         fprintf (stderr, "%s endian architecture\n",
96                 endian > 0 ? "big" : "little");
97 }
98
99
100 int
101 make_intermediates (char *file)
102 {
103     char *cp;
104
105     for (cp = file + 1; (cp = strchr(cp, '/')); cp++) {
106         struct stat st;
107
108         *cp = '\0';
109         if (stat (file, &st) == NOTOK) {
110             int answer;
111             char *ep;
112             if (errno != ENOENT) {
113                 advise (file, "error on directory");
114 losing_directory:
115                 *cp = '/';
116                 return NOTOK;
117             }
118
119             ep = concat ("Create directory \"", file, "\"? ", NULL);
120             answer = getanswer (ep);
121             free (ep);
122
123             if (!answer)
124                 goto losing_directory;
125             if (!makedir (file)) {
126                 advise (NULL, "unable to create directory %s", file);
127                 goto losing_directory;
128             }
129         }
130
131         *cp = '/';
132     }
133
134     return OK;
135 }
136
137
138 /*
139  * Construct error message for content
140  */
141
142 void
143 content_error (char *what, CT ct, char *fmt, ...)
144 {
145     va_list arglist;
146     int i, len, buflen;
147     char *bp, buffer[BUFSIZ];
148     CI ci;
149
150     bp = buffer;
151     buflen = sizeof(buffer);
152
153     if (userrs && invo_name && *invo_name) {
154         snprintf (bp, buflen, "%s: ", invo_name);
155         len = strlen (bp);
156         bp += len;
157         buflen -= len;
158     }
159
160     va_start (arglist, fmt);
161
162     vsnprintf (bp, buflen, fmt, arglist);
163     len = strlen (bp);
164     bp += len;
165     buflen -= len;
166
167     ci = &ct->c_ctinfo;
168
169     if (what) {
170         char *s;
171
172         if (*what) {
173             snprintf (bp, buflen, " %s: ", what);
174             len = strlen (bp);
175             bp += len;
176             buflen -= len;
177         }
178
179         if ((s = strerror (errno)))
180             snprintf (bp, buflen, "%s", s);
181         else
182             snprintf (bp, buflen, "Error %d", errno);
183
184         len = strlen (bp);
185         bp += len;
186         buflen -= len;
187     }
188
189     i = strlen (invo_name) + 2;
190
191     /* Now add content type and subtype */
192     snprintf (bp, buflen, "\n%*.*s(content %s/%s", i, i, "",
193         ci->ci_type, ci->ci_subtype);
194     len = strlen (bp);
195     bp += len;
196     buflen -= len;
197
198     /* Now add the message/part number */
199     if (ct->c_file) {
200         snprintf (bp, buflen, " in message %s", ct->c_file);
201         len = strlen (bp);
202         bp += len;
203         buflen -= len;
204
205         if (ct->c_partno) {
206             snprintf (bp, buflen, ", part %s", ct->c_partno);
207             len = strlen (bp);
208             bp += len;
209             buflen -= len;
210         }
211     }
212
213     snprintf (bp, buflen, ")");
214     len = strlen (bp);
215     bp += len;
216     buflen -= len;
217
218     if (userrs) {
219         *bp++ = '\n';
220         *bp = '\0';
221         buflen--;
222
223         errs = add (buffer, errs);
224     } else {
225         advise (NULL, "%s", buffer);
226     }
227 }
228
229
230 void
231 flush_errors (void)
232 {
233     if (errs) {
234         fflush (stdout);
235         fprintf (stderr, "%s", errs);
236         free (errs);
237         errs = NULL;
238     }
239 }