source: rtems/cpukit/telnetd/pty.c @ bd520203

4.104.114.84.95
Last change on this file since bd520203 was bd520203, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 9, 2001 at 10:06:51 PM

2001-08-09 Fernando-Ruiz Casas <correo@…>

  • Makefile.am, configure.in, rtems_servers/Makefile.am, rtems_servers/telnetd.c, rtems_servers/telnetd.h, rtems_telnetd/Makefile.am, rtems_telnetd/README, rtems_telnetd/icmds.c, rtems_telnetd/pty.c, rtems_telnetd/pty.h, rtems_telnetd/telnetd.c, rtems_telnetd/telnetd.h, wrapup/Makefile.am:
    • pty and telnetd have a new subdir rtems_telnetd to avoid the side effect when ftpd change.
    • the tcp/ip stats have been implemented into icmds.c and started when telnetd daemon is started.
  • rtems_servers/telnetd.c, rtems_servers/telnetd.h: Removed.
  • rtems_telnetd: New directory.
  • rtems_telnetd/Makefile.am, rtems_telnetd/README, rtems_telnetd/icmds.c, rtems_telnetd/pty.c, rtems_telnetd/pty.h, rtems_telnetd/telnetd.c, rtems_telnetd/telnetd.h: New files.
  • Property mode set to 100644
File size: 10.3 KB
Line 
1/*
2 * /dev/ptyXX  (A first version for pseudo-terminals)
3 *
4 *  Author: Fernando RUIZ CASAS (fernando.ruiz@ctv.es)
5 *  May 2001
6 *
7 *  This program is distributed in the hope that it will be useful,
8 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 *
11 *  $Id$
12 */
13/*-----------------------------------------*/
14#include <termios.h>
15#include <rtems.h>
16#include <rtems/libio.h>
17#include <bsp.h>
18#include <rtems/pty.h>
19/*-----------------------------------------*/
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24/*-----------------------------------------*/
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28/*-----------------------------------------*/
29#define printk printf
30/*-----------------------------------------*/
31#define IAC_ESC    255
32#define IAC_DONT   254
33#define IAC_DO     253
34#define IAC_WONT   252
35#define IAC_WILL   251
36#define IAC_SB     250
37#define IAC_GA     249
38#define IAC_EL     248
39#define IAC_EC     247
40#define IAC_AYT    246
41#define IAC_AO     245
42#define IAC_IP     244
43#define IAC_BRK    243
44#define IAC_DMARK  242
45#define IAC_NOP    241
46#define IAC_SE     240
47#define IAC_EOR    239
48
49struct pty_tt;
50typedef struct pty_tt pty_t;
51
52struct pty_tt {
53 char                     *devname;
54 struct rtems_termios_tty *ttyp;
55 tcflag_t                  c_cflag;
56 int                       opened;
57 int                       socket;
58
59 int                       last_cr;
60 int                       iac_mode;   
61};
62
63
64int ptys_initted=FALSE;
65pty_t ptys[MAX_PTYS];
66
67/* This procedure returns the devname for a pty slot free.
68 * If not slot availiable (field socket>=0)
69 *  then the socket argument is closed
70 */
71
72char *  get_pty(int socket) {
73        int ndx;
74        if (!ptys_initted) return NULL;
75        for (ndx=0;ndx<MAX_PTYS;ndx++) {
76                if (ptys[ndx].socket<0) {
77                        ptys[ndx].socket=socket;
78                        return ptys[ndx].devname;
79                };
80        };
81        close(socket);
82        return NULL;
83}
84
85
86/*-----------------------------------------------------------*/
87/*
88 * The NVT terminal is negociated in PollRead and PollWrite
89 * with every BYTE sendded or received.
90 * A litle status machine in the pty_read_byte(int minor)
91 *
92 */
93const char IAC_AYT_RSP[]="\r\nAYT? Yes, RTEMS-SHELL is here\r\n";
94const char IAC_BRK_RSP[]="<*Break*>";
95const char IAC_IP_RSP []="<*Interrupt*>";
96
97
98static
99int send_iac(int minor,unsigned char mode,unsigned char option) {
100        unsigned char buf[3];
101        buf[0]=IAC_ESC;
102        buf[1]=mode;
103        buf[2]=option;
104        return write(ptys[minor].socket,buf,sizeof(buf));
105}
106
107int read_pty(int minor) { /* Characters writed in the client side*/
108         unsigned char value;
109         int count;
110         int result;
111         count=read(ptys[minor].socket,&value,sizeof(value));
112         if (count<1) {
113          fclose(stdin);                 
114          fclose(stdout);               
115          fclose(stderr);               
116          /* If you don't read from the socket the system ends the task */
117          rtems_task_delete(RTEMS_SELF);
118         };
119         switch(ptys[minor].iac_mode) {
120          case IAC_ESC:
121               ptys[minor].iac_mode=0;
122               switch(value) {
123                case IAC_ESC :
124                     return IAC_ESC;
125                case IAC_DONT:
126                case IAC_DO  :
127                case IAC_WONT:
128                case IAC_WILL:
129                     ptys[minor].iac_mode=value;
130                     return -1;
131                case IAC_SB  :
132                     return -100;
133                case IAC_GA  :
134                     return -1;
135                case IAC_EL  :
136                     return 0x03; /* Ctrl-C*/
137                case IAC_EC  :
138                     return '\b';
139                case IAC_AYT :
140                     write(ptys[minor].socket,IAC_AYT_RSP,strlen(IAC_AYT_RSP));
141                     return -1;
142                case IAC_AO  :
143                     return -1;
144                case IAC_IP  :
145                     write(ptys[minor].socket,IAC_IP_RSP,strlen(IAC_IP_RSP));
146                     return -1;
147                case IAC_BRK :
148                     write(ptys[minor].socket,IAC_BRK_RSP,strlen(IAC_BRK_RSP));
149                     return -1;
150                case IAC_DMARK:
151                     return -2;
152                case IAC_NOP :
153                     return -1;
154                case IAC_SE  :
155                     return -101;
156                case IAC_EOR :
157                     return -102;
158                default      :
159                     return -1;
160               };
161               break;
162          case IAC_WILL:
163               ptys[minor].iac_mode=0;
164               if (value==34){send_iac(minor,IAC_DONT,   34);       /*LINEMODE*/ 
165                              send_iac(minor,IAC_DO  ,    1);} else /*ECHO    */
166                             {send_iac(minor,IAC_DONT,value);};
167               return -1;
168          case IAC_DONT:
169               ptys[minor].iac_mode=0;
170               return -1;
171          case IAC_DO  :
172               ptys[minor].iac_mode=0;
173               if (value==3) {send_iac(minor,IAC_WILL,    3);} else /* GO AHEAD*/
174               if (value==1) {                               } else /* ECHO */
175                             {send_iac(minor,IAC_WONT,value);};
176               return -1;
177          case IAC_WONT:
178               ptys[minor].iac_mode=0;
179               if (value==1) {send_iac(minor,IAC_WILL,    1);} else /* ECHO */
180                             {send_iac(minor,IAC_WONT,value);};
181               return -1;
182          default:
183               ptys[minor].iac_mode=0;
184               if (value==IAC_ESC) {
185                     ptys[minor].iac_mode=value;
186                     return -1;
187               } else {
188                     result=value; 
189                     if ((value=='\n') && (ptys[minor].last_cr)) result=-1;
190                     ptys[minor].last_cr=(value=='\r');
191                     return result;
192               };
193         };
194       
195}
196
197/*-----------------------------------------------------------*/
198static int ptySetAttributes(int minor,const struct termios *t);
199static int ptyPollInitialize(int major,int minor,void * arg) ;
200static int ptyShutdown(int major,int minor,void * arg) ;
201static int ptyPollWrite(int minor, const char * buf,int len) ;
202static int ptyPollRead(int minor) ;
203const rtems_termios_callbacks * pty_get_termios_handlers(int polled) ;
204/*-----------------------------------------------------------*/
205/* Set the 'Hardware'                                        */ 
206/*-----------------------------------------------------------*/
207static int
208ptySetAttributes(int minor,const struct termios *t) {
209        if (minor<MAX_PTYS) {   
210         ptys[minor].c_cflag=t->c_cflag;       
211        } else {
212         return -1;
213        };
214        return 0;
215}
216/*-----------------------------------------------------------*/
217static int 
218ptyPollInitialize(int major,int minor,void * arg) {
219        rtems_libio_open_close_args_t * args = arg;
220        struct termios t;
221        if (minor<MAX_PTYS) {   
222         if (ptys[minor].socket<0) return -1;           
223         ptys[minor].opened=TRUE;
224         ptys[minor].ttyp=args->iop->data1;
225         t.c_cflag=B9600|CS8;/* termios default */
226         return ptySetAttributes(minor,&t);
227        } else {
228         return -1;
229        };
230}
231/*-----------------------------------------------------------*/
232static int 
233ptyShutdown(int major,int minor,void * arg) {
234        if (minor<MAX_PTYS) {   
235         ptys[minor].opened=FALSE;
236         if (ptys[minor].socket>=0) close(ptys[minor].socket);
237         ptys[minor].socket=-1;
238         chown(ptys[minor].devname,2,0);
239        } else {
240         return -1;
241        };
242        return 0;
243}
244/*-----------------------------------------------------------*/
245/* Write Characters into pty device                          */ 
246/*-----------------------------------------------------------*/
247static int
248ptyPollWrite(int minor, const char * buf,int len) {
249        int count;
250        if (minor<MAX_PTYS) {   
251         if (ptys[minor].socket<0) return -1;           
252         count=write(ptys[minor].socket,buf,len);
253        } else {
254         count=-1;
255        };
256        return count;
257}
258/*-----------------------------------------------------------*/
259static int
260ptyPollRead(int minor) {
261        int result;
262        if (minor<MAX_PTYS) {   
263         if (ptys[minor].socket<0) return -1;           
264         result=read_pty(minor);
265         return result;
266        };
267        return -1;
268}
269/*-----------------------------------------------------------*/
270static const rtems_termios_callbacks pty_poll_callbacks = {
271        ptyPollInitialize,      /* FirstOpen*/
272        ptyShutdown,            /* LastClose*/
273        ptyPollRead,            /* PollRead  */
274        ptyPollWrite,           /* Write */
275        ptySetAttributes,       /* setAttributes */
276        NULL,                   /* stopRemoteTX */
277        NULL,                   /* StartRemoteTX */
278        0                       /* outputUsesInterrupts */
279};
280/*-----------------------------------------------------------*/
281const rtems_termios_callbacks * pty_get_termios_handlers(int polled) {
282        return &pty_poll_callbacks;
283}
284/*-----------------------------------------------------------*/
285void init_ptys(void) {
286        int ndx;
287        for (ndx=0;ndx<MAX_PTYS;ndx++) {
288                ptys[ndx].devname=malloc(strlen("/dev/ptyXX")+1);
289                sprintf(ptys[ndx].devname,"/dev/pty%X",ndx);
290                ptys[ndx].ttyp=NULL;
291                ptys[ndx].c_cflag=CS8|B9600;
292                ptys[ndx].socket=-1;
293                ptys[ndx].opened=FALSE;
294
295        };
296        ptys_initted=TRUE;
297}
298
299
300/*-----------------------------------------------------------*/
301/*  pty_initialize
302 *
303 *  This routine initializes the pty IO driver.
304 *
305 *  Input parameters: NONE
306 *
307 *  Output parameters:  NONE
308 *
309 *  Return values:
310 */
311/*-----------------------------------------------------------*/
312rtems_device_driver pty_initialize(
313  rtems_device_major_number  major,
314  rtems_device_minor_number  minor,
315  void                      *arg
316)
317{
318  int ndx;     
319  rtems_status_code status ;
320
321  /*
322   * Set up ptys
323   */
324
325  init_ptys();
326
327  /*
328   * Register the devices
329   */
330  for (ndx=0;ndx<MAX_PTYS;ndx++) {
331   status = rtems_io_register_name(ptys[ndx].devname, major, ndx);
332   if (status != RTEMS_SUCCESSFUL)
333     rtems_fatal_error_occurred(status);
334   chmod(ptys[ndx].devname,0660);
335   chown(ptys[ndx].devname,2,0); /* tty,root*/
336  };
337  printk("Device: /dev/pty%X../dev/pty%X (%d)pseudo-terminals registered.\n",0,MAX_PTYS-1,MAX_PTYS);
338
339  return RTEMS_SUCCESSFUL;
340}
341
342
343/*
344 *  Open entry point
345 */
346
347rtems_device_driver pty_open(
348  rtems_device_major_number major,
349  rtems_device_minor_number minor,
350  void                    * arg
351)
352{
353  rtems_status_code sc ;
354  sc = rtems_termios_open(major,minor,arg,pty_get_termios_handlers(FALSE));
355  return sc;
356}
357 
358/*
359 *  Close entry point
360 */
361
362rtems_device_driver pty_close(
363  rtems_device_major_number major,
364  rtems_device_minor_number minor,
365  void                    * arg
366)
367{
368  return rtems_termios_close(arg);
369}
370
371/*
372 * read bytes from the pty
373 */
374
375rtems_device_driver pty_read(
376  rtems_device_major_number major,
377  rtems_device_minor_number minor,
378  void                    * arg
379)
380{
381  return rtems_termios_read(arg);
382}
383
384/*
385 * write bytes to the pty
386 */
387
388rtems_device_driver pty_write(
389  rtems_device_major_number major,
390  rtems_device_minor_number minor,
391  void                    * arg
392)
393{
394  return rtems_termios_write(arg);
395}
396
397/*
398 *  IO Control entry point
399 */
400
401rtems_device_driver pty_control(
402  rtems_device_major_number major,
403  rtems_device_minor_number minor,
404  void                    * arg
405)
406{
407  return rtems_termios_ioctl(arg);
408}
Note: See TracBrowser for help on using the repository browser.