* 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)
* 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
# 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 \

View File

@ -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 */

View File

@ -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, &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
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 *) &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
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]);
}
}

View File

@ -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;

View File

@ -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
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
#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

View File

@ -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 */

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. */
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))