OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [libnetworking/] [rtems_telnetd/] [pty.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
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
 *  pty.c,v 1.3 2002/05/28 16:20:54 joel Exp
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
 
48
struct pty_tt;
49
typedef struct pty_tt pty_t;
50
 
51
struct 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
 
63
int ptys_initted=FALSE;
64
pty_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
 
71
char *  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
 */
92
const char IAC_AYT_RSP[]="\r\nAYT? Yes, RTEMS-SHELL is here\r\n";
93
const char IAC_BRK_RSP[]="<*Break*>";
94
const char IAC_IP_RSP []="<*Interrupt*>";
95
 
96
 
97
static
98
int 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
 
106
int 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
/*-----------------------------------------------------------*/
197
static int ptySetAttributes(int minor,const struct termios *t);
198
static int ptyPollInitialize(int major,int minor,void * arg) ;
199
static int ptyShutdown(int major,int minor,void * arg) ;
200
static int ptyPollWrite(int minor, const char * buf,int len) ;
201
static int ptyPollRead(int minor) ;
202
const rtems_termios_callbacks * pty_get_termios_handlers(int polled) ;
203
/*-----------------------------------------------------------*/
204
/* Set the 'Hardware'                                        */
205
/*-----------------------------------------------------------*/
206
static int
207
ptySetAttributes(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
/*-----------------------------------------------------------*/
216
static int
217
ptyPollInitialize(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
/*-----------------------------------------------------------*/
231
static int
232
ptyShutdown(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
/*-----------------------------------------------------------*/
246
static int
247
ptyPollWrite(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
/*-----------------------------------------------------------*/
258
static int
259
ptyPollRead(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
/*-----------------------------------------------------------*/
269
static 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
 
278
};
279
/*-----------------------------------------------------------*/
280
const rtems_termios_callbacks * pty_get_termios_handlers(int polled) {
281
        return &pty_poll_callbacks;
282
}
283
/*-----------------------------------------------------------*/
284
void 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
/*-----------------------------------------------------------*/
311
rtems_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
 
346
rtems_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
 
361
rtems_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
 
374
rtems_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
 
387
rtems_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
 
400
rtems_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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.