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

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