Commit f2279f27 f2279f27831f79d036ceab51e093250546f8b9d1 by Sergey Poznyakoff

Convert comsat to mu_cli

1 parent e3840467
...@@ -31,7 +31,7 @@ biff.rc.h: $(top_srcdir)/comsat/biff.rc ...@@ -31,7 +31,7 @@ biff.rc.h: $(top_srcdir)/comsat/biff.rc
31 $(top_srcdir)/comsat/biff.rc > biff.rc.h 31 $(top_srcdir)/comsat/biff.rc > biff.rc.h
32 32
33 comsatd_LDADD = \ 33 comsatd_LDADD = \
34 ${MU_APP_LIBRARIES}\ 34 ${MU_APP_NEW_LIBRARIES}\
35 ${MU_LIB_MBOX}\ 35 ${MU_LIB_MBOX}\
36 ${MU_LIB_IMAP}\ 36 ${MU_LIB_IMAP}\
37 ${MU_LIB_POP}\ 37 ${MU_LIB_POP}\
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
18 #include "comsat.h" 18 #include "comsat.h"
19 #define MU_CFG_COMPATIBILITY /* This source uses deprecated cfg interfaces */ 19 #define MU_CFG_COMPATIBILITY /* This source uses deprecated cfg interfaces */
20 #include "mailutils/libcfg.h" 20 #include "mailutils/libcfg.h"
21 #include "mailutils/libargp.h" 21 #include "mailutils/cli.h"
22 22
23 #ifndef PATH_DEV 23 #ifndef PATH_DEV
24 # define PATH_DEV "/dev" 24 # define PATH_DEV "/dev"
...@@ -59,44 +59,62 @@ typedef struct utmp UTMP; ...@@ -59,44 +59,62 @@ typedef struct utmp UTMP;
59 #define MAX_TTY_SIZE (sizeof (PATH_TTY_PFX) + sizeof (((UTMP*)0)->ut_line)) 59 #define MAX_TTY_SIZE (sizeof (PATH_TTY_PFX) + sizeof (((UTMP*)0)->ut_line))
60 60
61 const char *program_version = "comsatd (" PACKAGE_STRING ")"; 61 const char *program_version = "comsatd (" PACKAGE_STRING ")";
62 static char doc[] = N_("GNU comsatd -- notify users about incoming mail");
63 static char args_doc[] = N_("\n--test MBOX-URL MSG-QID");
64 62
65 #define OPT_FOREGROUND 256 63 int test_mode;
64 char *biffrc = BIFF_RC;
65 mu_m_server_t server;
66 66
67 static struct argp_option options[] = 67 static void
68 set_inetd_mode (struct mu_parseopt *po, struct mu_option *opt,
69 char const *arg)
68 { 70 {
69 { "test", 't', NULL, 0, N_("run in test mode"), 0 }, 71 mu_m_server_set_mode (server, MODE_INTERACTIVE);
70 { "foreground", OPT_FOREGROUND, 0, 0, N_("remain in foreground"), 0}, 72 }
71 { "inetd", 'i', 0, 0, N_("run in inetd mode"), 0 },
72 { "daemon", 'd', N_("NUMBER"), OPTION_ARG_OPTIONAL,
73 N_("runs in daemon mode with a maximum of NUMBER children"), 0 },
74 { "file", 'f', N_("FILE"), 0,
75 N_("read FILE instead of .biffrc"), 0 },
76 { NULL, 0, NULL, 0, NULL, 0 }
77 };
78 73
79 static error_t comsatd_parse_opt (int key, char *arg, 74 static void
80 struct argp_state *state); 75 set_daemon_mode (struct mu_parseopt *po, struct mu_option *opt,
76 char const *arg)
77 {
78 mu_m_server_set_mode (server, MODE_DAEMON);
79 if (arg)
80 {
81 size_t max_children;
82 char *errmsg;
83 int rc = mu_str_to_c (arg, mu_c_size, &max_children, &errmsg);
84 if (rc)
85 {
86 mu_parseopt_error (po, _("%s: bad argument"), arg);
87 exit (po->po_exit_error);
88 }
89 mu_m_server_set_max_children (server, max_children);
90 }
91 }
81 92
82 static struct argp argp = { 93 static void
83 options, 94 set_foreground (struct mu_parseopt *po, struct mu_option *opt,
84 comsatd_parse_opt, 95 char const *arg)
85 args_doc, 96 {
86 doc, 97 mu_m_server_set_foreground (server, 1);
87 NULL, 98 }
88 NULL, NULL
89 };
90 99
91 static const char *comsat_argp_capa[] = { 100 static struct mu_option comsat_options[] = {
92 "mailutils", 101 { "test", 't', NULL, MU_OPTION_DEFAULT,
93 "common", 102 N_("run in test mode"),
94 "debug", 103 mu_c_bool, &test_mode },
95 "logging", 104 { "foreground", 0, NULL, MU_OPTION_DEFAULT,
96 "mailbox", 105 N_("remain in foreground"),
97 "locking", 106 mu_c_bool, NULL, set_foreground },
98 NULL 107 { "inetd", 'i', NULL, MU_OPTION_DEFAULT,
99 }; 108 N_("run in inetd mode"),
109 mu_c_bool, NULL, set_inetd_mode },
110 { "daemon", 'd', N_("NUMBER"), MU_OPTION_ARG_OPTIONAL,
111 N_("runs in daemon mode with a maximum of NUMBER children"),
112 mu_c_string, NULL, set_daemon_mode },
113 { "file", 'f', N_("FILE"), MU_OPTION_DEFAULT,
114 N_("read FILE instead of .biffrc"),
115 mu_c_string, &biffrc },
116 MU_OPTION_END
117 }, *options[] = { comsat_options, NULL };
100 118
101 #define SUCCESS 0 119 #define SUCCESS 0
102 #define NOT_HERE 1 120 #define NOT_HERE 1
...@@ -107,7 +125,6 @@ char *hostname; ...@@ -107,7 +125,6 @@ char *hostname;
107 const char *username; 125 const char *username;
108 int require_tty; 126 int require_tty;
109 int biffrc_errors = BIFFRC_ERRORS_TO_TTY | BIFFRC_ERRORS_TO_ERR; 127 int biffrc_errors = BIFFRC_ERRORS_TO_TTY | BIFFRC_ERRORS_TO_ERR;
110 mu_m_server_t server;
111 128
112 static void comsat_init (void); 129 static void comsat_init (void);
113 static int comsat_main (int fd); 130 static int comsat_main (int fd);
...@@ -118,9 +135,6 @@ static char *mailbox_path (const char *user); ...@@ -118,9 +135,6 @@ static char *mailbox_path (const char *user);
118 static int change_user (const char *user); 135 static int change_user (const char *user);
119 136
120 static int reload = 0; 137 static int reload = 0;
121 int test_mode;
122 char *biffrc = BIFF_RC;
123
124 static int 138 static int
125 biffrc_error_ctl (mu_config_value_t *val, int flag) 139 biffrc_error_ctl (mu_config_value_t *val, int flag)
126 { 140 {
...@@ -178,48 +192,23 @@ struct mu_cfg_param comsat_cfg_param[] = { ...@@ -178,48 +192,23 @@ struct mu_cfg_param comsat_cfg_param[] = {
178 { NULL } 192 { NULL }
179 }; 193 };
180 194
181 static error_t 195 static char const *alt_args[] = { N_("--test MBOX-URL MSG-QID"), NULL };
182 comsatd_parse_opt (int key, char *arg, struct argp_state *state)
183 {
184 static mu_list_t lst;
185
186 switch (key)
187 {
188 case 'd':
189 mu_argp_node_list_new (lst, "mode", "daemon");
190 if (arg)
191 mu_argp_node_list_new (lst, "max-children", arg);
192 break;
193
194 case 'f':
195 biffrc = arg;
196 break;
197
198 case 'i':
199 mu_argp_node_list_new (lst, "mode", "inetd");
200 break;
201
202 case OPT_FOREGROUND:
203 mu_argp_node_list_new (lst, "foreground", "yes");
204 break;
205 196
206 case 't': 197 static struct mu_cli_setup cli = {
207 test_mode = 1; 198 options,
208 break; 199 comsat_cfg_param,
209 200 N_("GNU comsatd -- notify users about incoming mail"),
210 case ARGP_KEY_INIT: 201 "",
211 mu_argp_node_list_init (&lst); 202 alt_args,
212 break; 203 };
213
214 case ARGP_KEY_FINI:
215 mu_argp_node_list_finish (lst, NULL, NULL);
216 break;
217 204
218 default: 205 static char *capa[] = {
219 return ARGP_ERR_UNKNOWN; 206 "debug",
220 } 207 "logging",
221 return 0; 208 "mailbox",
222 } 209 "locking",
210 NULL
211 };
223 212
224 static RETSIGTYPE 213 static RETSIGTYPE
225 sig_hup (int sig) 214 sig_hup (int sig)
...@@ -558,12 +547,11 @@ int ...@@ -558,12 +547,11 @@ int
558 main (int argc, char **argv) 547 main (int argc, char **argv)
559 { 548 {
560 int c; 549 int c;
561 int ind; 550 char **save_argv;
562 551
563 /* Native Language Support */ 552 /* Native Language Support */
564 MU_APP_INIT_NLS (); 553 MU_APP_INIT_NLS ();
565 554
566 mu_argp_init (NULL, NULL);
567 comsat_init (); 555 comsat_init ();
568 mu_acl_cfg_init (); 556 mu_acl_cfg_init ();
569 mu_m_server_create (&server, program_version); 557 mu_m_server_create (&server, program_version);
...@@ -579,18 +567,15 @@ main (int argc, char **argv) ...@@ -579,18 +567,15 @@ main (int argc, char **argv)
579 /* FIXME: timeout is not needed. How to disable it? */ 567 /* FIXME: timeout is not needed. How to disable it? */
580 mu_log_syslog = 1; 568 mu_log_syslog = 1;
581 569
582 if (mu_app_init (&argp, comsat_argp_capa, comsat_cfg_param, argc, argv, 0, 570 save_argv = argv;
583 &ind, server)) 571
584 exit (EXIT_FAILURE); 572 mu_cli (argc, argv, &cli, capa, NULL, &argc, &argv);
585 573
586 if (test_mode) 574 if (test_mode)
587 { 575 {
588 struct passwd *pw; 576 struct passwd *pw;
589 char *user; 577 char *user;
590 578
591 argc -= ind;
592 argv += ind;
593
594 mu_stdstream_strerr_setup (MU_STRERR_STDERR); 579 mu_stdstream_strerr_setup (MU_STRERR_STDERR);
595 biffrc_errors = BIFFRC_ERRORS_TO_ERR; 580 biffrc_errors = BIFFRC_ERRORS_TO_ERR;
596 if (argc < 2 || argc > 2) 581 if (argc < 2 || argc > 2)
...@@ -630,7 +615,7 @@ main (int argc, char **argv) ...@@ -630,7 +615,7 @@ main (int argc, char **argv)
630 615
631 if (mu_m_server_mode (server) == MODE_DAEMON) 616 if (mu_m_server_mode (server) == MODE_DAEMON)
632 { 617 {
633 if (argv[0][0] != '/') 618 if (save_argv[0][0] != '/')
634 mu_diag_output (MU_DIAG_NOTICE, 619 mu_diag_output (MU_DIAG_NOTICE,
635 _("program name is not absolute; reloading will not " 620 _("program name is not absolute; reloading will not "
636 "be possible")); 621 "be possible"));
...@@ -651,7 +636,7 @@ main (int argc, char **argv) ...@@ -651,7 +636,7 @@ main (int argc, char **argv)
651 if (reload) 636 if (reload)
652 { 637 {
653 mu_diag_output (MU_DIAG_NOTICE, _("restarting")); 638 mu_diag_output (MU_DIAG_NOTICE, _("restarting"));
654 execvp (argv[0], argv); 639 execvp (save_argv[0], save_argv);
655 } 640 }
656 } 641 }
657 else 642 else
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
18 noinst_LTLIBRARIES = libcli.la 18 noinst_LTLIBRARIES = libcli.la
19 19
20 libcli_la_SOURCES = \ 20 libcli_la_SOURCES = \
21 acl.c\
21 capa.c\ 22 capa.c\
22 cli.c\ 23 cli.c\
23 stdcapa.c 24 stdcapa.c
......
1 /* This file is part of GNU Mailutils
2 Copyright (C) 2007-2012, 2014-2016 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 3, or (at
7 your option) any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 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
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include "mailutils/acl.h"
22 #include "mailutils/argcv.h"
23 #include "mailutils/cidr.h"
24 #include "mailutils/cfg.h"
25 #include "mailutils/errno.h"
26 #include "mailutils/nls.h"
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <sys/time.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36
37 #define ISSPACE(c) ((c)==' '||(c)=='\t')
38
39 #define SKIPWS(p) while (*(p) && ISSPACE (*(p))) (p)++;
40
41 static const char *
42 getword (mu_config_value_t *val, int *pn)
43 {
44 int n = (*pn)++;
45 mu_config_value_t *v;
46
47 if (n >= val->v.arg.c)
48 {
49 mu_error (_("not enough arguments"));
50 return NULL;
51 }
52 v = &val->v.arg.v[n];
53 if (mu_cfg_assert_value_type (v, MU_CFG_STRING))
54 return NULL;
55 return v->v.string;
56 }
57
58 static int
59 parsearg (mu_config_value_t *val, struct mu_cidr *cidr, char **prest)
60 {
61 const char *w;
62 int n = 0;
63 int rc;
64
65 if (mu_cfg_assert_value_type (val, MU_CFG_ARRAY))
66 return 1;
67
68 w = getword (val, &n);
69 if (!w)
70 return 1;
71 if (strcmp (w, "from") == 0) {
72 w = getword (val, &n);
73 if (!w)
74 return 1;
75 }
76
77 if (strcmp (w, "any") == 0)
78 cidr->len = 0;
79 else
80 {
81 rc = mu_cidr_from_string (cidr, w);
82 if (rc)
83 {
84 mu_error (_("invalid source CIDR: %s"), mu_strerror (rc));
85 return 1;
86 }
87 }
88
89 if (prest)
90 {
91 if (n == val->v.arg.c)
92 *prest = NULL;
93 else
94 {
95 size_t size = 0;
96 int i;
97 char *buf;
98
99 for (i = n; i < val->v.arg.c; i++)
100 {
101 if (mu_cfg_assert_value_type (&val->v.arg.v[i], MU_CFG_STRING))
102 return 1;
103 size += strlen (val->v.arg.v[i].v.string) + 1;
104 }
105
106 buf = malloc (size);
107 if (!buf)
108 {
109 mu_error ("%s", mu_strerror (errno));
110 return 1;
111 }
112
113 *prest = buf;
114 for (i = n; i < val->v.arg.c; i++)
115 {
116 if (i > n)
117 *buf++ = ' ';
118 strcpy (buf, val->v.arg.v[i].v.string);
119 buf += strlen (buf);
120 }
121 *buf = 0;
122 }
123 }
124 else if (n != val->v.arg.c)
125 {
126 mu_error (_("junk after IP address"));
127 return 1;
128 }
129 return 0;
130 }
131
132 static int
133 cb_allow (void *data, mu_config_value_t *val)
134 {
135 int rc;
136 mu_acl_t acl = *(mu_acl_t*)data;
137 struct mu_cidr cidr;
138
139 if (parsearg (val, &cidr, NULL))
140 return 1;
141 rc = mu_acl_append (acl, mu_acl_accept, NULL, &cidr);
142 if (rc)
143 mu_error (_("cannot append acl entry: %s"), mu_strerror (rc));
144 return rc;
145 }
146
147 static int
148 cb_deny (void *data, mu_config_value_t *val)
149 {
150 int rc;
151 mu_acl_t acl = *(mu_acl_t*)data;
152 struct mu_cidr cidr;
153
154 if (parsearg (val, &cidr, NULL))
155 return 1;
156 rc = mu_acl_append (acl, mu_acl_deny, NULL, &cidr);
157 if (rc)
158 mu_error (_("cannot append acl entry: %s"), mu_strerror (rc));
159 return rc;
160 }
161
162 static int
163 cb_log (void *data, mu_config_value_t *val)
164 {
165 int rc;
166 mu_acl_t acl = *(mu_acl_t*)data;
167 struct mu_cidr cidr;
168 char *rest;
169
170 if (parsearg (val, &cidr, &rest))
171 return 1;
172 rc = mu_acl_append (acl, mu_acl_log, rest, &cidr);
173 if (rc)
174 mu_error (_("cannot append acl entry: %s"), mu_strerror (rc));
175 return rc;
176 }
177
178 static int
179 cb_exec (void *data, mu_config_value_t *val)
180 {
181 int rc;
182 mu_acl_t acl = *(mu_acl_t*)data;
183 struct mu_cidr cidr;
184 char *rest;
185
186 if (parsearg (val, &cidr, &rest))
187 return 1;
188 rc = mu_acl_append (acl, mu_acl_exec, rest, &cidr);
189 if (rc)
190 mu_error (_("cannot append acl entry: %s"), mu_strerror (rc));
191 return rc;
192 }
193
194 static int
195 cb_ifexec (void *data, mu_config_value_t *val)
196 {
197 int rc;
198 mu_acl_t acl = *(mu_acl_t*)data;
199 struct mu_cidr cidr;
200 char *rest;
201
202 if (parsearg (val, &cidr, &rest))
203 return 1;
204 rc = mu_acl_append (acl, mu_acl_ifexec, rest, &cidr);
205 if (rc)
206 mu_error (_("cannot append acl entry: %s"), mu_strerror (rc));
207 return rc;
208 }
209
210 static struct mu_cfg_param acl_param[] = {
211 { "allow", mu_cfg_callback, NULL, 0, cb_allow,
212 N_("Allow connections from this IP address. Optional word `from' is "
213 "allowed between it and its argument. The same holds true for other "
214 "actions below."),
215 N_("addr: IP") },
216 { "deny", mu_cfg_callback, NULL, 0, cb_deny,
217 N_("Deny connections from this IP address."),
218 N_("addr: IP") },
219 { "log", mu_cfg_callback, NULL, 0, cb_log,
220 N_("Log connections from this IP address."),
221 N_("addr: IP") },
222 { "exec", mu_cfg_callback, NULL, 0, cb_exec,
223 N_("Execute supplied program if a connection from this IP address is "
224 "requested. Arguments are:\n"
225 " <addr: IP> <program: string>\n"
226 "Following macros are expanded in <program> before executing:\n"
227 " address - Source IP address\n"
228 " port - Source port number\n") },
229 { "ifexec", mu_cfg_callback, NULL, 0, cb_ifexec,
230 N_("If a connection from this IP address is requested, execute supplied "
231 "program and allow or deny the connection depending on its exit code. "
232 "See `exec' for a description of its arguments.") },
233 { NULL }
234 };
235
236 static int
237 acl_section_parser (enum mu_cfg_section_stage stage,
238 const mu_cfg_node_t *node,
239 const char *section_label, void **section_data,
240 void *call_data,
241 mu_cfg_tree_t *tree)
242 {
243 switch (stage)
244 {
245 case mu_cfg_section_start:
246 {
247 void *data = *section_data;
248 mu_acl_create ((mu_acl_t*)data);
249 }
250 break;
251
252 case mu_cfg_section_end:
253 break;
254 }
255 return 0;
256 }
257
258 void
259 mu_acl_cfg_init (void)
260 {
261 struct mu_cfg_section *section;
262 if (mu_create_canned_section ("acl", &section) == 0)
263 {
264 section->parser = acl_section_parser;
265 mu_cfg_section_add_params (section, acl_param);
266 }
267 }