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 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 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 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 127 sighandler(int signo) 128 { 129 gotsig = signo; 130 } 131 132 static void __dead 133 usage(void) 134 { 135 fprintf(stderr, "usage: vnode [-Iv] -f path test-case\n"); 136 exit(1); 137 } 138