* docs/MAIL.FILTERING: added note on removing procmail -f or
[mmh] / uip / dist.c
1
2 /*
3  * dist.c -- re-distribute a message
4  *
5  * $Id$
6  *
7  * This code is Copyright (c) 2002, by the authors of nmh.  See the
8  * COPYRIGHT file in the root directory of the nmh distribution for
9  * complete copyright information.
10  */
11
12 #include <h/mh.h>
13 #include <h/utils.h>
14 #include <fcntl.h>
15
16 static struct swit switches[] = {
17 #define ANNOSW  0
18     { "annotate", 0 },
19 #define NANNOSW 1
20     { "noannotate", 0 },
21 #define DFOLDSW 2
22     { "draftfolder +folder", 0 },
23 #define DMSGSW  3
24     { "draftmessage msg", 0 },
25 #define NDFLDSW 4
26     { "nodraftfolder", 0 },
27 #define EDITRSW 5
28     { "editor editor", 0 },
29 #define NEDITSW 6
30     { "noedit", 0 },
31 #define FORMSW  7
32     { "form formfile", 0 },
33 #define INPLSW  8
34     { "inplace", 0 },
35 #define NINPLSW 9
36     { "noinplace", 0 },
37 #define WHATSW  10
38     { "whatnowproc program", 0 },
39 #define NWHATSW 11
40     { "nowhatnowproc", 0 },
41 #define VERSIONSW 12
42     { "version", 0 },
43 #define HELPSW  13
44     { "help", 0 },
45 #define FILESW  14
46     { "file file", -4 },        /* interface from msh */
47     { NULL, 0 }
48 };
49
50 static struct swit aqrnl[] = {
51 #define NOSW    0
52     { "quit", 0 },
53 #define YESW    1
54     { "replace", 0 },
55 #define LISTDSW 2
56     { "list", 0 },
57 #define REFILSW 3
58     { "refile +folder", 0 },
59 #define NEWSW   4
60     { "new", 0 },
61     { NULL, 0 }
62 };
63
64
65 static struct swit aqrl[] = {
66     { "quit", 0 },
67     { "replace", 0 },
68     { "list", 0 },
69     { "refile +folder", 0 },
70     { NULL, 0 }
71 };
72
73
74 int
75 main (int argc, char **argv)
76 {
77     int anot = 0, inplace = 1, nedit = 0;
78     int nwhat = 0, i, in, isdf = 0, out;
79     char *cp, *cwd, *maildir, *msgnam, *dfolder = NULL;
80     char *dmsg = NULL, *ed = NULL, *file = NULL, *folder = NULL;
81     char *form = NULL, *msg = NULL, buf[BUFSIZ], drft[BUFSIZ];
82     char **argp, **arguments;
83     struct msgs *mp = NULL;
84     struct stat st;
85
86 #ifdef LOCALE
87     setlocale(LC_ALL, "");
88 #endif
89     invo_name = r1bindex (argv[0], '/');
90
91     /* read user profile/context */
92     context_read();
93
94     arguments = getarguments (invo_name, argc, argv, 1);
95     argp = arguments;
96
97     while ((cp = *argp++)) {
98         if (*cp == '-') {
99             switch (smatch (++cp, switches)) {
100                 case AMBIGSW: 
101                     ambigsw (cp, switches);
102                     done (1);
103                 case UNKWNSW: 
104                     adios (NULL, "-%s unknown", cp);
105
106                 case HELPSW: 
107                     snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]",
108                         invo_name);
109                     print_help (buf, switches, 1);
110                     done (1);
111                 case VERSIONSW:
112                     print_version(invo_name);
113                     done (1);
114
115                 case ANNOSW: 
116                     anot++;
117                     continue;
118                 case NANNOSW: 
119                     anot = 0;
120                     continue;
121
122                 case EDITRSW: 
123                     if (!(ed = *argp++) || *ed == '-')
124                         adios (NULL, "missing argument to %s", argp[-2]);
125                     nedit = 0;
126                     continue;
127                 case NEDITSW:
128                     nedit++;
129                     continue;
130                     
131                 case WHATSW: 
132                     if (!(whatnowproc = *argp++) || *whatnowproc == '-')
133                         adios (NULL, "missing argument to %s", argp[-2]);
134                     nwhat = 0;
135                     continue;
136                 case NWHATSW: 
137                     nwhat++;
138                     continue;
139
140                 case FILESW: 
141                     if (file)
142                         adios (NULL, "only one file at a time!");
143                     if (!(cp = *argp++) || *cp == '-')
144                         adios (NULL, "missing argument to %s", argp[-2]);
145                     file = path (cp, TFILE);
146                     continue;
147                 case FORMSW: 
148                     if (!(form = *argp++) || *form == '-')
149                         adios (NULL, "missing argument to %s", argp[-2]);
150                     continue;
151
152                 case INPLSW: 
153                     inplace++;
154                     continue;
155                 case NINPLSW: 
156                     inplace = 0;
157                     continue;
158
159                 case DFOLDSW: 
160                     if (dfolder)
161                         adios (NULL, "only one draft folder at a time!");
162                     if (!(cp = *argp++) || *cp == '-')
163                         adios (NULL, "missing argument to %s", argp[-2]);
164                     dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
165                             *cp != '@' ? TFOLDER : TSUBCWF);
166                     continue;
167                 case DMSGSW: 
168                     if (dmsg)
169                         adios (NULL, "only one draft message at a time!");
170                     if (!(dmsg = *argp++) || *dmsg == '-')
171                         adios (NULL, "missing argument to %s", argp[-2]);
172                     continue;
173                 case NDFLDSW: 
174                     dfolder = NULL;
175                     isdf = NOTOK;
176                     continue;
177             }
178         }
179         if (*cp == '+' || *cp == '@') {
180             if (folder)
181                 adios (NULL, "only one folder at a time!");
182             else
183                 folder = pluspath (cp);
184         } else {
185             if (msg)
186                 adios (NULL, "only one message at a time!");
187             else
188                 msg = cp;
189         }
190     }
191
192     cwd = getcpy (pwd ());
193
194     if (!context_find ("path"))
195         free (path ("./", TFOLDER));
196     if (file && (msg || folder))
197         adios (NULL, "can't mix files and folders/msgs");
198
199     in = open_form(&form, distcomps);
200
201 try_it_again:
202     strncpy (drft, m_draft (dfolder, dmsg, NOUSE, &isdf), sizeof(drft));
203
204     /* Check if draft already exists */
205     if (stat (drft, &st) != NOTOK) {
206         printf ("Draft \"%s\" exists (%ld bytes).", drft, (long) st.st_size);
207         for (i = LISTDSW; i != YESW;) {
208             if (!(argp = getans ("\nDisposition? ", isdf ? aqrnl : aqrl)))
209                 done (1);
210             switch (i = smatch (*argp, isdf ? aqrnl : aqrl)) {
211                 case NOSW: 
212                     done (0);
213                 case NEWSW: 
214                     dmsg = NULL;
215                     goto try_it_again;
216                 case YESW: 
217                     break;
218                 case LISTDSW: 
219                     showfile (++argp, drft);
220                     break;
221                 case REFILSW: 
222                     if (refile (++argp, drft) == 0)
223                         i = YESW;
224                     break;
225                 default: 
226                     advise (NULL, "say what?");
227                     break;
228             }
229         }
230     }
231     if ((out = creat (drft, m_gmprot ())) == NOTOK)
232         adios (drft, "unable to create");
233
234     cpydata (in, out, form, drft);
235     close (in);
236     close (out);
237
238     if (file) {
239         /*
240          * Dist a file
241          */
242         anot = 0;       /* don't want to annotate a file */
243     } else {
244         /*
245          * Dist a message
246          */
247         if (!msg)
248             msg = "cur";
249         if (!folder)
250             folder = getfolder (1);
251         maildir = m_maildir (folder);
252
253         if (chdir (maildir) == NOTOK)
254             adios (maildir, "unable to change directory to");
255
256         /* read folder and create message structure */
257         if (!(mp = folder_read (folder)))
258             adios (NULL, "unable to read folder %s", folder);
259
260         /* check for empty folder */
261         if (mp->nummsg == 0)
262             adios (NULL, "no messages in %s", folder);
263
264         /* parse the message range/sequence/name and set SELECTED */
265         if (!m_convert (mp, msg))
266             done (1);
267         seq_setprev (mp);       /* set the previous-sequence */
268
269         if (mp->numsel > 1)
270             adios (NULL, "only one message at a time!");
271     }
272
273     msgnam = file ? file : getcpy (m_name (mp->lowsel));
274     if ((in = open (msgnam, O_RDONLY)) == NOTOK)
275         adios (msgnam, "unable to open message");
276
277     if (!file) {
278         context_replace (pfolder, folder);/* update current folder  */
279         seq_setcur (mp, mp->lowsel);      /* update current message */
280         seq_save (mp);                    /* synchronize sequences  */
281         context_save ();                  /* save the context file  */
282     }
283
284     if (nwhat)
285         done (0);
286     what_now (ed, nedit, NOUSE, drft, msgnam, 1, mp,
287         anot ? "Resent" : NULL, inplace, cwd);
288     done (1);
289     return 1;
290 }