opt_serv.h
#ifndef OPT_SERV_H
#define OPT_SERV_H
#include "opt.h"
#include "conf.h"
#include "evnt.h"
#define OPT_SERV_CONF_BUF_SZ (128 - sizeof(Vstr_node_buf))
#define OPT_SERV_CONF_MEM_PREALLOC_MAX (128 * 1024)
#define OPT_SERV_CONF_USE_DAEMON FALSE
#define OPT_SERV_CONF_USE_DROP_PRIVS FALSE
#define OPT_SERV_CONF_USE_PDEATHSIG FALSE
#define OPT_SERV_CONF_DEF_RLIM_CORE_CALL FALSE
#define OPT_SERV_CONF_DEF_RLIM_FILE_CALL FALSE
#define OPT_SERV_CONF_DEF_TCP_DEFER_ACCEPT 8
#define OPT_SERV_CONF_DEF_PRIV_UID 60001
#define OPT_SERV_CONF_DEF_PRIV_GID 60001
#define OPT_SERV_CONF_DEF_NUM_PROCS 1
#define OPT_SERV_CONF_DEF_IDLE_TIMEOUT (2 * 60)
#define OPT_SERV_CONF_DEF_Q_LISTEN_LEN 128
#define OPT_SERV_CONF_DEF_MAX_CONNECTIONS 0
#define OPT_SERV_CONF_DEF_RLIM_CORE_NUM 0
#define OPT_SERV_CONF_DEF_RLIM_FILE_NUM 0
typedef struct Opt_serv_policy_opts
{
Vstr_ref *ref;
struct Opt_serv_policy_opts *next;
struct Opt_serv_opts *beg;
Vstr_base *policy_name;
unsigned int idle_timeout;
unsigned int max_connections;
} Opt_serv_policy_opts;
typedef struct Opt_serv_addr_opts
{
struct Opt_serv_addr_opts *next;
Vstr_base *acpt_filter_file;
Vstr_base *ipv4_address;
unsigned short tcp_port;
unsigned int defer_accept;
unsigned int q_listen_len;
unsigned int max_connections;
} Opt_serv_addr_opts;
typedef struct Opt_serv_opts
{
Opt_serv_policy_opts *def_policy;
Opt_serv_policy_opts *(*make_policy)(struct Opt_serv_opts *);
int (*copy_policy)(struct Opt_serv_policy_opts *,
const struct Opt_serv_policy_opts *);
unsigned int become_daemon : 1;
unsigned int drop_privs : 1;
unsigned int use_pdeathsig : 1;
unsigned int no_conf_listen : 1;
unsigned int rlim_core_call : 1;
unsigned int rlim_file_call : 1;
Vstr_base *pid_file;
Vstr_base *cntl_file;
Vstr_base *chroot_dir;
Vstr_base *vpriv_uid;
uid_t priv_uid;
Vstr_base *vpriv_gid;
gid_t priv_gid;
unsigned int num_procs;
unsigned int rlim_core_num;
unsigned int rlim_file_num;
unsigned int max_spare_bases;
unsigned int max_spare_buf_nodes;
unsigned int max_spare_ptr_nodes;
unsigned int max_spare_ref_nodes;
Opt_serv_addr_opts *addr_beg;
} Opt_serv_opts;
#define OPT_SERV_CONF_INIT_OPTS() \
NULL, \
opt_policy_make, \
opt_policy_copy, \
OPT_SERV_CONF_USE_DAEMON, \
OPT_SERV_CONF_USE_DROP_PRIVS, \
OPT_SERV_CONF_USE_PDEATHSIG, \
FALSE, \
OPT_SERV_CONF_DEF_RLIM_CORE_CALL, \
OPT_SERV_CONF_DEF_RLIM_FILE_CALL, \
NULL, NULL, NULL, \
NULL, OPT_SERV_CONF_DEF_PRIV_UID, \
NULL, OPT_SERV_CONF_DEF_PRIV_GID, \
OPT_SERV_CONF_DEF_NUM_PROCS, \
OPT_SERV_CONF_DEF_RLIM_CORE_NUM, \
OPT_SERV_CONF_DEF_RLIM_FILE_NUM, \
4, \
(OPT_SERV_CONF_MEM_PREALLOC_MAX / OPT_SERV_CONF_BUF_SZ), \
(OPT_SERV_CONF_MEM_PREALLOC_MAX / OPT_SERV_CONF_BUF_SZ), \
(OPT_SERV_CONF_MEM_PREALLOC_MAX / OPT_SERV_CONF_BUF_SZ), \
NULL
#define OPT_SERV_CONF_DECL_OPTS(N) \
Opt_serv_opts N[1] = {{OPT_SERV_CONF_INIT_OPTS()}}
extern void opt_serv_conf_free(Opt_serv_opts *);
extern int opt_serv_conf_init(Opt_serv_opts *);
extern Opt_serv_addr_opts *opt_serv_make_addr(Opt_serv_opts *);
extern int opt_serv_conf(Opt_serv_opts *, const Conf_parse *, Conf_token *);
extern int opt_serv_conf_parse_cstr(Vstr_base *, Opt_serv_opts *, const char *);
extern int opt_serv_conf_parse_file(Vstr_base *, Opt_serv_opts *, const char *);
extern void opt_serv_logger(Vlg *);
extern void opt_serv_sc_drop_privs(Opt_serv_opts *);
extern void opt_serv_sc_rlim_file_num(unsigned int);
extern void opt_serv_sc_rlim_core_num(unsigned int);
extern int opt_serv_sc_acpt_end(const Opt_serv_policy_opts *,
struct Evnt *, struct Evnt *);
extern void opt_serv_sc_free_beg(struct Evnt *, struct Vstr_ref *);
extern void opt_serv_sc_signals(void);
extern void opt_serv_sc_check_children(void);
extern void opt_serv_sc_cntl_resources(const Opt_serv_opts *);
#define OPT_SERV_DECL_GETOPTS() \
{"help", no_argument, NULL, 'h'}, \
{"daemon", optional_argument, NULL, 1}, \
{"chroot", required_argument, NULL, 2}, \
{"drop-privs", optional_argument, NULL, 3}, \
{"priv-uid", required_argument, NULL, 4}, \
{"priv-gid", required_argument, NULL, 5}, \
{"pid-file", required_argument, NULL, 6}, \
{"cntl-file", required_argument, NULL, 7}, \
{"acpt-filter-file", required_argument, NULL, 8}, \
{"accept-filter-file", required_argument, NULL, 8}, \
{"processes", required_argument, NULL, 9}, \
{"procs", required_argument, NULL, 9}, \
{"debug", no_argument, NULL, 'd'}, \
{"host", required_argument, NULL, 'H'}, \
{"port", required_argument, NULL, 'P'}, \
{"nagle", optional_argument, NULL, 'n'}, \
{"max-connections", required_argument, NULL, 'M'}, \
{"idle-timeout", required_argument, NULL, 't'}, \
{"defer-accept", required_argument, NULL, 10}, \
{"version", no_argument, NULL, 'V'}
#define OPT_SERV_GETOPTS(opts) \
case 't': opts->def_policy->idle_timeout = atoi(optarg); break; \
case 'H': OPT_VSTR_ARG(opts->addr_beg->ipv4_address); break; \
case 'M': OPT_NUM_NR_ARG(opts->addr_beg->max_connections, \
"max connections"); \
opts->def_policy->max_connections = opts->addr_beg->max_connections; \
break; \
case 'P': OPT_NUM_ARG(opts->addr_beg->tcp_port, "tcp port", \
0, 65535, ""); \
opts->no_conf_listen = FALSE; break; \
case 'd': vlg_debug(vlg); break; \
\
case 'n': OPT_TOGGLE_ARG(evnt_opt_nagle); break; \
\
case 1: OPT_TOGGLE_ARG(opts->become_daemon); break; \
case 2: OPT_VSTR_ARG(opts->chroot_dir); break; \
case 3: OPT_TOGGLE_ARG(opts->drop_privs); break; \
case 4: OPT_VSTR_ARG(opts->vpriv_uid); break; \
case 5: OPT_VSTR_ARG(opts->vpriv_gid); break; \
case 6: OPT_VSTR_ARG(opts->pid_file); break; \
case 7: OPT_VSTR_ARG(opts->cntl_file); break; \
case 8: OPT_VSTR_ARG(opts->addr_beg->acpt_filter_file); break; \
case 9: OPT_NUM_ARG(opts->num_procs, "number of processes", \
1, 255, ""); break; \
case 10: OPT_NUM_ARG(opts->addr_beg->defer_accept, \
"seconds to defer connections", \
0, 4906, " (1 hour 8 minutes)"); break
#if 0
# define OPT_SERV_PRIME_SYM_EQ_DECL() \
const Vstr_sect_node *opt_serv__sym_cmp_val = NULL
# define OPT_SERV_SYM_EQ(x) \
conf_token_cmp_sym_cstr_eq(conf, token, x))
#else
# define OPT_SERV_PRIME_SYM_EQ_DECL() \
unsigned int opt_serv__sym_cmp_tok = 0; \
const Vstr_sect_node *opt_serv__sym_cmp_val = NULL
# define OPT_SERV_SYM_EQ(x) ( \
(((opt_serv__sym_cmp_tok == token->num) && opt_serv__sym_cmp_val) || \
((token->type == CONF_TOKEN_TYPE_SYMBOL) && \
(opt_serv__sym_cmp_val = conf_token_value(token)) && \
(opt_serv__sym_cmp_tok = token->num))) && \
(opt_serv__sym_cmp_val->len == strlen(x)) && \
!vstr_cmp_buf(conf->data, \
opt_serv__sym_cmp_val->pos, \
opt_serv__sym_cmp_val->len, (x), opt_serv__sym_cmp_val->len))
#endif
#define OPT_SERV_X_TOGGLE(x) do { \
int opt__val = (x); \
\
if (conf_sc_token_parse_toggle(conf, token, &opt__val)) \
return (FALSE); \
(x) = opt__val; \
} while (FALSE)
#define OPT_SERV_X_UINT(x) do { \
unsigned int opt__val = 0; \
\
if (conf_sc_token_parse_uint(conf, token, &opt__val)) \
return (FALSE); \
(x) = opt__val; \
} while (FALSE)
#define OPT_SERV_X__ESC_VSTR(x, p, l) do { \
if ((token->type == CONF_TOKEN_TYPE_QUOTE_ESC_D) || \
(token->type == CONF_TOKEN_TYPE_QUOTE_ESC_DDD) || \
(token->type == CONF_TOKEN_TYPE_QUOTE_ESC_S) || \
(token->type == CONF_TOKEN_TYPE_QUOTE_ESC_SSS) || \
FALSE) \
if (!conf_sc_conv_unesc((x), p, l, NULL)) \
return (FALSE); \
} while (FALSE)
#define OPT_SERV_X__VSTR(x, p, l) do { \
if (conf_sc_token_sub_vstr(conf, token, x, p, l)) \
return (FALSE); \
\
if ((x)->conf->malloc_bad) \
return (FALSE); \
OPT_SERV_X__ESC_VSTR(x, p, token->u.node->len); \
} while (FALSE)
#define OPT_SERV_X_VSTR(x) OPT_SERV_X__VSTR(x, 1, (x)->len)
#endif