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