Re: dynamic conpty loading

Takashi Yano via Cygwin <[email protected]>
Newsgroups gmane.os.cygwin
Message-ID <[email protected]>
On Thu, 27 Nov 2025 17:20:26 +0900
Takashi Yano via Cygwin <[email protected]> wrote:
> On Wed, 26 Nov 2025 19:50:07 +0100
> Thomas Wolff wrote:
> > 
> > Am 26.11.2025 um 11:32 schrieb Takashi Yano via Cygwin:
> > > On Fri, 21 Nov 2025 17:58:01 +0100
> > > Thomas Wolff wrote:
> > >
> > >> Am 21.11.2025 um 17:46 schrieb Corinna Vinschen via Cygwin:
> > >>> Hi Thomas,
> > >>>
> > >>> On Nov 21 16:46, Thomas Wolff via Cygwin wrote:
> > >>>> Am 21.11.2025 um 11:04 schrieb Takashi Yano via Cygwin:
> > >>>>> On Sun, 5 Oct 2025 10:15:55 +0200
> > >>>>> Thomas Wolff wrote:
> > >>>>>>>> The procedure seems to be:
> > >>>>>>>> try LoadLibrary("conpty.dll"), (if not successful, fallback to
> > >>>>>>>> GetModuleHandle("kernel32") instead) to retrieve GetProcAddress for
> > >>>>>>>> CreatePseudoConsole, ResizePseudoConsole, ClosePseudoConsole, and
> > >>>>>>>> then somehow (?) use those while calling CreateProcess.
> > >>>>>>>> The latter is woven into the cygwin library and I don't think it's a
> > >>>>>>>> good idea to clone that out of cygwin for a patched process creation
> > >>>>>>>> in mintty.
> > >>>>>>>>
> > >>>>>>>> My question/suggestion:
> > >>>>>>>> Can a cygwin mode switch to a selected conpty library instead of the
> > >>>>>>>> default one please?
> > >>> Where do you expect this conpty.dll to reside?
> > >>>
> > >>> If we do something like that, I would suggest to make sure that this
> > >>> conpty.dll is in a well-defined place. /bin or /lib might be a good
> > >>> idea. And if it exists in this defined place, it will be used by Cygwin.
> > >>>
> > >>> We can tweak the autoload mechanism to allow a primary DLL and a fallback
> > >>> DLL, that drops the need to set the CYWIN env var.
> > >>>
> > >>> The mintty package could contain a post-install script, or some other
> > >>> script in /bin to allow a user with admin rights downloading the latest
> > >>> (or the most sensible) conpty.dll from MSFT.
> > >>>
> > >>> Would that make sense?
> > >>>
> > >>>
> > >>> Corinna
> > >>>
> > >> That makes much sense, yes, thank you. /bin/conpty.dll would probably be
> > >> a good place.
> > > I checked the source of conpty.dll
> > > https://github.com/microsoft/terminal/blob/main/src/winconpty/winconpty.cpp
> > >
> > > conpty.dll seems to launch OpenConsole.exe in the directory where
> > > WindowsTerminal is installed.
> > > However, BUILTIN\Users does not have permission to execute OpenConsole.exe.
> > >
> > > Do you have some idea how to solve this problem?
> > > WindowsTerminal itself can launch OpenConsole.exe, so there should be
> > > some solutions, I think.
> > Did you install the nuget package? It can be extracted with zip, so you 
> > can install OpenConsole as a normal program...
> > I did not find a way, though, to invoke it explicitly so that it would 
> > solve the pty interworking problems.
> 
> Thanks.
> 
> I've made an experimental patch against fhandler/pty.cc and
> draft package named openconsole that installs official OpenConsole.exe
> binary into /usr/bin.
> 
> I confirmed the patch with openconsole package enables the mouse
> support for vim91 and neovim 0.8.0 (native windows binary) in
> pseudo console.

pty patch and openconsole package files are revised.

> Any comments and suggestions would be appreciated.


-- 
Takashi Yano <[email protected]>


-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple
v2-0001-Cygwin-pty-Experimental-OpenConsole.exe-support.patch (text/plain, 13.1 KB)
From 28570bd464446eb327b588b623f70f8cf8f46b3d Mon Sep 17 00:00:00 2001
From: Takashi Yano <[email protected]>
Date: Thu, 27 Nov 2025 15:52:12 +0900
Subject: [PATCH v2] Cygwin: pty: Experimental OpenConsole.exe support

Signed-off-by: Takashi Yano <[email protected]>
---
 winsup/cygwin/fhandler/pty.cc | 281 ++++++++++++++++++++++++++++++----
 1 file changed, 251 insertions(+), 30 deletions(-)

diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
index 679068ea2..2c9af1742 100644
--- a/winsup/cygwin/fhandler/pty.cc
+++ b/winsup/cygwin/fhandler/pty.cc
@@ -33,6 +33,136 @@ details. */
 #define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE 0x00020016
 #endif /* PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE */
 
+static NTSTATUS
+create_handle (PHANDLE handle, PCWSTR device_name,
+	       ACCESS_MASK desired_access, HANDLE parent,
+	       BOOLEAN inheritable, ULONG open_options)
+{
+  ULONG flags = OBJ_CASE_INSENSITIVE;
+  if (inheritable)
+    flags |= OBJ_INHERIT;
+
+  UNICODE_STRING name;
+  RtlInitUnicodeString (&name, device_name);
+
+  OBJECT_ATTRIBUTES object_attributes;
+  InitializeObjectAttributes (&object_attributes, &name, flags, parent, NULL);
+
+  IO_STATUS_BLOCK io;
+  return NtOpenFile (handle, desired_access, &object_attributes, &io,
+		     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+		     open_options);
+}
+
+extern "C" WINBASEAPI HRESULT WINAPI
+CreatePseudoConsole_new (COORD size, HANDLE h_input, HANDLE h_output,
+			 DWORD flags, HPCON *hpcon)
+{
+
+  HANDLE h_con_server, h_con_reference;
+  NTSTATUS status;
+  BOOL res;
+  HANDLE h_read_pipe, h_write_pipe;
+  BOOL inherit_cursor;
+  path_conv conhost ("/usr/bin/OpenConsole.exe");
+  size_t len;
+  HANDLE inherited_handles[4];
+  STARTUPINFOEXW si = {0, };
+  PROCESS_INFORMATION pi;
+  SIZE_T list_size = 0;
+  LPPROC_THREAD_ATTRIBUTE_LIST attr_list;
+  HPCON_INTERNAL *hpcon_internal;
+
+  status = create_handle (&h_con_server, L"\\Device\\ConDrv\\Server",
+			  GENERIC_ALL, NULL, TRUE, 0);
+  if (!NT_SUCCESS (status))
+    goto cleanup;
+  status = create_handle (&h_con_reference, L"\\Reference",
+			 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
+			 h_con_server, FALSE, FILE_SYNCHRONOUS_IO_NONALERT);
+  if (!NT_SUCCESS (status))
+    goto cleanup_h_con_server;
+
+  res = CreatePipe (&h_read_pipe, &h_write_pipe, &sec_none, 0);
+  if (!res)
+    goto cleanup_h_con_reference;
+  res = SetHandleInformation (h_read_pipe,
+			      HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
+  if (!res)
+    goto cleanup_pipe;
+
+  inherit_cursor = (flags & PSEUDOCONSOLE_INHERIT_CURSOR) ? TRUE : FALSE;
+
+  WCHAR cmd[MAX_PATH];
+  len = conhost.get_wide_win32_path_len ();
+  conhost.get_wide_win32_path (cmd);
+  __small_swprintf (cmd + len,
+		    L" --headless %W"
+		    "--width %d --height %d --signal 0x%x --server 0x%x",
+		    inherit_cursor ? L"--inheritcursor " : L"",
+		    size.X, size.Y, h_read_pipe, h_con_server);
+
+  si.StartupInfo.cb = sizeof (STARTUPINFOEXW);
+  si.StartupInfo.hStdInput = h_input;
+  si.StartupInfo.hStdOutput = h_output;
+  si.StartupInfo.hStdError = h_output;
+  si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
+
+  inherited_handles[0] = h_con_server;
+  inherited_handles[1] = h_input;
+  inherited_handles[2] = h_output;
+  inherited_handles[3] = h_read_pipe;
+
+  InitializeProcThreadAttributeList (NULL, 1, 0, &list_size);
+  attr_list =
+    (LPPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc (GetProcessHeap (), 0, list_size);
+  if (!attr_list)
+    goto cleanup_pipe;
+
+  si.lpAttributeList = attr_list;
+  InitializeProcThreadAttributeList (si.lpAttributeList, 1, 0, &list_size);
+  UpdateProcThreadAttribute (si.lpAttributeList, 0,
+			     PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
+			     inherited_handles, sizeof (inherited_handles),
+			     NULL, NULL);
+
+
+  res = CreateProcessW (NULL, cmd, NULL, NULL,
+			TRUE, EXTENDED_STARTUPINFO_PRESENT,
+			NULL, NULL, &si.StartupInfo, &pi);
+  if (!res)
+    goto cleanup_heap;
+
+  hpcon_internal = (HPCON_INTERNAL *)
+    HeapAlloc (GetProcessHeap (), 0, sizeof (HPCON_INTERNAL));
+  if (!hpcon_internal)
+    goto cleanup_heap;
+  hpcon_internal->hWritePipe = h_write_pipe;
+  hpcon_internal->hConDrvReference = h_con_reference;
+  hpcon_internal->hConHostProcess = pi.hProcess;
+  *hpcon = (HPCON) hpcon_internal;
+
+  HeapFree (GetProcessHeap(), 0, attr_list);
+  CloseHandle (h_con_server);
+  CloseHandle (pi.hThread);
+  CloseHandle (pi.hProcess);
+
+  return S_OK;
+
+cleanup_heap:
+  HeapFree (GetProcessHeap(), 0, attr_list);
+cleanup_pipe:
+  CloseHandle (h_read_pipe);
+  CloseHandle (h_write_pipe);
+cleanup_h_con_reference:
+  CloseHandle (h_con_reference);
+cleanup_h_con_server:
+  CloseHandle (h_con_server);
+cleanup:
+  return E_FAIL;
+}
+
+
 extern "C" int sscanf (const char *, const char *, ...);
 
 #define close_maybe(h) \
@@ -2136,6 +2266,8 @@ fhandler_pty_master::close (int flag)
 ssize_t
 fhandler_pty_master::write (const void *ptr, size_t len)
 {
+  size_t towrite = len;
+
   ssize_t ret;
   char *p = (char *) ptr;
   termios &ti = tc ()->ti;
@@ -2152,7 +2284,7 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 	 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 = strlen ("\033[32768;32868R");
+      static const int wpbuf_len = 64; /* for response to CSI6n nad CSIc */
       static char wpbuf[wpbuf_len];
       static int ixput = 0;
       static int state = 0;
@@ -2170,6 +2302,7 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 	    }
 	  if (state == 1)
 	    {
+	      towrite--;
 	      if (ixput < wpbuf_len)
 		wpbuf[ixput++] = p[i];
 	      else
@@ -2181,21 +2314,27 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 		}
 	    }
 	  else
-	    line_edit (p + i, 1, ti, &ret);
-	  if (state == 1 && p[i] == 'R')
+	    {
+	      if (ixput)
+		line_edit (wpbuf, ixput, ti, &ret);
+	      get_ttyp ()->pcon_start = false;
+	      ptr = p + i;
+	      break;
+	    }
+	  if (state == 1 && isalpha(p[i]))
 	    state = 2;
-	}
-      if (state == 2)
-	{
-	  /* req_xfer_input is true if "ESC[6n" was sent just for
-	     triggering transfer_input() in master. In this case,
-	     the responce sequence should not be written. */
-	  if (!get_ttyp ()->req_xfer_input)
-	    WriteFile (to_slave_nat, wpbuf, ixput, &n, NULL);
-	  ixput = 0;
-	  state = 0;
-	  get_ttyp ()->req_xfer_input = false;
-	  get_ttyp ()->pcon_start = false;
+	  if (state == 2)
+	    {
+	      /* req_xfer_input is true if "ESC[6n" was sent just for
+		 triggering transfer_input() in master. In this case,
+		 the responce sequence should not be written. */
+	      if (!get_ttyp ()->req_xfer_input)
+		WriteFile (to_slave_nat, wpbuf, ixput, &n, NULL);
+	      if (p[i] == 'R')
+		get_ttyp ()->req_xfer_input = false;
+	      ixput = 0;
+	      state = 0;
+	    }
 	}
       ReleaseMutex (input_mutex);
 
@@ -2219,8 +2358,8 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 	    }
 	  get_ttyp ()->pcon_start_pid = 0;
 	}
-
-      return len;
+      if (towrite == 0)
+	return len;
     }
 
   /* Write terminal input to to_slave_nat pipe instead of output_handle
@@ -2232,14 +2371,14 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 	 is activated. */
       tmp_pathbuf tp;
       char *buf = (char *) ptr;
-      size_t nlen = len;
+      size_t nlen = towrite;
       if (get_ttyp ()->term_code_page != CP_UTF8)
 	{
 	  static mbstate_t mbp;
 	  buf = tp.c_get ();
 	  nlen = NT_MAX_PATH;
 	  convert_mb_str (CP_UTF8, buf, &nlen,
-			  get_ttyp ()->term_code_page, (const char *) ptr, len,
+			  get_ttyp ()->term_code_page, (const char *) ptr, nlen,
 			  &mbp);
 	}
 
@@ -2255,8 +2394,50 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 	    }
 	}
 
+      char *bs_pos = (char *) memchr (buf, '\010' /* ^H */, nlen);
+      HANDLE pcon_owner = NULL;
+      HANDLE h_pcon_in = NULL;
+      DWORD resume_pid = 0;
+      if (bs_pos)
+	{
+	  pcon_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
+				    get_ttyp ()->nat_pipe_owner_pid);
+	  DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in,
+			   GetCurrentProcess (), &h_pcon_in,
+			   0, FALSE, DUPLICATE_SAME_ACCESS);
+	  resume_pid =
+	    attach_console_temporarily (get_ttyp()->nat_pipe_owner_pid);
+	}
+
       DWORD n;
-      WriteFile (to_slave_nat, buf, nlen, &n, NULL);
+      while (bs_pos)
+	{
+	  if (bs_pos - buf > 0)
+	    WriteFile (to_slave_nat, buf, bs_pos - buf, &n, NULL);
+	  INPUT_RECORD r;
+	  r.EventType = KEY_EVENT;
+	  r.Event.KeyEvent.bKeyDown = 1;
+	  r.Event.KeyEvent.wRepeatCount = 0;
+	  r.Event.KeyEvent.wVirtualKeyCode = 0;
+	  r.Event.KeyEvent.wVirtualScanCode = 0;
+	  r.Event.KeyEvent.uChar.AsciiChar = '\010'; /* ^H */
+	  r.Event.KeyEvent.dwControlKeyState = LEFT_CTRL_PRESSED;
+	  WriteConsoleInput(h_pcon_in, &r, 1, &n);
+	  r.Event.KeyEvent.bKeyDown = 0;
+	  WriteConsoleInput(h_pcon_in, &r, 1, &n);
+	  nlen -= bs_pos - buf + 1;
+	  buf = bs_pos + 1;
+	  bs_pos = (char *) memchr (buf, '\010' /* ^H */, nlen);
+	}
+      if (nlen > 0)
+	WriteFile (to_slave_nat, buf, nlen, &n, NULL);
+
+      if (resume_pid)
+	resume_from_temporarily_attach (resume_pid);
+      if (h_pcon_in)
+	CloseHandle(h_pcon_in);
+      if (pcon_owner)
+	CloseHandle(pcon_owner);
       ReleaseMutex (input_mutex);
 
       return len;
@@ -2302,11 +2483,30 @@ int
 fhandler_pty_master::tcgetattr (struct termios *t)
 {
   *t = cygwin_shared->tty[get_minor ()]->ti;
-  /* Workaround for rlwrap v0.40 or later */
-  if (get_ttyp ()->pcon_start)
-    t->c_lflag &= ~(ICANON | ECHO);
+
   if (get_ttyp ()->pcon_activated)
-    t->c_iflag &= ~ICRNL;
+    {
+      t->c_lflag &= ~(ICANON | ECHO);
+      t->c_iflag &= ~ICRNL;
+
+      HANDLE pcon_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
+				       get_ttyp ()->nat_pipe_owner_pid);
+      HANDLE h_pcon_in;
+      DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in,
+		       GetCurrentProcess (), &h_pcon_in,
+		       0, FALSE, DUPLICATE_SAME_ACCESS);
+      DWORD resume_pid =
+	attach_console_temporarily (get_ttyp()->nat_pipe_owner_pid);
+      DWORD mode;
+      GetConsoleMode (h_pcon_in, &mode);
+      resume_from_temporarily_attach (resume_pid);
+      CloseHandle (h_pcon_in);
+      CloseHandle (pcon_owner);
+      if (mode & ENABLE_LINE_INPUT)
+	t->c_lflag |= ICANON;
+      if (mode & ENABLE_ECHO_INPUT)
+	t->c_lflag |= ECHO;
+    }
   return 0;
 }
 
@@ -2680,7 +2880,7 @@ fhandler_pty_master::pty_master_fwd_thread (const master_fwd_thread_param_t *p)
 	  int state = 0;
 	  int start_at = 0;
 	  for (DWORD i=0; i<rlen; i++)
-	    if (outbuf[i] == '\033')
+	    if (state == 0 && outbuf[i] == '\033')
 	      {
 		start_at = i;
 		state = 1;
@@ -2688,12 +2888,14 @@ fhandler_pty_master::pty_master_fwd_thread (const master_fwd_thread_param_t *p)
 	      }
 	    else if ((state == 1 && outbuf[i] == ']') ||
 		     (state == 2 && outbuf[i] == '0') ||
-		     (state == 3 && outbuf[i] == ';'))
+		     (state == 3 && outbuf[i] == ';') ||
+		     (state == 4 && outbuf[i] == '\033'))
 	      {
 		state ++;
 		continue;
 	      }
-	    else if (state == 4 && outbuf[i] == '\a')
+	    else if ((state == 4 && outbuf[i] == '\a')
+		     || (state == 5 && outbuf[i] == '\\'))
 	      {
 		const char *helper_str = "\\bin\\cygwin-console-helper.exe";
 		if (memmem (&outbuf[start_at], i + 1 - start_at,
@@ -3268,9 +3470,14 @@ fhandler_pty_slave::setup_pseudoconsole ()
       const DWORD inherit_cursor = 1;
       hpcon = NULL;
       SetLastError (ERROR_SUCCESS);
-      HRESULT res = CreatePseudoConsole (size, get_handle_nat (),
-					 get_output_handle_nat (),
-					 inherit_cursor, &hpcon);
+      /* Try OpenConsole.exe before conhost.exe */
+      HRESULT res = CreatePseudoConsole_new (size, get_handle_nat (),
+					     get_output_handle_nat (),
+					     inherit_cursor, &hpcon);
+      if (res != S_OK) /* Fallback to legacy conhost.exe */
+        res = CreatePseudoConsole (size, get_handle_nat (),
+				   get_output_handle_nat (),
+				   inherit_cursor, &hpcon);
       if (res != S_OK || GetLastError () == ERROR_PROC_NOT_FOUND)
 	{
 	  if (res != S_OK)
@@ -3627,6 +3834,20 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to)
 	  ttyp->nat_pipe_owner_pid = 0;
 	  ttyp->pcon_start = false;
 	  ttyp->pcon_start_pid = 0;
+	  do
+	    {
+	      pinfo p (ttyp->master_pid);
+	      HANDLE pty_master = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
+					       p->dwProcessId);
+	      HANDLE to_master_nat;
+	      DuplicateHandle (pty_master, ttyp->to_master_nat (),
+			       GetCurrentProcess (), &to_master_nat,
+			       0, FALSE, DUPLICATE_SAME_ACCESS);
+	      WriteFile (to_master_nat, "\033[?1004l", 8, NULL, NULL);
+	      CloseHandle (to_master_nat);
+	      CloseHandle (pty_master);
+	    }
+	  while (false);
 	}
     }
   else
-- 
2.51.0
libopenconsole.postinstall (text/plain, 814 B)
if [ $(uname -m) = "x86_64" ]
then
	POSTFIX="x64"
else
	POSTFIX="x86"
fi
VERSION=$(cat /etc/libopenconsole/version.txt)
cd /tmp
wget -q https://github.com/microsoft/terminal/releases/download/v${VERSION}/Microsoft.WindowsTerminal_${VERSION}_${POSTFIX}.zip -O - > Microsoft.WindowsTerminal_${VERSION}_${POSTFIX}.tmp
if sha256sum --status -c /etc/libopenconsole/Microsoft.WindowsTerminal_${VERSION}_${POSTFIX}.zip.sha256
then
	mv Microsoft.WindowsTerminal_${VERSION}_${POSTFIX}.tmp Microsoft.WindowsTerminal_${VERSION}_${POSTFIX}.zip
	unzip -jq Microsoft.WindowsTerminal_${VERSION}_${POSTFIX}.zip '*/OpenConsole.exe'
	mv OpenConsole.exe /usr/bin/.
else
	# Hash mismatch (or failed to download)
	rm Microsoft.WindowsTerminal_${VERSION}_${POSTFIX}.tmp
	exit 1
fi
chmod a+x /usr/bin/OpenConsole.exe
libopenconsole.preremove (text/plain, 32 B)
rm -f /usr/bin/OpenConsole.exe
openconsole.cygport (text/plain, 1.4 KB)
NAME="openconsole"
VERSION=1.23.12811.0
RELEASE=1
CATEGORY="Libs"
SUMMARY="conhost.exe alternative"
DESCRIPTION="conhost.exe alternative for new features of pusedo console"
HOMEPAGE="https://github.com/microsoft/terminal/"
LICENSE="MIT"
ARCH="noarch" # This is noarch because it's just helper shell scrpits.
SRC_URI="${NAME}-${VERSION}.tar.xz"
CYGWIN_FILES="
	lib${NAME}.postinstall
	lib${NAME}.preremove
"

# Make dummy source file for prep
if [ ! -f ${SRC_URI} ]
then
	mkdir -p ${NAME}-${VERSION}
	tar acf ${SRC_URI} ${NAME}-${VERSION}
	rm -rf ${NAME}-${VERSION}
fi

PKG_NAMES="libopenconsole"
libopenconsole_CONTENTS="etc/"
libopenconsole_REQUIRES="wget unzip"

src_compile() {
	:
}

src_install() {
	mkdir -p ${D}/etc/lib${NAME}
	# Make sha256 hash
	wget -q https://github.com/microsoft/terminal/releases/download/v${VERSION}/Microsoft.WindowsTerminal_${VERSION}_x64.zip -O - | sha256sum | sed "s/-$/Microsoft.WindowsTerminal_${VERSION}_x64.tmp/" > ${D}/etc/lib${NAME}/Microsoft.WindowsTerminal_${VERSION}_x64.zip.sha256
	wget -q https://github.com/microsoft/terminal/releases/download/v${VERSION}/Microsoft.WindowsTerminal_${VERSION}_x86.zip -O - | sha256sum | sed "s/-$/Microsoft.WindowsTerminal_${VERSION}_x86.tmp/" > ${D}/etc/lib${NAME}/Microsoft.WindowsTerminal_${VERSION}_x86.zip.sha256
	# Make version text
	echo ${VERSION} > ${D}/etc/lib${NAME}/version.txt
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.