]> diplodocus.org Git - nmh/blob - uip/mhmisc.c
getpass.c: Move interface to own file.
[nmh] / uip / mhmisc.c
1 /* mhmisc.c -- misc routines to process MIME messages
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include "h/mh.h"
9 #include "sbr/error.h"
10 #include "h/mime.h"
11 #include "h/mhparse.h"
12 #include "h/utils.h"
13 #include "sbr/makedir.h"
14 #include "mhmisc.h"
15
16 extern int debugsw;
17
18 /*
19 * limit actions to specified parts or content types
20 */
21 int npart = 0;
22 int ntype = 0;
23 char *parts[NPARTS + 1];
24 char *types[NTYPES + 1];
25
26 bool userrs;
27
28 static char *errs = NULL;
29
30
31 int
32 part_ok (CT ct)
33 {
34 char **ap;
35 int len;
36
37 /* a part is "ok", i.e., should be processed, if:
38 - there were no -part arguments
39 - this part is a multipart
40 */
41 if (npart == 0 || ct->c_type == CT_MULTIPART) {
42 return 1;
43 }
44
45 /* or if:
46 - this part is a an exact match for any -part option
47 - this part is a sub-part of any -part option
48 */
49 for (ap = parts; *ap; ap++) {
50 len = strlen(*ap);
51 if (!strncmp (*ap, ct->c_partno, len) &&
52 (!ct->c_partno[len] || ct->c_partno[len] == '.' )) {
53 return 1;
54 }
55 }
56
57 return 0;
58 }
59
60 int
61 part_exact(CT ct)
62 {
63 char **ap;
64
65 if (!ct->c_partno)
66 return 0;
67
68 for (ap = parts; *ap; ap++) {
69 if (!strcmp (*ap, ct->c_partno)) {
70 return 1;
71 }
72 }
73
74 return 0;
75 }
76
77
78 int
79 type_ok (CT ct, int sP)
80 {
81 char **ap;
82 char buffer[BUFSIZ];
83 CI ci = &ct->c_ctinfo;
84
85 if (ntype == 0 || (ct->c_type == CT_MULTIPART && (sP || ct->c_subtype)))
86 return 1;
87
88 snprintf (buffer, sizeof(buffer), "%s/%s", ci->ci_type, ci->ci_subtype);
89 for (ap = types; *ap; ap++)
90 if (!strcasecmp (*ap, ci->ci_type) || !strcasecmp (*ap, buffer))
91 return 1;
92
93 return 0;
94 }
95
96
97 /*
98 * Returns true if the content has a disposition of "inline".
99 *
100 * Technically we should check parent content to see if they have
101 * disposition to use as a default, but we don't right now. Maybe
102 * later ....
103 */
104
105 int
106 is_inline(CT ct)
107 {
108 /*
109 * If there isn't any disposition at all, it's "inline". Obviously
110 * if it's "inline", then it's inline. RFC 2183 says if it's an unknown
111 * disposition, treat it as 'attachment'.
112 */
113
114 if (! ct->c_dispo_type || strcasecmp(ct->c_dispo_type, "inline") == 0)
115 return 1;
116 return 0;
117 }
118
119 int
120 make_intermediates (char *file)
121 {
122 char *cp;
123
124 for (cp = file + 1; (cp = strchr(cp, '/')); cp++) {
125 struct stat st;
126
127 *cp = '\0';
128 if (stat (file, &st) == NOTOK) {
129 int answer;
130 char *ep;
131 if (errno != ENOENT) {
132 advise (file, "error on directory");
133 losing_directory:
134 *cp = '/';
135 return NOTOK;
136 }
137
138 ep = concat ("Create directory \"", file, "\"? ", NULL);
139 answer = read_yes_or_no_if_tty (ep);
140 free (ep);
141
142 if (!answer)
143 goto losing_directory;
144 if (!makedir (file)) {
145 inform("unable to create directory %s", file);
146 goto losing_directory;
147 }
148 }
149
150 *cp = '/';
151 }
152
153 return OK;
154 }
155
156
157 /*
158 * Construct error message for content
159 */
160
161 void
162 content_error (char *what, CT ct, char *fmt, ...)
163 {
164 va_list arglist;
165 int len, buflen;
166 char *bp, buffer[BUFSIZ];
167 CI ci;
168
169 bp = buffer;
170 buflen = sizeof(buffer);
171
172 if (userrs && invo_name && *invo_name) {
173 snprintf (bp, buflen, "%s: ", invo_name);
174 len = strlen (bp);
175 bp += len;
176 buflen -= len;
177 }
178
179 va_start (arglist, fmt);
180
181 vsnprintf (bp, buflen, fmt, arglist);
182 len = strlen (bp);
183 bp += len;
184 buflen -= len;
185
186 ci = &ct->c_ctinfo;
187
188 if (what) {
189 char *s;
190
191 if (*what) {
192 snprintf (bp, buflen, " %s: ", what);
193 len = strlen (bp);
194 bp += len;
195 buflen -= len;
196 }
197
198 if ((s = strerror (errno)))
199 snprintf (bp, buflen, "%s", s);
200 else
201 snprintf (bp, buflen, "Error %d", errno);
202
203 len = strlen (bp);
204 bp += len;
205 buflen -= len;
206 }
207
208 /* Now add content type and subtype */
209 snprintf (bp, buflen, "\n (content %s/%s",
210 ci->ci_type, ci->ci_subtype);
211 len = strlen (bp);
212 bp += len;
213 buflen -= len;
214
215 /* Now add the message/part number */
216 if (ct->c_file) {
217 snprintf (bp, buflen, " in message %s", ct->c_file);
218 len = strlen (bp);
219 bp += len;
220 buflen -= len;
221
222 if (ct->c_partno) {
223 snprintf (bp, buflen, ", part %s", ct->c_partno);
224 len = strlen (bp);
225 bp += len;
226 buflen -= len;
227 }
228 }
229
230 snprintf (bp, buflen, ")");
231 len = strlen (bp);
232 bp += len;
233 buflen -= len;
234
235 if (userrs) {
236 *bp++ = '\n';
237 *bp = '\0';
238 buflen--;
239
240 errs = add (buffer, errs);
241 } else {
242 inform("%s", buffer);
243 }
244
245 va_end(arglist);
246 }
247
248
249 void
250 flush_errors (void)
251 {
252 if (errs) {
253 fflush (stdout);
254 fputs(errs, stderr);
255 free (errs);
256 errs = NULL;
257 }
258 }