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

Revision 12455, 9.4 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 * refile.c -- move or link message(s) from a source folder
4 *          -- into one or more destination folders
5 *
6 * $Id: refile.c,v 1.1.1.1 1999-02-07 18:14:16 danw Exp $
7 */
8
9#include <h/mh.h>
10#include <fcntl.h>
11#include <errno.h>
12
13/*
14 * We allocate spaces for messages (msgs array)
15 * this number of elements at a time.
16 */
17#define MAXMSGS  256
18
19
20static struct swit switches[] = {
21#define DRAFTSW          0
22    { "draft", 0 },
23#define LINKSW           1
24    { "link", 0 },
25#define NLINKSW          2
26    { "nolink", 0 },
27#define PRESSW           3
28    { "preserve", 0 },
29#define NPRESSW          4
30    { "nopreserve", 0 },
31#define UNLINKSW         5
32    { "unlink", 0 },
33#define NUNLINKSW        6
34    { "nounlink", 0 },
35#define SRCSW            7
36    { "src +folder", 0 },
37#define FILESW           8
38    { "file file", 0 },
39#define RPROCSW          9
40    { "rmmproc program", 0 },
41#define NRPRCSW         10
42    { "normmproc", 0 },
43#define VERSIONSW       11
44    { "version", 0 },
45#define HELPSW          12
46    { "help", 4 },
47    { NULL, 0 }
48};
49
50extern int errno;
51
52static char maildir[BUFSIZ];
53
54struct st_fold {
55    char *f_name;
56    struct msgs *f_mp;
57};
58
59/*
60 * static prototypes
61 */
62static void opnfolds (struct st_fold *, int);
63static void clsfolds (struct st_fold *, int);
64static void remove_files (int, char **);
65static int m_file (char *, struct st_fold *, int, int);
66
67
68int
69main (int argc, char **argv)
70{
71    int linkf = 0, preserve = 0, filep = 0;
72    int foldp = 0, isdf = 0, unlink_msgs = 0;
73    int i, msgnum, nummsgs, maxmsgs;
74    char *cp, *folder = NULL, buf[BUFSIZ];
75    char **argp, **arguments, **msgs;
76    char *filevec[NFOLDERS + 2];
77    char **files = &filevec[1];    /* leave room for remove_files:vec[0] */
78    struct st_fold folders[NFOLDERS + 1];
79    struct msgs *mp;
80
81#ifdef LOCALE
82    setlocale(LC_ALL, "");
83#endif
84    invo_name = r1bindex (argv[0], '/');
85
86    /* read user profile/context */
87    context_read();
88
89    arguments = getarguments (invo_name, argc, argv, 1);
90    argp = arguments;
91
92    /*
93     * Allocate the initial space to record message
94     * names, ranges, and sequences.
95     */
96    nummsgs = 0;
97    maxmsgs = MAXMSGS;
98    if (!(msgs = (char **) malloc ((size_t) (maxmsgs * sizeof(*msgs)))))
99        adios (NULL, "unable to allocate storage");
100
101    /*
102     * Parse arguments
103     */
104    while ((cp = *argp++)) {
105        if (*cp == '-') {
106            switch (smatch (++cp, switches)) {
107            case AMBIGSW:
108                ambigsw (cp, switches);
109                done (1);
110            case UNKWNSW:
111                adios (NULL, "-%s unknown\n", cp);
112
113            case HELPSW:
114                snprintf (buf, sizeof(buf), "%s [msgs] [switches] +folder ...",
115                          invo_name);
116                print_help (buf, switches, 1);
117                done (1);
118            case VERSIONSW:
119                print_version(invo_name);
120                done (1);
121
122            case LINKSW:
123                linkf++;
124                continue;
125            case NLINKSW:
126                linkf = 0;
127                continue;
128
129            case PRESSW:
130                preserve++;
131                continue;
132            case NPRESSW:
133                preserve = 0;
134                continue;
135
136            case UNLINKSW:
137                unlink_msgs++;
138                continue;
139            case NUNLINKSW:
140                unlink_msgs = 0;
141                continue;
142
143            case SRCSW:
144                if (folder)
145                    adios (NULL, "only one source folder at a time!");
146                if (!(cp = *argp++) || *cp == '-')
147                    adios (NULL, "missing argument to %s", argp[-2]);
148                folder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
149                               *cp != '@' ? TFOLDER : TSUBCWF);
150                continue;
151            case DRAFTSW:
152                if (filep > NFOLDERS)
153                    adios (NULL, "only %d files allowed!", NFOLDERS);
154                isdf = 0;
155                files[filep++] = getcpy (m_draft (NULL, NULL, 1, &isdf));
156                continue;
157            case FILESW:
158                if (filep > NFOLDERS)
159                    adios (NULL, "only %d files allowed!", NFOLDERS);
160                if (!(cp = *argp++) || *cp == '-')
161                    adios (NULL, "missing argument to %s", argp[-2]);
162                files[filep++] = path (cp, TFILE);
163                continue;
164
165            case RPROCSW:
166                if (!(rmmproc = *argp++) || *rmmproc == '-')
167                    adios (NULL, "missing argument to %s", argp[-2]);
168                continue;
169            case NRPRCSW:
170                rmmproc = NULL;
171                continue;
172            }
173        }
174        if (*cp == '+' || *cp == '@') {
175            if (foldp > NFOLDERS)
176                adios (NULL, "only %d folders allowed!", NFOLDERS);
177            folders[foldp++].f_name =
178                path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
179        } else {
180            /*
181             * Check if we need to allocate more space
182             * for message names, ranges, and sequences.
183             */
184            if (nummsgs >= maxmsgs) {
185                maxmsgs += MAXMSGS;
186                if (!(msgs = (char **) realloc (msgs,
187                                                (size_t) (maxmsgs * sizeof(*msgs)))))
188                    adios (NULL, "unable to reallocate msgs storage");
189            }
190            msgs[nummsgs++] = cp;
191        }
192    }
193
194    if (!context_find ("path"))
195        free (path ("./", TFOLDER));
196    if (foldp == 0)
197        adios (NULL, "no folder specified");
198
199#ifdef WHATNOW
200    if (!nummsgs && !foldp && !filep && (cp = getenv ("mhdraft")) && *cp)
201        files[filep++] = cp;
202#endif /* WHATNOW */
203
204    /*
205     * We are refiling a file to the folders
206     */
207    if (filep > 0) {
208        if (folder || nummsgs)
209            adios (NULL, "use -file or some messages, not both");
210        opnfolds (folders, foldp);
211        for (i = 0; i < filep; i++)
212            if (m_file (files[i], folders, foldp, preserve))
213                done (1);
214        /* If -nolink, then "remove" files */
215        if (!linkf)
216            remove_files (filep, filevec);
217        done (0);
218    }
219
220    if (!nummsgs)
221        msgs[nummsgs++] = "cur";
222    if (!folder)
223        folder = getfolder (1);
224    strncpy (maildir, m_maildir (folder), sizeof(maildir));
225
226    if (chdir (maildir) == NOTOK)
227        adios (maildir, "unable to change directory to");
228
229    /* read source folder and create message structure */
230    if (!(mp = folder_read (folder)))
231        adios (NULL, "unable to read folder %s", folder);
232
233    /* check for empty folder */
234    if (mp->nummsg == 0)
235        adios (NULL, "no messages in %s", folder);
236
237    /* parse the message range/sequence/name and set SELECTED */
238    for (msgnum = 0; msgnum < nummsgs; msgnum++)
239        if (!m_convert (mp, msgs[msgnum]))
240            done (1);
241    seq_setprev (mp);   /* set the previous-sequence */
242
243    /* create folder structures for each destination folder */
244    opnfolds (folders, foldp);
245
246    /* Link all the selected messages into destination folders */
247    for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
248        if (is_selected (mp, msgnum)) {
249            cp = getcpy (m_name (msgnum));
250            if (m_file (cp, folders, foldp, preserve))
251                done (1);
252            free (cp);
253        }
254    }
255
256    /*
257     * This is a hack.  If we are using an external rmmproc,
258     * then save the current folder to the context file,
259     * so the external rmmproc will remove files from the correct
260     * directory.  This should be moved to folder_delmsgs().
261     */
262    if (rmmproc) {
263        context_replace (pfolder, folder);
264        context_save ();
265        fflush (stdout);
266    }
267
268    /* If -nolink, then "remove" messages from source folder */
269    if (!linkf) {
270        folder_delmsgs (mp, unlink_msgs);
271    }
272
273    clsfolds (folders, foldp);
274
275    if (mp->hghsel != mp->curmsg
276        && (mp->numsel != mp->nummsg || linkf))
277        seq_setcur (mp, mp->hghsel);
278    seq_save (mp);      /* synchronize message sequences */
279
280    context_replace (pfolder, folder);  /* update current folder   */
281    context_save ();                    /* save the context file   */
282    folder_free (mp);                   /* free folder structure   */
283    done (0);
284}
285
286
287/*
288 * Read all the destination folders and
289 * create folder structures for all of them.
290 */
291
292static void
293opnfolds (struct st_fold *folders, int nfolders)
294{
295    register char *cp;
296    char nmaildir[BUFSIZ];
297    register struct st_fold *fp, *ep;
298    register struct msgs *mp;
299    struct stat st;
300
301    for (fp = folders, ep = folders + nfolders; fp < ep; fp++) {
302        chdir (m_maildir (""));
303        strncpy (nmaildir, m_maildir (fp->f_name), sizeof(nmaildir));
304
305        if (stat (nmaildir, &st) == NOTOK) {
306            if (errno != ENOENT)
307                adios (nmaildir, "error on folder");
308            cp = concat ("Create folder \"", nmaildir, "\"? ", NULL);
309            if (!getanswer (cp))
310                done (1);
311            free (cp);
312            if (!makedir (nmaildir))
313                adios (NULL, "unable to create folder %s", nmaildir);
314        }
315
316        if (chdir (nmaildir) == NOTOK)
317            adios (nmaildir, "unable to change directory to");
318        if (!(mp = folder_read (fp->f_name)))
319            adios (NULL, "unable to read folder %s", fp->f_name);
320        mp->curmsg = 0;
321
322        fp->f_mp = mp;
323
324        chdir (maildir);
325    }
326}
327
328
329/*
330 * Set the Previous-Sequence and then sychronize the
331 * sequence file, for each destination folder.
332 */
333
334static void
335clsfolds (struct st_fold *folders, int nfolders)
336{
337    register struct st_fold *fp, *ep;
338    register struct msgs *mp;
339
340    for (fp = folders, ep = folders + nfolders; fp < ep; fp++) {
341        mp = fp->f_mp;
342        seq_setprev (mp);
343        seq_save (mp);
344    }
345}
346
347
348/*
349 * If you have a "rmmproc" defined, we called that
350 * to remove all the specified files.  If "rmmproc"
351 * is not defined, then just unlink the files.
352 */
353
354static void
355remove_files (int filep, char **files)
356{
357    int i;
358    char **vec;
359
360    /* If rmmproc is defined, we use that */
361    if (rmmproc) {
362        vec = files++;          /* vec[0] = filevec[0] */
363        files[filep] = NULL;    /* NULL terminate list */
364
365        fflush (stdout);
366        vec[0] = r1bindex (rmmproc, '/');
367        execvp (rmmproc, vec);
368        adios (rmmproc, "unable to exec");
369    }
370
371    /* Else just unlink the files */
372    files++;    /* advance past filevec[0] */
373    for (i = 0; i < filep; i++) {
374        if (unlink (files[i]) == NOTOK)
375            admonish (files[i], "unable to unlink");
376    }
377}
378
379
380/*
381 * Link (or copy) the message into each of
382 * the destination folders.
383 */
384
385static int
386m_file (char *msgfile, struct st_fold *folders, int nfolders, int preserve)
387{
388    int msgnum;
389    struct st_fold *fp, *ep;
390
391    for (fp = folders, ep = folders + nfolders; fp < ep; fp++) {
392        if ((msgnum = folder_addmsg (&fp->f_mp, msgfile, 1, 0, preserve)) == -1)
393            return 1;
394    }
395    return 0;
396}
Note: See TracBrowser for help on using the repository browser.