1 Index: test/cmd-subst-pwd.sh
2 ===================================================================
3 --- test/cmd-subst-pwd.sh (revision 0)
4 +++ test/cmd-subst-pwd.sh (revision 0)
10 Property changes on: test/cmd-subst-pwd.sh
11 ___________________________________________________________________
15 Index: test/cmd-subst.t
16 ===================================================================
17 --- test/cmd-subst.t (revision 0)
18 +++ test/cmd-subst.t (revision 0)
28 +./testtree.sh testtree
29 +test "`cat testtree/CHROOT`" = "testtree" || not
32 +t=`./fakechroot.sh testtree /bin/pwd`
33 +test "$t" = "/" || not
34 +ok "fakechroot pwd is /"
36 +export FAKECHROOT_CMD_SUBST="/bin/pwd=$(pwd)/cmd-subst-pwd.sh"
38 +t=`./fakechroot.sh testtree /bin/pwd`
39 +test "$t" = "substituted" || not
40 +ok "fakechroot substituted pwd (1)"
42 +export FAKECHROOT_CMD_SUBST="/no/file=foo:/bin/pwd=$(pwd)/cmd-subst-pwd.sh"
44 +t=`./fakechroot.sh testtree /bin/pwd`
45 +test "$t" = "substituted" || not
46 +ok "fakechroot substituted pwd (2)"
48 +export FAKECHROOT_CMD_SUBST="/no/file=foo:/other/file=bar"
50 +t=`./fakechroot.sh testtree /bin/pwd`
51 +test "$t" = "/" || not
52 +ok "fakechroot not substituted pwd is /"
58 Property changes on: test/cmd-subst.t
59 ___________________________________________________________________
63 Index: test/Makefile.am
64 ===================================================================
65 --- test/Makefile.am (revision 323)
66 +++ test/Makefile.am (working copy)
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
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);
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.
87 + * FAKECHROOT_CMD_SUBST=cmd=subst:cmd=subst:...
90 +try_cmd_subst (char *env, const char *filename, char *cmd_subst)
92 + int len = strlen (filename), len2;
95 + if (env == NULL) return 0;
98 + p = strchrnul (env, ':');
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';
110 + } while (*env++ != '\0');
115 /* #include <unistd.h> */
116 int execve (const char *filename, char *const argv [], char *const envp[])
118 @@ -1479,32 +1510,16 @@
120 char tmp[FAKECHROOT_MAXPATH], newfilename[FAKECHROOT_MAXPATH], argv0[FAKECHROOT_MAXPATH];
122 - unsigned int i, j, n, len;
123 + unsigned int i, j, n, len, r, newenvppos;
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];
133 - strncpy(argv0, filename, FAKECHROOT_MAXPATH);
135 - expand_chroot_path(filename, fakechroot_path, fakechroot_ptr, fakechroot_buf);
136 - strcpy(tmp, filename);
139 - if ((file = open(filename, O_RDONLY)) == -1) {
144 - i = read(file, hashbang, FAKECHROOT_MAXPATH-2);
151 if (next_execve == NULL) fakechroot_init();
153 /* Scan envp and check its size */
154 @@ -1514,39 +1529,69 @@
157 /* Copy envp to newenvp */
158 - newenvp = malloc( sizeenvp * sizeof (char *) + sizeof(envkey) );
159 + newenvp = malloc( (sizeenvp + 1) * sizeof (char *) );
160 if (newenvp == NULL) {
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] == '=')
174 + newenvp[newenvppos] = *ep;
178 + newenvp[newenvppos] = NULL;
180 + strncpy(argv0, filename, FAKECHROOT_MAXPATH);
182 + r = try_cmd_subst (getenv ("FAKECHROOT_CMD_SUBST"), filename, tmp);
186 + /* FAKECHROOT_CMD_SUBST escapes the chroot. newenvp here does
187 + * not contain LD_PRELOAD and the other special environment
190 + return next_execve(filename, argv, newenvp);
193 + expand_chroot_path(filename, fakechroot_path, fakechroot_ptr, fakechroot_buf);
194 + strcpy(tmp, filename);
197 + if ((file = open(filename, O_RDONLY)) == -1) {
202 + i = read(file, hashbang, FAKECHROOT_MAXPATH-2);
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) {
216 - for (j = 0; j < sizeof(envkey) / sizeof(char *); j++) {
217 + for (j = 0; j < nr_envkey; j++) {
218 env = getenv(envkey[j]);
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);
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);
233 + newenvp[newenvppos] = NULL;
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)
242 The list of directories which are excluded from being chrooted. The elements
243 of list are separated with colon.
245 +=item B<FAKECHROOT_CMD_SUBST>
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).
253 + FAKECHROOT_CMD_SUBST=/sbin/ldconfig=/tmp/ldconfig-wrapper
255 +will substitute C</tmp/ldconfig-wrapper> for C</sbin/ldconfig>.
257 +Give as many substitute commands as you want, separated by C<:>
260 =item B<LD_LIBRARY_PATH>, B<LD_PRELOAD>
262 Fakechroot is implemented by wrapping system calls. This is accomplished by