From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9055 invoked by alias); 26 Mar 2005 01:27:29 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 8714 invoked from network); 26 Mar 2005 01:27:05 -0000 Received: from unknown (HELO sethra.codesourcery.com) (65.74.133.9) by sourceware.org with SMTP; 26 Mar 2005 01:27:05 -0000 Received: from sethra.codesourcery.com (localhost.localdomain [127.0.0.1]) by sethra.codesourcery.com (8.12.11/8.12.11) with ESMTP id j2Q1R5cq022156 for ; Fri, 25 Mar 2005 17:27:05 -0800 Received: (from mitchell@localhost) by sethra.codesourcery.com (8.12.11/8.12.11/Submit) id j2Q1R59a022152; Fri, 25 Mar 2005 17:27:05 -0800 Date: Sat, 26 Mar 2005 01:27:00 -0000 Message-Id: <200503260127.j2Q1R59a022152@sethra.codesourcery.com> From: Mark Mitchell To: gdb-patches@sources.redhat.com Subject: PATCH: Windows sockets Reply-to: mark@codesourcery.com X-SW-Source: 2005-03/txt/msg00331.txt.bz2 Here's the first "interesting" patch for Windows support. This patch modifies ser-tcp.c to support Windows, so that we can use a GDB running on Windows to talk to a gdbserver process. Here is a sumary of the changes in this patch: 1. Link with -lws2_32 on MinGW so we can use sockets. 2. In defs.h, define WINAPI so that source files know whether they are supposed to use the Windows API. 3. Move ser_unix_readchar and friends (which were only barely UNIX-specific) into ser-base.c, renaming appropriately. 4. Add a new member (read_prim) to struct serial_ops, and use it from ser_base_readchar. The reason for this is that sockets must be read with "recv" on Windows; plain "read" does not work. So, we need a way to indicate which low-level primitive to use to read from a file descriptor. 5. Make a handful of minor changes to ter-tcp.c to account for differences in the BSD and Windows sockets APIs. 6. Tweak safe_strerror to deal with Windows sockets error codes. Tested on x86_64-unknown-linux-gnu, to make sure I didn't break UNIX, and cursorily on Windows (with other patches, not yet submitted). OK to apply? -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com 2005-03-25 Mark Mitchell * configure.ac: Link with -lws2_32 on mingw. * configure: Regenerated. * defs.h (WINAPI): Define, conditionally. * ser-base.c (winsock2.h): Include it. (fd_event): Use read_prim. (ser_base_wait_for): Moved here from ser-unix.c. (do_ser_base_readchar): Likewise. (generic_readchar): Likewise. (ser_base_readchar): Likewise. * ser-base.h (generic_readchar): Declare. (ser_base_readchar): Likewise. * ser-pipe.c (_initialize_ser_pipe): Adjust for name changes. * ser-tcp.c (winsock2.h): Include it. (ETIMEDOUT): Define on Windows. (closesocket): Define on UNIX. (ioctlsocket): Likewise. (net_open): Adjust for differences in socket functions between Windows and UNIX. (_initialize_ser_tcp): Adjust for name changes. (net_read_prim): New function. (net_write): Likewise. * ser-unix.c (generic_readchar): Remove. (ser_unix_wait_for): Likewise. (do_unix_readchar): Likewise. (ser_unix_readchar): Likewise. (_initialize_ser_hardwire): Adjust for name changes. (ser_unix_read_prim): New function. * ser-unix.h (ser_unix_readchar): Remove. (ser_unix_read_prim): Declare. * serial.h (struct serial_ops): Add read_prim. * utils.c (winerror.h): Include it. (safe_strerror): Handle winsock errors. Index: configure.ac =================================================================== RCS file: /cvs/src/src/gdb/configure.ac,v retrieving revision 1.17 diff -c -5 -p -r1.17 configure.ac *** configure.ac 25 Mar 2005 19:47:23 -0000 1.17 --- configure.ac 26 Mar 2005 01:00:29 -0000 *************** if test x$gdb_cv_os_cygwin = xyes; then *** 1185,1194 **** --- 1185,1201 ---- case "${target}" in *cygwin*) WIN32LIBS="$WIN32LIBS -limagehlp" ;; esac fi + + # The ser-tcp.c module requires sockets. + case ${host} in + *mingw32*) + WIN32LIBS="$WIN32LIBS -lwsock32" + ;; + esac AC_SUBST(WIN32LIBS) LIBGUI="../libgui/src/libgui.a" GUI_CFLAGS_X="-I${srcdir}/../libgui/src" AC_SUBST(LIBGUI) Index: defs.h =================================================================== RCS file: /cvs/src/src/gdb/defs.h,v retrieving revision 1.182 diff -c -5 -p -r1.182 defs.h *** defs.h 17 Mar 2005 22:11:09 -0000 1.182 --- defs.h 26 Mar 2005 01:00:29 -0000 *************** extern int use_windows; *** 1149,1158 **** --- 1149,1162 ---- #ifndef SLASH_STRING #define SLASH_STRING "/" #endif + #if defined(__WIN32__) && !defined(__CYGWIN__) + #define WINAPI + #endif + /* Provide default definitions of PIDGET, TIDGET, and MERGEPID. The name ``TIDGET'' is a historical accident. Many uses of TIDGET in the code actually refer to a lightweight process id, i.e, something that can be considered a process id in its own right for certain purposes. */ Index: ser-base.c =================================================================== RCS file: /cvs/src/src/gdb/ser-base.c,v retrieving revision 1.2 diff -c -5 -p -r1.2 ser-base.c *** ser-base.c 25 Mar 2005 20:06:36 -0000 1.2 --- ser-base.c 26 Mar 2005 01:00:29 -0000 *************** *** 22,31 **** --- 22,34 ---- #include "defs.h" #include "serial.h" #include "ser-unix.h" #include "event-loop.h" + #ifdef WINAPI + #include + #endif static timer_handler_func push_event; static handler_func fd_event; /* Event handling for ASYNC serial code. *************** fd_event (int error, void *context) *** 134,148 **** { /* Prime the input FIFO. The readchar() function is used to pull characters out of the buffer. See also generic_readchar(). */ int nr; ! do ! { ! nr = read (scb->fd, scb->buf, BUFSIZ); ! } ! while (nr == -1 && errno == EINTR); if (nr == 0) { scb->bufcnt = SERIAL_EOF; } else if (nr > 0) --- 137,147 ---- { /* Prime the input FIFO. The readchar() function is used to pull characters out of the buffer. See also generic_readchar(). */ int nr; ! nr = scb->ops->read_prim (scb, BUFSIZ); if (nr == 0) { scb->bufcnt = SERIAL_EOF; } else if (nr > 0) *************** push_event (void *context) *** 172,181 **** --- 171,359 ---- scb->async_handler (scb, scb->async_context); /* re-schedule */ reschedule (scb); } + /* Wait for input on scb, with timeout seconds. Returns 0 on success, + otherwise SERIAL_TIMEOUT or SERIAL_ERROR. */ + + static int + ser_base_wait_for (struct serial *scb, int timeout) + { + while (1) + { + int numfds; + struct timeval tv; + fd_set readfds, exceptfds; + + /* NOTE: Some OS's can scramble the READFDS when the select() + call fails (ex the kernel with Red Hat 5.2). Initialize all + arguments before each call. */ + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + FD_ZERO (&readfds); + FD_ZERO (&exceptfds); + FD_SET (scb->fd, &readfds); + FD_SET (scb->fd, &exceptfds); + + if (timeout >= 0) + numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv); + else + numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0); + + if (numfds <= 0) + { + if (numfds == 0) + return SERIAL_TIMEOUT; + else if (errno == EINTR) + continue; + else + return SERIAL_ERROR; /* Got an error from select or poll */ + } + + return 0; + } + } + + /* Read a character with user-specified timeout. TIMEOUT is number of seconds + to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns + char if successful. Returns -2 if timeout expired, EOF if line dropped + dead, or -3 for any other error (see errno in that case). */ + + static int + do_ser_base_readchar (struct serial *scb, int timeout) + { + int status; + int delta; + + /* We have to be able to keep the GUI alive here, so we break the + original timeout into steps of 1 second, running the "keep the + GUI alive" hook each time through the loop. + + Also, timeout = 0 means to poll, so we just set the delta to 0, + so we will only go through the loop once. */ + + delta = (timeout == 0 ? 0 : 1); + while (1) + { + + /* N.B. The UI may destroy our world (for instance by calling + remote_stop,) in which case we want to get out of here as + quickly as possible. It is not safe to touch scb, since + someone else might have freed it. The + deprecated_ui_loop_hook signals that we should exit by + returning 1. */ + + if (deprecated_ui_loop_hook) + { + if (deprecated_ui_loop_hook (0)) + return SERIAL_TIMEOUT; + } + + status = ser_base_wait_for (scb, delta); + if (timeout > 0) + timeout -= delta; + + /* If we got a character or an error back from wait_for, then we can + break from the loop before the timeout is completed. */ + + if (status != SERIAL_TIMEOUT) + { + break; + } + + /* If we have exhausted the original timeout, then generate + a SERIAL_TIMEOUT, and pass it out of the loop. */ + + else if (timeout == 0) + { + status = SERIAL_TIMEOUT; + break; + } + } + + if (status < 0) + return status; + + status = scb->ops->read_prim (scb, BUFSIZ); + + if (status <= 0) + { + if (status == 0) + return SERIAL_TIMEOUT; /* 0 chars means timeout [may need to + distinguish between EOF & timeouts + someday] */ + else + return SERIAL_ERROR; /* Got an error from read */ + } + + scb->bufcnt = status; + scb->bufcnt--; + scb->bufp = scb->buf; + return *scb->bufp++; + } + + /* Perform operations common to both old and new readchar. */ + + /* Return the next character from the input FIFO. If the FIFO is + empty, call the SERIAL specific routine to try and read in more + characters. + + Initially data from the input FIFO is returned (fd_event() + pre-reads the input into that FIFO. Once that has been emptied, + further data is obtained by polling the input FD using the device + specific readchar() function. Note: reschedule() is called after + every read. This is because there is no guarentee that the lower + level fd_event() poll_event() code (which also calls reschedule()) + will be called. */ + + int + generic_readchar (struct serial *scb, int timeout, + int (do_readchar) (struct serial *scb, int timeout)) + { + int ch; + if (scb->bufcnt > 0) + { + ch = *scb->bufp; + scb->bufcnt--; + scb->bufp++; + } + else if (scb->bufcnt < 0) + { + /* Some errors/eof are are sticky. */ + ch = scb->bufcnt; + } + else + { + ch = do_readchar (scb, timeout); + if (ch < 0) + { + switch ((enum serial_rc) ch) + { + case SERIAL_EOF: + case SERIAL_ERROR: + /* Make the error/eof stick. */ + scb->bufcnt = ch; + break; + case SERIAL_TIMEOUT: + scb->bufcnt = 0; + break; + } + } + } + reschedule (scb); + return ch; + } + + int + ser_base_readchar (struct serial *scb, int timeout) + { + return generic_readchar (scb, timeout, do_ser_base_readchar); + } + int ser_base_write (struct serial *scb, const char *str, int len) { int cc; Index: ser-base.h =================================================================== RCS file: /cvs/src/src/gdb/ser-base.h,v retrieving revision 1.2 diff -c -5 -p -r1.2 ser-base.h *** ser-base.h 25 Mar 2005 20:06:36 -0000 1.2 --- ser-base.h 26 Mar 2005 01:00:29 -0000 *************** *** 23,32 **** --- 23,35 ---- #define SER_BASE_H struct serial; struct ui_file; + extern int generic_readchar (struct serial *scb, int timeout, + int (*do_readchar) (struct serial *scb, + int timeout)); extern void reschedule (struct serial *scb); extern int ser_base_flush_output (struct serial *scb); extern int ser_base_flush_input (struct serial *scb); extern int ser_base_send_break (struct serial *scb); extern void ser_base_raw (struct serial *scb); *************** extern int ser_base_setstopbits (struct *** 44,50 **** --- 47,54 ---- extern int ser_base_drain_output (struct serial *scb); extern int ser_base_write (struct serial *scb, const char *str, int len); extern void ser_base_async (struct serial *scb, int async_p); + extern int ser_base_readchar (struct serial *scb, int timeout); #endif Index: ser-pipe.c =================================================================== RCS file: /cvs/src/src/gdb/ser-pipe.c,v retrieving revision 1.15 diff -c -5 -p -r1.15 ser-pipe.c *** ser-pipe.c 25 Mar 2005 20:06:36 -0000 1.15 --- ser-pipe.c 26 Mar 2005 01:00:29 -0000 *************** _initialize_ser_pipe (void) *** 142,152 **** memset (ops, 0, sizeof (struct serial_ops)); ops->name = "pipe"; ops->next = 0; ops->open = pipe_open; ops->close = pipe_close; ! ops->readchar = ser_unix_readchar; ops->write = ser_base_write; ops->flush_output = ser_base_flush_output; ops->flush_input = ser_base_flush_input; ops->send_break = ser_base_send_break; ops->go_raw = ser_base_raw; --- 142,152 ---- memset (ops, 0, sizeof (struct serial_ops)); ops->name = "pipe"; ops->next = 0; ops->open = pipe_open; ops->close = pipe_close; ! ops->readchar = ser_base_readchar; ops->write = ser_base_write; ops->flush_output = ser_base_flush_output; ops->flush_input = ser_base_flush_input; ops->send_break = ser_base_send_break; ops->go_raw = ser_base_raw; *************** _initialize_ser_pipe (void) *** 156,162 **** --- 156,163 ---- ops->noflush_set_tty_state = ser_base_noflush_set_tty_state; ops->setbaudrate = ser_base_setbaudrate; ops->setstopbits = ser_base_setstopbits; ops->drain_output = ser_base_drain_output; ops->async = ser_base_async; + ops->read_prim = ser_unix_read_prim; serial_add_interface (ops); } Index: ser-tcp.c =================================================================== RCS file: /cvs/src/src/gdb/ser-tcp.c,v retrieving revision 1.20 diff -c -5 -p -r1.20 ser-tcp.c *** ser-tcp.c 25 Mar 2005 20:06:36 -0000 1.20 --- ser-tcp.c 26 Mar 2005 01:00:29 -0000 *************** *** 32,46 **** --- 32,54 ---- #ifdef HAVE_SYS_IOCTL_H #include /* For FIONBIO. */ #endif #include + + #ifdef WINAPI + #include + #define ETIMEDOUT WSAETIMEDOUT + #else #include #include #include #include #include + #define closesocket close + #define ioctlsocket ioctl + #endif #include #include "gdb_string.h" static int net_open (struct serial *scb, const char *name); *************** net_open (struct serial *scb, const char *** 60,69 **** --- 68,82 ---- char *port_str, hostname[100]; int n, port, tmp; int use_udp; struct hostent *hostent; struct sockaddr_in sockaddr; + #ifdef WINAPI + u_long ioarg; + #else + int ioarg; + #endif use_udp = 0; if (strncmp (name, "udp:", 4) == 0) { use_udp = 1; *************** net_open (struct serial *scb, const char *** 106,123 **** sockaddr.sin_port = htons (port); memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, sizeof (struct in_addr)); /* set socket nonblocking */ ! tmp = 1; ! ioctl (scb->fd, FIONBIO, &tmp); /* Use Non-blocking connect. connect() will return 0 if connected already. */ n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)); ! if (n < 0 && errno != EINPROGRESS) { net_close (scb); return -1; } if (n) --- 119,147 ---- sockaddr.sin_port = htons (port); memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, sizeof (struct in_addr)); /* set socket nonblocking */ ! ioarg = 1; ! ioctlsocket (scb->fd, FIONBIO, &ioarg); /* Use Non-blocking connect. connect() will return 0 if connected already. */ n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)); ! if (n < 0 ! #ifdef WINAPI ! /* Under Windows, calling "connect" with a non-blocking socket ! results in WSAEWOULDBLOCK, not WSAEINPROGRESS. */ ! && WSAGetLastError() != WSAEWOULDBLOCK ! #else ! && errno != EINPROGRESS ! #endif ! ) { + #ifdef WINAPI + errno = WSAGetLastError(); + #endif net_close (scb); return -1; } if (n) *************** net_open (struct serial *scb, const char *** 163,185 **** /* Got something. Is it an error? */ { int res, err, len; len = sizeof(err); ! res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, &err, &len); if (res < 0 || err) { if (err) errno = err; net_close (scb); return -1; } } /* turn off nonblocking */ ! tmp = 0; ! ioctl (scb->fd, FIONBIO, &tmp); if (use_udp == 0) { /* Disable Nagle algorithm. Needed in some cases. */ tmp = 1; --- 187,213 ---- /* Got something. Is it an error? */ { int res, err, len; len = sizeof(err); ! /* On Windows, the fourth parameter to getsockopt is a "char *"; ! on UNIX systems it is generally "void *". The cast to "void *" ! is OK everywhere, since in C "void *" can be implicitly ! converted to any pointer type. */ ! res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len); if (res < 0 || err) { if (err) errno = err; net_close (scb); return -1; } } /* turn off nonblocking */ ! ioarg = 0; ! ioctlsocket (scb->fd, FIONBIO, &ioarg); if (use_udp == 0) { /* Disable Nagle algorithm. Needed in some cases. */ tmp = 1; *************** static void *** 200,224 **** net_close (struct serial *scb) { if (scb->fd < 0) return; ! close (scb->fd); scb->fd = -1; } void _initialize_ser_tcp (void) { ! struct serial_ops *ops = XMALLOC (struct serial_ops); memset (ops, 0, sizeof (struct serial_ops)); ops->name = "tcp"; ops->next = 0; ops->open = net_open; ops->close = net_close; ! ops->readchar = ser_unix_readchar; ! ops->write = ser_base_write; ops->flush_output = ser_base_flush_output; ops->flush_input = ser_base_flush_input; ops->send_break = ser_base_send_break; ops->go_raw = ser_base_raw; ops->get_tty_state = ser_base_get_tty_state; --- 228,293 ---- net_close (struct serial *scb) { if (scb->fd < 0) return; ! closesocket (scb->fd); scb->fd = -1; } + static int + net_read_prim (struct serial *scb, size_t count) + { + #ifdef WINAPI + /* Under Windows, we must use "recv" to read data from sockets. */ + return recv (scb->fd, scb->buf, count, 0); + #else + return ser_unix_read_prim (scb, count); + #endif + } + + static int + net_write (struct serial *scb, const char *str, int len) + { + #ifdef WINAPI + /* Under Windows, we must use "send" to send data to and from + sockets. */ + int cc; + + while (len > 0) + { + cc = send (scb->fd, str, len, 0); + + if (cc < 0) + return 1; + len -= cc; + str += cc; + } + return 0; + #else + return ser_base_write (scb, str, len); + #endif + } + void _initialize_ser_tcp (void) { ! struct serial_ops *ops; ! #ifdef WINAPI ! WSADATA wsa_data; ! if (WSAStartup (MAKEWORD (1, 0), &wsa_data) != 0) ! /* WinSock is unavailable. */ ! return; ! #endif ! ops = XMALLOC (struct serial_ops); memset (ops, 0, sizeof (struct serial_ops)); ops->name = "tcp"; ops->next = 0; ops->open = net_open; ops->close = net_close; ! ops->readchar = ser_base_readchar; ! ops->write = net_write; ops->flush_output = ser_base_flush_output; ops->flush_input = ser_base_flush_input; ops->send_break = ser_base_send_break; ops->go_raw = ser_base_raw; ops->get_tty_state = ser_base_get_tty_state; *************** _initialize_ser_tcp (void) *** 227,233 **** --- 296,303 ---- ops->noflush_set_tty_state = ser_base_noflush_set_tty_state; ops->setbaudrate = ser_base_setbaudrate; ops->setstopbits = ser_base_setstopbits; ops->drain_output = ser_base_drain_output; ops->async = ser_base_async; + ops->read_prim = net_read_prim; serial_add_interface (ops); } Index: ser-unix.c =================================================================== RCS file: /cvs/src/src/gdb/ser-unix.c,v retrieving revision 1.24 diff -c -5 -p -r1.24 ser-unix.c *** ser-unix.c 25 Mar 2005 20:06:36 -0000 1.24 --- ser-unix.c 26 Mar 2005 01:00:30 -0000 *************** struct hardwire_ttystate *** 68,80 **** static int hardwire_open (struct serial *scb, const char *name); static void hardwire_raw (struct serial *scb); static int wait_for (struct serial *scb, int timeout); static int hardwire_readchar (struct serial *scb, int timeout); static int do_hardwire_readchar (struct serial *scb, int timeout); - static int generic_readchar (struct serial *scb, int timeout, - int (*do_readchar) (struct serial *scb, - int timeout)); static int rate_to_code (int rate); static int hardwire_setbaudrate (struct serial *scb, int rate); static void hardwire_close (struct serial *scb); static int get_tty_state (struct serial *scb, struct hardwire_ttystate * state); --- 68,77 ---- *************** hardwire_raw (struct serial *scb) *** 420,430 **** For termio{s}, we actually just setup VTIME if necessary, and let the timeout occur in the read() in hardwire_read(). */ /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent ! ser_unix*() until the old TERMIOS/SGTTY/... timer code has been flushed. . */ /* NOTE: cagney/1999-09-30: Much of the code below is dead. The only possible values of the TIMEOUT parameter are ONE and ZERO. Consequently all the code that tries to handle the possability of --- 417,427 ---- For termio{s}, we actually just setup VTIME if necessary, and let the timeout occur in the read() in hardwire_read(). */ /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent ! ser_base*() until the old TERMIOS/SGTTY/... timer code has been flushed. . */ /* NOTE: cagney/1999-09-30: Much of the code below is dead. The only possible values of the TIMEOUT parameter are ONE and ZERO. Consequently all the code that tries to handle the possability of *************** wait_for (struct serial *scb, int timeou *** 540,556 **** to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns char if successful. Returns SERIAL_TIMEOUT if timeout expired, EOF if line dropped dead, or SERIAL_ERROR for any other error (see errno in that case). */ /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent ! ser_unix*() until the old TERMIOS/SGTTY/... timer code has been flushed. */ /* NOTE: cagney/1999-09-16: This function is not identical to ! ser_unix_readchar() as part of replacing it with ser_unix*() merging will be required - this code handles the case where read() ! times out due to no data while ser_unix_readchar() doesn't expect that. */ static int do_hardwire_readchar (struct serial *scb, int timeout) { --- 537,553 ---- to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns char if successful. Returns SERIAL_TIMEOUT if timeout expired, EOF if line dropped dead, or SERIAL_ERROR for any other error (see errno in that case). */ /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent ! ser_base*() until the old TERMIOS/SGTTY/... timer code has been flushed. */ /* NOTE: cagney/1999-09-16: This function is not identical to ! ser_base_readchar() as part of replacing it with ser_base*() merging will be required - this code handles the case where read() ! times out due to no data while ser_base_readchar() doesn't expect that. */ static int do_hardwire_readchar (struct serial *scb, int timeout) { *************** hardwire_close (struct serial *scb) *** 861,1066 **** return; close (scb->fd); scb->fd = -1; } - - /* Wait for input on scb, with timeout seconds. Returns 0 on success, - otherwise SERIAL_TIMEOUT or SERIAL_ERROR. */ - - static int - ser_unix_wait_for (struct serial *scb, int timeout) - { - while (1) - { - int numfds; - struct timeval tv; - fd_set readfds, exceptfds; - - /* NOTE: Some OS's can scramble the READFDS when the select() - call fails (ex the kernel with Red Hat 5.2). Initialize all - arguments before each call. */ - - tv.tv_sec = timeout; - tv.tv_usec = 0; - - FD_ZERO (&readfds); - FD_ZERO (&exceptfds); - FD_SET (scb->fd, &readfds); - FD_SET (scb->fd, &exceptfds); - - if (timeout >= 0) - numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv); - else - numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0); - - if (numfds <= 0) - { - if (numfds == 0) - return SERIAL_TIMEOUT; - else if (errno == EINTR) - continue; - else - return SERIAL_ERROR; /* Got an error from select or poll */ - } - - return 0; - } - } - - /* Read a character with user-specified timeout. TIMEOUT is number of seconds - to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns - char if successful. Returns -2 if timeout expired, EOF if line dropped - dead, or -3 for any other error (see errno in that case). */ - - static int - do_unix_readchar (struct serial *scb, int timeout) - { - int status; - int delta; - - /* We have to be able to keep the GUI alive here, so we break the - original timeout into steps of 1 second, running the "keep the - GUI alive" hook each time through the loop. - - Also, timeout = 0 means to poll, so we just set the delta to 0, - so we will only go through the loop once. */ - - delta = (timeout == 0 ? 0 : 1); - while (1) - { - - /* N.B. The UI may destroy our world (for instance by calling - remote_stop,) in which case we want to get out of here as - quickly as possible. It is not safe to touch scb, since - someone else might have freed it. The - deprecated_ui_loop_hook signals that we should exit by - returning 1. */ - - if (deprecated_ui_loop_hook) - { - if (deprecated_ui_loop_hook (0)) - return SERIAL_TIMEOUT; - } - - status = ser_unix_wait_for (scb, delta); - if (timeout > 0) - timeout -= delta; - - /* If we got a character or an error back from wait_for, then we can - break from the loop before the timeout is completed. */ - - if (status != SERIAL_TIMEOUT) - { - break; - } - - /* If we have exhausted the original timeout, then generate - a SERIAL_TIMEOUT, and pass it out of the loop. */ - - else if (timeout == 0) - { - status = SERIAL_TIMEOUT; - break; - } - } - - if (status < 0) - return status; - - while (1) - { - status = read (scb->fd, scb->buf, BUFSIZ); - if (status != -1 || errno != EINTR) - break; - } - - if (status <= 0) - { - if (status == 0) - return SERIAL_TIMEOUT; /* 0 chars means timeout [may need to - distinguish between EOF & timeouts - someday] */ - else - return SERIAL_ERROR; /* Got an error from read */ - } - - scb->bufcnt = status; - scb->bufcnt--; - scb->bufp = scb->buf; - return *scb->bufp++; - } - - /* Perform operations common to both old and new readchar. */ - - /* Return the next character from the input FIFO. If the FIFO is - empty, call the SERIAL specific routine to try and read in more - characters. - - Initially data from the input FIFO is returned (fd_event() - pre-reads the input into that FIFO. Once that has been emptied, - further data is obtained by polling the input FD using the device - specific readchar() function. Note: reschedule() is called after - every read. This is because there is no guarentee that the lower - level fd_event() poll_event() code (which also calls reschedule()) - will be called. */ - - static int - generic_readchar (struct serial *scb, int timeout, - int (do_readchar) (struct serial *scb, int timeout)) - { - int ch; - if (scb->bufcnt > 0) - { - ch = *scb->bufp; - scb->bufcnt--; - scb->bufp++; - } - else if (scb->bufcnt < 0) - { - /* Some errors/eof are are sticky. */ - ch = scb->bufcnt; - } - else - { - ch = do_readchar (scb, timeout); - if (ch < 0) - { - switch ((enum serial_rc) ch) - { - case SERIAL_EOF: - case SERIAL_ERROR: - /* Make the error/eof stick. */ - scb->bufcnt = ch; - break; - case SERIAL_TIMEOUT: - scb->bufcnt = 0; - break; - } - } - } - reschedule (scb); - return ch; - } - - int - ser_unix_readchar (struct serial *scb, int timeout) - { - return generic_readchar (scb, timeout, do_unix_readchar); - } void _initialize_ser_hardwire (void) { struct serial_ops *ops = XMALLOC (struct serial_ops); memset (ops, 0, sizeof (struct serial_ops)); ops->name = "hardwire"; ops->next = 0; ops->open = hardwire_open; ops->close = hardwire_close; ! /* FIXME: Don't replace this with the equivalent ser_unix*() until the old TERMIOS/SGTTY/... timer code has been flushed. cagney 1999-09-16. */ ops->readchar = hardwire_readchar; ops->write = ser_base_write; ops->flush_output = hardwire_flush_output; --- 858,879 ---- return; close (scb->fd); scb->fd = -1; } void _initialize_ser_hardwire (void) { struct serial_ops *ops = XMALLOC (struct serial_ops); memset (ops, 0, sizeof (struct serial_ops)); ops->name = "hardwire"; ops->next = 0; ops->open = hardwire_open; ops->close = hardwire_close; ! /* FIXME: Don't replace this with the equivalent ser_base*() until the old TERMIOS/SGTTY/... timer code has been flushed. cagney 1999-09-16. */ ops->readchar = hardwire_readchar; ops->write = ser_base_write; ops->flush_output = hardwire_flush_output; *************** _initialize_ser_hardwire (void) *** 1073,1079 **** --- 886,907 ---- ops->noflush_set_tty_state = hardwire_noflush_set_tty_state; ops->setbaudrate = hardwire_setbaudrate; ops->setstopbits = hardwire_setstopbits; ops->drain_output = hardwire_drain_output; ops->async = ser_base_async; + ops->read_prim = ser_unix_read_prim; serial_add_interface (ops); } + + int + ser_unix_read_prim (struct serial *scb, size_t count) + { + int status; + + while (1) + { + status = read (scb->fd, scb->buf, count); + if (status != -1 || errno != EINTR) + break; + } + return status; + } Index: ser-unix.h =================================================================== RCS file: /cvs/src/src/gdb/ser-unix.h,v retrieving revision 1.5 diff -c -5 -p -r1.5 ser-unix.h *** ser-unix.h 25 Mar 2005 19:47:23 -0000 1.5 --- ser-unix.h 26 Mar 2005 01:00:30 -0000 *************** *** 20,27 **** Boston, MA 02111-1307, USA. */ #ifndef SER_UNIX_H #define SER_UNIX_H ! extern int ser_unix_readchar (struct serial *scb, int timeout); #endif --- 20,27 ---- Boston, MA 02111-1307, USA. */ #ifndef SER_UNIX_H #define SER_UNIX_H ! extern int ser_unix_read_prim (struct serial *scb, size_t count); #endif Index: serial.h =================================================================== RCS file: /cvs/src/src/gdb/serial.h,v retrieving revision 1.10 diff -c -5 -p -r1.10 serial.h *** serial.h 14 Jan 2005 01:59:20 -0000 1.10 --- serial.h 26 Mar 2005 01:00:30 -0000 *************** struct serial_ops *** 230,239 **** --- 230,242 ---- int (*drain_output) (struct serial *); /* Change the serial device into/out of asynchronous mode, call the specified function when ever there is something interesting. */ void (*async) (struct serial *scb, int async_p); + /* Perform a low-level read operation, reading (at most) COUNT + bytes into SCB->BUF. */ + int (*read_prim)(struct serial *scb, size_t count); }; /* Add a new serial interface to the interface list */ extern void serial_add_interface (struct serial_ops * optable); Index: utils.c =================================================================== RCS file: /cvs/src/src/gdb/utils.c,v retrieving revision 1.160 diff -c -5 -p -r1.160 utils.c *** utils.c 18 Mar 2005 20:46:38 -0000 1.160 --- utils.c 26 Mar 2005 01:00:30 -0000 *************** *** 56,65 **** --- 56,69 ---- #include "inferior.h" /* for signed_pointer_to_address */ #include /* For MAXPATHLEN */ + #ifdef WINAPI + #include + #endif + #include "gdb_curses.h" #include "readline/readline.h" #if !HAVE_DECL_MALLOC *************** internal_warning (const char *file, int *** 844,861 **** char * safe_strerror (int errnum) { char *msg; ! msg = strerror (errnum); ! if (msg == NULL) { ! static char buf[32]; ! xsnprintf (buf, sizeof buf, "(undocumented errno %d)", errnum); msg = buf; } return (msg); } /* Print the system error message for errno, and also mention STRING as the file name for which the error was encountered. --- 848,879 ---- char * safe_strerror (int errnum) { char *msg; + static char buf[32]; ! #ifdef WINAPI ! /* The strerror function only works for functions that set errno. ! In the case of Windows sockets, we can get error numbers that ! strerror cannot handle. */ ! if (errnum > WSABASEERR) { ! xsnprintf (buf, sizeof buf, "(winsock error %d)", errnum); msg = buf; } + else + #endif + { + msg = strerror (errnum); + + if (msg == NULL) + { + xsnprintf (buf, sizeof buf, "(undocumented errno %d)", errnum); + msg = buf; + } + } return (msg); } /* Print the system error message for errno, and also mention STRING as the file name for which the error was encountered.