/* This file is part of Mailfromd.
Copyright (C) 2005-2020 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "dns.h"
#define _(String) gettext(String)
#define N_(String) String
#if defined HAVE_SYSCONF && defined _SC_OPEN_MAX
# define getmaxfd() sysconf(_SC_OPEN_MAX)
#elif defined (HAVE_GETDTABLESIZE)
# define getmaxfd() getdtablesize()
#else
# define getmaxfd() 256
#endif
/* The following defines are borrowed from intprops.h (gnulib) */
/* True if the arithmetic type T is signed. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
/* Return zero if T can be determined to be an unsigned type.
Otherwise, return 1.
When compiling with GCC, INT_STRLEN_BOUND uses this macro to obtain a
tighter bound. Otherwise, it overestimates the true bound by one byte
when applied to unsigned types of size 2, 4, 16, ... bytes.
The symbol signed_type_or_expr__ is private to this header file. */
#if __GNUC__ >= 2
# define signed_type_or_expr__(t) TYPE_SIGNED (__typeof__ (t))
#else
# define signed_type_or_expr__(t) 1
#endif
/* Bound on length of the string representing an integer type or expression T.
Subtract 1 for the sign bit if T is signed; log10 (2.0) < 146/485;
add 1 for integer division truncation; add 1 more for a minus sign
if needed. */
#define INT_STRLEN_BOUND(t) \
((sizeof (t) * CHAR_BIT - signed_type_or_expr__ (t)) * 146 / 485 \
+ signed_type_or_expr__ (t) + 1)
/* Bound on buffer size needed to represent an integer type or expression T,
including the terminating null. */
#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
/* Size of the buffer able to accomodate mailfromd numeric type */
#define NUMERIC_BUFSIZE_BOUND INT_BUFSIZE_BOUND(long)
/* Status values used throughout the program */
typedef enum mf_status_code {
mf_success,
mf_not_found,
mf_failure,
mf_temp_failure,
mf_timeout,
#define mf_status_count (mf_smtp_temp_failure+1)
} mf_status;
#define mf_resolved(c) ((c) == mf_success || (c) == mf_not_found)
const char *mf_status_str(mf_status s);
enum smtp_timeout {
smtp_timeout_connect,
smtp_timeout_initial,
smtp_timeout_helo,
smtp_timeout_mail,
smtp_timeout_rcpt,
smtp_timeout_rset,
smtp_timeout_quit
};
#define SMTP_NUM_TIMEOUT (smtp_timeout_quit+1)
#define MF_GETOPT_DEFAULT 0x00
/* Process options in order; don't permute */
#define MF_GETOPT_IN_ORDER 0x01
/* Don't parse configuration files */
#define MF_GETOPT_NO_CONFIG 0x02
void mf_getopt(struct mu_cli_setup *cli, int *pargc, char ***pargv, char **capa,
int flags);
void mailfromd_version(struct mu_parseopt *po, mu_stream_t stream);
int mf_vercmp(const char *a, const char *b, int *pres);
void mf_init_nls (void);
int parse_time_interval(const char *str, time_t *pint, const char **endp);
void dict_init(mu_assoc_t *dict);
char *dict_install(mu_assoc_t dict, const char *name, const char *value);
void dict_destroy(mu_assoc_t *dict);
char *dict_getsym(void *data, const char *str);
struct mf_privs {
char *user;
int allgroups;
mu_list_t groups;
};
struct mf_gid_list;
struct mf_gid_list *mf_gid_list_alloc(void);
void mf_gid_list_free(struct mf_gid_list *gl);
struct mf_gid_list *mf_gid_list_dup(struct mf_gid_list *src);
void mf_gid_list_add(struct mf_gid_list *gl, gid_t gid);
void mf_gid_list_array(struct mf_gid_list *gl, size_t *gc, gid_t **gv);
int switch_to_privs (uid_t uid, gid_t gid, struct mf_gid_list *);
void get_user_groups (struct mf_gid_list *grouplist, const char *user);
void mf_priv_setup (struct mf_privs *);
void mf_epriv_setup (struct mf_privs *);
char **config_array_to_argv (mu_config_value_t *val);
char *config_array_to_string (mu_config_value_t *val);
int config_cb_timeout (struct timeval *pt, mu_config_value_t *val);
int config_cb_time_t(void *data, mu_config_value_t *arg);
int config_cb_ignore(void *data, mu_config_value_t *val);
int config_cb_lock_retry_count(void *data, mu_config_value_t *val);
int config_cb_lock_retry_timeout(void *data, mu_config_value_t *val);
void mf_proctitle_init (int argc, char *argv[], char *env[]);
void mf_proctitle_format (const char *fmt, ...);
int stderr_closed_p(void);
int mf_list_compare_string(const void *item, const void *value);
struct symtab;
struct syment {
char *name;
unsigned refcnt;
};
typedef int (*symtab_enumerator_t)(void *sym, void *data);
#define SYMTAB_COPY_KEY 0x1
#define SYMTAB_ICASE 0x2
const char * symtab_strerror(int rc);
int symtab_lookup_or_install(struct syment **ent,
struct symtab *st, const char *name,
int *install);
int symtab_lookup_or_install_entry(struct syment **elp,
struct symtab *st, struct syment *ent,
int *install);
void symtab_clear(struct symtab *st);
struct symtab *symtab_create(size_t elsize, int flags,
void *(*alloc_fun)(size_t),
void (*free_fun)(void *));
void symtab_destroy(struct symtab **pst);
int symtab_remove(struct symtab *st, const char *name);
int symtab_replace(struct symtab *st, struct syment *ent,
struct syment **old_ent);
int symtab_enumerate(struct symtab *st, symtab_enumerator_t fun, void *data);
typedef int (*symtab_selfun)(const struct syment *ent, void *closure);
typedef int (*symtab_errfun)(int rc, struct symtab *tab, const char *name,
void *closure);
typedef int (*symtab_confun)(struct symtab *dst,
struct syment *dstent, struct syment *srcent,
void *closure);
typedef int (*symtab_cpyfun)(struct syment **pdst, struct syment *src,
size_t len, void *closure);
int symtab_import(struct symtab *dst, struct symtab *src,
symtab_selfun selfun, symtab_errfun errfun,
symtab_confun confun, symtab_cpyfun cpyfun,
void *closure);
size_t symtab_count_entries(struct symtab *st);
typedef struct transform *transform_t;
typedef int (*transform_append_t)(void *, const char *s, size_t len);
typedef char *(*transform_reduce_t)(void *);
const char *transform_error_string (void);
transform_t transform_compile(const char *expr, int cflags);
void transform_free(transform_t);
char *transform_string (transform_t tf, const char *input,
void *slist,
transform_append_t append,
transform_reduce_t reduce);
void close_fds_above(int fd);
void close_fds_except(fd_set *exfd);
/* logger.c */
#ifdef DEFAULT_SYSLOG_ASYNC
# define DEFAULT_LOG_STREAM "syslog:async"
#else
# define DEFAULT_LOG_STREAM "syslog"
#endif
#define LOGF_STDERR 0x01 /* Logger uses stderr */
struct logger {
char *name;
int flags;
void (*log_open)(void);
void (*log_close)(void);
void (*log_fdset)(fd_set *set);
void (*log_text)(int, const char *);
};
int logger_flags(int mask);
int logger_select(const char *name);
void logger_open(void);
void logger_close(void);
void logger_fdset(fd_set *set);
void logger_text(int prio, const char *text);
#define vlogmsg mu_diag_voutput
#define logmsg mu_diag_output
/* strmwait.c */
struct timeout_ctl {
time_t start;
time_t timeout;
};
#define UPDATE_TTW(t) do { \
time_t now = time(NULL); \
time_t delta = now - (t).start; \
if ((t).timeout > delta) \
(t).timeout -= delta; \
else \
(t).timeout = 0; \
(t).start = now; \
} while (0)
void init_timeout_ctl(struct timeout_ctl *tctl, time_t timeout);
int mf_stream_wait(mu_stream_t stream, int flags, struct timeout_ctl *tctl);
/* ftimestr.c */
extern char *time_format_string;
size_t format_time_str(FILE *fp, time_t timestamp);
/* dns.c */
void dnsbase_init(void);
mf_status dns_to_mf_status(dns_status stat);
dns_status mf_to_dns_status(mf_status stat);
mf_status resolve_ipstr_domain(const char *ipstr, const char *domain, char **phbuf);
mf_status resolve_ipstr(const char *ipstr, char **phbuf);
mf_status resolve_hostname(const char *host, char **pipbuf);
/* server.c */
#define MF_SERVER_FOREGROUND 0x01
#define MF_SERVER_NORESTART 0x02
extern void mf_server_log_setup(void);
extern mode_t mf_server_umask;
extern char *mf_server_user;
extern struct mf_gid_list *mf_server_retain_groups;
extern char *mf_server_lint_option;
void mf_server_check_pidfile(const char *name);
void mf_server_save_cmdline(int argc, char **argv);
void mf_server_start(const char *program, const char *dir,
const char *pidfile, int flags);
/* namefixup.c */
void mf_namefixup_register(char **ptr, const char *initval);
void mf_file_name_ptr_fixup(char **ptr, char *dir, size_t dirlen);
void mf_namefixup_run(char *dir);
void mf_namefixup_free(void);