/* Replacement termios functions for MinGW32. These versions of termios functions serialize over a pipe to another process, which adjusts the terminal. Copyright (C) 2008 CodeSourcery, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include "mingw-termios.h" static HANDLE pipe_handle = INVALID_HANDLE_VALUE; static HANDLE pipe_mutex = INVALID_HANDLE_VALUE; static int link_to_wrapper (void) { static int tried = 0; if (!tried) { char pipe_name[256]; tried = 1; /* Connect to the named pipe for communication with the wrapper. */ sprintf (pipe_name, "\\\\.\\pipe\\gdb_wrapper_%ld", GetCurrentProcessId ()); pipe_handle = CreateFile (pipe_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (pipe_handle != INVALID_HANDLE_VALUE) pipe_mutex = CreateMutex (NULL, TRUE, NULL); } else if (pipe_mutex != INVALID_HANDLE_VALUE) WaitForSingleObject (pipe_mutex, INFINITE); return (pipe_handle != INVALID_HANDLE_VALUE); } static int cygming_wrapper_cmd (const char *cmd, const void *args, int arglen, int *ret, char **retdata) { if (link_to_wrapper ()) { static char buf[4096] = {0}; int len = strlen (cmd) + 1; DWORD read; DWORD written; memcpy (buf, cmd, len); memcpy (buf + len, args, arglen); //fprintf (stderr, "%.8lx writing to the wrapper\n", GetCurrentThreadId ()); if (!WriteFile (pipe_handle, buf, len + arglen, &written, NULL)) { fprintf (stderr, "error writting to cygming wrapper: %ld\n", GetLastError ()); fflush (stderr); ReleaseMutex (pipe_mutex); return 0; } if (!ReadFile (pipe_handle, buf, sizeof (buf), &read, NULL)) { fprintf (stderr, "error waiting for cygming wrapper response: %ld", GetLastError ()); fflush (stderr); ReleaseMutex (pipe_mutex); return 0; } //fprintf (stderr, "%.8lx finished read from the wrapper\n", GetCurrentThreadId ()); /* The returned value should be "OK" ';' . */ if (memcmp (buf, "OK", 2) != 0) { fprintf (stderr, "error: unexpected wrapper response: %s\n", buf); fflush (stderr); ReleaseMutex (pipe_mutex); return 0; } *ret = strtol (buf + 2, retdata, 0); (*retdata)++; ReleaseMutex (pipe_mutex); return 1; } else return 0; } int tcgetattr (int fd, struct termios *buf) { int ret; char *retdata; if (cygming_wrapper_cmd ("tcgetattr", "", 0, &ret, &retdata)) { if (ret == 0) memcpy (buf, retdata, sizeof (*buf)); else errno = EINVAL; return ret; } else { memset (buf, 0, sizeof (*buf)); /* If FD is a TTY, readline will use getch for it, so we will must echo manually - getch does not echo. If it is not a TTY, we must not echo since we have no way to disable the typical echo. */ if (isatty (fd)) buf->c_lflag = ECHO; return 0; } } int tcsetattr (int fd, int actions, const struct termios *buf) { int ret; char *retdata; if (cygming_wrapper_cmd ("tcsetattr", buf, sizeof (*buf), &ret, &retdata)) { if (ret != 0) errno = EINVAL; return ret; } else { errno = EINVAL; return -1; } } int tcdrain (int fd) { int ret; char *retdata; if (cygming_wrapper_cmd ("tcdrain", "", 0, &ret, &retdata)) { if (ret != 0) errno = EINVAL; return ret; } else { errno = EINVAL; return -1; } } int tcflow (int fd, int action) { errno = ENOTTY; return -1; } int mingw_getwinsize (struct winsize *window_size) { int ret; char *retdata; if (cygming_wrapper_cmd ("getwinsize", "", 0, &ret, &retdata)) { if (ret == 0) memcpy (window_size, retdata, sizeof (*window_size)); else errno = EINVAL; return ret; } else { errno = EINVAL; return -1; } }