Commit 966f07cc 966f07ccacdc8b1d13b87e28b1032192ac729fa4 by Sergey Poznyakoff

Initial implementation of a `prog' mailer.

* configure.ac: Enable/disable prog mailer support.
* include/mailutils/progmailer.h: New file.
* include/mailutils/Makefile.am (pkginclude_HEADERS): Add
progmailer.h
* include/mailutils/mailutils.h: Include progmailer.h
* include/mailutils/registrar.h (MU_PROG_PRIO): New define.
(mu_prog_record): New extern.
(mu_register_all_mailer_formats): Register mu_prog_record.
* include/mailutils/types.hin (mu_progmailer_t): New typedef.
* libproto/include/registrar0.h (MU_PROG_SCHEME)
(MU_PROG_SCHEME_LEN): New defines.
* libproto/mailer/prog.c: New file.
* libproto/mailer/Makefile.am (libmu_mailer_la_SOURCES): Add
prog.c
* libproto/mailer/sendmail.c: Rewrite using mu_progmailer_t
* libproto/remote/folder.c (_remote_is_scheme): Remove unused
variable.
* mailbox/progmailer.c: New file
* mailbox/Makefile.am (libmailutils_la_SOURCES): Add progmailer.c

* mailbox/acl.c (_expand_aclno): Add a fixme.
* mail/send.c (msg_to_pipe): Bugfix: use pclose, instead of fclose.
* examples/config/mailutils.schema: Update.
1 parent 5d3f1ff9
1 2008-10-25 Sergey Poznyakoff <gray@gnu.org.ua>
2
3 Initial implementation of a `prog' mailer.
4
5 * configure.ac: Enable/disable prog mailer support.
6 * include/mailutils/progmailer.h: New file.
7 * include/mailutils/Makefile.am (pkginclude_HEADERS): Add
8 progmailer.h
9 * include/mailutils/mailutils.h: Include progmailer.h
10 * include/mailutils/registrar.h (MU_PROG_PRIO): New define.
11 (mu_prog_record): New extern.
12 (mu_register_all_mailer_formats): Register mu_prog_record.
13 * include/mailutils/types.hin (mu_progmailer_t): New typedef.
14 * libproto/include/registrar0.h (MU_PROG_SCHEME)
15 (MU_PROG_SCHEME_LEN): New defines.
16 * libproto/mailer/prog.c: New file.
17 * libproto/mailer/Makefile.am (libmu_mailer_la_SOURCES): Add
18 prog.c
19 * libproto/mailer/sendmail.c: Rewrite using mu_progmailer_t
20 * libproto/remote/folder.c (_remote_is_scheme): Remove unused
21 variable.
22 * mailbox/progmailer.c: New file
23 * mailbox/Makefile.am (libmailutils_la_SOURCES): Add progmailer.c
24
25 * mailbox/acl.c (_expand_aclno): Add a fixme.
26 * mail/send.c (msg_to_pipe): Bugfix: use pclose, instead of fclose.
27 * examples/config/mailutils.schema: Update.
28
1 2008-10-24 Sergey Poznyakoff <gray@gnu.org.ua> 29 2008-10-24 Sergey Poznyakoff <gray@gnu.org.ua>
2 30
3 * examples/config/mailutils.dict: Use GNU OID number. 31 * examples/config/mailutils.dict: Use GNU OID number.
......
...@@ -767,10 +767,13 @@ MU_ENABLE_SUPPORT(nntp) ...@@ -767,10 +767,13 @@ MU_ENABLE_SUPPORT(nntp)
767 767
768 AC_SUBST(BUILD_SMTP_PROGRAMS) 768 AC_SUBST(BUILD_SMTP_PROGRAMS)
769 AC_SUBST(RUN_SMTP_DEJATOOL) 769 AC_SUBST(RUN_SMTP_DEJATOOL)
770
770 MU_ENABLE_SUPPORT(smtp, [BUILD_SMTP_PROGRAMS='$(PROGRAMS_SMTP)' 771 MU_ENABLE_SUPPORT(smtp, [BUILD_SMTP_PROGRAMS='$(PROGRAMS_SMTP)'
771 RUN_SMTP_DEJATOOL='$(SMTP_DEJATOOL)']) 772 RUN_SMTP_DEJATOOL='$(SMTP_DEJATOOL)'])
772 MU_ENABLE_SUPPORT(sendmail) 773 MU_ENABLE_SUPPORT(sendmail)
773 774
775 MU_ENABLE_SUPPORT(prog)
776
774 AC_SUBST(BUILD_MH_PROGRAMS) 777 AC_SUBST(BUILD_MH_PROGRAMS)
775 AC_SUBST(BUILD_MH_LIBRARIES) 778 AC_SUBST(BUILD_MH_LIBRARIES)
776 AC_SUBST(BUILD_MH_EXEC_HOOK) 779 AC_SUBST(BUILD_MH_EXEC_HOOK)
......
1 # This file is part of GNU Mailutils -- a suite of utilities for electronic 1 # This file is part of GNU Mailutils -- a suite of utilities for electronic
2 # mail 2 # mail
3 # Copyright (C) 2008 Free Software Foundation, Inc. 3 # Copyright (C) 2007, 2008 Free Software Foundation, Inc.
4 # 4 #
5 # GNU Mailutils is free software; you can redistribute it and/or 5 # GNU Mailutils is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License as 6 # modify it under the terms of the GNU General Public License as
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 # GNU General Public License for more details. 13 # GNU General Public License for more details.
14 # 14 #
15 # You should have received a copy of the GNU General Public License 15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>. 16 # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
17 17
18 # Mailutuls LDAP schema items 18 # Mailutuls LDAP schema items
19 # 19 #
......
...@@ -78,6 +78,7 @@ pkginclude_HEADERS = \ ...@@ -78,6 +78,7 @@ pkginclude_HEADERS = \
78 pam.h\ 78 pam.h\
79 parse822.h\ 79 parse822.h\
80 pop3.h\ 80 pop3.h\
81 progmailer.h\
81 property.h\ 82 property.h\
82 radius.h\ 83 radius.h\
83 refcount.h\ 84 refcount.h\
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
50 #include <mailutils/opool.h> 50 #include <mailutils/opool.h>
51 #include <mailutils/parse822.h> 51 #include <mailutils/parse822.h>
52 #include <mailutils/pop3.h> 52 #include <mailutils/pop3.h>
53 #include <mailutils/progmailer.h>
53 #include <mailutils/property.h> 54 #include <mailutils/property.h>
54 #include <mailutils/refcount.h> 55 #include <mailutils/refcount.h>
55 #include <mailutils/registrar.h> 56 #include <mailutils/registrar.h>
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2008 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library; if not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301 USA */
18
19 #ifndef _MAILUTILS_PROGMAILER_H
20 #define _MAILUTILS_PROGMAILER_H
21
22 #include <mailutils/types.h>
23
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27
28 int mu_progmailer_create (mu_progmailer_t *pm);
29 int mu_progmailer_set_command (mu_progmailer_t pm, const char *command);
30 int mu_progmailer_sget_command (mu_progmailer_t pm, const char **command);
31 /* FIXME: missing _aget_ and _get_ */
32 int mu_progmailer_set_debug (mu_progmailer_t pm, mu_debug_t debug);
33 int mu_progmailer_open (mu_progmailer_t pm, char **argv);
34 int mu_progmailer_send (mu_progmailer_t pm, mu_message_t msg);
35 int mu_progmailer_close (mu_progmailer_t pm);
36 void mu_progmailer_destroy (mu_progmailer_t *pm);
37
38 #ifdef __cplusplus
39 }
40 #endif
41
42 #endif /* _MAILUTILS_PROGMAILER_H */
43
...@@ -121,11 +121,14 @@ extern mu_record_t mu_remote_mbox_record; ...@@ -121,11 +121,14 @@ extern mu_record_t mu_remote_mbox_record;
121 #define MU_REMOTE_MBOX_PRIO 10000 121 #define MU_REMOTE_MBOX_PRIO 10000
122 #define MU_SMTP_PRIO 10000 122 #define MU_SMTP_PRIO 10000
123 #define MU_SENDMAIL_PRIO 10000 123 #define MU_SENDMAIL_PRIO 10000
124 #define MU_PROG_PRIO 10000
124 125
125 /* SMTP mailer, "smtp://" */ 126 /* SMTP mailer, "smtp://" */
126 extern mu_record_t mu_smtp_record; 127 extern mu_record_t mu_smtp_record;
127 /* Sendmail, "sendmail:" */ 128 /* Sendmail, "sendmail:" */
128 extern mu_record_t mu_sendmail_record; 129 extern mu_record_t mu_sendmail_record;
130 /* Program mailer, "prog://", "|" */
131 extern mu_record_t mu_prog_record;
129 132
130 #define mu_register_all_mbox_formats() do {\ 133 #define mu_register_all_mbox_formats() do {\
131 mu_registrar_record (mu_path_record);\ 134 mu_registrar_record (mu_path_record);\
...@@ -156,6 +159,7 @@ extern mu_record_t mu_sendmail_record; ...@@ -156,6 +159,7 @@ extern mu_record_t mu_sendmail_record;
156 #define mu_register_all_mailer_formats() do {\ 159 #define mu_register_all_mailer_formats() do {\
157 mu_registrar_record (mu_sendmail_record);\ 160 mu_registrar_record (mu_sendmail_record);\
158 mu_registrar_record (mu_smtp_record);\ 161 mu_registrar_record (mu_smtp_record);\
162 mu_registrar_record (mu_prog_record);\
159 } while (0) 163 } while (0)
160 164
161 #define mu_register_extra_formats() do {\ 165 #define mu_register_extra_formats() do {\
......
...@@ -111,6 +111,7 @@ typedef struct _mu_server *mu_server_t; ...@@ -111,6 +111,7 @@ typedef struct _mu_server *mu_server_t;
111 typedef struct _mu_ip_server *mu_ip_server_t; 111 typedef struct _mu_ip_server *mu_ip_server_t;
112 typedef struct _mu_m_server *mu_m_server_t; 112 typedef struct _mu_m_server *mu_m_server_t;
113 typedef struct _mu_opool *mu_opool_t; 113 typedef struct _mu_opool *mu_opool_t;
114 typedef struct _mu_progmailer *mu_progmailer_t;
114 115
115 #define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001 116 #define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001
116 #define MU_FOLDER_ATTRIBUTE_FILE 0x002 117 #define MU_FOLDER_ATTRIBUTE_FILE 0x002
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2004, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
3 3
4 This library is free software; you can redistribute it and/or 4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public 5 modify it under the terms of the GNU Lesser General Public
...@@ -19,10 +19,6 @@ ...@@ -19,10 +19,6 @@
19 #ifndef _REGISTRAR0_H 19 #ifndef _REGISTRAR0_H
20 #define _REGISTRAR0_H 20 #define _REGISTRAR0_H
21 21
22 #ifdef DMALLOC
23 # include <dmalloc.h>
24 #endif
25
26 #include <mailutils/registrar.h> 22 #include <mailutils/registrar.h>
27 23
28 #ifdef __cplusplus 24 #ifdef __cplusplus
...@@ -85,6 +81,9 @@ extern int _mailer_smtp_init (mu_mailer_t); ...@@ -85,6 +81,9 @@ extern int _mailer_smtp_init (mu_mailer_t);
85 extern int _url_sendmail_init (mu_url_t); 81 extern int _url_sendmail_init (mu_url_t);
86 extern int _mailer_sendmail_init (mu_mailer_t); 82 extern int _mailer_sendmail_init (mu_mailer_t);
87 83
84 #define MU_PROG_SCHEME "prog"
85 #define MU_PROG_SCHEME_LEN (sizeof (MU_PROG_SCHEME) - 1)
86
88 #define MU_MH_SCHEME "mh" 87 #define MU_MH_SCHEME "mh"
89 #define MU_MH_SCHEME_LEN (sizeof (MU_MH_SCHEME) - 1) 88 #define MU_MH_SCHEME_LEN (sizeof (MU_MH_SCHEME) - 1)
90 extern int _mailbox_mh_init (mu_mailbox_t mailbox); 89 extern int _mailbox_mh_init (mu_mailbox_t mailbox);
......
1 ## Process this file with GNU Automake to create Makefile.in 1 ## Process this file with GNU Automake to create Makefile.in
2 2
3 ## Copyright (C) 2007 Free Software Foundation, Inc. 3 ## Copyright (C) 2007, 2008 Free Software Foundation, Inc.
4 ## 4 ##
5 ## GNU Mailutils is free software; you can redistribute it and/or 5 ## GNU Mailutils is free software; you can redistribute it and/or
6 ## modify it under the terms of the GNU General Public License as 6 ## modify it under the terms of the GNU General Public License as
...@@ -24,6 +24,7 @@ libmu_mailer_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@ ...@@ -24,6 +24,7 @@ libmu_mailer_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
24 libmu_mailer_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@ 24 libmu_mailer_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@
25 25
26 libmu_mailer_la_SOURCES = \ 26 libmu_mailer_la_SOURCES = \
27 prog.c\
27 sendmail.c\ 28 sendmail.c\
28 smtp.c\ 29 smtp.c\
29 url_sendmail.c\ 30 url_sendmail.c\
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2008 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not,
16 see <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #ifdef ENABLE_PROG
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <unistd.h>
26
27 #include <mailutils/address.h>
28 #include <mailutils/argcv.h>
29 #include <mailutils/debug.h>
30 #include <mailutils/errno.h>
31 #include <mailutils/header.h>
32 #include <mailutils/message.h>
33 #include <mailutils/observer.h>
34 #include <mailutils/progmailer.h>
35 #include <mailutils/vartab.h>
36
37 #include <url0.h>
38 #include <mailer0.h>
39 #include <registrar0.h>
40
41 static int _url_prog_init (mu_url_t);
42 static int _url_pipe_init (mu_url_t);
43 static int _mailer_prog_init (mu_mailer_t);
44
45 static struct _mu_record _prog_record =
46 {
47 MU_PROG_PRIO,
48 MU_PROG_SCHEME,
49 _url_prog_init, /* url init. */
50 NULL, /* Mailbox entry. */
51 _mailer_prog_init, /* Mailer entry. */
52 NULL, /* Folder entry. */
53 NULL, /* No need for a back pointer. */
54 NULL, /* _is_scheme method. */
55 NULL, /* _get_url method. */
56 NULL, /* _get_mailbox method. */
57 NULL, /* _get_mailer method. */
58 NULL /* _get_folder method. */
59 };
60
61 mu_record_t mu_prog_record = &_prog_record;
62
63
64 static int
65 _url_prog_init (mu_url_t url)
66 {
67 int status = mu_url_init (url, 0, "prog");
68 if (status)
69 return status;
70 /* not valid in a sendmail url */
71 if (url->user || url->passwd || url->auth || url->host || url->port)
72 return EINVAL;
73 if (!url->path)
74 return EINVAL;
75 return 0;
76 }
77
78
79 static void prog_destroy (mu_mailer_t);
80 static int prog_open (mu_mailer_t, int);
81 static int prog_close (mu_mailer_t);
82 static int prog_send_message (mu_mailer_t, mu_message_t, mu_address_t,
83 mu_address_t);
84
85 static int
86 _mailer_prog_init (mu_mailer_t mailer)
87 {
88 int status;
89 mu_progmailer_t pm;
90
91 status = mu_progmailer_create (&pm);
92 if (status)
93 return status;
94
95 mailer->data = pm;
96 mailer->_destroy = prog_destroy;
97 mailer->_open = prog_open;
98 mailer->_close = prog_close;
99 mailer->_send_message = prog_send_message;
100
101 return 0;
102 }
103
104 static void
105 prog_destroy (mu_mailer_t mailer)
106 {
107 mu_progmailer_destroy ((mu_progmailer_t*)&mailer->data);
108 }
109
110 static int
111 prog_open (mu_mailer_t mailer, int flags)
112 {
113 mu_progmailer_t pm = mailer->data;
114 int status;
115 const char *path;
116
117 /* Sanity checks. */
118 if (pm == NULL)
119 return EINVAL;
120
121 mailer->flags = flags;
122
123 if ((status = mu_url_sget_path (mailer->url, &path)))
124 return status;
125
126 if (access (path, X_OK) == -1)
127 return errno;
128
129 mu_progmailer_set_debug (pm, mailer->debug);
130 status = mu_progmailer_set_command (pm, path);
131 MU_DEBUG1 (mailer->debug, MU_DEBUG_TRACE, "prog (%s)\n", path);
132 return status;
133 }
134
135 static int
136 prog_close (mu_mailer_t mailer)
137 {
138 return mu_progmailer_close (mailer->data);
139 }
140
141 static int
142 _expand_sender (const char *name, void *data, char **p)
143 {
144 mu_address_t addr = data;
145 const char *email;
146 int status = mu_address_sget_email (addr, 1, &email);
147
148 if (status != 0)
149 return status;
150 *(const char**)p = email;
151 return 0;
152 }
153
154 struct ex_rcpt
155 {
156 mu_message_t msg;
157 mu_address_t addr;
158 char *string;
159 };
160
161 static int
162 address_add (mu_address_t *paddr, const char *value)
163 {
164 mu_address_t addr = NULL;
165 int status;
166
167 status = mu_address_create (&addr, value);
168 if (status)
169 return status;
170 status = mu_address_union (paddr, addr);
171 mu_address_destroy (&addr);
172 return status;
173 }
174
175 static int
176 message_read_rcpt (mu_message_t msg, mu_address_t *paddr)
177 {
178 mu_header_t header = NULL;
179 const char *value;
180 int status;
181
182 status = mu_message_get_header (msg, &header);
183 if (status)
184 return status;
185
186 status = mu_header_sget_value (header, MU_HEADER_TO, &value);
187
188 if (status == 0)
189 address_add (paddr, value);
190 else if (status != MU_ERR_NOENT)
191 return status;
192
193 status = mu_header_sget_value (header, MU_HEADER_CC, &value);
194 if (status == 0)
195 address_add (paddr, value);
196 else if (status != MU_ERR_NOENT)
197 return status;
198
199 status = mu_header_sget_value (header, MU_HEADER_BCC, &value);
200 if (status == 0)
201 address_add (paddr, value);
202 else if (status != MU_ERR_NOENT)
203 return status;
204 return 0;
205 }
206
207 static int
208 _expand_rcpt (const char *name, void *data, char **p)
209 {
210 struct ex_rcpt *exrcpt = data;
211 int status;
212
213 if (!exrcpt->string)
214 {
215 size_t i, count = 0;
216 size_t len = 0;
217 char *str;
218 mu_address_t tmp_addr = NULL, addr;
219
220 if (exrcpt->addr)
221 addr = exrcpt->addr;
222 else
223 {
224 status = message_read_rcpt (exrcpt->msg, &tmp_addr);
225 if (status)
226 {
227 mu_address_destroy (&tmp_addr);
228 return status;
229 }
230 addr = tmp_addr;
231 }
232
233 mu_address_get_count (addr, &count);
234 for (i = 1; i <= count; i++)
235 {
236 const char *email;
237 if (i > 1)
238 len++;
239 if ((status = mu_address_sget_email (addr, i, &email)) != 0)
240 {
241 mu_address_destroy (&tmp_addr);
242 return status;
243 }
244 len += strlen (email);
245 }
246
247 str = malloc (len + 1);
248 if (!str)
249 {
250 mu_address_destroy (&tmp_addr);
251 return ENOMEM;
252 }
253 exrcpt->string = str;
254
255 for (i = 1; i <= count; i++)
256 {
257 const char *email;
258 if (i > 1)
259 *str++ = ' ';
260 if (mu_address_sget_email (addr, i, &email))
261 continue;
262 strcpy (str, email);
263 str += strlen (email);
264 }
265 *str = 0;
266 mu_address_destroy (&tmp_addr);
267 }
268 *p = exrcpt->string;
269 return 0;
270 }
271
272 void
273 _free_rcpt (void *data, char *value)
274 {
275 free (value);
276 }
277
278 static int
279 url_to_argv (mu_url_t url, mu_message_t msg,
280 mu_address_t from, mu_address_t to,
281 int *pargc, char ***pargv)
282 {
283 int rc;
284 mu_vartab_t vtab;
285 struct ex_rcpt ex_rcpt;
286 const char *query;
287 char *cmdargs;
288 int argc;
289 char **argv;
290
291 ex_rcpt.msg = msg;
292 ex_rcpt.addr = to;
293 ex_rcpt.string = NULL;
294 mu_vartab_create (&vtab);
295 mu_vartab_define_exp (vtab, "sender", _expand_sender, NULL, from);
296 mu_vartab_define_exp (vtab, "rcpt", _expand_rcpt, _free_rcpt, &ex_rcpt);
297
298 rc = mu_url_sget_query (url, &query);
299 if (rc)
300 return rc;
301
302 rc = mu_vartab_expand (vtab, query, &cmdargs);
303 mu_vartab_destroy (&vtab);
304 if (rc)
305 return rc;
306
307 rc = mu_argcv_get_np (cmdargs, strlen (cmdargs),
308 "&", NULL,
309 0, &argc, &argv, NULL);
310 free (cmdargs);
311 if (rc)
312 return rc;
313 argv = realloc (argv, (argc + 2) * sizeof (argv[0]));
314 memmove (argv + 1, argv, (argc + 1) * sizeof (argv[0]));
315 mu_url_aget_path (url, &argv[0]);
316
317 *pargc = argc + 1;
318 *pargv = argv;
319 return 0;
320 }
321
322 static int
323 prog_send_message (mu_mailer_t mailer, mu_message_t msg, mu_address_t from,
324 mu_address_t to)
325 {
326 mu_progmailer_t pm = mailer->data;
327 int argc;
328 char **argv;
329 int status;
330
331 status = url_to_argv(mailer->url, msg, from, to, &argc, &argv);
332 if (status)
333 {
334 MU_DEBUG1 (mailer->debug, MU_DEBUG_ERROR,
335 "cannot convert URL to command line: %s\n",
336 mu_strerror (status));
337 return status;
338 }
339
340 mu_progmailer_set_debug (pm, mailer->debug);
341 status = mu_progmailer_open (pm, argv);
342 if (status == 0)
343 {
344 status = mu_progmailer_send (pm, msg);
345 if (status == 0)
346 mu_observable_notify (mailer->observable, MU_EVT_MAILER_MESSAGE_SENT,
347 msg);
348 else
349 MU_DEBUG1 (mailer->debug, MU_DEBUG_ERROR,
350 "progmailer error: %s\n",
351 mu_strerror (status));
352 }
353
354 mu_argcv_free (argc, argv);
355 return status;
356 }
357
358 #else
359 #include <stdio.h>
360 #include <registrar0.h>
361 mu_record_t mu_prog_record = NULL;
362 #endif
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2007 Free Software Foundation, Inc. 2 Copyright (C) 2007, 2008 Free Software Foundation, Inc.
3 3
4 This library is free software; you can redistribute it and/or 4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public 5 modify it under the terms of the GNU Lesser General Public
...@@ -46,7 +46,6 @@ _remote_is_scheme (mu_record_t record, mu_url_t url, int flags) ...@@ -46,7 +46,6 @@ _remote_is_scheme (mu_record_t record, mu_url_t url, int flags)
46 { 46 {
47 char *scheme = url->scheme; 47 char *scheme = url->scheme;
48 size_t scheme_len = scheme ? strlen (scheme) : 0; 48 size_t scheme_len = scheme ? strlen (scheme) : 0;
49 int rc;
50 struct _mu_url s_url; 49 struct _mu_url s_url;
51 50
52 if (!scheme 51 if (!scheme
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2002, 2003, 2004, 2 Copyright (C) 1999, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc. 3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
4 4
5 GNU Mailutils is free software; you can redistribute it and/or modify 5 GNU Mailutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
...@@ -666,7 +666,7 @@ msg_to_pipe (const char *cmd, mu_message_t msg) ...@@ -666,7 +666,7 @@ msg_to_pipe (const char *cmd, mu_message_t msg)
666 fprintf (fp, "%s", buffer); 666 fprintf (fp, "%s", buffer);
667 off += n; 667 off += n;
668 } 668 }
669 fclose (fp); 669 pclose (fp);
670 } 670 }
671 else 671 else
672 util_error (_("Piping %s failed"), cmd); 672 util_error (_("Piping %s failed"), cmd);
......
...@@ -108,6 +108,7 @@ libmailutils_la_SOURCES = \ ...@@ -108,6 +108,7 @@ libmailutils_la_SOURCES = \
108 opool.c\ 108 opool.c\
109 parse822.c\ 109 parse822.c\
110 parsedate.c\ 110 parsedate.c\
111 progmailer.c\
111 property.c\ 112 property.c\
112 registrar.c\ 113 registrar.c\
113 refcount.c\ 114 refcount.c\
......
...@@ -501,6 +501,7 @@ _expand_aclno (const char *name, void *data, char **p) ...@@ -501,6 +501,7 @@ _expand_aclno (const char *name, void *data, char **p)
501 { 501 {
502 struct run_closure *rp = data; 502 struct run_closure *rp = data;
503 char buf[UINTMAX_STRSIZE_BOUND]; 503 char buf[UINTMAX_STRSIZE_BOUND];
504 /*FIXME: memory leak*/
504 *p = strdup (umaxtostr (rp->idx, buf)); 505 *p = strdup (umaxtostr (rp->idx, buf));
505 return 0; 506 return 0;
506 } 507 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2004, 2005,
3 2006, 2007, 2008 Free Software Foundation, Inc.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 3 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General
16 Public License along with this library; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301 USA */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <errno.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sysexits.h>
30
31 #include <sys/types.h>
32 #include <sys/wait.h>
33
34 #include <mailutils/debug.h>
35 #include <mailutils/error.h>
36 #include <mailutils/errno.h>
37 #include <mailutils/stream.h>
38 #include <mailutils/header.h>
39 #include <mailutils/body.h>
40 #include <mailutils/message.h>
41 #include <mailutils/progmailer.h>
42
43 struct _mu_progmailer
44 {
45 int fd;
46 pid_t pid;
47 RETSIGTYPE (*sighandler)();
48 mu_debug_t debug;
49 char *command;
50 };
51
52 /* Close FD unless it is part of pipe P */
53 #define SCLOSE(fd,p) if (p[0]!=fd&&p[1]!=fd) close(fd)
54
55 int
56 mu_progmailer_create (struct _mu_progmailer **ppm)
57 {
58 struct _mu_progmailer *pm = malloc (sizeof (*pm));
59 if (!pm)
60 return ENOMEM;
61 pm->fd = -1;
62 pm->pid = -1;
63 pm->sighandler = SIG_ERR;
64 pm->debug = NULL;
65 pm->command = NULL;
66 *ppm = pm;
67 return 0;
68 }
69
70 int
71 mu_progmailer_set_command (mu_progmailer_t pm, const char *command)
72 {
73 if (!pm)
74 return EINVAL;
75 free (pm->command);
76 if (command)
77 {
78 pm->command = strdup (command);
79 if (!pm->command)
80 return EINVAL;
81 }
82 else
83 pm->command = NULL;
84 return 0;
85 }
86
87 int
88 mu_progmailer_sget_command (mu_progmailer_t pm, const char **command)
89 {
90 if (!pm)
91 return EINVAL;
92 *command = pm->command;
93 return 0;
94 }
95
96 int
97 mu_progmailer_set_debug (mu_progmailer_t pm, mu_debug_t debug)
98 {
99 if (!pm)
100 return EINVAL;
101 pm->debug = debug;
102 }
103
104 void
105 mu_progmailer_destroy (struct _mu_progmailer **ppm)
106 {
107 if (*ppm)
108 {
109 free ((*ppm)->command);
110 free (*ppm);
111 *ppm = NULL;
112 }
113 }
114
115 int
116 mu_progmailer_open (struct _mu_progmailer *pm, char **argv)
117 {
118 int tunnel[2];
119 int status = 0;
120 int i;
121
122 if (!pm || !argv)
123 return EINVAL;
124
125 if ((pm->sighandler = signal (SIGCHLD, SIG_DFL)) == SIG_ERR)
126 {
127 status = errno;
128 MU_DEBUG1 (pm->debug, MU_DEBUG_ERROR,
129 "setting SIGCHLD failed: %s\n", mu_strerror (status));
130 return status;
131 }
132
133 if (pipe (tunnel) == 0)
134 {
135 pm->fd = tunnel[1];
136 pm->pid = fork ();
137 if (pm->pid == 0) /* Child. */
138 {
139 SCLOSE (STDIN_FILENO, tunnel);
140 SCLOSE (STDOUT_FILENO, tunnel);
141 SCLOSE (STDERR_FILENO, tunnel);
142 close (tunnel[1]);
143 dup2 (tunnel[0], STDIN_FILENO);
144 execv (pm->command ? pm->command : argv[0], argv);
145 exit (errno ? EX_CANTCREAT : 0);
146 }
147 else if (pm->pid == -1)
148 {
149 status = errno;
150 MU_DEBUG1 (pm->debug, MU_DEBUG_ERROR,
151 "fork failed: %s\n", mu_strerror (status));
152 }
153 }
154 else
155 {
156 status = errno;
157 MU_DEBUG1 (pm->debug, MU_DEBUG_ERROR,
158 "pipe() failed: %s\n", mu_strerror (status));
159 }
160 MU_DEBUG1 (pm->debug, MU_DEBUG_TRACE, "exec %s argv:", pm->command);
161 for (i = 0; argv[i]; i++)
162 MU_DEBUG1 (pm->debug, MU_DEBUG_TRACE, " %s", argv[i]);
163 MU_DEBUG (pm->debug, MU_DEBUG_TRACE, "\n");
164 close (tunnel[0]);
165
166 if (status != 0)
167 close (pm->fd);
168 return status;
169 }
170
171 int
172 mu_progmailer_send (struct _mu_progmailer *pm, mu_message_t msg)
173 {
174 int status;
175 mu_stream_t stream = NULL;
176 char buffer[512];
177 size_t len = 0;
178 int rc;
179 size_t offset = 0;
180 mu_header_t hdr;
181 mu_body_t body;
182 int found_nl = 0;
183 int exit_status;
184
185 if (!pm || !msg)
186 return EINVAL;
187 mu_message_get_header (msg, &hdr);
188 mu_header_get_stream (hdr, &stream);
189
190 MU_DEBUG (pm->debug, MU_DEBUG_TRACE, "Sending headers...\n");
191 while ((status = mu_stream_readline (stream, buffer, sizeof (buffer),
192 offset, &len)) == 0
193 && len != 0)
194 {
195 if (strncasecmp (buffer, MU_HEADER_FCC, sizeof (MU_HEADER_FCC) - 1))
196 {
197 MU_DEBUG1 (pm->debug, MU_DEBUG_PROT, "Header: %s", buffer);
198 if (write (pm->fd, buffer, len) == -1)
199 {
200 status = errno;
201
202 MU_DEBUG1 (pm->debug, MU_DEBUG_TRACE,
203 "write failed: %s\n", strerror (status));
204 break;
205 }
206 }
207 found_nl = (len == 1 && buffer[0] == '\n');
208
209 offset += len;
210 }
211
212 if (!found_nl)
213 {
214 if (write (pm->fd, "\n", 1) == -1)
215 {
216 status = errno;
217
218 MU_DEBUG1 (pm->debug, MU_DEBUG_TRACE,
219 "write failed: %s\n", strerror (status));
220 }
221 }
222
223 mu_message_get_body (msg, &body);
224 mu_body_get_stream (body, &stream);
225
226 MU_DEBUG (pm->debug, MU_DEBUG_TRACE, "Sending body...\n");
227 offset = 0;
228 while ((status = mu_stream_read (stream, buffer, sizeof (buffer),
229 offset, &len)) == 0
230 && len != 0)
231 {
232 if (write (pm->fd, buffer, len) == -1)
233 {
234 status = errno;
235
236 MU_DEBUG1 (pm->debug, MU_DEBUG_TRACE,
237 "write failed: %s\n", strerror (status));
238 break;
239 }
240 offset += len;
241 }
242
243 close (pm->fd);
244
245 rc = waitpid (pm->pid, &exit_status, 0);
246 if (status == 0)
247 {
248 if (rc < 0)
249 {
250 if (errno == ECHILD)
251 status = 0;
252 else
253 {
254 status = errno;
255 MU_DEBUG2 (pm->debug, MU_DEBUG_TRACE,
256 "waitpid(%lu) failed: %s\n",
257 (unsigned long) pm->pid, strerror (status));
258 }
259 }
260 else if (WIFEXITED (exit_status))
261 {
262 exit_status = WEXITSTATUS (exit_status);
263 MU_DEBUG2 (pm->debug, MU_DEBUG_TRACE,
264 "%s exited with: %d\n",
265 pm->command, exit_status);
266 status = (exit_status == 0) ? 0 : MU_ERR_PROCESS_EXITED;
267 }
268 else if (WIFSIGNALED (exit_status))
269 status = MU_ERR_PROCESS_SIGNALED;
270 else
271 status = MU_ERR_PROCESS_UNKNOWN_FAILURE;
272 }
273 pm->pid = -1;
274 return status;
275 }
276
277 int
278 mu_progmailer_close (struct _mu_progmailer *pm)
279 {
280 int status = 0;
281
282 if (!pm)
283 return EINVAL;
284
285 if (pm->pid > 0)
286 {
287 kill (SIGTERM, pm->pid);
288 pm->pid = -1;
289 }
290
291 if (pm->sighandler != SIG_ERR
292 && signal (SIGCHLD, pm->sighandler) == SIG_ERR)
293 {
294 status = errno;
295 MU_DEBUG1 (pm->debug, MU_DEBUG_ERROR,
296 "resetting SIGCHLD failed: %s\n", mu_strerror (status));
297 }
298 pm->sighandler = SIG_ERR;
299 return status;
300 }