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