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

4.104.114.84.95
Last change on this file since 79061679 was af028338, checked in by Ralf Corsepius <ralf.corsepius@…>, on 10/25/05 at 14:18:00

Make many functions static.

Rename rtems_telnetd_maximum_ptys to rtems_pty_maximum_ptys.

  • Property mode set to 100644
File size: 10.4 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
48typedef struct {
49 char                     *devname;
50 struct rtems_termios_tty *ttyp;
51 tcflag_t                  c_cflag;
52 int                       opened;
53 int                       socket;
54
55 int                       last_cr;
56 int                       iac_mode;   
57} pty_t;
58
59
60static int ptys_initted=FALSE;
61static pty_t *ptys;
62
63size_t rtems_pty_maximum_ptys;
64
65/* This procedure returns the devname for a free pty slot.
66 * If no slot available (field socket>=0)
67 * then the socket argument is closed
68 */
69
70char *  rtems_pty_get(int socket) {
71        int ndx;
72        if (!ptys_initted) return NULL;
73        for (ndx=0;ndx<rtems_pty_maximum_ptys;ndx++) {
74                if (ptys[ndx].socket<0) {
75                        ptys[ndx].socket=socket;
76                        return ptys[ndx].devname;
77                };
78        };
79        close(socket);
80        return NULL;
81}
82
83
84/*-----------------------------------------------------------*/
85/*
86 * The NVT terminal is negociated in PollRead and PollWrite
87 * with every BYTE sendded or received.
88 * A litle status machine in the pty_read_byte(int minor)
89 *
90 */
91static const char IAC_AYT_RSP[]="\r\nAYT? Yes, RTEMS-SHELL is here\r\n";
92static const char IAC_BRK_RSP[]="<*Break*>";
93static const char IAC_IP_RSP []="<*Interrupt*>";
94
95
96static
97int send_iac(int minor,unsigned char mode,unsigned char option) {
98        unsigned char buf[3];
99        buf[0]=IAC_ESC;
100        buf[1]=mode;
101        buf[2]=option;
102        return write(ptys[minor].socket,buf,sizeof(buf));
103}
104
105int read_pty(int minor) { /* Characters writed in the client side*/
106         unsigned char value;
107         int count;
108         int result;
109         count=read(ptys[minor].socket,&value,sizeof(value));
110         if (count<1) {
111          fclose(stdin);                 
112          fclose(stdout);               
113          fclose(stderr);               
114          /* If you don't read from the socket the system ends the task */
115          rtems_task_delete(RTEMS_SELF);
116         };
117         switch(ptys[minor].iac_mode) {
118          case IAC_ESC:
119               ptys[minor].iac_mode=0;
120               switch(value) {
121                case IAC_ESC :
122                     return IAC_ESC;
123                case IAC_DONT:
124                case IAC_DO  :
125                case IAC_WONT:
126                case IAC_WILL:
127                     ptys[minor].iac_mode=value;
128                     return -1;
129                case IAC_SB  :
130                     return -100;
131                case IAC_GA  :
132                     return -1;
133                case IAC_EL  :
134                     return 0x03; /* Ctrl-C*/
135                case IAC_EC  :
136                     return '\b';
137                case IAC_AYT :
138                     write(ptys[minor].socket,IAC_AYT_RSP,strlen(IAC_AYT_RSP));
139                     return -1;
140                case IAC_AO  :
141                     return -1;
142                case IAC_IP  :
143                     write(ptys[minor].socket,IAC_IP_RSP,strlen(IAC_IP_RSP));
144                     return -1;
145                case IAC_BRK :
146                     write(ptys[minor].socket,IAC_BRK_RSP,strlen(IAC_BRK_RSP));
147                     return -1;
148                case IAC_DMARK:
149                     return -2;
150                case IAC_NOP :
151                     return -1;
152                case IAC_SE  :
153                     return -101;
154                case IAC_EOR :
155                     return -102;
156                default      :
157                     return -1;
158               };
159               break;
160          case IAC_WILL:
161               ptys[minor].iac_mode=0;
162               if (value==34){send_iac(minor,IAC_DONT,   34);       /*LINEMODE*/
163                              send_iac(minor,IAC_DO  ,    1);} else /*ECHO    */
164                             {send_iac(minor,IAC_DONT,value);};
165               return -1;
166          case IAC_DONT:
167               ptys[minor].iac_mode=0;
168               return -1;
169          case IAC_DO  :
170               ptys[minor].iac_mode=0;
171               if (value==3) {send_iac(minor,IAC_WILL,    3);} else /* GO AHEAD*/
172               if (value==1) {                               } else /* ECHO */
173                             {send_iac(minor,IAC_WONT,value);};
174               return -1;
175          case IAC_WONT:
176               ptys[minor].iac_mode=0;
177               if (value==1) {send_iac(minor,IAC_WILL,    1);} else /* ECHO */
178                             {send_iac(minor,IAC_WONT,value);};
179               return -1;
180          default:
181               ptys[minor].iac_mode=0;
182               if (value==IAC_ESC) {
183                     ptys[minor].iac_mode=value;
184                     return -1;
185               } else {
186                     result=value; 
187                     if ((value=='\n') && (ptys[minor].last_cr)) result=-1;
188                     ptys[minor].last_cr=(value=='\r');
189                     return result;
190               };
191         };
192       
193}
194
195/*-----------------------------------------------------------*/
196static int ptySetAttributes(int minor,const struct termios *t);
197static int ptyPollInitialize(int major,int minor,void * arg) ;
198static int ptyShutdown(int major,int minor,void * arg) ;
199static int ptyPollWrite(int minor, const char * buf,int len) ;
200static int ptyPollRead(int minor) ;
201static const rtems_termios_callbacks * pty_get_termios_handlers(int polled) ;
202/*-----------------------------------------------------------*/
203/* Set the 'Hardware'                                        */
204/*-----------------------------------------------------------*/
205static int
206ptySetAttributes(int minor,const struct termios *t) {
207        if (minor<rtems_pty_maximum_ptys) {     
208         ptys[minor].c_cflag=t->c_cflag;       
209        } else {
210         return -1;
211        };
212        return 0;
213}
214/*-----------------------------------------------------------*/
215static int
216ptyPollInitialize(int major,int minor,void * arg) {
217        rtems_libio_open_close_args_t * args = arg;
218        struct termios t;
219        if (minor<rtems_pty_maximum_ptys) {     
220         if (ptys[minor].socket<0) return -1;           
221         ptys[minor].opened=TRUE;
222         ptys[minor].ttyp=args->iop->data1;
223         t.c_cflag=B9600|CS8;/* termios default */
224         return ptySetAttributes(minor,&t);
225        } else {
226         return -1;
227        };
228}
229/*-----------------------------------------------------------*/
230static int
231ptyShutdown(int major,int minor,void * arg) {
232        if (minor<rtems_pty_maximum_ptys) {     
233         ptys[minor].opened=FALSE;
234         if (ptys[minor].socket>=0) close(ptys[minor].socket);
235         ptys[minor].socket=-1;
236         chown(ptys[minor].devname,2,0);
237        } else {
238         return -1;
239        };
240        return 0;
241}
242/*-----------------------------------------------------------*/
243/* Write Characters into pty device                          */
244/*-----------------------------------------------------------*/
245static int
246ptyPollWrite(int minor, const char * buf,int len) {
247        int count;
248        if (minor<rtems_pty_maximum_ptys) {     
249         if (ptys[minor].socket<0) return -1;           
250         count=write(ptys[minor].socket,buf,len);
251        } else {
252         count=-1;
253        };
254        return count;
255}
256/*-----------------------------------------------------------*/
257static int
258ptyPollRead(int minor) {
259        int result;
260        if (minor<rtems_pty_maximum_ptys) {     
261         if (ptys[minor].socket<0) return -1;           
262         result=read_pty(minor);
263         return result;
264        };
265        return -1;
266}
267/*-----------------------------------------------------------*/
268static const rtems_termios_callbacks pty_poll_callbacks = {
269        ptyPollInitialize,      /* FirstOpen*/
270        ptyShutdown,            /* LastClose*/
271        ptyPollRead,            /* PollRead  */
272        ptyPollWrite,           /* Write */
273        ptySetAttributes,       /* setAttributes */
274        NULL,                   /* stopRemoteTX */
275        NULL,                   /* StartRemoteTX */
276        0                       /* outputUsesInterrupts */
277};
278/*-----------------------------------------------------------*/
279static const rtems_termios_callbacks * pty_get_termios_handlers(int polled) {
280        return &pty_poll_callbacks;
281}
282/*-----------------------------------------------------------*/
283static void init_ptys(void) {
284        int ndx;
285        ptys = malloc( sizeof(pty_t) * rtems_pty_maximum_ptys );
286        for (ndx=0;ndx<rtems_pty_maximum_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<rtems_pty_maximum_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",
337      0,rtems_pty_maximum_ptys-1,rtems_pty_maximum_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.