This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

1.3.22-1: execvp in libc.a seems different from newlib/libc/posix


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/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]