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