Beispiel #1
0
void
mgt_cli_setup(int fdi, int fdo, int verbose, const char *ident,
    mgt_cli_close_f *closefunc, void *priv)
{
	struct cli *cli;
	struct vev *ev;

	(void)ident;
	(void)verbose;
	if (cls == NULL)
		mgt_cli_init_cls();

	cli = VCLS_AddFd(cls, fdi, fdo, closefunc, priv);

	cli->ident = strdup(ident);

	if (fdi != 0 && secret_file != NULL) {
		cli->auth = MCF_NOAUTH;
		mgt_cli_challenge(cli);
	} else {
		cli->auth = MCF_AUTH;
		mcf_banner(cli, NULL, NULL);
	}
	AZ(VSB_finish(cli->sb));
	(void)VCLI_WriteResult(fdo, cli->result, VSB_data(cli->sb));


	ev = vev_new();
	AN(ev);
	ev->name = cli->ident;
	ev->fd = fdi;
	ev->fd_flags = EV_RD;
	ev->callback = mgt_cli_callback2;
	ev->priv = cli;
	AZ(vev_add(mgt_evb, ev));
}
Beispiel #2
0
Lck_CondWait(pthread_cond_t *cond, struct lock *lck, double when)
{
	struct ilck *ilck;
	int retval = 0;
	struct timespec ts;
	double t;

	CAST_OBJ_NOTNULL(ilck, lck->priv, ILCK_MAGIC);
	AN(ilck->held);
	assert(pthread_equal(ilck->owner, pthread_self()));
	ilck->held = 0;
	if (when == 0) {
		AZ(pthread_cond_wait(cond, &ilck->mtx));
	} else {
		ts.tv_nsec = (long)(modf(when, &t) * 1e9);
		ts.tv_sec = (long)t;
		retval = pthread_cond_timedwait(cond, &ilck->mtx, &ts);
		assert(retval == 0 || retval == ETIMEDOUT);
	}
	AZ(ilck->held);
	ilck->held = 1;
	ilck->owner = pthread_self();
	return (retval);
}
Beispiel #3
0
static void
vcc_expr_tostring(struct expr **e, enum var_type fmt)
{
	const char *p;

	CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC);
	AN(fmt == STRING || fmt == STRING_LIST);

	p = NULL;
	switch((*e)->fmt) {
	case BACKEND:	p = "VRT_backend_string(sp, \v1)"; break;
	case BOOL:	p = "VRT_bool_string(sp, \v1)"; break;
	case DURATION:	p = "VRT_double_string(sp, \v1)"; break;
			 /* XXX: should DURATION insist on "s" suffix ? */
	case INT:	p = "VRT_int_string(sp, \v1)"; break;
	case IP:	p = "VRT_IP_string(sp, \v1)"; break;
	case BYTES:	p = "VRT_double_string(sp, \v1)"; break; /* XXX */
	case REAL:	p = "VRT_double_string(sp, \v1)"; break;
	case TIME:	p = "VRT_time_string(sp, \v1)"; break;
	default:	break;
	}
	if (p != NULL)
		*e = vcc_expr_edit(fmt, p, *e, NULL);
}
static const char *
ban_error(struct ban_proto *bp, const char *fmt, ...)
{
	va_list ap;

	CHECK_OBJ_NOTNULL(bp, BAN_PROTO_MAGIC);
	AN(bp->vsb);

	/* First error is sticky */
	if (bp->err == NULL) {
		if (fmt == ban_build_err_no_mem) {
			bp->err = ban_build_err_no_mem;
		} else {
			/* Record the error message in the vsb */
			VSB_clear(bp->vsb);
			va_start(ap, fmt);
			(void)VSB_vprintf(bp->vsb, fmt, ap);
			va_end(ap);
			AZ(VSB_finish(bp->vsb));
			bp->err = VSB_data(bp->vsb);
		}
	}
	return (bp->err);
}
Beispiel #5
0
static struct vsmw_cluster *
vsmw_newcluster(struct vsmw *vsmw, size_t len, const char *pfx)
{
	struct vsmw_cluster *vc;
	int fd;
	size_t ps;

	ALLOC_OBJ(vc, VSMW_CLUSTER_MAGIC);
	AN(vc);

	vsmw_mkent(vsmw, pfx);
	REPLACE(vc->fn, VSB_data(vsmw->vsb));

	VTAILQ_INSERT_TAIL(&vsmw->clusters, vc, list);

	ps = getpagesize();
	len = RUP2(len, ps);
	vc->len = len;

	fd = openat(vsmw->vdirfd, vc->fn,
	    O_RDWR | O_CREAT | O_EXCL, vsmw->mode);
	assert(fd >= 0);

	AZ(VFIL_allocate(fd, (off_t)len, 1));

	vc->ptr = (void *)mmap(NULL, len,
	    PROT_READ|PROT_WRITE,
	    MAP_HASSEMAPHORE | MAP_NOSYNC | MAP_SHARED,
	    fd, 0);

	AZ(close(fd));
	assert(vc->ptr != MAP_FAILED);
	(void)mlock(vc->ptr, len);

	return (vc);
}
Beispiel #6
0
void
VSMW_DestroyCluster(struct vsmw *vsmw, struct vsmw_cluster **vsmcp)
{
	struct vsmw_cluster *vc;

	vsmw_lock();
	CHECK_OBJ_NOTNULL(vsmw, VSMW_MAGIC);
	AN(vsmcp);
	vc = *vsmcp;
	*vsmcp = NULL;
	CHECK_OBJ_NOTNULL(vc, VSMW_CLUSTER_MAGIC);

	if (vc->cseg != NULL) {
		/*
		 * Backends go on the cool list, so the VGC cluster is
		 * destroyed before they are.  Solve this by turning the
		 * cluster into an anonymous cluster which dies with the
		 * refcount on it.
		 */
		vsmw_delseg(vsmw, vc->cseg, 1);
		vc->cseg = NULL;
		if (vc->refs > 0) {
			vsmw_unlock();
			return;
		}
	}
	AZ(munmap(vc->ptr, vc->len));

	AZ(vc->refs);
	VTAILQ_REMOVE(&vsmw->clusters, vc, list);
	if (unlinkat(vsmw->vdirfd, vc->fn, 0))
		assert (errno == ENOENT);
	REPLACE(vc->fn, NULL);
	FREE_OBJ(vc);
	vsmw_unlock();
}
Beispiel #7
0
void
VRT_hashdata(VRT_CTX, const char *str, ...)
{
	va_list ap;
	const char *p;

	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
	CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
	AN(ctx->specific);
	HSH_AddString(ctx->req, ctx->specific, str);
	va_start(ap, str);
	while (1) {
		p = va_arg(ap, const char *);
		if (p == vrt_magic_string_end)
			break;
		HSH_AddString(ctx->req, ctx->specific, p);
	}
	va_end(ap);
	/*
	 * Add a 'field-separator' to make it more difficult to
	 * manipulate the hash.
	 */
	HSH_AddString(ctx->req, ctx->specific, NULL);
}
Beispiel #8
0
enum vgzret_e
VGZ_WrwGunzip(struct req *req, struct vgz *vg, const void *ibuf,
    ssize_t ibufl)
{
	enum vgzret_e vr;
	size_t dl;
	const void *dp;
	struct worker *wrk;

	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
	wrk = req->wrk;
	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(vg, VGZ_MAGIC);
	AN(vg->m_buf);
	VGZ_Ibuf(vg, ibuf, ibufl);
	if (ibufl == 0)
		return (VGZ_OK);
	do {
		if (vg->m_len == vg->m_sz)
			vr = VGZ_STUCK;
		else {
			vr = VGZ_Gunzip(vg, &dp, &dl);
			vg->m_len += dl;
		}
		if (vr < VGZ_OK)
			return (vr);
		if (vg->m_len == vg->m_sz || vr == VGZ_STUCK) {
			(void)VDP_bytes(req, VDP_FLUSH, vg->m_buf, vg->m_len);
			vg->m_len = 0;
			VGZ_Obuf(vg, vg->m_buf, vg->m_sz);
		}
	} while (!VGZ_IbufEmpty(vg));
	if (vr == VGZ_STUCK)
		vr = VGZ_OK;
	return (vr);
}
Beispiel #9
0
void
VSL(enum VSL_tag_e tag, int id, const char *fmt, ...)
{
    va_list ap;
    unsigned n, mlen = cache_param->shm_reclen;
    char buf[mlen];

    /*
     * XXX: consider formatting into a stack buffer then move into
     * XXX: shmlog with vslr().
     */
    AN(fmt);
    va_start(ap, fmt);

    if (strchr(fmt, '%') == NULL) {
        vslr(tag, id, fmt, strlen(fmt));
    } else {
        n = vsnprintf(buf, mlen, fmt, ap);
        if (n > mlen)
            n = mlen;
        vslr(tag, id, buf, n);
    }
    va_end(ap);
}
Beispiel #10
0
static void
varnish_vcl(struct varnish *v, const char *vcl, enum VCLI_status_e expect)
{
	struct vsb *vsb;
	enum VCLI_status_e u;

	if (v->cli_fd < 0)
		varnish_launch(v);
	if (vtc_error)
		return;
	vsb = VSB_new_auto();
	AN(vsb);

	VSB_printf(vsb, "vcl.inline vcl%d << %s\n%s\n%s\n",
	    ++v->vcl_nbr, NONSENSE, vcl, NONSENSE);
	AZ(VSB_finish(vsb));

	u = varnish_ask_cli(v, VSB_data(vsb), NULL);
	if (u != expect) {
		VSB_delete(vsb);
		vtc_log(v->vl, 0,
		    "VCL compilation got %u expected %u",
		    u, expect);
		return;
	}
	if (u == CLIS_OK) {
		VSB_clear(vsb);
		VSB_printf(vsb, "vcl.use vcl%d", v->vcl_nbr);
		AZ(VSB_finish(vsb));
		u = varnish_ask_cli(v, VSB_data(vsb), NULL);
		assert(u == CLIS_OK);
	} else {
		vtc_log(v->vl, 2, "VCL compilation failed (as expected)");
	}
	VSB_delete(vsb);
}
Beispiel #11
0
int
SES_Schedule(struct sess *sp)
{
	struct sessmem *sm;
	struct sesspool *pp;

	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);

	AZ(sp->wrk);

	sm = sp->mem;
	CHECK_OBJ_NOTNULL(sm, SESSMEM_MAGIC);

	pp = sm->pool;
	CHECK_OBJ_NOTNULL(pp, SESSPOOL_MAGIC);

	AN(pp->pool);

	if (Pool_Schedule(pp->pool, sp)) {
		SES_Delete(sp, "dropped");
		return (1);
	}
	return (0);
}
Beispiel #12
0
struct waiter *
Waiter_New(void)
{
	struct waiter *w;

	AN(waiter);
	AN(waiter->name);
	AN(waiter->init);
	AN(waiter->enter);
	AN(waiter->fini);

	w = calloc(1, sizeof (struct waiter) + waiter->size);
	AN(w);
	INIT_OBJ(w, WAITER_MAGIC);
	w->priv = (void*)(w + 1);
	w->impl = waiter;
	VTAILQ_INIT(&w->waithead);
	w->heap = binheap_new(w, waited_cmp, waited_update);

	waiter->init(w);

	return (w);
}
Beispiel #13
0
static void
vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
{
	struct expr *e1, *e2;
	const struct symbol *sym;
	double d;

	*e = NULL;
	if (tl->t->tok == '(') {
		SkipToken(tl, '(');
		vcc_expr0(tl, &e2, fmt);
		ERRCHK(tl);
		SkipToken(tl, ')');
		*e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL);
		return;
	}
	switch(tl->t->tok) {
	case ID:
		/*
		 * XXX: what if var and func/proc had same name ?
		 * XXX: look for SYM_VAR first for consistency ?
		 */
		sym = VCC_FindSymbol(tl, tl->t, SYM_NONE);
		if (sym == NULL || sym->eval == NULL) {
			VSB_printf(tl->sb, "Symbol not found: ");
			vcc_ErrToken(tl, tl->t);
			VSB_printf(tl->sb, " (expected type %s):\n",
			    vcc_Type(fmt));
			vcc_ErrWhere(tl, tl->t);
			return;
		}
		AN(sym);
		switch(sym->kind) {
		case SYM_VAR:
		case SYM_FUNC:
		case SYM_BACKEND:
			AN(sym->eval);
			AZ(*e);
			sym->eval(tl, e, sym);
			return;
		default:
			break;
		}
		VSB_printf(tl->sb,
		    "Symbol type (%s) can not be used in expression.\n",
		    VCC_SymKind(tl, sym));
		vcc_ErrWhere(tl, tl->t);
		return;
	case CSTR:
		assert(fmt != VOID);
		e1 = vcc_new_expr();
		EncToken(e1->vsb, tl->t);
		e1->fmt = STRING;
		e1->t1 = tl->t;
		e1->constant = 1;
		vcc_NextToken(tl);
		AZ(VSB_finish(e1->vsb));
		*e = e1;
		break;
	case CNUM:
		/*
		 * XXX: %g may not have enough decimals by default
		 * XXX: but %a is ugly, isn't it ?
		 */
		assert(fmt != VOID);
		if (fmt == DURATION) {
			vcc_RTimeVal(tl, &d);
			ERRCHK(tl);
			e1 = vcc_mk_expr(DURATION, "%g", d);
		} else if (fmt == BYTES) {
			vcc_ByteVal(tl, &d);
			ERRCHK(tl);
			e1 = vcc_mk_expr(BYTES, "%.1f", d);
			ERRCHK(tl);
		} else if (fmt == REAL) {
			e1 = vcc_mk_expr(REAL, "%g", vcc_DoubleVal(tl));
			ERRCHK(tl);
		} else {
			e1 = vcc_mk_expr(INT, "%.*s", PF(tl->t));
			vcc_NextToken(tl);
		}
		e1->constant = 1;
		*e = e1;
		break;
	default:
		VSB_printf(tl->sb, "Unknown token ");
		vcc_ErrToken(tl, tl->t);
		VSB_printf(tl->sb, " when looking for %s\n\n", vcc_Type(fmt));
		vcc_ErrWhere(tl, tl->t);
		break;
	}
}
Beispiel #14
0
static SF(jtsortb2){A z;B up;I i,ii,j,p,yv[4];US*v,*wv,x,zz[4];
 GA(z,AT(w),AN(w),AR(w),AS(w)); v=(US*)AV(z);
 wv=(US*)AV(w); p=4; up=1==jt->compgt;
 DO(p, yv[i]=0;); 
Beispiel #15
0
void
vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
{
	const char *p, *r;
	struct expr *e1, *e2;
	enum var_type fmt;
	char buf[32];

	assert(sym->kind == SYM_FUNC || sym->kind == SYM_PROC);
	AN(sym->cfunc);
	AN(sym->args);
	SkipToken(tl, ID);
	SkipToken(tl, '(');
	p = sym->args;
	e2 = vcc_mk_expr(vcc_arg_type(&p), "%s(sp\v+", sym->cfunc);
	while (*p != '\0') {
		e1 = NULL;
		fmt = vcc_arg_type(&p);
		if (fmt == VOID && !strcmp(p, "PRIV_VCL")) {
			r = strchr(sym->name, '.');
			AN(r);
			e1 = vcc_mk_expr(VOID, "&vmod_priv_%.*s",
			    r - sym->name, sym->name);
			p += strlen(p) + 1;
		} else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) {
			bprintf(buf, "vmod_priv_%u", tl->nvmodpriv++);
			Fh(tl, 0, "struct vmod_priv %s;\n", buf);
			e1 = vcc_mk_expr(VOID, "&%s", buf);
			p += strlen(p) + 1;
		} else if (fmt == ENUM) {
			ExpectErr(tl, ID);
			ERRCHK(tl);
			r = p;
			do {
				if (vcc_IdIs(tl->t, p))
					break;
				p += strlen(p) + 1;
			} while (*p != '\0');
			if (*p == '\0') {
				VSB_printf(tl->sb, "Wrong enum value.");
				VSB_printf(tl->sb, "  Expected one of:\n");
				do {
					VSB_printf(tl->sb, "\t%s\n", r);
					r += strlen(r) + 1;
				} while (*r != '\0');
				vcc_ErrWhere(tl, tl->t);
				return;
			}
			e1 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t));
			while (*p != '\0')
				p += strlen(p) + 1;
			p++;
			SkipToken(tl, ID);
			if (*p != '\0')
				SkipToken(tl, ',');
		} else if (fmt == HEADER) {
			const struct var *v;
			sym = VCC_FindSymbol(tl, tl->t, SYM_NONE);
			ERRCHK(tl);
			SkipToken(tl, ID);
			if (sym == NULL) {
				VSB_printf(tl->sb, "Symbol not found.\n");
				vcc_ErrWhere(tl, tl->t);
				return;
			}
			vcc_AddUses(tl, tl->t, sym->r_methods, "Not available");
			if (sym->kind != SYM_VAR) {
				VSB_printf(tl->sb, "Wrong kind of symbol.\n");
				vcc_ErrWhere(tl, tl->t);
				return;
			}
			AN(sym->var);
			v = sym->var;
			if (v->http == NULL) {
				VSB_printf(tl->sb,
				    "Variable not an HTTP header.\n");
				vcc_ErrWhere(tl, tl->t);
				return;
			}
			e1 = vcc_mk_expr(VOID, "%s, \"%s\"", v->http, v->hdr);
			if (*p != '\0')
				SkipToken(tl, ',');
		} else {
			vcc_expr0(tl, &e1, fmt);
			ERRCHK(tl);
			if (e1->fmt != fmt) {
				VSB_printf(tl->sb, "Wrong argument type.");
				VSB_printf(tl->sb, "  Expected %s.",
					vcc_Type(fmt));
				VSB_printf(tl->sb, "  Got %s.\n",
					vcc_Type(e1->fmt));
				vcc_ErrWhere2(tl, e1->t1, tl->t);
				return;
			}
			assert(e1->fmt == fmt);
			if (e1->fmt == STRING_LIST) {
				e1 = vcc_expr_edit(STRING_LIST,
				    "\v+\n\v1,\nvrt_magic_string_end\v-",
				    e1, NULL);
			}
			if (*p != '\0')
				SkipToken(tl, ',');
		}
		e2 = vcc_expr_edit(e2->fmt, "\v1,\n\v2", e2, e1);
	}
	SkipToken(tl, ')');
	e2 = vcc_expr_edit(e2->fmt, "\v1\n)\v-", e2, NULL);
	*e = e2;
}
Beispiel #16
0
void
parse_string(const char *spec, const struct cmds *cmd, void *priv,
    struct vtclog *vl)
{
	char *token_s[MAX_TOKENS], *token_e[MAX_TOKENS];
	struct vsb *token_exp[MAX_TOKENS];
	char *p, *q, *f, *buf;
	int nest_brace;
	int tn;
	const struct cmds *cp;

	AN(spec);
	buf = strdup(spec);
	AN(buf);
	for (p = buf; *p != '\0'; p++) {
		if (vtc_error || vtc_stop)
			break;
		/* Start of line */
		if (isspace(*p))
			continue;
		if (*p == '\n')
			continue;

		if (*p == '#') {
			for (; *p != '\0' && *p != '\n'; p++)
				;
			if (*p == '\0')
				break;
			continue;
		}

		q = strchr(p, '\n');
		if (q == NULL)
			q = strchr(p, '\0');
		if (q - p > 60)
			vtc_log(vl, 2, "=== %.60s...", p);
		else
			vtc_log(vl, 2, "=== %.*s", (int)(q - p), p);

		/* First content on line, collect tokens */
		tn = 0;
		f = p;
		while (*p != '\0') {
			assert(tn < MAX_TOKENS);
			if (*p == '\n') { /* End on NL */
				break;
			}
			if (isspace(*p)) { /* Inter-token whitespace */
				p++;
				continue;
			}
			if (*p == '\\' && p[1] == '\n') { /* line-cont */
				p += 2;
				continue;
			}
			if (*p == '"') { /* quotes */
				token_s[tn] = ++p;
				q = p;
				for (; *p != '\0'; p++) {
					if (*p == '"')
						break;
					if (*p == '\\') {
						p += VAV_BackSlash(p, q) - 1;
						q++;
					} else {
						if (*p == '\n')
							vtc_log(vl, 0,
				"Unterminated quoted string in line: %*.*s",
				(int)(p - f), (int)(p - f), f);
						assert(*p != '\n');
						*q++ = *p;
					}
				}
				token_e[tn++] = q;
				p++;
			} else if (*p == '{') { /* Braces */
				nest_brace = 0;
				token_s[tn] = p + 1;
				for (; *p != '\0'; p++) {
					if (*p == '{')
						nest_brace++;
					else if (*p == '}') {
						if (--nest_brace == 0)
							break;
					}
				}
				assert(*p == '}');
				token_e[tn++] = p++;
			} else { /* other tokens */
				token_s[tn] = p;
				for (; *p != '\0' && !isspace(*p); p++)
					;
				token_e[tn++] = p;
			}
		}
		assert(tn < MAX_TOKENS);
		token_s[tn] = NULL;
		for (tn = 0; token_s[tn] != NULL; tn++) {
			token_exp[tn] = NULL;
			AN(token_e[tn]);	/*lint !e771 */
			*token_e[tn] = '\0';	/*lint !e771 */
			if (NULL == strstr(token_s[tn], "${"))
				continue;
			token_exp[tn] = macro_expand(vl, token_s[tn]);
			if (vtc_error) {
				return;
			}
			token_s[tn] = VSB_data(token_exp[tn]);
			token_e[tn] = strchr(token_s[tn], '\0');
		}

		for (cp = cmd; cp->name != NULL; cp++)
			if (!strcmp(token_s[0], cp->name))
				break;
		if (cp->name == NULL) {
			vtc_log(vl, 0, "Unknown command: \"%s\"", token_s[0]);
			return;
		}

		assert(cp->cmd != NULL);
		cp->cmd(token_s, priv, cmd, vl);
	}
}
Beispiel #17
0
static void dwr(A w){if(w){C*p=CAV(w); DO(AN(w), jputc(p[i]));}}
Beispiel #18
0
static void
vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs)
{
	char *p;
	int i;

	AN(plhs);
	AZ(*plhs);
	ALLOC_OBJ(*plhs, VEX_LHS_MAGIC);
	AN(*plhs);
	(*plhs)->tags = vbit_init(SLT__MAX);
	(*plhs)->level = -1;

	if (vxp->t->tok == '{') {
		/* Transaction level limits */
		vxp_NextToken(vxp);
		if (vxp->t->tok != VAL) {
			VSB_printf(vxp->sb, "Expected integer got '%.*s' ",
			    PF(vxp->t));
			vxp_ErrWhere(vxp, vxp->t, -1);
			return;
		}
		(*plhs)->level = (int)strtol(vxp->t->dec, &p, 0);
		if ((*plhs)->level < 0) {
			VSB_printf(vxp->sb, "Expected positive integer ");
			vxp_ErrWhere(vxp, vxp->t, -1);
			return;
		}
		if (*p == '-') {
			(*plhs)->level_pm = -1;
			p++;
		} else if (*p == '+') {
			(*plhs)->level_pm = 1;
			p++;
		}
		if (*p) {
			VSB_printf(vxp->sb, "Syntax error in level limit ");
			vxp_ErrWhere(vxp, vxp->t, -1);
			return;
		}
		vxp_NextToken(vxp);
		ExpectErr(vxp, '}');
		vxp_NextToken(vxp);
	}

	while (1) {
		/* The tags this expression applies to */
		if (vxp->t->tok != VAL) {
			VSB_printf(vxp->sb, "Expected VSL tag name got '%.*s' ",
			    PF(vxp->t));
			vxp_ErrWhere(vxp, vxp->t, -1);
			return;
		}
		i = VSL_Glob2Tags(vxp->t->dec, -1, vsl_vbm_bitset,
		    (*plhs)->tags);
		if (i == -1) {
			VSB_printf(vxp->sb, "Tag name matches zero tags ");
			vxp_ErrWhere(vxp, vxp->t, -1);
			return;
		}
		if (i == -2) {
			VSB_printf(vxp->sb, "Tag name is ambiguous ");
			vxp_ErrWhere(vxp, vxp->t, -1);
			return;
		}
		if (i == -3) {
			VSB_printf(vxp->sb, "Syntax error in tag name ");
			vxp_ErrWhere(vxp, vxp->t, -1);
			return;
		}
		assert(i > 0);
		vxp_NextToken(vxp);
		if (vxp->t->tok != ',')
			break;
		vxp_NextToken(vxp);
	}

	if (vxp->t->tok == ':') {
		/* Record prefix */
		vxp_NextToken(vxp);
		if (vxp->t->tok != VAL) {
			VSB_printf(vxp->sb, "Expected string got '%.*s' ",
			    PF(vxp->t));
			vxp_ErrWhere(vxp, vxp->t, -1);
			return;
		}
		AN(vxp->t->dec);
		(*plhs)->prefix = strdup(vxp->t->dec);
		AN((*plhs)->prefix);
		(*plhs)->prefixlen = strlen((*plhs)->prefix);
		vxp_NextToken(vxp);
	}

	if (vxp->t->tok == '[') {
		/* LHS field [] */
		vxp_NextToken(vxp);
		if (vxp->t->tok != VAL) {
			VSB_printf(vxp->sb, "Expected integer got '%.*s' ",
			    PF(vxp->t));
			vxp_ErrWhere(vxp, vxp->t, -1);
			return;
		}
		(*plhs)->field = (int)strtol(vxp->t->dec, &p, 0);
		if (*p || (*plhs)->field <= 0) {
			VSB_printf(vxp->sb, "Expected positive integer ");
			vxp_ErrWhere(vxp, vxp->t, -1);
			return;
		}
		vxp_NextToken(vxp);
		ExpectErr(vxp, ']');
		vxp_NextToken(vxp);
	}
}
Beispiel #19
0
static enum fetch_step
vbf_stp_fetchbody(struct worker *wrk, struct busyobj *bo)
{
	ssize_t l;
	uint8_t *ptr;
	enum vfp_status vfps = VFP_ERROR;
	ssize_t est;
	struct vfp_ctx *vfc;

	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
	vfc = bo->vfc;
	CHECK_OBJ_NOTNULL(vfc, VFP_CTX_MAGIC);

	AN(vfc->vfp_nxt);

	est = bo->htc->content_length;
	if (est < 0)
		est = 0;

	do {
		if (vfc->oc->flags & OC_F_ABANDON) {
			/*
			 * A pass object and delivery was terminated
			 * We don't fail the fetch, in order for hit-for-pass
			 * objects to be created.
			 */
			AN(vfc->oc->flags & OC_F_PASS);
			VSLb(wrk->vsl, SLT_Debug,
			    "Fetch: Pass delivery abandoned");
			bo->htc->doclose = SC_RX_BODY;
			break;
		}
		AZ(vfc->failed);
		l = est;
		assert(l >= 0);
		if (VFP_GetStorage(vfc, &l, &ptr) != VFP_OK) {
			bo->htc->doclose = SC_RX_BODY;
			break;
		}

		AZ(vfc->failed);
		vfps = VFP_Suck(vfc, ptr, &l);
		if (l > 0 && vfps != VFP_ERROR) {
			bo->acct.beresp_bodybytes += l;
			VFP_Extend(vfc, l);
			if (est >= l)
				est -= l;
			else
				est = 0;
		}
	} while (vfps == VFP_OK);

	if (vfc->failed) {
		(void)VFP_Error(vfc, "Fetch pipeline failed to process");
		bo->htc->doclose = SC_RX_BODY;
		VFP_Close(vfc);
		VDI_Finish(wrk, bo);
		if (!bo->do_stream) {
			assert(bo->fetch_objcore->boc->state < BOS_STREAM);
			// XXX: doclose = ?
			return (F_STP_ERROR);
		} else {
			wrk->stats->fetch_failed++;
			return (F_STP_FAIL);
		}
	}

	ObjTrimStore(wrk, vfc->oc);
	return (F_STP_FETCHEND);
}
VDP_ESI(struct req *req, enum vdp_action act, void **priv,
    const void *ptr, ssize_t len)
{
	uint8_t *q, *r;
	ssize_t l = 0;
	uint32_t icrc = 0;
	uint8_t tailbuf[8 + 5];
	const uint8_t *pp;
	struct ecx *ecx, *pecx;
	int retval = 0;

	if (act == VDP_INIT) {
		AZ(*priv);
		ALLOC_OBJ(ecx, ECX_MAGIC);
		AN(ecx);
		ecx->preq = req;
		*priv = ecx;
		return (0);
	}
	CAST_OBJ_NOTNULL(ecx, *priv, ECX_MAGIC);
	if (act == VDP_FINI) {
		FREE_OBJ(ecx);
		*priv = NULL;
		return (0);
	}
	pp = ptr;

	while (1) {
		switch (ecx->state) {
		case 0:
			ecx->p = ObjGetattr(req->wrk, req->objcore,
			    OA_ESIDATA, &l);
			AN(ecx->p);
			assert(l > 0);
			ecx->e = ecx->p + l;

			if (*ecx->p == VEC_GZ) {
				ecx->isgzip = 1;
				ecx->p++;
			}

			if (req->esi_level == 0) {
				/*
				 * Only the top level document gets to
				 * decide this.
				 */
				if (ecx->isgzip) {
					assert(sizeof gzip_hdr == 10);
					/* Send out the gzip header */
					retval = VDP_bytes(req, VDP_NULL,
					    gzip_hdr, 10);
					ecx->l_crc = 0;
					ecx->crc = crc32(0L, Z_NULL, 0);
				}
			}
			ecx->state = 1;

			break;
		case 1:
			if (ecx->p >= ecx->e) {
				ecx->state = 2;
				break;
			}
			switch (*ecx->p) {
			case VEC_V1:
			case VEC_V2:
			case VEC_V8:
				ecx->l = ved_decode_len(req, &ecx->p);
				if (ecx->l < 0)
					return (-1);
				if (ecx->isgzip) {
					assert(*ecx->p == VEC_C1 ||
					    *ecx->p == VEC_C2 ||
					    *ecx->p == VEC_C8);
					l = ved_decode_len(req, &ecx->p);
					if (l < 0)
						return (-1);
					icrc = vbe32dec(ecx->p);
					ecx->p += 4;
					if (ecx->isgzip) {
						ecx->crc = crc32_combine(
						    ecx->crc, icrc, l);
						ecx->l_crc += l;
					}
				}
				ecx->state = 3;
				break;
			case VEC_S1:
			case VEC_S2:
			case VEC_S8:
				ecx->l = ved_decode_len(req, &ecx->p);
				if (ecx->l < 0)
					return (-1);
				Debug("SKIP1(%d)\n", (int)ecx->l);
				ecx->state = 4;
				break;
			case VEC_INCL:
				ecx->p++;
				q = (void*)strchr((const char*)ecx->p, '\0');
				AN(q);
				q++;
				r = (void*)strchr((const char*)q, '\0');
				AN(r);
				if (VDP_bytes(req, VDP_FLUSH, NULL, 0)) {
					ecx->p = ecx->e;
					break;
				}
				Debug("INCL [%s][%s] BEGIN\n", q, ecx->p);
				ved_include(req,
				    (const char*)q, (const char*)ecx->p, ecx);
				Debug("INCL [%s][%s] END\n", q, ecx->p);
				ecx->p = r + 1;
				break;
			default:
				VSLb(req->vsl, SLT_Error,
				    "ESI corruption line %d 0x%02x [%s]\n",
				    __LINE__, *ecx->p, ecx->p);
				WRONG("ESI-codes: Illegal code");
			}
			break;
		case 2:
			if (ecx->isgzip && req->esi_level == 0) {
				/*
				 * We are bytealigned here, so simply emit
				 * a gzip literal block with finish bit set.
				 */
				tailbuf[0] = 0x01;
				tailbuf[1] = 0x00;
				tailbuf[2] = 0x00;
				tailbuf[3] = 0xff;
				tailbuf[4] = 0xff;

				/* Emit CRC32 */
				vle32enc(tailbuf + 5, ecx->crc);

				/* MOD(2^32) length */
				vle32enc(tailbuf + 9, ecx->l_crc);

				(void)VDP_bytes(req, VDP_NULL, tailbuf, 13);
			}
			if (req->transport->deliver == VED_Deliver) {
				CAST_OBJ_NOTNULL(pecx, req->transport_priv,
				    ECX_MAGIC);
				pecx->crc = crc32_combine(pecx->crc,
				    ecx->crc, ecx->l_crc);
				pecx->l_crc += ecx->l_crc;
			}
			retval = VDP_bytes(req, VDP_FLUSH, NULL, 0);
			ecx->state = 99;
			return (retval);
		case 3:
		case 4:
			/*
			 * There is no guarantee that the 'l' bytes are all
			 * in the same storage segment, so loop over storage
			 * until we have processed them all.
			 */
			if (ecx->l <= len) {
				if (ecx->state == 3)
					retval = VDP_bytes(req, act,
					    pp, ecx->l);
				len -= ecx->l;
				pp += ecx->l;
				ecx->state = 1;
				break;
			}
			if (ecx->state == 3 && len > 0)
				retval = VDP_bytes(req, act, pp, len);
			ecx->l -= len;
			return (retval);
		case 99:
			/*
			 * VEP does not account for the PAD+CRC+LEN
			 * so we can see up to approx 15 bytes here.
			 */
			return (retval);
		default:
			WRONG("FOO");
			break;
		}
		if (retval)
			return (retval);
	}
}
Beispiel #21
0
void
VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
    struct objcore *oldoc, enum vbf_fetch_mode_e mode)
{
	struct boc *boc;
	struct busyobj *bo;
	const char *how;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
	AN(oc->flags & OC_F_BUSY);
	CHECK_OBJ_ORNULL(oldoc, OBJCORE_MAGIC);

	bo = VBO_GetBusyObj(wrk, req);
	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);

	boc = HSH_RefBoc(oc);
	CHECK_OBJ_NOTNULL(boc, BOC_MAGIC);

	switch (mode) {
	case VBF_PASS:
		how = "pass";
		bo->do_pass = 1;
		break;
	case VBF_NORMAL:
		how = "fetch";
		break;
	case VBF_BACKGROUND:
		how = "bgfetch";
		bo->is_bgfetch = 1;
		break;
	default:
		WRONG("Wrong fetch mode");
	}

	VSLb(bo->vsl, SLT_Begin, "bereq %u %s", VXID(req->vsl->wid), how);
	VSLb(req->vsl, SLT_Link, "bereq %u %s", VXID(bo->vsl->wid), how);

	THR_SetBusyobj(bo);

	bo->sp = req->sp;
	SES_Ref(bo->sp);

	AN(bo->vcl);

	oc->boc->vary = req->vary_b;
	req->vary_b = NULL;

	HSH_Ref(oc);
	AZ(bo->fetch_objcore);
	bo->fetch_objcore = oc;

	AZ(bo->stale_oc);
	if (oldoc != NULL) {
		assert(oldoc->refcnt > 0);
		HSH_Ref(oldoc);
		bo->stale_oc = oldoc;
	}

	AZ(bo->req);
	bo->req = req;

	bo->fetch_task.priv = bo;
	bo->fetch_task.func = vbf_fetch_thread;

	if (Pool_Task(wrk->pool, &bo->fetch_task, TASK_QUEUE_BO)) {
		wrk->stats->fetch_no_thread++;
		(void)vbf_stp_fail(req->wrk, bo);
		if (bo->stale_oc != NULL)
			(void)HSH_DerefObjCore(wrk, &bo->stale_oc, 0);
		HSH_DerefBoc(wrk, oc);
		SES_Rel(bo->sp);
		VBO_ReleaseBusyObj(wrk, &bo);
	} else {
		bo = NULL; /* ref transferred to fetch thread */
		if (mode == VBF_BACKGROUND) {
			ObjWaitState(oc, BOS_REQ_DONE);
			(void)VRB_Ignore(req);
		} else {
			ObjWaitState(oc, BOS_STREAM);
			if (oc->boc->state == BOS_FAILED) {
				AN((oc->flags & OC_F_FAILED));
			} else {
				AZ(oc->flags & OC_F_BUSY);
			}
		}
	}
	AZ(bo);
	VSLb_ts_req(req, "Fetch", W_TIM_real(wrk));
	assert(oc->boc == boc);
	HSH_DerefBoc(wrk, oc);
	if (mode == VBF_BACKGROUND)
		(void)HSH_DerefObjCore(wrk, &oc, HSH_RUSH_POLICY);
	THR_SetBusyobj(NULL);
}
Beispiel #22
0
static enum fetch_step
vbf_stp_error(struct worker *wrk, struct busyobj *bo)
{
	ssize_t l, ll, o;
	double now;
	uint8_t *ptr;
	struct vsb *synth_body;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
	CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);
	AN(bo->fetch_objcore->flags & OC_F_BUSY);
	assert(bo->director_state == DIR_S_NULL);

	wrk->stats->fetch_failed++;

	now = W_TIM_real(wrk);
	VSLb_ts_busyobj(bo, "Error", now);

	if (bo->fetch_objcore->stobj->stevedore != NULL)
		ObjFreeObj(bo->wrk, bo->fetch_objcore);

	if (bo->storage == NULL)
		bo->storage = STV_next();

	// XXX: reset all beresp flags ?

	HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod);
	http_PutResponse(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed");
	http_TimeHeader(bo->beresp, "Date: ", now);
	http_SetHeader(bo->beresp, "Server: Varnish");

	bo->fetch_objcore->t_origin = now;
	if (!VTAILQ_EMPTY(&bo->fetch_objcore->objhead->waitinglist)) {
		/*
		 * If there is a waitinglist, it means that there is no
		 * grace-able object, so cache the error return for a
		 * short time, so the waiting list can drain, rather than
		 * each objcore on the waiting list sequentially attempt
		 * to fetch from the backend.
		 */
		bo->fetch_objcore->ttl = 1;
		bo->fetch_objcore->grace = 5;
		bo->fetch_objcore->keep = 5;
	} else {
		bo->fetch_objcore->ttl = 0;
		bo->fetch_objcore->grace = 0;
		bo->fetch_objcore->keep = 0;
	}

	synth_body = VSB_new_auto();
	AN(synth_body);

	VCL_backend_error_method(bo->vcl, wrk, NULL, bo, synth_body);

	AZ(VSB_finish(synth_body));

	if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL) {
		VSB_destroy(&synth_body);
		return (F_STP_FAIL);
	}

	if (wrk->handling == VCL_RET_RETRY) {
		VSB_destroy(&synth_body);
		if (bo->retries++ < cache_param->max_retries)
			return (F_STP_RETRY);
		VSLb(bo->vsl, SLT_VCL_Error, "Too many retries, failing");
		return (F_STP_FAIL);
	}

	assert(wrk->handling == VCL_RET_DELIVER);

	assert(bo->vfc->wrk == bo->wrk);
	assert(bo->vfc->oc == bo->fetch_objcore);
	assert(bo->vfc->resp == bo->beresp);
	assert(bo->vfc->req == bo->bereq);

	if (vbf_beresp2obj(bo)) {
		(void)VFP_Error(bo->vfc, "Could not get storage");
		VSB_destroy(&synth_body);
		return (F_STP_FAIL);
	}

	ll = VSB_len(synth_body);
	o = 0;
	while (ll > 0) {
		l = ll;
		if (VFP_GetStorage(bo->vfc, &l, &ptr) != VFP_OK)
			break;
		if (l > ll)
			l = ll;
		memcpy(ptr, VSB_data(synth_body) + o, l);
		VFP_Extend(bo->vfc, l);
		ll -= l;
		o += l;
	}
	AZ(ObjSetU64(wrk, bo->fetch_objcore, OA_LEN, o));
	VSB_destroy(&synth_body);
	HSH_Unbusy(wrk, bo->fetch_objcore);
	ObjSetState(wrk, bo->fetch_objcore, BOS_FINISHED);
	return (F_STP_DONE);
}
Beispiel #23
0
static enum fetch_step
vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
{
	const char *p;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
	CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);

	assert(wrk->handling == VCL_RET_DELIVER);

	if (vbf_figure_out_vfp(bo)) {
		(bo)->htc->doclose = SC_OVERLOAD;
		VDI_Finish((bo)->wrk, bo);
		return (F_STP_ERROR);
	}

	if (bo->fetch_objcore->flags & OC_F_PRIVATE)
		AN(bo->uncacheable);

	bo->fetch_objcore->boc->len_so_far = 0;

	if (VFP_Open(bo->vfc)) {
		(void)VFP_Error(bo->vfc, "Fetch pipeline failed to open");
		bo->htc->doclose = SC_RX_BODY;
		VDI_Finish(bo->wrk, bo);
		return (F_STP_ERROR);
	}

	if (vbf_beresp2obj(bo)) {
		(void)VFP_Error(bo->vfc, "Could not get storage");
		bo->htc->doclose = SC_RX_BODY;
		VFP_Close(bo->vfc);
		VDI_Finish(bo->wrk, bo);
		return (F_STP_ERROR);
	}

	if (bo->do_esi)
		ObjSetFlag(bo->wrk, bo->fetch_objcore, OF_ESIPROC, 1);

	if (bo->do_gzip || (bo->is_gzip && !bo->do_gunzip))
		ObjSetFlag(bo->wrk, bo->fetch_objcore, OF_GZIPED, 1);

	if (bo->do_gzip || bo->do_gunzip)
		ObjSetFlag(bo->wrk, bo->fetch_objcore, OF_CHGGZIP, 1);

	if (!(bo->fetch_objcore->flags & OC_F_PASS) &&
	    http_IsStatus(bo->beresp, 200) && (
	      http_GetHdr(bo->beresp, H_Last_Modified, &p) ||
	      http_GetHdr(bo->beresp, H_ETag, &p)))
		ObjSetFlag(bo->wrk, bo->fetch_objcore, OF_IMSCAND, 1);

	if (bo->htc->body_status != BS_NONE &&
	    VDI_GetBody(bo->wrk, bo) != 0) {
		(void)VFP_Error(bo->vfc,
		    "GetBody failed - workspace_backend overflow?");
		VFP_Close(bo->vfc);
		bo->htc->doclose = SC_OVERLOAD;
		VDI_Finish(bo->wrk, bo);
		return (F_STP_ERROR);
	}

	assert(bo->fetch_objcore->boc->refcount >= 1);

	assert(bo->fetch_objcore->boc->state == BOS_REQ_DONE);

	if (bo->do_stream) {
		ObjSetState(wrk, bo->fetch_objcore, BOS_PREP_STREAM);
		HSH_Unbusy(wrk, bo->fetch_objcore);
		ObjSetState(wrk, bo->fetch_objcore, BOS_STREAM);
	}

	VSLb(bo->vsl, SLT_Fetch_Body, "%u %s %s",
	    bo->htc->body_status, body_status_2str(bo->htc->body_status),
	    bo->do_stream ? "stream" : "-");

	if (bo->htc->body_status != BS_NONE) {
		assert(bo->htc->body_status != BS_ERROR);
		return (F_STP_FETCHBODY);
	}
	AZ(bo->vfc->failed);
	return (F_STP_FETCHEND);
}
Beispiel #24
0
static F1(jtravtranspose){I i,n,s;Z t,*v;UC*iv,*jv;UI j;
 n=AN(w); v=ZAV(w);
 j=n; s=SY_64?64:32; while(1<j){j>>=1; --s;} 
 iv=(UC*)&i; jv=(UC*)&j;
 if(128!=revb[1])DO(256, revb[i]=16*revb16[i%16]+revb16[i/16];);
Beispiel #25
0
static int
vbf_beresp2obj(struct busyobj *bo)
{
	unsigned l, l2;
	const char *b;
	uint8_t *bp;
	struct vsb *vary = NULL;
	int varyl = 0;

	l = 0;

	/* Create Vary instructions */
	if (!(bo->fetch_objcore->flags & OC_F_PRIVATE)) {
		varyl = VRY_Create(bo, &vary);
		if (varyl > 0) {
			AN(vary);
			assert(varyl == VSB_len(vary));
			l += PRNDUP((intptr_t)varyl);
		} else if (varyl < 0) {
			/*
			 * Vary parse error
			 * Complain about it, and make this a pass.
			 */
			VSLb(bo->vsl, SLT_Error,
			    "Illegal 'Vary' header from backend, "
			    "making this a pass.");
			bo->uncacheable = 1;
			AZ(vary);
		} else
			/* No vary */
			AZ(vary);
	}

	l2 = http_EstimateWS(bo->beresp,
	    bo->uncacheable ? HTTPH_A_PASS : HTTPH_A_INS);
	l += l2;

	if (bo->uncacheable)
		bo->fetch_objcore->flags |= OC_F_PASS;

	if (!vbf_allocobj(bo, l)) {
		if (vary != NULL)
			VSB_destroy(&vary);
		AZ(vary);
		return (-1);
	}

	if (vary != NULL) {
		AN(ObjSetAttr(bo->wrk, bo->fetch_objcore, OA_VARY, varyl,
			VSB_data(vary)));
		VSB_destroy(&vary);
	}

	AZ(ObjSetU32(bo->wrk, bo->fetch_objcore, OA_VXID, VXID(bo->vsl->wid)));

	/* for HTTP_Encode() VSLH call */
	bo->beresp->logtag = SLT_ObjMethod;

	/* Filter into object */
	bp = ObjSetAttr(bo->wrk, bo->fetch_objcore, OA_HEADERS, l2, NULL);
	AN(bp);
	HTTP_Encode(bo->beresp, bp, l2,
	    bo->uncacheable ? HTTPH_A_PASS : HTTPH_A_INS);

	if (http_GetHdr(bo->beresp, H_Last_Modified, &b))
		AZ(ObjSetDouble(bo->wrk, bo->fetch_objcore, OA_LASTMODIFIED,
		    VTIM_parse(b)));
	else
		AZ(ObjSetDouble(bo->wrk, bo->fetch_objcore, OA_LASTMODIFIED,
		    floor(bo->fetch_objcore->t_origin)));

	return (0);
}
Beispiel #26
0
int
exec_file(const char *fn, const char *script, const char *tmpdir,
    char *logbuf, unsigned loglen)
{
	unsigned old_err;
	char *cwd, *p;
	FILE *f;
	struct extmacro *m;

	signal(SIGPIPE, SIG_IGN);

	vtc_loginit(logbuf, loglen);
	vltop = vtc_logopen("top");
	AN(vltop);

	init_macro();
	init_sema();

	/* Apply extmacro definitions */
	VTAILQ_FOREACH(m, &extmacro_list, list)
		macro_def(vltop, NULL, m->name, "%s", m->val);

	/* Other macro definitions */
	cwd = getcwd(NULL, PATH_MAX);
	macro_def(vltop, NULL, "pwd", "%s", cwd);
	macro_def(vltop, NULL, "topbuild", "%s/%s", cwd, TOP_BUILDDIR);

	/*
	 * We need an IP number which will not repond, ever, and that is a
	 * lot harder than it sounds.  This IP# is from RFC5737 and a
	 * C-class broadcast at that.
	 * If tests involving ${bad_ip} fails and you run linux, you should
	 * check your /proc/sys/net/ipv4/ip_nonlocal_bind setting.
	 */
	macro_def(vltop, NULL, "bad_ip", "192.0.2.255");

	/* Move into our tmpdir */
	AZ(chdir(tmpdir));
	macro_def(vltop, NULL, "tmpdir", "%s", tmpdir);

	/* Drop file to tell what was going on here */
	f = fopen("INFO", "w");
	AN(f);
	fprintf(f, "Test case: %s\n", fn);
	AZ(fclose(f));

	vtc_stop = 0;
	vtc_desc = NULL;
	vtc_log(vltop, 1, "TEST %s starting", fn);

	p = strdup(script);
	AN(p);

	vtc_thread = pthread_self();
	parse_string(p, cmds, NULL, vltop);
	old_err = vtc_error;
	vtc_stop = 1;
	vtc_log(vltop, 1, "RESETTING after %s", fn);
	reset_cmds(cmds);
	vtc_error = old_err;

	if (vtc_error)
		vtc_log(vltop, 1, "TEST %s FAILED", fn);
	else
		vtc_log(vltop, 1, "TEST %s completed", fn);

	free(vtc_desc);
	return (vtc_error);
}
Beispiel #27
0
int
shHero::addObjectToInventory (shObject *obj, int quiet /* = 0 */)
{
    int spot;
    char let, spots[52];

    if (hasBugSensing ())  obj->setBugginessKnown ();

    const char *what = AN (obj);

    for (int i = 0; i < 52; spots[i++] = 0)
        ;
    /* Try merging. */
    for (int i = 0; i < mInventory->count (); ++i) {
        shObject *iobj;

        iobj = mInventory->get (i);
        if (iobj->canMerge (obj)) {
            mWeight += obj->getMass ();
            iobj->merge (obj);
            if (0 == quiet) {
                I->p ("%c - %s", iobj->mLetter, what);
            }
            computeIntrinsics (quiet);
            return 1;
        }
        let = iobj->mLetter;
        spot =
            (let >= 'a' and let <= 'z') ? let - 'a' :
            (let >= 'A' and let <= 'Z') ? let - 'A' + 26 :
            -1;

        assert (-1 != spot);
        assert (0 == spots[spot]);
        spots[spot] = 1;
    }
    /* Try to place item in exactly the spot it was before. */
    let = obj->mLetter;
    spot =
        (let >= 'a' and let <= 'z') ? let - 'a' :
        (let >= 'A' and let <= 'Z') ? let - 'A' + 26 :
        -1;
    int i;
    if (-1 != spot and 0 == spots[spot]) {
        i = spot; /* Place item under its old letter. */
    } else { /* Look for free spot. */
        for (i = 0; i < 52 and 0 != spots[i]; ++i)
            ;
    }
    if (i < 52) {
        mInventory->add (obj);
        mWeight += obj->getMass ();
        obj->mLetter = i < 26 ? i + 'a' : i + 'A' - 26;
        obj->mLocation = shObject::kInventory;
        obj->mOwner = this;
        if (!quiet)  I->p ("%c - %s", obj->mLetter, what);
        mInventory->sort (&compareObjects);
        computeIntrinsics (quiet);
        return 1;
    }

    if (!quiet)  I->p ("You don't have any room in your pack for %s.", what);
    return 0;
}
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 void
ved_stripgzip(struct req *req, struct busyobj *bo)
{
	ssize_t start, last, stop, lpad;
	ssize_t l;
	char *p;
	uint32_t icrc;
	uint32_t ilen;
	uint64_t olen;
	uint8_t *dbits;
	uint8_t *pp;
	uint8_t tailbuf[8];
	enum objiter_status ois;
	void *oi;
	void *sp;
	ssize_t sl, ll, dl;
	struct ecx *ecx;
	struct req *preq;

	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
	CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
	CAST_OBJ_NOTNULL(ecx, req->transport_priv, ECX_MAGIC);
	preq = ecx->preq;

	if (bo != NULL)
		VBO_waitstate(bo, BOS_FINISHED);

	AN(ObjCheckFlag(req->wrk, req->objcore, OF_GZIPED));

	/*
	 * This is the interesting case: Deliver all the deflate
	 * blocks, stripping the "LAST" bit of the last one and
	 * padding it, as necessary, to a byte boundary.
	 */

	p = ObjGetattr(req->wrk, req->objcore, OA_GZIPBITS, &l);
	AN(p);
	assert(l == 32);
	start = vbe64dec(p);
	last = vbe64dec(p + 8);
	stop = vbe64dec(p + 16);
	olen = ObjGetLen(req->wrk, req->objcore);
	assert(start > 0 && start < olen * 8);
	assert(last > 0 && last < olen * 8);
	assert(stop > 0 && stop < olen * 8);
	assert(last >= start);
	assert(last < stop);

	/* The start bit must be byte aligned. */
	AZ(start & 7);

	/*
	 * XXX: optimize for the case where the 'last'
	 * XXX: bit is in a empty copy block
	 */

	memset(tailbuf, 0xdd, sizeof tailbuf);
	dbits = WS_Alloc(req->ws, 8);
	AN(dbits);
	ll = 0;
	oi = ObjIterBegin(req->wrk, req->objcore);
	do {
		ois = ObjIter(req->objcore, oi, &sp, &sl);
		pp = sp;
		if (sl > 0) {
			/* Skip over the GZIP header */
			dl = start / 8 - ll;
			if (dl > 0) {
				/* Before start, skip */
				if (dl > sl)
					dl = sl;
				ll += dl;
				sl -= dl;
				pp += dl;
			}
		}
		if (sl > 0) {
			/* The main body of the object */
			dl = last / 8 - ll;
			if (dl > 0) {
				if (dl > sl)
					dl = sl;
				if (ved_bytes(req, preq, VDP_NULL, pp, dl))
					break;
				ll += dl;
				sl -= dl;
				pp += dl;
			}
		}
		if (sl > 0 && ll == last / 8) {
			/* Remove the "LAST" bit */
			dbits[0] = *pp;
			dbits[0] &= ~(1U << (last & 7));
			if (ved_bytes(req, preq, VDP_NULL, dbits, 1))
				break;
			ll++;
			sl--;
			pp++;
		}
		if (sl > 0) {
			/* Last block */
			dl = stop / 8 - ll;
			if (dl > 0) {
				if (dl > sl)
					dl = sl;
				if (ved_bytes(req, preq, VDP_NULL, pp, dl))
					break;
				ll += dl;
				sl -= dl;
				pp += dl;
			}
		}
		if (sl > 0 && (stop & 7) && ll == stop / 8) {
			/* Add alignment to byte boundary */
			dbits[1] = *pp;
			ll++;
			sl--;
			pp++;
			switch((int)(stop & 7)) {
			case 1: /*
				 * x000....
				 * 00000000 00000000 11111111 11111111
				 */
			case 3: /*
				 * xxx000..
				 * 00000000 00000000 11111111 11111111
				 */
			case 5: /*
				 * xxxxx000
				 * 00000000 00000000 11111111 11111111
				 */
				dbits[2] = 0x00; dbits[3] = 0x00;
				dbits[4] = 0xff; dbits[5] = 0xff;
				lpad = 5;
				break;
			case 2: /* xx010000 00000100 00000001 00000000 */
				dbits[1] |= 0x08;
				dbits[2] = 0x20;
				dbits[3] = 0x80;
				dbits[4] = 0x00;
				lpad = 4;
				break;
			case 4: /* xxxx0100 00000001 00000000 */
				dbits[1] |= 0x20;
				dbits[2] = 0x80;
				dbits[3] = 0x00;
				lpad = 3;
				break;
			case 6: /* xxxxxx01 00000000 */
				dbits[1] |= 0x80;
				dbits[2] = 0x00;
				lpad = 2;
				break;
			case 7:	/*
				 * xxxxxxx0
				 * 00......
				 * 00000000 00000000 11111111 11111111
				 */
				dbits[2] = 0x00;
				dbits[3] = 0x00; dbits[4] = 0x00;
				dbits[5] = 0xff; dbits[6] = 0xff;
				lpad = 6;
				break;
			case 0: /* xxxxxxxx */
			default:
				WRONG("compiler must be broken");
			}
			if (ved_bytes(req, preq, VDP_NULL, dbits + 1, lpad))
				break;
		}
		if (sl > 0) {
			/* Recover GZIP tail */
			dl = olen - ll;
			assert(dl >= 0);
			if (dl > sl)
				dl = sl;
			if (dl > 0) {
				assert(dl <= 8);
				l = ll - (olen - 8);
				assert(l >= 0);
				assert(l <= 8);
				assert(l + dl <= 8);
				memcpy(tailbuf + l, pp, dl);
				ll += dl;
				sl -= dl;
				pp += dl;
			}
		}
	} while (ois == OIS_DATA || ois == OIS_STREAM);
	ObjIterEnd(req->objcore, &oi);
	(void)ved_bytes(req, preq, VDP_FLUSH, NULL, 0);

	icrc = vle32dec(tailbuf);
	ilen = vle32dec(tailbuf + 4);

	ecx->crc = crc32_combine(ecx->crc, icrc, ilen);
	ecx->l_crc += ilen;
}
Beispiel #30
0
static void
vxp_expr_cmp(struct vxp *vxp, struct vex **pvex)
{

	AN(pvex);
	AZ(*pvex);
	*pvex = vex_alloc(vxp);
	AN(*pvex);
	vxp_expr_lhs(vxp, &(*pvex)->lhs);
	ERRCHK(vxp);

	/* Test operator */
	switch (vxp->t->tok) {

	/* Single lhs expressions don't take any more tokens */
	case EOI:
	case T_AND:
	case T_OR:
	case ')':
		(*pvex)->tok = T_TRUE;
		return;

	/* Valid operators */
	case T_EQ:		/* == */
	case '<':		/* < */
	case '>':		/* > */
	case T_GEQ:		/* >= */
	case T_LEQ:		/* <= */
	case T_NEQ:		/* != */
	case T_SEQ:		/* eq */
	case T_SNEQ:		/* ne */
	case '~':		/* ~ */
	case T_NOMATCH:		/* !~ */
		(*pvex)->tok = vxp->t->tok;
		break;

	/* Error */
	default:
		VSB_printf(vxp->sb, "Expected operator got '%.*s' ",
		    PF(vxp->t));
		vxp_ErrWhere(vxp, vxp->t, -1);
		return;
	}
	vxp_NextToken(vxp);
	ERRCHK(vxp);

	/* Value */
	switch((*pvex)->tok) {
	case '\0':
		WRONG("Missing token");
		break;
	case T_EQ:		/* == */
	case '<':		/* < */
	case '>':		/* > */
	case T_GEQ:		/* >= */
	case T_LEQ:		/* <= */
	case T_NEQ:		/* != */
		vxp_expr_num(vxp, &(*pvex)->rhs);
		break;
	case T_SEQ:		/* eq */
	case T_SNEQ:		/* ne */
		vxp_expr_str(vxp, &(*pvex)->rhs);
		break;
	case '~':		/* ~ */
	case T_NOMATCH:		/* !~ */
		vxp_expr_regex(vxp, &(*pvex)->rhs);
		break;
	default:
		INCOMPL();
	}
}