static void vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1) { char *p; int i; for (i = 0; i < ind; i++) VSB_cat(d, " "); p = VSB_data(e1->vsb); while (*p != '\0') { if (*p == '\n') { VSB_putc(d, '\n'); if (p[1] != '\0') { for (i = 0; i < ind; i++) VSB_cat(d, " "); } p++; continue; } if (*p != '\v') { VSB_putc(d, *p); p++; continue; } p++; switch(*p) { case '+': ind += 2; break; case '-': ind -= 2; break; default: assert(__LINE__ == 0); } p++; } }
struct vsb * vtc_hex_to_bin(struct vtclog *vl, const char *arg) { struct vsb *vsb; unsigned sh = 4; unsigned c, b = 0; vsb = VSB_new_auto(); AN(vsb); for (; *arg != '\0'; arg++) { if (vct_issp(*arg) || *arg == '\n') continue; c = (uint8_t)*arg; if (c >= '0' && c <= '9') b |= (c - 48U) << sh; else if (c >= 'A' && c <= 'F') b |= (c - 55U) << sh; else if (c >= 'a' && c <= 'f') b |= (c - 87U) << sh; else vtc_fatal(vl,"Illegal hex string"); sh = 4 - sh; if (sh == 4) { VSB_putc(vsb, b); b = 0; } } if (sh != 4) VSB_putc(vsb, b); AZ(VSB_finish(vsb)); return (vsb); }
static void vxp_quote(const struct vxp *vxp, const char *b, const char *e, int tokoff) { const char *p; char c; assert(b <= e); assert(b >= vxp->b); assert(e <= vxp->e); for (p = vxp->b; p < vxp->e; p++) { if (isspace(*p)) VSB_putc(vxp->sb, ' '); else VSB_putc(vxp->sb, *p); } VSB_putc(vxp->sb, '\n'); for (p = vxp->b; p < vxp->e; p++) { if (p >= b && p < e) { if (p - b == tokoff) c = '^'; else c = '#'; } else c = '-'; VSB_putc(vxp->sb, c); } VSB_putc(vxp->sb, '\n'); }
static struct expr * vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1, struct expr *e2) { struct expr *e; int nl = 1; e = vcc_new_expr(); while (*p != '\0') { if (*p == '\n') { if (!nl) VSB_putc(e->vsb, *p); nl = 1; p++; continue; } nl = 0; if (*p != '\v') { VSB_putc(e->vsb, *p); p++; continue; } assert(*p == '\v'); p++; switch(*p) { case '+': VSB_cat(e->vsb, "\v+"); break; case '-': VSB_cat(e->vsb, "\v-"); break; case '1': case '2': if (*p == '1') VSB_cat(e->vsb, VSB_data(e1->vsb)); else { AN(e2); VSB_cat(e->vsb, VSB_data(e2->vsb)); } break; default: assert(__LINE__ == 0); } p++; } AZ(VSB_finish(e->vsb)); if (e1 != NULL) e->t1 = e1->t1; else if (e2 != NULL) e->t1 = e2->t1; if (e2 != NULL) e->t2 = e2->t1; else if (e1 != NULL) e->t1 = e1->t1; if ((e1 == NULL || e1->constant) && (e2 == NULL || e2->constant)) e->constant = 1; vcc_delete_expr(e1); vcc_delete_expr(e2); e->fmt = fmt; return (e); }
void vxp_ErrWhere(struct vxp *vxp, const struct token *t, int tokoff) { AN(vxp); AN(t); vxp_Pos(vxp, vxp->sb, t, tokoff); VSB_putc(vxp->sb, '\n'); vxp_quote(vxp, t->b, t->e, tokoff); VSB_putc(vxp->sb, '\n'); vxp->err = 1; }
static void ban_parse_http(const struct ban_proto *bp, const char *a1) { int l; l = strlen(a1) + 1; assert(l <= 127); VSB_putc(bp->vsb, (char)l); VSB_cat(bp->vsb, a1); VSB_putc(bp->vsb, ':'); VSB_putc(bp->vsb, '\0'); }
const char * BAN_AddTest(struct ban_proto *bp, const char *a1, const char *a2, const char *a3) { const struct pvar *pv; const char *err; CHECK_OBJ_NOTNULL(bp, BAN_PROTO_MAGIC); AN(bp->vsb); AN(a1); AN(a2); AN(a3); if (bp->err != NULL) return (bp->err); for (pv = pvars; pv->name != NULL; pv++) if (!strncmp(a1, pv->name, strlen(pv->name))) break; if (pv->name == NULL) return (ban_error(bp, "Unknown or unsupported field \"%s\"", a1)); bp->flags |= pv->flag; VSB_putc(bp->vsb, pv->tag); if (pv->flag & BANS_FLAG_HTTP) ban_parse_http(bp, a1 + strlen(pv->name)); ban_add_lump(bp, a3, strlen(a3) + 1); if (!strcmp(a2, "~")) { VSB_putc(bp->vsb, BANS_OPER_MATCH); err = ban_parse_regexp(bp, a3); if (err) return (err); } else if (!strcmp(a2, "!~")) { VSB_putc(bp->vsb, BANS_OPER_NMATCH); err = ban_parse_regexp(bp, a3); if (err) return (err); } else if (!strcmp(a2, "==")) { VSB_putc(bp->vsb, BANS_OPER_EQ); } else if (!strcmp(a2, "!=")) { VSB_putc(bp->vsb, BANS_OPER_NEQ); } else { return (ban_error(bp, "expected conditional (~, !~, == or !=) got \"%s\"", a2)); } return (NULL); }
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); }
//lint -e{818} void vtc_log(struct vtclog *vl, int lvl, const char *fmt, ...) { double tx; CHECK_OBJ_NOTNULL(vl, VTCLOG_MAGIC); tx = VTIM_mono() - t0; AZ(pthread_mutex_lock(&vl->mtx)); vl->act = 1; assert(lvl < (int)NLEAD); VSB_clear(vl->vsb); VSB_printf(vl->vsb, "%s %-4s %4.1f ", lead[lvl < 0 ? 1: lvl], vl->id, tx); va_list ap; va_start(ap, fmt); (void)VSB_vprintf(vl->vsb, fmt, ap); va_end(ap); VSB_putc(vl->vsb, '\n'); AZ(VSB_finish(vl->vsb)); vtc_log_emit(vl, lvl); VSB_clear(vl->vsb); vl->act = 0; AZ(pthread_mutex_unlock(&vl->mtx)); if (lvl > 0) return; if (lvl == 0) vtc_error = 1; if (pthread_self() != vtc_thread) pthread_exit(NULL); }
void vcc_Expr(struct vcc *tl, enum var_type fmt) { struct expr *e; struct token *t1; assert(fmt != VOID); t1 = tl->t; vcc_expr0(tl, &e, fmt); ERRCHK(tl); if (fmt == STRING || fmt == STRING_LIST) vcc_expr_tostring(&e, fmt); if (!tl->err && fmt != e->fmt) { VSB_printf(tl->sb, "Expression has type %s, expected %s\n", vcc_Type(e->fmt), vcc_Type(fmt)); tl->err = 1; } if (!tl->err) { if (e->fmt == STRING_LIST) { e = vcc_expr_edit(STRING_LIST, "\v+\n\v1,\nvrt_magic_string_end\v-", e, NULL); } vcc_expr_fmt(tl->fb, tl->indent, e); VSB_putc(tl->fb, '\n'); } else { if (t1 != tl->t) vcc_ErrWhere2(tl, t1, tl->t); } vcc_delete_expr(e); }
static void vbp_bitmap(struct vsb *vsb, char c, uint64_t map, const char *lbl) { int i; uint64_t u = (1ULL << 63); VSB_printf(vsb, " "); for (i = 0; i < 64; i++) { if (map & u) VSB_putc(vsb, c); else VSB_putc(vsb, '-'); map <<= 1; } VSB_printf(vsb, " %s\n", lbl); }
run_cc(void *priv) { struct vcc_priv *vp; struct vsb *sb; int pct; char *p; VJ_subproc(JAIL_SUBPROC_CC); CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC); AZ(chdir(vp->dir)); sb = VSB_new_auto(); AN(sb); for (p = mgt_cc_cmd, pct = 0; *p; ++p) { if (pct) { switch (*p) { case 's': VSB_cat(sb, VGC_SRC); break; case 'o': VSB_cat(sb, VGC_LIB); break; case '%': VSB_putc(sb, '%'); break; default: VSB_putc(sb, '%'); VSB_putc(sb, *p); break; } pct = 0; } else if (*p == '%') { pct = 1; } else { VSB_putc(sb, *p); } } if (pct) VSB_putc(sb, '%'); AZ(VSB_finish(sb)); (void)umask(027); (void)execl("/bin/sh", "/bin/sh", "-c", VSB_data(sb), (char*)0); VSB_destroy(&sb); // For flexelint }
void vxp__Expect(struct vxp *vxp, unsigned tok) { if (vxp->t->tok == tok) return; VSB_printf(vxp->sb, "Expected %s got ", vxp_tnames[tok]); vxp_ErrToken(vxp, vxp->t); VSB_putc(vxp->sb, ' '); vxp_ErrWhere(vxp, vxp->t, -1); }
int vtc_send_proxy(int fd, int version, const struct suckaddr *sac, const struct suckaddr *sas) { struct vsb *vsb; char hc[VTCP_ADDRBUFSIZE]; char pc[VTCP_PORTBUFSIZE]; char hs[VTCP_ADDRBUFSIZE]; char ps[VTCP_PORTBUFSIZE]; int i, len; int proto; AN(sac); AN(sas); assert(version == 1 || version == 2); vsb = VSB_new_auto(); AN(vsb); proto = VSA_Get_Proto(sas); assert(proto == PF_INET6 || proto == PF_INET); if (version == 1) { VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig)); if (proto == PF_INET6) VSB_printf(vsb, " TCP6 "); else if (proto == PF_INET) VSB_printf(vsb, " TCP4 "); VTCP_name(sac, hc, sizeof(hc), pc, sizeof(pc)); VTCP_name(sas, hs, sizeof(hs), ps, sizeof(ps)); VSB_printf(vsb, "%s %s %s %s\r\n", hc, hs, pc, ps); } else if (version == 2) { VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig)); VSB_putc(vsb, 0x21); if (proto == PF_INET6) { VSB_putc(vsb, 0x21); VSB_putc(vsb, 0x00); VSB_putc(vsb, 0x24); } else if (proto == PF_INET) { VSB_putc(vsb, 0x11); VSB_putc(vsb, 0x00); VSB_putc(vsb, 0x0c); } vpx_enc_addr(vsb, proto, sac); vpx_enc_addr(vsb, proto, sas); vpx_enc_port(vsb, sac); vpx_enc_port(vsb, sas); } else WRONG("Wrong proxy version"); AZ(VSB_finish(vsb)); len = VSB_len(vsb); i = write(fd, VSB_data(vsb), len); VSB_delete(vsb); return (i != len); }
static void ban_add_lump(const struct ban_proto *bp, const void *p, uint32_t len) { uint8_t buf[sizeof len]; buf[0] = 0xff; while (VSB_len(bp->vsb) & PALGN) VSB_putc(bp->vsb, buf[0]); vbe32enc(buf, len); VSB_bcat(bp->vsb, buf, sizeof buf); VSB_bcat(bp->vsb, p, len); }
void vtc_fatal(struct vtclog *vl, const char *fmt, ...) { GET_VL(vl); va_list ap; va_start(ap, fmt); vtc_leadinv(vl, 0, fmt, ap); VSB_putc(vl->vsb, '\n'); va_end(ap); REL_VL(vl); vtc_logfail(); }
/* * Quote a string */ void VSB_quote(struct vsb *s, const char *p, int len, int how) { const char *q; int quote = 0; (void)how; /* For future enhancements */ if (len == -1) len = strlen(p); for (q = p; q < p + len; q++) { if (!isgraph(*q) || *q == '"' || *q == '\\') { quote++; break; } } if (!quote) { (void)VSB_bcat(s, p, len); return; } (void)VSB_putc(s, '"'); for (q = p; q < p + len; q++) { switch (*q) { case ' ': (void)VSB_putc(s, *q); break; case '\\': case '"': (void)VSB_putc(s, '\\'); (void)VSB_putc(s, *q); break; case '\n': if (how & VSB_QUOTE_NONL) (void)VSB_cat(s, "\n"); else (void)VSB_cat(s, "\\n"); break; case '\r': (void)VSB_cat(s, "\\r"); break; case '\t': (void)VSB_cat(s, "\\t"); break; default: if (isgraph(*q)) (void)VSB_putc(s, *q); else (void)VSB_printf(s, "\\%o", *q & 0xff); break; } } (void)VSB_putc(s, '"'); }
static void cmd_err_shell(CMD_ARGS) { (void)priv; (void)cmd; struct vsb *vsb; FILE *fp; int r, c; if (av == NULL) return; AN(av[1]); AN(av[2]); AZ(av[3]); vsb = VSB_new_auto(); AN(vsb); vtc_dump(vl, 4, "cmd", av[2], -1); fp = popen(av[2], "r"); if (fp == NULL) vtc_log(vl, 0, "popen fails: %s", strerror(errno)); do { c = getc(fp); if (c != EOF) VSB_putc(vsb, c); } while (c != EOF); r = pclose(fp); vtc_log(vl, 4, "Status = %d", WEXITSTATUS(r)); if (WIFSIGNALED(r)) vtc_log(vl, 4, "Signal = %d", WTERMSIG(r)); if (WEXITSTATUS(r) == 0) { vtc_log(vl, 0, "expected error from shell"); } AZ(VSB_finish(vsb)); vtc_dump(vl, 4, "stdout", VSB_data(vsb), VSB_len(vsb)); if (strstr(VSB_data(vsb), av[1]) == NULL) vtc_log(vl, 0, "Did not find expected string: (\"%s\")", av[1]); else vtc_log(vl, 4, "Found expected string: (\"%s\")", av[1]); VSB_delete(vsb); }
void vtc_log(struct vtclog *vl, int lvl, const char *fmt, ...) { GET_VL(vl); va_list ap; va_start(ap, fmt); if (lvl >= 0) { vtc_leadinv(vl, lvl, fmt, ap); VSB_putc(vl->vsb, '\n'); } va_end(ap); REL_VL(vl); if (lvl > 0) return; if (lvl == 0) vtc_logfail(); }
static struct expr * vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1, struct expr *e2) { struct expr *e; int nl = 1; AN(e1); e = vcc_new_expr(); while (*p != '\0') { if (*p != '\v') { if (*p != '\n' || !nl) VSB_putc(e->vsb, *p); nl = (*p == '\n'); p++; continue; } assert(*p == '\v'); switch(*++p) { case '+': VSB_cat(e->vsb, "\v+"); break; case '-': VSB_cat(e->vsb, "\v-"); break; case '1': VSB_cat(e->vsb, VSB_data(e1->vsb)); break; case '2': AN(e2); VSB_cat(e->vsb, VSB_data(e2->vsb)); break; default: WRONG("Illegal edit in VCC expression"); } p++; } AZ(VSB_finish(e->vsb)); e->t1 = e1->t1; e->t2 = e1->t2; if (e2 != NULL) e->t2 = e2->t2; vcc_delete_expr(e1); vcc_delete_expr(e2); e->fmt = fmt; return (e); }
void VEP_Parse(struct vep_state *vep, const char *p, size_t l) { const char *e; struct vep_match *vm; int i; CHECK_OBJ_NOTNULL(vep, VEP_MAGIC); assert(l > 0); if (vep->startup) { /* * We must force the GZIP header out as a SKIP string, * otherwise an object starting with <esi:include would * have its GZIP header appear after the included object * (e000026.vtc) */ vep->ver_p = ""; vep->last_mark = SKIP; vep_mark_common(vep, vep->ver_p, VERBATIM); vep->startup = 0; AZ(vep->hack_p); vep->hack_p = p; } vep->ver_p = p; e = p + l; while (p < e) { AN(vep->state); i = e - p; if (i > 10) i = 10; Debug("EP %s %d (%.*s) [%.*s]\n", vep->state, vep->remove, vep->tag_i, vep->tag, i, p); assert(p >= vep->ver_p); /****************************************************** * SECTION A */ if (vep->state == VEP_START) { if (FEATURE(FEATURE_ESI_REMOVE_BOM) && *p == '\xeb') { vep->match = vep_match_bom; vep->state = VEP_MATCH; } else vep->state = VEP_BOM; } else if (vep->state == VEP_BOM) { vep_mark_skip(vep, p); if (FEATURE(FEATURE_ESI_DISABLE_XML_CHECK)) vep->state = VEP_NEXTTAG; else vep->state = VEP_TESTXML; } else if (vep->state == VEP_TESTXML) { /* * If the first non-whitespace char is different * from '<' we assume this is not XML. */ while (p < e && vct_islws(*p)) p++; vep_mark_verbatim(vep, p); if (p < e && *p == '<') { p++; vep->state = VEP_STARTTAG; } else if (p < e && *p == '\xeb') { VSLb(vep->vc->wrk->vsl, SLT_ESI_xmlerror, "No ESI processing, " "first char not '<' but BOM." " (See feature esi_remove_bom)" ); vep->state = VEP_NOTXML; } else if (p < e) { VSLb(vep->vc->wrk->vsl, SLT_ESI_xmlerror, "No ESI processing, " "first char not '<'." " (See feature esi_disable_xml_check)" ); vep->state = VEP_NOTXML; } } else if (vep->state == VEP_NOTXML) { /* * This is not recognized as XML, just skip thru * vfp_esi_end() will handle the rest */ p = e; vep_mark_verbatim(vep, p); /****************************************************** * SECTION B */ } else if (vep->state == VEP_NOTMYTAG) { if (FEATURE(FEATURE_ESI_IGNORE_OTHER_ELEMENTS)) { p++; vep->state = VEP_NEXTTAG; } else { vep->tag_i = 0; while (p < e) { if (*p++ == '>') { vep->state = VEP_NEXTTAG; break; } } } if (p == e && !vep->remove) vep_mark_verbatim(vep, p); } else if (vep->state == VEP_NEXTTAG) { /* * Hunt for start of next tag and keep an eye * out for end of EsiCmt if armed. */ vep->emptytag = 0; vep->attr = NULL; vep->dostuff = NULL; while (p < e && *p != '<') { if (vep->esicmt_p == NULL) { p++; continue; } if (*p != *vep->esicmt_p) { p++; vep->esicmt_p = vep->esicmt; continue; } if (!vep->remove && vep->esicmt_p == vep->esicmt) vep_mark_verbatim(vep, p); p++; if (*++vep->esicmt_p == '\0') { vep->esi_found = 1; vep->esicmt = NULL; vep->esicmt_p = NULL; /* * The end of the esicmt * should not be emitted. * But the stuff before should */ vep_mark_skip(vep, p); } } if (p < e) { if (!vep->remove) vep_mark_verbatim(vep, p); assert(*p == '<'); p++; vep->state = VEP_STARTTAG; } else if (vep->esicmt_p == vep->esicmt && !vep->remove) vep_mark_verbatim(vep, p); /****************************************************** * SECTION C */ } else if (vep->state == VEP_STARTTAG) { /* Start of tag, set up match table */ vep->endtag = 0; vep->match = vep_match_starttag; vep->state = VEP_MATCH; } else if (vep->state == VEP_COMMENT) { vep->esicmt_p = vep->esicmt = NULL; vep->until_p = vep->until = "-->"; vep->until_s = VEP_NEXTTAG; vep->state = VEP_UNTIL; } else if (vep->state == VEP_COMMENTESI) { if (vep->remove) vep_error(vep, "ESI 1.0 Nested <!--esi" " element in <esi:remove>"); vep->esicmt_p = vep->esicmt = "-->"; vep->state = VEP_NEXTTAG; vep_mark_skip(vep, p); } else if (vep->state == VEP_CDATA) { /* * Easy: just look for the end of CDATA */ vep->until_p = vep->until = "]]>"; vep->until_s = VEP_NEXTTAG; vep->state = VEP_UNTIL; } else if (vep->state == VEP_ESIENDTAG) { vep->endtag = 1; vep->state = VEP_ESITAG; } else if (vep->state == VEP_ESITAG) { vep->in_esi_tag = 1; vep->esi_found = 1; vep_mark_skip(vep, p); vep->match = vep_match_esi; vep->state = VEP_MATCH; } else if (vep->state == VEP_ESIINCLUDE) { if (vep->remove) { vep_error(vep, "ESI 1.0 <esi:include> element" " nested in <esi:remove>"); vep->state = VEP_TAGERROR; } else if (vep->endtag) { vep_error(vep, "ESI 1.0 </esi:include> illegal end-tag"); vep->state = VEP_TAGERROR; } else { vep->dostuff = vep_do_include; vep->state = VEP_INTAG; vep->attr = vep_match_attr_include; } } else if (vep->state == VEP_ESIREMOVE) { vep->dostuff = vep_do_remove; vep->state = VEP_INTAG; } else if (vep->state == VEP_ESICOMMENT) { if (vep->remove) { vep_error(vep, "ESI 1.0 <esi:comment> element" " nested in <esi:remove>"); vep->state = VEP_TAGERROR; } else if (vep->endtag) { vep_error(vep, "ESI 1.0 </esi:comment> illegal end-tag"); vep->state = VEP_TAGERROR; } else { vep->dostuff = vep_do_comment; vep->state = VEP_INTAG; } } else if (vep->state == VEP_ESIBOGON) { vep_error(vep, "ESI 1.0 <esi:bogus> element"); vep->state = VEP_TAGERROR; /****************************************************** * SECTION D */ } else if (vep->state == VEP_INTAG) { vep->tag_i = 0; while (p < e && vct_islws(*p) && !vep->emptytag) { p++; vep->canattr = 1; } if (p < e && *p == '/' && !vep->emptytag) { p++; vep->emptytag = 1; vep->canattr = 0; } if (p < e && *p == '>') { p++; AN(vep->dostuff); vep_mark_skip(vep, p); vep->dostuff(vep, DO_TAG); vep->in_esi_tag = 0; vep->state = VEP_NEXTTAG; } else if (p < e && vep->emptytag) { vep_error(vep, "XML 1.0 '>' does not follow '/' in tag"); vep->state = VEP_TAGERROR; } else if (p < e && vep->canattr && vct_isxmlnamestart(*p)) { vep->state = VEP_ATTR; } else if (p < e) { vep_error(vep, "XML 1.0 Illegal attribute start char"); vep->state = VEP_TAGERROR; } } else if (vep->state == VEP_TAGERROR) { while (p < e && *p != '>') p++; if (p < e) { p++; vep_mark_skip(vep, p); vep->in_esi_tag = 0; vep->state = VEP_NEXTTAG; } /****************************************************** * SECTION E */ } else if (vep->state == VEP_ATTR) { AZ(vep->attr_delim); if (vep->attr == NULL) { p++; AZ(vep->attr_vsb); vep->state = VEP_SKIPATTR; } else { vep->match = vep->attr; vep->state = VEP_MATCH; } } else if (vep->state == VEP_SKIPATTR) { while (p < e && vct_isxmlname(*p)) p++; if (p < e && *p == '=') { p++; vep->state = VEP_ATTRDELIM; } else if (p < e && *p == '>') { vep->state = VEP_INTAG; } else if (p < e && *p == '/') { vep->state = VEP_INTAG; } else if (p < e && vct_issp(*p)) { vep->state = VEP_INTAG; } else if (p < e) { vep_error(vep, "XML 1.0 Illegal attr char"); vep->state = VEP_TAGERROR; } } else if (vep->state == VEP_ATTRGETVAL) { vep->attr_vsb = VSB_new_auto(); vep->state = VEP_ATTRDELIM; } else if (vep->state == VEP_ATTRDELIM) { AZ(vep->attr_delim); if (*p == '"' || *p == '\'') { vep->attr_delim = *p++; vep->state = VEP_ATTRVAL; } else if (!vct_issp(*p)) { vep->attr_delim = ' '; vep->state = VEP_ATTRVAL; } else { vep_error(vep, "XML 1.0 Illegal attribute delimiter"); vep->state = VEP_TAGERROR; } } else if (vep->state == VEP_ATTRVAL) { while (p < e && *p != '>' && *p != vep->attr_delim && (vep->attr_delim != ' ' || !vct_issp(*p))) { if (vep->attr_vsb != NULL) VSB_putc(vep->attr_vsb, *p); p++; } if (p < e && *p == '>') { vep_error(vep, "XML 1.0 Missing end attribute delimiter"); vep->state = VEP_TAGERROR; vep->attr_delim = 0; if (vep->attr_vsb != NULL) { AZ(VSB_finish(vep->attr_vsb)); VSB_destroy(&vep->attr_vsb); } } else if (p < e) { vep->attr_delim = 0; p++; vep->state = VEP_INTAG; if (vep->attr_vsb != NULL) { AZ(VSB_finish(vep->attr_vsb)); AN(vep->dostuff); vep->dostuff(vep, DO_ATTR); vep->attr_vsb = NULL; } } /****************************************************** * Utility Section */ } else if (vep->state == VEP_MATCH) { /* * Match against a table */ vm = vep_match(vep, p, e); vep->match_hit = vm; if (vm != NULL) { if (vm->match != NULL) p += strlen(vm->match); vep->state = *vm->state; vep->match = NULL; vep->tag_i = 0; } else { assert(e - p <= sizeof(vep->tag)); memcpy(vep->tag, p, e - p); vep->tag_i = e - p; vep->state = VEP_MATCHBUF; p = e; } } else if (vep->state == VEP_MATCHBUF) { /* * Match against a table while split over input * sections. */ AN(vep->match); i = sizeof(vep->tag) - vep->tag_i; if (i > e - p) i = e - p; memcpy(vep->tag + vep->tag_i, p, i); vm = vep_match(vep, vep->tag, vep->tag + vep->tag_i + i); if (vm == NULL) { vep->tag_i += i; p += i; assert(p == e); } else { vep->match_hit = vm; vep->state = *vm->state; if (vm->match != NULL) p += strlen(vm->match) - vep->tag_i; vep->match = NULL; vep->tag_i = 0; } } else if (vep->state == VEP_UNTIL) { /* * Skip until we see magic string */ while (p < e) { if (*p++ != *vep->until_p++) { vep->until_p = vep->until; } else if (*vep->until_p == '\0') { vep->state = vep->until_s; break; } } if (p == e && !vep->remove) vep_mark_verbatim(vep, p); } else { Debug("*** Unknown state %s\n", vep->state); WRONG("WRONG ESI PARSER STATE"); } } /* * We must always mark up the storage we got, try to do so * in the most efficient way, in particular with respect to * minimizing and limiting use of pending. */ if (p == vep->ver_p) ; else if (vep->in_esi_tag) vep_mark_skip(vep, p); else if (vep->remove) vep_mark_skip(vep, p); else vep_mark_pending(vep, p); }
/* * Quote a string */ void VSB_quote_pfx(struct vsb *s, const char *pfx, const void *v, int len, int how) { const char *p; const char *q; int quote = 0; int nl = 0; const unsigned char *u, *w; assert(v != NULL); if (len == -1) len = strlen(v); if (len == 0 && (how & VSB_QUOTE_CSTR)) { VSB_printf(s, "%s\"\"", pfx); return; } else if (len == 0) return; VSB_cat(s, pfx); if (how & VSB_QUOTE_HEX) { u = v; for (w = u; w < u + len; w++) if (*w != 0x00) break; VSB_printf(s, "0x"); if (w == u + len && len > 4) { VSB_printf(s, "0...0"); } else { for (w = u; w < u + len; w++) VSB_printf(s, "%02x", *w); } return; } p = v; for (q = p; q < p + len; q++) { if (!isgraph(*q) || *q == '"' || *q == '\\') { quote++; break; } } if (!quote && !(how & (VSB_QUOTE_JSON|VSB_QUOTE_CSTR))) { (void)VSB_bcat(s, p, len); if ((how & (VSB_QUOTE_UNSAFE|VSB_QUOTE_NONL)) && p[len-1] != '\n') (void)VSB_putc(s, '\n'); return; } if (how & VSB_QUOTE_CSTR) (void)VSB_putc(s, '"'); for (q = p; q < p + len; q++) { if (nl) VSB_cat(s, pfx); nl = 0; switch (*q) { case '?': if (how & VSB_QUOTE_CSTR) (void)VSB_putc(s, '\\'); (void)VSB_putc(s, *q); break; case ' ': (void)VSB_putc(s, *q); break; case '\\': case '"': if (!(how & VSB_QUOTE_UNSAFE)) (void)VSB_putc(s, '\\'); (void)VSB_putc(s, *q); break; case '\n': if (how & VSB_QUOTE_CSTR) { (void)VSB_printf(s, "\\n\"\n%s\t\"", pfx); } else if (how & (VSB_QUOTE_NONL|VSB_QUOTE_UNSAFE)) { (void)VSB_printf(s, "\n"); nl = 1; } else { (void)VSB_printf(s, "\\n"); } break; case '\r': (void)VSB_cat(s, "\\r"); break; case '\t': (void)VSB_cat(s, "\\t"); break; case '\v': (void)VSB_cat(s, "\\v"); break; default: /* XXX: Implement VSB_QUOTE_JSON */ if (isgraph(*q)) (void)VSB_putc(s, *q); else if (how & VSB_QUOTE_ESCHEX) (void)VSB_printf(s, "\\x%02x", *q & 0xff); else (void)VSB_printf(s, "\\%03o", *q & 0xff); break; } } if (how & VSB_QUOTE_CSTR) (void)VSB_putc(s, '"'); if ((how & (VSB_QUOTE_NONL|VSB_QUOTE_UNSAFE)) && !nl) (void)VSB_putc(s, '\n'); }
pan_ic(const char *func, const char *file, int line, const char *cond, enum vas_e kind) { const char *q; struct req *req; struct busyobj *bo; struct sigaction sa; int err = errno; AZ(pthread_mutex_lock(&panicstr_mtx)); /* Won't be released, we're going to die anyway */ /* * should we trigger a SIGSEGV while handling a panic, our sigsegv * handler would hide the panic, so we need to reset the handler to * default */ memset(&sa, 0, sizeof sa); sa.sa_handler = SIG_DFL; (void)sigaction(SIGSEGV, &sa, NULL); /* Set SIGABRT back to default so the final abort() has the desired effect */ (void)sigaction(SIGABRT, &sa, NULL); switch(kind) { case VAS_WRONG: VSB_printf(pan_vsb, "Wrong turn at %s:%d:\n%s\n", file, line, cond); break; case VAS_VCL: VSB_printf(pan_vsb, "Panic from VCL:\n %s\n", cond); break; case VAS_MISSING: VSB_printf(pan_vsb, "Missing errorhandling code in %s(), %s line %d:\n" " Condition(%s) not true.", func, file, line, cond); break; case VAS_INCOMPLETE: VSB_printf(pan_vsb, "Incomplete code in %s(), %s line %d:\n", func, file, line); break; default: case VAS_ASSERT: VSB_printf(pan_vsb, "Assert error in %s(), %s line %d:\n" " Condition(%s) not true.\n", func, file, line, cond); break; } if (err) VSB_printf(pan_vsb, "errno = %d (%s)\n", err, strerror(err)); q = THR_GetName(); if (q != NULL) VSB_printf(pan_vsb, "thread = (%s)\n", q); VSB_printf(pan_vsb, "version = %s\n", VCS_version); VSB_printf(pan_vsb, "ident = %s,%s\n", VSB_data(vident) + 1, Waiter_GetName()); pan_backtrace(pan_vsb); if (!FEATURE(FEATURE_SHORT_PANIC)) { req = THR_GetRequest(); if (req != NULL) { pan_req(pan_vsb, req); VSL_Flush(req->vsl, 0); } bo = THR_GetBusyobj(); if (bo != NULL) { pan_busyobj(pan_vsb, bo); VSL_Flush(bo->vsl, 0); } } VSB_printf(pan_vsb, "\n"); VSB_putc(pan_vsb, '\0'); /* NUL termination */ if (FEATURE(FEATURE_NO_COREDUMP)) exit(4); else abort(); }