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