* Makefile.in: Add new file ser-tcp.c.

* defs.h (memcmp):  Add decl for memcmp to #ifndef MEM_FNS_DECLARED.
	* findvar.c (write_register):  See if we are writing back the same
	value that's already in the register.  If so, don't bother.
	* remote.c (putpkt, getpkt):  Improve handling of communication
	problems.
	* ser-go32.c:  Prototype it to death.  Update serial_ops and add
	dummy routines where appropriate.
	* ser-tcp.c:  New module to implement serial I/O via TCP
	connections.
	* ser-unix.c:  Clean up getting/setting of tty state.  Get rid of
	SERIAL_RESTORE, add SERIAL_{GET|SET}_TTY_STATE interfaces.
	* serial.c:  Add start of support for connect command.
	(serial_open):  Distinguish between tcp and local devices.
	* serial.h (struct serial_ops):  Get rid of restore, add
	get_tty_state and set_tty_state.  Define protoypes and macros for
	this mess.
	* gdbserver/remote-utils.c:  Add tcp support.  (readchar):  Do
	some real buffering.  Handle error conditions gracefully.
	* gdbserver/remote-inflow-sparc.c:  Update to remote-inflow.c
	(Lynx), remove lots of cruft.
This commit is contained in:
Stu Grossman 1993-05-29 01:33:36 +00:00
parent 633c8b0a9d
commit 38dc5e123f
10 changed files with 740 additions and 357 deletions

View File

@ -1,3 +1,27 @@
Fri May 28 17:18:05 1993 Stu Grossman (grossman@cygnus.com)
* Makefile.in: Add new file ser-tcp.c.
* defs.h (memcmp): Add decl for memcmp to #ifndef MEM_FNS_DECLARED.
* findvar.c (write_register): See if we are writing back the same
value that's already in the register. If so, don't bother.
* remote.c (putpkt, getpkt): Improve handling of communication
problems.
* ser-go32.c: Prototype it to death. Update serial_ops and add
dummy routines where appropriate.
* ser-tcp.c: New module to implement serial I/O via TCP
connections.
* ser-unix.c: Clean up getting/setting of tty state. Get rid of
SERIAL_RESTORE, add SERIAL_{GET|SET}_TTY_STATE interfaces.
* serial.c: Add start of support for connect command.
(serial_open): Distinguish between tcp and local devices.
* serial.h (struct serial_ops): Get rid of restore, add
get_tty_state and set_tty_state. Define protoypes and macros for
this mess.
* gdbserver/remote-utils.c: Add tcp support. (readchar): Do
some real buffering. Handle error conditions gracefully.
* gdbserver/remote-inflow-sparc.c: Update to remote-inflow.c
(Lynx), remove lots of cruft.
Fri May 28 17:24:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) Fri May 28 17:24:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
* printcmd.c (print_address_symbolic): turn this into an assigment * printcmd.c (print_address_symbolic): turn this into an assigment

View File

@ -185,7 +185,7 @@ RUNTESTFLAGS=
# part of libiberty) a POSIX interface. But at least for now the # part of libiberty) a POSIX interface. But at least for now the
# host-dependent makefile fragment might need to use something else # host-dependent makefile fragment might need to use something else
# besides ser-unix.o # besides ser-unix.o
SER_HARDWIRE=ser-unix.o SER_HARDWIRE=ser-unix.o ser-tcp.o
# Host and target-dependent makefile fragments come in here. # Host and target-dependent makefile fragments come in here.
#### ####
@ -304,7 +304,7 @@ SFILES = ${srcdir}/blockframe.c ${srcdir}/breakpoint.c ${srcdir}/buildsym.c \
${srcdir}/target.c ${srcdir}/typeprint.c ${srcdir}/utils.c \ ${srcdir}/target.c ${srcdir}/typeprint.c ${srcdir}/utils.c \
${srcdir}/valarith.c \ ${srcdir}/valarith.c \
${srcdir}/valops.c ${srcdir}/valprint.c ${srcdir}/values.c \ ${srcdir}/valops.c ${srcdir}/valprint.c ${srcdir}/values.c \
${srcdir}/serial.c ${srcdir}/ser-unix.c ${srcdir}/serial.c ${srcdir}/ser-unix.c ${srcdir}/ser-tcp.c
# Files that are not source code, but need to go into gdb-$(VERSION).tar.Z. # Files that are not source code, but need to go into gdb-$(VERSION).tar.Z.
NONSRC = ${srcdir}/Makefile.in ${srcdir}/depend ${srcdir}/alldeps.mak \ NONSRC = ${srcdir}/Makefile.in ${srcdir}/depend ${srcdir}/alldeps.mak \

View File

@ -434,20 +434,23 @@ enum val_prettyprint
/* Defaults for system-wide constants (if not defined by xm.h, we fake it). */ /* Defaults for system-wide constants (if not defined by xm.h, we fake it). */
#if !defined (UINT_MAX) #if !defined (UINT_MAX)
#define UINT_MAX 0xffffffff #define UINT_MAX ((unsigned int)(~0)) /* 0xFFFFFFFF for 32-bits */
#endif
#if !defined (LONG_MAX)
#define LONG_MAX 0x7fffffff
#endif #endif
#if !defined (INT_MAX) #if !defined (INT_MAX)
#define INT_MAX 0x7fffffff #define INT_MAX (UINT_MAX >> 1) /* 0x7FFFFFFF for 32-bits */
#endif #endif
#if !defined (INT_MIN) #if !defined (INT_MIN)
/* Two's complement, 32 bit. */ #define INT_MIN (-INT_MAX - 1) /* 0x80000000 for 32-bits */
#define INT_MIN -0x80000000 #endif
#if !defined (ULONG_MAX)
#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF for 32-bits */
#endif
#if !defined (LONG_MAX)
#define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */
#endif #endif
/* Number of bits in a char or unsigned char for the target machine. /* Number of bits in a char or unsigned char for the target machine.
@ -722,10 +725,10 @@ qsort PARAMS ((void *base, size_t nmemb, /* 4.10.5.2 */
#ifndef MEM_FNS_DECLARED /* Some non-ANSI use void *, not char *. */ #ifndef MEM_FNS_DECLARED /* Some non-ANSI use void *, not char *. */
extern PTR extern PTR
memcpy PARAMS ((void *, const void *, size_t)); /* 4.11.2.1 */ memcpy PARAMS ((void *, const void *, size_t)); /* 4.11.2.1 */
#endif
extern int extern int
memcmp PARAMS ((const void *, const void *, size_t)); /* 4.11.4.1 */ memcmp PARAMS ((const void *, const void *, size_t)); /* 4.11.4.1 */
#endif
extern char * extern char *
strchr PARAMS ((const char *, int)); /* 4.11.5.2 */ strchr PARAMS ((const char *, int)); /* 4.11.5.2 */

View File

@ -1,9 +1,24 @@
/* Low level interface to ptrace, for GDB when running under Unix. /* Low level interface to ptrace, for the remote server for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc. Copyright (C) 1986, 1987, 1993 Free Software Foundation, Inc.
*/
This file is part of GDB.
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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h" #include "defs.h"
#include "wait.h" #include "/usr/include/sys/wait.h"
#include "frame.h" #include "frame.h"
#include "inferior.h" #include "inferior.h"
/*************************** /***************************
@ -38,12 +53,6 @@ extern int errno;
extern int inferior_pid; extern int inferior_pid;
void error (), quit (), perror_with_name (); void error (), quit (), perror_with_name ();
int query (); int query ();
void supply_register (), write_register ();
CORE_ADDR read_register ();
/* Nonzero if we are debugging an attached outside process
rather than an inferior. */
/* Start an inferior process and returns its pid. /* Start an inferior process and returns its pid.
ALLARGS is a vector of program-name and args. ALLARGS is a vector of program-name and args.
@ -101,52 +110,52 @@ kill_inferior ()
/*************inferior_died ();****VK**************/ /*************inferior_died ();****VK**************/
} }
/* Resume execution of the inferior process. /* Wait for process, returns status */
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
unsigned char unsigned char
myresume (step, signal, status) mywait (status)
int step;
int signal;
char *status; char *status;
{ {
int pid; int pid;
WAITTYPE w; union wait w;
errno = 0;
ptrace (step ? 9 : 7, inferior_pid, 1, signal);
if (errno)
perror_with_name ("ptrace");
pid = wait (&w); pid = wait (&w);
if (pid != inferior_pid) if (pid != inferior_pid)
perror_with_name ("wait"); perror_with_name ("wait");
fetch_inferior_registers (0);
if (WIFEXITED (w)) if (WIFEXITED (w))
{ {
printf ("\nChild exited with retcode = %x \n", WEXITSTATUS (w)); fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
*status = 'E'; *status = 'E';
return ((unsigned char) WEXITSTATUS (w)); return ((unsigned char) WEXITSTATUS (w));
} }
else if (!WIFSTOPPED (w)) else if (!WIFSTOPPED (w))
{ {
printf ("\nChild terminated with signal = %x \n", WTERMSIG (w)); fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
*status = 'T'; *status = 'T';
return ((unsigned char) WTERMSIG (w)); return ((unsigned char) WTERMSIG (w));
} }
else
{ fetch_inferior_registers (0);
printf ("\nChild stopped with signal = %x \n", WSTOPSIG (w));
*status = 'S'; *status = 'S';
return ((unsigned char) WSTOPSIG (w)); return ((unsigned char) WSTOPSIG (w));
}
} }
#define INT_REGS 1 /* Resume execution of the inferior process.
#define STACK_REGS 2 If STEP is nonzero, single-step it.
#define FP_REGS 4 If SIGNAL is nonzero, give it that signal. */
void
myresume (step, signal)
int step;
int signal;
{
errno = 0;
ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
if (errno)
perror_with_name ("ptrace");
}
/* Fetch one or more registers from the inferior. REGNO == -1 to get /* Fetch one or more registers from the inferior. REGNO == -1 to get
them all. We actually fetch more than requested, when convenient, them all. We actually fetch more than requested, when convenient,
@ -234,63 +243,6 @@ store_inferior_registers (ignored)
perror("ptrace_setfpregs"); perror("ptrace_setfpregs");
} }
#if 0
void
fetch_inferior_registers ()
{
struct regs inferior_registers;
struct fp_status inferior_fp_registers;
extern char registers[];
ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
if (errno)
perror_with_name ("ptrace");
/**********debugging begin **********/
print_some_registers (&inferior_registers);
/**********debugging end **********/
ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
if (errno)
perror_with_name ("ptrace");
bcopy (&inferior_registers, registers, 16 * 4);
bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof inferior_fp_registers.fpu_regs);
*(int *) &registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
*(int *) &registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
bcopy (&inferior_fp_registers.fpu_flags,
&registers[REGISTER_BYTE (FPC_REGNUM)],
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fpu_regs);
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
store_inferior_registers (regno)
int regno;
{
struct regs inferior_registers;
struct fp_status inferior_fp_registers;
extern char registers[];
bcopy (registers, &inferior_registers, 16 * 4);
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
sizeof inferior_fp_registers.fps_regs);
inferior_registers.r_ps = *(int *) &registers[REGISTER_BYTE (PS_REGNUM)];
inferior_registers.r_pc = *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
&inferior_fp_registers.fps_control,
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
if (errno)
perror_with_name ("ptrace");
ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
if (errno)
perror_with_name ("ptrace");
}
#endif /* 0 */
/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory /* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
in the NEW_SUN_PTRACE case. in the NEW_SUN_PTRACE case.
It ought to be straightforward. But it appears that writing did It ought to be straightforward. But it appears that writing did
@ -373,79 +325,14 @@ write_inferior_memory (memaddr, myaddr, len)
return 0; return 0;
} }
void
try_writing_regs_command ()
{
register int i;
register int val;
if (inferior_pid == 0)
error ("There is no inferior process now.");
fetch_inferior_registers (0);
for (i = 0; i < 18; i++)
{
QUIT;
errno = 0;
val = read_register (i);
write_register (i, val);
if (errno == 0)
{
printf (" Succeeded with register %d; value 0x%x (%d).\n",
i, val, val);
}
else
printf (" Failed with register %d.\n", i);
}
}
void void
initialize () initialize ()
{ {
inferior_pid = 0; inferior_pid = 0;
} }
/* Return the contents of register REGNO,
regarding it as an integer. */
CORE_ADDR
read_register (regno)
int regno;
{
/* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
return *(int *) &registers[REGISTER_BYTE (regno)];
}
/* Store VALUE in the register number REGNO, regarded as an integer. */
void
write_register (regno, val)
int regno, val;
{
/* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
*(int *) &registers[REGISTER_BYTE (regno)] = val;
if (have_inferior_p ())
store_inferior_registers (regno);
}
int int
have_inferior_p () have_inferior_p ()
{ {
return inferior_pid != 0; return inferior_pid != 0;
} }
print_some_registers (regs)
int regs[];
{
register int i;
for (i = 0; i < 18; i++)
{
printf ("reg[%d] = %x\n", i, regs[i]);
}
}

View File

@ -25,10 +25,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <a.out.h> #include <a.out.h>
#include <sys/file.h> #include <sys/file.h>
#include <sgtty.h> #include <sgtty.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/tcp.h>
#include <sys/time.h>
extern int remote_desc; extern int remote_desc;
extern int remote_debugging; extern int remote_debugging;
extern int kiodebug;
void remote_open (); void remote_open ();
void remote_send (); void remote_send ();
@ -53,13 +58,56 @@ remote_open (name, from_tty)
remote_debugging = 0; remote_debugging = 0;
remote_desc = open (name, O_RDWR); if (!strchr (name, ':'))
if (remote_desc < 0) {
perror_with_name ("Could not open remote device"); remote_desc = open (name, O_RDWR);
if (remote_desc < 0)
perror_with_name ("Could not open remote device");
ioctl (remote_desc, TIOCGETP, &sg); ioctl (remote_desc, TIOCGETP, &sg);
sg.sg_flags = RAW; sg.sg_flags = RAW;
ioctl (remote_desc, TIOCSETP, &sg); ioctl (remote_desc, TIOCSETP, &sg);
}
else
{
char *port_str;
int port;
struct sockaddr_in sockaddr;
int tmp;
port_str = strchr (name, ':');
port = atoi (port_str + 1);
remote_desc = socket (PF_INET, SOCK_STREAM, 0);
if (remote_desc < 0)
perror_with_name ("Can't open socket");
/* Allow rapid reuse of this port. */
tmp = 1;
setsockopt (remote_desc, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp,
sizeof(tmp));
/* Enable TCP keep alive process. */
tmp = 1;
setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
sockaddr.sin_family = PF_INET;
sockaddr.sin_port = htons(port);
sockaddr.sin_addr.s_addr = INADDR_ANY;
if (bind (remote_desc, &sockaddr, sizeof (sockaddr))
|| listen (remote_desc, 1))
perror_with_name ("Can't bind address");
tmp = sizeof (sockaddr);
remote_desc = accept (remote_desc, &sockaddr, &tmp);
if (remote_desc == -1)
perror_with_name ("Accept failed");
tmp = 1;
setsockopt (remote_desc, 6, TCP_NODELAY, (char *)&tmp, sizeof(tmp));
}
fprintf (stderr, "Remote debugging using %s\n", name); fprintf (stderr, "Remote debugging using %s\n", name);
remote_debugging = 1; remote_debugging = 1;
@ -148,9 +196,24 @@ putpkt (buf)
static int static int
readchar () readchar ()
{ {
char buf[1]; static char buf[BUFSIZ];
while (read (remote_desc, buf, 1) != 1); static int bufcnt = 0;
return buf[0] & 0x7f; static char *bufp;
if (bufcnt-- > 0)
return *bufp++ & 0x7f;
bufcnt = read (remote_desc, buf, sizeof (buf));
if (bufcnt <= 0)
{
perror ("readchar");
fatal ("read error, quitting");
}
bufp = buf;
bufcnt--;
return *bufp++ & 0x7f;
} }
/* Read a packet from the remote machine, with error checking, /* Read a packet from the remote machine, with error checking,
@ -161,12 +224,13 @@ getpkt (buf)
char *buf; char *buf;
{ {
char *bp; char *bp;
unsigned char csum, c, c1, c2; unsigned char csum, c1, c2;
extern kiodebug; int c;
while (1) while (1)
{ {
csum = 0; csum = 0;
while ((c = readchar ()) != '$'); while ((c = readchar ()) != '$');
bp = buf; bp = buf;

View File

@ -21,6 +21,33 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "serial.h" #include "serial.h"
#include <sys/dos.h> #include <sys/dos.h>
/* This is unused for now. We just return a placeholder. */
struct go32_ttystate
{
int bogus;
};
static int go32_open PARAMS ((serial_t scb, const char *name));
static void go32_raw PARAMS ((serial_t scb));
static int wait_for PARAMS ((serial_t scb, int timeout));
static int go32_readchar PARAMS ((serial_t scb, int timeout));
static int rate_to_code PARAMS ((int rate));
static int go32_setbaudrate PARAMS ((serial_t scb, int rate));
static int go32_write PARAMS ((serial_t scb, const char *str, int len));
static void go32_restore PARAMS ((serial_t scb));
static void go32_close PARAMS ((serial_t scb));
serial_ttystate go32_get_tty_state PARAMS ((serial_t scb));
static int go32_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
static int strncasecmp PARAMS ((char *str1, char *str2, int len));
static char *aptr PARAMS ((short p));
static ASYNC_STRUCT *getivec PARAMS ((int which));
static int dos_async_init PARAMS ((int port));
static void dos_async_tx PARAMS ((const char c));
static int dos_async_ready PARAMS (());
static int dos_async_rx PARAMS (());
static int dosasync_read PARAMS ((int fd, char *buf, int len, int timeout));
static int dosasync_write PARAMS ((int fd, const char *buf, int len, int timeout));
#define SIGNATURE 0x4154 #define SIGNATURE 0x4154
#define VERSION 1 #define VERSION 1
#define OFFSET 0x104 #define OFFSET 0x104
@ -260,6 +287,30 @@ go32_readchar (scb, timeout)
return SERIAL_TIMEOUT; return SERIAL_TIMEOUT;
} }
/* go32_{get set}_tty_state() are both dummys to fill out the function
vector. Someday, they may do something real... */
static serial_ttystate
go32_get_tty_state(scb)
serial_t scb;
{
struct go32_ttystate *state;
state = (struct go32_ttystate *)xmalloc(sizeof *state);
return (serial_ttystate)state;
}
static int
go32_set_tty_state(scb, ttystate)
serial_t scb;
serial_ttystate ttystate;
{
struct go32_ttystate *state;
return 0;
}
static int static int
go32_setbaudrate (scb, rate) go32_setbaudrate (scb, rate)
serial_t scb; serial_t scb;
@ -284,12 +335,6 @@ go32_close ()
{ {
} }
static void
go32_restore (scb)
serial_t scb;
{
}
static struct serial_ops go32_ops = static struct serial_ops go32_ops =
{ {
"hardwire", "hardwire",
@ -299,7 +344,8 @@ static struct serial_ops go32_ops =
go32_readchar, go32_readchar,
go32_write, go32_write,
go32_raw, go32_raw,
go32_restore, go32_get_tty_state,
go32_set_tty_state,
go32_setbaudrate go32_setbaudrate
}; };

270
gdb/ser-tcp.c Normal file
View File

@ -0,0 +1,270 @@
/* Serial interface for raw TCP connections on Un*x like systems
Copyright 1992, 1993 Free Software Foundation, Inc.
This file is part of GDB.
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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "serial.h"
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include "signals.h"
struct tcp_ttystate
{
int bogus;
};
static int tcp_open PARAMS ((serial_t scb, const char *name));
static void tcp_raw PARAMS ((serial_t scb));
static int wait_for PARAMS ((serial_t scb, int timeout));
static int tcp_readchar PARAMS ((serial_t scb, int timeout));
static int tcp_setbaudrate PARAMS ((serial_t scb, int rate));
static int tcp_write PARAMS ((serial_t scb, const char *str, int len));
static void tcp_restore PARAMS ((serial_t scb));
static void tcp_close PARAMS ((serial_t scb));
static serial_ttystate tcp_get_tty_state PARAMS ((serial_t scb));
static int tcp_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
/* Open up a raw tcp socket */
static int
tcp_open(scb, name)
serial_t scb;
const char *name;
{
char *port_str;
int port;
struct hostent *hostent;
struct sockaddr_in sockaddr;
int tmp;
char hostname[100];
port_str = strchr (name, ':');
if (!port_str)
error ("tcp_open: No colon in host name!"); /* Shouldn't ever happen */
tmp = min(port_str - name + 1, sizeof hostname);
strncpy (hostname, name, tmp - 1); /* Don't want colon */
port = atoi (port_str + 1);
hostent = gethostbyname (hostname);
if (!hostent)
{
errno = ENOENT;
return -1;
}
scb->fd = socket (PF_INET, SOCK_STREAM, 0);
if (scb->fd < 0)
return -1;
/* Allow rapid reuse of this port. */
tmp = 1;
setsockopt (scb->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, sizeof(tmp));
/* Enable TCP keep alive process. */
tmp = 1;
setsockopt (scb->fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
sockaddr.sin_family = PF_INET;
sockaddr.sin_port = htons(port);
memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
sizeof (struct in_addr));
if (connect(scb->fd, &sockaddr, sizeof(sockaddr)))
{
close(scb->fd);
return -1;
}
tmp = 1;
if (setsockopt (scb->fd, 6, TCP_NODELAY, (char *)&tmp, sizeof(tmp)))
return -1;
signal(SIGPIPE, SIG_IGN); /* If we don't do this, then GDB simply exits
when the remote side dies. */
return 0;
}
static serial_ttystate
tcp_get_tty_state(scb)
serial_t scb;
{
struct tcp_ttystate *state;
state = (struct tcp_ttystate *)xmalloc(sizeof *state);
return (serial_ttystate)state;
}
static int
tcp_set_tty_state(scb, ttystate)
serial_t scb;
serial_ttystate ttystate;
{
struct tcp_ttystate *state;
state = (struct tcp_ttystate *)ttystate;
return 0;
}
static void
tcp_raw(scb)
serial_t scb;
{
return; /* Always in raw mode */
}
/* Wait for input on scb, with timeout seconds. Returns 0 on success,
otherwise SERIAL_TIMEOUT or SERIAL_ERROR.
For termio{s}, we actually just setup VTIME if necessary, and let the
timeout occur in the read() in tcp_read().
*/
static int
wait_for(scb, timeout)
serial_t scb;
int timeout;
{
int numfds;
struct timeval tv;
fd_set readfds;
FD_ZERO (&readfds);
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_SET(scb->fd, &readfds);
if (timeout >= 0)
numfds = select(scb->fd+1, &readfds, 0, 0, &tv);
else
numfds = select(scb->fd+1, &readfds, 0, 0, 0);
if (numfds <= 0)
if (numfds == 0)
return SERIAL_TIMEOUT;
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
tcp_readchar(scb, timeout)
serial_t scb;
int timeout;
{
int status;
if (scb->bufcnt-- > 0)
return *scb->bufp++;
status = wait_for(scb, timeout);
if (status < 0)
return status;
scb->bufcnt = read(scb->fd, scb->buf, BUFSIZ);
if (scb->bufcnt <= 0)
if (scb->bufcnt == 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--;
scb->bufp = scb->buf;
return *scb->bufp++;
}
static int
tcp_setbaudrate(scb, rate)
serial_t scb;
int rate;
{
return 0; /* Never fails! */
}
static int
tcp_write(scb, str, len)
serial_t scb;
const char *str;
int len;
{
int cc;
while (len > 0)
{
cc = write(scb->fd, str, len);
if (cc < 0)
return 1;
len -= cc;
str += cc;
}
return 0;
}
static void
tcp_close(scb)
serial_t scb;
{
if (scb->fd < 0)
return;
close(scb->fd);
scb->fd = -1;
}
static struct serial_ops tcp_ops =
{
"tcp",
0,
tcp_open,
tcp_close,
tcp_readchar,
tcp_write,
tcp_raw,
tcp_get_tty_state,
tcp_set_tty_state,
tcp_setbaudrate,
};
void
_initialize_ser_tcp ()
{
serial_add_interface (&tcp_ops);
}

View File

@ -30,12 +30,29 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_TERMIOS #ifdef HAVE_TERMIOS
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
struct hardwire_ttystate
{
struct termios termios;
};
#endif #endif
#ifdef HAVE_TERMIO #ifdef HAVE_TERMIO
#include <termio.h> #include <termio.h>
struct hardwire_ttystate
{
struct termio termio;
};
#endif #endif
#ifdef HAVE_SGTTY #ifdef HAVE_SGTTY
#include <sgtty.h> #include <sgtty.h>
struct hardwire_ttystate
{
struct sgttyb sgttyb;
};
#endif #endif
static int hardwire_open PARAMS ((serial_t scb, const char *name)); static int hardwire_open PARAMS ((serial_t scb, const char *name));
@ -47,6 +64,10 @@ static int hardwire_setbaudrate PARAMS ((serial_t scb, int rate));
static int hardwire_write PARAMS ((serial_t scb, const char *str, int len)); static int hardwire_write PARAMS ((serial_t scb, const char *str, int len));
static void hardwire_restore PARAMS ((serial_t scb)); static void hardwire_restore PARAMS ((serial_t scb));
static void hardwire_close PARAMS ((serial_t scb)); static void hardwire_close PARAMS ((serial_t scb));
static int get_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
static int set_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
static serial_ttystate hardwire_get_tty_state PARAMS ((serial_t scb));
static int hardwire_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
/* Open up a real live device for serial I/O */ /* Open up a real live device for serial I/O */
@ -62,68 +83,108 @@ hardwire_open(scb, name)
return 0; return 0;
} }
static int
get_tty_state(scb, state)
serial_t scb;
struct hardwire_ttystate *state;
{
#ifdef HAVE_TERMIOS
return tcgetattr(scb->fd, &state->termios);
#endif
#ifdef HAVE_TERMIO
return ioctl (scb->fd, TCGETA, &state->termio);
#endif
#ifdef HAVE_SGTTY
return ioctl (scb->fd, TIOCGETP, &state->sgttyb);
#endif
}
static int
set_tty_state(scb, state)
serial_t scb;
struct hardwire_ttystate *state;
{
int err;
#ifdef HAVE_TERMIOS
return tcsetattr(scb->fd, TCSANOW, &state->termios);
#endif
#ifdef HAVE_TERMIO
return ioctl (scb->fd, TCSETA, &state->termio);
#endif
#ifdef HAVE_SGTTY
return ioctl (scb->fd, TIOCSETP, &state->sgttyb);
#endif
}
static serial_ttystate
hardwire_get_tty_state(scb)
serial_t scb;
{
struct hardwire_ttystate *state;
state = (struct hardwire_ttystate *)xmalloc(sizeof *state);
if (get_tty_state(scb, state))
return NULL;
return (serial_ttystate)state;
}
static int
hardwire_set_tty_state(scb, ttystate)
serial_t scb;
serial_ttystate ttystate;
{
struct hardwire_ttystate *state;
state = (struct hardwire_ttystate *)ttystate;
return set_tty_state(scb, state);
}
static void static void
hardwire_raw(scb) hardwire_raw(scb)
serial_t scb; serial_t scb;
{ {
struct hardwire_ttystate state;
if (get_tty_state(scb, &state))
fprintf(stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
#ifdef HAVE_TERMIOS #ifdef HAVE_TERMIOS
struct termios termios; state.termios.c_iflag = 0;
state.termios.c_oflag = 0;
if (tcgetattr(scb->fd, &termios)) state.termios.c_lflag = 0;
{ state.termios.c_cflag &= ~(CSIZE|PARENB);
fprintf(stderr, "tcgetattr failed: %s\n", safe_strerror(errno)); state.termios.c_cflag |= CS8;
} state.termios.c_cc[VMIN] = 0;
state.termios.c_cc[VTIME] = 0;
termios.c_iflag = 0;
termios.c_oflag = 0;
termios.c_lflag = 0;
termios.c_cflag &= ~(CSIZE|PARENB);
termios.c_cflag |= CS8;
termios.c_cc[VMIN] = 0;
termios.c_cc[VTIME] = 0;
if (tcsetattr(scb->fd, TCSANOW, &termios))
{
fprintf(stderr, "tcsetattr failed: %s\n", safe_strerror(errno));
}
#endif #endif
#ifdef HAVE_TERMIO #ifdef HAVE_TERMIO
struct termio termio; state.termio.c_iflag = 0;
state.termio.c_oflag = 0;
if (ioctl (scb->fd, TCGETA, &termio)) state.termio.c_lflag = 0;
{ state.termio.c_cflag &= ~(CSIZE|PARENB);
fprintf(stderr, "TCGETA failed: %s\n", safe_strerror(errno)); state.termio.c_cflag |= CS8;
} state.termio.c_cc[VMIN] = 0;
state.termio.c_cc[VTIME] = 0;
termio.c_iflag = 0;
termio.c_oflag = 0;
termio.c_lflag = 0;
termio.c_cflag &= ~(CSIZE|PARENB);
termio.c_cflag |= CS8;
termio.c_cc[VMIN] = 0;
termio.c_cc[VTIME] = 0;
if (ioctl (scb->fd, TCSETA, &termio))
{
fprintf(stderr, "TCSETA failed: %s\n", safe_strerror(errno));
}
#endif #endif
#ifdef HAVE_SGTTY #ifdef HAVE_SGTTY
struct sgttyb sgttyb; state.sgttyb.sg_flags |= RAW | ANYP;
state.sgttyb.sg_flags &= ~(CBREAK | ECHO);
if (ioctl (scb->fd, TIOCGETP, &sgttyb))
fprintf(stderr, "TIOCGETP failed: %s\n", safe_strerror(errno));
sgttyb.sg_flags |= RAW | ANYP;
sgttyb.sg_flags &= ~(CBREAK | ECHO);
if (ioctl (scb->fd, TIOCSETP, &sgttyb))
fprintf(stderr, "TIOCSETP failed: %s\n", safe_strerror(errno));
#endif #endif
scb->current_timeout = 0; scb->current_timeout = 0;
if (set_tty_state (scb, &state))
fprintf(stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
} }
/* Wait for input on scb, with timeout seconds. Returns 0 on success, /* Wait for input on scb, with timeout seconds. Returns 0 on success,
@ -171,31 +232,24 @@ wait_for(scb, timeout)
return 0; return 0;
{ {
struct hardwire_ttystate state;
if (get_tty_state(scb, &state))
fprintf(stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
#ifdef HAVE_TERMIOS #ifdef HAVE_TERMIOS
struct termios termios; state.termios.c_cc[VTIME] = timeout * 10;
#endif
if (tcgetattr(scb->fd, &termios))
fprintf(stderr, "wait_for() tcgetattr failed: %s\n", safe_strerror(errno));
termios.c_cc[VTIME] = timeout * 10;
if (tcsetattr(scb->fd, TCSANOW, &termios))
fprintf(stderr, "wait_for() tcsetattr failed: %s\n", safe_strerror(errno));
#endif /* HAVE_TERMIOS */
#ifdef HAVE_TERMIO #ifdef HAVE_TERMIO
struct termio termio; state.termio.c_cc[VTIME] = timeout * 10;
#endif
if (ioctl (scb->fd, TCGETA, &termio))
fprintf(stderr, "wait_for() TCGETA failed: %s\n", safe_strerror(errno));
termio.c_cc[VTIME] = timeout * 10;
if (ioctl (scb->fd, TCSETA, &termio))
fprintf(stderr, "TCSETA failed: %s\n", safe_strerror(errno));
#endif /* HAVE_TERMIO */
scb->current_timeout = timeout; scb->current_timeout = timeout;
if (set_tty_state (scb, &state))
fprintf(stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
return 0; return 0;
} }
#endif /* HAVE_TERMIO || HAVE_TERMIOS */ #endif /* HAVE_TERMIO || HAVE_TERMIOS */
@ -290,49 +344,31 @@ hardwire_setbaudrate(scb, rate)
serial_t scb; serial_t scb;
int rate; int rate;
{ {
struct hardwire_ttystate state;
if (get_tty_state(scb, &state))
return -1;
#ifdef HAVE_TERMIOS #ifdef HAVE_TERMIOS
struct termios termios; cfsetospeed (&state.termios, rate_to_code (rate));
cfsetispeed (&state.termios, rate_to_code (rate));
if (tcgetattr (scb->fd, &termios))
return -1;
cfsetospeed (&termios, rate_to_code (rate));
cfsetispeed (&termios, rate_to_code (rate));
if (tcsetattr (scb->fd, TCSANOW, &termios))
return -1;
#endif #endif
#ifdef HAVE_TERMIO #ifdef HAVE_TERMIO
struct termio termio;
if (ioctl (scb->fd, TCGETA, &termio))
return -1;
#ifndef CIBAUD #ifndef CIBAUD
#define CIBAUD CBAUD #define CIBAUD CBAUD
#endif #endif
termio.c_cflag &= ~(CBAUD | CIBAUD); state.termio.c_cflag &= ~(CBAUD | CIBAUD);
termio.c_cflag |= rate_to_code (rate); state.termio.c_cflag |= rate_to_code (rate);
if (ioctl (scb->fd, TCSETA, &termio))
return -1;
#endif #endif
#ifdef HAVE_SGTTY #ifdef HAVE_SGTTY
struct sgttyb sgttyb; state.sgttyb.sg_ispeed = rate_to_code (rate);
state.sgttyb.sg_ospeed = rate_to_code (rate);
if (ioctl (scb->fd, TIOCGETP, &sgttyb))
return -1;
sgttyb.sg_ispeed = rate_to_code (rate);
sgttyb.sg_ospeed = rate_to_code (rate);
if (ioctl (scb->fd, TIOCSETP, &sgttyb))
return -1;
#endif #endif
return 0;
return set_tty_state (scb, &state);
} }
static int static int
@ -355,12 +391,6 @@ hardwire_write(scb, str, len)
return 0; return 0;
} }
static void
hardwire_restore(scb)
serial_t scb;
{
}
static void static void
hardwire_close(scb) hardwire_close(scb)
serial_t scb; serial_t scb;
@ -381,8 +411,9 @@ static struct serial_ops hardwire_ops =
hardwire_readchar, hardwire_readchar,
hardwire_write, hardwire_write,
hardwire_raw, hardwire_raw,
hardwire_restore, hardwire_get_tty_state,
hardwire_setbaudrate hardwire_set_tty_state,
hardwire_setbaudrate,
}; };
void void

View File

@ -20,10 +20,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h" #include "defs.h"
#include "serial.h" #include "serial.h"
/* Open up a device or a network socket, depending upon the syntax of NAME. */ /* Linked list of serial I/O handlers */
static struct serial_ops *serial_ops_list = NULL; static struct serial_ops *serial_ops_list = NULL;
/* This is the last serial stream opened. Used by connect command. */
static serial_t last_serial_opened = NULL;
static struct serial_ops * static struct serial_ops *
serial_interface_lookup (name) serial_interface_lookup (name)
char *name; char *name;
@ -45,6 +49,8 @@ serial_add_interface(optable)
serial_ops_list = optable; serial_ops_list = optable;
} }
/* Open up a device or a network socket, depending upon the syntax of NAME. */
serial_t serial_t
serial_open(name) serial_open(name)
const char *name; const char *name;
@ -52,7 +58,10 @@ serial_open(name)
serial_t scb; serial_t scb;
struct serial_ops *ops; struct serial_ops *ops;
ops = serial_interface_lookup ("hardwire"); if (strchr (name, ':'))
ops = serial_interface_lookup ("tcp");
else
ops = serial_interface_lookup ("hardwire");
if (!ops) if (!ops)
return NULL; return NULL;
@ -70,6 +79,34 @@ serial_open(name)
return NULL; return NULL;
} }
last_serial_opened = scb;
return scb;
}
serial_t
serial_fdopen(fd)
const int fd;
{
serial_t scb;
struct serial_ops *ops;
ops = serial_interface_lookup ("hardwire");
if (!ops)
return NULL;
scb = (serial_t)xmalloc (sizeof (struct _serial_t));
scb->ops = ops;
scb->bufcnt = 0;
scb->bufp = scb->buf;
scb->fd = fd;
last_serial_opened = scb;
return scb; return scb;
} }
@ -77,21 +114,28 @@ void
serial_close(scb) serial_close(scb)
serial_t scb; serial_t scb;
{ {
last_serial_opened = NULL;
scb->ops->close(scb); scb->ops->close(scb);
free(scb); free(scb);
} }
#if 0 #if 0
/* Connect the user directly to the remote system. This command acts just like /* Connect the user directly to the remote system. This command acts just like
the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */ the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
static serial_t tty_desc; /* Controlling terminal */
static void static void
cleanup_tty(ttystate) cleanup_tty(ttystate)
struct ttystate ttystate; serial_ttystate ttystate;
{ {
printf("\r\n[Exiting connect mode]\r\n"); printf ("\r\n[Exiting connect mode]\r\n");
serial_restore(0, &ttystate); SERIAL_SET_TTY_STATE (tty_desc, ttystate);
free (ttystate);
SERIAL_CLOSE (tty_desc);
} }
static void static void
@ -99,87 +143,94 @@ connect_command (args, fromtty)
char *args; char *args;
int fromtty; int fromtty;
{ {
fd_set readfds;
int numfds;
int c; int c;
char cur_esc = 0; char cur_esc = 0;
static struct ttystate ttystate; serial_ttystate ttystate;
serial_t port_desc; /* TTY port */
dont_repeat(); dont_repeat();
if (desc < 0)
error("target not open.");
if (args) if (args)
fprintf("This command takes no args. They have been ignored.\n"); fprintf(stderr, "This command takes no args. They have been ignored.\n");
printf("[Entering connect mode. Use ~. or ~^D to escape]\n"); printf("[Entering connect mode. Use ~. or ~^D to escape]\n");
serial_raw(0, &ttystate); tty_desc = SERIAL_FDOPEN (0);
port_desc = last_serial_opened;
make_cleanup(cleanup_tty, &ttystate); ttystate = SERIAL_GET_TTY_STATE (tty_desc);
FD_ZERO(&readfds); SERIAL_RAW (tty_desc);
SERIAL_RAW (port_desc);
make_cleanup (cleanup_tty, ttystate);
while (1) while (1)
{ {
do int mask;
{
FD_SET(0, &readfds);
FD_SET(desc, &readfds);
numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
}
while (numfds == 0);
if (numfds < 0) mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
perror_with_name("select");
if (FD_ISSET(0, &readfds)) if (mask & 2)
{ /* tty input, send to stdebug */ { /* tty input */
char cx; char cx;
c = serial_readchar(-1); while (1)
if (c < 0)
perror_with_name("connect");
cx = c;
serial_write(&cx, 1);
switch (cur_esc)
{ {
case 0: c = SERIAL_READCHAR(tty_desc, 0);
if (c == '\r')
cur_esc = c; if (c == SERIAL_TIMEOUT)
break; break;
case '\r':
if (c == '~') if (c < 0)
cur_esc = c; perror_with_name("connect");
else
cur_esc = 0; cx = c;
break; SERIAL_WRITE(port_desc, &cx, 1);
case '~':
if (c == '.' || c == '\004') switch (cur_esc)
return; {
else case 0:
cur_esc = 0; if (c == '\r')
cur_esc = c;
break;
case '\r':
if (c == '~')
cur_esc = c;
else
cur_esc = 0;
break;
case '~':
if (c == '.' || c == '\004')
return;
else
cur_esc = 0;
}
} }
} }
if (FD_ISSET(desc, &readfds)) if (mask & 1)
{ { /* Port input */
char cx;
while (1) while (1)
{ {
c = serial_readchar(-1); c = SERIAL_READCHAR(port_desc, 0);
if (c == SERIAL_TIMEOUT)
break;
if (c < 0) if (c < 0)
break; perror_with_name("connect");
putchar(c);
cx = c;
SERIAL_WRITE(tty_desc, &cx, 1);
} }
fflush(stdout);
} }
} }
} }
#endif
#if 0
void void
_initialize_serial () _initialize_serial ()
{ {
@ -187,4 +238,4 @@ _initialize_serial ()
"Connect the terminal directly up to the command monitor.\n\ "Connect the terminal directly up to the command monitor.\n\
Use <CR>~. or <CR>~^D to break out."); Use <CR>~. or <CR>~^D to break out.");
} }
#endif #endif /* 0 */

View File

@ -19,13 +19,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Terminal state pointer. This is specific to each type of interface. */ /* Terminal state pointer. This is specific to each type of interface. */
typedef PTR ttystate; typedef PTR serial_ttystate;
struct _serial_t struct _serial_t
{ {
int fd; /* File descriptor */ int fd; /* File descriptor */
struct serial_ops *ops; /* Function vector */ struct serial_ops *ops; /* Function vector */
ttystate ttystate; /* Not used (yet) */ serial_ttystate ttystate; /* Not used (yet) */
int bufcnt; /* Amount of data in receive buffer */ int bufcnt; /* Amount of data in receive buffer */
unsigned char *bufp; /* Current byte */ unsigned char *bufp; /* Current byte */
unsigned char buf[BUFSIZ]; /* Da buffer itself */ unsigned char buf[BUFSIZ]; /* Da buffer itself */
@ -42,7 +42,8 @@ struct serial_ops {
int (*readchar) PARAMS ((serial_t, int timeout)); int (*readchar) PARAMS ((serial_t, int timeout));
int (*write) PARAMS ((serial_t, const char *str, int len)); int (*write) PARAMS ((serial_t, const char *str, int len));
void (*go_raw) PARAMS ((serial_t)); void (*go_raw) PARAMS ((serial_t));
void (*restore) PARAMS ((serial_t)); serial_ttystate (*get_tty_state) PARAMS ((serial_t));
int (*set_tty_state) PARAMS ((serial_t, serial_ttystate));
int (*setbaudrate) PARAMS ((serial_t, int rate)); int (*setbaudrate) PARAMS ((serial_t, int rate));
}; };
@ -52,6 +53,8 @@ void serial_add_interface PARAMS ((struct serial_ops *optable));
serial_t serial_open PARAMS ((const char *name)); serial_t serial_open PARAMS ((const char *name));
serial_t serial_fdopen PARAMS ((int fd));
/* For most routines, if a failure is indicated, then errno should be /* For most routines, if a failure is indicated, then errno should be
examined. */ examined. */
@ -60,10 +63,18 @@ serial_t serial_open PARAMS ((const char *name));
#define SERIAL_OPEN(NAME) serial_open(NAME) #define SERIAL_OPEN(NAME) serial_open(NAME)
/* Open a new serial stream using a file handle. */
#define SERIAL_FDOPEN(FD) serial_fdopen(FD)
/* Turn the port into raw mode. */ /* Turn the port into raw mode. */
#define SERIAL_RAW(SERIAL_T) (SERIAL_T)->ops->go_raw((SERIAL_T)) #define SERIAL_RAW(SERIAL_T) (SERIAL_T)->ops->go_raw((SERIAL_T))
#define SERIAL_GET_TTY_STATE(SERIAL_T) (SERIAL_T)->ops->get_tty_state((SERIAL_T))
#define SERIAL_SET_TTY_STATE(SERIAL_T, TTYSTATE) (SERIAL_T)->ops->set_tty_state((SERIAL_T), (TTYSTATE))
/* Read one char from the serial device with TIMEOUT seconds timeout. /* Read one char from the serial device with TIMEOUT seconds timeout.
Returns char if ok, else one of the following codes. Note that all Returns char if ok, else one of the following codes. Note that all
error codes are guaranteed to be < 0. */ error codes are guaranteed to be < 0. */
@ -90,7 +101,3 @@ void serial_close PARAMS ((serial_t));
#define SERIAL_CLOSE(SERIAL_T) serial_close(SERIAL_T) #define SERIAL_CLOSE(SERIAL_T) serial_close(SERIAL_T)
/* Restore the serial port to the state saved in oldstate. XXX - currently
unused! */
#define SERIAL_RESTORE(SERIAL_T) (SERIAL_T)->ops->restore((SERIAL_T))