/* * This function establishes a connection to the specified ip and port and * sends a command to varnishd. If varnishd returns an OK status, the result * is printed and 0 returned. Else, an error message is printed and 1 is * returned */ static int cli_sock(struct vadmin_config_t *vadmin, struct agent_core_t *core) { int fd; unsigned status; char *answer = NULL; char buf[CLI_AUTH_RESPONSE_LEN + 1]; n_arg_sock(core); if (core->config->T_arg == NULL) { logger(vadmin->logger, "No T-arg (Administration port) available. Varnishadm-commands wont work."); return (-1); } vadmin->sock = VSS_open(vadmin->logger, core->config->T_arg, core->config->timeout); if (vadmin->sock < 0) { logger(vadmin->logger, "Connection failed (%s)", core->config->T_arg); return (-1); } (void)VCLI_ReadResult(vadmin->sock, &status, &answer, core->config->timeout); if (status == CLIS_AUTH) { if (core->config->S_arg == NULL) { logger(vadmin->logger, "Authentication required"); assert(close(vadmin->sock) == 0); return(-1); } fd = open(core->config->S_arg, O_RDONLY); if (fd < 0) { logger(vadmin->logger, "Cannot open \"%s\": %s", core->config->S_arg, strerror(errno)); assert(close(vadmin->sock) == 0); return (-1); } VCLI_AuthResponse(fd, answer, buf); assert(close(fd) == 0); free(answer); cli_write(vadmin->sock, "auth "); cli_write(vadmin->sock, buf); cli_write(vadmin->sock, "\n"); (void)VCLI_ReadResult(vadmin->sock, &status, &answer, core->config->timeout); } if (status != CLIS_OK) { logger(vadmin->logger, "Rejected %u\n%s", status, answer); assert(close(vadmin->sock) == 0); return (-1); } free(answer); cli_write(vadmin->sock, "ping\n"); (void)VCLI_ReadResult(vadmin->sock, &status, &answer, core->config->timeout); if (status != CLIS_OK || strstr(answer, "PONG") == NULL) { logger(vadmin->logger, "No pong received from server"); assert(close(vadmin->sock) == 0); return(-1); } free(answer); vadmin->state = 1; return (vadmin->sock); }
/* * This function establishes a connection to the specified ip and port and * sends a command to varnishd. If varnishd returns an OK status, the result * is printed and 0 returned. Else, an error message is printed and 1 is * returned */ static int cli_sock(const char *T_arg, const char *S_arg) { int fd; int sock; unsigned status; char *answer = NULL; char buf[CLI_AUTH_RESPONSE_LEN + 1]; const char *err; sock = VTCP_open(T_arg, NULL, timeout, &err); if (sock < 0) { fprintf(stderr, "Connection failed (%s): %s\n", T_arg, err); return (-1); } (void)VCLI_ReadResult(sock, &status, &answer, timeout); if (status == CLIS_AUTH) { if (S_arg == NULL) { fprintf(stderr, "Authentication required\n"); AZ(close(sock)); return(-1); } fd = open(S_arg, O_RDONLY); if (fd < 0) { fprintf(stderr, "Cannot open \"%s\": %s\n", S_arg, strerror(errno)); AZ(close(sock)); return (-1); } VCLI_AuthResponse(fd, answer, buf); AZ(close(fd)); free(answer); cli_write(sock, "auth "); cli_write(sock, buf); cli_write(sock, "\n"); (void)VCLI_ReadResult(sock, &status, &answer, timeout); } if (status != CLIS_OK) { fprintf(stderr, "Rejected %u\n%s\n", status, answer); AZ(close(sock)); free(answer); return (-1); } free(answer); cli_write(sock, "ping\n"); (void)VCLI_ReadResult(sock, &status, &answer, timeout); if (status != CLIS_OK || strstr(answer, "PONG") == NULL) { fprintf(stderr, "No pong received from server\n"); AZ(close(sock)); free(answer); return (-1); } free(answer); return (sock); }
static enum VCLI_status_e varnish_ask_cli(const struct varnish *v, const char *cmd, char **repl) { int i; unsigned retval; char *r; if (cmd != NULL) { vtc_dump(v->vl, 4, "CLI TX", cmd, -1); i = write(v->cli_fd, cmd, strlen(cmd)); assert(i == strlen(cmd)); i = write(v->cli_fd, "\n", 1); assert(i == 1); } i = VCLI_ReadResult(v->cli_fd, &retval, &r, 20.0); if (i != 0) { vtc_log(v->vl, 0, "CLI failed (%s) = %d %u %s", cmd, i, retval, r); return ((enum VCLI_status_e)retval); } assert(i == 0); vtc_log(v->vl, 3, "CLI RX %u", retval); vtc_dump(v->vl, 4, "CLI RX", r, -1); if (repl != NULL) *repl = r; else free(r); return ((enum VCLI_status_e)retval); }
static void vadmin_run(struct vadmin_config_t *vadmin, char *cmd, struct ipc_ret_t *ret) { int sock = vadmin->sock; int nret; assert(cmd); nret = cli_write(sock, cmd); if (!nret) { logger(vadmin->logger, "Communication error with varnishd."); ret->status = 400; ret->answer = strdup("Varnishd disconnected"); vadmin->state = 0; return; } nret = cli_write(sock, "\n"); if (!nret) { logger(vadmin->logger, "Communication error with varnishd."); ret->status = 400; ret->answer = strdup("Varnishd disconnected"); vadmin->state = 0; return; } logger(vadmin->logger, "Running %s",cmd); (void)VCLI_ReadResult(sock, &ret->status, &ret->answer, 2000); logger(vadmin->logger, "Got: %d ",ret->status, ret->answer); }
static void do_args(int sock, int argc, char * const *argv) { int i; unsigned status; char *answer = NULL; for (i=0; i<argc; i++) { /* XXX: We should really CLI-quote these */ if (i > 0) cli_write(sock, " "); cli_write(sock, argv[i]); } cli_write(sock, "\n"); (void)VCLI_ReadResult(sock, &status, &answer, 2000); /* XXX: AZ() ? */ (void)close(sock); printf("%s\n", answer); if (status == CLIS_OK) { exit(0); } fprintf(stderr, "Command failed with error code %u\n", status); exit(1); }
/* * No arguments given, simply pass bytes on stdin/stdout and CLI socket */ static void pass(int sock) { struct pollfd fds[2]; char buf[1024]; int i; char *answer = NULL; unsigned u, status; ssize_t n; fds[0].fd = sock; fds[0].events = POLLIN; fds[1].fd = 0; fds[1].events = POLLIN; while (1) { i = poll(fds, 2, -1); if (i == -1 && errno == EINTR) { continue; } assert(i > 0); if (fds[0].revents & POLLIN) { u = VCLI_ReadResult(fds[0].fd, &status, &answer, timeout); if (u) { if (status == CLIS_COMMS) RL_EXIT(0); if (answer) fprintf(stderr, "%s\n", answer); RL_EXIT(1); } sprintf(buf, "%u\n", status); u = write(1, buf, strlen(buf)); if (answer) { u = write(1, answer, strlen(answer)); u = write(1, "\n", 1); free(answer); answer = NULL; } } if (fds[1].revents & POLLIN || fds[1].revents & POLLHUP) { n = read(fds[1].fd, buf, sizeof buf - 1); if (n == 0) { AZ(shutdown(sock, SHUT_WR)); fds[1].fd = -1; } else if (n < 0) { RL_EXIT(0); } else { buf[n] = '\0'; cli_write(sock, buf); } } } }
/* * Write the command, read the result. * XXX: VCLI_ReadResult will allocate ret->answer. Caller MUST free it. */ void ipc_send(int handle, void *data, int len, struct ipc_ret_t *ret) { assert(data); char buffer[12]; assert(len < 1000000000); assert(len >= 0); assert(threads_started > 0); snprintf(buffer,11,"%09d ",len); ipc_write(handle, buffer, 10); ipc_write(handle, data, len); VCLI_ReadResult(handle, &ret->status, &ret->answer, 5.0); }
static void mcf_askchild(struct cli *cli, const char * const *av, void *priv) { int i; char *q; unsigned u; struct vsb *vsb; (void)priv; /* * Command not recognized in master, try cacher if it is * running. */ if (cli_o <= 0) { if (!strcmp(av[1], "help")) { if (av[2] == NULL || strcmp(av[2], "-j")) VCLI_Out(cli, "No help from child, (not running).\n"); return; } VCLI_SetResult(cli, CLIS_UNKNOWN); VCLI_Out(cli, "Unknown request in manager process " "(child not running).\n" "Type 'help' for more info."); return; } vsb = VSB_new_auto(); for (i = 1; av[i] != NULL; i++) { VSB_quote(vsb, av[i], strlen(av[i]), 0); VSB_putc(vsb, ' '); } VSB_putc(vsb, '\n'); AZ(VSB_finish(vsb)); i = write(cli_o, VSB_data(vsb), VSB_len(vsb)); if (i != VSB_len(vsb)) { VSB_destroy(&vsb); VCLI_SetResult(cli, CLIS_COMMS); VCLI_Out(cli, "CLI communication error"); MGT_Child_Cli_Fail(); return; } VSB_destroy(&vsb); if (VCLI_ReadResult(cli_i, &u, &q, mgt_param.cli_timeout)) MGT_Child_Cli_Fail(); VCLI_SetResult(cli, u); VCLI_Out(cli, "%s", q); free(q); }
int mgt_cli_askchild(unsigned *status, char **resp, const char *fmt, ...) { int i, j; va_list ap; unsigned u; if (cli_buf == NULL) { cli_buf = VSB_new_auto(); AN(cli_buf); } else { VSB_clear(cli_buf); } if (resp != NULL) *resp = NULL; if (status != NULL) *status = 0; if (cli_i < 0 || cli_o < 0) { if (status != NULL) *status = CLIS_CANT; return (CLIS_CANT); } va_start(ap, fmt); AZ(VSB_vprintf(cli_buf, fmt, ap)); va_end(ap); AZ(VSB_finish(cli_buf)); i = VSB_len(cli_buf); assert(i > 0 && VSB_data(cli_buf)[i - 1] == '\n'); j = write(cli_o, VSB_data(cli_buf), i); if (j != i) { if (status != NULL) *status = CLIS_COMMS; if (resp != NULL) *resp = strdup("CLI communication error"); MCH_Cli_Fail(); return (CLIS_COMMS); } if (VCLI_ReadResult(cli_i, &u, resp, mgt_param.cli_timeout)) MCH_Cli_Fail(); if (status != NULL) *status = u; return (u == CLIS_OK ? 0 : u); }
int mgt_cli_askchild(unsigned *status, char **resp, const char *fmt, ...) { int i, j; va_list ap; unsigned u; char buf[params->cli_buffer], *p; if (resp != NULL) *resp = NULL; if (status != NULL) *status = 0; if (cli_i < 0|| cli_o < 0) { if (status != NULL) *status = CLIS_CANT; return (CLIS_CANT); } va_start(ap, fmt); vbprintf(buf, fmt, ap); va_end(ap); p = strchr(buf, '\0'); assert(p != NULL && p > buf && p[-1] == '\n'); i = p - buf; j = write(cli_o, buf, i); if (j != i) { if (status != NULL) *status = CLIS_COMMS; if (resp != NULL) *resp = strdup("CLI communication error"); MGT_Child_Cli_Fail(); return (CLIS_COMMS); } (void)VCLI_ReadResult(cli_i, &u, resp, params->cli_timeout); if (status != NULL) *status = u; if (u == CLIS_COMMS) MGT_Child_Cli_Fail(); return (u == CLIS_OK ? 0 : u); }
static void vadmin_run(struct vadmin_config_t *vadmin, char *cmd, struct ipc_ret_t *ret) { int sock = vadmin->sock; char *p; int nret; assert(cmd); for (p = cmd; *p; p++) { if (!isspace(*p)) break; } if (*p == '\0') { /* cmd is all whitespace */ ret->answer = strdup(""); return; } nret = cli_write(sock, cmd); if (!nret) { warnlog(vadmin->logger, "Communication error with varnishd."); ret->status = 400; ret->answer = strdup("Varnishd disconnected"); vadmin->state = 0; return; } nret = cli_write(sock, "\n"); if (!nret) { warnlog(vadmin->logger, "Communication error with varnishd."); ret->status = 400; ret->answer = strdup("Varnishd disconnected"); vadmin->state = 0; return; } debuglog(vadmin->logger, "Running '%s'",cmd); (void)VCLI_ReadResult(sock, &ret->status, &ret->answer, 2000); debuglog(vadmin->logger, "Got: %d ",ret->status); }
/* * No arguments given, simply pass bytes on stdin/stdout and CLI socket * Send a "banner" to varnish, to provoke a welcome message. */ static void pass(int sock) { struct pollfd fds[2]; char buf[1024]; int i; char *answer = NULL; unsigned u, status; #ifndef HAVE_LIBEDIT int n; #endif #ifdef HAVE_LIBEDIT _line_sock = sock; rl_already_prompted = 1; if (isatty(0)) { rl_callback_handler_install("varnish> ", send_line); } else { rl_callback_handler_install("", send_line); } #endif cli_write(sock, "banner\n"); fds[0].fd = sock; fds[0].events = POLLIN; fds[1].fd = 0; fds[1].events = POLLIN; while (1) { i = poll(fds, 2, -1); assert(i > 0); if (fds[0].revents & POLLIN) { /* Get rid of the prompt, kinda hackish */ u = write(1, "\r \r", 13); u = VCLI_ReadResult(fds[0].fd, &status, &answer, timeout); if (u) { if (status == CLIS_COMMS) RL_EXIT(0); if (answer) fprintf(stderr, "%s\n", answer); RL_EXIT(1); } sprintf(buf, "%u\n", status); u = write(1, buf, strlen(buf)); if (answer) { u = write(1, answer, strlen(answer)); u = write(1, "\n", 1); free(answer); answer = NULL; } #ifdef HAVE_LIBEDIT rl_forced_update_display(); #endif } if (fds[1].revents & POLLIN) { #ifdef HAVE_LIBEDIT rl_callback_read_char(); #else n = read(fds[1].fd, buf, sizeof buf); if (n == 0) { AZ(shutdown(sock, SHUT_WR)); fds[1].fd = -1; } else if (n < 0) { RL_EXIT(0); } else { buf[n] = '\0'; cli_write(sock, buf); } #endif } } }
/* * No arguments given, simply pass bytes on stdin/stdout and CLI socket * Send a "banner" to varnish, to provoke a welcome message. */ static void interactive(int sock) { struct pollfd fds[2]; char buf[1024]; int i; char *answer = NULL; unsigned u, status; _line_sock = sock; rl_already_prompted = 1; rl_callback_handler_install("varnish> ", send_line); rl_attempted_completion_function = varnishadm_completion; fds[0].fd = sock; fds[0].events = POLLIN; fds[1].fd = 0; fds[1].events = POLLIN; /* Grab the commands, for completion */ cli_write(sock, "help\n"); u = VCLI_ReadResult(fds[0].fd, &status, &answer, timeout); if (!u) { char *t, c[128]; if (status == CLIS_COMMS) { RL_EXIT(0); } t = answer; i = 0; while (*t) { if (sscanf(t, "%127s", c) == 1) { commands[i++] = strdup(c); while (*t != '\n' && *t != '\0') t++; if (*t == '\n') t++; } else { /* what? */ fprintf(stderr, "Unknown command '%s' parsing " "help output. Tab completion may be " "broken\n", t); break; } } } cli_write(sock, "banner\n"); while (1) { i = poll(fds, 2, -1); if (i == -1 && errno == EINTR) { continue; } assert(i > 0); if (fds[0].revents & POLLIN) { /* Get rid of the prompt, kinda hackish */ u = write(1, "\r \r", 13); u = VCLI_ReadResult(fds[0].fd, &status, &answer, timeout); if (u) { if (status == CLIS_COMMS) RL_EXIT(0); if (answer) fprintf(stderr, "%s\n", answer); RL_EXIT(1); } sprintf(buf, "%u\n", status); u = write(1, buf, strlen(buf)); if (answer) { u = write(1, answer, strlen(answer)); u = write(1, "\n", 1); free(answer); answer = NULL; } rl_forced_update_display(); } if (fds[1].revents & POLLIN) { rl_callback_read_char(); } } }