2 * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <sys/queue.h>
18 #include <sys/socket.h>
52 static const char *argv0;
53 static const char *dir;
56 static uint8_t *lastmsg;
58 static struct imsgbuf ibuf;
59 static int ibuf_inuse;
60 static int child_out = -1;
62 static struct procs procs = TAILQ_HEAD_INITIALIZER(procs);
63 static struct tests tests = TAILQ_HEAD_INITIALIZER(tests);
67 static struct opstacks blocks = TAILQ_HEAD_INITIALIZER(blocks);
68 static struct opstacks args = TAILQ_HEAD_INITIALIZER(args);
70 #define STACK_HEIGHT 64
71 static struct value vstack[STACK_HEIGHT];
74 static struct envs envs = TAILQ_HEAD_INITIALIZER(envs);
76 static struct value v_false = {.type = V_NUM, .v = {.num = 0}};
77 static struct value v_true = {.type = V_NUM, .v = {.num = 1}};
79 static uint8_t lasttag;
82 static int syntaxcheck;
84 static const char *filler;
96 check_for_output(void)
98 static char buf[BUFSIZ];
104 if (poll(&pfd, 1, 0) == -1)
107 if (!(pfd.revents & POLLIN))
111 if ((r = read(child_out, buf, sizeof(buf))) == -1) {
119 fwrite(buf, 1, r, stdout);
124 peekn(int depth, struct value *v)
127 errx(1, "can't peek the stack at %d: underflow",
129 memcpy(v, &vstack[stackh - depth], sizeof(*v));
132 printf("peeking(%d) ", depth); pp_val(v); printf("\n");
137 popv(struct value *v)
140 errx(1, "can't pop the stack: underflow");
141 memcpy(v, &vstack[--stackh], sizeof(*v));
144 printf("popping "); pp_val(v); printf("\n");
158 pushv(struct value *v)
160 if (stackh == STACK_HEIGHT)
161 errx(1, "can't push the stack: overflow");
164 printf("pushing "); pp_val(v); printf("\n");
167 memcpy(&vstack[stackh++], v, sizeof(*v));
173 pushv(n ? &v_true : &v_false);
186 static inline struct opstack *
187 pushstack(struct opstacks *stack)
191 ops = xcalloc(1, sizeof(*ops));
192 TAILQ_INSERT_HEAD(stack, ops, entry);
196 static inline struct opstack *
197 peek(struct opstacks *stack)
199 if (TAILQ_EMPTY(stack))
200 errx(1, "%s: args underflow", __func__);
202 return TAILQ_FIRST(stack);
205 static inline struct op *
206 finalize(struct opstacks *stack, int *argc)
211 if (TAILQ_EMPTY(stack))
212 errx(1, "%s: args underflow", __func__);
215 TAILQ_REMOVE(&args, ops, entry);
219 *argc = ops->counter;
226 push(struct opstacks *stack, struct op *op)
231 if (ops->last == NULL) {
235 ops->last->next = op;
247 e = xcalloc(1, sizeof(*e));
248 TAILQ_INSERT_HEAD(&envs, e, entry);
251 static inline struct env *
254 assert(!TAILQ_EMPTY(&envs));
255 return TAILQ_FIRST(&envs);
262 struct binding *b, *tb;
265 TAILQ_REMOVE(&envs, e, entry);
267 TAILQ_FOREACH_SAFE(b, &e->bindings, entry, tb)
274 setvar(char *sym, struct op *op)
281 if ((ret = eval(op)) != EVAL_OK)
284 if (stackh != height + 1) {
286 printf("trying to assign to `%s' a void value: ", sym);
292 b = xcalloc(1, sizeof(*b));
296 e = TAILQ_FIRST(&envs);
297 TAILQ_INSERT_HEAD(&e->bindings, b, entry);
303 setvar_raw(char *sym, struct op *op)
308 b = xcalloc(1, sizeof(*b));
312 e = TAILQ_FIRST(&envs);
313 TAILQ_INSERT_HEAD(&e->bindings, b, entry);
317 getvar(const char *sym, struct value *v)
322 TAILQ_FOREACH(e, &envs, entry) {
323 TAILQ_FOREACH(b, &e->bindings, entry) {
324 if (!strcmp(sym, b->name)) {
325 memcpy(v, &b->val, sizeof(*v));
332 fprintf(stderr, "unbound variable %s\n", sym);
337 getvar_raw(const char *sym, struct op **raw)
342 TAILQ_FOREACH(e, &envs, entry) {
343 TAILQ_FOREACH(b, &e->bindings, entry) {
344 if (!strcmp(sym, b->name)) {
355 global_set(char *sym, struct op *op)
360 /* TODO: check for duplicates */
362 if (op->type != OP_LITERAL &&
363 (op->type == OP_CAST && op->v.cast.expr->type != OP_LITERAL))
366 b = xcalloc(1, sizeof(*b));
369 /* it's only a cast on a literal! */
370 if (op->type == OP_CAST) {
371 if (eval(op) != EVAL_OK) {
377 memcpy(&b->val, &op->v.literal, sizeof(b->val));
379 e = TAILQ_LAST(&envs, envs);
380 TAILQ_INSERT_HEAD(&e->bindings, b, entry);
390 op = xcalloc(1, sizeof(*op));
397 free_op_rec(struct op *op)
409 free_op(struct op *op)
420 free(op->v.assign.name);
421 free_op_rec(op->v.assign.expr);
424 free_op_rec(op->v.assert);
427 free_op_rec(op->v.funcall.argv);
433 free_op_rec(op->v.cast.expr);
437 free_op_rec(op->v.bin_cmp.a);
438 free_op_rec(op->v.bin_cmp.b);
441 free_op_rec(op->v.faccess.expr);
442 free(op->v.faccess.field);
445 free(op->v.sfail.msg);
446 free_op_rec(op->v.sfail.expr);
459 return newop(OP_REST);
463 op_assign(char *sym, struct op *expr)
467 op = newop(OP_ASSIGN);
468 op->v.assign.name = sym;
469 op->v.assign.expr = expr;
475 op_assert(struct op *expr)
479 op = newop(OP_ASSERT);
497 op_lit_str(char *str)
501 op = newop(OP_LITERAL);
502 op->v.literal.type = V_STR;
503 op->v.literal.v.str = str;
509 op_lit_num(uint64_t n)
513 op = newop(OP_LITERAL);
514 op->v.literal.type = V_NUM;
515 op->v.literal.v.num = n;
521 op_cmp_eq(struct op *a, struct op *b)
525 op = newop(OP_CMP_EQ);
533 op_cmp_leq(struct op *a, struct op *b)
537 op = newop(OP_CMP_LEQ);
545 op_cast(struct op *expr, int totype)
550 op->v.cast.expr = expr;
551 op->v.cast.totype = totype;
557 op_faccess(struct op *expr, char *field)
561 op = newop(OP_FACCESS);
562 op->v.faccess.expr = expr;
563 op->v.faccess.field = field;
569 op_sfail(struct op *expr, char *msg)
573 op = newop(OP_SFAIL);
574 op->v.sfail.expr = expr;
575 op->v.sfail.msg = msg;
585 op = newop(OP_VARGS);
591 ppf_val(FILE *f, struct value *val)
597 fprintf(f, "%s", val->v.str);
600 fprintf(f, "\"%s\"", val->v.str);
603 fprintf(f, "%"PRIi64, val->v.num);
606 fprintf(f, "%"PRIu8, val->v.u8);
609 fprintf(f, "%"PRIu16, val->v.u16);
612 fprintf(f, "%"PRIu32, val->v.u32);
616 for (i = 0; i < val->v.msg.len; ++i)
617 fprintf(f, "%x%s", val->v.msg.msg[i],
618 i == val->v.msg.len-1 ? "" : " ");
622 fprintf(f, "qids[n=%zu]", val->v.qidvec.len);
625 fprintf(f, "<unknown value>");
631 pp_val(struct value *val)
633 ppf_val(stdout, val);
637 val_type(struct value *v)
640 case V_SYM: return "symbol";
641 case V_STR: return "string";
642 case V_NUM: return "number";
643 case V_MSG: return "message";
644 case V_QID: return "qid";
645 case V_U8: return "u8";
646 case V_U16: return "u16";
647 case V_U32: return "u32";
648 default: return "unknown";
653 val_trueish(struct value *a)
661 val_isnum(struct value *a)
663 return a->type == V_NUM
670 val_tonum(struct value *a)
673 case V_NUM: return a->v.num;
674 case V_U8: return a->v.u8;
675 case V_U16: return a->v.u16;
676 case V_U32: return a->v.u32;
679 fprintf(stderr, "%s: given value is not a number\n", __func__);
685 val_eq(struct value *a, struct value *b)
687 if (val_isnum(a) && val_isnum(b))
688 return val_tonum(a) == val_tonum(b);
690 if (a->type != b->type)
696 return !strcmp(a->v.str, b->v.str);
703 val_leq(struct value *a, struct value *b)
705 if (val_isnum(a) && val_isnum(b))
706 return val_tonum(a) <= val_tonum(b);
710 static inline const char *
711 pp_totype(int totype)
714 * Not all of these are valid cast type thought, including
715 * every possibility only to aid debugging.
718 case V_STR: return "str";
719 case V_SYM: return "sym";
720 case V_NUM: return "num";
721 case V_QID: return "qid";
722 case V_U8: return "u8";
723 case V_U16: return "u16";
724 case V_U32: return "u32";
725 default: return "unknown";
730 val_cast(struct value *a, int totype)
734 #define NUMCAST(val, t, c, totype, max) do { \
737 fprintf(stderr, "can't cast %"PRIu64 \
738 " to %s\n", val, pp_totype(totype)); \
746 if (a->type == totype)
751 fprintf(stderr, "can't cast ");
753 fprintf(stderr, " to type %s\n", pp_totype(totype));
759 case V_U8: NUMCAST(v, u8, uint8_t, totype, UINT8_MAX);
760 case V_U16: NUMCAST(v, u16, uint16_t, totype, UINT16_MAX);
761 case V_U32: NUMCAST(v, u32, uint32_t, totype, UINT32_MAX);
764 fprintf(stderr, "can't cast %"PRIu64" to %s\n",
765 v, pp_totype(totype));
773 val_faccess(struct value *a, const char *field, struct value *ret)
779 #define MSGTYPE(m) *(m.msg + 4) /* skip the length */
783 /* TODO: add path. needs uint64_t values thought! */
784 if (!strcmp(field, "vers")) {
786 memcpy(&ret->v.u32, a->v.qid+1, 4);
788 } else if (!strcmp(field, "type")) {
790 ret->v.u8 = *a->v.qid;
796 mtype = MSGTYPE(a->v.msg);
797 if (!strcmp(field, "type")) {
799 ret->v.u8 = MSGTYPE(a->v.msg);
801 } else if (!strcmp(field, "tag")) {
803 memcpy(&ret->v.u16, &a->v.msg.msg[5], 2);
804 ret->v.u16 = le16toh(ret->v.u16);
806 } else if (!strcmp(field, "msize") && mtype == Rversion) {
808 memcpy(&ret->v.u32, &a->v.msg.msg[7], 4);
809 ret->v.u32 = le32toh(ret->v.u32);
811 } else if (!strcmp(field, "qid") && mtype == Rattach) {
813 memcpy(&ret->v.qid, &a->v.msg.msg[7], QIDSIZE);
815 } else if (!strcmp(field, "nwqid") && mtype == Rwalk) {
817 memcpy(&ret->v.u16, &a->v.msg.msg[7], 2);
818 ret->v.u16 = le16toh(ret->v.u16);
820 } else if (!strcmp(field, "wqid") && mtype == Rwalk) {
821 ret->type = V_QIDVEC;
822 ret->v.qidvec.start = &a->v.msg.msg[9];
823 memcpy(&len, &a->v.msg.msg[7], 2);
825 ret->v.qidvec.len = len;
831 len = strtonum(field, 0, MAXWELEM, &errstr);
832 if (errstr != NULL) {
834 printf("can't access qid #%s: %s\n", field, errstr);
838 if (len >= a->v.qidvec.len) {
840 printf("can't access qid #%d: out-of-bound "
841 "(max %zu)\n", len, a->v.qidvec.len);
846 memcpy(&ret->v.qid, a->v.qidvec.start + len * QIDSIZE,
856 printf("can't access field `%s' on type %s (", field, val_type(a));
874 printf("%s = ", op->v.assign.name);
875 pp_op(op->v.assign.expr);
882 printf("funcall %s(", op->v.funcall.proc->name);
883 for (aux = op->v.funcall.argv; aux != NULL; aux = aux->next) {
885 if (aux->next != NULL)
891 pp_val(&op->v.literal);
894 printf("%s", op->v.var);
897 pp_op(op->v.cast.expr);
899 switch (op->v.cast.totype) {
900 case V_U8: printf("u8"); break;
901 case V_U16: printf("u16"); break;
902 case V_U32: printf("u32"); break;
903 case V_STR: printf("str"); break;
904 default: printf("???"); break;
908 pp_op(op->v.bin_cmp.a);
910 pp_op(op->v.bin_cmp.b);
913 pp_op(op->v.bin_cmp.a);
915 pp_op(op->v.bin_cmp.b);
918 pp_op(op->v.faccess.expr);
919 printf(".%s", op->v.faccess.field);
922 printf("should-fail ");
923 pp_op(op->v.sfail.expr);
924 if (op->v.sfail.msg != NULL)
925 printf(": \"%s\"", op->v.sfail.msg);
931 printf(" ???[%d] ", op->type);
936 pp_block(struct op *op)
952 struct op *t, *tnext;
963 * Try to load the rest argument. Note that it can be
966 if ((ret = getvar_raw("...", &t)) == EVAL_OK)
967 if ((ret = eval(t)) != EVAL_OK)
972 ret = setvar(op->v.assign.name, op->v.assign.expr);
978 if ((ret = eval(op->v.assert)) != EVAL_OK)
981 if (!val_trueish(&a)) {
983 printf("assertion failed: ");
991 /* assume airity matches */
993 proc = op->v.funcall.proc;
994 if (proc->nativefn != NULL) {
996 * Push arguments on the stack for builtin
997 * functions. Counting the height of the
998 * stack is done to compute the correct number
999 * in the vararg case. argc only counts the
1000 * "syntactical" arguments, i.e. foo(x, ...)
1001 * has argc == 2, but at runtime argc may be
1002 * 1, 2 or a greater number!
1006 t = op->v.funcall.argv;
1007 if (t != NULL && (ret = eval(t)) != EVAL_OK)
1013 if ((ret = proc->nativefn(i))
1017 if (proc->body == NULL) {
1019 printf("warn: calling the empty proc `%s'\n",
1026 for (t = op->v.funcall.argv, i = 0;
1030 * Push a pseudo variable `...' (and
1031 * don't evaluate it) in the vararg
1032 * case. A special case is when the
1033 * variable is itself `...'.
1035 if (proc->vararg && i == proc->minargs) {
1036 if (t->type != OP_REST)
1037 setvar_raw(xstrdup("..."), t);
1042 * The arguments are a linked list of
1043 * ops. Setvar will call eval that
1044 * will evaluate *all* the arguments.
1045 * The dance here that sets next to
1046 * NULL and then restores it is to
1047 * avoid this behaviour.
1051 ret = setvar(proc->args[i], t);
1058 if ((ret = eval(proc->body)) != EVAL_OK)
1067 pushv(&op->v.literal);
1071 if ((ret = getvar(op->v.var, &a)) != EVAL_OK)
1077 if ((ret = eval(op->v.cast.expr)) != EVAL_OK)
1080 if ((ret = val_cast(&a, op->v.cast.totype)) != EVAL_OK)
1086 if ((ret = eval(op->v.bin_cmp.a)) != EVAL_OK)
1088 if ((ret = eval(op->v.bin_cmp.b)) != EVAL_OK)
1093 pushbool(val_eq(&a, &b));
1097 if ((ret = eval(op->v.bin_cmp.a)) != EVAL_OK)
1099 if ((ret = eval(op->v.bin_cmp.b)) != EVAL_OK)
1104 pushbool(val_leq(&a, &b));
1108 if ((ret = eval(op->v.faccess.expr)) != EVAL_OK)
1111 if ((ret = val_faccess(&a, op->v.faccess.field, &b))
1118 if ((ret = eval(op->v.sfail.expr)) == EVAL_OK) {
1120 printf("expecting failure");
1121 if (op->v.sfail.msg != NULL)
1122 printf(" \"%s\"", op->v.sfail.msg);
1124 printf("expression: ");
1125 pp_op(op->v.sfail.expr);
1129 if (ret == EVAL_SKIP)
1134 if ((ret = getvar_raw("...", &t)) == EVAL_OK) {
1135 for (i = 0; t != NULL; t = t->next)
1144 fprintf(stderr, "invalid op, aborting.\n");
1149 return eval(op->next);
1154 prepare_funcall(void)
1160 push_arg(struct op *op)
1166 op_funcall(struct proc *proc)
1168 struct op *op, *argv;
1171 argv = finalize(&args, &argc);
1173 op = newop(OP_FUNCALL);
1174 op->v.funcall.proc = proc;
1175 op->v.funcall.argv = argv;
1176 op->v.funcall.argc = argc;
1182 add_builtin_proc(const char *name, int (*fn)(int), int argc, int vararg)
1186 proc = xcalloc(1, sizeof(*proc));
1187 proc->name = xstrdup(name);
1188 proc->nativefn = fn;
1189 proc->minargs = argc;
1190 proc->vararg = vararg;
1192 TAILQ_INSERT_HEAD(&procs, proc, entry);
1202 proc_setup_body(void)
1204 struct opstack *argv;
1209 for (i = 0, op = argv->base.next; op != NULL; i++) {
1211 * TODO: should free the whole list on error but..,
1212 * we're gonna exit real soon(tm)!
1214 if (op->type != OP_VAR && op->type != OP_REST)
1220 assert(i == argv->counter);
1226 proc_done(char *name)
1229 struct op *op, *next, *argv, *body;
1232 argv = finalize(&args, &argc);
1233 body = finalize(&blocks, NULL);
1235 proc = xcalloc(1, sizeof(*proc));
1237 proc->minargs = argc;
1239 for (i = 0, op = argv; op != NULL; ++i) {
1240 if (op->type == OP_REST) {
1246 proc->args[i] = xstrdup(op->v.var);
1252 assert(i == argc || (proc->vararg && i == proc->minargs));
1256 TAILQ_INSERT_HEAD(&procs, proc, entry);
1260 block_push(struct op *op)
1266 proc_by_name(const char *name)
1270 TAILQ_FOREACH(p, &procs, entry) {
1271 if (!strcmp(p->name, name))
1285 test_done(int shouldfail, char *name)
1289 test = xcalloc(1, sizeof(*test));
1290 test->shouldfail = shouldfail;
1292 test->body = finalize(&blocks, NULL);
1294 if (TAILQ_EMPTY(&tests))
1295 TAILQ_INSERT_HEAD(&tests, test, entry);
1297 TAILQ_INSERT_TAIL(&tests, test, entry);
1303 builtin_print(int argc)
1310 for (i = argc; i > 0; --i) {
1312 if (v.type == V_STR)
1313 printf("%s", v.v.str);
1327 builtin_debug(int argc)
1330 return builtin_print(argc);
1337 builtin_skip(int argc)
1343 builtin_iota(int argc)
1348 if ((v.v.u16 = ++lasttag) == 255)
1349 v.v.u16 = ++lasttag;
1356 builtin_send(int argc)
1367 * Compute the length of the packet. 4 is for the initial
1372 for (i = argc; i > 0; --i) {
1376 len += 2; /* count */
1377 len += strlen(v.v.str);
1394 printf("%s: can't serialize ", __func__);
1401 if (len > UINT16_MAX) {
1403 printf("%s: message size too long: got %d when max is %d\n",
1404 __func__, len, UINT16_MAX);
1408 if ((buf = imsg_create(&ibuf, IMSG_BUF, 0, 0, len)) == NULL)
1409 fatal("imsg_create(%d)", len);
1412 imsg_add(buf, &len, sizeof(len));
1414 for (i = argc; i > 0; --i) {
1418 slen = strlen(v.v.str);
1419 slen = htole16(slen);
1420 imsg_add(buf, &slen, sizeof(slen));
1421 imsg_add(buf, v.v.str, strlen(v.v.str));
1425 imsg_add(buf, &v.v.u8, 1);
1429 v.v.u16 = htole16(v.v.u16);
1430 imsg_add(buf, &v.v.u16, 2);
1434 v.v.u32 = htole32(v.v.u32);
1435 imsg_add(buf, &v.v.u32, 4);
1440 imsg_close(&ibuf, buf);
1442 if (imsg_flush(&ibuf) == -1) {
1445 printf("%s: imsg_flush failed: %s\n", __func__, strerror(i));
1454 builtin_recv(int argc)
1462 if (lastmsg != NULL) {
1468 pfd.events = POLLIN;
1469 if (poll(&pfd, 1, INFTIM) == -1) {
1472 printf("%s: poll failed: %s\n", __func__, strerror(serrno));
1477 if ((n = imsg_read(&ibuf)) == -1) {
1478 if (errno == EAGAIN)
1485 printf("child disconnected\n");
1492 /* read only one message */
1493 if ((n = imsg_get(&ibuf, &imsg)) == -1)
1498 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1499 switch (imsg.hdr.type) {
1502 if ((v.v.msg.msg = malloc(datalen)) == NULL)
1504 memcpy(v.v.msg.msg, imsg.data, datalen);
1505 v.v.msg.len = datalen;
1512 printf("subprocess closed the connection\n");
1522 printf("got unknown message from subprocess: %d\n",
1530 spawn_client_proc(void)
1532 const char *argv[4];
1533 int p[2], out[2], argc = 0;
1536 if (child_out != -1)
1539 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
1540 PF_UNSPEC, p) == -1)
1541 fatal("socketpair");
1543 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
1544 PF_UNSPEC, out) == -1)
1545 fatal("socketpair");
1547 switch (pid = fork()) {
1549 fatal("cannot fork");
1557 msgbuf_clear(&ibuf.w);
1560 imsg_init(&ibuf, p[0]);
1568 if (dup2(out[1], 1) == -1 ||
1569 dup2(out[1], 2) == -1)
1573 if (dup2(p[1], 3) == -1)
1574 fatal("cannot setup imsg fd");
1575 } else if (fcntl(F_SETFD, 0) == -1)
1576 fatal("cannot setup imsg fd");
1578 argv[argc++] = argv0;
1579 argv[argc++] = "-Tc";
1582 argv[argc++] = "-v";
1585 argv[argc++] = NULL;
1587 execvp(argv0, (char *const *)argv);
1592 prepare_child_for_test(struct test *t)
1596 if ((pw = getpwuid(uid)) == NULL)
1597 fatal("getpwuid(%d)", uid);
1599 imsg_compose(&ibuf, IMSG_AUTH, 0, 0, -1,
1600 pw->pw_name, strlen(pw->pw_name)+1);
1601 imsg_compose(&ibuf, IMSG_AUTH_DIR, 0, 0, -1,
1602 dir, strlen(dir)+1);
1604 if (imsg_flush(&ibuf) == -1)
1605 fatal("imsg_flush");
1609 run_test(struct test *t)
1616 puts("=====================");
1618 puts("=====================");
1624 if (t->body == NULL) {
1626 printf("no instructions, skipping...\n");
1630 pid = spawn_client_proc();
1631 prepare_child_for_test(t);
1632 ret = eval(t->body);
1634 imsg_compose(&ibuf, IMSG_CONN_GONE, 0, 0, -1, NULL, 0);
1637 while (waitpid(pid, NULL, 0) != pid)
1642 if (t->shouldfail) {
1643 if (ret == EVAL_OK) {
1645 printf("test was expected to fail\n");
1647 } else if (ret == EVAL_ERR)
1655 main(int argc, char **argv)
1659 int ch, i, r, passed = 0, failed = 0, skipped = 0;
1661 const char *pat = NULL;
1664 assert(argv0 = argv[0]);
1666 signal(SIGPIPE, SIG_IGN);
1668 log_init(1, LOG_DAEMON);
1671 /* prepare the global env */
1674 add_builtin_proc("print", builtin_print, 1, 1);
1675 add_builtin_proc("debug", builtin_debug, 1, 1);
1676 add_builtin_proc("skip", builtin_skip, 0, 0);
1677 add_builtin_proc("iota", builtin_iota, 0, 0);
1678 add_builtin_proc("send", builtin_send, 2, 1);
1679 add_builtin_proc("recv", builtin_recv, 0, 0);
1681 while ((ch = getopt(argc, argv, "nT:r:vx:")) != -1) {
1687 assert(*optarg == 'c');
1700 fprintf(stderr, "Usage: %s [-nv] [files...]\n",
1712 fatal("missing root test dir");
1714 if (stat(dir, &sb) == -1)
1715 fatal("stat(\"%s\")", dir);
1721 if (regcomp(®, pat, REG_ICASE | REG_NOSUB) != 0)
1722 fatalx("invalid regexp: %s", pat);
1724 for (i = 0; i < argc; ++i)
1728 fprintf(stderr, "files OK\n");
1732 /* Check for root privileges. */
1734 fatalx("need root privileges");
1737 TAILQ_FOREACH(t, &tests, entry) {
1738 if (regexec(®, t->name, 0, NULL, 0) != 0)
1741 printf("===> [%d/%d] running test \"%s\"... ", i+1, ntests,
1760 printf("skipped\n");
1771 printf("%d/%d passed (%d skipped and %d failed)\n",
1772 passed, i, skipped, failed);