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