From: Takashi Yano <takashi.yano@nifty.ne.jp>
To: cygwin-developers@cygwin.com
Subject: Re: New implementation of pseudo console support (experimental)
Date: Tue, 19 May 2020 22:40:18 +0900 [thread overview]
Message-ID: <20200519224018.746f6324badd8a5762df42b1@nifty.ne.jp> (raw)
In-Reply-To: <20200516164735.2a2ef183788b151e9185ef41@nifty.ne.jp>
[-- Attachment #1: Type: text/plain, Size: 449 bytes --]
On Sat, 16 May 2020 16:47:35 +0900
Takashi Yano via Cygwin-developers <cygwin-developers@cygwin.com> wrote:
> On Sat, 16 May 2020 09:29:56 +0900
> Takashi Yano via Cygwin-developers <cygwin-developers@cygwin.com> wrote:
> > Fix a small bug caused when stdio is redirected to another pty.
>
> Fix another bug caused when stdio is redirected to another pty.
Revise the patch to fit the current git head.
--
Takashi Yano <takashi.yano@nifty.ne.jp>
[-- Attachment #2: pcon2-20200519.diff --]
[-- Type: text/plain, Size: 17340 bytes --]
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 857f0a4e0..ea89d8f30 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -2264,6 +2264,7 @@ class fhandler_pty_common: public fhandler_termios
return get_ttyp ()->h_pseudo_console;
}
bool to_be_read_from_pcon (void);
+ void resize_pseudo_console2 (struct winsize *);
protected:
BOOL process_opost_output (HANDLE h,
@@ -2356,6 +2357,9 @@ class fhandler_pty_slave: public fhandler_pty_common
void wait_pcon_fwd (void);
void pull_pcon_input (void);
void update_pcon_input_state (bool need_lock);
+ bool setup_pseudoconsole2 (STARTUPINFOEXW *si);
+ void close_pseudoconsole2 (void);
+ void wait_pcon_fwd2 (void);
};
#define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 02b78cd2c..c4106273f 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -41,6 +41,8 @@ extern "C" {
VOID WINAPI ClosePseudoConsole (HPCON);
}
+#define USE_PCON_MODE2 true
+
#define close_maybe(h) \
do { \
if (h && h != INVALID_HANDLE_VALUE) \
@@ -534,22 +536,26 @@ fhandler_pty_master::accept_input ()
bytes_left = eat_readahead (-1);
+ HANDLE write_to = get_output_handle ();
+ if (to_be_read_from_pcon () && USE_PCON_MODE2)
+ write_to = to_slave;
+
if (!bytes_left)
{
termios_printf ("sending EOF to slave");
get_ttyp ()->read_retval = 0;
}
- else if (!to_be_read_from_pcon ())
+ else if (!to_be_read_from_pcon () || USE_PCON_MODE2)
{
char *p = rabuf ();
DWORD rc;
DWORD written = 0;
paranoid_printf ("about to write %u chars to slave", bytes_left);
- rc = WriteFile (get_output_handle (), p, bytes_left, &written, NULL);
+ rc = WriteFile (write_to, p, bytes_left, &written, NULL);
if (!rc)
{
- debug_printf ("error writing to pipe %p %E", get_output_handle ());
+ debug_printf ("error writing to pipe %p %E", write_to);
get_ttyp ()->read_retval = -1;
ret = -1;
}
@@ -1256,6 +1262,8 @@ fhandler_pty_slave::get_readahead_valid (void)
void
fhandler_pty_slave::set_switch_to_pcon (int fd_set)
{
+ if (USE_PCON_MODE2)
+ return;
if (fd < 0)
fd = fd_set;
if (fd == 0 && !get_ttyp ()->switch_to_pcon_in)
@@ -1302,6 +1310,7 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
get_ttyp ()->switch_to_pcon_in = false;
get_ttyp ()->switch_to_pcon_out = false;
init_console_handler (true);
+ get_ttyp ()->h_pseudo_console2 = NULL;
}
void
@@ -1561,8 +1570,9 @@ fhandler_pty_slave::mask_switch_to_pcon_in (bool mask)
bool
fhandler_pty_common::to_be_read_from_pcon (void)
{
- return !get_ttyp ()->pcon_in_empty ||
- (get_ttyp ()->switch_to_pcon_in && !get_ttyp ()->mask_switch_to_pcon_in);
+ return !get_ttyp ()->pcon_in_empty || get_ttyp ()->pcon2_start
+ || (get_ttyp ()->switch_to_pcon_in
+ && !get_ttyp ()->mask_switch_to_pcon_in);
}
void __reg3
@@ -2066,6 +2076,8 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg)
cleanup:
restore_reattach_pcon ();
}
+ if (get_ttyp ()->h_pseudo_console2 && get_ttyp ()->pcon_pid)
+ resize_pseudo_console2 ((struct winsize *) arg);
if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
|| get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
@@ -2355,6 +2367,27 @@ fhandler_pty_common::close ()
return 0;
}
+void
+fhandler_pty_common::resize_pseudo_console2 (struct winsize *ws)
+{
+ COORD size;
+ size.X = ws->ws_col;
+ size.Y = ws->ws_row;
+ pinfo p (get_ttyp ()->pcon_pid);
+ if (p)
+ {
+ HPCON_INTERNAL hpcon_local;
+ HANDLE pcon_owner =
+ OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->exec_dwProcessId);
+ DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_write_pipe,
+ GetCurrentProcess (), &hpcon_local.hWritePipe,
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
+ ResizePseudoConsole ((HPCON) &hpcon_local, size);
+ CloseHandle (pcon_owner);
+ CloseHandle (hpcon_local.hWritePipe);
+ }
+}
+
void
fhandler_pty_master::cleanup ()
{
@@ -2492,7 +2525,8 @@ fhandler_pty_master::write (const void *ptr, size_t len)
/* Write terminal input to to_slave pipe instead of output_handle
if current application is native console application. */
- if (to_be_read_from_pcon ())
+ if (to_be_read_from_pcon ()
+ && (!USE_PCON_MODE2 || get_ttyp ()->h_pseudo_console2))
{
size_t nlen;
char *buf = convert_mb_str
@@ -2504,11 +2538,52 @@ fhandler_pty_master::write (const void *ptr, size_t len)
get_ttyp ()->req_flush_pcon_input = true;
DWORD wLen;
+
+ if (get_ttyp ()->pcon2_start)
+ {
+ /* Pseudo condole support mode-2 uses "CSI6n" to get cursor
+ position. If the reply for "CSI6n" is divided into multiple
+ writes, pseudo console sometimes does not recognize it.
+ Therefore, put them together into wpbuf and write all at once. */
+ static const int wpbuf_len = 64;
+ static char wpbuf[wpbuf_len];
+ static int ixput = 0;
+
+ if (ixput == 0 && buf[0] != '\033')
+ { /* fail-safe */
+ WriteFile (to_slave, "\033[1;1R", 6, &wLen, NULL); /* dummy */
+ get_ttyp ()->pcon2_start = false;
+ }
+ else
+ {
+ if (ixput + nlen < wpbuf_len)
+ for (size_t i=0; i<nlen; i++)
+ wpbuf[ixput++] = buf[i];
+ else
+ {
+ WriteFile (to_slave, wpbuf, ixput, &wLen, NULL);
+ ixput = 0;
+ get_ttyp ()->pcon2_start = false;
+ WriteFile (to_slave, buf, nlen, &wLen, NULL);
+ }
+ if (ixput && memchr (wpbuf, 'R', ixput))
+ {
+ WriteFile (to_slave, wpbuf, ixput, &wLen, NULL);
+ ixput = 0;
+ get_ttyp ()->pcon2_start = false;
+ }
+ ReleaseMutex (input_mutex);
+ mb_str_free (buf);
+ return len;
+ }
+ }
+
WriteFile (to_slave, buf, nlen, &wLen, NULL);
get_ttyp ()->pcon_in_empty = false;
ReleaseMutex (input_mutex);
+#if !USE_PCON_MODE2
/* Use line_edit () in order to set input_available_event. */
bool is_echo = tc ()->ti.c_lflag & ECHO;
if (!get_ttyp ()->mask_switch_to_pcon_in)
@@ -2534,6 +2609,7 @@ fhandler_pty_master::write (const void *ptr, size_t len)
eat_readahead (-1);
SetEvent (input_available_event);
}
+#endif /* USE_PCON_MODE2 */
mb_str_free (buf);
return len;
@@ -2615,6 +2691,8 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
size.Y = ((struct winsize *) arg)->ws_row;
ResizePseudoConsole (get_pseudo_console (), size);
}
+ if (get_ttyp ()->h_pseudo_console2 && get_ttyp ()->pcon_pid)
+ resize_pseudo_console2 ((struct winsize *) arg);
if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
|| get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
{
@@ -2891,6 +2969,19 @@ fhandler_pty_slave::wait_pcon_fwd (void)
cygwait (get_ttyp ()->fwd_done, INFINITE);
}
+void
+fhandler_pty_slave::wait_pcon_fwd2 (void)
+{
+ const int sleep_in_pcon = 16;
+ const int time_to_wait = sleep_in_pcon * 2 + 1/* margine */;
+ get_ttyp ()->pcon_last_time = GetTickCount ();
+ while (GetTickCount () - get_ttyp ()->pcon_last_time < time_to_wait)
+ {
+ int tw = time_to_wait - (GetTickCount () - get_ttyp ()->pcon_last_time);
+ cygwait (tw);
+ }
+}
+
void
fhandler_pty_slave::trigger_redraw_screen (void)
{
@@ -3270,6 +3361,8 @@ fhandler_pty_master::pty_master_fwd_thread ()
Sleep (1);
}
}
+ if (USE_PCON_MODE2)
+ get_ttyp ()->pcon_last_time = GetTickCount ();
if (!ReadFile (from_slave, outbuf, sizeof outbuf, &rlen, NULL))
{
termios_printf ("ReadFile for forwarding failed, %E");
@@ -3277,8 +3370,9 @@ fhandler_pty_master::pty_master_fwd_thread ()
}
ssize_t wlen = rlen;
char *ptr = outbuf;
- if (get_pseudo_console ())
+ if (get_pseudo_console () || get_ttyp ()->h_pseudo_console2)
{
+#if !USE_PCON_MODE2
/* Avoid duplicating slave output which is already sent to
to_master_cyg */
if (!get_ttyp ()->switch_to_pcon_out)
@@ -3331,6 +3425,7 @@ fhandler_pty_master::pty_master_fwd_thread ()
rlen -= 4;
}
wlen = rlen;
+#endif /* USE_PCON_MODE2 */
size_t nlen;
char *buf = convert_mb_str
@@ -3700,7 +3795,10 @@ fhandler_pty_master::setup ()
t.winsize.ws_col = 80;
t.winsize.ws_row = 25;
- setup_pseudoconsole ();
+ if (!USE_PCON_MODE2)
+ setup_pseudoconsole ();
+ else
+ CreatePipe (&from_master, &to_slave, &sec_none, 0);
t.set_from_master (from_master);
t.set_from_master_cyg (from_master_cyg);
@@ -3862,3 +3960,126 @@ fhandler_pty_common::process_opost_output (HANDLE h, const void *ptr, ssize_t& l
len -= towrite;
return res;
}
+
+bool
+fhandler_pty_slave::setup_pseudoconsole2 (STARTUPINFOEXW *si)
+{
+ if (USE_PCON_MODE2)
+ {
+ fhandler_base *fh = (fhandler_pty_slave *) ::cygheap->fdtab[0];
+ if (fh && fh->get_major () == DEV_PTYS_MAJOR)
+ {
+ fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
+ ptys->get_ttyp ()->switch_to_pcon_in = true;
+ if (ptys->get_ttyp ()->pcon_pid == 0 ||
+ !pinfo (ptys->get_ttyp ()->pcon_pid))
+ ptys->get_ttyp ()->pcon_pid = myself->pid;
+ }
+ }
+ if (!USE_PCON_MODE2)
+ return false;
+ if (disable_pcon)
+ return false;
+ /* If the legacy console mode is enabled, pseudo console seems
+ not to work as expected. To determine console mode, registry
+ key ForceV2 in HKEY_CURRENT_USER\Console is checked. */
+ reg_key reg (HKEY_CURRENT_USER, KEY_READ, L"Console", NULL);
+ if (reg.error ())
+ return false;
+ if (reg.get_dword (L"ForceV2", 1) == 0)
+ {
+ termios_printf ("Pseudo console is disabled "
+ "because the legacy console mode is enabled.");
+ return false;
+ }
+
+ COORD size = {
+ (SHORT) get_ttyp ()->winsize.ws_col,
+ (SHORT) get_ttyp ()->winsize.ws_row
+ };
+ SetLastError (ERROR_SUCCESS);
+ HRESULT res = CreatePseudoConsole (size, get_handle (), get_output_handle (),
+ 1, &get_ttyp ()->h_pseudo_console2);
+ if (res != S_OK || GetLastError () == ERROR_PROC_NOT_FOUND)
+ {
+ if (res != S_OK)
+ system_printf ("CreatePseudoConsole() failed. %08x %08x\n",
+ GetLastError (), res);
+ goto fallback;
+ }
+
+ SIZE_T bytesRequired;
+ InitializeProcThreadAttributeList (NULL, 1, 0, &bytesRequired);
+ ZeroMemory (si, sizeof (*si));
+ si->StartupInfo.cb = sizeof (STARTUPINFOEXW);
+ si->lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)
+ HeapAlloc (GetProcessHeap (), 0, bytesRequired);
+ if (si->lpAttributeList == NULL)
+ goto cleanup_pseudo_console;
+ if (!InitializeProcThreadAttributeList (si->lpAttributeList,
+ 1, 0, &bytesRequired))
+ goto cleanup_heap;
+ if (!UpdateProcThreadAttribute (si->lpAttributeList,
+ 0,
+ PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
+ get_ttyp ()->h_pseudo_console2,
+ sizeof (get_ttyp ()->h_pseudo_console2),
+ NULL, NULL))
+ goto cleanup_heap;
+ si->StartupInfo.dwFlags = STARTF_USESTDHANDLES;
+ si->StartupInfo.hStdInput = NULL;
+ si->StartupInfo.hStdOutput = NULL;
+ si->StartupInfo.hStdError = NULL;
+
+ {
+ fhandler_pty_slave *p0 = (fhandler_pty_slave *) ::cygheap->fdtab[0];
+ if (p0 && p0->get_device () != get_device ())
+ si->StartupInfo.hStdInput = p0->get_handle ();
+ fhandler_pty_slave *p1 = (fhandler_pty_slave *) ::cygheap->fdtab[1];
+ if (p1 && p1->get_device () != get_device ())
+ si->StartupInfo.hStdOutput = p1->get_output_handle ();
+ fhandler_pty_slave *p2 = (fhandler_pty_slave *) ::cygheap->fdtab[2];
+ if (p2 && p2->get_device () != get_device ())
+ si->StartupInfo.hStdError = p2->get_output_handle ();
+ }
+
+ if (get_ttyp ()->pcon_pid == 0 || !pinfo (get_ttyp ()->pcon_pid))
+ get_ttyp ()->pcon_pid = myself->pid;
+
+ if (get_ttyp ()->h_pseudo_console2 && get_ttyp ()->pcon_pid == myself->pid)
+ {
+ HPCON_INTERNAL *hp = (HPCON_INTERNAL *) get_ttyp ()->h_pseudo_console2;
+ get_ttyp ()->h_pcon_write_pipe = hp->hWritePipe;
+ }
+ get_ttyp ()->pcon2_start = true;
+ return true;
+
+cleanup_heap:
+ HeapFree (GetProcessHeap (), 0, si->lpAttributeList);
+cleanup_pseudo_console:
+ if (get_ttyp ()->h_pseudo_console2)
+ {
+ HPCON_INTERNAL *hp = (HPCON_INTERNAL *) get_ttyp ()->h_pseudo_console2;
+ HANDLE tmp = hp->hConHostProcess;
+ ClosePseudoConsole (get_ttyp ()->h_pseudo_console2);
+ CloseHandle (tmp);
+ }
+fallback:
+ get_ttyp ()->h_pseudo_console2 = NULL;
+ return false;
+}
+
+void
+fhandler_pty_slave::close_pseudoconsole2 (void)
+{
+ if (get_ttyp ()->h_pseudo_console2)
+ {
+ HPCON_INTERNAL *hp = (HPCON_INTERNAL *) get_ttyp ()->h_pseudo_console2;
+ HANDLE tmp = hp->hConHostProcess;
+ ClosePseudoConsole (get_ttyp ()->h_pseudo_console2);
+ CloseHandle (tmp);
+ get_ttyp ()->h_pseudo_console2 = NULL;
+ get_ttyp ()->switch_to_pcon_in = false;
+ get_ttyp ()->pcon_pid = 0;
+ }
+}
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 3e8c8367a..514125072 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -194,6 +194,24 @@ handle (int fd, bool writing)
return h;
}
+static bool
+is_console_app (WCHAR *filename)
+{
+ HANDLE h;
+ const int id_offset = 92;
+ h = CreateFileW (filename, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ char buf[1024];
+ DWORD n;
+ ReadFile (h, buf, sizeof (buf), &n, 0);
+ CloseHandle (h);
+ char *p = (char *) memmem (buf, n, "PE\0\0", 4);
+ if (p && p + id_offset <= buf + n)
+ return p[id_offset] == '\003'; /* 02: GUI, 03: console */
+ else
+ return false;
+}
+
int
iscmd (const char *argv0, const char *what)
{
@@ -583,6 +601,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
/* Attach to pseudo console if pty salve is used */
pid_restore = fhandler_console::get_console_process_id
(GetCurrentProcessId (), false);
+ fhandler_pty_slave *ptys_primary = NULL;
for (int i = 0; i < 3; i ++)
{
const int chk_order[] = {1, 0, 2};
@@ -591,6 +610,8 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
if (fh && fh->get_major () == DEV_PTYS_MAJOR)
{
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
+ if (ptys_primary == NULL)
+ ptys_primary = ptys;
if (ptys->get_pseudo_console ())
{
DWORD helper_process_id = ptys->get_helper_process_id ();
@@ -632,6 +653,18 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
if (!iscygwin ())
init_console_handler (myself->ctty > 0);
+ bool use_pcon_mode2 = false;
+ STARTUPINFOEXW si_pcon;
+ ZeroMemory (&si_pcon, sizeof (si_pcon));
+ STARTUPINFOW *si_tmp = &si;
+ if (!iscygwin () && ptys_primary && is_console_app (runpath))
+ if (ptys_primary->setup_pseudoconsole2 (&si_pcon))
+ {
+ c_flags |= EXTENDED_STARTUPINFO_PRESENT;
+ si_tmp = &si_pcon.StartupInfo;
+ use_pcon_mode2 = true;
+ }
+
loop:
/* When ruid != euid we create the new process under the current original
account and impersonate in child, this way maintaining the different
@@ -660,7 +693,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
c_flags,
envblock, /* environment */
NULL,
- &si,
+ si_tmp,
&pi);
}
else
@@ -714,7 +747,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
c_flags,
envblock, /* environment */
NULL,
- &si,
+ si_tmp,
&pi);
if (hwst)
{
@@ -727,6 +760,11 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
CloseDesktop (hdsk);
}
}
+ if (use_pcon_mode2)
+ {
+ DeleteProcThreadAttributeList (si_pcon.lpAttributeList);
+ HeapFree (GetProcessHeap (), 0, si_pcon.lpAttributeList);
+ }
if (mode != _P_OVERLAY)
SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT,
@@ -897,6 +935,12 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
&& WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
wait_for_myself ();
}
+ if (use_pcon_mode2)
+ {
+ WaitForSingleObject (pi.hProcess, INFINITE);
+ ptys_primary->wait_pcon_fwd2 ();
+ ptys_primary->close_pseudoconsole2 ();
+ }
myself.exit (EXITCODE_NOSET);
break;
case _P_WAIT:
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index 0663dc5ee..9bc1457d1 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -250,6 +250,8 @@ tty::init ()
pcon_in_empty = true;
req_transfer_input_to_pcon = false;
req_flush_pcon_input = false;
+ h_pseudo_console2 = NULL;
+ pcon2_start = false;
}
HANDLE
diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h
index a24afad06..a7546715e 100644
--- a/winsup/cygwin/tty.h
+++ b/winsup/cygwin/tty.h
@@ -111,6 +111,9 @@ private:
bool pcon_in_empty;
bool req_transfer_input_to_pcon;
bool req_flush_pcon_input;
+ HPCON h_pseudo_console2;
+ HANDLE h_pcon_write_pipe;
+ bool pcon2_start;
public:
HANDLE from_master () const { return _from_master; }
next prev parent reply other threads:[~2020-05-19 13:40 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-13 12:16 Takashi Yano
2020-05-13 12:35 ` Thomas Wolff
2020-05-14 9:28 ` Takashi Yano
2020-05-14 9:34 ` Takashi Yano
2020-05-16 0:29 ` Takashi Yano
2020-05-16 7:47 ` Takashi Yano
2020-05-19 13:40 ` Takashi Yano [this message]
2020-05-25 10:53 ` Takashi Yano
2020-05-25 15:22 ` Corinna Vinschen
2020-05-25 19:16 ` Thomas Wolff
2020-05-26 1:00 ` Takashi Yano
2020-05-26 7:14 ` Thomas Wolff
2020-05-26 9:21 ` Takashi Yano
2020-05-26 9:32 ` Thomas Wolff
2020-05-26 8:33 ` Corinna Vinschen
2020-05-26 1:09 ` Takashi Yano
2020-05-28 15:40 ` Takashi Yano
2020-05-29 15:30 ` Corinna Vinschen
2020-05-30 7:36 ` Takashi Yano
2020-05-30 13:14 ` Takashi Yano
2020-05-30 17:43 ` Corinna Vinschen
2020-05-31 5:52 ` Takashi Yano
2020-07-01 11:47 ` Takashi Yano
2020-07-17 11:19 ` Corinna Vinschen
2020-07-17 12:47 ` Thomas Wolff
2020-07-17 14:59 ` Thomas Wolff
2020-07-18 5:05 ` Takashi Yano
2020-07-18 20:57 ` Thomas Wolff
2020-07-23 17:17 ` Takashi Yano
2020-07-27 17:10 ` Thomas Wolff
2020-07-17 12:52 ` Ken Brown
2020-07-18 5:07 ` Takashi Yano
2020-07-18 5:30 ` Takashi Yano
2020-07-20 8:06 ` Corinna Vinschen
2020-07-21 18:17 ` Takashi Yano
2020-07-22 8:45 ` Takashi Yano
2020-07-22 11:49 ` Corinna Vinschen
2020-07-22 12:13 ` Ken Brown
2020-07-23 0:33 ` Takashi Yano
2020-07-24 5:38 ` Takashi Yano
2020-07-24 11:22 ` Takashi Yano
2020-08-02 12:01 ` Corinna Vinschen
2020-08-03 2:05 ` Takashi Yano
2020-08-03 10:50 ` Corinna Vinschen
2020-08-03 2:11 ` Takashi Yano
2020-08-03 12:23 ` Takashi Yano
2020-08-11 11:12 ` Takashi Yano
2020-08-13 9:58 ` Takashi Yano
2020-08-17 11:57 ` Takashi Yano
2020-08-19 11:39 ` Takashi Yano
2020-08-19 13:41 ` Corinna Vinschen
2020-08-19 15:43 ` Thomas Wolff
2020-08-19 20:47 ` Mark Geisert
2020-08-20 8:02 ` Takashi Yano
2020-08-31 12:49 ` Johannes Schindelin
2020-08-31 14:14 ` Takashi Yano
[not found] ` <20200831231253.332c66fdddb33ceed5f61db6@nifty.ne.jp>
2020-08-31 14:22 ` Johannes Schindelin
2020-08-31 14:53 ` Takashi Yano
2020-08-31 15:56 ` Johannes Schindelin
2020-08-31 16:12 ` Thomas Wolff
2020-08-31 17:39 ` Thomas Wolff
2020-08-31 19:17 ` Johannes Schindelin
2020-08-31 19:37 ` Corinna Vinschen
2020-09-01 4:46 ` Johannes Schindelin
2020-09-01 9:23 ` Takashi Yano
2020-09-01 6:32 ` Johannes Schindelin
2020-09-01 22:33 ` Takashi Yano
2020-09-02 6:13 ` Johannes Schindelin
2020-09-01 9:42 ` Takashi Yano
2020-08-31 21:07 ` Thomas Wolff
2020-08-31 23:23 ` Takashi Yano
2020-09-01 5:00 ` Johannes Schindelin
2020-09-01 8:56 ` Thomas Wolff
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200519224018.746f6324badd8a5762df42b1@nifty.ne.jp \
--to=takashi.yano@nifty.ne.jp \
--cc=cygwin-developers@cygwin.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).