mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
* 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:
parent
633c8b0a9d
commit
38dc5e123f
@ -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)
|
||||
|
||||
* printcmd.c (print_address_symbolic): turn this into an assigment
|
||||
|
@ -185,7 +185,7 @@ RUNTESTFLAGS=
|
||||
# part of libiberty) a POSIX interface. But at least for now the
|
||||
# host-dependent makefile fragment might need to use something else
|
||||
# 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.
|
||||
####
|
||||
@ -304,7 +304,7 @@ SFILES = ${srcdir}/blockframe.c ${srcdir}/breakpoint.c ${srcdir}/buildsym.c \
|
||||
${srcdir}/target.c ${srcdir}/typeprint.c ${srcdir}/utils.c \
|
||||
${srcdir}/valarith.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.
|
||||
NONSRC = ${srcdir}/Makefile.in ${srcdir}/depend ${srcdir}/alldeps.mak \
|
||||
|
21
gdb/defs.h
21
gdb/defs.h
@ -434,20 +434,23 @@ enum val_prettyprint
|
||||
/* Defaults for system-wide constants (if not defined by xm.h, we fake it). */
|
||||
|
||||
#if !defined (UINT_MAX)
|
||||
#define UINT_MAX 0xffffffff
|
||||
#endif
|
||||
|
||||
#if !defined (LONG_MAX)
|
||||
#define LONG_MAX 0x7fffffff
|
||||
#define UINT_MAX ((unsigned int)(~0)) /* 0xFFFFFFFF for 32-bits */
|
||||
#endif
|
||||
|
||||
#if !defined (INT_MAX)
|
||||
#define INT_MAX 0x7fffffff
|
||||
#define INT_MAX (UINT_MAX >> 1) /* 0x7FFFFFFF for 32-bits */
|
||||
#endif
|
||||
|
||||
#if !defined (INT_MIN)
|
||||
/* Two's complement, 32 bit. */
|
||||
#define INT_MIN -0x80000000
|
||||
#define INT_MIN (-INT_MAX - 1) /* 0x80000000 for 32-bits */
|
||||
#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
|
||||
|
||||
/* 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 *. */
|
||||
extern PTR
|
||||
memcpy PARAMS ((void *, const void *, size_t)); /* 4.11.2.1 */
|
||||
#endif
|
||||
|
||||
extern int
|
||||
memcmp PARAMS ((const void *, const void *, size_t)); /* 4.11.4.1 */
|
||||
#endif
|
||||
|
||||
extern char *
|
||||
strchr PARAMS ((const char *, int)); /* 4.11.5.2 */
|
||||
|
@ -1,9 +1,24 @@
|
||||
/* Low level interface to ptrace, for GDB when running under Unix.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
*/
|
||||
/* Low level interface to ptrace, for the remote server for GDB.
|
||||
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 "wait.h"
|
||||
#include "/usr/include/sys/wait.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
/***************************
|
||||
@ -38,12 +53,6 @@ extern int errno;
|
||||
extern int inferior_pid;
|
||||
void error (), quit (), perror_with_name ();
|
||||
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.
|
||||
ALLARGS is a vector of program-name and args.
|
||||
@ -101,52 +110,52 @@ kill_inferior ()
|
||||
/*************inferior_died ();****VK**************/
|
||||
}
|
||||
|
||||
/* Resume execution of the inferior process.
|
||||
If STEP is nonzero, single-step it.
|
||||
If SIGNAL is nonzero, give it that signal. */
|
||||
/* Wait for process, returns status */
|
||||
|
||||
unsigned char
|
||||
myresume (step, signal, status)
|
||||
int step;
|
||||
int signal;
|
||||
mywait (status)
|
||||
char *status;
|
||||
{
|
||||
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);
|
||||
if (pid != inferior_pid)
|
||||
perror_with_name ("wait");
|
||||
|
||||
fetch_inferior_registers (0);
|
||||
|
||||
if (WIFEXITED (w))
|
||||
{
|
||||
printf ("\nChild exited with retcode = %x \n", WEXITSTATUS (w));
|
||||
fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
|
||||
*status = 'E';
|
||||
return ((unsigned char) WEXITSTATUS (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';
|
||||
return ((unsigned char) WTERMSIG (w));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("\nChild stopped with signal = %x \n", WSTOPSIG (w));
|
||||
*status = 'S';
|
||||
return ((unsigned char) WSTOPSIG (w));
|
||||
}
|
||||
|
||||
fetch_inferior_registers (0);
|
||||
|
||||
*status = 'S';
|
||||
return ((unsigned char) WSTOPSIG (w));
|
||||
}
|
||||
|
||||
#define INT_REGS 1
|
||||
#define STACK_REGS 2
|
||||
#define FP_REGS 4
|
||||
/* Resume execution of the inferior process.
|
||||
If STEP is nonzero, single-step it.
|
||||
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
|
||||
them all. We actually fetch more than requested, when convenient,
|
||||
@ -234,63 +243,6 @@ store_inferior_registers (ignored)
|
||||
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, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
sizeof inferior_fp_registers.fpu_regs);
|
||||
*(int *) ®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
|
||||
*(int *) ®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
|
||||
bcopy (&inferior_fp_registers.fpu_flags,
|
||||
®isters[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 (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
|
||||
sizeof inferior_fp_registers.fps_regs);
|
||||
inferior_registers.r_ps = *(int *) ®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||
inferior_registers.r_pc = *(int *) ®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
bcopy (®isters[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
|
||||
in the NEW_SUN_PTRACE case.
|
||||
It ought to be straightforward. But it appears that writing did
|
||||
@ -373,79 +325,14 @@ write_inferior_memory (memaddr, myaddr, len)
|
||||
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
|
||||
initialize ()
|
||||
{
|
||||
|
||||
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 *) ®isters[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 *) ®isters[REGISTER_BYTE (regno)] = val;
|
||||
|
||||
if (have_inferior_p ())
|
||||
store_inferior_registers (regno);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
have_inferior_p ()
|
||||
{
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <a.out.h>
|
||||
#include <sys/file.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_debugging;
|
||||
extern int kiodebug;
|
||||
|
||||
void remote_open ();
|
||||
void remote_send ();
|
||||
@ -53,13 +58,56 @@ remote_open (name, from_tty)
|
||||
|
||||
remote_debugging = 0;
|
||||
|
||||
remote_desc = open (name, O_RDWR);
|
||||
if (remote_desc < 0)
|
||||
perror_with_name ("Could not open remote device");
|
||||
if (!strchr (name, ':'))
|
||||
{
|
||||
remote_desc = open (name, O_RDWR);
|
||||
if (remote_desc < 0)
|
||||
perror_with_name ("Could not open remote device");
|
||||
|
||||
ioctl (remote_desc, TIOCGETP, &sg);
|
||||
sg.sg_flags = RAW;
|
||||
ioctl (remote_desc, TIOCSETP, &sg);
|
||||
ioctl (remote_desc, TIOCGETP, &sg);
|
||||
sg.sg_flags = RAW;
|
||||
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);
|
||||
remote_debugging = 1;
|
||||
@ -148,9 +196,24 @@ putpkt (buf)
|
||||
static int
|
||||
readchar ()
|
||||
{
|
||||
char buf[1];
|
||||
while (read (remote_desc, buf, 1) != 1);
|
||||
return buf[0] & 0x7f;
|
||||
static char buf[BUFSIZ];
|
||||
static int bufcnt = 0;
|
||||
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,
|
||||
@ -161,12 +224,13 @@ getpkt (buf)
|
||||
char *buf;
|
||||
{
|
||||
char *bp;
|
||||
unsigned char csum, c, c1, c2;
|
||||
extern kiodebug;
|
||||
unsigned char csum, c1, c2;
|
||||
int c;
|
||||
|
||||
while (1)
|
||||
{
|
||||
csum = 0;
|
||||
|
||||
while ((c = readchar ()) != '$');
|
||||
|
||||
bp = buf;
|
||||
|
@ -21,6 +21,33 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "serial.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 VERSION 1
|
||||
#define OFFSET 0x104
|
||||
@ -260,6 +287,30 @@ go32_readchar (scb, 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
|
||||
go32_setbaudrate (scb, rate)
|
||||
serial_t scb;
|
||||
@ -284,12 +335,6 @@ go32_close ()
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
go32_restore (scb)
|
||||
serial_t scb;
|
||||
{
|
||||
}
|
||||
|
||||
static struct serial_ops go32_ops =
|
||||
{
|
||||
"hardwire",
|
||||
@ -299,7 +344,8 @@ static struct serial_ops go32_ops =
|
||||
go32_readchar,
|
||||
go32_write,
|
||||
go32_raw,
|
||||
go32_restore,
|
||||
go32_get_tty_state,
|
||||
go32_set_tty_state,
|
||||
go32_setbaudrate
|
||||
};
|
||||
|
||||
|
270
gdb/ser-tcp.c
Normal file
270
gdb/ser-tcp.c
Normal 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);
|
||||
}
|
245
gdb/ser-unix.c
245
gdb/ser-unix.c
@ -30,12 +30,29 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#ifdef HAVE_TERMIOS
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct hardwire_ttystate
|
||||
{
|
||||
struct termios termios;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TERMIO
|
||||
#include <termio.h>
|
||||
|
||||
struct hardwire_ttystate
|
||||
{
|
||||
struct termio termio;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SGTTY
|
||||
#include <sgtty.h>
|
||||
|
||||
struct hardwire_ttystate
|
||||
{
|
||||
struct sgttyb sgttyb;
|
||||
};
|
||||
#endif
|
||||
|
||||
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 void hardwire_restore 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 */
|
||||
|
||||
@ -62,68 +83,108 @@ hardwire_open(scb, name)
|
||||
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
|
||||
hardwire_raw(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
|
||||
struct termios termios;
|
||||
|
||||
if (tcgetattr(scb->fd, &termios))
|
||||
{
|
||||
fprintf(stderr, "tcgetattr failed: %s\n", safe_strerror(errno));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
state.termios.c_iflag = 0;
|
||||
state.termios.c_oflag = 0;
|
||||
state.termios.c_lflag = 0;
|
||||
state.termios.c_cflag &= ~(CSIZE|PARENB);
|
||||
state.termios.c_cflag |= CS8;
|
||||
state.termios.c_cc[VMIN] = 0;
|
||||
state.termios.c_cc[VTIME] = 0;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TERMIO
|
||||
struct termio termio;
|
||||
|
||||
if (ioctl (scb->fd, TCGETA, &termio))
|
||||
{
|
||||
fprintf(stderr, "TCGETA failed: %s\n", safe_strerror(errno));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
state.termio.c_iflag = 0;
|
||||
state.termio.c_oflag = 0;
|
||||
state.termio.c_lflag = 0;
|
||||
state.termio.c_cflag &= ~(CSIZE|PARENB);
|
||||
state.termio.c_cflag |= CS8;
|
||||
state.termio.c_cc[VMIN] = 0;
|
||||
state.termio.c_cc[VTIME] = 0;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SGTTY
|
||||
struct sgttyb sgttyb;
|
||||
|
||||
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));
|
||||
state.sgttyb.sg_flags |= RAW | ANYP;
|
||||
state.sgttyb.sg_flags &= ~(CBREAK | ECHO);
|
||||
#endif
|
||||
|
||||
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,
|
||||
@ -171,31 +232,24 @@ wait_for(scb, timeout)
|
||||
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
|
||||
struct termios termios;
|
||||
|
||||
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 */
|
||||
state.termios.c_cc[VTIME] = timeout * 10;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TERMIO
|
||||
struct termio termio;
|
||||
|
||||
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 */
|
||||
state.termio.c_cc[VTIME] = timeout * 10;
|
||||
#endif
|
||||
|
||||
scb->current_timeout = timeout;
|
||||
|
||||
if (set_tty_state (scb, &state))
|
||||
fprintf(stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_TERMIO || HAVE_TERMIOS */
|
||||
@ -290,49 +344,31 @@ hardwire_setbaudrate(scb, rate)
|
||||
serial_t scb;
|
||||
int rate;
|
||||
{
|
||||
struct hardwire_ttystate state;
|
||||
|
||||
if (get_tty_state(scb, &state))
|
||||
return -1;
|
||||
|
||||
#ifdef HAVE_TERMIOS
|
||||
struct termios termios;
|
||||
|
||||
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;
|
||||
cfsetospeed (&state.termios, rate_to_code (rate));
|
||||
cfsetispeed (&state.termios, rate_to_code (rate));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TERMIO
|
||||
struct termio termio;
|
||||
|
||||
if (ioctl (scb->fd, TCGETA, &termio))
|
||||
return -1;
|
||||
|
||||
#ifndef CIBAUD
|
||||
#define CIBAUD CBAUD
|
||||
#endif
|
||||
|
||||
termio.c_cflag &= ~(CBAUD | CIBAUD);
|
||||
termio.c_cflag |= rate_to_code (rate);
|
||||
|
||||
if (ioctl (scb->fd, TCSETA, &termio))
|
||||
return -1;
|
||||
state.termio.c_cflag &= ~(CBAUD | CIBAUD);
|
||||
state.termio.c_cflag |= rate_to_code (rate);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SGTTY
|
||||
struct sgttyb sgttyb;
|
||||
|
||||
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;
|
||||
state.sgttyb.sg_ispeed = rate_to_code (rate);
|
||||
state.sgttyb.sg_ospeed = rate_to_code (rate);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
return set_tty_state (scb, &state);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -355,12 +391,6 @@ hardwire_write(scb, str, len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
hardwire_restore(scb)
|
||||
serial_t scb;
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
hardwire_close(scb)
|
||||
serial_t scb;
|
||||
@ -381,8 +411,9 @@ static struct serial_ops hardwire_ops =
|
||||
hardwire_readchar,
|
||||
hardwire_write,
|
||||
hardwire_raw,
|
||||
hardwire_restore,
|
||||
hardwire_setbaudrate
|
||||
hardwire_get_tty_state,
|
||||
hardwire_set_tty_state,
|
||||
hardwire_setbaudrate,
|
||||
};
|
||||
|
||||
void
|
||||
|
165
gdb/serial.c
165
gdb/serial.c
@ -20,10 +20,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "defs.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;
|
||||
|
||||
/* This is the last serial stream opened. Used by connect command. */
|
||||
|
||||
static serial_t last_serial_opened = NULL;
|
||||
|
||||
static struct serial_ops *
|
||||
serial_interface_lookup (name)
|
||||
char *name;
|
||||
@ -45,6 +49,8 @@ serial_add_interface(optable)
|
||||
serial_ops_list = optable;
|
||||
}
|
||||
|
||||
/* Open up a device or a network socket, depending upon the syntax of NAME. */
|
||||
|
||||
serial_t
|
||||
serial_open(name)
|
||||
const char *name;
|
||||
@ -52,7 +58,10 @@ serial_open(name)
|
||||
serial_t scb;
|
||||
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)
|
||||
return NULL;
|
||||
@ -70,6 +79,34 @@ serial_open(name)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -77,21 +114,28 @@ void
|
||||
serial_close(scb)
|
||||
serial_t scb;
|
||||
{
|
||||
last_serial_opened = NULL;
|
||||
|
||||
scb->ops->close(scb);
|
||||
|
||||
free(scb);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* 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. */
|
||||
|
||||
static serial_t tty_desc; /* Controlling terminal */
|
||||
|
||||
static void
|
||||
cleanup_tty(ttystate)
|
||||
struct ttystate ttystate;
|
||||
serial_ttystate ttystate;
|
||||
{
|
||||
printf("\r\n[Exiting connect mode]\r\n");
|
||||
serial_restore(0, &ttystate);
|
||||
printf ("\r\n[Exiting connect mode]\r\n");
|
||||
SERIAL_SET_TTY_STATE (tty_desc, ttystate);
|
||||
free (ttystate);
|
||||
SERIAL_CLOSE (tty_desc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -99,87 +143,94 @@ connect_command (args, fromtty)
|
||||
char *args;
|
||||
int fromtty;
|
||||
{
|
||||
fd_set readfds;
|
||||
int numfds;
|
||||
int c;
|
||||
char cur_esc = 0;
|
||||
static struct ttystate ttystate;
|
||||
serial_ttystate ttystate;
|
||||
serial_t port_desc; /* TTY port */
|
||||
|
||||
dont_repeat();
|
||||
|
||||
if (desc < 0)
|
||||
error("target not open.");
|
||||
|
||||
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");
|
||||
|
||||
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)
|
||||
{
|
||||
do
|
||||
{
|
||||
FD_SET(0, &readfds);
|
||||
FD_SET(desc, &readfds);
|
||||
numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
|
||||
}
|
||||
while (numfds == 0);
|
||||
int mask;
|
||||
|
||||
if (numfds < 0)
|
||||
perror_with_name("select");
|
||||
mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
|
||||
|
||||
if (FD_ISSET(0, &readfds))
|
||||
{ /* tty input, send to stdebug */
|
||||
if (mask & 2)
|
||||
{ /* tty input */
|
||||
char cx;
|
||||
|
||||
c = serial_readchar(-1);
|
||||
if (c < 0)
|
||||
perror_with_name("connect");
|
||||
|
||||
cx = c;
|
||||
serial_write(&cx, 1);
|
||||
switch (cur_esc)
|
||||
while (1)
|
||||
{
|
||||
case 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;
|
||||
c = SERIAL_READCHAR(tty_desc, 0);
|
||||
|
||||
if (c == SERIAL_TIMEOUT)
|
||||
break;
|
||||
|
||||
if (c < 0)
|
||||
perror_with_name("connect");
|
||||
|
||||
cx = c;
|
||||
SERIAL_WRITE(port_desc, &cx, 1);
|
||||
|
||||
switch (cur_esc)
|
||||
{
|
||||
case 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)
|
||||
{
|
||||
c = serial_readchar(-1);
|
||||
c = SERIAL_READCHAR(port_desc, 0);
|
||||
|
||||
if (c == SERIAL_TIMEOUT)
|
||||
break;
|
||||
|
||||
if (c < 0)
|
||||
break;
|
||||
putchar(c);
|
||||
perror_with_name("connect");
|
||||
|
||||
cx = c;
|
||||
|
||||
SERIAL_WRITE(tty_desc, &cx, 1);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void
|
||||
_initialize_serial ()
|
||||
{
|
||||
@ -187,4 +238,4 @@ _initialize_serial ()
|
||||
"Connect the terminal directly up to the command monitor.\n\
|
||||
Use <CR>~. or <CR>~^D to break out.");
|
||||
}
|
||||
#endif
|
||||
#endif /* 0 */
|
||||
|
21
gdb/serial.h
21
gdb/serial.h
@ -19,13 +19,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* Terminal state pointer. This is specific to each type of interface. */
|
||||
|
||||
typedef PTR ttystate;
|
||||
typedef PTR serial_ttystate;
|
||||
|
||||
struct _serial_t
|
||||
{
|
||||
int fd; /* File descriptor */
|
||||
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 */
|
||||
unsigned char *bufp; /* Current byte */
|
||||
unsigned char buf[BUFSIZ]; /* Da buffer itself */
|
||||
@ -42,7 +42,8 @@ struct serial_ops {
|
||||
int (*readchar) PARAMS ((serial_t, int timeout));
|
||||
int (*write) PARAMS ((serial_t, const char *str, int len));
|
||||
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));
|
||||
};
|
||||
|
||||
@ -52,6 +53,8 @@ void serial_add_interface PARAMS ((struct serial_ops *optable));
|
||||
|
||||
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
|
||||
examined. */
|
||||
|
||||
@ -60,10 +63,18 @@ serial_t serial_open PARAMS ((const char *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. */
|
||||
|
||||
#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.
|
||||
Returns char if ok, else one of the following codes. Note that all
|
||||
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)
|
||||
|
||||
/* Restore the serial port to the state saved in oldstate. XXX - currently
|
||||
unused! */
|
||||
|
||||
#define SERIAL_RESTORE(SERIAL_T) (SERIAL_T)->ops->restore((SERIAL_T))
|
||||
|
Loading…
Reference in New Issue
Block a user