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 int varnish_read (user_data_t *ud) /* {{{ */ { struct VSM_data *vd; const c_varnish_stats_t *stats; user_config_t *conf; if ((ud == NULL) || (ud->data == NULL)) return (EINVAL); conf = ud->data; vd = VSM_New(); #if HAVE_VARNISH_V3 VSC_Setup(vd); #endif if (conf->instance != NULL) { int status; status = VSM_n_Arg (vd, conf->instance); if (status < 0) { VSM_Delete (vd); ERROR ("varnish plugin: VSM_n_Arg (\"%s\") failed " "with status %i.", conf->instance, status); return (-1); } } #if HAVE_VARNISH_V3 if (VSC_Open (vd, /* diag = */ 1)) #else /* if HAVE_VARNISH_V4 */ if (VSM_Open (vd)) #endif { VSM_Delete (vd); ERROR ("varnish plugin: Unable to open connection."); return (-1); } #if HAVE_VARNISH_V3 stats = VSC_Main(vd); #else /* if HAVE_VARNISH_V4 */ stats = VSC_Main(vd, NULL); #endif if (!stats) { VSM_Delete (vd); ERROR ("varnish plugin: Unable to get statistics."); return (-1); } varnish_monitor (conf, stats); VSM_Delete (vd); return (0); } /* }}} */