📄 pty.c
字号:
/* * /dev/ptyXX (A first version for pseudo-terminals) * * Author: Fernando RUIZ CASAS (fernando.ruiz@ctv.es) * May 2001 * * 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. * * $Id: pty.c,v 1.3 2002/05/28 16:20:54 joel Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif/*-----------------------------------------*/#include <termios.h>#include <rtems.h>#include <rtems/libio.h>#include <rtems/pty.h>#include <rtems/bspIo.h>/*-----------------------------------------*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>/*-----------------------------------------*/#define IAC_ESC 255#define IAC_DONT 254#define IAC_DO 253#define IAC_WONT 252#define IAC_WILL 251#define IAC_SB 250#define IAC_GA 249#define IAC_EL 248#define IAC_EC 247#define IAC_AYT 246#define IAC_AO 245#define IAC_IP 244#define IAC_BRK 243#define IAC_DMARK 242#define IAC_NOP 241#define IAC_SE 240#define IAC_EOR 239struct pty_tt;typedef struct pty_tt pty_t;struct pty_tt { char *devname; struct rtems_termios_tty *ttyp; tcflag_t c_cflag; int opened; int socket; int last_cr; int iac_mode; };int ptys_initted=FALSE;pty_t ptys[MAX_PTYS];/* This procedure returns the devname for a pty slot free. * If not slot availiable (field socket>=0) * then the socket argument is closed */char * get_pty(int socket) { int ndx; if (!ptys_initted) return NULL; for (ndx=0;ndx<MAX_PTYS;ndx++) { if (ptys[ndx].socket<0) { ptys[ndx].socket=socket; return ptys[ndx].devname; }; }; close(socket); return NULL;}/*-----------------------------------------------------------*//* * The NVT terminal is negociated in PollRead and PollWrite * with every BYTE sendded or received. * A litle status machine in the pty_read_byte(int minor) * */const char IAC_AYT_RSP[]="\r\nAYT? Yes, RTEMS-SHELL is here\r\n";const char IAC_BRK_RSP[]="<*Break*>";const char IAC_IP_RSP []="<*Interrupt*>";staticint send_iac(int minor,unsigned char mode,unsigned char option) { unsigned char buf[3]; buf[0]=IAC_ESC; buf[1]=mode; buf[2]=option; return write(ptys[minor].socket,buf,sizeof(buf));}int read_pty(int minor) { /* Characters writed in the client side*/ unsigned char value; int count; int result; count=read(ptys[minor].socket,&value,sizeof(value)); if (count<1) { fclose(stdin); fclose(stdout); fclose(stderr); /* If you don't read from the socket the system ends the task */ rtems_task_delete(RTEMS_SELF); }; switch(ptys[minor].iac_mode) { case IAC_ESC: ptys[minor].iac_mode=0; switch(value) { case IAC_ESC : return IAC_ESC; case IAC_DONT: case IAC_DO : case IAC_WONT: case IAC_WILL: ptys[minor].iac_mode=value; return -1; case IAC_SB : return -100; case IAC_GA : return -1; case IAC_EL : return 0x03; /* Ctrl-C*/ case IAC_EC : return '\b'; case IAC_AYT : write(ptys[minor].socket,IAC_AYT_RSP,strlen(IAC_AYT_RSP)); return -1; case IAC_AO : return -1; case IAC_IP : write(ptys[minor].socket,IAC_IP_RSP,strlen(IAC_IP_RSP)); return -1; case IAC_BRK : write(ptys[minor].socket,IAC_BRK_RSP,strlen(IAC_BRK_RSP)); return -1; case IAC_DMARK: return -2; case IAC_NOP : return -1; case IAC_SE : return -101; case IAC_EOR : return -102; default : return -1; }; break; case IAC_WILL: ptys[minor].iac_mode=0; if (value==34){send_iac(minor,IAC_DONT, 34); /*LINEMODE*/ send_iac(minor,IAC_DO , 1);} else /*ECHO */ {send_iac(minor,IAC_DONT,value);}; return -1; case IAC_DONT: ptys[minor].iac_mode=0; return -1; case IAC_DO : ptys[minor].iac_mode=0; if (value==3) {send_iac(minor,IAC_WILL, 3);} else /* GO AHEAD*/ if (value==1) { } else /* ECHO */ {send_iac(minor,IAC_WONT,value);}; return -1; case IAC_WONT: ptys[minor].iac_mode=0; if (value==1) {send_iac(minor,IAC_WILL, 1);} else /* ECHO */ {send_iac(minor,IAC_WONT,value);}; return -1; default: ptys[minor].iac_mode=0; if (value==IAC_ESC) { ptys[minor].iac_mode=value; return -1; } else { result=value; if ((value=='\n') && (ptys[minor].last_cr)) result=-1; ptys[minor].last_cr=(value=='\r'); return result; }; }; }/*-----------------------------------------------------------*/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 int ptyPollWrite(int minor, const char * buf,int len) ;static int ptyPollRead(int minor) ;const rtems_termios_callbacks * pty_get_termios_handlers(int polled) ;/*-----------------------------------------------------------*//* Set the 'Hardware' */ /*-----------------------------------------------------------*/static intptySetAttributes(int minor,const struct termios *t) { if (minor<MAX_PTYS) { ptys[minor].c_cflag=t->c_cflag; } else { return -1; }; return 0;}/*-----------------------------------------------------------*/static int ptyPollInitialize(int major,int minor,void * arg) { rtems_libio_open_close_args_t * args = arg; struct termios t; if (minor<MAX_PTYS) { if (ptys[minor].socket<0) return -1; ptys[minor].opened=TRUE; ptys[minor].ttyp=args->iop->data1; t.c_cflag=B9600|CS8;/* termios default */ return ptySetAttributes(minor,&t); } else { return -1; };}/*-----------------------------------------------------------*/static int ptyShutdown(int major,int minor,void * arg) { if (minor<MAX_PTYS) { ptys[minor].opened=FALSE; if (ptys[minor].socket>=0) close(ptys[minor].socket); ptys[minor].socket=-1; chown(ptys[minor].devname,2,0); } else { return -1; }; return 0;}/*-----------------------------------------------------------*//* Write Characters into pty device */ /*-----------------------------------------------------------*/static intptyPollWrite(int minor, const char * buf,int len) { int count; if (minor<MAX_PTYS) { if (ptys[minor].socket<0) return -1; count=write(ptys[minor].socket,buf,len); } else { count=-1; }; return count;}/*-----------------------------------------------------------*/static intptyPollRead(int minor) { int result; if (minor<MAX_PTYS) { if (ptys[minor].socket<0) return -1; result=read_pty(minor); return result; }; return -1;}/*-----------------------------------------------------------*/static const rtems_termios_callbacks pty_poll_callbacks = { ptyPollInitialize, /* FirstOpen*/ ptyShutdown, /* LastClose*/ ptyPollRead, /* PollRead */ ptyPollWrite, /* Write */ ptySetAttributes, /* setAttributes */ NULL, /* stopRemoteTX */ NULL, /* StartRemoteTX */ 0 /* outputUsesInterrupts */};/*-----------------------------------------------------------*/const rtems_termios_callbacks * pty_get_termios_handlers(int polled) { return &pty_poll_callbacks;}/*-----------------------------------------------------------*/void init_ptys(void) { int ndx; for (ndx=0;ndx<MAX_PTYS;ndx++) { ptys[ndx].devname=malloc(strlen("/dev/ptyXX")+1); sprintf(ptys[ndx].devname,"/dev/pty%X",ndx); ptys[ndx].ttyp=NULL; ptys[ndx].c_cflag=CS8|B9600; ptys[ndx].socket=-1; ptys[ndx].opened=FALSE; }; ptys_initted=TRUE;}/*-----------------------------------------------------------*//* pty_initialize * * This routine initializes the pty IO driver. * * Input parameters: NONE * * Output parameters: NONE * * Return values: *//*-----------------------------------------------------------*/rtems_device_driver pty_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg){ int ndx; rtems_status_code status ; /* * Set up ptys */ init_ptys(); /* * Register the devices */ for (ndx=0;ndx<MAX_PTYS;ndx++) { status = rtems_io_register_name(ptys[ndx].devname, major, ndx); if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred(status); chmod(ptys[ndx].devname,0660); chown(ptys[ndx].devname,2,0); /* tty,root*/ }; printk("Device: /dev/pty%X../dev/pty%X (%d)pseudo-terminals registered.\n",0,MAX_PTYS-1,MAX_PTYS); return RTEMS_SUCCESSFUL;}/* * Open entry point */rtems_device_driver 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 */rtems_device_driver pty_close( rtems_device_major_number major, rtems_device_minor_number minor, void * arg){ return rtems_termios_close(arg);}/* * read bytes from the pty */rtems_device_driver pty_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg){ return rtems_termios_read(arg);}/* * write bytes to the pty */rtems_device_driver pty_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg){ return rtems_termios_write(arg);}/* * IO Control entry point */rtems_device_driver pty_control( rtems_device_major_number major, rtems_device_minor_number minor, void * arg){ return rtems_termios_ioctl(arg);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -