diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index c7ba806f8..961845f5c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,27 @@ +2008-03-22 Christopher Faylor + + * dtable.cc: Define various device-related string constants as wide + character constants. + (dtable::init_std_file_from_handle): Reorganize pipe handling to try to + catch special tty case. + (build_fh_name_worker): Declare for common use. + (build_fh_name): Define char version. + (build_fh_name): Define (currently unused) UNICODE_STRING version. + (decode_tty): Detect if pipe is actually a cygwin tty, returning the + tty name in the buffer. + (handle_to_fn): Reorganize to use wide characters. + * dtable.h (build_fh_name): Declare (currently unused) UNICODE_STRING + version. + * fhandler_tty.cc (fhandler_pty_master::setup): Use + fhandler_pipe::create_selectable to create a pipe with a given name. + * pipe.cc (pipe_handler): Make returned handle inheritable. + (fhandler_pipe::create_selectable): Take an optional name. Use a + standard cygwin introducer for the name. + + * path.cc (path_conv::check): Make first argument const. + * path.h (path_conv::check): Ditto for declaration. + (path_conv::path_conv): Ditto for UNICODE_STRING version. + 2008-03-18 Corinna Vinschen * include/sys/cygwin.h: Revert erroneous move of `#ifdef WINVER' to @@ -241,7 +265,7 @@ * cygtls.cc (_cygtls::remove): Free temporary TLS path buffers. * cygtls.h (TP_NUM_C_BUFS): Define. (TP_NUM_W_BUFS): Define. - (class tls_pathbuf): New class to store pointers to thread local + (class tls_pathbuf): New class to store pointers to thread local temporary path buffers. (_local_storage::pathbufs): New member. * environ.cc (win_env::add_cache): Use temporary TLS path buffer instead diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index f1eb20fd3..05663d268 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -18,8 +18,8 @@ details. */ #include #include #include -#include #include +#include #define USE_SYS_TYPES_FD_SET #include @@ -35,23 +35,26 @@ details. */ #include "ntdll.h" #include "shared_info.h" -static const char NO_COPY unknown_file[] = "some disk file"; - static const NO_COPY DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE}; -static const char *handle_to_fn (HANDLE, char *); +static void handle_to_fn (HANDLE, char *); -#define DEVICE_PREFIX "\\device\\" -#define DEVICE_PREFIX_LEN sizeof (DEVICE_PREFIX) - 1 -#define REMOTE "\\Device\\LanmanRedirector\\" -#define REMOTE_LEN sizeof (REMOTE) - 1 -#define REMOTE1 "\\Device\\WinDfs\\Root\\" -#define REMOTE1_LEN sizeof (REMOTE1) - 1 -#define NAMED_PIPE "\\Device\\NamedPipe\\" -#define NAMED_PIPE_LEN sizeof (NAMED_PIPE) - 1 -#define POSIX_NAMED_PIPE "/Device/NamedPipe/" -#define POSIX_NAMED_PIPE_LEN sizeof (POSIX_NAMED_PIPE) - 1 +#define WCLEN(x) ((sizeof (x) / sizeof (WCHAR)) - 1) +char unknown_file[] = "some disk file"; +const WCHAR DEV_NULL[] = L"\\Device\\Null"; + +const WCHAR DEVICE_PREFIX[] = L"\\device\\"; +const size_t DEVICE_PREFIX_LEN WCLEN (DEVICE_PREFIX); + +static const WCHAR DEV_NAMED_PIPE[] = L"\\Device\\NamedPipe\\"; +static const size_t DEV_NAMED_PIPE_LEN = WCLEN (DEV_NAMED_PIPE); + +static const WCHAR DEV_REMOTE[] = L"\\Device\\LanmanRedirector\\"; +static const size_t DEV_REMOTE_LEN = WCLEN (DEV_REMOTE); + +static const WCHAR DEV_REMOTE1[] = L"\\Device\\WinDfs\\Root\\"; +static const size_t DEV_REMOTE1_LEN = WCLEN (DEV_REMOTE1); /* Set aside space for the table of fds */ void @@ -262,7 +265,6 @@ cygwin_attach_handle_to_fd (char *name, int fd, HANDLE handle, mode_t bin, void dtable::init_std_file_from_handle (int fd, HANDLE handle) { - const char *name = NULL; CONSOLE_SCREEN_BUFFER_INFO buf; struct sockaddr sa; int sal = sizeof (sa); @@ -278,55 +280,63 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle) return; SetLastError (0); + DWORD access = 0; DWORD ft = GetFileType (handle); - if (ft != FILE_TYPE_UNKNOWN || GetLastError () != ERROR_INVALID_HANDLE) + char name[NT_MAX_PATH]; + name[0] = '\0'; + if (ft == FILE_TYPE_PIPE) { - /* See if we can consoleify it */ - if (GetConsoleScreenBufferInfo (handle, &buf)) - { - if (ISSTATE (myself, PID_USETTY)) - dev.parse (FH_TTY); - else - dev = *console_dev; - } - else if (GetNumberOfConsoleInputEvents (handle, (DWORD *) &buf)) - { - if (ISSTATE (myself, PID_USETTY)) - dev.parse (FH_TTY); - else - dev = *console_dev; - } - else if (wsock_started && getpeername ((SOCKET) handle, &sa, &sal) == 0) - dev = *tcp_dev; - else if (GetCommState (handle, &dcb)) - dev.parse (DEV_TTYS_MAJOR, 0); + handle_to_fn (handle, name); + if (name[0]) + /* ok */; + else if (fd == 0) + dev = *piper_dev; else - { - name = handle_to_fn (handle, tp.c_get ()); - if (!strncasematch (name, POSIX_NAMED_PIPE, POSIX_NAMED_PIPE_LEN)) - /* nothing */; - else if (fd == 0) - dev = *piper_dev; - else - dev = *pipew_dev; - } + dev = *pipew_dev; } + else if (ft == FILE_TYPE_UNKNOWN && GetLastError () == ERROR_INVALID_HANDLE) + /* can't figure out what this is */; + else if (GetConsoleScreenBufferInfo (handle, &buf)) + { + /* Console output */ + if (ISSTATE (myself, PID_USETTY)) + dev.parse (FH_TTY); + else + dev = *console_dev; + } + else if (GetNumberOfConsoleInputEvents (handle, (DWORD *) &buf)) + { + /* Console input */ + if (ISSTATE (myself, PID_USETTY)) + dev.parse (FH_TTY); + else + dev = *console_dev; + } + else if (wsock_started && getpeername ((SOCKET) handle, &sa, &sal) == 0) + /* socket */ + dev = *tcp_dev; + else if (GetCommState (handle, &dcb)) + /* serial */ + dev.parse (DEV_TTYS_MAJOR, 0); + else + /* Try to figure it out from context - probably a disk file */ + handle_to_fn (handle, name); - if (!name && !dev) + if (!name[0] && !dev) fds[fd] = NULL; else { fhandler_base *fh; if (dev) - fh = build_fh_dev (dev, name); + fh = build_fh_dev (dev); else fh = build_fh_name (name); if (fh) cygheap->fdtab[fd] = fh; - if (name) + if (name[0]) { bin = fh->pc_binmode (); if (!bin) @@ -337,7 +347,6 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle) } } - DWORD access; if (dev == FH_TTY || dev == FH_CONSOLE) access = GENERIC_READ | GENERIC_WRITE; else if (fd == 0) @@ -352,10 +361,10 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle) } #define cnew(name) new ((void *) ccalloc (HEAP_FHANDLER, 1, sizeof (name))) name -fhandler_base * -build_fh_name (const char *name, HANDLE h, unsigned opt, suffix_info *si) + +static fhandler_base * +build_fh_name_worker (path_conv& pc, HANDLE h, unsigned opt, suffix_info *si) { - path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si); if (pc.error) { fhandler_base *fh = cnew (fhandler_nodevice) (); @@ -370,6 +379,20 @@ build_fh_name (const char *name, HANDLE h, unsigned opt, suffix_info *si) return build_fh_pc (pc); } +fhandler_base * +build_fh_name (const char *name, HANDLE h, unsigned opt, suffix_info *si) +{ + path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si); + return build_fh_name_worker (pc, h, opt, si); +} + +#define cnew(name) new ((void *) ccalloc (HEAP_FHANDLER, 1, sizeof (name))) name +fhandler_base * +build_fh_name (const UNICODE_STRING *name, HANDLE h, unsigned opt, suffix_info *si) +{ + path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si); + return build_fh_name_worker (pc, h, opt, si); +} fhandler_base * build_fh_dev (const device& dev, const char *unix_name) @@ -843,124 +866,134 @@ dtable::vfork_child_fixup () } #endif /*NEWVFORK*/ -static const char * +void decode_tty (WCHAR *w32, char *buf) +{ + int ttyn = wcstol (w32, NULL, 10); + __small_sprintf (buf, "/dev/tty%d", ttyn); +} + +static void handle_to_fn (HANDLE h, char *posix_fn) { tmp_pathbuf tp; - OBJECT_NAME_INFORMATION *ntfn; - const size_t len = sizeof (OBJECT_NAME_INFORMATION) - + NT_MAX_PATH * sizeof (WCHAR); - char *fnbuf = (char *) alloca (len); + ULONG len = 0; + OBJECT_NAME_INFORMATION dummy_oni; + WCHAR *maxmatchdos = NULL; + int maxmatchlen = 0; - memset (fnbuf, 0, len); - ntfn = (OBJECT_NAME_INFORMATION *) fnbuf; - ntfn->Name.MaximumLength = (NT_MAX_PATH - 1) * sizeof (WCHAR); - ntfn->Name.Buffer = (WCHAR *) (ntfn + 1); + NtQueryObject (h, ObjectNameInformation, &dummy_oni, sizeof (dummy_oni), &len); + if (!len) + { + debug_printf ("NtQueryObject failed 1"); + goto unknown; + } + OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION *) alloca (len + sizeof (WCHAR)); NTSTATUS res = NtQueryObject (h, ObjectNameInformation, ntfn, len, NULL); if (!NT_SUCCESS (res)) { - strcpy (posix_fn, unknown_file); - debug_printf ("NtQueryObject failed"); - return unknown_file; + debug_printf ("NtQueryObject failed 2"); + goto unknown; } // NT seems to do this on an unopened file if (!ntfn->Name.Buffer) { debug_printf ("nt->Name.Buffer == NULL"); - return NULL; + goto unknown; } - ntfn->Name.Buffer[ntfn->Name.Length / sizeof (WCHAR)] = 0; + WCHAR *w32 = ntfn->Name.Buffer; + size_t w32len = ntfn->Name.Length / sizeof (WCHAR); + w32[w32len] = L'\0'; - char *win32_fn = tp.c_get (); - sys_wcstombs (win32_fn, NT_MAX_PATH, ntfn->Name.Buffer, - ntfn->Name.Length / sizeof (WCHAR)); - debug_printf ("nt name '%s'", win32_fn); - if (!strncasematch (win32_fn, DEVICE_PREFIX, DEVICE_PREFIX_LEN) - || !QueryDosDevice (NULL, fnbuf, len)) - return strcpy (posix_fn, win32_fn); - - char *p = strechr (win32_fn + DEVICE_PREFIX_LEN, '\\'); - - int n = p - win32_fn; - int maxmatchlen = 0; - char *maxmatchdos = NULL; - char *device = tp.c_get (); - for (char *s = fnbuf; *s; s = strchr (s, '\0') + 1) + if (wcscasecmp (w32, DEV_NULL) == 0) { - device[NT_MAX_PATH - 1] = '\0'; - if (strchr (s, ':') == NULL) + strcpy (posix_fn, "/dev/null"); + return; + } + + if (wcsncasecmp (w32, DEV_NAMED_PIPE, DEV_NAMED_PIPE_LEN) == 0) + { + w32 += DEV_NAMED_PIPE_LEN; + if (wcsncmp (w32, L"cygwin-tty", WCLEN (L"cygwin-tty")) == 0) + decode_tty (w32 + WCLEN (L"cygwin-tty"), posix_fn); + return; + } + + + WCHAR fnbuf[64 * 1024]; + if (wcsncasecmp (w32, DEVICE_PREFIX, DEVICE_PREFIX_LEN) != 0 + || !QueryDosDeviceW (NULL, fnbuf, sizeof (fnbuf))) + { + sys_wcstombs (posix_fn, NT_MAX_PATH, w32, w32len); + return; + } + + for (WCHAR *s = fnbuf; *s; s = wcschr (s, '\0') + 1) + { + WCHAR device[NT_MAX_PATH]; + if (!QueryDosDeviceW (s, device, sizeof (device))) continue; - if (!QueryDosDevice (s, device, NT_MAX_PATH - 1)) + if (wcschr (s, ':') == NULL) continue; - char *q = strrchr (device, ';'); + WCHAR *q = wcsrchr (device, ';'); if (q) { - char *r = strchr (q, '\\'); + WCHAR *r = wcschr (q, '\\'); if (r) - strcpy (q, r + 1); + wcscpy (q, r + 1); } - int devlen = strlen (device); - if (device[devlen - 1] == '\\') - device[--devlen] = '\0'; + int devlen = wcslen (device); + if (device[devlen - 1] == L'\\') + device[--devlen] = L'\0'; if (devlen < maxmatchlen) continue; - if (!strncasematch (device, win32_fn, devlen) || - (win32_fn[devlen] != '\0' && win32_fn[devlen] != '\\')) + if (wcsncmp (device, w32, devlen) != 0|| + (w32[devlen] != L'\0' && w32[devlen] != L'\\')) continue; maxmatchlen = devlen; maxmatchdos = s; - debug_printf ("current match '%s'", device); + debug_printf ("current match '%W' = '%W'\n", s, device); } - char *w32 = win32_fn; - bool justslash = false; if (maxmatchlen) { - n = strlen (maxmatchdos); - if (maxmatchdos[n - 1] == '\\') - n--; - w32 += maxmatchlen - n; - memcpy (w32, maxmatchdos, n); - w32[n] = '\\'; + WCHAR *p = wcschr (w32 + DEVICE_PREFIX_LEN, L'\\'); + size_t n = wcslen (maxmatchdos); + WCHAR ch; + if (!p) + ch = L'\0'; + else + { + if (maxmatchdos[n - 1] == L'\\') + n--; + w32 += maxmatchlen - n; + ch = L'\\'; + } + memcpy (w32, maxmatchdos, n * sizeof (WCHAR)); + w32[n] = ch; } - else if (strncasematch (w32, NAMED_PIPE, NAMED_PIPE_LEN)) + else if (wcsncmp (w32, DEV_REMOTE, DEV_REMOTE_LEN) == 0) { - debug_printf ("pipe"); - justslash = true; - } - else if (strncasematch (w32, REMOTE, REMOTE_LEN)) - { - w32 += REMOTE_LEN - 2; - *w32 = '\\'; + w32 += DEV_REMOTE_LEN - 2; + *w32 = L'\\'; debug_printf ("remote drive"); - justslash = true; } - else if (strncasematch (w32, REMOTE1, REMOTE1_LEN)) + else if (wcsncmp (w32, DEV_REMOTE1, DEV_REMOTE1_LEN) == 0) { - w32 += REMOTE1_LEN - 2; - *w32 = '\\'; + w32 += DEV_REMOTE1_LEN - 2; + *w32 = L'\\'; debug_printf ("remote drive"); - justslash = true; } - if (!justslash) - cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, w32, posix_fn, - NT_MAX_PATH); - else - { - char *s, *d; - for (s = w32, d = posix_fn; *s; s++, d++) - if (*s == '\\') - *d = '/'; - else - *d = *s; - *d = 0; - } + cygwin_conv_path (CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, w32, posix_fn, + NT_MAX_PATH); - debug_printf ("derived path '%s', posix '%s'", w32, posix_fn); - return posix_fn; + debug_printf ("derived path '%W', posix '%s'", w32, posix_fn); + return; + +unknown: + strcpy (posix_fn, unknown_file); } diff --git a/winsup/cygwin/dtable.h b/winsup/cygwin/dtable.h index dcd70f66e..b2c5f1b5b 100644 --- a/winsup/cygwin/dtable.h +++ b/winsup/cygwin/dtable.h @@ -90,7 +90,8 @@ public: }; fhandler_base *build_fh_dev (const device&, const char * = NULL); -fhandler_base *build_fh_name (const char *unix_name, HANDLE = NULL, unsigned = 0, suffix_info * = NULL); +fhandler_base *build_fh_name (const char *, HANDLE = NULL, unsigned = 0, suffix_info * = NULL); +fhandler_base *build_fh_name (const UNICODE_STRING *, HANDLE = NULL, unsigned = 0, suffix_info * = NULL); fhandler_base *build_fh_pc (path_conv& pc); void dtable_init (); diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index f78861cde..a80ae8dd4 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -551,7 +551,7 @@ public: int ready_for_read (int fd, DWORD howlong); void init (HANDLE, DWORD, mode_t); static int create (fhandler_pipe *[2], unsigned, int); - static int create_selectable (LPSECURITY_ATTRIBUTES, HANDLE&, HANDLE&, DWORD); + static int create_selectable (LPSECURITY_ATTRIBUTES, HANDLE&, HANDLE&, DWORD, const char * = NULL); }; enum fifo_state diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 44a811ab3..26620b7cd 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -1352,6 +1352,7 @@ fhandler_tty_master::init_console () bool fhandler_pty_master::setup (bool ispty) { + int res; tty& t = *cygwin_shared->tty[get_unit ()]; tcinit (&t, true); /* Set termios information. Force initialization. */ @@ -1362,13 +1363,24 @@ fhandler_pty_master::setup (bool ispty) /* Create communication pipes */ /* FIXME: should this be sec_none_nih? */ - if (!CreatePipe (&from_master, &get_output_handle (), &sec_all, 128 * 1024)) + + /* Create communication pipes */ + + char pipename[sizeof("ttyNNNN-from-master")]; + __small_sprintf (pipename, "tty%d-from-master", get_unit ()); + res = fhandler_pipe::create_selectable (&sec_all_nih, from_master, + get_output_handle (), 128 * 1024, + pipename); + if (res) { errstr = "input pipe"; goto err; } - if (!CreatePipe (&get_io_handle (), &to_master, &sec_all, 128 * 1024)) + __small_sprintf (pipename, "tty%d-to-master", get_unit ()); + res = fhandler_pipe::create_selectable (&sec_all_nih, get_io_handle (), + to_master, 128 * 1024, pipename); + if (res) { errstr = "output pipe"; goto err; @@ -1380,7 +1392,7 @@ fhandler_pty_master::setup (bool ispty) need_nl = 0; - /* We do not open allow the others to open us (for handle duplication) + /* We do not allow others to open us (for handle duplication) but rely on cygheap->inherited_ctty for descendant processes. In the future the cygserver may allow access by others. */ diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index e92480f53..dc09c1f7e 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -1,7 +1,7 @@ /* miscfuncs.cc: misc funcs that don't belong anywhere else Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007 Red Hat, Inc. + 2005, 2006, 2007, 2008 Red Hat, Inc. This file is part of Cygwin. diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 84490f287..9b3dc51da 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1,7 +1,7 @@ - /* path.cc: path support. +/* path.cc: path support. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007 Red Hat, Inc. + 2006, 2007, 2008 Red Hat, Inc. This file is part of Cygwin. @@ -790,7 +790,7 @@ getfileattr (const char *path, bool managed) /* path has to be always absolute. realy nothing but converting to char *, until path_conv handles wide-char paths directly. */ void -path_conv::check (PUNICODE_STRING src, unsigned opt, +path_conv::check (const UNICODE_STRING *src, unsigned opt, const suffix_info *suffixes) { tmp_pathbuf tp; diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 2b1c751f7..f49c420f1 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -199,7 +199,7 @@ class path_conv void set_has_symlinks () {path_flags |= PATH_HAS_SYMLINKS;} void set_exec (int x = 1) {path_flags |= x ? PATH_EXEC : PATH_NOTEXEC;} - void check (PUNICODE_STRING upath, unsigned opt = PC_SYM_FOLLOW, + void check (const UNICODE_STRING *upath, unsigned opt = PC_SYM_FOLLOW, const suffix_info *suffixes = NULL) __attribute__ ((regparm(3))); void check (const char *src, unsigned opt = PC_SYM_FOLLOW, const suffix_info *suffixes = NULL) __attribute__ ((regparm(3))); @@ -217,7 +217,7 @@ class path_conv check (src, opt, suffixes); } - path_conv (PUNICODE_STRING src, unsigned opt = PC_SYM_FOLLOW, + path_conv (const UNICODE_STRING *src, unsigned opt = PC_SYM_FOLLOW, const suffix_info *suffixes = NULL) { check (src, opt | PC_NULLEMPTY, suffixes); @@ -300,10 +300,10 @@ enum fe_types FE_CWD = 4, /* Search CWD for program */ FE_DLL = 8 /* Search for DLLs, not executables. */ }; -const char * __stdcall find_exec (const char *name, path_conv& buf, - const char *winenv = "PATH=", - unsigned opt = FE_NADA, - const char **known_suffix = NULL) +const char *__stdcall find_exec (const char *name, path_conv& buf, + const char *winenv = "PATH=", + unsigned opt = FE_NADA, + const char **known_suffix = NULL) __attribute__ ((regparm(3))); /* Common macros for checking for invalid path names */ diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc index 87a7474bd..82bfe47ad 100644 --- a/winsup/cygwin/pipe.cc +++ b/winsup/cygwin/pipe.cc @@ -59,7 +59,7 @@ static DWORD WINAPI pipe_handler (LPVOID in_ps) { pipesync ps = *(pipesync *) in_ps; - HANDLE in, out; + HANDLE h, in, out; DWORD err = fhandler_pipe::create_selectable (&sec_none_nih, in, out, 0); if (err) { @@ -67,7 +67,8 @@ pipe_handler (LPVOID in_ps) system_printf ("couldn't create a shadow pipe for non-cygwin pipe I/O, %E"); return 0; } - ((pipesync *) in_ps)->ret_handle = ps.reader ? in : out; + h = ((pipesync *) in_ps)->ret_handle = ps.reader ? in : out; + SetHandleInformation (h, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); SetEvent (ps.ev); char buf[4096]; @@ -124,6 +125,7 @@ pipesync::pipesync (HANDLE f, DWORD is_reader): system_printf ("couldn't create synchronization event for non-cygwin pipe, %E"); goto out; } + debug_printf ("created thread synchronization event %p", ev); non_cygwin_h = f; reader = !!is_reader; ret_handle = NULL; @@ -153,7 +155,6 @@ out: return; } -#define WINPIPE "\\\\.\\pipe\\" void fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode) { @@ -324,6 +325,8 @@ fhandler_pipe::dup (fhandler_base *child) return res; } +#define PIPE_INTRO "\\\\.\\pipe\\cygwin-" + /* Create a pipe, and return handles to the read and write ends, just like CreatePipe, but ensure that the write end permits FILE_READ_ATTRIBUTES access, on later versions of win32 where @@ -333,7 +336,7 @@ fhandler_pipe::dup (fhandler_base *child) unlike CreatePipe, which returns a bool for success or failure. */ int fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r, - HANDLE& w, DWORD psize) + HANDLE& w, DWORD psize, const char *name) { /* Default to error. */ r = w = INVALID_HANDLE_VALUE; @@ -342,20 +345,26 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r, if (psize < PIPE_BUF) psize = PIPE_BUF; - char pipename[MAX_PATH]; + char pipename[MAX_PATH] = PIPE_INTRO; + /* FIXME: Eventually make ttys work with overlapped I/O. */ + DWORD overlapped = name ? 0 : FILE_FLAG_OVERLAPPED; /* Retry CreateNamedPipe as long as the pipe name is in use. Retrying will probably never be necessary, but we want to be as robust as possible. */ - while (1) + DWORD err; + do { static volatile ULONG pipe_unique_id; - - __small_sprintf (pipename, "\\\\.\\pipe\\cygwin-%p-%p", myself->pid, - InterlockedIncrement ((LONG *) &pipe_unique_id)); + if (!name) + __small_sprintf (pipename + strlen(PIPE_INTRO), "%p-%p", myself->pid, + InterlockedIncrement ((LONG *) &pipe_unique_id)); + else + strcpy (pipename + strlen(PIPE_INTRO), name); debug_printf ("CreateNamedPipe: name %s, size %lu", pipename, psize); + err = 0; /* Use CreateNamedPipe instead of CreatePipe, because the latter returns a write handle that does not permit FILE_READ_ATTRIBUTES access, on versions of win32 earlier than WinXP SP2. @@ -365,7 +374,7 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r, the pipe was not created earlier by some other process, even if the pid has been reused. We avoid FILE_FLAG_FIRST_PIPE_INSTANCE because that is only available for Win2k SP2 and WinXP. */ - r = CreateNamedPipe (pipename, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, + r = CreateNamedPipe (pipename, PIPE_ACCESS_INBOUND | overlapped, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, psize, psize, NMPWAIT_USE_DEFAULT_WAIT, sa_ptr); @@ -376,7 +385,7 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r, break; } - DWORD err = GetLastError (); + err = GetLastError (); switch (err) { case ERROR_PIPE_BUSY: @@ -397,13 +406,17 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r, } } } + while (!name); + + if (err) + return err; debug_printf ("CreateFile: name %s", pipename); /* Open the named pipe for writing. Be sure to permit FILE_READ_ATTRIBUTES access. */ w = CreateFile (pipename, GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0, sa_ptr, - OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + OPEN_EXISTING, overlapped, 0); if (!w || w == INVALID_HANDLE_VALUE) {