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

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