void vcc_ErrWhere(struct tokenlist *tl, const struct token *t) { unsigned x, y; const char *p, *l, *e; vcc_icoord(tl->sb, t, &l); vsb_printf(tl->sb, "\n"); x = y = 0; e = t->src->e; for (p = l; p < e && *p != '\n'; p++) { if (*p == '\t') { y &= ~7; y += 8; while (x < y) { vsb_bcat(tl->sb, " ", 1); x++; } } else { x++; y++; vsb_bcat(tl->sb, p, 1); } } vsb_cat(tl->sb, "\n"); x = y = 0; for (p = l; p < e && *p != '\n'; p++) { if (p >= t->b && p < t->e) { vsb_bcat(tl->sb, "#", 1); x++; y++; continue; } if (*p == '\t') { y &= ~7; y += 8; } else y++; while (x < y) { vsb_bcat(tl->sb, "-", 1); x++; } } vsb_cat(tl->sb, "\n"); tl->err = 1; }
/* * Copy a byte string into an vsb. */ int vsb_bcpy(struct vsb *s, const void *buf, size_t len) { assert_vsb_integrity(s); assert_vsb_state(s, 0); vsb_clear(s); return (vsb_bcat(s, buf, len)); }
/* * 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': (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, '"'); }
/* * Unquote a string */ const char * vsb_unquote(struct vsb *s, const char *p, int len, int how) { const char *q; char *r; unsigned long u; char c; (void)how; /* For future enhancements */ if (len == -1) len = strlen(p); for (q = p; q < p + len; q++) { if (*q != '\\') { (void)vsb_bcat(s, q, 1); continue; } if (++q >= p + len) return ("Incomplete '\\'-sequence at end of string"); switch(*q) { case 'n': (void)vsb_bcat(s, "\n", 1); continue; case 'r': (void)vsb_bcat(s, "\r", 1); continue; case 't': (void)vsb_bcat(s, "\t", 1); continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': errno = 0; u = strtoul(q, &r, 8); if (errno != 0 || (u & ~0xff)) return ("\\ooo sequence out of range"); c = (char)u; (void)vsb_bcat(s, &c, 1); q = r - 1; continue; default: (void)vsb_bcat(s, q, 1); } } return (NULL); }
static void cmd_http_txresp(CMD_ARGS) { struct http *hp; const char *proto = "HTTP/1.1"; const char *status = "200"; const char *msg = "Ok"; int bodylen = 0; char *b, *c; char *body = NULL, *nullbody; int nolen = 0; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); ONLY_SERVER(hp, av); assert(!strcmp(av[0], "txresp")); av++; vsb_clear(hp->vsb); /* send a "Content-Length: 0" header unless something else happens */ REPLACE(body, ""); nullbody = body; for(; *av != NULL; av++) { if (!strcmp(*av, "-proto")) { proto = av[1]; av++; } else if (!strcmp(*av, "-status")) { status = av[1]; av++; } else if (!strcmp(*av, "-msg")) { msg = av[1]; av++; continue; } else break; } vsb_printf(hp->vsb, "%s %s %s%s", proto, status, msg, nl); for(; *av != NULL; av++) { if (!strcmp(*av, "-nolen")) { nolen = 1; } else if (!strcmp(*av, "-hdr")) { vsb_printf(hp->vsb, "%s%s", av[1], nl); av++; } else break; } for(; *av != NULL; av++) { if (!strcmp(*av, "-body")) { assert(body == nullbody); REPLACE(body, av[1]); AN(body); av++; bodylen = strlen(body); for (b = body; *b != '\0'; b++) { if(*b == '\\' && b[1] == '0') { *b = '\0'; for(c = b+1; *c != '\0'; c++) { *c = c[1]; } b++; bodylen--; } } } else if (!strcmp(*av, "-bodylen")) { assert(body == nullbody); body = synth_body(av[1]); bodylen = strlen(body); av++; } else break; } if (*av != NULL) vtc_log(hp->vl, 0, "Unknown http txresp spec: %s\n", *av); if (body != NULL && !nolen) vsb_printf(hp->vsb, "Content-Length: %d%s", bodylen, nl); vsb_cat(hp->vsb, nl); if (body != NULL) vsb_bcat(hp->vsb, body, bodylen); http_write(hp, 4, "txresp"); }