forked from Imagelibrary/rtems
@@ -16,58 +16,25 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/termiostypes.h>
|
||||
|
||||
/* Number of ptys to setup */
|
||||
extern size_t rtems_pty_maximum_ptys;
|
||||
#define RTEMS_PTY_SB_MAX 16
|
||||
|
||||
/* Return the devname for a free pty slot.
|
||||
* If no slot available (socket>=0)
|
||||
* then the socket argument is closed
|
||||
*/
|
||||
char * rtems_pty_get(int socket);
|
||||
typedef struct {
|
||||
rtems_termios_device_context base;
|
||||
rtems_termios_tty *ttyp;
|
||||
tcflag_t c_cflag;
|
||||
int socket;
|
||||
int last_cr;
|
||||
unsigned iac_mode;
|
||||
unsigned char sb_buf[RTEMS_PTY_SB_MAX];
|
||||
int sb_ind;
|
||||
int width;
|
||||
int height;
|
||||
char name[sizeof("/dev/pty18446744073709551615")];
|
||||
} rtems_pty_context;
|
||||
|
||||
|
||||
/* OBSOLETE */
|
||||
#define get_pty rtems_pty_get
|
||||
|
||||
rtems_device_driver pty_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg);
|
||||
rtems_device_driver pty_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg);
|
||||
rtems_device_driver pty_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg);
|
||||
rtems_device_driver pty_read(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg);
|
||||
rtems_device_driver pty_write(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg);
|
||||
rtems_device_driver pty_control(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg);
|
||||
|
||||
|
||||
#define PTY_DRIVER_TABLE_ENTRY \
|
||||
{ pty_initialize , pty_open , pty_close , \
|
||||
pty_read , pty_write , pty_control }
|
||||
|
||||
/* Internal functions */
|
||||
|
||||
int telnet_pty_initialize(void);
|
||||
|
||||
int telnet_pty_finalize(void);
|
||||
|
||||
char *telnet_get_pty(int);
|
||||
char *telnet_get_pty(rtems_pty_context *ctx, int socket);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -29,16 +29,13 @@
|
||||
/* #define DEBUG DEBUG_WH */
|
||||
|
||||
/*-----------------------------------------*/
|
||||
#include <termios.h>
|
||||
#include <rtems/termiostypes.h>
|
||||
#include <sys/ttycom.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/bspIo.h>
|
||||
#include <rtems/pty.h>
|
||||
#include <rtems/seterr.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
/*-----------------------------------------*/
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -63,42 +60,38 @@
|
||||
#define IAC_SE 240
|
||||
#define IAC_EOR 239
|
||||
|
||||
#define SB_MAX 16
|
||||
#define SB_MAX RTEMS_PTY_SB_MAX
|
||||
|
||||
extern int rtems_telnetd_maximum_ptys;
|
||||
static bool ptyPollInitialize(rtems_termios_tty *,
|
||||
rtems_termios_device_context *, struct termios *,
|
||||
rtems_libio_open_close_args_t *);
|
||||
static void ptyShutdown(rtems_termios_tty *,
|
||||
rtems_termios_device_context *, rtems_libio_open_close_args_t *);
|
||||
static void ptyPollWrite(rtems_termios_device_context *, const char *, size_t);
|
||||
static int ptyPollRead(rtems_termios_device_context *);
|
||||
static bool ptySetAttributes(rtems_termios_device_context *,
|
||||
const struct termios *);
|
||||
static int my_pty_control(rtems_termios_device_context *,
|
||||
ioctl_command_t, void *);
|
||||
|
||||
struct pty_tt;
|
||||
typedef struct pty_tt pty_t;
|
||||
|
||||
struct pty_tt {
|
||||
char devname[17];
|
||||
struct rtems_termios_tty *ttyp;
|
||||
tcflag_t c_cflag;
|
||||
int opened;
|
||||
int socket;
|
||||
int last_cr;
|
||||
unsigned iac_mode;
|
||||
unsigned char sb_buf[SB_MAX];
|
||||
int sb_ind;
|
||||
int width;
|
||||
int height;
|
||||
static const rtems_termios_device_handler pty_handler = {
|
||||
.first_open = ptyPollInitialize,
|
||||
.last_close = ptyShutdown,
|
||||
.poll_read = ptyPollRead,
|
||||
.write = ptyPollWrite,
|
||||
.set_attributes = ptySetAttributes,
|
||||
.ioctl = my_pty_control
|
||||
};
|
||||
|
||||
|
||||
static int telnet_pty_inited=FALSE;
|
||||
static pty_t *telnet_ptys;
|
||||
|
||||
static rtems_device_major_number pty_major;
|
||||
|
||||
static
|
||||
int send_iac(int minor,unsigned char mode,unsigned char option)
|
||||
int send_iac(rtems_pty_context *pty, unsigned char mode, unsigned char option)
|
||||
{
|
||||
unsigned char buf[3];
|
||||
|
||||
buf[0]=IAC_ESC;
|
||||
buf[1]=mode;
|
||||
buf[2]=option;
|
||||
return write(telnet_ptys[minor].socket,buf,sizeof(buf));
|
||||
return write(pty->socket, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
/* This procedure returns the devname for a pty slot free.
|
||||
@@ -106,42 +99,31 @@ int send_iac(int minor,unsigned char mode,unsigned char option)
|
||||
* then the socket argument is closed
|
||||
*/
|
||||
|
||||
char * telnet_get_pty(int socket)
|
||||
char *telnet_get_pty(rtems_pty_context *pty, int socket)
|
||||
{
|
||||
int ndx;
|
||||
rtems_status_code sc;
|
||||
struct timeval t;
|
||||
|
||||
if (telnet_pty_inited) {
|
||||
#if 0
|
||||
if ( rtems_telnetd_maximum_ptys < 5 )
|
||||
rtems_telnetd_maximum_ptys = 5;
|
||||
|
||||
telnet_ptys = malloc( rtems_telnetd_maximum_ptys * sizeof (pty_t) );
|
||||
#endif
|
||||
if ( !telnet_ptys ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (ndx=0;ndx<rtems_telnetd_maximum_ptys;ndx++) {
|
||||
|
||||
if (telnet_ptys[ndx].socket<0) {
|
||||
struct timeval t;
|
||||
/* set a long polling interval to save CPU time */
|
||||
t.tv_sec=2;
|
||||
t.tv_usec=00000;
|
||||
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
|
||||
telnet_ptys[ndx].socket=socket;
|
||||
|
||||
/* inform the client that we will echo */
|
||||
send_iac(ndx, IAC_WILL, 1);
|
||||
|
||||
return telnet_ptys[ndx].devname;
|
||||
};
|
||||
};
|
||||
memset(pty, 0, sizeof(*pty));
|
||||
snprintf(pty->name, sizeof(pty->name), "/dev/pty%" PRIuPTR, (uintptr_t)pty);
|
||||
rtems_termios_device_context_initialize(&pty->base, "pty");
|
||||
pty->socket = socket;
|
||||
sc = rtems_termios_device_install(pty->name, &pty_handler, NULL, &pty->base);
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
close(socket);
|
||||
return NULL;
|
||||
}
|
||||
close(socket);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set a long polling interval to save CPU time */
|
||||
t.tv_sec=2;
|
||||
t.tv_usec=00000;
|
||||
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
|
||||
|
||||
/* inform the client that we will echo */
|
||||
send_iac(pty, IAC_WILL, 1);
|
||||
|
||||
return pty->name;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
@@ -155,7 +137,7 @@ static const char IAC_BRK_RSP[]="<*Break*>";
|
||||
static const char IAC_IP_RSP []="<*Interrupt*>";
|
||||
|
||||
static int
|
||||
handleSB(pty_t *pty)
|
||||
handleSB(rtems_pty_context *pty)
|
||||
{
|
||||
switch (pty->sb_buf[0]) {
|
||||
case 31: /* NAWS */
|
||||
@@ -174,13 +156,13 @@ handleSB(pty_t *pty)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_pty(int minor)
|
||||
static int ptyPollRead(rtems_termios_device_context *base)
|
||||
{ /* Characters written to the client side*/
|
||||
rtems_pty_context *pty = (rtems_pty_context *)base;
|
||||
unsigned char value;
|
||||
unsigned int omod;
|
||||
int count;
|
||||
int result;
|
||||
pty_t *pty=telnet_ptys+minor;
|
||||
|
||||
count=read(pty->socket,&value,sizeof(value));
|
||||
if (count<0)
|
||||
@@ -272,33 +254,33 @@ static int read_pty(int minor)
|
||||
|
||||
case IAC_WILL:
|
||||
if (value==34){
|
||||
send_iac(minor,IAC_DONT, 34); /*LINEMODE*/
|
||||
send_iac(minor,IAC_DO , 1); /*ECHO */
|
||||
send_iac(pty,IAC_DONT, 34); /*LINEMODE*/
|
||||
send_iac(pty,IAC_DO , 1); /*ECHO */
|
||||
} else if (value==31) {
|
||||
send_iac(minor,IAC_DO , 31); /*NAWS */
|
||||
send_iac(pty,IAC_DO , 31); /*NAWS */
|
||||
#if DEBUG & DEBUG_DETAIL
|
||||
printk("replied DO NAWS\n");
|
||||
#endif
|
||||
} else {
|
||||
send_iac(minor,IAC_DONT,value);
|
||||
send_iac(pty,IAC_DONT,value);
|
||||
}
|
||||
return -1;
|
||||
case IAC_DONT:
|
||||
return -1;
|
||||
case IAC_DO :
|
||||
if (value==3) {
|
||||
send_iac(minor,IAC_WILL, 3); /* GO AHEAD*/
|
||||
send_iac(pty,IAC_WILL, 3); /* GO AHEAD*/
|
||||
} else if (value==1) {
|
||||
send_iac(minor,IAC_WILL, 1); /* ECHO */
|
||||
send_iac(pty,IAC_WILL, 1); /* ECHO */
|
||||
} else {
|
||||
send_iac(minor,IAC_WONT,value);
|
||||
send_iac(pty,IAC_WONT,value);
|
||||
};
|
||||
return -1;
|
||||
case IAC_WONT:
|
||||
if (value==1) {
|
||||
send_iac(minor,IAC_WILL, 1);
|
||||
send_iac(pty,IAC_WILL, 1);
|
||||
} else { /* ECHO */
|
||||
send_iac(minor,IAC_WONT,value);
|
||||
send_iac(pty,IAC_WONT,value);
|
||||
}
|
||||
return -1;
|
||||
default:
|
||||
@@ -321,277 +303,75 @@ static int read_pty(int minor)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
static int ptySetAttributes(int minor,const struct termios *t);
|
||||
static int ptyPollInitialize(int major,int minor,void * arg) ;
|
||||
static int ptyShutdown(int major,int minor,void * arg) ;
|
||||
static ssize_t ptyPollWrite(int minor, const char * buf, size_t len) ;
|
||||
static int ptyPollRead(int minor) ;
|
||||
static const rtems_termios_callbacks * pty_get_termios_handlers(int polled) ;
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Set the 'Hardware' */
|
||||
/*-----------------------------------------------------------*/
|
||||
static int
|
||||
ptySetAttributes(int minor,const struct termios *t) {
|
||||
if (minor<rtems_telnetd_maximum_ptys) {
|
||||
telnet_ptys[minor].c_cflag=t->c_cflag;
|
||||
} else {
|
||||
return -1;
|
||||
};
|
||||
return 0;
|
||||
static bool
|
||||
ptySetAttributes(rtems_termios_device_context *base, const struct termios *t)
|
||||
{
|
||||
rtems_pty_context *pty = (rtems_pty_context *)base;
|
||||
pty->c_cflag = t->c_cflag;
|
||||
return true;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
static int
|
||||
ptyPollInitialize(int major,int minor,void * arg) {
|
||||
rtems_libio_open_close_args_t * args = (rtems_libio_open_close_args_t*)arg;
|
||||
struct termios t;
|
||||
if (minor<rtems_telnetd_maximum_ptys) {
|
||||
if (telnet_ptys[minor].socket<0) return -1;
|
||||
telnet_ptys[minor].opened=TRUE;
|
||||
telnet_ptys[minor].ttyp= (struct rtems_termios_tty *) args->iop->data1;
|
||||
telnet_ptys[minor].iac_mode=0;
|
||||
telnet_ptys[minor].sb_ind=0;
|
||||
telnet_ptys[minor].width=0;
|
||||
telnet_ptys[minor].height=0;
|
||||
t.c_cflag=B9600|CS8;/* termios default */
|
||||
return ptySetAttributes(minor,&t);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
static bool
|
||||
ptyPollInitialize(rtems_termios_tty *ttyp,
|
||||
rtems_termios_device_context *base, struct termios *t,
|
||||
rtems_libio_open_close_args_t *args)
|
||||
{
|
||||
rtems_pty_context *pty = (rtems_pty_context *)base;
|
||||
pty->ttyp = ttyp;
|
||||
pty->iac_mode = 0;
|
||||
pty->sb_ind = 0;
|
||||
pty->width = 0;
|
||||
pty->height = 0;
|
||||
return ptySetAttributes(&pty->base, t);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
static int
|
||||
ptyShutdown(int major,int minor,void * arg) {
|
||||
if (minor<rtems_telnetd_maximum_ptys) {
|
||||
telnet_ptys[minor].opened=FALSE;
|
||||
if (telnet_ptys[minor].socket>=0) close(telnet_ptys[minor].socket);
|
||||
telnet_ptys[minor].socket=-1;
|
||||
chown(telnet_ptys[minor].devname,2,0);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
static void
|
||||
ptyShutdown(rtems_termios_tty *ttyp,
|
||||
rtems_termios_device_context *base, rtems_libio_open_close_args_t *arg)
|
||||
{
|
||||
rtems_pty_context *pty = (rtems_pty_context *)base;
|
||||
close(pty->socket);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Write Characters into pty device */
|
||||
/*-----------------------------------------------------------*/
|
||||
static ssize_t
|
||||
ptyPollWrite(int minor, const char * buf, size_t len) {
|
||||
size_t count;
|
||||
if (minor<rtems_telnetd_maximum_ptys) {
|
||||
if (telnet_ptys[minor].socket<0)
|
||||
return -1;
|
||||
count=write(telnet_ptys[minor].socket,buf,len);
|
||||
} else {
|
||||
count=-1;
|
||||
static void
|
||||
ptyPollWrite(rtems_termios_device_context *base, const char *buf, size_t len)
|
||||
{
|
||||
rtems_pty_context *pty = (rtems_pty_context *)base;
|
||||
|
||||
while (len > 0) {
|
||||
ssize_t n = write(pty->socket, buf, len);
|
||||
if (n <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
buf += (size_t)n;
|
||||
len -= (size_t)n;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
ptyPollRead(int minor) {
|
||||
int result;
|
||||
|
||||
if (minor<rtems_telnetd_maximum_ptys) {
|
||||
if (telnet_ptys[minor].socket<0)
|
||||
return -1;
|
||||
result=read_pty(minor);
|
||||
return result;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/* pty_initialize
|
||||
*
|
||||
* This routine initializes the pty IO driver.
|
||||
*
|
||||
* Input parameters: NONE
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* Return values:
|
||||
*/
|
||||
/*-----------------------------------------------------------*/
|
||||
static
|
||||
rtems_device_driver my_pty_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
my_pty_control(rtems_termios_device_context *base,
|
||||
ioctl_command_t request, void *buffer)
|
||||
{
|
||||
int ndx;
|
||||
rtems_status_code status;
|
||||
|
||||
if ( rtems_telnetd_maximum_ptys < 5 )
|
||||
rtems_telnetd_maximum_ptys = 5;
|
||||
|
||||
telnet_ptys = malloc( rtems_telnetd_maximum_ptys * sizeof (pty_t) );
|
||||
|
||||
/*
|
||||
* Set up ptys
|
||||
*/
|
||||
|
||||
for (ndx=0;ndx<rtems_telnetd_maximum_ptys;ndx++) {
|
||||
/* devname is included in the structure */
|
||||
sprintf(telnet_ptys[ndx].devname,"/dev/pty%02X",ndx);
|
||||
telnet_ptys[ndx].ttyp = NULL;
|
||||
telnet_ptys[ndx].c_cflag = CS8|B9600;
|
||||
telnet_ptys[ndx].socket = -1;
|
||||
telnet_ptys[ndx].opened = FALSE;
|
||||
telnet_ptys[ndx].sb_ind = 0;
|
||||
telnet_ptys[ndx].width = 0;
|
||||
telnet_ptys[ndx].height = 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the devices
|
||||
*/
|
||||
for (ndx=0;ndx<rtems_telnetd_maximum_ptys;ndx++) {
|
||||
status = rtems_io_register_name(telnet_ptys[ndx].devname, major, ndx);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
rtems_fatal_error_occurred(status);
|
||||
chmod(telnet_ptys[ndx].devname,0660);
|
||||
chown(telnet_ptys[ndx].devname,2,0); /* tty,root*/
|
||||
};
|
||||
syslog(
|
||||
LOG_KERN | LOG_INFO,
|
||||
"/dev/pty%X../dev/pty%X (%d) pseudo-terminals registered.\n",
|
||||
0,
|
||||
rtems_telnetd_maximum_ptys - 1,
|
||||
rtems_telnetd_maximum_ptys
|
||||
);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int pty_do_finalize(void)
|
||||
{
|
||||
int ndx;
|
||||
rtems_status_code status;
|
||||
|
||||
if ( !telnet_pty_inited )
|
||||
return 0;
|
||||
|
||||
for (ndx=0;ndx<rtems_telnetd_maximum_ptys;ndx++) {
|
||||
if (telnet_ptys[ndx].opened) {
|
||||
fprintf(stderr,
|
||||
"There are still opened PTY devices, unable to proceed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (RTEMS_SUCCESSFUL != rtems_io_unregister_driver(pty_major)) {
|
||||
fprintf(stderr,"Unable to remove this driver\n");
|
||||
return -1;
|
||||
}
|
||||
for (ndx=0;ndx<rtems_telnetd_maximum_ptys;ndx++) {
|
||||
/* rtems_io_register_name() actually creates a node in the filesystem
|
||||
* (mknod())
|
||||
*/
|
||||
status = (rtems_status_code)unlink(telnet_ptys[ndx].devname);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
perror("removing pty device node from file system");
|
||||
else {
|
||||
telnet_ptys[ndx].devname[0] = '\0';
|
||||
}
|
||||
};
|
||||
|
||||
free ( telnet_ptys );
|
||||
|
||||
fprintf(stderr,"PTY driver unloaded successfully\n");
|
||||
telnet_pty_inited=FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open entry point
|
||||
*/
|
||||
|
||||
static
|
||||
rtems_device_driver my_pty_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
sc = rtems_termios_open(major,minor,arg,pty_get_termios_handlers(FALSE));
|
||||
return sc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close entry point
|
||||
*/
|
||||
|
||||
static
|
||||
rtems_device_driver my_pty_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
)
|
||||
{
|
||||
return rtems_termios_close(arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* read bytes from the pty
|
||||
*/
|
||||
|
||||
static
|
||||
rtems_device_driver my_pty_read(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
)
|
||||
{
|
||||
return rtems_termios_read(arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* write bytes to the pty
|
||||
*/
|
||||
|
||||
static
|
||||
rtems_device_driver my_pty_write(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
)
|
||||
{
|
||||
return rtems_termios_write(arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* IO Control entry point
|
||||
*/
|
||||
|
||||
static
|
||||
rtems_device_driver my_pty_control(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
)
|
||||
{
|
||||
rtems_libio_ioctl_args_t *args = (rtems_libio_ioctl_args_t*)arg;
|
||||
struct winsize *wp = (struct winsize*)args->buffer;
|
||||
pty_t *p = &telnet_ptys[minor];
|
||||
|
||||
switch (args->command) {
|
||||
rtems_pty_context *p = (rtems_pty_context *)base;
|
||||
struct winsize *wp = buffer;
|
||||
|
||||
switch (request) {
|
||||
case TIOCGWINSZ:
|
||||
|
||||
wp->ws_row = p->height;
|
||||
wp->ws_col = p->width;
|
||||
args->ioctl_return=0;
|
||||
#if DEBUG & DEBUG_WH
|
||||
fprintf(stderr,
|
||||
"ioctl(TIOCGWINSZ), returning %ix%i\n",
|
||||
wp->ws_col,
|
||||
wp->ws_row);
|
||||
#endif
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
case TIOCSWINSZ:
|
||||
#if DEBUG & DEBUG_WH
|
||||
fprintf(stderr,
|
||||
@@ -602,61 +382,11 @@ rtems_device_driver my_pty_control(
|
||||
|
||||
p->height = wp->ws_row;
|
||||
p->width = wp->ws_col;
|
||||
args->ioctl_return=0;
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
rtems_set_errno_and_return_minus_one(EINVAL);
|
||||
break;
|
||||
}
|
||||
|
||||
return rtems_termios_ioctl(arg);
|
||||
}
|
||||
|
||||
static rtems_driver_address_table drvPty = {
|
||||
my_pty_initialize,
|
||||
my_pty_open,
|
||||
my_pty_close,
|
||||
my_pty_read,
|
||||
my_pty_write,
|
||||
my_pty_control
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
static const rtems_termios_callbacks pty_poll_callbacks = {
|
||||
ptyPollInitialize, /* FirstOpen */
|
||||
ptyShutdown, /* LastClose */
|
||||
ptyPollRead, /* PollRead */
|
||||
ptyPollWrite, /* Write */
|
||||
ptySetAttributes, /* setAttributes */
|
||||
NULL, /* stopRemoteTX */
|
||||
NULL, /* StartRemoteTX */
|
||||
0 /* outputUsesInterrupts */
|
||||
};
|
||||
/*-----------------------------------------------------------*/
|
||||
static const rtems_termios_callbacks * pty_get_termios_handlers(int polled) {
|
||||
return &pty_poll_callbacks;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int pty_do_initialize(void)
|
||||
{
|
||||
if ( !telnet_pty_inited ) {
|
||||
if (RTEMS_SUCCESSFUL==rtems_io_register_driver(0, &drvPty, &pty_major))
|
||||
telnet_pty_inited=TRUE;
|
||||
else
|
||||
fprintf(stderr,"WARNING: registering the PTY driver FAILED\n");
|
||||
}
|
||||
return telnet_pty_inited;
|
||||
}
|
||||
|
||||
int telnet_pty_initialize(void)
|
||||
{
|
||||
return pty_do_initialize();
|
||||
}
|
||||
|
||||
int telnet_pty_finalize(void)
|
||||
{
|
||||
return pty_do_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -64,14 +64,11 @@
|
||||
|
||||
#define PARANOIA
|
||||
|
||||
extern char *telnet_get_pty(int socket);
|
||||
extern int telnet_pty_initialize(void);
|
||||
|
||||
struct shell_args {
|
||||
char *devname;
|
||||
void *arg;
|
||||
char peername[16];
|
||||
char delete_myself;
|
||||
rtems_pty_context pty;
|
||||
void *arg;
|
||||
char peername[16];
|
||||
char delete_myself;
|
||||
};
|
||||
|
||||
typedef union uni_sa {
|
||||
@@ -107,17 +104,23 @@ static const rtems_id (*telnetd_spawn_task)(
|
||||
void *
|
||||
) = telnetd_dflt_spawn;
|
||||
|
||||
static char *grab_a_Connection(
|
||||
static struct shell_args *grab_a_Connection(
|
||||
int des_socket,
|
||||
uni_sa *srv,
|
||||
char *peername,
|
||||
int sz
|
||||
)
|
||||
{
|
||||
char *rval = 0;
|
||||
struct shell_args *args = NULL;
|
||||
socklen_t size_adr = sizeof(srv->sin);
|
||||
int acp_sock;
|
||||
|
||||
args = malloc(sizeof(*args));
|
||||
if (args == NULL) {
|
||||
perror("telnetd:malloc");
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
acp_sock = accept(des_socket,&srv->sa,&size_adr);
|
||||
|
||||
if (acp_sock<0) {
|
||||
@@ -125,7 +128,7 @@ static char *grab_a_Connection(
|
||||
goto bailout;
|
||||
};
|
||||
|
||||
if ( !(rval=telnet_get_pty(acp_sock)) ) {
|
||||
if (telnet_get_pty(&args->pty, acp_sock) == NULL) {
|
||||
syslog( LOG_DAEMON | LOG_ERR, "telnetd: unable to obtain PTY");
|
||||
/* NOTE: failing 'do_get_pty()' closed the socket */
|
||||
goto bailout;
|
||||
@@ -138,12 +141,12 @@ static char *grab_a_Connection(
|
||||
syslog(LOG_DAEMON | LOG_INFO,
|
||||
"telnetd: accepted connection from %s on %s",
|
||||
peername,
|
||||
rval);
|
||||
args->pty.name);
|
||||
#endif
|
||||
|
||||
bailout:
|
||||
|
||||
return rval;
|
||||
return args;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +163,7 @@ static void release_a_Connection(char *devname, char *peername, FILE **pstd, int
|
||||
while (--n>=0)
|
||||
if (pstd[n]) fclose(pstd[n]);
|
||||
|
||||
unlink(devname);
|
||||
}
|
||||
|
||||
static int sockpeername(int sock, char *buf, int bufsz)
|
||||
@@ -186,7 +190,6 @@ rtems_task_telnetd(void *task_argument)
|
||||
{
|
||||
int des_socket;
|
||||
uni_sa srv;
|
||||
char *devname;
|
||||
char peername[16];
|
||||
int i=1;
|
||||
int size_adr;
|
||||
@@ -243,22 +246,19 @@ rtems_task_telnetd(void *task_argument)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
devname = grab_a_Connection(des_socket, &srv, peername, sizeof(peername));
|
||||
arg = grab_a_Connection(des_socket, &srv, peername, sizeof(peername));
|
||||
|
||||
if ( !devname ) {
|
||||
if (arg == NULL) {
|
||||
/* if something went wrong, sleep for some time */
|
||||
sleep(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
arg = malloc( sizeof(*arg) );
|
||||
|
||||
arg->devname = devname;
|
||||
arg->arg = telnetd_config->arg;
|
||||
strncpy(arg->peername, peername, sizeof(arg->peername));
|
||||
|
||||
telnetd_task_id = telnetd_spawn_task(
|
||||
devname,
|
||||
arg->pty.name,
|
||||
telnetd_config->priority,
|
||||
telnetd_config->stack_size,
|
||||
spawned_shell,
|
||||
@@ -278,9 +278,9 @@ rtems_task_telnetd(void *task_argument)
|
||||
* a stream...
|
||||
*/
|
||||
|
||||
if ( !(dummy=fopen(devname,"r+")) )
|
||||
if ( !(dummy=fopen(arg->pty.name,"r+")) )
|
||||
perror("Unable to dummy open the pty, losing a slot :-(");
|
||||
release_a_Connection(devname, peername, &dummy, 1);
|
||||
release_a_Connection(arg->pty.name, peername, &dummy, 1);
|
||||
free(arg);
|
||||
sleep(2); /* don't accept connections too fast */
|
||||
}
|
||||
@@ -315,14 +315,6 @@ rtems_status_code rtems_telnetd_start(const rtems_telnetd_config_table* config)
|
||||
return RTEMS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
if ( !telnet_pty_initialize() ) {
|
||||
fprintf(stderr, "telnetd cannot initialize PTY driver\n");
|
||||
free(telnetd_config);
|
||||
telnetd_config = NULL;
|
||||
return RTEMS_IO_ERROR;
|
||||
}
|
||||
|
||||
*telnetd_config = *config;
|
||||
|
||||
/* Check priority */
|
||||
@@ -396,7 +388,7 @@ spawned_shell(void *targ)
|
||||
|
||||
/* redirect stdio */
|
||||
for (i=0; i<3; i++) {
|
||||
if ( !(nstd[i]=fopen(arg->devname,"r+")) ) {
|
||||
if ( !(nstd[i]=fopen(arg->pty.name,"r+")) ) {
|
||||
perror("unable to open stdio");
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -418,13 +410,13 @@ spawned_shell(void *targ)
|
||||
start = rtems_shell_login_prompt(
|
||||
stdin,
|
||||
stderr,
|
||||
arg->devname,
|
||||
arg->pty.name,
|
||||
telnetd_config->login_check
|
||||
);
|
||||
login_failed = !start;
|
||||
}
|
||||
if (start) {
|
||||
telnetd_config->command( arg->devname, arg->arg);
|
||||
telnetd_config->command( arg->pty.name, arg->arg);
|
||||
}
|
||||
|
||||
stdin = ostd[0];
|
||||
@@ -440,7 +432,7 @@ spawned_shell(void *targ)
|
||||
}
|
||||
|
||||
cleanup:
|
||||
release_a_Connection(arg->devname, arg->peername, nstd, i);
|
||||
release_a_Connection(arg->pty.name, arg->peername, nstd, i);
|
||||
free(arg);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user