From 55fc91b9d62bec29deaba79e4adb4e85c35cc306 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Wed, 26 Apr 2000 05:13:32 +0000 Subject: [PATCH] * exceptions.cc (interruptible): Allocate slightly more space for directory name check. Windows 95 seems to null-terminate the directory otherwise. (interrupt_on_return): Issue a fatal error if we can't find the caller's stack. * spawn.cc (find_exec): Accept a path_conv argument rather than a buffer so that the caller can find things out about a translated path. (perhaps_suffix): Ditto. (spawn_guts): Allocate path_conv stuff here so that we can find out stuff about the translated path (this is work in progress). * environ.cc (environ_init): Accept an as-yet unused argument indicating whether we were invoked from a cygwin parent or not. (winenv): Ditto. (posify): Accept an argument indicating whether the path has already been translated. * dlfcn.cc (check_access): Provide a path_conv buffer to find_exec. * exec.cc (sexecvpe): Ditto. * path.cc (path_conv::check): Rename from path_conv::path_conv. (mount_item::getmntent): Recognize "Cygwin executable" bit. (symlink_info::check): Remove debugging statements. * path.h (class path_conv): Add iscygexec method. Rewrite constructor to call "check" method to allow multiple operations on a path_conv variable. * pinfo.cc (pinfo_init): Pass argument to environ_init. * shared.h: Bump PROC_MAGIC. * winsup.h: Reflect above changes to function arguments. * include/sys/mount.h: Add MOUNT_CYGWIN_EXEC type. --- winsup/cygwin/ChangeLog | 33 +++++++++++++++++++++++++++++ winsup/cygwin/dlfcn.cc | 2 +- winsup/cygwin/environ.cc | 35 ++++++++++++++++++------------- winsup/cygwin/exceptions.cc | 9 ++++---- winsup/cygwin/exec.cc | 2 +- winsup/cygwin/include/sys/mount.h | 16 +++++++------- winsup/cygwin/path.cc | 18 +++++++--------- winsup/cygwin/path.h | 14 +++++++++++-- winsup/cygwin/pinfo.cc | 4 ++-- winsup/cygwin/shared.h | 2 +- winsup/cygwin/spawn.cc | 33 +++++++++++++---------------- winsup/cygwin/winsup.h | 6 +++--- 12 files changed, 110 insertions(+), 64 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 01ab1a100..e6e2f125f 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,36 @@ +Wed Apr 26 01:07:16 2000 Christopher Faylor + + * exceptions.cc (interruptible): Allocate slightly more space for + directory name check. Windows 95 seems to null-terminate the directory + otherwise. + (interrupt_on_return): Issue a fatal error if we can't find the + caller's stack. + +Tue Apr 25 16:50:54 2000 Christopher Faylor + + * spawn.cc (find_exec): Accept a path_conv argument rather than a + buffer so that the caller can find things out about a translated path. + (perhaps_suffix): Ditto. + (spawn_guts): Allocate path_conv stuff here so that we can find out + stuff about the translated path (this is work in progress). + * environ.cc (environ_init): Accept an as-yet unused argument + indicating whether we were invoked from a cygwin parent or not. + (winenv): Ditto. + (posify): Accept an argument indicating whether the path has already + been translated. + * dlfcn.cc (check_access): Provide a path_conv buffer to find_exec. + * exec.cc (sexecvpe): Ditto. + * path.cc (path_conv::check): Rename from path_conv::path_conv. + (mount_item::getmntent): Recognize "Cygwin executable" bit. + (symlink_info::check): Remove debugging statements. + * path.h (class path_conv): Add iscygexec method. Rewrite constructor + to call "check" method to allow multiple operations on a path_conv + variable. + * pinfo.cc (pinfo_init): Pass argument to environ_init. + * shared.h: Bump PROC_MAGIC. + * winsup.h: Reflect above changes to function arguments. + * include/sys/mount.h: Add MOUNT_CYGWIN_EXEC type. + Thu Apr 25 21:35:00 2000 Corinna Vinschen * syscalls.cc (stat_worker): Previous patch failed to stat diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc index 21c6e5bd0..cf74d4696 100644 --- a/winsup/cygwin/dlfcn.cc +++ b/winsup/cygwin/dlfcn.cc @@ -60,7 +60,7 @@ check_access (const char *dir, const char *name) static const char * __stdcall check_path_access (const char *mywinenv, const char *name) { - static char buf[MAX_PATH]; + path_conv buf; return find_exec (name, buf, mywinenv, TRUE); } diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index b09fe90e9..7b9c33ac0 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -94,7 +94,7 @@ getwinenv (const char *env, const char *in_posix) /* Convert windows path specs to POSIX, if appropriate. */ static void __stdcall -posify (char **here, const char *value) +posify (int already_posix, char **here, const char *value) { char *src = *here; win_env *conv; @@ -103,17 +103,22 @@ posify (char **here, const char *value) if (!(conv = getwinenv (src))) return; - /* Turn all the items from c:; into their - mounted equivalents - if there is one. */ + if (already_posix) + conv->add_cache (value, NULL); + else + { + /* Turn all the items from c:; into their + mounted equivalents - if there is one. */ - char *outenv = (char *) malloc (1 + len + conv->posix_len (value)); - memcpy (outenv, src, len); - conv->toposix (value, outenv + len); - conv->add_cache (outenv + len, value); + char *outenv = (char *) malloc (1 + len + conv->posix_len (value)); + memcpy (outenv, src, len); + conv->toposix (value, outenv + len); + conv->add_cache (outenv + len, value); - debug_printf ("env var converted to %s", outenv); - *here = outenv; - free (src); + debug_printf ("env var converted to %s", outenv); + *here = outenv; + free (src); + } } /* @@ -435,7 +440,7 @@ regopt (const char *name) * environment variable and set appropriate options from it. */ void -environ_init (void) +environ_init (int already_posix) { const char * const rawenv = GetEnvironmentStrings (); int envsize, i; @@ -479,7 +484,7 @@ environ_init (void) if (strncmp (newp, "CYGWIN=", sizeof("CYGWIN=") - 1) == 0) parse_options (newp + sizeof("CYGWIN=") - 1); if (*eq) - posify (envp + i, *++eq ? eq : --eq); + posify (already_posix, envp + i, *++eq ? eq : --eq); debug_printf ("%s", envp[i]); } @@ -509,7 +514,7 @@ env_sort (const void *a, const void *b) * prior to placing them in the string. */ char * __stdcall -winenv (const char * const *envp) +winenv (const char * const *envp, int keep_posix) { int len, n, tl; const char * const *srcp; @@ -520,12 +525,14 @@ winenv (const char * const *envp) const char *newenvp[n + 1]; + debug_printf ("envp %p, keep_posix %d", envp, keep_posix); + for (tl = 0, srcp = envp, dstp = newenvp; *srcp; srcp++, dstp++) { len = strcspn (*srcp, "=") + 1; win_env *conv; - if ((conv = getwinenv (*srcp, *srcp + len))) + if (!keep_posix && (conv = getwinenv (*srcp, *srcp + len))) *dstp = conv->native; else *dstp = *srcp; diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index f82f6364a..dea040659 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -568,13 +568,13 @@ interruptible (DWORD pc) if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m)) sigproc_printf ("couldn't get memory info, %E"); - char *checkdir = (char *) alloca (windows_system_directory_length); + char *checkdir = (char *) alloca (windows_system_directory_length + 2); # define h ((HMODULE) m.AllocationBase) if (h == user_data->hmodule) res = 1; else if (h == cygwin_hmodule) res = 0; - else if (!GetModuleFileName (h, checkdir, windows_system_directory_length)) + else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2)) res = 0; else res = !strncasematch (windows_system_directory, checkdir, @@ -642,10 +642,11 @@ interrupt_on_return (DWORD ebp, int sig, struct sigaction& siga, void *handler) interrupt_setup (sig, siga, handler, *addr_retaddr, addr_retaddr); *addr_retaddr = (DWORD) sigdelayed; } - break; + return 1; } - return 1; + api_fatal ("couldn't send signal %d", sig); + return 0; } extern "C" void __stdcall diff --git a/winsup/cygwin/exec.cc b/winsup/cygwin/exec.cc index 54d2c9577..340e82ab4 100644 --- a/winsup/cygwin/exec.cc +++ b/winsup/cygwin/exec.cc @@ -198,7 +198,7 @@ int sexecvpe (HANDLE hToken, const char *file, const char * const *argv, const char *const *envp) { - char buf[MAXNAMLEN]; + path_conv buf; MALLOC_CHECK; return sexecve (hToken, find_exec (file, buf), argv, envp); } diff --git a/winsup/cygwin/include/sys/mount.h b/winsup/cygwin/include/sys/mount.h index 5f640178f..13963f957 100644 --- a/winsup/cygwin/include/sys/mount.h +++ b/winsup/cygwin/include/sys/mount.h @@ -6,13 +6,15 @@ extern "C" { #endif enum - { - MOUNT_SYMLINK = 1, /* "mount point" is a symlink */ - MOUNT_BINARY = 2, /* "binary" format read/writes */ - MOUNT_SYSTEM = 8, /* mount point came from system table */ - MOUNT_EXEC = 16, /* Any file in the mounted directory gets 'x' bit */ - MOUNT_AUTO = 32 /* mount point refers to auto device mount */ - }; +{ + MOUNT_SYMLINK = 1, /* "mount point" is a symlink */ + MOUNT_BINARY = 2, /* "binary" format read/writes */ + MOUNT_SYSTEM = 8, /* mount point came from system table */ + MOUNT_EXEC = 16, /* Any file in the mounted directory gets 'x' bit */ + MOUNT_AUTO = 32, /* mount point refers to auto device mount */ + MOUNT_CYGWIN_EXEC = 64/* file or directory is or contains a cygwin + executable */ +}; int mount (const char *, const char *, unsigned __flags); int umount (const char *); diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 30aa3f90b..c18989067 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -186,8 +186,9 @@ path_prefix_p_ (const char *path1, const char *path2, int len1) SYMLINK_CONTENTS - just return symlink contents */ -path_conv::path_conv (const char *src, symlink_follow follow_mode, - int use_full_path, const suffix_info *suffixes) +void +path_conv::check (const char *src, symlink_follow follow_mode, + int use_full_path, const suffix_info *suffixes) { /* This array is used when expanding symlinks. It is MAX_PATH * 2 in length so that we can hold the expanded symlink plus a @@ -1891,9 +1892,12 @@ mount_item::getmntent () else strcpy (cygwin_shared->mount.mnt_opts, (char *) "binmode"); - if (flags & MOUNT_EXEC) + if (flags & MOUNT_CYGWIN_EXEC) + strcat (cygwin_shared->mount.mnt_opts, (char *) ",cygexec"); + else if (flags & MOUNT_EXEC) strcat (cygwin_shared->mount.mnt_opts, (char *) ",exec"); + ret.mnt_opts = cygwin_shared->mount.mnt_opts; ret.mnt_freq = 1; @@ -2190,9 +2194,6 @@ symlink_info::check (const char *in_path, const suffix_info *suffixes) h = CreateFileA (path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - -syscall_printf ("opened '%s'(%p)", path, h); - res = -1; if (h == INVALID_HANDLE_VALUE) __seterrno (); @@ -2201,7 +2202,6 @@ syscall_printf ("opened '%s'(%p)", path, h); char cookie_buf[sizeof (SYMLINK_COOKIE) - 1]; DWORD got; -syscall_printf ("ReadFile"); if (! ReadFile (h, cookie_buf, sizeof (cookie_buf), &got, 0)) set_errno (EIO); else if (got == sizeof (cookie_buf) @@ -2238,18 +2238,16 @@ syscall_printf ("ReadFile"); else { /* Not a symlink, see if executable. */ - if (!(pflags & PATH_EXEC) && got >= 2 && + if (!(pflags & (PATH_EXEC | PATH_CYGWIN_EXEC)) && got >= 2 && ((cookie_buf[0] == '#' && cookie_buf[1] == '!') || (cookie_buf[0] == ':' && cookie_buf[1] == '\n'))) pflags |= PATH_EXEC; close_and_return: -syscall_printf ("close_and_return"); CloseHandle (h); goto file_not_symlink; } } -syscall_printf ("breaking from loop"); CloseHandle (h); break; } diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index f3be6b542..f2dff1b98 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -31,6 +31,7 @@ enum PATH_SYMLINK = MOUNT_SYMLINK, PATH_BINARY = MOUNT_BINARY, PATH_EXEC = MOUNT_EXEC, + PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC, PATH_SOCKET = 0x40000000, PATH_HASACLS = 0x80000000 }; @@ -49,6 +50,7 @@ class path_conv int issymlink () {return path_flags & PATH_SYMLINK;} int issocket () {return path_flags & PATH_SOCKET;} int isexec () {return path_flags & PATH_EXEC;} + int iscygexec () {return path_flags & PATH_CYGWIN_EXEC;} void set_binary () {path_flags |= PATH_BINARY;} void set_symlink () {path_flags |= PATH_SYMLINK;} @@ -63,8 +65,16 @@ class path_conv DWORD fileattr; - path_conv (const char * const, symlink_follow follow_mode = SYMLINK_FOLLOW, - int use_full_path = 0, const suffix_info *suffixes = NULL); + void check (const char *src, symlink_follow follow_mode = SYMLINK_FOLLOW, + int use_full_path = 0, const suffix_info *suffixes = NULL); + path_conv (const char *src, symlink_follow follow_mode = SYMLINK_FOLLOW, + int use_full_path = 0, const suffix_info *suffixes = NULL) + { + check (src, follow_mode, use_full_path, suffixes); + } + + path_conv (): path_flags (0), known_suffix (NULL), error (0), devn (0), unit (0), fileattr (0xffffffff) {path[0] = '\0';} + inline char *get_win32 () { return path; } operator char *() {return path; } BOOL is_device () {return devn != FH_BAD;} diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 48709fc86..d6ab35aa8 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -77,7 +77,7 @@ pinfo_init (LPBYTE info) { /* The process was execed. Reuse entry from the original owner of this pid. */ - environ_init (); /* Needs myself but affects calls below */ + environ_init (0); /* Needs myself but affects calls below */ /* spawn has already set up a pid structure for us so we'll use that */ @@ -100,7 +100,7 @@ pinfo_init (LPBYTE info) myself->ctty = -1; myself->uid = USHRT_MAX; - environ_init (); /* call after myself has been set up */ + environ_init (0); /* call after myself has been set up */ } debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid); diff --git a/winsup/cygwin/shared.h b/winsup/cygwin/shared.h index 987991cb3..8eb552a24 100644 --- a/winsup/cygwin/shared.h +++ b/winsup/cygwin/shared.h @@ -187,7 +187,7 @@ pinfo *__stdcall procinfo (int n); enum { - PROC_MAGIC = 0xaf05f000, + PROC_MAGIC = 0xaf06f000, PROC_FORK = PROC_MAGIC + 1, PROC_EXEC = PROC_MAGIC + 2, PROC_SPAWN = PROC_MAGIC + 3, diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index e1a191c7b..2a3c95c77 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -38,22 +38,21 @@ suffix_info std_suffixes[] = Returns (possibly NULL) suffix */ static const char * -perhaps_suffix (const char *prog, char *buf) +perhaps_suffix (const char *prog, path_conv &buf) { char *ext; debug_printf ("prog '%s'", prog); - path_conv temp (prog, SYMLINK_FOLLOW, 1, std_suffixes); - strcpy (buf, temp.get_win32 ()); + buf.check (prog, SYMLINK_FOLLOW, 1, std_suffixes); - if (temp.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) + if (buf.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) ext = NULL; - else if (temp.known_suffix) - ext = buf + (temp.known_suffix - temp.get_win32 ()); + else if (buf.known_suffix) + ext = buf + (buf.known_suffix - buf.get_win32 ()); else ext = strchr (buf, '\0'); - debug_printf ("buf %s, suffix found '%s'", buf, ext); + debug_printf ("buf %s, suffix found '%s'", (char *) buf, ext); return ext; } @@ -66,7 +65,7 @@ perhaps_suffix (const char *prog, char *buf) is undefined and NULL is returned. */ const char * __stdcall -find_exec (const char *name, char *buf, const char *mywinenv, +find_exec (const char *name, path_conv& buf, const char *mywinenv, int null_if_notfound, const char **known_suffix) { const char *suffix = ""; @@ -120,10 +119,10 @@ errout: if (null_if_notfound) retval = NULL; else - strcpy (buf, path_conv (name).get_win32 ()); + buf.check (name); out: - debug_printf ("%s = find_exec (%s)", buf, name); + debug_printf ("%s = find_exec (%s)", (char *) buf, name); if (known_suffix) *known_suffix = suffix ?: strchr (buf, '\0'); return retval; @@ -257,7 +256,7 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv, /* nothing */; char *real_path; - char real_path_buf[MAX_PATH]; + path_conv real_path_buf; linebuf one_line; @@ -274,15 +273,13 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv, goto skip_arg_parsing; } - MALLOC_CHECK; - real_path = real_path_buf; const char *saved_prog_arg; const char *newargv0, **firstarg; const char *ext; - if ((ext = perhaps_suffix (prog_arg, real_path)) == NULL) + if ((ext = perhaps_suffix (prog_arg, real_path_buf)) == NULL) { set_errno (ENOENT); return -1; @@ -381,7 +378,7 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv, one_line.prepend (" \"", 2); } - find_exec (pgm, real_path, "PATH=", 0, &ext); + find_exec (pgm, real_path_buf, "PATH=", 0, &ext); cygwin_conv_to_posix_path (real_path, buf2); one_line.prepend (buf2, strlen (buf2)); @@ -500,10 +497,8 @@ skip_arg_parsing: if (mode == _P_DETACH || !set_console_state_for_spawn ()) flags |= DETACHED_PROCESS; - MALLOC_CHECK; /* Build windows style environment list */ - char *envblock = winenv (envp); - MALLOC_CHECK; + char *envblock = winenv (envp, 0); /* Preallocated buffer for `sec_user' call */ char sa_buf[1024]; @@ -977,6 +972,6 @@ int spawnvpe (int mode, const char *file, const char * const *argv, const char * const *envp) { - char buf[MAXNAMLEN]; + path_conv buf; return _spawnve (NULL, mode, find_exec (file, buf), argv, envp); } diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index f3dbe3a0a..68fc14702 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -373,7 +373,7 @@ extern "C" int dll_noncygwin_dllcrt0 (HMODULE, per_process *); extern "C" void __stdcall do_exit (int) __attribute__ ((noreturn)); /* Initialize the environment */ -void environ_init (void); +void environ_init (int); /* Heap management. */ void heap_init (void); @@ -411,7 +411,7 @@ extern "C" int try_to_debug (); /**************************** Miscellaneous ******************************/ -const char * __stdcall find_exec (const char *name, char *buf, const char *winenv = "PATH=", +const char * __stdcall find_exec (const char *name, path_conv& buf, const char *winenv = "PATH=", int null_if_notfound = 0, const char **known_suffix = NULL); /* File manipulation */ @@ -556,7 +556,7 @@ struct win_env win_env * __stdcall getwinenv (const char *name, const char *posix = NULL); -char * __stdcall winenv (const char * const *); +char * __stdcall winenv (const char * const *, int); extern char **__cygwin_environ; /* The title on program start. */