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