1*0a6a1f1dSLionel Sambuc /* $NetBSD: flock.c,v 1.11 2014/08/18 09:16:35 christos Exp $ */
29488aa4cSDavid van Moolenbroek
39488aa4cSDavid van Moolenbroek /*-
49488aa4cSDavid van Moolenbroek * Copyright (c) 2012 The NetBSD Foundation, Inc.
59488aa4cSDavid van Moolenbroek * All rights reserved.
69488aa4cSDavid van Moolenbroek *
79488aa4cSDavid van Moolenbroek * This code is derived from software contributed to The NetBSD Foundation
89488aa4cSDavid van Moolenbroek * by Christos Zoulas.
99488aa4cSDavid van Moolenbroek *
109488aa4cSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
119488aa4cSDavid van Moolenbroek * modification, are permitted provided that the following conditions
129488aa4cSDavid van Moolenbroek * are met:
139488aa4cSDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
149488aa4cSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
159488aa4cSDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
169488aa4cSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
179488aa4cSDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
189488aa4cSDavid van Moolenbroek * from this software without specific prior written permission.
199488aa4cSDavid van Moolenbroek *
209488aa4cSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
219488aa4cSDavid van Moolenbroek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
229488aa4cSDavid van Moolenbroek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
239488aa4cSDavid van Moolenbroek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
249488aa4cSDavid van Moolenbroek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
259488aa4cSDavid van Moolenbroek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
269488aa4cSDavid van Moolenbroek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
279488aa4cSDavid van Moolenbroek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
289488aa4cSDavid van Moolenbroek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
299488aa4cSDavid van Moolenbroek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
309488aa4cSDavid van Moolenbroek * POSSIBILITY OF SUCH DAMAGE.
319488aa4cSDavid van Moolenbroek */
329488aa4cSDavid van Moolenbroek
339488aa4cSDavid van Moolenbroek #include <sys/cdefs.h>
34*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: flock.c,v 1.11 2014/08/18 09:16:35 christos Exp $");
359488aa4cSDavid van Moolenbroek
369488aa4cSDavid van Moolenbroek #include <stdio.h>
379488aa4cSDavid van Moolenbroek #include <string.h>
389488aa4cSDavid van Moolenbroek #include <fcntl.h>
399488aa4cSDavid van Moolenbroek #include <stdlib.h>
409488aa4cSDavid van Moolenbroek #include <signal.h>
419488aa4cSDavid van Moolenbroek #include <unistd.h>
429488aa4cSDavid van Moolenbroek #include <err.h>
439488aa4cSDavid van Moolenbroek #include <errno.h>
449488aa4cSDavid van Moolenbroek #include <getopt.h>
459488aa4cSDavid van Moolenbroek #include <paths.h>
46*0a6a1f1dSLionel Sambuc #include <limits.h>
479488aa4cSDavid van Moolenbroek #include <time.h>
489488aa4cSDavid van Moolenbroek
499488aa4cSDavid van Moolenbroek static struct option flock_longopts[] = {
509488aa4cSDavid van Moolenbroek { "debug", no_argument, 0, 'd' },
519488aa4cSDavid van Moolenbroek { "help", no_argument, 0, 'h' },
529488aa4cSDavid van Moolenbroek { "nonblock", no_argument, 0, 'n' },
539488aa4cSDavid van Moolenbroek { "nb", no_argument, 0, 'n' },
549488aa4cSDavid van Moolenbroek { "close", no_argument, 0, 'o' },
559488aa4cSDavid van Moolenbroek { "shared", no_argument, 0, 's' },
569488aa4cSDavid van Moolenbroek { "exclusive", no_argument, 0, 'x' },
579488aa4cSDavid van Moolenbroek { "unlock", no_argument, 0, 'u' },
589488aa4cSDavid van Moolenbroek { "verbose", no_argument, 0, 'v' },
599488aa4cSDavid van Moolenbroek { "command", required_argument, 0, 'c' },
609488aa4cSDavid van Moolenbroek { "wait", required_argument, 0, 'w' },
619488aa4cSDavid van Moolenbroek { "timeout", required_argument, 0, 'w' },
629488aa4cSDavid van Moolenbroek { NULL, 0, 0, 0 },
639488aa4cSDavid van Moolenbroek };
649488aa4cSDavid van Moolenbroek
659488aa4cSDavid van Moolenbroek static sig_atomic_t timeout_expired;
669488aa4cSDavid van Moolenbroek
67*0a6a1f1dSLionel Sambuc static __dead __printflike(1, 2) void
usage(const char * fmt,...)689488aa4cSDavid van Moolenbroek usage(const char *fmt, ...)
699488aa4cSDavid van Moolenbroek {
709488aa4cSDavid van Moolenbroek if (fmt) {
719488aa4cSDavid van Moolenbroek va_list ap;
729488aa4cSDavid van Moolenbroek va_start(ap, fmt);
739488aa4cSDavid van Moolenbroek fprintf(stderr, "%s: ", getprogname());
749488aa4cSDavid van Moolenbroek vfprintf(stderr, fmt, ap);
759488aa4cSDavid van Moolenbroek fputc('\n', stderr);
769488aa4cSDavid van Moolenbroek va_end(ap);
779488aa4cSDavid van Moolenbroek }
789488aa4cSDavid van Moolenbroek
799488aa4cSDavid van Moolenbroek fprintf(stderr, "Usage: %s [-dnosvx] [-w timeout] lockfile|lockdir "
809488aa4cSDavid van Moolenbroek "[-c command]|command ...\n\t%s [-dnsuvx] [-w timeout] lockfd\n",
819488aa4cSDavid van Moolenbroek getprogname(), getprogname());
829488aa4cSDavid van Moolenbroek exit(EXIT_FAILURE);
839488aa4cSDavid van Moolenbroek }
849488aa4cSDavid van Moolenbroek
859488aa4cSDavid van Moolenbroek static void
sigalrm(int sig)869488aa4cSDavid van Moolenbroek sigalrm(int sig)
879488aa4cSDavid van Moolenbroek {
889488aa4cSDavid van Moolenbroek timeout_expired++;
899488aa4cSDavid van Moolenbroek }
909488aa4cSDavid van Moolenbroek
919488aa4cSDavid van Moolenbroek static const char *
lock2name(int l)929488aa4cSDavid van Moolenbroek lock2name(int l)
939488aa4cSDavid van Moolenbroek {
949488aa4cSDavid van Moolenbroek static char buf[1024];
959488aa4cSDavid van Moolenbroek int nb = l & LOCK_NB;
969488aa4cSDavid van Moolenbroek
979488aa4cSDavid van Moolenbroek l &= ~LOCK_NB;
989488aa4cSDavid van Moolenbroek if (nb)
999488aa4cSDavid van Moolenbroek strlcpy(buf, "LOCK_NB|", sizeof(buf));
1009488aa4cSDavid van Moolenbroek else
1019488aa4cSDavid van Moolenbroek buf[0] = '\0';
1029488aa4cSDavid van Moolenbroek
1039488aa4cSDavid van Moolenbroek switch (l) {
1049488aa4cSDavid van Moolenbroek case LOCK_SH:
1059488aa4cSDavid van Moolenbroek strlcat(buf, "LOCK_SH", sizeof(buf));
1069488aa4cSDavid van Moolenbroek return buf;
1079488aa4cSDavid van Moolenbroek case LOCK_EX:
1089488aa4cSDavid van Moolenbroek strlcat(buf, "LOCK_EX", sizeof(buf));
1099488aa4cSDavid van Moolenbroek return buf;
1109488aa4cSDavid van Moolenbroek case LOCK_UN:
1119488aa4cSDavid van Moolenbroek strlcat(buf, "LOCK_UN", sizeof(buf));
1129488aa4cSDavid van Moolenbroek return buf;
1139488aa4cSDavid van Moolenbroek default:
1149488aa4cSDavid van Moolenbroek snprintf(buf, sizeof(buf), "*%d*", l | nb);
1159488aa4cSDavid van Moolenbroek return buf;
1169488aa4cSDavid van Moolenbroek }
1179488aa4cSDavid van Moolenbroek }
1189488aa4cSDavid van Moolenbroek
1199488aa4cSDavid van Moolenbroek static char
lockchar(int l)1209488aa4cSDavid van Moolenbroek lockchar(int l)
1219488aa4cSDavid van Moolenbroek {
1229488aa4cSDavid van Moolenbroek switch (l & ~LOCK_NB) {
1239488aa4cSDavid van Moolenbroek case LOCK_SH:
1249488aa4cSDavid van Moolenbroek return 's';
1259488aa4cSDavid van Moolenbroek case LOCK_EX:
1269488aa4cSDavid van Moolenbroek return 'x';
1279488aa4cSDavid van Moolenbroek case LOCK_UN:
1289488aa4cSDavid van Moolenbroek return 'u';
1299488aa4cSDavid van Moolenbroek default:
1309488aa4cSDavid van Moolenbroek return '*';
1319488aa4cSDavid van Moolenbroek }
1329488aa4cSDavid van Moolenbroek }
1339488aa4cSDavid van Moolenbroek
1349488aa4cSDavid van Moolenbroek static char *
cmdline(char ** av)1359488aa4cSDavid van Moolenbroek cmdline(char **av)
1369488aa4cSDavid van Moolenbroek {
1379488aa4cSDavid van Moolenbroek char *v = NULL;
1389488aa4cSDavid van Moolenbroek while (*av)
1399488aa4cSDavid van Moolenbroek if (v) {
1409488aa4cSDavid van Moolenbroek if (asprintf(&v, "%s %s", v, *av++) < 0)
1419488aa4cSDavid van Moolenbroek err(EXIT_FAILURE, "malloc");
1429488aa4cSDavid van Moolenbroek } else {
1439488aa4cSDavid van Moolenbroek if ((v = strdup(*av++)) == NULL)
1449488aa4cSDavid van Moolenbroek err(EXIT_FAILURE, "strdup");
1459488aa4cSDavid van Moolenbroek }
1469488aa4cSDavid van Moolenbroek return v;
1479488aa4cSDavid van Moolenbroek }
1489488aa4cSDavid van Moolenbroek
1499488aa4cSDavid van Moolenbroek int
main(int argc,char * argv[])1509488aa4cSDavid van Moolenbroek main(int argc, char *argv[])
1519488aa4cSDavid van Moolenbroek {
1529488aa4cSDavid van Moolenbroek int c;
1539488aa4cSDavid van Moolenbroek int lock = 0;
1549488aa4cSDavid van Moolenbroek double timeout = 0;
1559488aa4cSDavid van Moolenbroek int cls = 0;
1569488aa4cSDavid van Moolenbroek int fd = -1;
1579488aa4cSDavid van Moolenbroek int debug = 0;
1589488aa4cSDavid van Moolenbroek int verbose = 0;
159*0a6a1f1dSLionel Sambuc long l;
1609488aa4cSDavid van Moolenbroek char *mcargv[] = {
1619488aa4cSDavid van Moolenbroek __UNCONST(_PATH_BSHELL), __UNCONST("-c"), NULL, NULL
1629488aa4cSDavid van Moolenbroek };
1639488aa4cSDavid van Moolenbroek char **cmdargv = NULL, *v;
164*0a6a1f1dSLionel Sambuc #if !defined(__minix)
1659488aa4cSDavid van Moolenbroek timer_t tm;
166*0a6a1f1dSLionel Sambuc #else
1679488aa4cSDavid van Moolenbroek struct itimerval it;
168*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
1699488aa4cSDavid van Moolenbroek
1709488aa4cSDavid van Moolenbroek setprogname(argv[0]);
1719488aa4cSDavid van Moolenbroek
1729488aa4cSDavid van Moolenbroek while ((c = getopt_long(argc, argv, "+dnosuvw:x", flock_longopts, NULL))
1739488aa4cSDavid van Moolenbroek != -1)
1749488aa4cSDavid van Moolenbroek switch (c) {
1759488aa4cSDavid van Moolenbroek case 'd':
1769488aa4cSDavid van Moolenbroek debug++;
1779488aa4cSDavid van Moolenbroek break;
1789488aa4cSDavid van Moolenbroek case 'x':
1799488aa4cSDavid van Moolenbroek #define T(l) (lock & ~LOCK_NB) != (l) && (lock & ~LOCK_NB) != 0
1809488aa4cSDavid van Moolenbroek if (T(LOCK_EX))
1819488aa4cSDavid van Moolenbroek goto badlock;
1829488aa4cSDavid van Moolenbroek lock |= LOCK_EX;
1839488aa4cSDavid van Moolenbroek break;
1849488aa4cSDavid van Moolenbroek case 'n':
1859488aa4cSDavid van Moolenbroek lock |= LOCK_NB;
1869488aa4cSDavid van Moolenbroek break;
1879488aa4cSDavid van Moolenbroek case 's':
1889488aa4cSDavid van Moolenbroek if (T(LOCK_SH))
1899488aa4cSDavid van Moolenbroek goto badlock;
1909488aa4cSDavid van Moolenbroek lock |= LOCK_SH;
1919488aa4cSDavid van Moolenbroek break;
1929488aa4cSDavid van Moolenbroek case 'u':
1939488aa4cSDavid van Moolenbroek if (T(LOCK_UN))
1949488aa4cSDavid van Moolenbroek goto badlock;
1959488aa4cSDavid van Moolenbroek lock |= LOCK_UN;
1969488aa4cSDavid van Moolenbroek break;
1979488aa4cSDavid van Moolenbroek case 'w':
1989488aa4cSDavid van Moolenbroek timeout = strtod(optarg, NULL);
1999488aa4cSDavid van Moolenbroek break;
2009488aa4cSDavid van Moolenbroek case 'v':
2019488aa4cSDavid van Moolenbroek verbose = 1;
2029488aa4cSDavid van Moolenbroek break;
2039488aa4cSDavid van Moolenbroek case 'o':
2049488aa4cSDavid van Moolenbroek cls = 1;
2059488aa4cSDavid van Moolenbroek break;
2069488aa4cSDavid van Moolenbroek default:
2079488aa4cSDavid van Moolenbroek usage("Invalid option '%c'", c);
2089488aa4cSDavid van Moolenbroek badlock:
2099488aa4cSDavid van Moolenbroek usage("-%c can't be used with -%c", c, lockchar(lock));
2109488aa4cSDavid van Moolenbroek }
2119488aa4cSDavid van Moolenbroek
2129488aa4cSDavid van Moolenbroek argc -= optind;
2139488aa4cSDavid van Moolenbroek argv += optind;
2149488aa4cSDavid van Moolenbroek
2159488aa4cSDavid van Moolenbroek if ((lock & ~LOCK_NB) == 0)
216*0a6a1f1dSLionel Sambuc lock |= LOCK_EX; /* default to exclusive like linux */
2179488aa4cSDavid van Moolenbroek
2189488aa4cSDavid van Moolenbroek switch (argc) {
2199488aa4cSDavid van Moolenbroek case 0:
2209488aa4cSDavid van Moolenbroek usage("Missing lock file argument");
2219488aa4cSDavid van Moolenbroek case 1:
2229488aa4cSDavid van Moolenbroek if (cls)
223*0a6a1f1dSLionel Sambuc usage("Close is not valid for descriptors");
224*0a6a1f1dSLionel Sambuc errno = 0;
225*0a6a1f1dSLionel Sambuc l = strtol(argv[0], &v, 0);
226*0a6a1f1dSLionel Sambuc if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE)
227*0a6a1f1dSLionel Sambuc err(EXIT_FAILURE, "Bad file descriptor `%s'", argv[0]);
228*0a6a1f1dSLionel Sambuc if (l > INT_MAX || l < 0 || *v)
229*0a6a1f1dSLionel Sambuc errx(EXIT_FAILURE, "Bad file descriptor `%s'", argv[0]);
230*0a6a1f1dSLionel Sambuc fd = (int)l;
2319488aa4cSDavid van Moolenbroek if (debug) {
2329488aa4cSDavid van Moolenbroek fprintf(stderr, "descriptor %s lock %s\n",
2339488aa4cSDavid van Moolenbroek argv[0], lock2name(lock));
2349488aa4cSDavid van Moolenbroek }
2359488aa4cSDavid van Moolenbroek break;
2369488aa4cSDavid van Moolenbroek
2379488aa4cSDavid van Moolenbroek default:
2389488aa4cSDavid van Moolenbroek if ((lock & LOCK_NB) == LOCK_UN)
2399488aa4cSDavid van Moolenbroek usage("Unlock is only valid for descriptors");
2409488aa4cSDavid van Moolenbroek if (strcmp(argv[1], "-c") == 0 ||
2419488aa4cSDavid van Moolenbroek strcmp(argv[1], "--command") == 0) {
2429488aa4cSDavid van Moolenbroek if (argc == 2)
2439488aa4cSDavid van Moolenbroek usage("Missing argument to %s", strcmp(argv[1],
2449488aa4cSDavid van Moolenbroek "-c") == 0 ? "-c" : "--command");
2459488aa4cSDavid van Moolenbroek mcargv[2] = argv[2];
2469488aa4cSDavid van Moolenbroek cmdargv = mcargv;
2479488aa4cSDavid van Moolenbroek } else
2489488aa4cSDavid van Moolenbroek cmdargv = argv + 1;
2499488aa4cSDavid van Moolenbroek
2509488aa4cSDavid van Moolenbroek if ((fd = open(argv[0], O_RDONLY)) == -1) {
2519488aa4cSDavid van Moolenbroek if (errno != ENOENT ||
2529488aa4cSDavid van Moolenbroek (fd = open(argv[0], O_RDWR|O_CREAT, 0600)) == -1)
2539488aa4cSDavid van Moolenbroek err(EXIT_FAILURE, "Cannot open `%s'", argv[0]);
2549488aa4cSDavid van Moolenbroek }
2559488aa4cSDavid van Moolenbroek if (debug) {
2569488aa4cSDavid van Moolenbroek fprintf(stderr, "file %s lock %s command %s ...\n",
2579488aa4cSDavid van Moolenbroek argv[0], lock2name(lock), v = cmdline(cmdargv));
2589488aa4cSDavid van Moolenbroek free(v);
2599488aa4cSDavid van Moolenbroek }
2609488aa4cSDavid van Moolenbroek break;
2619488aa4cSDavid van Moolenbroek }
2629488aa4cSDavid van Moolenbroek
2639488aa4cSDavid van Moolenbroek if (timeout) {
264*0a6a1f1dSLionel Sambuc #if !defined(__minix)
2659488aa4cSDavid van Moolenbroek struct sigevent ev;
2669488aa4cSDavid van Moolenbroek struct itimerspec it;
267*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
2689488aa4cSDavid van Moolenbroek struct sigaction sa;
2699488aa4cSDavid van Moolenbroek
270*0a6a1f1dSLionel Sambuc #if !defined(__minix)
2719488aa4cSDavid van Moolenbroek timespecclear(&it.it_interval);
2729488aa4cSDavid van Moolenbroek it.it_value.tv_sec = timeout;
2739488aa4cSDavid van Moolenbroek it.it_value.tv_nsec = (timeout - it.it_value.tv_sec) *
2749488aa4cSDavid van Moolenbroek 1000000000;
2759488aa4cSDavid van Moolenbroek
2769488aa4cSDavid van Moolenbroek memset(&ev, 0, sizeof(ev));
2779488aa4cSDavid van Moolenbroek ev.sigev_notify = SIGEV_SIGNAL;
2789488aa4cSDavid van Moolenbroek ev.sigev_signo = SIGALRM;
2799488aa4cSDavid van Moolenbroek
2809488aa4cSDavid van Moolenbroek if (timer_create(CLOCK_REALTIME, &ev, &tm) == -1)
2819488aa4cSDavid van Moolenbroek err(EXIT_FAILURE, "timer_create");
2829488aa4cSDavid van Moolenbroek
2839488aa4cSDavid van Moolenbroek if (timer_settime(tm, TIMER_RELTIME, &it, NULL) == -1)
2849488aa4cSDavid van Moolenbroek err(EXIT_FAILURE, "timer_settime");
285*0a6a1f1dSLionel Sambuc #else
2869488aa4cSDavid van Moolenbroek memset(&it.it_interval, 0, sizeof(it.it_interval));
2879488aa4cSDavid van Moolenbroek it.it_value.tv_sec = timeout;
2889488aa4cSDavid van Moolenbroek it.it_value.tv_usec = (timeout - it.it_value.tv_sec) * 1000000;
2899488aa4cSDavid van Moolenbroek
2909488aa4cSDavid van Moolenbroek if (setitimer(ITIMER_REAL, &it, NULL) == -1)
2919488aa4cSDavid van Moolenbroek err(EXIT_FAILURE, "setitimer");
2929488aa4cSDavid van Moolenbroek
2939488aa4cSDavid van Moolenbroek memset(&it, 0, sizeof(it)); /* for the reset later */
294*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
2959488aa4cSDavid van Moolenbroek
2969488aa4cSDavid van Moolenbroek memset(&sa, 0, sizeof(sa));
2979488aa4cSDavid van Moolenbroek sa.sa_handler = sigalrm;
2989488aa4cSDavid van Moolenbroek sigemptyset(&sa.sa_mask);
2999488aa4cSDavid van Moolenbroek sa.sa_flags = 0;
3009488aa4cSDavid van Moolenbroek if (sigaction(SIGALRM, &sa, NULL) == -1)
3019488aa4cSDavid van Moolenbroek err(EXIT_FAILURE, "sigaction");
3029488aa4cSDavid van Moolenbroek
3039488aa4cSDavid van Moolenbroek if (debug)
3049488aa4cSDavid van Moolenbroek fprintf(stderr, "alarm %g\n", timeout);
3059488aa4cSDavid van Moolenbroek }
3069488aa4cSDavid van Moolenbroek
3079488aa4cSDavid van Moolenbroek while (flock(fd, lock) == -1) {
3089488aa4cSDavid van Moolenbroek if (errno == EINTR && timeout_expired == 0)
3099488aa4cSDavid van Moolenbroek continue;
3109488aa4cSDavid van Moolenbroek if (verbose)
3119488aa4cSDavid van Moolenbroek err(EXIT_FAILURE, "flock(%d, %s)", fd, lock2name(lock));
3129488aa4cSDavid van Moolenbroek else
3139488aa4cSDavid van Moolenbroek return EXIT_FAILURE;
3149488aa4cSDavid van Moolenbroek }
3159488aa4cSDavid van Moolenbroek
3169488aa4cSDavid van Moolenbroek if (timeout)
317*0a6a1f1dSLionel Sambuc #if !defined(__minix)
3189488aa4cSDavid van Moolenbroek timer_delete(tm);
319*0a6a1f1dSLionel Sambuc #else
3209488aa4cSDavid van Moolenbroek setitimer(ITIMER_REAL, &it, NULL);
321*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
3229488aa4cSDavid van Moolenbroek
3239488aa4cSDavid van Moolenbroek if (cls)
3249488aa4cSDavid van Moolenbroek (void)close(fd);
3259488aa4cSDavid van Moolenbroek
3269488aa4cSDavid van Moolenbroek if (cmdargv != NULL) {
3279488aa4cSDavid van Moolenbroek execvp(cmdargv[0], cmdargv);
3289488aa4cSDavid van Moolenbroek err(EXIT_FAILURE, "execvp '%s'", v = cmdline(cmdargv));
3299488aa4cSDavid van Moolenbroek free(v);
3309488aa4cSDavid van Moolenbroek }
3319488aa4cSDavid van Moolenbroek return 0;
3329488aa4cSDavid van Moolenbroek }
333