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