xref: /minix/external/bsd/pkg_install/dist/lib/fexec.c (revision 0a6a1f1d)
1 /*	$NetBSD: fexec.c,v 1.1.1.3 2009/08/06 16:55:26 joerg Exp $	*/
2 
3 /*-
4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Matthias Scheler.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 
33 #if HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 #include <nbcompat.h>
37 #if HAVE_SYS_CDEFS_H
38 #include <sys/cdefs.h>
39 #endif
40 #if HAVE_SYS_WAIT_H
41 #include <sys/wait.h>
42 #endif
43 
44 #if HAVE_ERR_H
45 #include <err.h>
46 #endif
47 #if HAVE_ERRNO_H
48 #include <errno.h>
49 #endif
50 #if HAVE_STDARG_H
51 #include <stdarg.h>
52 #endif
53 #if HAVE_STDLIB_H
54 #include <stdlib.h>
55 #endif
56 #if HAVE_UNISTD_H
57 #include <unistd.h>
58 #endif
59 
60 #include "lib.h"
61 
62 __RCSID("$NetBSD: fexec.c,v 1.1.1.3 2009/08/06 16:55:26 joerg Exp $");
63 
64 static int	vfcexec(const char *, int, const char *, va_list);
65 
66 /*
67  * fork, then change current working directory to path and
68  * execute the command and arguments in the argv array.
69  * wait for the command to finish, then return the exit status.
70  */
71 int
72 pfcexec(const char *path, const char *file, const char **argv)
73 {
74 	pid_t			child;
75 	int			status;
76 
77 	child = vfork();
78 	switch (child) {
79 	case 0:
80 		if ((path != NULL) && (chdir(path) < 0))
81 			_exit(127);
82 
83 		(void)execvp(file, __UNCONST(argv));
84 		_exit(127);
85 		/* NOTREACHED */
86 	case -1:
87 		return -1;
88 	}
89 
90 	while (waitpid(child, &status, 0) < 0) {
91 		if (errno != EINTR)
92 			return -1;
93 	}
94 
95 	if (!WIFEXITED(status))
96 		return -1;
97 
98 	return WEXITSTATUS(status);
99 }
100 
101 static int
102 vfcexec(const char *path, int skipempty, const char *arg, va_list ap)
103 {
104 	const char **argv;
105 	size_t argv_size, argc;
106 	int retval;
107 
108 	argv_size = 16;
109 	argv = xcalloc(argv_size, sizeof(*argv));
110 
111 	argv[0] = arg;
112 	argc = 1;
113 
114 	do {
115 		if (argc == argv_size) {
116 			argv_size *= 2;
117 			argv = xrealloc(argv, argv_size * sizeof(*argv));
118 		}
119 		arg = va_arg(ap, const char *);
120 		if (skipempty && arg && strlen(arg) == 0)
121 		    continue;
122 		argv[argc++] = arg;
123 	} while (arg != NULL);
124 
125 	retval = pfcexec(path, argv[0], argv);
126 	free(argv);
127 	return retval;
128 }
129 
130 int
131 fexec(const char *arg, ...)
132 {
133 	va_list	ap;
134 	int	result;
135 
136 	va_start(ap, arg);
137 	result = vfcexec(NULL, 0, arg, ap);
138 	va_end(ap);
139 
140 	return result;
141 }
142 
143 int
144 fexec_skipempty(const char *arg, ...)
145 {
146 	va_list	ap;
147 	int	result;
148 
149 	va_start(ap, arg);
150 	result = vfcexec(NULL, 1, arg, ap);
151 	va_end(ap);
152 
153 	return result;
154 }
155 
156 int
157 fcexec(const char *path, const char *arg, ...)
158 {
159 	va_list	ap;
160 	int	result;
161 
162 	va_start(ap, arg);
163 	result = vfcexec(path, 0, arg, ap);
164 	va_end(ap);
165 
166 	return result;
167 }
168