aboutsummaryrefslogtreecommitdiff
path: root/regress/fcgi-test.c
diff options
context:
space:
mode:
Diffstat (limited to 'regress/fcgi-test.c')
-rw-r--r--regress/fcgi-test.c95
1 files changed, 89 insertions, 6 deletions
diff --git a/regress/fcgi-test.c b/regress/fcgi-test.c
index 8f2f9ec..ed6ec4e 100644
--- a/regress/fcgi-test.c
+++ b/regress/fcgi-test.c
@@ -43,6 +43,10 @@
#define SUM(a, b) (((a) << 8) + (b))
+#ifndef nitems
+#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
struct fcgi_header {
uint8_t version;
uint8_t type;
@@ -63,6 +67,11 @@ struct fcgi_end_req_body {
unsigned char reserved[3];
};
+struct param {
+ char name[32];
+ char value[128];
+};
+
static int
prepare_header(struct fcgi_header *h, int type, int id, size_t size,
size_t padding)
@@ -156,12 +165,65 @@ assert_record(int fd, int type)
consume(fd, hdr.padding);
}
+static int
+parse_len(int sock)
+{
+ unsigned char c, x[3];
+
+ must_read(sock, &c, 1);
+ if (c >> 7 == 0)
+ return (c);
+
+ must_read(sock, &x, sizeof(x));
+ return (((c & 0x7F) << 24) | (x[0] << 16) | (x[1] << 8) | x[2]);
+}
+
+static void
+parse_params(int sock, struct param *param, struct fcgi_header *hdr)
+{
+ int tot;
+ int nlen, vlen;
+
+ tot = SUM(hdr->content_len1, hdr->content_len0);
+ tot -= sizeof(*hdr);
+
+ nlen = parse_len(sock);
+ vlen = parse_len(sock);
+
+ if (nlen + vlen != tot)
+ errx(1, "unexpected length, name=%d val=%d exp=%d",
+ nlen, vlen, tot);
+
+ if ((size_t)nlen > sizeof(param->name) - 1 ||
+ (size_t)vlen > sizeof(param->value) - 1)
+ errx(1, "parameter name or value too long");
+
+ memset(param, 0, sizeof(*param));
+ must_read(sock, param->name, nlen);
+ must_read(sock, param->value, vlen);
+
+ if (!strcmp(param->name, "SERVER_NAME"))
+ strlcpy(param->value, "<redacted>", sizeof(param->value));
+
+ consume(sock, hdr->padding);
+}
+
+static int
+param_cmp(const void *a, const void *b)
+{
+ const struct param *x = a, *y = b;
+
+ return (strcmp(x->name, y->name));
+}
+
int
main(int argc, char **argv)
{
struct fcgi_header hdr;
struct fcgi_end_req_body end;
struct sockaddr_un sun;
+ struct param params[64];
+ size_t i, nparam;
const char *path;
const char *msg;
size_t len;
@@ -201,37 +263,58 @@ main(int argc, char **argv)
assert_record(s, FCGI_BEGIN_REQUEST);
/* read params */
+ nparam = 0;
for (;;) {
read_header(s, &hdr);
- consume(s, SUM(hdr.content_len1, hdr.content_len0));
- consume(s, hdr.padding);
-
if (hdr.type != FCGI_PARAMS)
errx(1, "got %d; expecting PARAMS", hdr.type);
if (hdr.content_len0 == 0 &&
hdr.content_len1 == 0 &&
- hdr.padding == 0)
+ hdr.padding == 0) {
+ consume(s, SUM(hdr.content_len1, hdr.content_len0));
+ consume(s, hdr.padding);
break;
+ }
+
+ if (nparam == nitems(params))
+ errx(1, "too many parameters");
+
+ parse_params(s, &params[nparam++], &hdr);
}
assert_record(s, FCGI_STDIN);
- msg = "20 text/gemini\r\n# hello from fastcgi!\n";
+ msg = "20 text/gemini\r\n";
len = strlen(msg);
prepare_header(&hdr, FCGI_STDOUT, 1, len, 0);
must_write(s, &hdr, sizeof(hdr));
must_write(s, msg, len);
- msg = "some more content in the page...\n";
+ msg = "Here's the parameters I've got:\n";
len = strlen(msg);
prepare_header(&hdr, FCGI_STDOUT, 1, len, 0);
must_write(s, &hdr, sizeof(hdr));
must_write(s, msg, len);
+ qsort(params, nparam, sizeof(params[0]), param_cmp);
+ for (i = 0; i < nparam; ++i) {
+ char line[256];
+ int r;
+
+ r = snprintf(line, sizeof(line), "* %s=%s\n",
+ params[i].name, params[i].value);
+ if (r < 0 || (size_t)r >= sizeof(line))
+ errx(1, "line too short");
+
+ prepare_header(&hdr, FCGI_STDOUT, 1, r, 0);
+ must_write(s, &hdr, sizeof(hdr));
+ must_write(s, line, r);
+ }
+
prepare_header(&hdr, FCGI_END_REQUEST, 1, sizeof(end), 0);
write(s, &hdr, sizeof(hdr));
memset(&end, 0, sizeof(end));