return;
}
-
/*--------------------------------------------------------------------*/
-struct cli_proto CLI_cmds[] = {
+static void ccf_help(struct cli *cli, const char * const *av, void *priv);
+
+/*--------------------------------------------------------------------
+ * The CLI commandlist is split in three:
+ * Commands we get from/share with the manager
+ * Cache process commands
+ * Undocumented commands
+ */
+
+static struct cli_proto master_cmds[] = {
{ CLI_PING, cli_func_ping },
{ CLI_SERVER_START, cli_func_start },
-#if 0
- { CLI_URL_QUERY, cli_func_url_query },
-#endif
- { CLI_URL_PURGE, cli_func_url_purge },
- { CLI_HASH_PURGE, cli_func_hash_purge },
{ CLI_VCL_LOAD, cli_func_config_load },
{ CLI_VCL_LIST, cli_func_config_list },
{ CLI_VCL_DISCARD, cli_func_config_discard },
{ CLI_VCL_USE, cli_func_config_use },
+ { NULL }
+};
- /* Undocumented functions for debugging */
+static struct cli_proto cacher_cmds[] = {
+ { CLI_HELP, ccf_help, NULL },
+ { CLI_URL_PURGE, cli_func_url_purge },
+ { CLI_HASH_PURGE, cli_func_hash_purge },
+#if 0
+ { CLI_URL_QUERY, cli_func_url_query },
+#endif
+ { NULL }
+};
+
+static struct cli_proto undoc_cmds[] = {
{ "debug.sizeof", "debug.sizeof",
"\tDump sizeof various data structures\n",
0, 0, cli_debug_sizeof },
{ NULL }
};
+
+/*--------------------------------------------------------------------*/
+
+static void
+ccf_help(struct cli *cli, const char * const *av, void *priv)
+{
+
+ (void)priv;
+ /* "+1" to skip "help" entry, manager already did that. */
+ cli_func_help(cli, av, cacher_cmds + 1);
+
+ if (av[2] != NULL && !strcmp(av[2], "-d")) {
+ /* Also list undocumented commands */
+ cli_out(cli, "\nDebugging commands:\n");
+ cli_func_help(cli, av, undoc_cmds);
+ } else if (cli->result == CLIS_UNKNOWN) {
+ /* Otherwise, try the undocumented list */
+ vsb_clear(cli->sb);
+ cli->result = CLIS_OK;
+ cli_func_help(cli, av, undoc_cmds);
+ }
+}
+
+/*--------------------------------------------------------------------*/
+
static int
cli_vlu(void *priv, const char *p)
{
cli = priv;
VSL(SLT_CLI, 0, "Rd %s", p);
vsb_clear(cli->sb);
- cli_dispatch(cli, CLI_cmds, p);
+ cli_dispatch(cli, master_cmds, p);
+ if (cli->result == CLIS_UNKNOWN) {
+ vsb_clear(cli->sb);
+ cli->result = CLIS_OK;
+ cli_dispatch(cli, cacher_cmds, p);
+ }
+ if (cli->result == CLIS_UNKNOWN) {
+ vsb_clear(cli->sb);
+ cli->result = CLIS_OK;
+ cli_dispatch(cli, undoc_cmds, p);
+ }
vsb_finish(cli->sb);
AZ(vsb_overflowed(cli->sb));
i = cli_writeres(heritage.fds[1], cli);
#undef MAC_STAT
}
-
-/*--------------------------------------------------------------------
- * Passthru of cli commands. It is more or less just undoing what
- * the cli parser did, but such is life...
- */
-
static void
-mcf_passthru(struct cli *cli, const char * const *av, void *priv)
+mcf_help(struct cli *cli, const char * const *av, void *priv)
{
- struct vsb *sb;
- const char *p;
- char *q;
unsigned u;
- int i;
-
- (void)priv;
+ char *p;
- /* Request */
- if (cli_o <= 0) {
- cli_result(cli, CLIS_CANT);
- cli_out(cli, "Cache process not running");
- return;
- }
- sb = vsb_new(NULL, NULL, 64, VSB_AUTOEXTEND);
- XXXAN(sb);
- for (u = 1; av[u] != NULL; u++) {
- if (u > 1)
- vsb_putc(sb, ' ');
- vsb_putc(sb, '"');
- for (p = av[u]; *p; p++) {
- switch (*p) {
- case '\\':
- vsb_cat(sb, "\\\\");
- break;
- case '\n':
- vsb_cat(sb, "\\n");
- break;
- case '"':
- vsb_cat(sb, "\\\"");
- break;
- default:
- vsb_putc(sb, *p);
- }
- }
- vsb_putc(sb, '"');
+ cli_func_help(cli, av, priv);
+ if (cli_o >= 0 && (av[2] == NULL || *av[2] == '-')) {
+ p = NULL;
+ if (!mgt_cli_askchild(&u, &p,
+ "help %s\n", av[2] != NULL ? av[2] : "")) {
+ cli_out(cli, "%s", p);
+ cli_result(cli, u);
+ }
+ free(p);
}
- vsb_putc(sb, '\n');
- xxxassert(!vsb_overflowed(sb));
- vsb_finish(sb);
- AZ(vsb_overflowed(sb));
- i = write(cli_o, vsb_data(sb), vsb_len(sb));
- xxxassert(i == vsb_len(sb));
- vsb_delete(sb);
-
- i = cli_readres(cli_i, &u, &q, params->cli_timeout);
- cli_result(cli, u);
- cli_out(cli, "%s", q);
- free(q);
-
}
/*--------------------------------------------------------------------*/
-static struct cli_proto *cli_proto;
/* XXX: what order should this list be in ? */
-static struct cli_proto mgt_cli_proto[] = {
+static struct cli_proto cli_proto[] = {
+ { CLI_HELP, mcf_help, cli_proto },
{ CLI_PING, cli_func_ping },
{ CLI_SERVER_STATUS, mcf_server_status, NULL },
{ CLI_SERVER_START, mcf_server_startstop, NULL },
{ CLI_VCL_SHOW, mcf_config_show, NULL },
{ CLI_PARAM_SHOW, mcf_param_show, NULL },
{ CLI_PARAM_SET, mcf_param_set, NULL },
- { CLI_HELP, cli_func_help, NULL },
#if 0
{ CLI_SERVER_RESTART },
{ CLI_ZERO },
{ NULL }
};
-
-/*--------------------------------------------------------------------*/
-
-void
-mgt_cli_init(void)
-{
- struct cli_proto *cp;
- unsigned u, v;
-
- /*
- * Build the joint cli_proto by combining the manager process
- * entries with with the cache process entries. The latter
- * get a "passthough" function in the joint list
- */
- u = 0;
- for (cp = mgt_cli_proto; cp->request != NULL; cp++)
- u++;
- for (cp = CLI_cmds; cp->request != NULL; cp++)
- u++;
- cli_proto = calloc(sizeof *cli_proto, u + 1);
- XXXAN(cli_proto);
- u = 0;
- for (cp = mgt_cli_proto; cp->request != NULL; cp++)
- cli_proto[u++] = *cp;
- for (cp = CLI_cmds; cp->request != NULL; cp++) {
- /* Skip any cache commands we already have in the manager */
- for (v = 0; v < u; v++)
- if (!strcmp(cli_proto[v].request, cp->request))
- break;
- if (v < u)
- continue;
- cli_proto[u] = *cp;
- cli_proto[u].func = mcf_passthru;
- u++;
- }
-
- /* Fixup the entry for 'help' entry */
- for (u = 0; cli_proto[u].request != NULL; u++) {
- if (!strcmp(cli_proto[u].request, "help")) {
- cli_proto[u].priv = cli_proto;
- break;
- }
- }
-}
-
/*--------------------------------------------------------------------
* Ask the child something over CLI, return zero only if everything is
* happy happy.
*/
int
-mgt_cli_askchild(unsigned *status, char **resp, const char *fmt, ...)
-{
+mgt_cli_askchild(unsigned *status, char **resp, const char *fmt, ...) {
char *p;
int i, j;
va_list ap;
mgt_cli_vlu(void *priv, const char *p)
{
struct cli_port *cp;
+ char *q;
+ unsigned u;
+ int i;
CAST_OBJ_NOTNULL(cp, priv, CLI_PORT_MAGIC);
vsb_clear(cp->cli->sb);
cli_dispatch(cp->cli, cli_proto, p);
vsb_finish(cp->cli->sb);
AZ(vsb_overflowed(cp->cli->sb));
+ if (cp->cli->result == CLIS_UNKNOWN) {
+ /*
+ * Command not recognized in master, try cacher if it is
+ * running.
+ */
+ vsb_clear(cp->cli->sb);
+ cp->cli->result = CLIS_OK;
+ if (cli_o <= 0) {
+ cli_result(cp->cli, CLIS_UNKNOWN);
+ cli_out(cp->cli,
+ "Unknown request in manager process "
+ "(child not running).\n"
+ "Type 'help' for more info.");
+ } else {
+ i = write(cli_o, p, strlen(p));
+ xxxassert(i == strlen(p));
+ i = write(cli_o, "\n", 1);
+ xxxassert(i == 1);
+ i = cli_readres(cli_i, &u, &q, params->cli_timeout);
+ cli_result(cp->cli, u);
+ cli_out(cp->cli, "%s", q);
+ free(q);
+ }
+ vsb_finish(cp->cli->sb);
+ AZ(vsb_overflowed(cp->cli->sb));
+ }
/* send the result back */
if (cli_writeres(cp->fdo, cp->cli))