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