XBPS Library API  0.19
The X Binary Package System
fexec.c
1 /*-
2  * Copyright (c) 2003 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Matthias Scheler.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #define _BSD_SOURCE /* for vfork and chroot */
31 #include <sys/types.h>
32 #include <sys/wait.h>
33 #include <errno.h>
34 #include <stdarg.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 
39 #include "xbps_api_impl.h"
40 
41 static int
42 pfcexec(struct xbps_handle *xhp, const char *file, const char **argv)
43 {
44  pid_t child;
45  int status;
46 
47  child = vfork();
48  switch (child) {
49  case 0:
50  /*
51  * If rootdir != / and uid==0 and bin/sh exists,
52  * change root directory and exec command.
53  */
54  if (strcmp(xhp->rootdir, "/")) {
55  if (geteuid() == 0 && access("bin/sh", X_OK) == 0) {
56  if (chroot(xhp->rootdir) == 0) {
57  if (chdir("/") == -1)
58  _exit(129);
59  }
60  }
61  }
62  (void)execv(file, __UNCONST(argv));
63  _exit(127);
64  /* NOTREACHED */
65  case -1:
66  return -1;
67  }
68 
69  while (waitpid(child, &status, 0) < 0) {
70  if (errno != EINTR)
71  return -1;
72  }
73 
74  if (!WIFEXITED(status))
75  return -1;
76 
77  return WEXITSTATUS(status);
78 }
79 
80 static int
81 vfcexec(struct xbps_handle *xhp, const char *arg, va_list ap)
82 {
83  const char **argv;
84  size_t argv_size, argc;
85  int retval;
86 
87  argv_size = 16;
88  if ((argv = malloc(argv_size * sizeof(*argv))) == NULL) {
89  errno = ENOMEM;
90  return -1;
91  }
92 
93  argv[0] = arg;
94  argc = 1;
95 
96  do {
97  if (argc == argv_size) {
98  argv_size *= 2;
99  argv = realloc(argv, argv_size * sizeof(*argv));
100  if (argv == NULL) {
101  errno = ENOMEM;
102  return -1;
103  }
104  }
105 
106  arg = va_arg(ap, const char *);
107  argv[argc++] = arg;
108 
109  } while (arg != NULL);
110 
111  retval = pfcexec(xhp, argv[0], argv);
112  free(argv);
113 
114  return retval;
115 }
116 
117 int HIDDEN
118 xbps_file_exec(struct xbps_handle *xhp, const char *arg, ...)
119 {
120  va_list ap;
121  int result;
122 
123  va_start(ap, arg);
124  result = vfcexec(xhp, arg, ap);
125  va_end(ap);
126 
127  return result;
128 }