source: rtems/cpukit/telnetd/pty.c @ 7ed1e747

4.104.114.84.95
Last change on this file since 7ed1e747 was e3eab02, checked in by Joel Sherrill <joel.sherrill@…>, on 05/28/02 at 16:20:54

2002-05-18 Ralf Corsepius <corsepiu@…>

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