Implement SMTP shell in mu.
* include/mailutils/smtp.h (mu_smtp_get_reply_iterator) (mu_smtp_cmd,mu_smtp_test_param): New protos. * libproto/mailer/Makefile.am (libmu_mailer_la_SOURCES): Add smtp_cmd.c * libproto/mailer/smtp_cmd.c: New file. * libproto/mailer/smtp_io.c (mu_smtp_get_reply_iterator): New function. * libproto/mailer/smtp_param.c (mu_smtp_set_param): Accept NULL parameter value. (mu_smtp_test_param): New function. * mu/Makefile.am [MU_COND_SUPPORT_SMTP]: Add smtp.c to MODULES. (mu_SOURCES): Add getans.c, getyn.c and util.c * mu/getans.c: New file. * mu/getyn.c: New file. * mu/smtp.c: New file. * mu/util.c: New file. * mu/mu.h (port_from_sa): New proto. * mu/pop.c (port_from_sa): Move to util.c
Showing
13 changed files
with
1281 additions
and
28 deletions
... | @@ -47,7 +47,9 @@ int mu_smtp_write (mu_smtp_t smtp, const char *fmt, ...) MU_PRINTFLIKE(2,3); | ... | @@ -47,7 +47,9 @@ int mu_smtp_write (mu_smtp_t smtp, const char *fmt, ...) MU_PRINTFLIKE(2,3); |
47 | 47 | ||
48 | int mu_smtp_replcode (mu_smtp_t smtp, char *buf); | 48 | int mu_smtp_replcode (mu_smtp_t smtp, char *buf); |
49 | int mu_smtp_sget_reply (mu_smtp_t smtp, const char **pbuf); | 49 | int mu_smtp_sget_reply (mu_smtp_t smtp, const char **pbuf); |
50 | int mu_smtp_get_reply_iterator (mu_smtp_t smtp, mu_iterator_t *pitr); | ||
50 | 51 | ||
52 | int mu_smtp_cmd (mu_smtp_t smtp, int argc, char **argv); | ||
51 | 53 | ||
52 | #define MU_SMTP_TRACE_CLR 0 | 54 | #define MU_SMTP_TRACE_CLR 0 |
53 | #define MU_SMTP_TRACE_SET 1 | 55 | #define MU_SMTP_TRACE_SET 1 |
... | @@ -59,6 +61,7 @@ int mu_smtp_disconnect (mu_smtp_t smtp); | ... | @@ -59,6 +61,7 @@ int mu_smtp_disconnect (mu_smtp_t smtp); |
59 | int mu_smtp_ehlo (mu_smtp_t smtp); | 61 | int mu_smtp_ehlo (mu_smtp_t smtp); |
60 | int mu_smtp_set_param (mu_smtp_t smtp, int code, const char *val); | 62 | int mu_smtp_set_param (mu_smtp_t smtp, int code, const char *val); |
61 | int mu_smtp_get_param (mu_smtp_t smtp, int code, const char **param); | 63 | int mu_smtp_get_param (mu_smtp_t smtp, int code, const char **param); |
64 | int mu_smtp_test_param (mu_smtp_t smtp, int pcode); | ||
62 | int mu_smtp_set_url (mu_smtp_t smtp, mu_url_t url); | 65 | int mu_smtp_set_url (mu_smtp_t smtp, mu_url_t url); |
63 | int mu_smtp_get_url (mu_smtp_t smtp, mu_url_t *purl); | 66 | int mu_smtp_get_url (mu_smtp_t smtp, mu_url_t *purl); |
64 | int mu_smtp_set_secret (mu_smtp_t smtp, mu_secret_t secret); | 67 | int mu_smtp_set_secret (mu_smtp_t smtp, mu_secret_t secret); | ... | ... |
... | @@ -34,6 +34,7 @@ libmu_mailer_la_SOURCES = \ | ... | @@ -34,6 +34,7 @@ libmu_mailer_la_SOURCES = \ |
34 | smtp_capa.c\ | 34 | smtp_capa.c\ |
35 | smtp_capa_itr.c\ | 35 | smtp_capa_itr.c\ |
36 | smtp_carrier.c\ | 36 | smtp_carrier.c\ |
37 | smtp_cmd.c\ | ||
37 | smtp_create.c\ | 38 | smtp_create.c\ |
38 | smtp_data.c\ | 39 | smtp_data.c\ |
39 | smtp_disconnect.c\ | 40 | smtp_disconnect.c\ | ... | ... |
libproto/mailer/smtp_cmd.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010-2012 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | 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 | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | |||
21 | #include <errno.h> | ||
22 | #include <stdarg.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | #include <mailutils/errno.h> | ||
26 | #include <mailutils/cctype.h> | ||
27 | #include <mailutils/list.h> | ||
28 | #include <mailutils/util.h> | ||
29 | #include <mailutils/smtp.h> | ||
30 | #include <mailutils/stream.h> | ||
31 | #include <mailutils/sys/smtp.h> | ||
32 | |||
33 | /* Send an arbitrary command */ | ||
34 | int | ||
35 | mu_smtp_cmd (mu_smtp_t smtp, int argc, char **argv) | ||
36 | { | ||
37 | int status, i; | ||
38 | |||
39 | if (!smtp) | ||
40 | return EINVAL; | ||
41 | if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR)) | ||
42 | return MU_ERR_FAILURE; | ||
43 | status = mu_smtp_write (smtp, "%s", argv[0]); | ||
44 | MU_SMTP_CHECK_ERROR (smtp, status); | ||
45 | for (i = 1; i < argc; i++) | ||
46 | { | ||
47 | status = mu_smtp_write (smtp, " %s", argv[i]); | ||
48 | MU_SMTP_CHECK_ERROR (smtp, status); | ||
49 | } | ||
50 | |||
51 | status = mu_smtp_write (smtp, "\r\n"); | ||
52 | MU_SMTP_CHECK_ERROR (smtp, status); | ||
53 | status = mu_smtp_response (smtp); | ||
54 | MU_SMTP_CHECK_ERROR (smtp, status); | ||
55 | |||
56 | if (smtp->replcode[0] > '3') | ||
57 | return MU_ERR_REPLY; | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | |||
62 |
... | @@ -144,4 +144,10 @@ mu_smtp_sget_reply (mu_smtp_t smtp, const char **pbuf) | ... | @@ -144,4 +144,10 @@ mu_smtp_sget_reply (mu_smtp_t smtp, const char **pbuf) |
144 | return 0; | 144 | return 0; |
145 | } | 145 | } |
146 | 146 | ||
147 | 147 | int | |
148 | mu_smtp_get_reply_iterator (mu_smtp_t smtp, mu_iterator_t *pitr) | ||
149 | { | ||
150 | if (!smtp || !pitr) | ||
151 | return EINVAL; | ||
152 | return mu_list_get_iterator (smtp->mlrepl, pitr); | ||
153 | } | ... | ... |
... | @@ -49,6 +49,8 @@ mu_smtp_set_param (mu_smtp_t smtp, int pcode, const char *newparam) | ... | @@ -49,6 +49,8 @@ mu_smtp_set_param (mu_smtp_t smtp, int pcode, const char *newparam) |
49 | mu_secret_password_unref (smtp->secret); | 49 | mu_secret_password_unref (smtp->secret); |
50 | mu_secret_destroy (&smtp->secret); | 50 | mu_secret_destroy (&smtp->secret); |
51 | } | 51 | } |
52 | if (!newparam) | ||
53 | return 0; | ||
52 | MU_SMTP_FCLR (smtp, _MU_SMTP_CLNPASS); | 54 | MU_SMTP_FCLR (smtp, _MU_SMTP_CLNPASS); |
53 | return mu_secret_create (&smtp->secret, newparam, strlen (newparam)); | 55 | return mu_secret_create (&smtp->secret, newparam, strlen (newparam)); |
54 | } | 56 | } |
... | @@ -56,18 +58,28 @@ mu_smtp_set_param (mu_smtp_t smtp, int pcode, const char *newparam) | ... | @@ -56,18 +58,28 @@ mu_smtp_set_param (mu_smtp_t smtp, int pcode, const char *newparam) |
56 | { | 58 | { |
57 | mu_url_t url; | 59 | mu_url_t url; |
58 | int rc; | 60 | int rc; |
59 | 61 | ||
60 | rc = mu_url_create (&url, newparam); | 62 | if (!newparam) |
61 | if (rc) | 63 | mu_url_destroy (&smtp->url); |
62 | return rc; | 64 | else |
63 | mu_url_destroy (&smtp->url); | 65 | { |
64 | smtp->url = url; | 66 | rc = mu_url_create (&url, newparam); |
67 | if (rc) | ||
68 | return rc; | ||
69 | mu_url_destroy (&smtp->url); | ||
70 | smtp->url = url; | ||
71 | } | ||
65 | return 0; | 72 | return 0; |
66 | } | 73 | } |
67 | 74 | ||
68 | param = strdup (newparam); | 75 | if (newparam) |
69 | if (!param) | 76 | { |
70 | return ENOMEM; | 77 | param = strdup (newparam); |
78 | if (!param) | ||
79 | return ENOMEM; | ||
80 | } | ||
81 | else | ||
82 | param = NULL; | ||
71 | free (smtp->param[pcode]); | 83 | free (smtp->param[pcode]); |
72 | smtp->param[pcode] = param; | 84 | smtp->param[pcode] = param; |
73 | return 0; | 85 | return 0; |
... | @@ -99,3 +111,24 @@ mu_smtp_get_param (mu_smtp_t smtp, int pcode, const char **pparam) | ... | @@ -99,3 +111,24 @@ mu_smtp_get_param (mu_smtp_t smtp, int pcode, const char **pparam) |
99 | return 0; | 111 | return 0; |
100 | } | 112 | } |
101 | 113 | ||
114 | int | ||
115 | mu_smtp_test_param (mu_smtp_t smtp, int pcode) | ||
116 | { | ||
117 | if (!smtp) | ||
118 | return EINVAL; | ||
119 | if (pcode < 0 || pcode >= MU_SMTP_MAX_PARAM) | ||
120 | return EINVAL; | ||
121 | if (pcode == MU_SMTP_PARAM_PASSWORD) | ||
122 | { | ||
123 | if (smtp->secret) | ||
124 | return 0; | ||
125 | return MU_ERR_NOENT; | ||
126 | } | ||
127 | else if (pcode == MU_SMTP_PARAM_URL) | ||
128 | { | ||
129 | if (smtp->url) | ||
130 | return 0; | ||
131 | return MU_ERR_NOENT; | ||
132 | } | ||
133 | return smtp->param[pcode] ? 0 : MU_ERR_NOENT; | ||
134 | } | ... | ... |
... | @@ -269,6 +269,9 @@ void mh_global_save_state (void); | ... | @@ -269,6 +269,9 @@ void mh_global_save_state (void); |
269 | int mh_interactive_mode_p (void); | 269 | int mh_interactive_mode_p (void); |
270 | int mh_getyn (const char *fmt, ...) MU_PRINTFLIKE(1,2); | 270 | int mh_getyn (const char *fmt, ...) MU_PRINTFLIKE(1,2); |
271 | int mh_getyn_interactive (const char *fmt, ...) MU_PRINTFLIKE(1,2); | 271 | int mh_getyn_interactive (const char *fmt, ...) MU_PRINTFLIKE(1,2); |
272 | int mu_vgetans (const char *variants, const char *fmt, va_list ap); | ||
273 | int mu_getans (const char *variants, const char *fmt, ...) | ||
274 | MU_PRINTFLIKE(2,3); | ||
272 | int mh_check_folder (const char *pathname, int confirm); | 275 | int mh_check_folder (const char *pathname, int confirm); |
273 | int mh_makedir (const char *p); | 276 | int mh_makedir (const char *p); |
274 | 277 | ... | ... |
... | @@ -39,6 +39,12 @@ else | ... | @@ -39,6 +39,12 @@ else |
39 | IDLE_MODULES+=dbm.c | 39 | IDLE_MODULES+=dbm.c |
40 | endif | 40 | endif |
41 | 41 | ||
42 | if MU_COND_SUPPORT_SMTP | ||
43 | SMTP_C=smtp.c | ||
44 | else | ||
45 | IDLE_MODULES+=smtp.c | ||
46 | endif | ||
47 | |||
42 | MODULES = \ | 48 | MODULES = \ |
43 | acl.c\ | 49 | acl.c\ |
44 | cflags.c\ | 50 | cflags.c\ |
... | @@ -51,16 +57,20 @@ MODULES = \ | ... | @@ -51,16 +57,20 @@ MODULES = \ |
51 | ldflags.c\ | 57 | ldflags.c\ |
52 | logger.c\ | 58 | logger.c\ |
53 | $(POP_C)\ | 59 | $(POP_C)\ |
54 | send.c\ | ||
55 | query.c\ | 60 | query.c\ |
61 | send.c\ | ||
62 | $(SMTP_C)\ | ||
56 | wicket.c | 63 | wicket.c |
57 | 64 | ||
58 | mu_SOURCES = \ | 65 | mu_SOURCES = \ |
59 | dispatch.c\ | 66 | dispatch.c\ |
67 | getans.c\ | ||
60 | getarg.c\ | 68 | getarg.c\ |
69 | getyn.c\ | ||
61 | mu.h\ | 70 | mu.h\ |
62 | mu.c\ | 71 | mu.c\ |
63 | shell.c\ | 72 | shell.c\ |
73 | util.c\ | ||
64 | verbose.c\ | 74 | verbose.c\ |
65 | $(MODULES) | 75 | $(MODULES) |
66 | 76 | ... | ... |
mu/getans.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010, 2012 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils 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 | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <mailutils/mailutils.h> | ||
21 | #include "mu.h" | ||
22 | |||
23 | int | ||
24 | mu_vgetans (const char *variants, const char *fmt, va_list ap) | ||
25 | { | ||
26 | char repl[64]; | ||
27 | |||
28 | while (1) | ||
29 | { | ||
30 | size_t n; | ||
31 | char *p; | ||
32 | |||
33 | mu_stream_vprintf (mu_strout, fmt, ap); | ||
34 | mu_stream_write (mu_strout, "? ", 2, NULL); | ||
35 | mu_stream_flush (mu_strout); | ||
36 | if (mu_stream_read (mu_strin, repl, sizeof repl, &n) || n == 0) | ||
37 | return 0; | ||
38 | mu_rtrim_class (repl, MU_CTYPE_ENDLN); | ||
39 | |||
40 | p = strchr (variants, *repl); | ||
41 | if (p) | ||
42 | return *p; | ||
43 | |||
44 | mu_stream_printf (mu_strout, _("Please answer one of [%s]: "), variants); | ||
45 | } | ||
46 | return 0; /* to pacify gcc */ | ||
47 | } | ||
48 | |||
49 | int | ||
50 | mu_getans (const char *variants, const char *fmt, ...) | ||
51 | { | ||
52 | va_list ap; | ||
53 | int rc; | ||
54 | |||
55 | va_start (ap, fmt); | ||
56 | rc = mu_vgetans (variants, fmt, ap); | ||
57 | va_end (ap); | ||
58 | return rc; | ||
59 | } | ||
60 |
mu/getyn.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010, 2012 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils 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 | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <mailutils/mailutils.h> | ||
21 | #include "mu.h" | ||
22 | |||
23 | int | ||
24 | mu_vgetyn (const char *fmt, va_list ap) | ||
25 | { | ||
26 | char repl[64]; | ||
27 | |||
28 | while (1) | ||
29 | { | ||
30 | int rc; | ||
31 | size_t n; | ||
32 | |||
33 | mu_stream_vprintf (mu_strout, fmt, ap); | ||
34 | mu_stream_write (mu_strout, "? ", 2, NULL); | ||
35 | mu_stream_flush (mu_strout); | ||
36 | if (mu_stream_read (mu_strin, repl, sizeof repl, &n) || n == 0) | ||
37 | return 0; | ||
38 | mu_rtrim_class (repl, MU_CTYPE_ENDLN); | ||
39 | |||
40 | rc = mu_true_answer_p (repl); | ||
41 | |||
42 | if (rc >= 0) | ||
43 | return rc; | ||
44 | |||
45 | /* TRANSLATORS: See msgids "nN" and "yY". */ | ||
46 | mu_stream_printf (mu_strout, "%s", _("Please answer yes or no: ")); | ||
47 | } | ||
48 | return 0; /* to pacify gcc */ | ||
49 | } | ||
50 | |||
51 | int | ||
52 | mu_getyn (const char *fmt, ...) | ||
53 | { | ||
54 | va_list ap; | ||
55 | int rc; | ||
56 | |||
57 | va_start (ap, fmt); | ||
58 | rc = mu_vgetyn (fmt, ap); | ||
59 | va_end (ap); | ||
60 | return rc; | ||
61 | } | ||
62 |
... | @@ -42,6 +42,8 @@ int mu_help (void); | ... | @@ -42,6 +42,8 @@ int mu_help (void); |
42 | mutool_action_t dispatch_find_action (const char *name); | 42 | mutool_action_t dispatch_find_action (const char *name); |
43 | char *dispatch_docstring (const char *text); | 43 | char *dispatch_docstring (const char *text); |
44 | 44 | ||
45 | int port_from_sa (struct mu_sockaddr *sa); | ||
46 | |||
45 | 47 | ||
46 | #define VERBOSE_MASK(n) (1<<((n)+1)) | 48 | #define VERBOSE_MASK(n) (1<<((n)+1)) |
47 | #define SET_VERBOSE_MASK(n) (shell_verbose_flags |= VERBOSE_MASK (n)) | 49 | #define SET_VERBOSE_MASK(n) (shell_verbose_flags |= VERBOSE_MASK (n)) | ... | ... |
... | @@ -473,22 +473,6 @@ com_disconnect (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) | ... | @@ -473,22 +473,6 @@ com_disconnect (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) |
473 | } | 473 | } |
474 | 474 | ||
475 | static int | 475 | static int |
476 | port_from_sa (struct mu_sockaddr *sa) | ||
477 | { | ||
478 | switch (sa->addr->sa_family) | ||
479 | { | ||
480 | case AF_INET: | ||
481 | return ntohs (((struct sockaddr_in *)sa->addr)->sin_port); | ||
482 | |||
483 | #ifdef MAILUTILS_IPV6 | ||
484 | case AF_INET6: | ||
485 | return ntohs (((struct sockaddr_in6 *)sa->addr)->sin6_port); | ||
486 | #endif | ||
487 | } | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static int | ||
492 | com_connect (int argc, char **argv) | 476 | com_connect (int argc, char **argv) |
493 | { | 477 | { |
494 | int status; | 478 | int status; | ... | ... |
mu/smtp.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010-2012 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils 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 | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <unistd.h> | ||
21 | #include <stdio.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <netdb.h> | ||
24 | #include <netinet/in.h> | ||
25 | #include <mailutils/cctype.h> | ||
26 | #include <mailutils/mailutils.h> | ||
27 | #include <mailutils/smtp.h> | ||
28 | #include <argp.h> | ||
29 | #include "mu.h" | ||
30 | |||
31 | static char smtp_doc[] = N_("mu smtp - run a SMTP session."); | ||
32 | char smtp_docstring[] = N_("run a SMTP session"); | ||
33 | static char smtp_args_doc[] = ""; | ||
34 | |||
35 | static struct argp_option smtp_options[] = { | ||
36 | { NULL } | ||
37 | }; | ||
38 | |||
39 | static error_t | ||
40 | smtp_parse_opt (int key, char *arg, struct argp_state *state) | ||
41 | { | ||
42 | switch (key) | ||
43 | { | ||
44 | default: | ||
45 | return ARGP_ERR_UNKNOWN; | ||
46 | } | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static struct argp smtp_argp = { | ||
51 | smtp_options, | ||
52 | smtp_parse_opt, | ||
53 | smtp_args_doc, | ||
54 | smtp_doc, | ||
55 | NULL, | ||
56 | NULL, | ||
57 | NULL | ||
58 | }; | ||
59 | |||
60 | enum smtp_session_status | ||
61 | { | ||
62 | smtp_session_disconnected, | ||
63 | smtp_session_connected, | ||
64 | smtp_session_logged_in | ||
65 | }; | ||
66 | |||
67 | static enum smtp_session_status smtp_session_status; | ||
68 | static int connect_argc; | ||
69 | static char **connect_argv; | ||
70 | |||
71 | /* Host we are connected to. */ | ||
72 | #define host connect_argv[0] | ||
73 | static int port = 25; | ||
74 | |||
75 | static char *sender; | ||
76 | static mu_list_t recipients; | ||
77 | |||
78 | static char *msgfile; | ||
79 | static int temp_msgfile; | ||
80 | static mu_smtp_t smtp; | ||
81 | |||
82 | const char * | ||
83 | smtp_session_str (enum smtp_session_status stat) | ||
84 | { | ||
85 | switch (stat) | ||
86 | { | ||
87 | case smtp_session_disconnected: | ||
88 | return "disconnected"; | ||
89 | |||
90 | case smtp_session_connected: | ||
91 | return "connected"; | ||
92 | |||
93 | case smtp_session_logged_in: | ||
94 | return "logged in"; | ||
95 | } | ||
96 | return "unknown"; | ||
97 | } | ||
98 | |||
99 | static void | ||
100 | smtp_prompt_env () | ||
101 | { | ||
102 | const char *value; | ||
103 | |||
104 | if (!mutool_prompt_env) | ||
105 | mutool_prompt_env = mu_calloc (2*7 + 1, sizeof(mutool_prompt_env[0])); | ||
106 | |||
107 | mutool_prompt_env[0] = "user"; | ||
108 | mutool_prompt_env[1] = "[nouser]"; | ||
109 | if (smtp_session_status == smtp_session_logged_in && | ||
110 | mu_smtp_get_param (smtp, MU_SMTP_PARAM_USERNAME, &value) == 0) | ||
111 | mutool_prompt_env[1] = (char*) value; | ||
112 | |||
113 | mutool_prompt_env[2] = "host"; | ||
114 | mutool_prompt_env[3] = (smtp_session_status != smtp_session_disconnected) ? | ||
115 | host : "[nohost]"; | ||
116 | |||
117 | mutool_prompt_env[4] = "program-name"; | ||
118 | mutool_prompt_env[5] = (char*) mu_program_name; | ||
119 | |||
120 | mutool_prompt_env[6] = "canonical-program-name"; | ||
121 | mutool_prompt_env[7] = "mu"; | ||
122 | |||
123 | mutool_prompt_env[8] = "package"; | ||
124 | mutool_prompt_env[9] = PACKAGE; | ||
125 | |||
126 | mutool_prompt_env[10] = "version"; | ||
127 | mutool_prompt_env[11] = PACKAGE_VERSION; | ||
128 | |||
129 | mutool_prompt_env[12] = "status"; | ||
130 | mutool_prompt_env[13] = (char*) smtp_session_str (smtp_session_status); | ||
131 | |||
132 | mutool_prompt_env[14] = NULL; | ||
133 | } | ||
134 | |||
135 | static void | ||
136 | smtp_set_verbose (void) | ||
137 | { | ||
138 | if (smtp) | ||
139 | { | ||
140 | if (QRY_VERBOSE ()) | ||
141 | mu_smtp_trace (smtp, MU_SMTP_TRACE_SET); | ||
142 | else | ||
143 | mu_smtp_trace (smtp, MU_SMTP_TRACE_CLR); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | static void | ||
148 | smtp_set_verbose_mask (void) | ||
149 | { | ||
150 | if (smtp) | ||
151 | { | ||
152 | mu_smtp_trace_mask (smtp, QRY_VERBOSE_MASK (MU_XSCRIPT_SECURE) | ||
153 | ? MU_SMTP_TRACE_SET : MU_SMTP_TRACE_CLR, | ||
154 | MU_XSCRIPT_SECURE); | ||
155 | mu_smtp_trace_mask (smtp, QRY_VERBOSE_MASK (MU_XSCRIPT_PAYLOAD) | ||
156 | ? MU_SMTP_TRACE_SET : MU_SMTP_TRACE_CLR, | ||
157 | MU_XSCRIPT_PAYLOAD); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | static int | ||
162 | com_verbose (int argc, char **argv) | ||
163 | { | ||
164 | return shell_verbose (argc, argv, | ||
165 | smtp_set_verbose, smtp_set_verbose_mask); | ||
166 | } | ||
167 | |||
168 | static int | ||
169 | smtp_error_handler (int rc) | ||
170 | { | ||
171 | if (rc == 0 || rc == MU_ERR_REPLY) | ||
172 | { | ||
173 | char code[4]; | ||
174 | const char *repl; | ||
175 | |||
176 | mu_smtp_replcode (smtp, code); | ||
177 | mu_smtp_sget_reply (smtp, &repl); | ||
178 | mu_printf ("%s %s\n", code, repl); | ||
179 | } | ||
180 | return rc; | ||
181 | } | ||
182 | |||
183 | static int | ||
184 | com_disconnect (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) | ||
185 | { | ||
186 | if (smtp) | ||
187 | { | ||
188 | mu_smtp_disconnect (smtp); | ||
189 | mu_smtp_destroy (&smtp); | ||
190 | smtp = NULL; | ||
191 | |||
192 | mu_argcv_free (connect_argc, connect_argv); | ||
193 | connect_argc = 0; | ||
194 | connect_argv = NULL; | ||
195 | smtp_session_status = smtp_session_disconnected; | ||
196 | smtp_prompt_env (); | ||
197 | } | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static int | ||
202 | com_connect (int argc, char **argv) | ||
203 | { | ||
204 | int status; | ||
205 | int tls = 0; | ||
206 | int i = 1; | ||
207 | int n; | ||
208 | |||
209 | for (i = 1; i < argc; i++) | ||
210 | { | ||
211 | if (strcmp (argv[i], "-tls") == 0) | ||
212 | { | ||
213 | #ifdef WITH_TLS | ||
214 | tls = 1; | ||
215 | #else | ||
216 | mu_error ("TLS not supported"); | ||
217 | return 0; | ||
218 | #endif | ||
219 | } | ||
220 | else | ||
221 | break; | ||
222 | } | ||
223 | |||
224 | argc -= i; | ||
225 | argv += i; | ||
226 | |||
227 | if (smtp_session_status != smtp_session_disconnected) | ||
228 | com_disconnect (0, NULL); | ||
229 | |||
230 | status = mu_smtp_create (&smtp); | ||
231 | if (status == 0) | ||
232 | { | ||
233 | mu_stream_t tcp; | ||
234 | struct mu_sockaddr *sa; | ||
235 | struct mu_sockaddr_hints hints; | ||
236 | |||
237 | if (QRY_VERBOSE ()) | ||
238 | { | ||
239 | smtp_set_verbose (); | ||
240 | smtp_set_verbose_mask (); | ||
241 | } | ||
242 | |||
243 | memset (&hints, 0, sizeof (hints)); | ||
244 | hints.flags = MU_AH_DETECT_FAMILY; | ||
245 | hints.port = tls ? 465 : 25; | ||
246 | hints.protocol = IPPROTO_TCP; | ||
247 | hints.socktype = SOCK_STREAM; | ||
248 | status = mu_sockaddr_from_node (&sa, argv[0], argv[1], &hints); | ||
249 | if (status == 0) | ||
250 | { | ||
251 | n = port_from_sa (sa); | ||
252 | status = mu_tcp_stream_create_from_sa (&tcp, sa, NULL, 0); | ||
253 | if (status) | ||
254 | mu_sockaddr_free (sa); | ||
255 | } | ||
256 | if (status == 0) | ||
257 | { | ||
258 | #ifdef WITH_TLS | ||
259 | if (tls) | ||
260 | { | ||
261 | mu_stream_t tlsstream; | ||
262 | |||
263 | status = mu_tls_client_stream_create (&tlsstream, tcp, tcp, 0); | ||
264 | mu_stream_unref (tcp); | ||
265 | if (status) | ||
266 | { | ||
267 | mu_error ("cannot create TLS stream: %s", | ||
268 | mu_strerror (status)); | ||
269 | return 0; | ||
270 | } | ||
271 | tcp = tlsstream; | ||
272 | } | ||
273 | #endif | ||
274 | mu_smtp_set_carrier (smtp, tcp); | ||
275 | status = smtp_error_handler (mu_smtp_open (smtp)); | ||
276 | } | ||
277 | else | ||
278 | { | ||
279 | mu_smtp_destroy (&smtp); | ||
280 | smtp = NULL; | ||
281 | } | ||
282 | } | ||
283 | |||
284 | if (status) | ||
285 | mu_error ("Failed to create smtp: %s", mu_strerror (status)); | ||
286 | else | ||
287 | { | ||
288 | connect_argc = argc; | ||
289 | connect_argv = mu_calloc (argc, sizeof (*connect_argv)); | ||
290 | for (i = 0; i < argc; i++) | ||
291 | connect_argv[i] = mu_strdup (argv[i]); | ||
292 | connect_argv[i] = NULL; | ||
293 | port = n; | ||
294 | smtp_session_status = smtp_session_connected; | ||
295 | |||
296 | smtp_prompt_env (); | ||
297 | } | ||
298 | |||
299 | /* Provide a default URL. Authentication functions require it, see comment | ||
300 | in smtp_auth.c:119. */ | ||
301 | mu_smtp_set_param (smtp, MU_SMTP_PARAM_URL, "smtp://"); | ||
302 | |||
303 | return status; | ||
304 | } | ||
305 | |||
306 | static int | ||
307 | com_capa (int argc, char **argv) | ||
308 | { | ||
309 | mu_iterator_t iterator = NULL; | ||
310 | int status = 0; | ||
311 | int i = 1; | ||
312 | |||
313 | if (i < argc) | ||
314 | { | ||
315 | for (; i < argc; i++) | ||
316 | { | ||
317 | const char *elt; | ||
318 | int rc = mu_smtp_capa_test (smtp, argv[i], &elt); | ||
319 | switch (rc) | ||
320 | { | ||
321 | case 0: | ||
322 | if (*elt) | ||
323 | mu_printf ("%s: %s\n", argv[i], elt); | ||
324 | else | ||
325 | mu_printf ("%s is set\n", argv[i]); | ||
326 | break; | ||
327 | |||
328 | case MU_ERR_NOENT: | ||
329 | mu_printf ("%s is not set\n", argv[i]); | ||
330 | break; | ||
331 | |||
332 | default: | ||
333 | return smtp_error_handler (rc); | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | else | ||
338 | { | ||
339 | status = mu_smtp_capa_iterator (smtp, &iterator); | ||
340 | |||
341 | if (status == 0) | ||
342 | { | ||
343 | for (mu_iterator_first (iterator); | ||
344 | !mu_iterator_is_done (iterator); mu_iterator_next (iterator)) | ||
345 | { | ||
346 | char *capa = NULL; | ||
347 | mu_iterator_current (iterator, (void **) &capa); | ||
348 | mu_printf ("CAPA: %s\n", capa ? capa : ""); | ||
349 | } | ||
350 | mu_iterator_destroy (&iterator); | ||
351 | } | ||
352 | } | ||
353 | return status; | ||
354 | } | ||
355 | |||
356 | static int | ||
357 | com_ehlo (int argc, char **argv) | ||
358 | { | ||
359 | if (argc == 1) | ||
360 | { | ||
361 | if (mu_smtp_test_param (smtp, MU_SMTP_PARAM_DOMAIN)) | ||
362 | { | ||
363 | mu_error (_("no domain set")); | ||
364 | return 0; | ||
365 | } | ||
366 | } | ||
367 | else | ||
368 | mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN, argv[1]); | ||
369 | return com_capa (1, argv); | ||
370 | } | ||
371 | |||
372 | static int | ||
373 | com_rset (int argc, char **argv) | ||
374 | { | ||
375 | return smtp_error_handler (mu_smtp_rset (smtp)); | ||
376 | } | ||
377 | |||
378 | static int | ||
379 | com_quit (int argc, char **argv) | ||
380 | { | ||
381 | int status = 0; | ||
382 | if (smtp) | ||
383 | { | ||
384 | if (smtp_error_handler (mu_smtp_quit (smtp)) == 0) | ||
385 | { | ||
386 | status = com_disconnect (0, NULL); | ||
387 | } | ||
388 | else | ||
389 | { | ||
390 | mu_printf ("Try 'exit' to leave %s\n", mu_program_name); | ||
391 | } | ||
392 | } | ||
393 | else | ||
394 | mu_printf ("Try 'exit' to leave %s\n", mu_program_name); | ||
395 | return status; | ||
396 | } | ||
397 | |||
398 | static int | ||
399 | com_from (int argc, char **argv) | ||
400 | { | ||
401 | if (argc == 1) | ||
402 | { | ||
403 | if (!sender) | ||
404 | { | ||
405 | mu_error (_("no sender address")); | ||
406 | return 0; | ||
407 | } | ||
408 | } | ||
409 | else | ||
410 | { | ||
411 | free (sender); | ||
412 | sender = mu_strdup (argv[1]); | ||
413 | } | ||
414 | return smtp_error_handler (mu_smtp_mail_basic (smtp, sender, NULL)); | ||
415 | } | ||
416 | |||
417 | static int | ||
418 | send_rcpt_to (void *item, void *data) | ||
419 | { | ||
420 | return smtp_error_handler (mu_smtp_rcpt_basic (smtp, (char*) item, NULL)); | ||
421 | } | ||
422 | |||
423 | static int | ||
424 | com_to (int argc, char **argv) | ||
425 | { | ||
426 | int rc; | ||
427 | |||
428 | if (argc == 1) | ||
429 | { | ||
430 | if (mu_list_is_empty (recipients)) | ||
431 | { | ||
432 | mu_error (_("no recipients")); | ||
433 | return 1; | ||
434 | } | ||
435 | mu_list_foreach (recipients, send_rcpt_to, NULL); | ||
436 | rc = 0; | ||
437 | } | ||
438 | else | ||
439 | { | ||
440 | if (!recipients) | ||
441 | mu_list_create (&recipients); | ||
442 | mu_list_set_destroy_item (recipients, mu_list_free_item); | ||
443 | rc = smtp_error_handler (mu_smtp_rcpt_basic (smtp, argv[1], NULL)); | ||
444 | if (rc == 0) | ||
445 | mu_list_append (recipients, mu_strdup (argv[1])); | ||
446 | } | ||
447 | return rc; | ||
448 | } | ||
449 | |||
450 | static int | ||
451 | edit (const char *file) | ||
452 | { | ||
453 | char *ed; | ||
454 | char *edv[3]; | ||
455 | int rc, status; | ||
456 | |||
457 | ed = getenv ("VISUAL"); | ||
458 | if (!ed) | ||
459 | { | ||
460 | ed = getenv ("EDITOR"); | ||
461 | if (!ed) | ||
462 | ed = "/bin/ed"; | ||
463 | } | ||
464 | |||
465 | edv[0] = ed; | ||
466 | edv[1] = (char*) file; | ||
467 | edv[2] = NULL; | ||
468 | |||
469 | rc = mu_spawnvp (edv[0], edv, &status); | ||
470 | if (rc) | ||
471 | mu_diag_funcall (MU_DIAG_ERROR, "mu_spawnvp", edv[0], rc); | ||
472 | return rc; | ||
473 | } | ||
474 | |||
475 | struct rcptout | ||
476 | { | ||
477 | mu_stream_t str; | ||
478 | int n; | ||
479 | }; | ||
480 | |||
481 | static int | ||
482 | print_rcpt (void *item, void *data) | ||
483 | { | ||
484 | struct rcptout *p = data; | ||
485 | if (p->n++) | ||
486 | mu_stream_write (p->str, ", ", 2, NULL); | ||
487 | mu_stream_printf (p->str, "%s", (char *)item); | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static int | ||
492 | edit_file (const char *fname, int inplace) | ||
493 | { | ||
494 | int rc; | ||
495 | |||
496 | if (fname && !inplace) | ||
497 | { | ||
498 | mu_stream_t istr, ostr; | ||
499 | |||
500 | rc = mu_file_stream_create (&istr, fname, MU_STREAM_READ|MU_STREAM_SEEK); | ||
501 | if (rc == 0) | ||
502 | { | ||
503 | char *tempfile = mu_tempname (NULL); | ||
504 | rc = mu_file_stream_create (&ostr, tempfile, | ||
505 | MU_STREAM_CREAT|MU_STREAM_WRITE); | ||
506 | if (rc) | ||
507 | { | ||
508 | free (tempfile); | ||
509 | mu_error (_("cannot create temporary file: %s"), | ||
510 | mu_strerror (rc)); | ||
511 | return -1; | ||
512 | } | ||
513 | rc = mu_stream_copy (ostr, istr, 0, NULL); | ||
514 | if (rc) | ||
515 | { | ||
516 | unlink (tempfile); | ||
517 | free (tempfile); | ||
518 | mu_error (_("error copying to temporary file: %s"), | ||
519 | mu_strerror (rc)); | ||
520 | return -1; | ||
521 | } | ||
522 | mu_stream_unref (ostr); | ||
523 | free (msgfile); | ||
524 | msgfile = tempfile; | ||
525 | temp_msgfile = 1; | ||
526 | } | ||
527 | else if (rc != ENOENT) | ||
528 | { | ||
529 | mu_diag_funcall (MU_DIAG_ERROR, "mu_file_stream_create", fname, rc); | ||
530 | return 1; | ||
531 | } | ||
532 | mu_stream_unref (istr); | ||
533 | } | ||
534 | else if (!fname) | ||
535 | { | ||
536 | struct rcptout rcptout; | ||
537 | |||
538 | if (temp_msgfile) | ||
539 | unlink (msgfile); | ||
540 | free (msgfile); | ||
541 | msgfile = mu_tempname (NULL); | ||
542 | temp_msgfile = 1; | ||
543 | |||
544 | rc = mu_file_stream_create (&rcptout.str, msgfile, | ||
545 | MU_STREAM_CREAT|MU_STREAM_WRITE); | ||
546 | if (rc) | ||
547 | { | ||
548 | mu_error (_("cannot open temporary file for writing: %s"), | ||
549 | mu_strerror (rc)); | ||
550 | return 1; | ||
551 | } | ||
552 | rcptout.n = 0; | ||
553 | if (sender) | ||
554 | mu_stream_printf (rcptout.str, "From: %s\n", sender); | ||
555 | else | ||
556 | mu_stream_printf (rcptout.str, "From: \n"); | ||
557 | mu_stream_printf (rcptout.str, "To: "); | ||
558 | mu_list_foreach (recipients, print_rcpt, &rcptout); | ||
559 | mu_stream_write (rcptout.str, "\n", 1, NULL); | ||
560 | mu_stream_printf (rcptout.str, "Subject: \n\n"); | ||
561 | mu_stream_unref (rcptout.str); | ||
562 | } | ||
563 | else | ||
564 | { | ||
565 | free (msgfile); | ||
566 | msgfile = mu_strdup (fname); | ||
567 | temp_msgfile = 0; | ||
568 | } | ||
569 | |||
570 | do | ||
571 | { | ||
572 | if (edit (msgfile)) | ||
573 | return 1; | ||
574 | } | ||
575 | while ((rc = mu_getans ("seqSEQ", _("What now: [s]end, [e]dit, [q]uit"))) | ||
576 | == 'e' || rc == 'E'); | ||
577 | |||
578 | return rc == 'q' || rc == 'Q'; | ||
579 | } | ||
580 | |||
581 | static int | ||
582 | com_send (int argc, char **argv) | ||
583 | { | ||
584 | int rc; | ||
585 | mu_stream_t instr; | ||
586 | |||
587 | if (argc == 1) | ||
588 | { | ||
589 | if (msgfile) | ||
590 | { | ||
591 | switch (mu_getans ("rReEdD", | ||
592 | _("Previous message exists. " | ||
593 | "What now: [r]euse, [e]dit, " | ||
594 | "[u]se as a template or\n" | ||
595 | "[d]rop and start from scratch"))) | ||
596 | { | ||
597 | case 'r': | ||
598 | case 'R': | ||
599 | rc = 0; | ||
600 | break; | ||
601 | |||
602 | case 'e': | ||
603 | case 'E': | ||
604 | rc = edit_file (msgfile, 1); | ||
605 | break; | ||
606 | |||
607 | case 'd': | ||
608 | case 'D': | ||
609 | if (temp_msgfile) | ||
610 | unlink (msgfile); | ||
611 | free (msgfile); | ||
612 | msgfile = NULL; | ||
613 | temp_msgfile = 0; | ||
614 | rc = edit_file (NULL, 0); | ||
615 | break; | ||
616 | |||
617 | case 'u': | ||
618 | case 'U': | ||
619 | rc = edit_file (msgfile, 0); | ||
620 | } | ||
621 | } | ||
622 | else | ||
623 | rc = edit_file (NULL, 0); | ||
624 | if (rc) | ||
625 | return 0; | ||
626 | } | ||
627 | else | ||
628 | { | ||
629 | if (temp_msgfile) | ||
630 | unlink (msgfile); | ||
631 | free (msgfile); | ||
632 | msgfile = NULL; | ||
633 | temp_msgfile = 0; | ||
634 | msgfile = mu_strdup (argv[1]); | ||
635 | } | ||
636 | |||
637 | rc = mu_file_stream_create (&instr, msgfile, MU_STREAM_READ|MU_STREAM_SEEK); | ||
638 | if (rc) | ||
639 | { | ||
640 | mu_diag_funcall (MU_DIAG_ERROR, "mu_file_stream_create", msgfile, rc); | ||
641 | return 1; | ||
642 | } | ||
643 | |||
644 | rc = mu_smtp_send_stream (smtp, instr); | ||
645 | mu_stream_unref (instr); | ||
646 | |||
647 | if (rc) | ||
648 | smtp_error_handler (rc); | ||
649 | else | ||
650 | rc = smtp_error_handler (mu_smtp_dot (smtp)); | ||
651 | |||
652 | return rc; | ||
653 | } | ||
654 | |||
655 | static int | ||
656 | com_starttls (int argc, char **argv) | ||
657 | { | ||
658 | if (mu_smtp_capa_test (smtp, "STARTTLS", NULL) == 0) | ||
659 | return smtp_error_handler (mu_smtp_starttls (smtp)); | ||
660 | else | ||
661 | mu_error (_("remote party does not offer STARTTLS")); | ||
662 | return 1; | ||
663 | } | ||
664 | |||
665 | static int | ||
666 | com_auth (int argc, char **argv) | ||
667 | { | ||
668 | int rc, i; | ||
669 | |||
670 | rc = mu_smtp_clear_auth_mech (smtp); | ||
671 | if (rc) | ||
672 | { | ||
673 | mu_diag_funcall (MU_DIAG_ERROR, "mu_smtp_clear_auth_mech", NULL, rc); | ||
674 | return MU_ERR_FAILURE; | ||
675 | } | ||
676 | for (i = 1; i < argc; i++) | ||
677 | if ((rc = mu_smtp_add_auth_mech (smtp, argv[1]))) | ||
678 | { | ||
679 | mu_diag_funcall (MU_DIAG_ERROR, "mu_smtp_add_auth_mech", NULL, rc); | ||
680 | return MU_ERR_FAILURE; | ||
681 | } | ||
682 | |||
683 | rc = mu_smtp_auth (smtp); | ||
684 | |||
685 | switch (rc) | ||
686 | { | ||
687 | case 0: | ||
688 | smtp_session_status = smtp_session_logged_in; | ||
689 | break; | ||
690 | |||
691 | case ENOSYS: | ||
692 | mu_error (_("authentication not implemented")); | ||
693 | break; | ||
694 | |||
695 | case MU_ERR_NOENT: | ||
696 | mu_error (_("no suitable authentication mechanism found")); | ||
697 | break; | ||
698 | |||
699 | default: | ||
700 | smtp_error_handler (rc); | ||
701 | return rc; | ||
702 | } | ||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | static struct mu_kwd paramtab[] = { | ||
707 | { "domain", MU_SMTP_PARAM_DOMAIN }, | ||
708 | { "username", MU_SMTP_PARAM_USERNAME }, | ||
709 | { "password", MU_SMTP_PARAM_PASSWORD }, | ||
710 | { "service", MU_SMTP_PARAM_SERVICE }, | ||
711 | { "realm", MU_SMTP_PARAM_REALM }, | ||
712 | { "host", MU_SMTP_PARAM_HOST }, | ||
713 | { "url", MU_SMTP_PARAM_URL }, | ||
714 | { NULL } | ||
715 | }; | ||
716 | |||
717 | static int | ||
718 | get_param (int param, char *prompt, char **retval) | ||
719 | { | ||
720 | int rc; | ||
721 | |||
722 | if (param == MU_SMTP_PARAM_PASSWORD) | ||
723 | { | ||
724 | rc = mu_getpass (mu_strin, mu_strout, prompt, retval); | ||
725 | if (rc) | ||
726 | mu_diag_funcall (MU_DIAG_ERROR, "mu_getpass", NULL, rc); | ||
727 | } | ||
728 | else | ||
729 | { | ||
730 | char *buf = NULL; | ||
731 | size_t size = 0; | ||
732 | rc = mu_stream_write (mu_strout, prompt, strlen (prompt), NULL); | ||
733 | if (rc) | ||
734 | return rc; | ||
735 | mu_stream_flush (mu_strout); | ||
736 | rc = mu_stream_getline (mu_strin, &buf, &size, NULL); | ||
737 | if (rc == 0) | ||
738 | { | ||
739 | mu_rtrim_cset (buf, "\n"); | ||
740 | *retval = buf; | ||
741 | } | ||
742 | } | ||
743 | return rc; | ||
744 | } | ||
745 | |||
746 | static int | ||
747 | com_set (int argc, char **argv) | ||
748 | { | ||
749 | int param, i, rc; | ||
750 | |||
751 | for (i = 1; i < argc; i += 2) | ||
752 | { | ||
753 | if (mu_kwd_xlat_name (paramtab, argv[i], ¶m)) | ||
754 | { | ||
755 | mu_error (_("unrecognized parameter: %s"), argv[i]); | ||
756 | continue; | ||
757 | } | ||
758 | if (i + 1 < argc) | ||
759 | { | ||
760 | rc = mu_smtp_set_param (smtp, param, argv[i+1]); | ||
761 | if (rc) | ||
762 | mu_diag_funcall (MU_DIAG_ERROR, "mu_smtp_set_param", argv[i], rc); | ||
763 | } | ||
764 | else | ||
765 | { | ||
766 | char *prompt, *value; | ||
767 | mu_asprintf (&prompt, "%s: ", argv[i]); | ||
768 | rc = get_param (param, prompt, &value); | ||
769 | free (prompt); | ||
770 | if (rc) | ||
771 | mu_error (_("error reading value: %s"), mu_strerror (rc)); | ||
772 | else | ||
773 | { | ||
774 | rc = mu_smtp_set_param (smtp, param, value); | ||
775 | if (param == MU_SMTP_PARAM_PASSWORD) | ||
776 | memset (value, 0, strlen (value)); | ||
777 | if (rc) | ||
778 | mu_diag_funcall (MU_DIAG_ERROR, "mu_smtp_set_param", argv[i], | ||
779 | rc); | ||
780 | free (value); | ||
781 | } | ||
782 | } | ||
783 | } | ||
784 | return 0; | ||
785 | } | ||
786 | |||
787 | static int | ||
788 | com_clear (int argc, char **argv) | ||
789 | { | ||
790 | int param, i, rc; | ||
791 | |||
792 | if (argc > 1) | ||
793 | { | ||
794 | for (i = 1; i < argc; i++) | ||
795 | { | ||
796 | if (mu_kwd_xlat_name (paramtab, argv[i], ¶m)) | ||
797 | { | ||
798 | mu_error (_("unrecognized parameter: %s"), argv[i]); | ||
799 | continue; | ||
800 | } | ||
801 | rc = mu_smtp_set_param (smtp, param, NULL); | ||
802 | if (rc) | ||
803 | mu_diag_funcall (MU_DIAG_ERROR, "mu_smtp_set_param", argv[i], rc); | ||
804 | } | ||
805 | } | ||
806 | else | ||
807 | { | ||
808 | for (i = 0; paramtab[i].name; i++) | ||
809 | { | ||
810 | rc = mu_smtp_set_param (smtp, paramtab[i].tok, NULL); | ||
811 | if (rc) | ||
812 | mu_diag_funcall (MU_DIAG_ERROR, "mu_smtp_set_param", | ||
813 | paramtab[i].name, rc); | ||
814 | } | ||
815 | } | ||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | static int | ||
820 | com_list_param (int argc, char **argv) | ||
821 | { | ||
822 | int param, i, rc; | ||
823 | const char *value; | ||
824 | |||
825 | if (argc > 1) | ||
826 | { | ||
827 | for (i = 1; i < argc; i++) | ||
828 | { | ||
829 | if (mu_kwd_xlat_name (paramtab, argv[i], ¶m)) | ||
830 | { | ||
831 | mu_error (_("unrecognized parameter: %s"), argv[i]); | ||
832 | continue; | ||
833 | } | ||
834 | rc = mu_smtp_get_param (smtp, param, &value); | ||
835 | if (rc) | ||
836 | mu_diag_funcall (MU_DIAG_ERROR, "mu_smtp_set_param", argv[i], rc); | ||
837 | else if (value) | ||
838 | mu_printf ("%s = %s\n", argv[i], value); | ||
839 | else | ||
840 | mu_printf (_("%s not set\n"), argv[i]); | ||
841 | } | ||
842 | } | ||
843 | else | ||
844 | { | ||
845 | for (i = 0; paramtab[i].name; i++) | ||
846 | { | ||
847 | rc = mu_smtp_get_param (smtp, paramtab[i].tok, &value); | ||
848 | if (rc) | ||
849 | mu_diag_funcall (MU_DIAG_ERROR, "mu_smtp_set_param", | ||
850 | paramtab[i].name, rc); | ||
851 | else if (value) | ||
852 | mu_printf ("%s = %s\n", paramtab[i].name, value); | ||
853 | else | ||
854 | mu_printf (_("%s not set\n"), paramtab[i].name); | ||
855 | } | ||
856 | } | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static int | ||
861 | com_smtp_command (int argc, char **argv) | ||
862 | { | ||
863 | int rc; | ||
864 | mu_iterator_t itr; | ||
865 | |||
866 | rc = mu_smtp_cmd (smtp, argc - 1, argv + 1); | ||
867 | smtp_error_handler (rc); | ||
868 | if (rc) | ||
869 | return rc; | ||
870 | rc = mu_smtp_get_reply_iterator (smtp, &itr); | ||
871 | if (rc) | ||
872 | { | ||
873 | mu_diag_funcall (MU_DIAG_ERROR, "mu_smtp_get_reply_iterator", NULL, rc); | ||
874 | return 1; | ||
875 | } | ||
876 | |||
877 | for (mu_iterator_first (itr); | ||
878 | !mu_iterator_is_done (itr); mu_iterator_next (itr)) | ||
879 | { | ||
880 | char *str = NULL; | ||
881 | mu_iterator_current (itr, (void **) &str); | ||
882 | mu_printf ("%s\n", str); | ||
883 | } | ||
884 | mu_iterator_destroy (&itr); | ||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | struct mutool_command smtp_comtab[] = { | ||
889 | { "connect", 1, 4, 0, com_connect, | ||
890 | /* TRANSLATORS: -tls is a keyword. */ | ||
891 | N_("[-tls] HOSTNAME [PORT]"), | ||
892 | N_("open connection") }, | ||
893 | |||
894 | { "set", 2, -1, 0, com_set, | ||
895 | N_("PARAM [ARG...]"), | ||
896 | N_("Set connection parameter") }, | ||
897 | { "clear", 1, -1, 0, com_clear, | ||
898 | N_("[PARAM...]"), | ||
899 | N_("Clear connection parameters") }, | ||
900 | |||
901 | { "list", 1, -1, 0, com_list_param, | ||
902 | N_("[PARAM...]"), | ||
903 | N_("List connection parameters") }, | ||
904 | |||
905 | { "auth", 2, -1, 0, com_auth, | ||
906 | N_("MECH [MECH...]"), | ||
907 | N_("Authenticate") }, | ||
908 | |||
909 | { "ehlo", 1, 2, 0, com_ehlo, | ||
910 | N_("[DOMAIN]"), | ||
911 | N_("Greet the server") }, | ||
912 | |||
913 | { "capa", 1, -1, 0, com_capa, | ||
914 | N_("[NAME...]"), | ||
915 | N_("list server capabilities") }, | ||
916 | |||
917 | { "starttls", 1, 1, 0, com_starttls, | ||
918 | NULL, | ||
919 | N_("initiate encrypted connection") }, | ||
920 | |||
921 | { "rset", 1, 1, 0, com_rset, | ||
922 | NULL, | ||
923 | N_("reset the session state") }, | ||
924 | |||
925 | { "from", 1, 2, 0, com_from, | ||
926 | N_("[EMAIL]"), | ||
927 | N_("set sender email") }, | ||
928 | |||
929 | { "to", 1, 2, 0, com_to, | ||
930 | N_("[EMAIL]"), | ||
931 | N_("set recipient email") }, | ||
932 | |||
933 | { "send", 1, 2, 0, com_send, | ||
934 | N_("[FILE]"), | ||
935 | N_("send message") }, | ||
936 | |||
937 | { "smtp", 2, -1, 0, com_smtp_command, | ||
938 | N_("COMMAND [ARGS...]"), | ||
939 | N_("send an arbitrary COMMAND") }, | ||
940 | |||
941 | { "quit", 1, 1, 0, com_quit, | ||
942 | NULL, | ||
943 | N_("quit the session") }, | ||
944 | |||
945 | { "verbose", 1, 4, 0, com_verbose, | ||
946 | "[on|off|mask|unmask] [secure [payload]]", | ||
947 | N_("control the protocol tracing") }, | ||
948 | |||
949 | { NULL } | ||
950 | }; | ||
951 | |||
952 | int | ||
953 | mutool_smtp (int argc, char **argv) | ||
954 | { | ||
955 | int index; | ||
956 | |||
957 | mu_registrar_record (mu_smtp_record); | ||
958 | mu_registrar_record (mu_smtps_record); | ||
959 | |||
960 | if (argp_parse (&smtp_argp, argc, argv, 0, &index, NULL)) | ||
961 | return 1; | ||
962 | |||
963 | argc -= index; | ||
964 | |||
965 | if (argc) | ||
966 | { | ||
967 | mu_error (_("bad arguments")); | ||
968 | return 1; | ||
969 | } | ||
970 | |||
971 | mutool_shell_prompt = mu_strdup ("smtp> "); | ||
972 | smtp_prompt_env (); | ||
973 | mutool_shell ("smtp", smtp_comtab); | ||
974 | |||
975 | if (temp_msgfile) | ||
976 | unlink (msgfile); | ||
977 | |||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | /* | ||
982 | MU Setup: smtp | ||
983 | mu-handler: mutool_smtp | ||
984 | mu-docstring: smtp_docstring | ||
985 | End MU Setup: | ||
986 | */ |
mu/util.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010-2012 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils 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 | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #if defined(HAVE_CONFIG_H) | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | |||
21 | #include <stdlib.h> | ||
22 | #include <arpa/inet.h> | ||
23 | #include <mailutils/mailutils.h> | ||
24 | #include "mu.h" | ||
25 | |||
26 | int | ||
27 | port_from_sa (struct mu_sockaddr *sa) | ||
28 | { | ||
29 | switch (sa->addr->sa_family) | ||
30 | { | ||
31 | case AF_INET: | ||
32 | return ntohs (((struct sockaddr_in *)sa->addr)->sin_port); | ||
33 | |||
34 | #ifdef MAILUTILS_IPV6 | ||
35 | case AF_INET6: | ||
36 | return ntohs (((struct sockaddr_in6 *)sa->addr)->sin6_port); | ||
37 | #endif | ||
38 | } | ||
39 | return 0; | ||
40 | } | ||
41 |
-
Please register or sign in to post a comment