build: Allow VPATH docs build
[nbdkit/ericb.git] / wrapper.c
blobe5f74a26c20835f670104a1cf9937c2e19f05c9a
1 /* nbdkit
2 * Copyright (C) 2017-2018 Red Hat Inc.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of Red Hat nor the names of its contributors may be
17 * used to endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 /*------------------------------------------------------------
35 * This wrapper lets you run nbdkit from the source directory.
37 * You can use either:
38 * ./nbdkit file [arg=value] [arg=value] ...
39 * or:
40 * /path/to/nbdkit file [arg=value] [arg=value] ...
42 * Or you can set $PATH to include the nbdkit source directory and run
43 * the bare "nbdkit" command without supplying the full path.
45 * The wrapper modifies the bare plugin name (eg. "file") to be the
46 * full path to the locally compiled plugin. If you don't use this
47 * program and run src/nbdkit directly then it will pick up the
48 * installed plugins which is not usually what you want.
50 * This program is also used to run the tests (make check).
52 * You can enable valgrind by setting NBDKIT_VALGRIND=1 (this
53 * is mainly used by the internal tests).
55 * You can enable debugging by setting NBDKIT_GDB=1
56 *------------------------------------------------------------
59 #include <config.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <stdbool.h>
64 #include <stdarg.h>
65 #include <string.h>
66 #include <unistd.h>
67 #include <getopt.h>
68 #include <limits.h>
70 #include "options.h"
72 /* Construct an array of parameters passed through to real nbdkit. */
73 static const char **cmd;
74 static size_t len;
76 static void
77 passthru (const char *s)
79 cmd = realloc (cmd, (len+1) * sizeof (const char *));
80 if (cmd == NULL)
81 abort ();
82 cmd[len] = s;
83 ++len;
86 static void __attribute__((format (printf, 1, 2)))
87 passthru_format (const char *fs, ...)
89 va_list args;
90 char *str;
92 va_start (args, fs);
93 if (vasprintf (&str, fs, args) == -1)
94 abort ();
95 va_end (args);
96 passthru (str);
99 static void
100 end_passthru (void)
102 passthru (NULL);
105 static void
106 print_command (void)
108 size_t i;
110 if (len > 0)
111 fprintf (stderr, "%s", cmd[0]);
112 for (i = 1; i < len && cmd[i] != NULL; ++i)
113 fprintf (stderr, " %s", cmd[i]);
114 fprintf (stderr, "\n");
118 main (int argc, char *argv[])
120 bool verbose = false;
121 char *s;
123 /* If NBDKIT_VALGRIND=1 is set in the environment, then we run the
124 * program under valgrind. This is used by the tests. Similarly if
125 * NBDKIT_GDB=1 is set, we run the program under GDB, useful during
126 * development.
128 s = getenv ("NBDKIT_VALGRIND");
129 if (s && strcmp (s, "1") == 0) {
130 passthru (VALGRIND);
131 passthru ("--vgdb=no");
132 passthru ("--leak-check=full");
133 passthru ("--error-exitcode=119");
134 passthru_format ("--suppressions=%s/valgrind-suppressions", srcdir);
135 passthru ("--trace-children=no");
136 passthru ("--child-silent-after-fork=yes");
137 passthru ("--run-libc-freeres=no");
138 passthru ("--num-callers=20");
140 else {
141 s = getenv ("NBDKIT_GDB");
142 if (s && strcmp (s, "1") == 0) {
143 passthru ("gdb");
144 passthru ("--args");
148 /* Absolute path of the real nbdkit command. */
149 passthru_format ("%s/src/nbdkit", builddir);
151 /* Option parsing. We don't really parse options here. We are only
152 * interested in which options have arguments and which need
153 * rewriting.
155 for (;;) {
156 int c;
157 int long_index = -1;
158 bool is_long_option;
160 c = getopt_long (argc, argv, short_options, long_options, &long_index);
161 if (c == -1)
162 break;
164 if (c == '?') /* getopt prints an error */
165 exit (EXIT_FAILURE);
167 /* long_index is only set if it's an actual long option. */
168 is_long_option = long_index >= 0;
170 /* Verbose is special because we will print the final command. */
171 if (c == 'v') {
172 verbose = true;
173 if (is_long_option)
174 passthru ("--verbose");
175 else
176 passthru ("-v");
178 /* Filters can be rewritten if they are a short name. */
179 else if (c == FILTER_OPTION) {
180 if (is_short_name (optarg))
181 passthru_format ("--filter=%s/filters/%s/.libs/nbdkit-%s-filter.so",
182 builddir, optarg, optarg);
183 else
184 passthru_format ("--filter=%s", optarg);
186 /* Any long option. */
187 else if (is_long_option) {
188 if (optarg) /* Long option which takes an argument. */
189 passthru_format ("--%s=%s", long_options[long_index].name, optarg);
190 else /* Long option which takes no argument. */
191 passthru_format ("--%s", long_options[long_index].name);
193 /* Any short option. */
194 else {
195 passthru_format ("-%c", c);
196 if (optarg)
197 passthru (optarg);
201 /* Are there any non-option arguments? */
202 if (optind < argc) {
203 /* Ensure any further parameters can never be parsed as options by
204 * real nbdkit.
206 passthru ("--");
208 /* The first non-option argument is the plugin name. If it is a
209 * short name then rewrite it.
211 if (is_short_name (argv[optind])) {
212 /* Special plugins written in Perl. */
213 if (strcmp (argv[optind], "example4") == 0 ||
214 strcmp (argv[optind], "tar") == 0) {
215 passthru_format ("%s/plugins/perl/.libs/nbdkit-perl-plugin.so",
216 builddir);
217 passthru_format ("%s/plugins/%s/nbdkit-%s-plugin",
218 builddir, argv[optind], argv[optind]);
220 else {
221 passthru_format ("%s/plugins/%s/.libs/nbdkit-%s-plugin.so",
222 builddir, argv[optind], argv[optind]);
224 ++optind;
227 /* Everything else is passed through without rewriting. */
228 while (optind < argc) {
229 passthru (argv[optind]);
230 ++optind;
234 end_passthru ();
235 if (verbose)
236 print_command ();
238 /* Run the final command. */
239 execvp (cmd[0], (char **) cmd);
240 perror (cmd[0]);
241 exit (EXIT_FAILURE);