Default per-utility config files are ~/.programrc. If you want to segregate
you mailutils configuration, make ~/.mailutils a directory, and put your config files in it (same name, minus the leading "."). Also organized all common options under the heading "Common options", moved the daemon and auth options before the common options, and implemented a --lock-flags option.
Showing
1 changed file
with
187 additions
and
73 deletions
... | @@ -18,23 +18,30 @@ | ... | @@ -18,23 +18,30 @@ |
18 | #ifdef HAVE_CONFIG_H | 18 | #ifdef HAVE_CONFIG_H |
19 | # include <config.h> | 19 | # include <config.h> |
20 | #endif | 20 | #endif |
21 | #include <stdlib.h> | 21 | |
22 | #include <getline.h> | ||
23 | #include <pwd.h> | ||
22 | #include <stdio.h> | 24 | #include <stdio.h> |
25 | #include <stdlib.h> | ||
23 | #include <string.h> | 26 | #include <string.h> |
24 | #include <syslog.h> | 27 | #include <syslog.h> |
28 | #include <unistd.h> | ||
29 | #include <xalloc.h> | ||
30 | |||
31 | #include <sys/types.h> | ||
32 | #include <sys/stat.h> | ||
33 | |||
25 | #ifdef HAVE_STRINGS_H | 34 | #ifdef HAVE_STRINGS_H |
26 | # include <strings.h> | 35 | # include <strings.h> |
27 | #endif | 36 | #endif |
28 | #include <sys/types.h> | 37 | |
29 | #include <sys/stat.h> | ||
30 | #include <unistd.h> | ||
31 | #include <pwd.h> | ||
32 | #include <xalloc.h> | ||
33 | #include <getline.h> | ||
34 | #include <mailutils/mutil.h> | ||
35 | #include <mailutils/error.h> | 38 | #include <mailutils/error.h> |
39 | #include <mailutils/mutil.h> | ||
40 | #include <mailutils/locker.h> | ||
41 | |||
36 | #include <argcv.h> | 42 | #include <argcv.h> |
37 | #include <mu_argp.h> | 43 | #include <mu_argp.h> |
44 | |||
38 | #ifdef HAVE_MYSQL | 45 | #ifdef HAVE_MYSQL |
39 | # include "../MySql/MySql.h" | 46 | # include "../MySql/MySql.h" |
40 | #endif | 47 | #endif |
... | @@ -49,21 +56,37 @@ | ... | @@ -49,21 +56,37 @@ |
49 | #define ARG_SQL_DB 8 | 56 | #define ARG_SQL_DB 8 |
50 | #define ARG_SQL_PORT 9 | 57 | #define ARG_SQL_PORT 9 |
51 | #define ARG_PAM_SERVICE 10 | 58 | #define ARG_PAM_SERVICE 10 |
59 | #define ARG_LOCK_FLAGS 11 | ||
60 | |||
61 | static struct argp_option mu_common_argp_options[] = | ||
62 | { | ||
63 | { NULL, 0, NULL, 0, "Common options:", 0}, | ||
64 | { NULL, 0, NULL, 0, NULL, 0 } | ||
65 | }; | ||
66 | |||
67 | /* Option to print the licence. */ | ||
68 | static struct argp_option mu_licence_argp_option[] = { | ||
69 | { "license", 'L', NULL, 0, "Print license and exit", -2 }, | ||
70 | { NULL, 0, NULL, 0, NULL, 0 } | ||
71 | }; | ||
52 | 72 | ||
53 | static struct argp_option mu_common_argp_option[] = { | 73 | /* Options used by programs that access mailboxes. */ |
74 | static struct argp_option mu_mailbox_argp_option[] = { | ||
54 | {"mail-spool", 'm', "URL", 0, | 75 | {"mail-spool", 'm', "URL", 0, |
55 | "use specified URL as a mailspool directory", 0}, | 76 | "Use specified URL as a mailspool directory", 0}, |
56 | { "license", 'L', NULL, 0, "print license and exit", 0 }, | 77 | {"lock-flags", ARG_LOCK_FLAGS, "FLAGS", 0, |
78 | "Default locker flags (E=external, R=retry, T=time, P=pid)", 0}, | ||
57 | { NULL, 0, NULL, 0, NULL, 0 } | 79 | { NULL, 0, NULL, 0, NULL, 0 } |
58 | }; | 80 | }; |
59 | 81 | ||
82 | /* Options used by programs that log to syslog. */ | ||
60 | static struct argp_option mu_logging_argp_option[] = { | 83 | static struct argp_option mu_logging_argp_option[] = { |
61 | {"log-facility", ARG_LOG_FACILITY, "FACILITY", 0, | 84 | {"log-facility", ARG_LOG_FACILITY, "FACILITY", 0, |
62 | "output logs to syslog FACILITY", 0}, | 85 | "Output logs to syslog FACILITY", 0}, |
63 | { NULL, 0, NULL, 0, NULL, 0 } | 86 | { NULL, 0, NULL, 0, NULL, 0 } |
64 | }; | 87 | }; |
65 | 88 | ||
66 | 89 | /* Options used by programs that use extended authentication mechanisms. */ | |
67 | static struct argp_option mu_auth_argp_option[] = { | 90 | static struct argp_option mu_auth_argp_option[] = { |
68 | #ifdef USE_LIBPAM | 91 | #ifdef USE_LIBPAM |
69 | { "pam-service", ARG_PAM_SERVICE, "STRING", 0, | 92 | { "pam-service", ARG_PAM_SERVICE, "STRING", 0, |
... | @@ -83,22 +106,23 @@ static struct argp_option mu_auth_argp_option[] = { | ... | @@ -83,22 +106,23 @@ static struct argp_option mu_auth_argp_option[] = { |
83 | {"sql-passwd", ARG_SQL_PASSWD, "STRING", 0, | 106 | {"sql-passwd", ARG_SQL_PASSWD, "STRING", 0, |
84 | "SQL connection password", 0}, | 107 | "SQL connection password", 0}, |
85 | {"sql-db", ARG_SQL_DB, "STRING", 0, | 108 | {"sql-db", ARG_SQL_DB, "STRING", 0, |
86 | "name of the database to connect to", 0}, | 109 | "Name of the database to connect to", 0}, |
87 | {"sql-port", ARG_SQL_PORT, "NUMBER", 0, | 110 | {"sql-port", ARG_SQL_PORT, "NUMBER", 0, |
88 | "port to use", 0}, | 111 | "Port to use", 0}, |
89 | #endif | 112 | #endif |
90 | { NULL, 0, NULL, 0, NULL, 0 } | 113 | { NULL, 0, NULL, 0, NULL, 0 } |
91 | }; | 114 | }; |
92 | 115 | ||
116 | /* Options used by programs that become daemons. */ | ||
93 | static struct argp_option mu_daemon_argp_option[] = { | 117 | static struct argp_option mu_daemon_argp_option[] = { |
94 | {"daemon", 'd', "NUMBER", OPTION_ARG_OPTIONAL, | 118 | {"daemon", 'd', "NUMBER", OPTION_ARG_OPTIONAL, |
95 | "runs in daemon mode with a maximum of NUMBER children"}, | 119 | "Runs in daemon mode with a maximum of NUMBER children"}, |
96 | {"inetd", 'i', 0, 0, | 120 | {"inetd", 'i', 0, 0, |
97 | "run in inetd mode", 0}, | 121 | "Run in inetd mode", 0}, |
98 | {"port", 'p', "PORT", 0, | 122 | {"port", 'p', "PORT", 0, |
99 | "listen on specified port number", 0}, | 123 | "Listen on specified port number", 0}, |
100 | {"timeout", 't', "NUMBER", 0, | 124 | {"timeout", 't', "NUMBER", 0, |
101 | "set idle timeout value to NUMBER seconds", 0}, | 125 | "Set idle timeout value to NUMBER seconds", 0}, |
102 | { NULL, 0, NULL, 0, NULL, 0 } | 126 | { NULL, 0, NULL, 0, NULL, 0 } |
103 | }; | 127 | }; |
104 | 128 | ||
... | @@ -108,71 +132,74 @@ static error_t mu_daemon_argp_parser __P((int key, char *arg, | ... | @@ -108,71 +132,74 @@ static error_t mu_daemon_argp_parser __P((int key, char *arg, |
108 | struct argp_state *state)); | 132 | struct argp_state *state)); |
109 | 133 | ||
110 | struct argp mu_common_argp = { | 134 | struct argp mu_common_argp = { |
111 | mu_common_argp_option, | 135 | mu_common_argp_options, |
112 | mu_common_argp_parser, | 136 | mu_common_argp_parser, |
113 | "", | ||
114 | "", | ||
115 | NULL, | ||
116 | NULL, | ||
117 | NULL | ||
118 | }; | 137 | }; |
119 | 138 | ||
120 | struct argp_child mu_common_argp_child = { | 139 | struct argp_child mu_common_argp_child = { |
121 | &mu_common_argp, | 140 | &mu_common_argp, |
122 | 0, | 141 | 0, |
123 | "Common mailutils options", | 142 | "", |
124 | 1 | 143 | -10, |
125 | }; | 144 | }; |
126 | 145 | ||
127 | struct argp mu_auth_argp = { | 146 | struct argp mu_licence_argp = { |
128 | mu_auth_argp_option, | 147 | mu_licence_argp_option, |
129 | mu_common_argp_parser, | 148 | mu_common_argp_parser, |
149 | }; | ||
150 | |||
151 | struct argp_child mu_licence_argp_child = { | ||
152 | &mu_licence_argp, | ||
153 | 0, | ||
130 | "", | 154 | "", |
131 | "", | 155 | -2 |
132 | NULL, | ||
133 | NULL, | ||
134 | NULL | ||
135 | }; | 156 | }; |
136 | 157 | ||
137 | struct argp_child mu_auth_argp_child = { | 158 | struct argp mu_mailbox_argp = { |
138 | &mu_auth_argp, | 159 | mu_mailbox_argp_option, |
160 | mu_common_argp_parser, | ||
161 | }; | ||
162 | |||
163 | struct argp_child mu_mailbox_argp_child = { | ||
164 | &mu_mailbox_argp, | ||
139 | 0, | 165 | 0, |
140 | "Authentication-relevant options", | 166 | "", |
141 | 1 | 167 | -3 |
142 | }; | 168 | }; |
143 | 169 | ||
144 | struct argp mu_logging_argp = { | 170 | struct argp mu_logging_argp = { |
145 | mu_logging_argp_option, | 171 | mu_logging_argp_option, |
146 | mu_common_argp_parser, | 172 | mu_common_argp_parser, |
147 | "", | ||
148 | "", | ||
149 | NULL, | ||
150 | NULL, | ||
151 | NULL | ||
152 | }; | 173 | }; |
153 | 174 | ||
154 | struct argp_child mu_logging_argp_child = { | 175 | struct argp_child mu_logging_argp_child = { |
155 | &mu_logging_argp, | 176 | &mu_logging_argp, |
156 | 0, | 177 | 0, |
157 | "Logging options", | 178 | "", |
158 | 1 | 179 | -3 |
180 | }; | ||
181 | |||
182 | struct argp mu_auth_argp = { | ||
183 | mu_auth_argp_option, | ||
184 | mu_common_argp_parser, | ||
185 | }; | ||
186 | |||
187 | struct argp_child mu_auth_argp_child = { | ||
188 | &mu_auth_argp, | ||
189 | 0, | ||
190 | "Authentication options", | ||
159 | }; | 191 | }; |
160 | 192 | ||
161 | struct argp mu_daemon_argp = { | 193 | struct argp mu_daemon_argp = { |
162 | mu_daemon_argp_option, | 194 | mu_daemon_argp_option, |
163 | mu_daemon_argp_parser, | 195 | mu_daemon_argp_parser, |
164 | "", | ||
165 | "", | ||
166 | NULL, | ||
167 | NULL, | ||
168 | NULL | ||
169 | }; | 196 | }; |
170 | 197 | ||
171 | struct argp_child mu_daemon_argp_child = { | 198 | struct argp_child mu_daemon_argp_child = { |
172 | &mu_daemon_argp, | 199 | &mu_daemon_argp, |
173 | 0, | 200 | 0, |
174 | "Daemon configuration options", | 201 | "Daemon configuration options", |
175 | 1 | 202 | 0 |
176 | }; | 203 | }; |
177 | 204 | ||
178 | int log_facility = LOG_FACILITY; | 205 | int log_facility = LOG_FACILITY; |
... | @@ -247,18 +274,50 @@ mu_common_argp_parser (int key, char *arg, struct argp_state *state) | ... | @@ -247,18 +274,50 @@ mu_common_argp_parser (int key, char *arg, struct argp_state *state) |
247 | 274 | ||
248 | switch (key) | 275 | switch (key) |
249 | { | 276 | { |
277 | /* common */ | ||
278 | case 'L': | ||
279 | printf ("Licence for %s:\n\n", argp_program_version); | ||
280 | printf ("%s", license_text); | ||
281 | exit (0); | ||
282 | |||
283 | /* mailbox */ | ||
250 | case 'm': | 284 | case 'm': |
251 | mu_path_maildir = arg; | 285 | mu_path_maildir = arg; |
252 | break; | 286 | break; |
253 | 287 | ||
254 | case 'L': | 288 | case ARG_LOCK_FLAGS: |
255 | printf ("%s", license_text); | 289 | { |
256 | exit (0); | 290 | int flags = 0; |
291 | for ( ; *arg; arg++) | ||
292 | { | ||
293 | switch (*arg) | ||
294 | { | ||
295 | case 'E': | ||
296 | flags |= MU_LOCKER_EXTERNAL; | ||
297 | break; | ||
298 | case 'R': | ||
299 | flags |= MU_LOCKER_RETRY; | ||
300 | break; | ||
301 | case 'T': | ||
302 | flags |= MU_LOCKER_TIME; | ||
303 | break; | ||
304 | case 'P': | ||
305 | flags |= MU_LOCKER_PID; | ||
306 | break; | ||
307 | default: | ||
308 | argp_error (state, "invalid lock flag '%c'", *arg); | ||
309 | } | ||
310 | } | ||
311 | locker_set_default_flags(flags); | ||
312 | } | ||
313 | break; | ||
257 | 314 | ||
315 | /* log */ | ||
258 | case ARG_LOG_FACILITY: | 316 | case ARG_LOG_FACILITY: |
259 | log_facility = parse_log_facility (arg); | 317 | log_facility = parse_log_facility (arg); |
260 | break; | 318 | break; |
261 | 319 | ||
320 | /* authentication */ | ||
262 | #ifdef USE_LIBPAM | 321 | #ifdef USE_LIBPAM |
263 | case ARG_PAM_SERVICE: | 322 | case ARG_PAM_SERVICE: |
264 | pam_service = arg; | 323 | pam_service = arg; |
... | @@ -308,8 +367,7 @@ mu_common_argp_parser (int key, char *arg, struct argp_state *state) | ... | @@ -308,8 +367,7 @@ mu_common_argp_parser (int key, char *arg, struct argp_state *state) |
308 | p = mu_normalize_maildir (mu_path_maildir); | 367 | p = mu_normalize_maildir (mu_path_maildir); |
309 | if (!p) | 368 | if (!p) |
310 | { | 369 | { |
311 | mu_error ("Badly formed maildir: %s", mu_path_maildir); | 370 | argp_error (state, "badly formed maildir: %s", mu_path_maildir); |
312 | exit (mu_argp_error_code); | ||
313 | } | 371 | } |
314 | mu_path_maildir = p; | 372 | mu_path_maildir = p; |
315 | break; | 373 | break; |
... | @@ -508,6 +566,7 @@ mu_create_argcv (const char *capa[], | ... | @@ -508,6 +566,7 @@ mu_create_argcv (const char *capa[], |
508 | int x_argc; | 566 | int x_argc; |
509 | char **x_argv; | 567 | char **x_argv; |
510 | int i; | 568 | int i; |
569 | int rcdir = 0; | ||
511 | 570 | ||
512 | progname = strrchr (argv[0], '/'); | 571 | progname = strrchr (argv[0], '/'); |
513 | if (progname) | 572 | if (progname) |
... | @@ -530,20 +589,61 @@ mu_create_argcv (const char *capa[], | ... | @@ -530,20 +589,61 @@ mu_create_argcv (const char *capa[], |
530 | /* Add global config file. */ | 589 | /* Add global config file. */ |
531 | read_rc (progname, MU_CONFIG_FILE, capa, &x_argc, &x_argv); | 590 | read_rc (progname, MU_CONFIG_FILE, capa, &x_argc, &x_argv); |
532 | 591 | ||
592 | /* Look for per-user config files in ~/.mailutils/ or in ~/, but | ||
593 | not both. This allows mailutils' utilities to have their config | ||
594 | files segregated, if necessary. */ | ||
595 | |||
596 | { | ||
597 | struct stat s; | ||
598 | char* rcdirname = mu_tilde_expansion (MU_USER_CONFIG_FILE, "/", NULL); | ||
599 | |||
600 | if (!rcdirname) | ||
601 | { | ||
602 | fprintf (stderr, "%s: not enough memory\n", progname); | ||
603 | exit (1); | ||
604 | } | ||
605 | if(stat(rcdirname, &s) == 0 && S_ISDIR(s.st_mode)) | ||
606 | rcdir = 1; | ||
607 | |||
608 | free(rcdirname); | ||
609 | } | ||
610 | |||
533 | /* Add per-user config file. */ | 611 | /* Add per-user config file. */ |
612 | if(!rcdir) | ||
613 | { | ||
534 | read_rc (progname, MU_USER_CONFIG_FILE, capa, &x_argc, &x_argv); | 614 | read_rc (progname, MU_USER_CONFIG_FILE, capa, &x_argc, &x_argv); |
615 | } | ||
616 | else | ||
617 | { | ||
618 | char* userrc = NULL; | ||
535 | 619 | ||
536 | /* Add per-program (and per-user) config file. */ | 620 | asprintf(&userrc, "%s/mailutils", MU_USER_CONFIG_FILE); |
621 | |||
622 | if (!userrc) | ||
537 | { | 623 | { |
538 | char* progrc = malloc (strlen (progname) | 624 | fprintf (stderr, "%s: not enough memory\n", progname); |
539 | + 6 /* ~/.mu. */ | 625 | exit (1); |
540 | + 3 /* rc */ + 1); | 626 | } |
627 | read_rc (progname, userrc, capa, &x_argc, &x_argv); | ||
628 | |||
629 | free(userrc); | ||
630 | } | ||
631 | |||
632 | /* Add per-user, per-program config file. */ | ||
633 | { | ||
634 | char* progrc = NULL; | ||
635 | |||
636 | if(rcdir) | ||
637 | asprintf(&progrc, "%s/%src", MU_USER_CONFIG_FILE, progname); | ||
638 | else | ||
639 | asprintf(&progrc, "~/.%src", progname); | ||
640 | |||
541 | if (!progrc) | 641 | if (!progrc) |
542 | { | 642 | { |
543 | fprintf (stderr, "%s: not enough memory\n", progname); | 643 | fprintf (stderr, "%s: not enough memory\n", progname); |
544 | exit (1); | 644 | exit (1); |
545 | } | 645 | } |
546 | sprintf (progrc, "~/.mu.%src", progname); | 646 | |
547 | read_rc (NULL, progrc, capa, &x_argc, &x_argv); | 647 | read_rc (NULL, progrc, capa, &x_argc, &x_argv); |
548 | free (progrc); | 648 | free (progrc); |
549 | } | 649 | } |
... | @@ -563,10 +663,12 @@ struct argp_capa { | ... | @@ -563,10 +663,12 @@ struct argp_capa { |
563 | char *capability; | 663 | char *capability; |
564 | struct argp_child *child; | 664 | struct argp_child *child; |
565 | } mu_argp_capa[] = { | 665 | } mu_argp_capa[] = { |
566 | {"mailutils", &mu_common_argp_child}, | 666 | {"common", &mu_common_argp_child}, |
567 | {"daemon", &mu_daemon_argp_child}, | 667 | {"licence", &mu_licence_argp_child}, |
568 | {"auth", &mu_auth_argp_child}, | 668 | {"mailbox", &mu_mailbox_argp_child}, |
569 | {"logging", &mu_logging_argp_child}, | 669 | {"logging", &mu_logging_argp_child}, |
670 | {"auth", &mu_auth_argp_child}, | ||
671 | {"daemon", &mu_daemon_argp_child}, | ||
570 | {NULL,} | 672 | {NULL,} |
571 | }; | 673 | }; |
572 | 674 | ||
... | @@ -584,10 +686,12 @@ static struct argp * | ... | @@ -584,10 +686,12 @@ static struct argp * |
584 | mu_build_argp (const struct argp *template, const char *capa[]) | 686 | mu_build_argp (const struct argp *template, const char *capa[]) |
585 | { | 687 | { |
586 | int n; | 688 | int n; |
689 | int nchild; | ||
587 | struct argp_child *ap; | 690 | struct argp_child *ap; |
588 | struct argp *argp; | 691 | struct argp *argp; |
692 | int group = -100; | ||
589 | 693 | ||
590 | /* Count the capabilities */ | 694 | /* Count the capabilities. */ |
591 | for (n = 0; capa && capa[n]; n++) | 695 | for (n = 0; capa && capa[n]; n++) |
592 | ; | 696 | ; |
593 | if (template->children) | 697 | if (template->children) |
... | @@ -601,32 +705,42 @@ mu_build_argp (const struct argp *template, const char *capa[]) | ... | @@ -601,32 +705,42 @@ mu_build_argp (const struct argp *template, const char *capa[]) |
601 | abort (); | 705 | abort (); |
602 | } | 706 | } |
603 | 707 | ||
604 | n = 0; | 708 | /* Copy the template's children. */ |
709 | nchild = 0; | ||
605 | if (template->children) | 710 | if (template->children) |
606 | for (; template->children[n].argp; n++) | 711 | for (n = 0; template->children[n].argp; n++, nchild++) |
607 | ap[n] = template->children[n]; | 712 | ap[nchild] = template->children[n]; |
713 | |||
714 | group = -nchild - 1; | ||
608 | 715 | ||
609 | for (; capa && capa[n]; n++) | 716 | /* Append any capabilities to the children or options, as appropriate. */ |
717 | for (n = 0; capa && capa[n]; n++) | ||
610 | { | 718 | { |
611 | struct argp_child *tmp = find_argp_child (capa[n]); | 719 | struct argp_child *child = find_argp_child (capa[n]); |
612 | if (!tmp) | 720 | if (!child) |
613 | { | 721 | { |
614 | mu_error ("INTERNAL ERROR: requested unknown argp capability %s", | 722 | mu_error ("INTERNAL ERROR: requested unknown argp capability %s", |
615 | capa[n]); | 723 | capa[n]); |
616 | abort (); | 724 | abort (); |
617 | } | 725 | } |
618 | ap[n] = *tmp; | 726 | ap[nchild] = *child; |
619 | ap[n].group = n; | 727 | // ap[nchild].group = group++; |
728 | nchild++; | ||
620 | } | 729 | } |
621 | ap[n].argp = NULL; | 730 | ap[nchild].argp = NULL; |
731 | |||
732 | /* Copy the template, and give it the expanded children. */ | ||
622 | argp = malloc (sizeof (*argp)); | 733 | argp = malloc (sizeof (*argp)); |
623 | if (!argp) | 734 | if (!argp) |
624 | { | 735 | { |
625 | mu_error ("out of memory"); | 736 | mu_error ("out of memory"); |
626 | abort (); | 737 | abort (); |
627 | } | 738 | } |
739 | |||
628 | memcpy (argp, template, sizeof (*argp)); | 740 | memcpy (argp, template, sizeof (*argp)); |
741 | |||
629 | argp->children = ap; | 742 | argp->children = ap; |
743 | |||
630 | return argp; | 744 | return argp; |
631 | } | 745 | } |
632 | 746 | ... | ... |
-
Please register or sign in to post a comment