Commit a810eb84 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Refactor argv processing.

Create a general list for holding "args to be dealt with later"
and use it for pretty much everything in that class.

Side-effect:  Multiple -T, -M and -P options are supported now.
parent 7e6d4caa
...@@ -50,7 +50,6 @@ ...@@ -50,7 +50,6 @@
#include "hash/hash_slinger.h" #include "hash/hash_slinger.h"
#include "libvcc.h" #include "libvcc.h"
#include "vav.h"
#include "vcli_serve.h" #include "vcli_serve.h"
#include "vend.h" #include "vend.h"
#include "vev.h" #include "vev.h"
...@@ -73,16 +72,10 @@ struct VSC_mgt *VSC_C_mgt; ...@@ -73,16 +72,10 @@ struct VSC_mgt *VSC_C_mgt;
static int I_fd = -1; static int I_fd = -1;
static char *workdir; static char *workdir;
static struct vpf_fh *pfh1 = NULL;
static struct vpf_fh *pfh2 = NULL;
static struct vfil_path *vcl_path = NULL; static struct vfil_path *vcl_path = NULL;
static VTAILQ_HEAD(,f_arg) f_args = VTAILQ_HEAD_INITIALIZER(f_args);
static const char opt_spec[] = "?a:b:Cdf:Fh:i:I:j:l:M:n:P:p:r:S:s:T:t:VW:x:"; static const char opt_spec[] = "?a:b:Cdf:Fh:i:I:j:l:M:n:P:p:r:S:s:T:t:VW:x:";
int optreset; // Some has it, some doesn't. Cheaper than auto*
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static void static void
...@@ -175,6 +168,46 @@ usage(void) ...@@ -175,6 +168,46 @@ usage(void)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
struct arg_list {
unsigned magic;
#define ARG_LIST_MAGIC 0x7b0d1bc4
char arg[2];
char *val;
VTAILQ_ENTRY(arg_list) list;
void *priv;
};
static VTAILQ_HEAD(, arg_list) arglist = VTAILQ_HEAD_INITIALIZER(arglist);
static struct arg_list *
arg_list_add(const char arg, const char *val)
{
struct arg_list *alp;
ALLOC_OBJ(alp, ARG_LIST_MAGIC);
AN(alp);
alp->arg[0] = arg;
alp->arg[1] = '\0';
REPLACE(alp->val, val);
VTAILQ_INSERT_TAIL(&arglist, alp, list);
return (alp);
}
static unsigned
arg_list_count(const char *arg)
{
unsigned retval = 0;
struct arg_list *alp;
VTAILQ_FOREACH(alp, &arglist, list) {
if (!strcmp(alp->arg, arg))
retval++;
}
return (retval);
}
/*--------------------------------------------------------------------*/
static void static void
cli_check(const struct cli *cli) cli_check(const struct cli *cli)
{ {
...@@ -252,7 +285,6 @@ mgt_Cflag_atexit(void) ...@@ -252,7 +285,6 @@ mgt_Cflag_atexit(void)
if (getpid() != heritage.mgt_pid) if (getpid() != heritage.mgt_pid)
return; return;
VJ_rmdir("vmod_cache"); VJ_rmdir("vmod_cache");
VJ_unlink("_.pid");
(void)chdir("/"); (void)chdir("/");
VJ_rmdir(workdir); VJ_rmdir(workdir);
} }
...@@ -411,10 +443,9 @@ struct f_arg { ...@@ -411,10 +443,9 @@ struct f_arg {
#define F_ARG_MAGIC 0x840649a8 #define F_ARG_MAGIC 0x840649a8
char *farg; char *farg;
char *src; char *src;
VTAILQ_ENTRY(f_arg) list;
}; };
static void static struct f_arg *
mgt_f_read(const char *fn) mgt_f_read(const char *fn)
{ {
struct f_arg *fa; struct f_arg *fa;
...@@ -431,7 +462,7 @@ mgt_f_read(const char *fn) ...@@ -431,7 +462,7 @@ mgt_f_read(const char *fn)
free(fa->farg); free(fa->farg);
fa->farg = fnp; fa->farg = fnp;
fa->src = f; fa->src = f;
VTAILQ_INSERT_TAIL(&f_args, fa, list); return (fa);
} }
static void static void
...@@ -457,35 +488,34 @@ mgt_b_conv(const char *b_arg) ...@@ -457,35 +488,34 @@ mgt_b_conv(const char *b_arg)
fa->src = strdup(VSB_data(vsb)); fa->src = strdup(VSB_data(vsb));
AN(fa->src); AN(fa->src);
VSB_destroy(&vsb); VSB_destroy(&vsb);
VTAILQ_INSERT_TAIL(&f_args, fa, list); AZ(arg_list_count("f"));
arg_list_add('f', "")->priv = fa;
} }
static int static int
mgt_process_f_args(struct cli *cli, unsigned C_flag) mgt_process_f_arg(struct cli *cli, unsigned C_flag, void **fap)
{ {
int retval = 0; int retval = 0;
struct f_arg *fa; struct f_arg *fa;
const char *name = NULL;
while (!VTAILQ_EMPTY(&f_args)) {
fa = VTAILQ_FIRST(&f_args); TAKE_OBJ_NOTNULL(fa, fap, F_ARG_MAGIC);
CHECK_OBJ_NOTNULL(fa, F_ARG_MAGIC); if (arg_list_count("f") == 1)
VTAILQ_REMOVE(&f_args, fa, list); name = "boot";
mgt_vcl_startup(cli, fa->src, mgt_vcl_startup(cli, fa->src, name, fa->farg, C_flag);
VTAILQ_EMPTY(&f_args) ? "boot" : NULL, fa->farg, C_flag); if (C_flag) {
if (C_flag) { if (cli->result != CLIS_OK &&
if (cli->result != CLIS_OK && cli->result != CLIS_TRUNCATED)
cli->result != CLIS_TRUNCATED) retval = 2;
retval = 2; AZ(VSB_finish(cli->sb));
AZ(VSB_finish(cli->sb)); fprintf(stderr, "%s\n", VSB_data(cli->sb));
fprintf(stderr, "%s\n", VSB_data(cli->sb)); VSB_clear(cli->sb);
VSB_clear(cli->sb); } else {
} else { cli_check(cli);
cli_check(cli);
}
free(fa->farg);
free(fa->src);
FREE_OBJ(fa);
} }
free(fa->farg);
free(fa->src);
FREE_OBJ(fa);
return (retval); return (retval);
} }
...@@ -543,21 +573,15 @@ main(int argc, char * const *argv) ...@@ -543,21 +573,15 @@ main(int argc, char * const *argv)
{ {
int o, eric_fd = -1; int o, eric_fd = -1;
unsigned C_flag = 0; unsigned C_flag = 0;
unsigned f_flag = 0;
unsigned F_flag = 0; unsigned F_flag = 0;
const char *b_arg = NULL; const char *b_arg = NULL;
const char *i_arg = NULL; const char *i_arg = NULL;
const char *j_arg = NULL; const char *j_arg = NULL;
const char *h_arg = "critbit"; const char *h_arg = "critbit";
const char *M_arg = NULL;
const char *n_arg = NULL; const char *n_arg = NULL;
const char *P_arg = NULL;
const char *S_arg = NULL; const char *S_arg = NULL;
const char *s_arg = "default,100m"; const char *s_arg = "default,100m";
const char *W_arg = NULL; const char *W_arg = NULL;
int s_arg_given = 0;
int novcl = 0;
const char *T_arg = "localhost:0";
char *p; char *p;
struct cli cli[1]; struct cli cli[1];
const char *err; const char *err;
...@@ -565,6 +589,8 @@ main(int argc, char * const *argv) ...@@ -565,6 +589,8 @@ main(int argc, char * const *argv)
struct sigaction sac; struct sigaction sac;
struct vev *e; struct vev *e;
pid_t pid; pid_t pid;
struct arg_list *alp;
int first_arg = 1;
if (argc == 2 && !strcmp(argv[1], "--optstring")) { if (argc == 2 && !strcmp(argv[1], "--optstring")) {
printf("%s\n", opt_spec); printf("%s\n", opt_spec);
...@@ -581,35 +607,22 @@ main(int argc, char * const *argv) ...@@ -581,35 +607,22 @@ main(int argc, char * const *argv)
mgt_initialize(cli); mgt_initialize(cli);
/* Check if first argument is a special flag */ for (; (o = getopt(argc, argv, opt_spec)) != -1; first_arg = 0) {
o = getopt(argc, argv, opt_spec);
switch (o) {
case 'x':
if (argc != 3)
ARGV_ERR("Too many arguments for -x\n");
mgt_x_arg(optarg);
exit(0);
case 'V':
if (argc != 2)
ARGV_ERR("Too many arguments for -V\n");
VCS_Message("varnishd");
exit(0);
default:
break;
}
/* First pass over arguments to determine overall configuration */
do {
switch (o) { switch (o) {
case '?':
usage();
exit(2);
case 'V': case 'V':
if (!first_arg)
ARGV_ERR("-V must be the first argument\n");
if (argc != 2)
ARGV_ERR("Too many arguments for -V\n");
VCS_Message("varnishd");
exit(0);
case 'x': case 'x':
ARGV_ERR("-%c must be the first argument\n", o); if (!first_arg)
break; ARGV_ERR("-x must be the first argument\n");
if (argc != 3)
ARGV_ERR("Too many arguments for -x\n");
mgt_x_arg(optarg);
exit(0);
case 'b': case 'b':
b_arg = optarg; b_arg = optarg;
break; break;
...@@ -619,31 +632,60 @@ main(int argc, char * const *argv) ...@@ -619,31 +632,60 @@ main(int argc, char * const *argv)
case 'd': case 'd':
d_flag++; d_flag++;
break; break;
case 'f':
f_flag = 1;
break;
case 'F': case 'F':
F_flag = 1; F_flag = 1;
break; break;
case 'j': case 'j':
j_arg = optarg; j_arg = optarg;
break; break;
default: case 'h':
h_arg = optarg;
break;
case 'i':
i_arg = optarg;
break;
case 'l':
arg_list_add('p', "vsl_space")->priv = optarg;
break;
case 'n':
n_arg = optarg;
break;
case 'S':
S_arg = optarg;
break;
case 't':
arg_list_add('p', "default_ttl")->priv = optarg;
break;
case 'W':
W_arg = optarg;
break;
case 'a':
case 'f':
case 'I':
case 'p':
case 'P':
case 'M':
case 'r':
case 's':
case 'T':
(void)arg_list_add(o, optarg);
break; break;
default:
usage();
exit(2);
} }
o = getopt(argc, argv, opt_spec); }
} while (o != -1);
if (argc != optind) if (argc != optind)
ARGV_ERR("Too many arguments (%s...)\n", argv[optind]); ARGV_ERR("Too many arguments (%s...)\n", argv[optind]);
if (b_arg != NULL && f_flag) if (b_arg != NULL && arg_list_count("f"))
ARGV_ERR("Only one of -b or -f can be specified\n"); ARGV_ERR("Only one of -b or -f can be specified\n");
if (d_flag && F_flag) if (d_flag && F_flag)
ARGV_ERR("Only one of -d or -F can be specified\n"); ARGV_ERR("Only one of -d or -F can be specified\n");
if (C_flag && b_arg == NULL && !f_flag) if (C_flag && b_arg == NULL && !arg_list_count("f"))
ARGV_ERR("-C needs either -b <backend> or -f <vcl_file>\n"); ARGV_ERR("-C needs either -b <backend> or -f <vcl_file>\n");
if (d_flag && C_flag) if (d_flag && C_flag)
...@@ -652,12 +694,18 @@ main(int argc, char * const *argv) ...@@ -652,12 +694,18 @@ main(int argc, char * const *argv)
if (F_flag && C_flag) if (F_flag && C_flag)
ARGV_ERR("-F makes no sense with -C\n"); ARGV_ERR("-F makes no sense with -C\n");
if (!d_flag && b_arg == NULL && !f_flag) if (!d_flag && b_arg == NULL && !arg_list_count("f"))
ARGV_ERR("Neither -b nor -f given. (use -f '' to override)\n"); ARGV_ERR("Neither -b nor -f given. (use -f '' to override)\n");
if (arg_list_count("I") > 1)
ARGV_ERR("\tOnly one -I allowed\n");
if (d_flag || F_flag) if (d_flag || F_flag)
complain_to_stderr = 1; complain_to_stderr = 1;
if (!arg_list_count("T"))
(void)arg_list_add('T', "localhost:0");
/* /*
* Start out by closing all unwanted file descriptors we might * Start out by closing all unwanted file descriptors we might
* have inherited from sloppy process control daemons. * have inherited from sloppy process control daemons.
...@@ -694,101 +742,46 @@ main(int argc, char * const *argv) ...@@ -694,101 +742,46 @@ main(int argc, char * const *argv)
if (b_arg != NULL) if (b_arg != NULL)
mgt_b_conv(b_arg); mgt_b_conv(b_arg);
optind = 1; /* Process delayed arguments */
optreset = 1; VTAILQ_FOREACH(alp, &arglist, list) {
while ((o = getopt(argc, argv, opt_spec)) != -1) { switch(alp->arg[0]) {
switch (o) {
case 'C':
case 'd':
case 'F':
case 'j':
/* Handled in first pass */
break;
case 'a': case 'a':
MAC_Arg(optarg); MAC_Arg(alp->val);
break;
case 'b':
/* already dealt with */
break; break;
case 'f': case 'f':
if (*optarg == '\0') if (*alp->val != '\0')
novcl = 1; alp->priv = mgt_f_read(alp->val);
else
mgt_f_read(optarg);
break;
case 'h':
h_arg = optarg;
break;
case 'i':
i_arg = optarg;
break; break;
case 'I': case 'I':
if (I_fd >= 0)
ARGV_ERR("\tOnly one -I allowed\n");
VJ_master(JAIL_MASTER_FILE); VJ_master(JAIL_MASTER_FILE);
I_fd = open(optarg, O_RDONLY); I_fd = open(alp->val, O_RDONLY);
if (I_fd < 0) if (I_fd < 0)
ARGV_ERR("\tCan't open %s: %s\n", ARGV_ERR("\tCan't open %s: %s\n",
optarg, VAS_errtxt(errno)); alp->val, VAS_errtxt(errno));
VJ_master(JAIL_MASTER_LOW); VJ_master(JAIL_MASTER_LOW);
break; break;
case 'l':
MCF_ParamSet(cli, "vsl_space", optarg);
cli_check(cli);
break;
case 'M':
M_arg = optarg;
break;
case 'n':
n_arg = optarg;
break;
case 'P':
P_arg = optarg;
break;
case 'p': case 'p':
p = strchr(optarg, '='); if (alp->priv) {
if (p == NULL) MCF_ParamSet(cli, alp->val, alp->priv);
ARGV_ERR("\t-p lacks '='\n"); } else {
AN(p); p = strchr(alp->val, '=');
*p++ = '\0'; if (p == NULL)
MCF_ParamSet(cli, optarg, p); ARGV_ERR("\t-p lacks '='\n");
*--p = '='; AN(p);
cli_check(cli); *p++ = '\0';
MCF_ParamSet(cli, alp->val, p);
}
break; break;
case 'r': case 'r':
MCF_ParamProtect(cli, optarg); MCF_ParamProtect(cli, alp->val);
cli_check(cli);
break;
case 'S':
S_arg = optarg;
break; break;
case 's': case 's':
s_arg_given = 1; STV_Config(alp->val);
STV_Config(optarg);
break;
case 'T':
if (!strcmp(optarg, "none"))
T_arg = NULL;
else
T_arg = optarg;
break;
case 't':
MCF_ParamSet(cli, "default_ttl", optarg);
break;
case 'W':
W_arg = optarg;
break; break;
default: default:
WRONG("Error in argument parsing"); break;
} }
} cli_check(cli);
assert(argc == optind);
/* XXX: we can have multiple CLI actions above, is this enough ? */
if (cli[0].result != CLIS_OK) {
AZ(VSB_finish(cli[0].sb));
ARGV_ERR("Failed parameter creation:\n%s\n",
VSB_data(cli[0].sb));
} }
VCLS_SetLimit(mgt_cls, &mgt_param.cli_limit); VCLS_SetLimit(mgt_cls, &mgt_param.cli_limit);
...@@ -839,13 +832,8 @@ main(int argc, char * const *argv) ...@@ -839,13 +832,8 @@ main(int argc, char * const *argv)
if (C_flag) if (C_flag)
AZ(atexit(mgt_Cflag_atexit)); AZ(atexit(mgt_Cflag_atexit));
pfh1 = create_pid_file(&pid, "%s/_.pid", workdir);
if (P_arg)
pfh2 = create_pid_file(&pid, "%s", P_arg);
/* If no -s argument specified, process default -s argument */ /* If no -s argument specified, process default -s argument */
if (!s_arg_given) if (!arg_list_count("s"))
STV_Config(s_arg); STV_Config(s_arg);
/* Configure Transient storage, if user did not */ /* Configure Transient storage, if user did not */
...@@ -853,10 +841,23 @@ main(int argc, char * const *argv) ...@@ -853,10 +841,23 @@ main(int argc, char * const *argv)
mgt_vcl_init(); mgt_vcl_init();
u = mgt_process_f_args(cli, C_flag); u = 0;
VTAILQ_FOREACH(alp, &arglist, list) {
if (!strcmp(alp->arg, "f") && alp->priv != NULL)
u |= mgt_process_f_arg(cli, C_flag, &alp->priv);
}
if (C_flag) if (C_flag)
exit(u); exit(u);
VTAILQ_FOREACH(alp, &arglist, list) {
if (!strcmp(alp->arg, "P"))
alp->priv = create_pid_file(&pid, "%s", alp->val);
}
/* Implict -P argument */
alp = arg_list_add('P', NULL);
alp->priv = create_pid_file(&pid, "%s/_.pid", workdir);
if (VTAILQ_EMPTY(&heritage.socks)) if (VTAILQ_EMPTY(&heritage.socks))
MAC_Arg(":80\0"); // XXX: extra NUL for FlexeLint MAC_Arg(":80\0"); // XXX: extra NUL for FlexeLint
...@@ -871,10 +872,14 @@ main(int argc, char * const *argv) ...@@ -871,10 +872,14 @@ main(int argc, char * const *argv)
mgt_SHM_static_alloc(i_arg, strlen(i_arg) + 1L, "Arg", "-i"); mgt_SHM_static_alloc(i_arg, strlen(i_arg) + 1L, "Arg", "-i");
VSC_C_mgt = VSC_mgt_New(NULL, NULL, ""); VSC_C_mgt = VSC_mgt_New(NULL, NULL, "");
if (M_arg != NULL) VTAILQ_FOREACH(alp, &arglist, list) {
mgt_cli_master(M_arg); if (!strcmp(alp->arg, "M"))
if (T_arg != NULL) mgt_cli_master(alp->val);
mgt_cli_telnet(T_arg); else if (!strcmp(alp->arg, "T") && strcmp(alp->val, "none"))
mgt_cli_telnet(alp->val);
else if (!strcmp(alp->arg, "P"))
VPF_Write(alp->priv);
}
AZ(VSB_finish(vident)); AZ(VSB_finish(vident));
...@@ -882,10 +887,6 @@ main(int argc, char * const *argv) ...@@ -882,10 +887,6 @@ main(int argc, char * const *argv)
S_arg = make_secret(workdir); S_arg = make_secret(workdir);
AN(S_arg); AN(S_arg);
VPF_Write(pfh1);
if (pfh2 != NULL)
VPF_Write(pfh2);
MGT_Complain(C_DEBUG, "Version: %s", VCS_String("V")); MGT_Complain(C_DEBUG, "Version: %s", VCS_String("V"));
MGT_Complain(C_DEBUG, "Platform: %s", VSB_data(vident) + 1); MGT_Complain(C_DEBUG, "Platform: %s", VSB_data(vident) + 1);
...@@ -918,7 +919,7 @@ main(int argc, char * const *argv) ...@@ -918,7 +919,7 @@ main(int argc, char * const *argv)
assert(I_fd == -1); assert(I_fd == -1);
err = mgt_has_vcl(); err = mgt_has_vcl();
if (!d_flag && err != NULL && !novcl) if (!d_flag && err != NULL && !arg_list_count("f"))
MGT_Complain(C_ERR, "%s", err); MGT_Complain(C_ERR, "%s", err);
if (err == NULL && !d_flag) if (err == NULL && !d_flag)
...@@ -967,8 +968,9 @@ main(int argc, char * const *argv) ...@@ -967,8 +968,9 @@ main(int argc, char * const *argv)
MGT_Complain(C_INFO, "manager dies"); MGT_Complain(C_INFO, "manager dies");
mgt_cli_close_all(); mgt_cli_close_all();
VEV_Destroy(&mgt_evb); VEV_Destroy(&mgt_evb);
VPF_Remove(pfh1); VTAILQ_FOREACH(alp, &arglist, list) {
if (pfh2 != NULL) if (!strcmp(alp->arg, "P"))
VPF_Remove(pfh2); VPF_Remove(alp->priv);
}
exit(exit_status); exit(exit_status);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment