1 /* $OpenBSD: vnode.c,v 1.3 2020/12/03 19:16:57 anton Exp $ */
2
3 /*
4 * Copyright (c) 2020 Anton Lindqvist <anton@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <err.h>
20 #include <errno.h>
21 #include <signal.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "extern.h"
29
30 static void sighandler(int);
31 static void __dead usage(void);
32
33 int loglevel = 0;
34
35 static int gotsig;
36
37 int
main(int argc,char * argv[])38 main(int argc, char *argv[])
39 {
40 struct {
41 const char *t_name;
42 int (*t_func)(struct context *);
43 } tests[] = {
44 { "deadlock", test_deadlock },
45
46 { NULL, NULL },
47 };
48 struct context ctx;
49 int ch, i;
50
51 memset(&ctx, 0, sizeof(ctx));
52 ctx.c_iterations = 100;
53
54 while ((ch = getopt(argc, argv, "If:v")) != -1) {
55 switch (ch) {
56 case 'I':
57 ctx.c_iterations = -1;
58 break;
59 case 'f':
60 ctx.c_path = optarg;
61 break;
62 case 'v':
63 loglevel++;
64 break;
65 default:
66 usage();
67 }
68 }
69 argc -= optind;
70 argv += optind;
71 if (argc != 1 || ctx.c_path == NULL)
72 usage();
73
74 if (signal(SIGINT, sighandler) == SIG_ERR)
75 err(1, "signal");
76
77 for (i = 0;; i++) {
78 if (tests[i].t_name == NULL)
79 err(1, "%s: no such test", *argv);
80
81 if (strcmp(tests[i].t_name, *argv))
82 continue;
83
84 return tests[i].t_func(&ctx);
85 }
86
87 return 0;
88 }
89
90 int
ctx_abort(struct context * ctx)91 ctx_abort(struct context *ctx)
92 {
93 if (gotsig)
94 return 1;
95 if (ctx->c_iterations > 0 && --ctx->c_iterations == 0)
96 return 1;
97 return 0;
98 }
99
100 void
logit(const char * fmt,...)101 logit(const char *fmt, ...)
102 {
103 char buf[1024];
104 va_list ap;
105 char *p = buf;
106 ssize_t siz = sizeof(buf);
107 int n;
108
109 n = snprintf(p, siz, "[%d] ", getpid());
110 if (n < 0 || n >= siz)
111 errc(1, ENAMETOOLONG, "%s", __func__);
112 p += n;
113 siz -= n;
114
115 va_start(ap, fmt);
116 n = vsnprintf(p, siz, fmt, ap);
117 va_end(ap);
118 if (n < 0 || n >= siz)
119 errc(1, ENAMETOOLONG, "%s", __func__);
120 p += n;
121 siz -= n;
122
123 fprintf(stderr, "%s\n", buf);
124 }
125
126 static void
sighandler(int signo)127 sighandler(int signo)
128 {
129 gotsig = signo;
130 }
131
132 static void __dead
usage(void)133 usage(void)
134 {
135 fprintf(stderr, "usage: vnode [-Iv] -f path test-case\n");
136 exit(1);
137 }
138