75bbf86fd667e61c9b0f45702f6baae8e7bb3073
[mmh] / uip / comp.c
1 /*
2 ** comp.c -- compose a message
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/utils.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <locale.h>
14 #include <sysexits.h>
15
16 static struct swit switches[] = {
17 #define EDITRSW  0
18         { "editor editor", 0 },
19 #define FORMSW  1
20         { "form formfile", 0 },
21 #define USESW  2
22         { "use", 0 },
23 #define NUSESW  3
24         { "nouse", 2 },
25 #define WHATSW  4
26         { "whatnowproc program", 0 },
27 #define VERSIONSW  5
28         { "Version", 0 },
29 #define HELPSW  6
30         { "help", 0 },
31         { NULL, 0 }
32 };
33
34 char *version=VERSION;
35
36 int
37 main(int argc, char **argv)
38 {
39         int use = NOUSE;
40         int in, out;
41         char *cp, *cwd, *maildir;
42         char *ed = NULL, *form = NULL;
43         char *folder = NULL, *msg = NULL, buf[BUFSIZ];
44         char drft[BUFSIZ], **argp, **arguments;
45         struct msgs *mp = NULL;
46         char *fmtstr;
47
48         setlocale(LC_ALL, "");
49         invo_name = mhbasename(argv[0]);
50
51         /* read user profile/context */
52         context_read();
53
54         arguments = getarguments(invo_name, argc, argv, 1);
55         argp = arguments;
56
57         while ((cp = *argp++)) {
58                 if (*cp == '-') {
59                         switch (smatch(++cp, switches)) {
60                         case AMBIGSW:
61                                 ambigsw(cp, switches);
62                                 exit(EX_USAGE);
63                         case UNKWNSW:
64                                 adios(EX_USAGE, NULL, "-%s unknown", cp);
65
66                         case HELPSW:
67                                 snprintf(buf, sizeof(buf), "%s [+folder] [msg] [switches]", invo_name);
68                                 print_help(buf, switches, 1);
69                                 exit(argc == 2 ? EX_OK : EX_USAGE);
70                         case VERSIONSW:
71                                 print_version(invo_name);
72                                 exit(argc == 2 ? EX_OK : EX_USAGE);
73
74                         case EDITRSW:
75                                 if (!(ed = *argp++) || *ed == '-') {
76                                         adios(EX_USAGE, NULL, "missing argument to %s", argp[-2]);
77                                 }
78                                 continue;
79
80                         case WHATSW:
81                                 if (!(whatnowproc = *argp++) || *whatnowproc == '-') {
82                                         adios(EX_USAGE, NULL, "missing argument to %s", argp[-2]);
83                                 }
84                                 continue;
85
86                         case FORMSW:
87                                 if (!(form = *argp++) || *form == '-') {
88                                         adios(EX_USAGE, NULL, "missing argument to %s", argp[-2]);
89                                 }
90                                 continue;
91
92                         case USESW:
93                                 use++;
94                                 continue;
95                         case NUSESW:
96                                 use = NOUSE;
97                                 continue;
98                         }
99                 }
100                 if (*cp == '+' || *cp == '@') {
101                         if (folder) {
102                                 adios(EX_USAGE, NULL, "only one folder at a time!");
103                         } else {
104                                 folder = mh_xstrdup(expandfol(cp));
105                         }
106                 } else {
107                         if (msg) {
108                                 adios(EX_USAGE, NULL, "only one message at a time!");
109                         } else {
110                                 msg = cp;
111                         }
112                 }
113         }
114
115         cwd = mh_xstrdup(pwd());
116
117         if (form && (folder || msg)) {
118                 adios(EX_USAGE, NULL, "can't mix forms and folders/msgs");
119         }
120
121         if (use && folder) {
122                 adios(EX_USAGE, NULL, "can't mix -use and +folder");
123         }
124
125         if (use) {
126                 /* Don't copy; the draft shall get removed in the end. */
127                 strncpy(drft, m_draft(msg ? msg : seq_cur), sizeof(drft));
128
129         } else if (folder || msg) {
130                 /* Take a message as the "form" for the new message. */
131                 if (!msg)
132                         msg = seq_cur;
133                 if (!folder)
134                         folder = getcurfol();
135                 maildir = toabsdir(folder);
136                 if (chdir(maildir) == NOTOK) {
137                         adios(EX_OSERR, maildir, "unable to change directory to");
138                 }
139                 /* read folder and create message structure */
140                 if (!(mp = folder_read(folder))) {
141                         adios(EX_IOERR, NULL, "unable to read folder %s", folder);
142                 }
143                 /* check for empty folder */
144                 if (mp->nummsg == 0) {
145                         adios(EX_DATAERR, NULL, "no messages in %s", folder);
146                 }
147                 /* parse the message range/sequence/name and set SELECTED */
148                 if (!m_convert(mp, msg)) {
149                         exit(EX_SOFTWARE);
150                 }
151                 seq_setprev(mp);  /* set the previous-sequence */
152                 if (mp->numsel > 1) {
153                         adios(EX_USAGE, NULL, "only one message at a time!");
154                 }
155                 if ((in = open(form = mh_xstrdup(m_name(mp->lowsel)),
156                                 O_RDONLY)) == NOTOK) {
157                         adios(EX_IOERR, form, "unable to open message");
158                 }
159
160                 strncpy(drft, m_draft(seq_beyond), sizeof(drft));
161                 if ((out = creat(drft, m_gmprot())) == NOTOK) {
162                         adios(EX_CANTCREAT, drft, "unable to create");
163                 }
164                 cpydata(in, out, form, drft);
165                 close(in);
166                 close(out);
167
168         } else {
169                 fmtstr = new_fs(form, components);
170                 strncpy(drft, m_draft(seq_beyond), sizeof(drft));
171                 if ((out = creat(drft, m_gmprot())) == NOTOK) {
172                 adios(EX_CANTCREAT, drft, "unable to create");
173                 }
174                 if (write(out, fmtstr, strlen(fmtstr)) != (int)strlen(fmtstr)) {
175                         adios(EX_IOERR, drft, "error writing");
176                 }
177                 close(out);
178         }
179
180         context_save();
181         what_now(ed, use, drft, NULL, 0, NULLMP, NULL, cwd);
182         return EX_OSERR;
183 }