Added -nocontentid (and -contentid, for symmetry) switch to mhbuild. This allows...
[mmh] / uip / rcvstore.c
1
2 /*
3  * rcvstore.c -- asynchronously add mail to a folder
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 #include <h/signals.h>
15 #include <errno.h>
16 #include <signal.h>
17 #include <h/mts.h>
18
19 static struct swit switches[] = {
20 #define CRETSW         0
21     { "create", 0 },
22 #define NCRETSW        1
23     { "nocreate", 0 },
24 #define UNSEENSW       2
25     { "unseen", 0 },
26 #define NUNSEENSW      3
27     { "nounseen", 0 },
28 #define PUBSW          4
29     { "public", 0 },
30 #define NPUBSW         5
31     { "nopublic",  0 },
32 #define ZEROSW         6
33     { "zero",   0 },
34 #define NZEROSW        7
35     { "nozero", 0 },
36 #define SEQSW          8
37     { "sequence name", 0 },
38 #define VERSIONSW      9
39     { "version", 0 },
40 #define HELPSW        10
41     { "help", 0 },
42     { NULL, 0 }
43 };
44
45
46 /*
47  * name of temporary file to store incoming message
48  */
49 static char *tmpfilenam = NULL;
50
51
52 int
53 main (int argc, char **argv)
54 {
55     int publicsw = -1, zerosw = 0;
56     int create = 1, unseensw = 1;
57     int fd, msgnum, seqp = 0;
58     char *cp, *maildir, *folder = NULL, buf[BUFSIZ];
59     char **argp, **arguments, *seqs[NUMATTRS+1];
60     struct msgs *mp;
61     struct stat st;
62
63 #ifdef LOCALE
64     setlocale(LC_ALL, "");
65 #endif
66     invo_name = r1bindex (argv[0], '/');
67
68     /* read user profile/context */
69     context_read();
70
71     mts_init (invo_name);
72     arguments = getarguments (invo_name, argc, argv, 1);
73     argp = arguments;
74
75     /* parse arguments */
76     while ((cp = *argp++)) {
77         if (*cp == '-') {
78             switch (smatch (++cp, switches)) {
79             case AMBIGSW: 
80                 ambigsw (cp, switches);
81                 done (1);
82             case UNKWNSW: 
83                 adios (NULL, "-%s unknown", cp);
84
85             case HELPSW: 
86                 snprintf (buf, sizeof(buf), "%s [+folder] [switches]",
87                           invo_name);
88                 print_help (buf, switches, 1);
89                 done (1);
90             case VERSIONSW:
91                 print_version(invo_name);
92                 done (1);
93
94             case SEQSW: 
95                 if (!(cp = *argp++) || *cp == '-')
96                     adios (NULL, "missing argument name to %s", argp[-2]);
97
98                 /* check if too many sequences specified */
99                 if (seqp >= NUMATTRS)
100                     adios (NULL, "too many sequences (more than %d) specified", NUMATTRS);
101                 seqs[seqp++] = cp;
102                 continue;
103
104             case UNSEENSW:
105                 unseensw = 1;
106                 continue;
107             case NUNSEENSW:
108                 unseensw = 0;
109                 continue;
110
111             case PUBSW: 
112                 publicsw = 1;
113                 continue;
114             case NPUBSW: 
115                 publicsw = 0;
116                 continue;
117
118             case ZEROSW: 
119                 zerosw++;
120                 continue;
121             case NZEROSW: 
122                 zerosw = 0;
123                 continue;
124
125             case CRETSW: 
126                 create++;
127                 continue;
128             case NCRETSW: 
129                 create = 0;
130                 continue;
131             }
132         }
133         if (*cp == '+' || *cp == '@') {
134             if (folder)
135                 adios (NULL, "only one folder at a time!");
136             else
137                 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
138         } else {
139             adios (NULL, "usage: %s [+folder] [switches]", invo_name);
140         }
141     }
142
143     seqs[seqp] = NULL;  /* NULL terminate list of sequences */
144
145     if (!context_find ("path"))
146         free (path ("./", TFOLDER));
147
148     /* if no folder is given, use default folder */
149     if (!folder)
150         folder = getfolder (0);
151     maildir = m_maildir (folder);
152
153     /* check if folder exists */
154     if (stat (maildir, &st) == NOTOK) {
155         if (errno != ENOENT)
156             adios (maildir, "error on folder");
157         if (!create)
158             adios (NULL, "folder %s doesn't exist", maildir);
159         if (!makedir (maildir))
160             adios (NULL, "unable to create folder %s", maildir);
161     }
162
163     if (chdir (maildir) == NOTOK)
164         adios (maildir, "unable to change directory to");
165
166     /* ignore a few signals */
167     SIGNAL (SIGHUP, SIG_IGN);
168     SIGNAL (SIGINT, SIG_IGN);
169     SIGNAL (SIGQUIT, SIG_IGN);
170     SIGNAL (SIGTERM, SIG_IGN);
171
172     /* create a temporary file */
173     tmpfilenam = m_scratch ("", invo_name);
174     if ((fd = creat (tmpfilenam, m_gmprot ())) == NOTOK)
175         adios (tmpfilenam, "unable to create");
176     chmod (tmpfilenam, m_gmprot());
177
178     /* copy the message from stdin into temp file */
179     cpydata (fileno (stdin), fd, "standard input", tmpfilenam);
180
181     if (fstat (fd, &st) == NOTOK) {
182         unlink (tmpfilenam);
183         adios (tmpfilenam, "unable to fstat");
184     }
185     if (close (fd) == NOTOK)
186         adios (tmpfilenam, "error closing");
187
188     /* don't add file if it is empty */
189     if (st.st_size == 0) {
190         unlink (tmpfilenam);
191         advise (NULL, "empty file");
192         done (0);
193     }
194
195     /*
196      * read folder and create message structure
197      */
198     if (!(mp = folder_read (folder)))
199         adios (NULL, "unable to read folder %s", folder);
200
201     /*
202      * Link message into folder, and possibly add
203      * to the Unseen-Sequence's.
204      */
205     if ((msgnum = folder_addmsg (&mp, tmpfilenam, 0, unseensw, 0, 0, (char *)0)) == -1)
206         done (1);
207
208     /*
209      * Add the message to any extra sequences
210      * that have been specified.
211      */
212     for (seqp = 0; seqs[seqp]; seqp++) {
213         if (!seq_addmsg (mp, seqs[seqp], msgnum, publicsw, zerosw))
214             done (1);
215     }
216
217     seq_setunseen (mp, 0);      /* synchronize any Unseen-Sequence's      */
218     seq_save (mp);              /* synchronize and save message sequences */
219     folder_free (mp);           /* free folder/message structure          */
220
221     context_save ();            /* save the global context file           */
222     unlink (tmpfilenam);        /* remove temporary file                  */
223     tmpfilenam = NULL;
224
225     return done (0);
226 }
227
228 /*
229  * Clean up and exit
230  */
231 int
232 done(int status)
233 {
234     if (tmpfilenam && *tmpfilenam)
235         unlink (tmpfilenam);
236     exit (status);
237     return 1;  /* dead code to satisfy the compiler */
238 }