Mail Archives: cygwin/2003/04/01/18:15:38
Hi,
I'm still working on the problem related to using execvp to
call a program through a relative symbolic link.
I have installed the latest release of cygwin (1.3.22-1)
available today.
I use the following test environment:
- create a directory d2 on a network share, containing two programs;
- create a sibling directory d1, containing a relative symbolic link
to one of the two previous programs in d2;
- call execvp (using a C program or with Perl) with PATH=d1:d2:$PATH.
With that setup, I am faced with the odd fact that the
symbolic link in d1 is not seen/used by execvp.
I have downloaded the cygwin source distribution, found the
execvp.c file in newlib/libc/posix, and compiled a version
of this file in my test environment, which I have put in a
library called -ldv.
Surprise: when linking with my version of execvp, everything
works fine.
If I interpose -lc (or -lcygwin) before my library, the
program no longer works.
Could it be that the objects in libc.a or libcygwin.a
are not in sync with the source, or something like that?
My environment test is provided in post-scriptum.
--
Daniel
# Edit this path to point to a non-existent directory on a
# network share.
network_dir=/home/danielv/tmp
[ -d $network_dir ] || mkdir $network_dir
cd $network_dir
rm -rf callfoo* lib* d1 d2
# create an object containing the definition of execvp,
# taken from src/newlib/libc/posix/execvp.c
cat >myexecvp.c <<'EOF'
#include <_ansi.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#define PATH_DELIM ':'
/*
* Copy string, until c or <nul> is encountered.
* NUL-terminate the destination string (s1).
*/
static char *
_DEFUN (strccpy, (s1, s2, c),
char *s1 _AND
char *s2 _AND
char c)
{
char *dest = s1;
while (*s2 && *s2 != c)
*s1++ = *s2++;
*s1 = 0;
return dest;
}
int
_DEFUN (execvp, (file, argv),
_CONST char *file _AND
char * _CONST argv[])
{
char *path = getenv ("PATH");
char buf[MAXNAMLEN];
/* If $PATH doesn't exist, just pass FILE on unchanged. */
if (!path)
return execv (file, argv);
/* If FILE contains a directory, don't search $PATH. */
if (strchr (file, '/')
)
return execv (file, argv);
while (*path)
{
strccpy (buf, path, PATH_DELIM);
/* An empty entry means the current directory. */
if (*buf != 0 && buf[strlen(buf) - 1] != '/')
strcat (buf, "/");
strcat (buf, file);
if (execv (buf, argv) == -1 && errno != ENOENT)
return -1;
while (*path && *path != PATH_DELIM)
path++;
if (*path == PATH_DELIM)
path++; /* skip over delim */
}
return -1;
}
EOF
gcc -o myexecvp.o -c myexecvp.c
ar cr libdv.a myexecvp.o
rm myexecvp.o
cat >callfoo.c <<'EOF'
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
char *argv[] = { "foo", NULL };
execvp("foo", argv);
perror("callfoo");
exit(EXIT_FAILURE);
}
EOF
gcc -o callfoo1 callfoo.c
gcc -o callfoo2 callfoo.c -L$network_dir -ldv
gcc -o callfoo3 callfoo.c -L$network_dir -lc -ldv
# create two subdirectories that will be prepended to the PATH
mkdir d1 d2
# create two programs that echo a string
cat >d2/print.c <<'EOF'
#include <stdio.h>
int main(int argc, char **argv)
{
printf("%s\n", NAME);
return 0;
}
EOF
gcc -DNAME='"foo"' -o d2/foo d2/print.c
gcc -DNAME='"bar"' -o d2/bar d2/print.c
# create a relative symlink from d1/foo to d2/bar, sooner in the path
ln -s ../d2/bar d1/foo
# ln -s $network_dir/d2/bar.sh d1/foo.sh
# call foo through execvp, with the symlink sooner in the PATH
echo 'next lines should all be "bar"'
PATH=d1:d2:$PATH ./callfoo1
PATH=d1:d2:$PATH ./callfoo2
PATH=d1:d2:$PATH ./callfoo3
# first one calls execvp
PATH=d1:d2:$PATH perl -e 'exec "foo"'
# second one calls the shell because of $
PATH=d1:d2:$PATH perl -e 'exec "foo \$EMPTY"'
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Bug reporting: http://cygwin.com/bugs.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
- Raw text -