Supermin appliance.
[febootstrap.git] / fakechroot-2.9-cmdsubst.patch
1 Index: test/cmd-subst-pwd.sh
2 ===================================================================
3 --- test/cmd-subst-pwd.sh       (revision 0)
4 +++ test/cmd-subst-pwd.sh       (revision 0)
5 @@ -0,0 +1,3 @@
6 +#!/bin/sh
7 +
8 +echo substituted
9
10 Property changes on: test/cmd-subst-pwd.sh
11 ___________________________________________________________________
12 Added: svn:executable
13    + *
14
15 Index: test/cmd-subst.t
16 ===================================================================
17 --- test/cmd-subst.t    (revision 0)
18 +++ test/cmd-subst.t    (revision 0)
19 @@ -0,0 +1,37 @@
20 +#!/bin/sh
21 +
22 +. ./tap.sh
23 +
24 +plan 5
25 +
26 +rm -rf testtree
27 +
28 +./testtree.sh testtree
29 +test "`cat testtree/CHROOT`" = "testtree" || not
30 +ok "testtree"
31 +
32 +t=`./fakechroot.sh testtree /bin/pwd`
33 +test "$t" = "/" || not
34 +ok "fakechroot pwd is /"
35 +
36 +export FAKECHROOT_CMD_SUBST="/bin/pwd=$(pwd)/cmd-subst-pwd.sh"
37 +
38 +t=`./fakechroot.sh testtree /bin/pwd`
39 +test "$t" = "substituted" || not
40 +ok "fakechroot substituted pwd (1)"
41 +
42 +export FAKECHROOT_CMD_SUBST="/no/file=foo:/bin/pwd=$(pwd)/cmd-subst-pwd.sh"
43 +
44 +t=`./fakechroot.sh testtree /bin/pwd`
45 +test "$t" = "substituted" || not
46 +ok "fakechroot substituted pwd (2)"
47 +
48 +export FAKECHROOT_CMD_SUBST="/no/file=foo:/other/file=bar"
49 +
50 +t=`./fakechroot.sh testtree /bin/pwd`
51 +test "$t" = "/" || not
52 +ok "fakechroot not substituted pwd is /"
53 +
54 +rm -rf testtree
55 +
56 +end
57
58 Property changes on: test/cmd-subst.t
59 ___________________________________________________________________
60 Added: svn:executable
61    + *
62
63 Index: test/Makefile.am
64 ===================================================================
65 --- test/Makefile.am    (revision 323)
66 +++ test/Makefile.am    (working copy)
67 @@ -1,6 +1,6 @@
68  SUBDIRS = src
69  
70 -TESTS = chroot.t escape-nested-chroot.t pwd.t touch.t
71 +TESTS = chroot.t cmd-subst.t escape-nested-chroot.t pwd.t touch.t
72  
73  suffix =
74  
75 Index: src/libfakechroot.c
76 ===================================================================
77 --- src/libfakechroot.c (revision 323)
78 +++ src/libfakechroot.c (working copy)
79 @@ -1467,7 +1467,38 @@
80      return execve (path, argv, environ);
81  }
82  
83 +/* Parse the FAKECHROOT_CMD_SUBST environment variable (the first
84 + * parameter) and if there is a match with filename, return the
85 + * substitution in cmd_subst.  Returns non-zero if there was a match.
86 + *
87 + * FAKECHROOT_CMD_SUBST=cmd=subst:cmd=subst:...
88 + */
89 +static int
90 +try_cmd_subst (char *env, const char *filename, char *cmd_subst)
91 +{
92 +    int len = strlen (filename), len2;
93 +    char *p;
94  
95 +    if (env == NULL) return 0;
96 +
97 +    do {
98 +       p = strchrnul (env, ':');
99 +
100 +       if (strncmp (env, filename, len) == 0 && env[len] == '=') {
101 +           len2 = p - &env[len+1];
102 +           if (len2 >= FAKECHROOT_MAXPATH)
103 +               len2 = FAKECHROOT_MAXPATH - 1;
104 +           strncpy (cmd_subst, &env[len+1], len2);
105 +           cmd_subst[len2] = '\0';
106 +           return 1;
107 +       }
108 +
109 +       env = p;
110 +    } while (*env++ != '\0');
111 +
112 +    return 0;
113 +}
114 +
115  /* #include <unistd.h> */
116  int execve (const char *filename, char *const argv [], char *const envp[])
117  {
118 @@ -1479,32 +1510,16 @@
119      char *env;
120      char tmp[FAKECHROOT_MAXPATH], newfilename[FAKECHROOT_MAXPATH], argv0[FAKECHROOT_MAXPATH];
121      char *ptr;
122 -    unsigned int i, j, n, len;
123 +    unsigned int i, j, n, len, r, newenvppos;
124      size_t sizeenvp;
125      char c;
126      char *fakechroot_path, *fakechroot_ptr, fakechroot_buf[FAKECHROOT_MAXPATH];
127      char *envkey[] = { "FAKECHROOT", "FAKECHROOT_BASE",
128                         "FAKECHROOT_VERSION", "FAKECHROOT_EXCLUDE_PATH",
129 +                       "FAKECHROOT_CMD_SUBST",
130                         "LD_LIBRARY_PATH", "LD_PRELOAD" };
131 +    const int nr_envkey = sizeof envkey / sizeof envkey[0];
132  
133 -    strncpy(argv0, filename, FAKECHROOT_MAXPATH);
134 -
135 -    expand_chroot_path(filename, fakechroot_path, fakechroot_ptr, fakechroot_buf);
136 -    strcpy(tmp, filename);
137 -    filename = tmp;
138 -
139 -    if ((file = open(filename, O_RDONLY)) == -1) {
140 -        errno = ENOENT;
141 -        return -1;
142 -    }
143 -
144 -    i = read(file, hashbang, FAKECHROOT_MAXPATH-2);
145 -    close(file);
146 -    if (i == -1) {
147 -        errno = ENOENT;
148 -        return -1;
149 -    }
150 -
151      if (next_execve == NULL) fakechroot_init();
152  
153      /* Scan envp and check its size */
154 @@ -1514,39 +1529,69 @@
155      }
156  
157      /* Copy envp to newenvp */
158 -    newenvp = malloc( sizeenvp * sizeof (char *) + sizeof(envkey) );
159 +    newenvp = malloc( (sizeenvp + 1) * sizeof (char *) );
160      if (newenvp == NULL) {
161          errno = ENOMEM;
162          return -1;
163      }
164 -    for (ep = envp, i = 0; *ep != NULL; ++ep) {
165 -        for (j = 0; j < sizeof (envkey) / sizeof (char *); j++) {
166 +    for (ep = envp, newenvppos = 0; *ep != NULL; ++ep) {
167 +        for (j = 0; j < nr_envkey; j++) {
168              len = strlen (envkey[j]);
169              if (strncmp (*ep, envkey[j], len) == 0 && (*ep)[len] == '=')
170                  goto skip;
171          }
172 -        newenvp[i] = *ep;
173 -        i++;
174 +        newenvp[newenvppos] = *ep;
175 +        newenvppos++;
176      skip: ;
177      }
178 +    newenvp[newenvppos] = NULL;
179  
180 +    strncpy(argv0, filename, FAKECHROOT_MAXPATH);
181 +
182 +    r = try_cmd_subst (getenv ("FAKECHROOT_CMD_SUBST"), filename, tmp);
183 +    if (r) {
184 +        filename = tmp;
185 +
186 +        /* FAKECHROOT_CMD_SUBST escapes the chroot.  newenvp here does
187 +         * not contain LD_PRELOAD and the other special environment
188 +         * variables.
189 +         */
190 +        return next_execve(filename, argv, newenvp);
191 +    }
192 +
193 +    expand_chroot_path(filename, fakechroot_path, fakechroot_ptr, fakechroot_buf);
194 +    strcpy(tmp, filename);
195 +    filename = tmp;
196 +
197 +    if ((file = open(filename, O_RDONLY)) == -1) {
198 +        errno = ENOENT;
199 +        return -1;
200 +    }
201 +
202 +    i = read(file, hashbang, FAKECHROOT_MAXPATH-2);
203 +    close(file);
204 +    if (i == -1) {
205 +        errno = ENOENT;
206 +        return -1;
207 +    }
208 +
209      /* Add our variables to newenvp */
210 -    newenvp = realloc( newenvp, i * sizeof(char *) + sizeof(envkey) );
211 +    newenvp = realloc( newenvp, (newenvppos + nr_envkey + 1) * sizeof(char *) );
212      if (newenvp == NULL) {
213          errno = ENOMEM;
214          return -1;
215      }
216 -    for (j = 0; j < sizeof(envkey) / sizeof(char *); j++) {
217 +    for (j = 0; j < nr_envkey; j++) {
218          env = getenv(envkey[j]);
219          if (env != NULL) {
220 -            newenvp[i] = malloc(strlen(envkey[j]) + strlen(env) + 3);
221 -            strcpy(newenvp[i], envkey[j]);
222 -            strcat(newenvp[i], "=");
223 -            strcat(newenvp[i], env);
224 -            i++;
225 +            newenvp[newenvppos] = malloc(strlen(envkey[j]) + strlen(env) + 3);
226 +            strcpy(newenvp[newenvppos], envkey[j]);
227 +            strcat(newenvp[newenvppos], "=");
228 +            strcat(newenvp[newenvppos], env);
229 +            newenvppos++;
230          }
231      }
232 -    newenvp[i] = NULL;
233 +    newenvp[newenvppos] = NULL;
234  
235      /* No hashbang in argv */
236      if (hashbang[0] != '#' || hashbang[1] != '!')
237 Index: man/fakechroot.pod
238 ===================================================================
239 --- man/fakechroot.pod  (revision 323)
240 +++ man/fakechroot.pod  (working copy)
241 @@ -139,6 +139,21 @@
242  The list of directories which are excluded from being chrooted.  The elements
243  of list are separated with colon.
244  
245 +=item B<FAKECHROOT_CMD_SUBST>
246 +
247 +A list of command substitutions.  If a program tries to execute one of
248 +the commands given (path relative to the chroot) then the substitute
249 +command runs instead (path to substitute command is not chrooted).
250 +
251 +For example:
252 +
253 + FAKECHROOT_CMD_SUBST=/sbin/ldconfig=/tmp/ldconfig-wrapper
254 +
255 +will substitute C</tmp/ldconfig-wrapper> for C</sbin/ldconfig>.
256 +
257 +Give as many substitute commands as you want, separated by C<:>
258 +(colon) characters.
259 +
260  =item B<LD_LIBRARY_PATH>, B<LD_PRELOAD>
261  
262  Fakechroot is implemented by wrapping system calls.  This is accomplished by