source: trunk/third/tcsh/mi.termios.c @ 12039

Revision 12039, 11.0 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12038, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/mi.termios.c,v 1.1.1.2 1998-10-03 21:09:53 danw Exp $ */
2/* termios.c - fake termios interface using sgtty interface
3 *             by Magnus Doell and Bruce Evans.
4 *
5 */
6#include "sh.h"
7RCSID("$Id: mi.termios.c,v 1.1.1.2 1998-10-03 21:09:53 danw Exp $")
8
9#ifdef _MINIX
10
11
12/* Undefine everything that clashes with sgtty.h. */
13#undef B0
14#undef B50
15#undef B75
16#undef B110
17#undef B134
18#undef B150
19#undef B200
20#undef B300
21#undef B600
22#undef B1200
23#undef B1800
24#undef B2400
25#undef B4800
26#undef B9600
27#undef B19200
28#undef B28800
29#undef B38400
30#undef B57600
31#undef B115200
32/* Do not #undef CRMOD. We want a warning when they differ! */
33#undef ECHO
34/* Do not #undef XTABS. We want a warning when they differ! */
35
36/* Redefine some of the termios.h names just undefined with 'T_' prefixed
37 * to the name.  Don't bother with the low speeds - Minix does not support
38 * them.  Add support for higher speeds (speeds are now easy and don't need
39 * defines because they are not encoded).
40 */
41#define T_ECHO          000001
42
43#include <errno.h>
44#include <sgtty.h>
45
46static _PROTOTYPE( int tc_to_sg_speed, (speed_t speed) );
47static _PROTOTYPE( speed_t sg_to_tc_speed, (int speed) );
48#define B19200   192
49
50/* The speed get/set functions could be macros in the Minix implementation
51 * because there are speed fields in the structure with no fancy packing
52 * and it is not practical to check the values outside the driver.
53 * Where tests are necessary because the driver acts different from what
54 * POSIX requires, they are done in tcsetattr.
55 */
56
57speed_t cfgetispeed(termios_p)
58struct termios *termios_p;
59{
60    return termios_p->c_ispeed;
61}
62
63speed_t cfgetospeed(termios_p)
64struct termios *termios_p;
65{
66    return termios_p->c_ospeed;
67}
68
69speed_t cfsetispeed(termios_p, speed)
70struct termios *termios_p;
71speed_t speed;
72{
73    termios_p->c_ispeed = speed;
74    return 0;
75}
76
77speed_t cfsetospeed(termios_p, speed)
78struct termios *termios_p;
79speed_t speed;
80{
81    termios_p->c_ospeed = speed;
82    return 0;
83}
84
85static speed_t sg_to_tc_speed(speed)
86int speed;
87{
88    /* The speed encodings in sgtty.h and termios.h are different.  Both are
89     * inflexible.  Minix doesn't really support B0 but we map it through
90     * anyway.  It doesn't support B50, B75 or B134.
91     */
92    switch (speed) {
93        case B0: return 0;
94        case B110: return 110;
95        case B200: return 200;
96        case B300: return 300;
97        case B600: return 600;
98        case B1200: return 1200;
99        case B1800: return 1800;
100        case B2400: return 2400;
101        case B4800: return 4800;
102        case B9600: return 9600;
103        case B19200: return 19200;
104#ifdef B28800
105        case B28800: return 28800;
106#endif
107#ifdef B38400
108        case B38400: return 38400;
109#endif
110#ifdef B57600
111        case B57600: return 57600;
112#endif
113#ifdef B115200
114        case B115200: return 115200;
115#endif
116        default: return (speed_t)-1;
117    }
118}
119
120static int tc_to_sg_speed(speed)
121speed_t speed;
122{
123    /* Don't use a switch here in case the compiler is 16-bit and doesn't
124     * properly support longs (speed_t's) in switches.  It turns out the
125     * switch is larger and slower for most compilers anyway!
126     */
127    if (speed == 0) return 0;
128    if (speed == 110) return B110;
129    if (speed == 200) return B200;
130    if (speed == 300) return B300;
131    if (speed == 600) return B600;
132    if (speed == 1200) return B1200;
133    if (speed == 1800) return B1800;
134    if (speed == 2400) return B2400;
135    if (speed == 4800) return B4800;
136    if (speed == 9600) return B9600;
137    if (speed == 19200) return B19200;
138#ifdef B28800
139    if (speed == 28800) return B28800;
140#endif
141#ifdef B38400
142    if (speed == 38400) return B38400;
143#endif
144#ifdef B57600
145    if (speed == 57600) return B57600;
146#endif
147#ifdef B115200
148    if (speed == 115200) return B115200;
149#endif
150    return -1;
151}
152
153int tcgetattr(filedes, termios_p)
154int filedes;
155struct termios *termios_p;
156{
157    struct sgttyb sgbuf;
158    struct tchars tcbuf;
159
160    if (ioctl(filedes, TIOCGETP, &sgbuf) < 0
161        || ioctl(filedes, TIOCGETC, (struct sgttyb *) &tcbuf) < 0)
162    {
163        return -1;
164    }
165
166    /* Minix input flags:
167     *   BRKINT:  forced off (break is not recognized)
168     *   IGNBRK:  forced on (break is not recognized)
169     *   ICRNL:   set if CRMOD is set and not RAW (CRMOD also controls output)
170     *   IGNCR:   forced off (ignoring cr's is not supported)
171     *   INLCR:   forced off (mapping nl's to cr's is not supported)
172     *   ISTRIP:  forced off (should be off for consoles, on for rs232 no RAW)
173     *   IXOFF:   forced off (rs232 uses CTS instead of XON/XOFF)
174     *   IXON:    forced on if not RAW
175     *   PARMRK:  forced off (no '\377', '\0', X sequence on errors)
176     * ? IGNPAR:  forced off (input with parity/framing errors is kept)
177     * ? INPCK:   forced off (input parity checking is not supported)
178     */
179    termios_p->c_iflag = IGNBRK;
180    if (!(sgbuf.sg_flags & RAW))
181    {
182        termios_p->c_iflag |= IXON;
183        if (sgbuf.sg_flags & CRMOD)
184        {
185            termios_p->c_iflag |= ICRNL;
186        }
187    }
188
189    /* Minix output flags:
190     *   OPOST:   set if CRMOD or XTABS is set
191     *   XTABS:   copied from sg_flags
192     *   CRMOD:   copied from sg_flags
193     */
194    termios_p->c_oflag = sgbuf.sg_flags & (CRMOD | XTABS);
195    if (termios_p->c_oflag)
196    {
197        termios_p->c_oflag |= OPOST;
198    }
199
200    /* Minix local flags:
201     *   ECHO:    set if ECHO is set
202     *   ECHOE:   set if ECHO is set (ERASE echoed as error-corecting backspace)
203     *   ECHOK:   set if ECHO is set ('\n' echoed after KILL char)
204     *   ECHONL:  forced off ('\n' not echoed when ECHO isn't set)
205     *   ICANON:  set if neither CBREAK nor RAW
206     *   IEXTEN:  forced off
207     *   ISIG:    set if not RAW
208     *   NOFLSH:  forced off (input/output queues are always flushed)
209     *   TOSTOP:  forced off (no job control)
210     */
211    termios_p->c_lflag = 0;
212    if (sgbuf.sg_flags & ECHO)
213    {
214        termios_p->c_lflag |= T_ECHO | ECHOE | ECHOK;
215    }
216    if (!(sgbuf.sg_flags & RAW))
217    {
218        termios_p->c_lflag |= ISIG;
219        if (!(sgbuf.sg_flags & CBREAK))
220        {
221            termios_p->c_lflag |= ICANON;
222        }
223    }
224
225    /* Minix control flags:
226     *   CLOCAL:  forced on (ignore modem status lines - not quite right)
227     *   CREAD:   forced on (receiver is always enabled)
228     *   CSIZE:   CS5-CS8 correspond directly to BITS5-BITS8
229     *   CSTOPB:  set for B110 (driver will generate 2 stop-bits than)
230     *   HUPCL:   forced off
231     *   PARENB:  set if EVENP or ODDP is set
232     *   PARODD:  set if ODDP is set
233     */
234    termios_p->c_cflag = CLOCAL | CREAD;
235    switch (sgbuf.sg_flags & BITS8)
236    {
237        case BITS5: termios_p->c_cflag |= CS5; break;
238        case BITS6: termios_p->c_cflag |= CS6; break;
239        case BITS7: termios_p->c_cflag |= CS7; break;
240        case BITS8: termios_p->c_cflag |= CS8; break;
241    }
242    if (sgbuf.sg_flags & ODDP)
243    {
244        termios_p->c_cflag |= PARENB | PARODD;
245    }
246    if (sgbuf.sg_flags & EVENP)
247    {
248        termios_p->c_cflag |= PARENB;
249    }
250    if (sgbuf.sg_ispeed == B110)
251    {
252        termios_p->c_cflag |= CSTOPB;
253    }
254
255    /* Minix may give back different input and output baudrates,
256     * but only the input baudrate is valid for both.
257     * As our termios emulation will fail, if input baudrate differs
258     * from output baudrate, force them to be equal.
259     * Otherwise it would be very suprisingly not to be able to set
260     * the terminal back to the state returned by tcgetattr :).
261     */
262    termios_p->c_ospeed =
263    termios_p->c_ispeed =
264                sg_to_tc_speed((unsigned char) sgbuf.sg_ispeed);
265
266    /* Minix control characters correspond directly except VSUSP and the
267     * important VMIN and VTIME are not really supported.
268     */
269    termios_p->c_cc[VEOF] = tcbuf.t_eofc;
270    termios_p->c_cc[VEOL] = tcbuf.t_brkc;
271    termios_p->c_cc[VERASE] = sgbuf.sg_erase;
272    termios_p->c_cc[VINTR] = tcbuf.t_intrc;
273    termios_p->c_cc[VKILL] = sgbuf.sg_kill;
274    termios_p->c_cc[VQUIT] = tcbuf.t_quitc;
275    termios_p->c_cc[VSTART] = tcbuf.t_startc;
276    termios_p->c_cc[VSTOP] = tcbuf.t_stopc;
277    termios_p->c_cc[VMIN] = 1;
278    termios_p->c_cc[VTIME] = 0;
279    termios_p->c_cc[VSUSP] = 0;
280
281    return 0;
282}
283
284int tcsetattr(filedes, opt_actions, termios_p)
285int filedes;
286int opt_actions;
287struct termios *termios_p;
288{
289    struct sgttyb sgbuf;
290    struct tchars tcbuf;
291    int sgspeed;
292
293    /* Posix 1003.1-1988 page 135 says:
294     * Attempts to set unsupported baud rates shall be ignored, and it is
295     * implementation-defined whether an error is returned by any or all of
296     * cfsetispeed(), cfsetospeed(), or tcsetattr(). This refers both to
297     * changes to baud rates not supported by the hardware, and to changes
298     * setting the input and output baud rates to different values if the
299     * hardware does not support it.
300     * Ignoring means not to change the existing settings, doesn't it?
301     */
302    if ((termios_p->c_ispeed != 0 && termios_p->c_ispeed != termios_p->c_ospeed)
303        || (sgspeed = tc_to_sg_speed(termios_p->c_ospeed)) < 0)
304    {
305        errno = EINVAL;
306        return -1;
307    }
308
309    sgbuf.sg_ispeed = sgbuf.sg_ospeed = sgspeed;
310    sgbuf.sg_flags = 0;
311
312    /* I don't know what should happen with requests that are not supported by
313     * old Minix drivers and therefore cannot be emulated.
314     * Returning an error may confuse the application (the values aren't really
315     * invalid or unsupported by the hardware, they just couldn't be satisfied
316     * by the driver). Not returning an error might be even worse because the
317     * driver will act different to what the application requires it to act
318     * after sucessfully setting the attributes as specified.
319     * Settings that cannot be emulated fully include:
320     *   c_ospeed != 110 && c_cflag & CSTOPB
321     *   c_ospeed == 110 && ! c_cflag & CSTOPB
322     *   (c_cc[VMIN] != 1 || c_cc[VTIME] != 0) && ! c_lflag & ICANON
323     *   c_lflag & ICANON && ! c_lflag & ISIG
324     * For the moment I just ignore these conflicts.
325     */
326
327    if (termios_p->c_oflag & OPOST)
328    {
329        /* CRMOD isn't Posix and may conflict with ICRNL, which is Posix,
330         * so we just ignore it.
331         */
332        if (termios_p->c_oflag & XTABS)
333        {
334                sgbuf.sg_flags |= XTABS;
335        }
336    }
337
338    if (termios_p->c_iflag & ICRNL)
339    {
340        /* We couldn't do it better :-(. */
341        sgbuf.sg_flags |= CRMOD;
342    }
343
344    if (termios_p->c_lflag & T_ECHO)
345    {
346        sgbuf.sg_flags |= ECHO;
347    }
348    if (!(termios_p->c_lflag & ICANON))
349    {
350        if (termios_p->c_lflag & ISIG)
351        {
352             sgbuf.sg_flags |= CBREAK;
353        }
354        else
355        {
356             sgbuf.sg_flags |= RAW;
357        }
358    }
359
360    switch (termios_p->c_cflag & CSIZE)
361    {
362        case CS5: sgbuf.sg_flags |= BITS5; break;
363        case CS6: sgbuf.sg_flags |= BITS6; break;
364        case CS7: sgbuf.sg_flags |= BITS7; break;
365        case CS8: sgbuf.sg_flags |= BITS8; break;
366    }
367    if (termios_p->c_cflag & PARENB)
368    {
369        if (termios_p->c_cflag & PARODD)
370        {
371            sgbuf.sg_flags |= ODDP;
372        }
373        else
374        {
375            sgbuf.sg_flags |= EVENP;
376        }
377    }
378
379    sgbuf.sg_erase = termios_p->c_cc[VERASE];
380    sgbuf.sg_kill = termios_p->c_cc[VKILL];
381
382    tcbuf.t_intrc = termios_p->c_cc[VINTR];
383    tcbuf.t_quitc = termios_p->c_cc[VQUIT];
384    tcbuf.t_startc = termios_p->c_cc[VSTART];
385    tcbuf.t_stopc = termios_p->c_cc[VSTOP];
386    tcbuf.t_eofc = termios_p->c_cc[VEOF];
387    tcbuf.t_brkc = termios_p->c_cc[VEOL];
388
389    return ioctl(filedes, TIOCSETP, &sgbuf) < 0 &&
390           ioctl(filedes, TIOCSETC, (struct sgttyb *) &tcbuf) < 0 ?
391                -1 : 0;
392}
393#endif /* _MINIX */
Note: See TracBrowser for help on using the repository browser.