int main(int argc, char **argv) { struct VSM_data *vd; int o, once = 0; float period = 60; /* seconds */ vd = VSM_New(); while ((o = getopt(argc, argv, VSL_ARGS "1fVp:")) != -1) { switch (o) { case '1': AN(VSL_Arg(vd, 'd', NULL)); once = 1; break; case 'f': f_flag = 1; break; case 'p': errno = 0; period = strtol(optarg, NULL, 0); if (errno != 0) { fprintf(stderr, "Syntax error, %s is not a number", optarg); exit(1); } break; case 'V': VCS_Message("varnishtop"); exit(0); case 'm': fprintf(stderr, "-m is not supported\n"); exit(1); default: if (VSL_Arg(vd, o, optarg) > 0) break; usage(); } } if (VSM_Open(vd)) { fprintf(stderr, "%s\n", VSM_Error(vd)); exit (1); } if (once) { do_once(vd); } else { do_curses(vd, period); } exit(0); }
int main(int argc, char *argv[]) { int c; struct VSM_data *vd; const char *address = NULL; vd = VSM_New(); debug = 0; VSL_Arg(vd, 'c', NULL); while ((c = getopt(argc, argv, "a:Dr:n:")) != -1) { switch (c) { case 'a': address = optarg; break; case 'D': ++debug; break; default: if (VSL_Arg(vd, c, optarg) > 0) break; usage(); } } if (address == NULL) { usage(); } if (VSM_Open(vd)) { fprintf(stderr, "%s\n", VSM_Error(vd)); exit(1); } addr_info = init_connection(address); signal(SIGPIPE, SIG_IGN); pthread_attr_init(&thread_attr); /* * XXX: seting the stack size manually reduces the memory usage * XXX: (allowing more threads) and increases speed (?) */ pthread_attr_setstacksize(&thread_attr, 32768); while (VSL_Dispatch(vd, gen_traffic, NULL) == 0) /* nothing */ ; thread_close(-1); exit(0); }
static void * varnishlog_thread(void *priv) { struct varnish *v; struct VSM_data *vsl; CAST_OBJ_NOTNULL(v, priv, VARNISH_MAGIC); vsl = VSM_New(); VSL_Setup(vsl); (void)VSL_Arg(vsl, 'n', v->workdir); VSL_NonBlocking(vsl, 1); while (v->pid && VSL_Open(vsl, 0) != 0) { assert(usleep(VSL_SLEEP_USEC) == 0 || errno == EINTR); } while (v->pid) { if (VSL_Dispatch(vsl, h_addlog, v) < 0) { assert(usleep(v->vsl_sleep) == 0 || errno == EINTR); v->vsl_sleep += v->vsl_sleep; if (v->vsl_sleep > VSL_SLEEP_USEC) v->vsl_sleep = VSL_SLEEP_USEC; } } VSM_Delete(vsl); return (NULL); }
int main(int argc, char **argv) { int o; struct VSM_data *vd; vd = VSM_New(); VSL_Setup(vd); while ((o = getopt(argc, argv, VSL_ARGS "Vw:")) != -1) { switch (o) { case 'V': VCS_Message("varnishhist"); exit(0); case 'w': delay = atoi(optarg); break; default: if (VSL_Arg(vd, o, optarg) > 0) break; usage(); } } if (VSL_Open(vd, 1)) exit(1); log_ten = log(10.0); do_curses(vd); exit(0); }
/* * Parse the -n argument and populate -T if necessary. * * Run on every connect, must do some cleanup. * * XXX: It writes to stdout in addition to the logger because the logger * may not be operational yet. Not sure if this makes sense... At any rate, * the required bit is to write to the logger. */ static int n_arg_sock(struct agent_core_t *core) { struct VSM_data *vsd; struct vadmin_config_t *vadmin; char *p; GET_PRIV(core, vadmin); vsd = VSM_New(); assert(VSL_Arg(vsd, 'n', core->config->n_arg)); if (VSM_Open(vsd, 1)) { logger(vadmin->logger,"Couldn't open VSM"); fprintf(stderr, "Couldn't open VSM\n"); VSM_Delete(vsd); vsd = NULL; } if (core->config->T_arg_orig) { if (core->config->T_arg) free(core->config->T_arg); core->config->T_arg = strdup(core->config->T_arg_orig); } else { if (vsd == NULL) { logger(vadmin->logger,"No -T arg and no shmlog readable."); return -1; } p = VSM_Find_Chunk(vsd, "Arg", "-T", "", NULL); if (p == NULL) { fprintf(stderr, "No -T arg in shared memory\n"); logger(vadmin->logger, "No -T arg in shared memory."); return (-1); } core->config->T_arg = strdup(p); } if (core->config->S_arg == NULL && !vsd) { logger(vadmin->logger, "No shmlog and no -S arg. Unknown if authentication will work."); } if (vsd && core->config->S_arg == NULL) { p = VSM_Find_Chunk(vsd, "Arg", "-S", "", NULL); if (p != NULL) core->config->S_arg = strdup(p); } p = strchr(core->config->T_arg, '\n'); if (p) { assert(p); *p = '\0'; } if (vsd) VSM_Delete(vsd); logger(vadmin->logger, "-T argument computed to: %s", core->config->T_arg ? core->config->T_arg : "(null)"); return (1); }
static void * varnishlog_thread(void *priv) { struct varnish *v; struct VSM_data *vsl; CAST_OBJ_NOTNULL(v, priv, VARNISH_MAGIC); vsl = VSM_New(); (void)VSL_Arg(vsl, 'n', v->workdir); while (v->pid) { if (VSL_Dispatch(vsl, h_addlog, v) <= 0) usleep(100000); } VSM_Delete(vsl); return (NULL); }
static int n_arg_sock(const char *n_arg) { char *T_arg = NULL, *T_start = NULL; char *S_arg = NULL; struct VSM_data *vsd; char *p; int sock; struct VSM_fantom vt; vsd = VSM_New(); assert(VSL_Arg(vsd, 'n', n_arg)); if (VSM_Open(vsd)) { fprintf(stderr, "%s\n", VSM_Error(vsd)); return (-1); } if (!VSM_Get(vsd, &vt, "Arg", "-T", "")) { fprintf(stderr, "No -T arg in shared memory\n"); return (-1); } AN(vt.b); T_start = T_arg = strdup(vt.b); if (VSM_Get(vsd, &vt, "Arg", "-S", "")) { AN(vt.b); S_arg = strdup(vt.b); } sock = -1; while (*T_arg) { p = strchr(T_arg, '\n'); AN(p); *p = '\0'; sock = cli_sock(T_arg, S_arg); if (sock >= 0) break; T_arg = p + 1; } free(T_start); free(S_arg); return (sock); }
static int n_arg_sock(const char *n_arg) { char *T_arg = NULL, *T_start = NULL; char *S_arg = NULL; struct VSM_data *vsd; char *p; int sock; vsd = VSM_New(); assert(VSL_Arg(vsd, 'n', n_arg)); if (VSM_Open(vsd, 1)) { fprintf(stderr, "Could not open shared memory\n"); return (-1); } if (T_arg == NULL) { p = VSM_Find_Chunk(vsd, "Arg", "-T", "", NULL); if (p == NULL) { fprintf(stderr, "No -T arg in shared memory\n"); return (-1); } T_start = T_arg = strdup(p); } if (S_arg == NULL) { p = VSM_Find_Chunk(vsd, "Arg", "-S", "", NULL); if (p != NULL) S_arg = strdup(p); } sock = -1; while (*T_arg) { p = strchr(T_arg, '\n'); AN(p); *p = '\0'; sock = cli_sock(T_arg, S_arg); if (sock >= 0) break; T_arg = p + 1; } free(T_start); free(S_arg); return (sock); }
static void varnish_launch(struct varnish *v) { struct vsb *vsb, *vsb1; int i, nfd, nap; struct vss_addr **ap; char abuf[128], pbuf[128]; struct pollfd fd[2]; enum VCLI_status_e u; char *r; v->vd = VSM_New(); VSC_Setup(v->vd); /* Create listener socket */ nap = VSS_resolve("127.0.0.1", "0", &ap); AN(nap); v->cli_fd = VSS_listen(ap[0], 1); VTCP_myname(v->cli_fd, abuf, sizeof abuf, pbuf, sizeof pbuf); AZ(VSB_finish(v->args)); vtc_log(v->vl, 2, "Launch"); vsb = VSB_new_auto(); AN(vsb); VSB_printf(vsb, "cd ${pwd} &&"); VSB_printf(vsb, " ${varnishd} -d -d -n %s", v->workdir); VSB_printf(vsb, " -l 10m,1m,-"); VSB_printf(vsb, " -p auto_restart=off"); VSB_printf(vsb, " -p syslog_cli_traffic=off"); VSB_printf(vsb, " -a '%s'", "127.0.0.1:0"); VSB_printf(vsb, " -S %s/_S", v->workdir); VSB_printf(vsb, " -M '%s %s'", abuf, pbuf); VSB_printf(vsb, " -P %s/varnishd.pid", v->workdir); VSB_printf(vsb, " %s", VSB_data(v->storage)); VSB_printf(vsb, " %s", VSB_data(v->args)); AZ(VSB_finish(vsb)); vtc_log(v->vl, 3, "CMD: %s", VSB_data(vsb)); vsb1 = macro_expand(v->vl, VSB_data(vsb)); AN(vsb1); VSB_delete(vsb); vsb = vsb1; vtc_log(v->vl, 3, "CMD: %s", VSB_data(vsb)); AZ(pipe(&v->fds[0])); AZ(pipe(&v->fds[2])); v->pid = fork(); assert(v->pid >= 0); if (v->pid == 0) { assert(dup2(v->fds[0], 0) == 0); assert(dup2(v->fds[3], 1) == 1); assert(dup2(1, 2) == 2); AZ(close(v->fds[0])); AZ(close(v->fds[1])); AZ(close(v->fds[2])); AZ(close(v->fds[3])); for (i = 3; i <getdtablesize(); i++) (void)close(i); AZ(execl("/bin/sh", "/bin/sh", "-c", VSB_data(vsb), (char*)0)); exit(1); } else { vtc_log(v->vl, 3, "PID: %ld", (long)v->pid); } AZ(close(v->fds[0])); AZ(close(v->fds[3])); v->fds[0] = v->fds[2]; v->fds[2] = v->fds[3] = -1; VSB_delete(vsb); AZ(pthread_create(&v->tp, NULL, varnish_thread, v)); AZ(pthread_create(&v->tp_vsl, NULL, varnishlog_thread, v)); /* Wait for the varnish to call home */ memset(fd, 0, sizeof fd); fd[0].fd = v->cli_fd; fd[0].events = POLLIN; fd[1].fd = v->fds[0]; fd[1].events = 0; /* Only care about POLLHUP, which is output-only */ i = poll(fd, 2, 10000); vtc_log(v->vl, 4, "CLIPOLL %d 0x%x 0x%x", i, fd[0].revents, fd[1].revents); if (i == 0) { vtc_log(v->vl, 0, "FAIL timeout waiting for CLI connection"); return; } if (fd[1].revents & POLLHUP) { vtc_log(v->vl, 0, "FAIL debug pipe closed"); return; } if (!(fd[0].revents & POLLIN)) { vtc_log(v->vl, 0, "FAIL CLI connection wait failure"); return; } nfd = accept(v->cli_fd, NULL, NULL); if (nfd < 0) { vtc_log(v->vl, 0, "FAIL no CLI connection accepted"); return; } AZ(close(v->cli_fd)); v->cli_fd = nfd; vtc_log(v->vl, 3, "CLI connection fd = %d", v->cli_fd); assert(v->cli_fd >= 0); /* Receive the banner or auth response */ u = varnish_ask_cli(v, NULL, &r); if (vtc_error) return; if (u != CLIS_AUTH) vtc_log(v->vl, 0, "CLI auth demand expected: %u %s", u, r); bprintf(abuf, "%s/_S", v->workdir); nfd = open(abuf, O_RDONLY); assert(nfd >= 0); assert(sizeof abuf >= CLI_AUTH_RESPONSE_LEN + 7); strcpy(abuf, "auth "); VCLI_AuthResponse(nfd, r, abuf + 5); AZ(close(nfd)); free(r); strcat(abuf, "\n"); u = varnish_ask_cli(v, abuf, &r); if (vtc_error) return; if (u != CLIS_OK) vtc_log(v->vl, 0, "CLI auth command failed: %u %s", u, r); free(r); (void)VSL_Arg(v->vd, 'n', v->workdir); AZ(VSC_Open(v->vd, 1)); }
static unsigned int vlog_reply(struct http_request *request, void *data) { struct vlog_req_priv vrp = { .limit = 10 }; int disp_status; char *p; char *tag = NULL; char *tag_re = NULL; struct VSL_data *vsl = NULL; struct VSLQ *vslq = NULL; struct VSL_cursor *c = NULL; enum VSL_grouping_e grouping = VSL_g_request; struct agent_core_t *core = data; p = next_slash(request->url + 1); if (p) { char *lim = strdup(p); assert(lim); char *tmp2 = strchr(lim, '/'); if (tmp2 && *tmp2) *tmp2 = '\0'; int j = sscanf(lim, "%u", &vrp.limit); if(j != 1) { free(lim); http_reply(request->connection, 500, "Not a number"); return 0; } free(lim); p = next_slash(p); } if (p) { tag = strdup(p); char *tmp2 = strchr(tag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } if (p) { tag_re = strdup(p); char *tmp2 = strchr(tag_re, '/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } vrp.answer = VSB_new_auto(); assert(vrp.answer != NULL); vrp.vsm = VSM_New(); assert(vrp.vsm); if (!VSM_n_Arg(vrp.vsm, core->config->n_arg)) { VSB_printf(vrp.answer, "Error in creating shmlog: %s", VSM_Error(vrp.vsm)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } if (VSM_Open(vrp.vsm) != 0) { VSB_printf(vrp.answer, "Error in opening shmlog: %s", VSM_Error(vrp.vsm)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } vsl = VSL_New(); assert(vsl); if (tag) { grouping = VSL_g_raw; if (VSL_Arg(vsl, 'i', tag) < 0) { VSB_printf(vrp.answer, "Unable to specify tag '%s': %s", tag, VSL_Error(vsl)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } if (tag_re) { VSL_Arg(vsl,'I', tag_re); } } c = VSL_CursorVSM(vsl, vrp.vsm, VSL_COPT_BATCH | VSL_COPT_TAILSTOP); if (c == NULL) { VSB_printf(vrp.answer, "Can't open log (%s)", VSL_Error(vsl)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } vslq = VSLQ_New(vsl, &c, grouping, NULL); if (vslq == NULL) { VSB_clear(vrp.answer); VSB_printf(vrp.answer, "Error in creating query: %s", VSL_Error(vsl)); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } VSB_printf(vrp.answer, "{ \"log\": ["); do { disp_status = VSLQ_Dispatch(vslq, vlog_cb_func, &vrp); } while (disp_status == 1 && vrp.entries < vrp.limit); VSB_printf(vrp.answer, "\n] }\n"); assert(VSB_finish(vrp.answer) == 0); if (VSB_len(vrp.answer) > 1) { struct http_response *resp = http_mkresp(request->connection, 200, NULL); resp->data = VSB_data(vrp.answer); resp->ndata = VSB_len(vrp.answer); http_add_header(resp,"Content-Type","application/json"); send_response(resp); http_free_resp(resp); } else { http_reply(request->connection, 500, "FAIL"); } cleanup: free(tag); free(tag_re); VSB_delete(vrp.answer); if (vslq) VSLQ_Delete(&vslq); if (vsl) VSL_Delete(vsl); if (vrp.vsm) VSM_Delete(vrp.vsm); vrp.answer = NULL; return 0; } void vlog_init(struct agent_core_t *core) { struct agent_plugin_t *plug; struct vlog_priv_t *priv; ALLOC_OBJ(priv); plug = plugin_find(core,"vlog"); plug->data = priv; http_register_url(core, "/log", M_GET, vlog_reply, core); }
static unsigned int vlog_reply(struct httpd_request *request, void *data) { struct vlog_priv_t *vlog; int ret; char *limit = NULL; char *p; char *tag = NULL; char *itag = NULL; struct agent_core_t *core = data; GET_PRIV(data,vlog); p = next_slash(request->url + 1); assert(vlog->tag==NULL); assert(vlog->answer == NULL); if (p) { limit = strdup(p); assert(limit); char *tmp2 = index(limit,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; if(!(atoi(limit) > 0)) { free(limit); send_response_fail(request->connection,"Not a number"); return 0; } p = next_slash(p); } if (p) { tag = strdup(p); char *tmp2 = index(tag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } if (p) { itag = strdup(p); char *tmp2 = index(itag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } vlog->answer = VSB_new_auto(); assert(vlog->answer != NULL); vlog->vd = VSM_New(); assert(VSL_Arg(vlog->vd, 'n', core->config->n_arg)); VSL_Setup(vlog->vd); VSL_Arg(vlog->vd, 'd', ""); if (tag) { VSL_Arg(vlog->vd, 'i', tag); if (itag) VSL_Arg(vlog->vd,'I',itag); } else { VSL_Arg(vlog->vd, 'k', limit ? limit : "10"); } if (limit) free(limit); VSB_printf(vlog->answer, "{ \"log\": ["); ret = VSL_Open(vlog->vd, 1); assert(!ret); if (tag == NULL) { do_order(vlog); } else { do_unorder(vlog); } if (tag) free(tag); if (itag) free(itag); VSB_printf(vlog->answer, "\n] }\n"); assert(VSB_finish(vlog->answer) == 0); if (VSB_len(vlog->answer) > 1) { send_response(request->connection, 200, VSB_data(vlog->answer), VSB_len(vlog->answer)); } else { send_response_fail(request->connection, "FAIL"); } VSB_clear(vlog->answer); VSM_Close(vlog->vd); vlog->answer = NULL; vlog->entries = 0; return 0; }
int VUT_Arg(int opt, const char *arg) { int i; char *p; switch (opt) { case 'd': /* Head */ VUT.d_opt = 1; return (1); case 'D': /* Daemon mode */ VUT.D_opt = 1; return (1); case 'g': /* Grouping */ return (VUT_g_Arg(arg)); case 'k': /* Log transaction limit */ VUT.k_arg = (int)strtol(arg, &p, 10); if (*p != '\0' || VUT.k_arg <= 0) VUT_Error(1, "-k: Invalid number '%s'", arg); return (1); case 'n': /* Varnish instance name */ REPLACE(VUT.n_arg, arg); return (1); case 'N': /* Varnish stale VSM file */ REPLACE(VUT.N_arg, arg); return (1); case 'P': /* PID file */ REPLACE(VUT.P_arg, arg); return (1); case 'q': /* Query to use */ REPLACE(VUT.q_arg, arg); return (1); case 'r': /* Binary file input */ REPLACE(VUT.r_arg, arg); return (1); case 't': /* VSM connect timeout */ if (!strcasecmp("off", arg)) VUT.t_arg = -1.; else { VUT.t_arg = VNUM(arg); if (isnan(VUT.t_arg)) VUT_Error(1, "-t: Syntax error"); if (VUT.t_arg < 0.) VUT_Error(1, "-t: Range error"); } return (1); case 'V': /* Print version number and exit */ VCS_Message(VUT.progname); exit(0); default: AN(VUT.vsl); i = VSL_Arg(VUT.vsl, opt, arg); if (i < 0) VUT_Error(1, "%s", VSL_Error(VUT.vsl)); return (i); } }