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