25 |
#ifdef HAVE_STRINGS_H |
#ifdef HAVE_STRINGS_H |
26 |
# include <strings.h> |
# include <strings.h> |
27 |
#endif |
#endif |
28 |
|
#include <sys/types.h> |
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> |
36 |
#include <argcv.h> |
#include <argcv.h> |
37 |
#include <mu_argp.h> |
#include <mu_argp.h> |
38 |
#ifdef HAVE_MYSQL |
#ifdef HAVE_MYSQL |
50 |
#define ARG_SQL_PORT 9 |
#define ARG_SQL_PORT 9 |
51 |
#define ARG_PAM_SERVICE 10 |
#define ARG_PAM_SERVICE 10 |
52 |
|
|
53 |
static struct argp_option mu_common_argp_option[] = |
static struct argp_option mu_common_argp_option[] = { |
|
{ |
|
54 |
{"maildir", 'm', "URL", 0, |
{"maildir", 'm', "URL", 0, |
55 |
"use specified URL as a mailspool directory", 0}, |
"use specified URL as a mailspool directory", 0}, |
56 |
{ "license", 'L', NULL, 0, "print license and exit", 0 }, |
{ "license", 'L', NULL, 0, "print license and exit", 0 }, |
57 |
{ NULL, 0, NULL, 0, NULL, 0 } |
{ NULL, 0, NULL, 0, NULL, 0 } |
58 |
}; |
}; |
59 |
|
|
60 |
static struct argp_option mu_logging_argp_option[] = |
static struct argp_option mu_logging_argp_option[] = { |
|
{ |
|
61 |
{"log-facility", ARG_LOG_FACILITY, "FACILITY", 0, |
{"log-facility", ARG_LOG_FACILITY, "FACILITY", 0, |
62 |
"output logs to syslog FACILITY", 0}, |
"output logs to syslog FACILITY", 0}, |
63 |
{ NULL, 0, NULL, 0, NULL, 0 } |
{ NULL, 0, NULL, 0, NULL, 0 } |
64 |
}; |
}; |
65 |
|
|
66 |
|
|
67 |
static struct argp_option mu_auth_argp_option[] = |
static struct argp_option mu_auth_argp_option[] = { |
|
{ |
|
68 |
#ifdef USE_LIBPAM |
#ifdef USE_LIBPAM |
69 |
{ "pam-service", ARG_PAM_SERVICE, "STRING", 0, |
{ "pam-service", ARG_PAM_SERVICE, "STRING", 0, |
70 |
"Use STRING as PAM service name", 0}, |
"Use STRING as PAM service name", 0}, |
90 |
{ NULL, 0, NULL, 0, NULL, 0 } |
{ NULL, 0, NULL, 0, NULL, 0 } |
91 |
}; |
}; |
92 |
|
|
93 |
static struct argp_option mu_daemon_argp_option[] = |
static struct argp_option mu_daemon_argp_option[] = { |
|
{ |
|
94 |
{"daemon", 'd', "NUMBER", OPTION_ARG_OPTIONAL, |
{"daemon", 'd', "NUMBER", OPTION_ARG_OPTIONAL, |
95 |
"runs in daemon mode with a maximum of NUMBER children"}, |
"runs in daemon mode with a maximum of NUMBER children"}, |
96 |
{"inetd", 'i', 0, 0, |
{"inetd", 'i', 0, 0, |
107 |
static error_t mu_daemon_argp_parser __P((int key, char *arg, |
static error_t mu_daemon_argp_parser __P((int key, char *arg, |
108 |
struct argp_state *state)); |
struct argp_state *state)); |
109 |
|
|
110 |
struct argp mu_common_argp = |
struct argp mu_common_argp = { |
|
{ |
|
111 |
mu_common_argp_option, |
mu_common_argp_option, |
112 |
mu_common_argp_parser, |
mu_common_argp_parser, |
113 |
"", |
"", |
124 |
1 |
1 |
125 |
}; |
}; |
126 |
|
|
127 |
struct argp mu_auth_argp = |
struct argp mu_auth_argp = { |
|
{ |
|
128 |
mu_auth_argp_option, |
mu_auth_argp_option, |
129 |
mu_common_argp_parser, |
mu_common_argp_parser, |
130 |
"", |
"", |
141 |
1 |
1 |
142 |
}; |
}; |
143 |
|
|
144 |
struct argp mu_logging_argp = |
struct argp mu_logging_argp = { |
|
{ |
|
145 |
mu_logging_argp_option, |
mu_logging_argp_option, |
146 |
mu_common_argp_parser, |
mu_common_argp_parser, |
147 |
"", |
"", |
158 |
1 |
1 |
159 |
}; |
}; |
160 |
|
|
161 |
struct argp mu_daemon_argp = |
struct argp mu_daemon_argp = { |
|
{ |
|
162 |
mu_daemon_argp_option, |
mu_daemon_argp_option, |
163 |
mu_daemon_argp_parser, |
mu_daemon_argp_parser, |
164 |
"", |
"", |
361 |
# define MU_CONFIG_FILE SYSCONFDIR "/mailutils.rc" |
# define MU_CONFIG_FILE SYSCONFDIR "/mailutils.rc" |
362 |
#endif |
#endif |
363 |
|
|
364 |
|
#ifndef MU_USER_CONFIG_FILE |
365 |
|
# define MU_USER_CONFIG_FILE ".mailutils" |
366 |
|
#endif |
367 |
|
|
368 |
static int |
static int |
369 |
member (const char *array[], const char *text, size_t len) |
member (const char *array[], const char *text, size_t len) |
370 |
{ |
{ |
376 |
} |
} |
377 |
|
|
378 |
void |
void |
379 |
|
read_rc (const char *progname, const char *name, const char *capa[], |
380 |
|
int *argc, char ***argv) |
381 |
|
{ |
382 |
|
FILE *fp; |
383 |
|
char *linebuf = NULL; |
384 |
|
char *buf = NULL; |
385 |
|
size_t n = 0; |
386 |
|
int x_argc = *argc; |
387 |
|
char **x_argv = *argv; |
388 |
|
|
389 |
|
fp = fopen (name, "r"); |
390 |
|
if (!fp) |
391 |
|
return; |
392 |
|
|
393 |
|
while (getline (&buf, &n, fp) > 0) |
394 |
|
{ |
395 |
|
char *kwp, *p; |
396 |
|
int len; |
397 |
|
|
398 |
|
for (kwp = buf; *kwp && isspace (*kwp); kwp++) |
399 |
|
; |
400 |
|
|
401 |
|
if (*kwp == '#' || *kwp == 0) |
402 |
|
continue; |
403 |
|
|
404 |
|
len = strlen (kwp); |
405 |
|
if (kwp[len-1] == '\n') |
406 |
|
kwp[--len] = 0; |
407 |
|
|
408 |
|
if (kwp[len-1] == '\\' || linebuf) |
409 |
|
{ |
410 |
|
int cont; |
411 |
|
|
412 |
|
if (kwp[len-1] == '\\') |
413 |
|
{ |
414 |
|
kwp[--len] = 0; |
415 |
|
cont = 1; |
416 |
|
} |
417 |
|
else |
418 |
|
cont = 0; |
419 |
|
|
420 |
|
if (!linebuf) |
421 |
|
linebuf = calloc (len + 1, 1); |
422 |
|
else |
423 |
|
linebuf = realloc (linebuf, strlen (linebuf) + len + 1); |
424 |
|
|
425 |
|
if (!linebuf) |
426 |
|
{ |
427 |
|
fprintf (stderr, "%s: not enough memory\n", progname); |
428 |
|
exit (1); |
429 |
|
} |
430 |
|
|
431 |
|
strcpy (linebuf + strlen (linebuf), kwp); |
432 |
|
if (cont) |
433 |
|
continue; |
434 |
|
kwp = linebuf; |
435 |
|
} |
436 |
|
|
437 |
|
len = 0; |
438 |
|
for (p = kwp; *p && !isspace (*p); p++) |
439 |
|
len++; |
440 |
|
|
441 |
|
if ((kwp[0] == ':' |
442 |
|
&& member (capa, kwp+1, len-1)) |
443 |
|
|| strncmp (progname, kwp, len) == 0) |
444 |
|
{ |
445 |
|
int i, n_argc = 0; |
446 |
|
char **n_argv; |
447 |
|
|
448 |
|
if (argcv_get (p, "", NULL, &n_argc, &n_argv)) |
449 |
|
{ |
450 |
|
argcv_free (n_argc, n_argv); |
451 |
|
if (linebuf) |
452 |
|
free (linebuf); |
453 |
|
linebuf = NULL; |
454 |
|
continue; |
455 |
|
} |
456 |
|
x_argv = realloc (x_argv, |
457 |
|
(x_argc + n_argc) * sizeof (x_argv[0])); |
458 |
|
if (!x_argv) |
459 |
|
{ |
460 |
|
fprintf (stderr, "%s: not enough memory\n", progname); |
461 |
|
exit (1); |
462 |
|
} |
463 |
|
|
464 |
|
for (i = 0; i < n_argc; i++) |
465 |
|
x_argv[x_argc++] = n_argv[i]; |
466 |
|
|
467 |
|
free (n_argv); |
468 |
|
if (linebuf) |
469 |
|
free (linebuf); |
470 |
|
linebuf = NULL; |
471 |
|
} |
472 |
|
} |
473 |
|
fclose (fp); |
474 |
|
|
475 |
|
*argc = x_argc; |
476 |
|
*argv = x_argv; |
477 |
|
} |
478 |
|
|
479 |
|
|
480 |
|
void |
481 |
mu_create_argcv (const char *capa[], |
mu_create_argcv (const char *capa[], |
482 |
int argc, char **argv, int *p_argc, char ***p_argv) |
int argc, char **argv, int *p_argc, char ***p_argv) |
483 |
{ |
{ |
|
FILE *fp; |
|
484 |
char *progname; |
char *progname; |
485 |
int x_argc; |
int x_argc; |
486 |
char **x_argv; |
char **x_argv; |
487 |
int i; |
int i; |
488 |
|
struct passwd *pw; |
489 |
|
|
490 |
progname = strrchr (argv[0], '/'); |
progname = strrchr (argv[0], '/'); |
491 |
if (progname) |
if (progname) |
505 |
x_argv[x_argc] = argv[x_argc]; |
x_argv[x_argc] = argv[x_argc]; |
506 |
x_argc++; |
x_argc++; |
507 |
|
|
508 |
/* Process the mailutils.rc file */ |
read_rc (progname, MU_CONFIG_FILE, capa, &x_argc, &x_argv); |
509 |
fp = fopen (MU_CONFIG_FILE, "r"); |
pw = getpwuid (getuid ()); |
510 |
if (fp) |
if (pw) |
511 |
{ |
{ |
512 |
char *linebuf = NULL; |
struct stat sb; |
513 |
char *buf = NULL; |
|
514 |
size_t n = 0; |
if (stat (pw->pw_dir, &sb) == 0 && S_ISDIR (sb.st_mode)) |
515 |
|
{ |
516 |
while (getline (&buf, &n, fp) > 0) |
/* note: sizeof return value counts terminating zero */ |
517 |
{ |
char *name = xmalloc (strlen (pw->pw_dir) + 1 |
518 |
char *kwp, *p; |
+ sizeof (MU_USER_CONFIG_FILE)); |
519 |
int len; |
sprintf (name, "%s/%s", pw->pw_dir, MU_USER_CONFIG_FILE); |
520 |
|
read_rc (progname, name, capa, &x_argc, &x_argv); |
521 |
for (kwp = buf; *kwp && isspace (*kwp); kwp++) |
free (name); |
522 |
; |
} |
|
|
|
|
if (*kwp == '#' || *kwp == 0) |
|
|
continue; |
|
|
|
|
|
len = strlen (kwp); |
|
|
if (kwp[len-1] == '\n') |
|
|
kwp[--len] = 0; |
|
|
|
|
|
if (kwp[len-1] == '\\' || linebuf) |
|
|
{ |
|
|
int cont; |
|
|
|
|
|
if (kwp[len-1] == '\\') |
|
|
{ |
|
|
kwp[--len] = 0; |
|
|
cont = 1; |
|
|
} |
|
|
else |
|
|
cont = 0; |
|
|
|
|
|
if (!linebuf) |
|
|
linebuf = calloc (len + 1, 1); |
|
|
else |
|
|
linebuf = realloc (linebuf, strlen (linebuf) + len + 1); |
|
|
|
|
|
if (!linebuf) |
|
|
{ |
|
|
fprintf (stderr, "%s: not enough memory\n", progname); |
|
|
exit (1); |
|
|
} |
|
|
|
|
|
strcpy (linebuf + strlen (linebuf), kwp); |
|
|
if (cont) |
|
|
continue; |
|
|
kwp = linebuf; |
|
|
} |
|
|
|
|
|
len = 0; |
|
|
for (p = kwp; *p && !isspace (*p); p++) |
|
|
len++; |
|
|
|
|
|
if ((kwp[0] == ':' |
|
|
&& member (capa, kwp+1, len-1)) |
|
|
|| strncmp (progname, kwp, len) == 0) |
|
|
{ |
|
|
int n_argc = 0; |
|
|
char **n_argv; |
|
|
|
|
|
if (argcv_get (p, "", NULL, &n_argc, &n_argv)) |
|
|
{ |
|
|
argcv_free (n_argc, n_argv); |
|
|
if (linebuf) |
|
|
free (linebuf); |
|
|
linebuf = NULL; |
|
|
continue; |
|
|
} |
|
|
x_argv = realloc (x_argv, |
|
|
(x_argc + n_argc + 1) * sizeof (x_argv[0])); |
|
|
if (!x_argv) |
|
|
{ |
|
|
fprintf (stderr, "%s: not enough memory\n", progname); |
|
|
exit (1); |
|
|
} |
|
|
|
|
|
for (i = 0; i < n_argc; i++) |
|
|
x_argv[x_argc++] = n_argv[i]; |
|
|
|
|
|
free (n_argv); |
|
|
if (linebuf) |
|
|
free (linebuf); |
|
|
linebuf = NULL; |
|
|
} |
|
|
} |
|
|
fclose (fp); |
|
523 |
} |
} |
524 |
|
|
525 |
/* Finally, add the command line options */ |
/* Finally, add the command line options */ |
526 |
x_argv = realloc (x_argv, (x_argc + argc + 1) * sizeof (x_argv[0])); |
x_argv = realloc (x_argv, (x_argc + argc) * sizeof (x_argv[0])); |
527 |
for (i = 1; i < argc; i++) |
for (i = 1; i < argc; i++) |
528 |
x_argv[x_argc++] = argv[i]; |
x_argv[x_argc++] = argv[i]; |
529 |
|
|
587 |
{ |
{ |
588 |
mu_error ("INTERNAL ERROR: requested unknown argp capability %s", |
mu_error ("INTERNAL ERROR: requested unknown argp capability %s", |
589 |
capa[n]); |
capa[n]); |
590 |
continue; |
abort (); |
591 |
} |
} |
592 |
ap[n] = *tmp; |
ap[n] = *tmp; |
593 |
ap[n].group = n; |
ap[n].group = n; |