source: trunk/third/nmh/uip/mhtest.c @ 12455

Revision 12455, 9.1 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12454, which included commits to RCS files with non-trunk default branches.
Line 
1
2/*
3 * mhtest.c -- test harness for MIME routines
4 *
5 * $Id: mhtest.c,v 1.1.1.1 1999-02-07 18:14:15 danw Exp $
6 */
7
8#include <h/mh.h>
9#include <fcntl.h>
10#include <h/signals.h>
11#include <h/md5.h>
12#include <errno.h>
13#include <signal.h>
14#include <zotnet/mts/mts.h>
15#include <zotnet/tws/tws.h>
16#include <h/mime.h>
17#include <h/mhparse.h>
18#include <h/mhcachesbr.h>
19
20#ifdef HAVE_SYS_WAIT_H
21# include <sys/wait.h>
22#endif
23
24/*
25 * We allocate space for message names (msgs array)
26 * this number of elements at a time.
27 */
28#define MAXMSGS  256
29
30
31static struct swit switches[] = {
32#define CHECKSW                 0
33    { "check", 0 },
34#define NCHECKSW                1
35    { "nocheck", 0 },
36#define VERBSW                  2
37    { "verbose", 0 },
38#define NVERBSW                 3
39    { "noverbose", 0 },
40#define FILESW                  4
41    { "file file", 0 },
42#define OUTFILESW               5
43    { "outfile file", 0 },
44#define PARTSW                  6
45    { "part number", 0 },
46#define TYPESW                  7
47    { "type content", 0 },
48#define RCACHESW                8
49    { "rcache policy", 0 },
50#define WCACHESW                9
51    { "wcache policy", 0 },
52#define VERSIONSW              10
53    { "version", 0 },
54#define HELPSW                 11
55    { "help", 4 },
56
57/*
58 * switches for debugging
59 */
60#define DEBUGSW                12
61    { "debug", -5 },
62    { NULL, 0 }
63};
64
65
66extern int errno;
67
68int ebcdicsw = 0;       /* hack for linking purposes */
69
70/* mhparse.c */
71extern int checksw;
72extern char *tmp;       /* directory to place temp files */
73
74/* mhcachesbr.c */
75extern int rcachesw;
76extern int wcachesw;
77extern char *cache_public;
78extern char *cache_private;
79
80/* mhmisc.c */
81extern int npart;
82extern int ntype;
83extern char *parts[NPARTS + 1];
84extern char *types[NTYPES + 1];
85extern int userrs;
86
87/*
88 * This is currently needed to keep mhparse happy.
89 * This needs to be changed.
90 */
91pid_t xpid  = 0;
92
93int debugsw = 0;
94int verbosw = 0;
95
96/* The list of top-level contents to display */
97CT *cts = NULL;
98
99#define quitser pipeser
100
101/* mhparse.c */
102CT parse_mime (char *);
103
104/* mhoutsbr.c */
105int output_message (CT, char *);
106
107/* mhmisc.c */
108int part_ok (CT, int);
109int type_ok (CT, int);
110void set_endian (void);
111void flush_errors (void);
112
113/* mhfree.c */
114void free_content (CT);
115
116/*
117 * static prototypes
118 */
119static int write_content (CT *, char *);
120static RETSIGTYPE pipeser (int);
121
122
123int
124main (int argc, char **argv)
125{
126    int nummsgs, maxmsgs, msgnum, *icachesw;
127    char *cp, *file = NULL, *folder = NULL;
128    char *maildir, buf[100], *outfile = NULL;
129    char **argp, **arguments, **msgs;
130    struct msgs *mp = NULL;
131    CT ct, *ctp;
132
133#ifdef LOCALE
134    setlocale(LC_ALL, "");
135#endif
136    invo_name = r1bindex (argv[0], '/');
137
138    /* read user profile/context */
139    context_read();
140
141    arguments = getarguments (invo_name, argc, argv, 1);
142    argp = arguments;
143
144    /*
145     * Allocate the initial space to record message
146     * names, ranges, and sequences.
147     */
148    nummsgs = 0;
149    maxmsgs = MAXMSGS;
150    if (!(msgs = (char **) malloc ((size_t) (maxmsgs * sizeof(*msgs)))))
151        adios (NULL, "unable to allocate storage");
152
153    /*
154     * Parse arguments
155     */
156    while ((cp = *argp++)) {
157        if (*cp == '-') {
158            switch (smatch (++cp, switches)) {
159            case AMBIGSW:
160                ambigsw (cp, switches);
161                done (1);
162            case UNKWNSW:
163                adios (NULL, "-%s unknown", cp);
164
165            case HELPSW:
166                snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]",
167                        invo_name);
168                print_help (buf, switches, 1);
169                done (1);
170            case VERSIONSW:
171                print_version(invo_name);
172                done (1);
173
174            case RCACHESW:
175                icachesw = &rcachesw;
176                goto do_cache;
177            case WCACHESW:
178                icachesw = &wcachesw;
179do_cache:
180                if (!(cp = *argp++) || *cp == '-')
181                    adios (NULL, "missing argument to %s", argp[-2]);
182                switch (*icachesw = smatch (cp, caches)) {
183                case AMBIGSW:
184                    ambigsw (cp, caches);
185                    done (1);
186                case UNKWNSW:
187                    adios (NULL, "%s unknown", cp);
188                default:
189                    break;
190                }
191                continue;
192
193            case CHECKSW:
194                checksw++;
195                continue;
196            case NCHECKSW:
197                checksw = 0;
198                continue;
199
200            case PARTSW:
201                if (!(cp = *argp++) || *cp == '-')
202                    adios (NULL, "missing argument to %s", argp[-2]);
203                if (npart >= NPARTS)
204                    adios (NULL, "too many parts (starting with %s), %d max",
205                           cp, NPARTS);
206                parts[npart++] = cp;
207                continue;
208
209            case TYPESW:
210                if (!(cp = *argp++) || *cp == '-')
211                    adios (NULL, "missing argument to %s", argp[-2]);
212                if (ntype >= NTYPES)
213                    adios (NULL, "too many types (starting with %s), %d max",
214                           cp, NTYPES);
215                types[ntype++] = cp;
216                continue;
217
218            case FILESW:
219                if (!(cp = *argp++) || (*cp == '-' && cp[1]))
220                    adios (NULL, "missing argument to %s", argp[-2]);
221                file = *cp == '-' ? cp : path (cp, TFILE);
222                continue;
223
224            case OUTFILESW:
225                if (!(cp = *argp++) || (*cp == '-' && cp[1]))
226                    adios (NULL, "missing argument to %s", argp[-2]);
227                outfile = *cp == '-' ? cp : path (cp, TFILE);
228                continue;
229
230            case VERBSW:
231                verbosw = 1;
232                continue;
233            case NVERBSW:
234                verbosw = 0;
235                continue;
236            case DEBUGSW:
237                debugsw = 1;
238                continue;
239            }
240        }
241        if (*cp == '+' || *cp == '@') {
242            if (folder)
243                adios (NULL, "only one folder at a time!");
244            else
245                folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
246        } else {
247            /*
248             * Check if we need to allocate more space
249             * for message names/ranges/sequences.
250             */
251            if (nummsgs >= maxmsgs) {
252                maxmsgs += MAXMSGS;
253                if (!(msgs = (char **) realloc (msgs,
254                        (size_t) (maxmsgs * sizeof(*msgs)))))
255                    adios (NULL, "unable to reallocate msgs storage");
256            }
257            msgs[nummsgs++] = cp;
258        }
259    }
260
261    /* null terminate the list of acceptable parts/types */
262    parts[npart] = NULL;
263    types[ntype] = NULL;
264
265    set_endian ();
266
267    if (outfile == NULL)
268        adios (NULL, "must specify output file");
269
270    /* Check for public cache location */
271    if ((cache_public = context_find (nmhcache)) && *cache_public != '/')
272        cache_public = NULL;
273
274    /* Check for private cache location */
275    if (!(cache_private = context_find (nmhprivcache)))
276        cache_private = ".cache";
277    cache_private = getcpy (m_maildir (cache_private));
278
279    /*
280     * Check for storage directory.  If specified,
281     * then store temporary files there.  Else we
282     * store them in standard nmh directory.
283     */
284    if ((cp = context_find (nmhstorage)) && *cp)
285        tmp = concat (cp, "/", invo_name, NULL);
286    else
287        tmp = add (m_maildir (invo_name), NULL);
288
289    if (!context_find ("path"))
290        free (path ("./", TFOLDER));
291
292    if (file && nummsgs)
293        adios (NULL, "cannot specify msg and file at same time!");
294
295    /*
296     * check if message is coming from file
297     */
298    if (file) {
299        if (!(cts = (CT *) calloc ((size_t) 2, sizeof(*cts))))
300            adios (NULL, "out of memory");
301        ctp = cts;
302
303        if ((ct = parse_mime (file)));
304            *ctp++ = ct;
305    } else {
306        /*
307         * message(s) are coming from a folder
308         */
309        if (!nummsgs)
310            msgs[nummsgs++] = "cur";
311        if (!folder)
312            folder = getfolder (1);
313        maildir = m_maildir (folder);
314
315        if (chdir (maildir) == NOTOK)
316            adios (maildir, "unable to change directory to");
317
318        /* read folder and create message structure */
319        if (!(mp = folder_read (folder)))
320            adios (NULL, "unable to read folder %s", folder);
321
322        /* check for empty folder */
323        if (mp->nummsg == 0)
324            adios (NULL, "no messages in %s", folder);
325
326        /* parse all the message ranges/sequences and set SELECTED */
327        for (msgnum = 0; msgnum < nummsgs; msgnum++)
328            if (!m_convert (mp, msgs[msgnum]))
329                done (1);
330        seq_setprev (mp);       /* set the previous-sequence */
331
332        if (!(cts = (CT *) calloc ((size_t) (mp->numsel + 1), sizeof(*cts))))
333            adios (NULL, "out of memory");
334        ctp = cts;
335
336        for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
337            if (is_selected(mp, msgnum)) {
338                char *msgnam;
339
340                msgnam = m_name (msgnum);
341                if ((ct = parse_mime (msgnam)))
342                    *ctp++ = ct;
343            }
344        }
345    }
346
347    if (!*cts)
348        done (1);
349
350    userrs = 1;
351    SIGNAL (SIGQUIT, quitser);
352    SIGNAL (SIGPIPE, pipeser);
353
354    /*
355     * Get the associated umask for the relevant contents.
356     */
357    for (ctp = cts; *ctp; ctp++) {
358        struct stat st;
359
360        ct = *ctp;
361        if (type_ok (ct, 1) && !ct->c_umask) {
362            if (stat (ct->c_file, &st) != NOTOK)
363                ct->c_umask = ~(st.st_mode & 0777);
364            else
365                ct->c_umask = ~m_gmprot();
366        }
367    }
368
369    /*
370     * Write the content to a file
371     */
372    write_content (cts, outfile);
373
374    /* Now free all the structures for the content */
375    for (ctp = cts; *ctp; ctp++)
376        free_content (*ctp);
377
378    free ((char *) cts);
379    cts = NULL;
380
381    /* If reading from a folder, do some updating */
382    if (mp) {
383        context_replace (pfolder, folder);/* update current folder  */
384        seq_setcur (mp, mp->hghsel);      /* update current message */
385        seq_save (mp);                    /* synchronize sequences  */
386        context_save ();                  /* save the context file  */
387    }
388
389    done (0);
390    /* NOTREACHED */
391}
392
393
394static int
395write_content (CT *cts, char *outfile)
396{
397    CT ct, *ctp;
398
399    for (ctp = cts; *ctp; ctp++) {
400        ct = *ctp;
401        output_message (ct, outfile);
402    }
403
404    flush_errors ();
405    return OK;
406}
407
408
409static RETSIGTYPE
410pipeser (int i)
411{
412    if (i == SIGQUIT) {
413        unlink ("core");
414        fflush (stdout);
415        fprintf (stderr, "\n");
416        fflush (stderr);
417    }
418
419    done (1);
420    /* NOTREACHED */
421}
422
423
424void
425done (int status)
426{
427    CT *ctp;
428
429    if ((ctp = cts))
430        for (; *ctp; ctp++)
431            free_content (*ctp);
432
433    exit (status);
434}
Note: See TracBrowser for help on using the repository browser.