~michaeleguo/ubuntu/trusty/percona-xtradb-cluster-5.5/arm64fix

« back to all changes in this revision

Viewing changes to cmd-line-utils/libedit/tty.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-10 14:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20140210144423-f2134l2gxuvq2m6l
Tags: upstream-5.5.34-25.9+dfsg
ImportĀ upstreamĀ versionĀ 5.5.34-25.9+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $NetBSD: tty.c,v 1.41 2011/10/04 15:27:04 christos Exp $        */
 
2
 
 
3
/*-
 
4
 * Copyright (c) 1992, 1993
 
5
 *      The Regents of the University of California.  All rights reserved.
 
6
 *
 
7
 * This code is derived from software contributed to Berkeley by
 
8
 * Christos Zoulas of Cornell University.
 
9
 *
 
10
 * Redistribution and use in source and binary forms, with or without
 
11
 * modification, are permitted provided that the following conditions
 
12
 * are met:
 
13
 * 1. Redistributions of source code must retain the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer.
 
15
 * 2. Redistributions in binary form must reproduce the above copyright
 
16
 *    notice, this list of conditions and the following disclaimer in the
 
17
 *    documentation and/or other materials provided with the distribution.
 
18
 * 3. Neither the name of the University nor the names of its contributors
 
19
 *    may be used to endorse or promote products derived from this software
 
20
 *    without specific prior written permission.
 
21
 *
 
22
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
32
 * SUCH DAMAGE.
 
33
 */
 
34
 
 
35
#include "config.h"
 
36
#if !defined(lint) && !defined(SCCSID)
 
37
#if 0
 
38
static char sccsid[] = "@(#)tty.c       8.1 (Berkeley) 6/4/93";
 
39
#else
 
40
#endif
 
41
#endif /* not lint && not SCCSID */
 
42
 
 
43
/*
 
44
 * tty.c: tty interface stuff
 
45
 */
 
46
#include <assert.h>
 
47
#include <errno.h>
 
48
#include <unistd.h>     /* for isatty */
 
49
#include <strings.h>    /* for ffs */
 
50
#include "el.h"
 
51
#include "tty.h"
 
52
 
 
53
typedef struct ttymodes_t {
 
54
        const char *m_name;
 
55
        unsigned int m_value;
 
56
        int m_type;
 
57
}          ttymodes_t;
 
58
 
 
59
typedef struct ttymap_t {
 
60
        Int nch, och;           /* Internal and termio rep of chars */
 
61
        el_action_t bind[3];    /* emacs, vi, and vi-cmd */
 
62
} ttymap_t;
 
63
 
 
64
 
 
65
private const ttyperm_t ttyperm = {
 
66
        {
 
67
                {"iflag:", ICRNL, (INLCR | IGNCR)},
 
68
                {"oflag:", (OPOST | ONLCR), ONLRET},
 
69
                {"cflag:", 0, 0},
 
70
                {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
 
71
                (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
 
72
                {"chars:", 0, 0},
 
73
        },
 
74
        {
 
75
                {"iflag:", (INLCR | ICRNL), IGNCR},
 
76
                {"oflag:", (OPOST | ONLCR), ONLRET},
 
77
                {"cflag:", 0, 0},
 
78
                {"lflag:", ISIG,
 
79
                (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
 
80
                {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
 
81
                            C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
 
82
                    C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
 
83
        },
 
84
        {
 
85
                {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
 
86
                {"oflag:", 0, 0},
 
87
                {"cflag:", 0, 0},
 
88
                {"lflag:", 0, ISIG | IEXTEN},
 
89
                {"chars:", 0, 0},
 
90
        }
 
91
};
 
92
 
 
93
private const ttychar_t ttychar = {
 
94
        {
 
95
                CINTR, CQUIT, CERASE, CKILL,
 
96
                CEOF, CEOL, CEOL2, CSWTCH,
 
97
                CDSWTCH, CERASE2, CSTART, CSTOP,
 
98
                CWERASE, CSUSP, CDSUSP, CREPRINT,
 
99
                CDISCARD, CLNEXT, CSTATUS, CPAGE,
 
100
                CPGOFF, CKILL2, CBRK, CMIN,
 
101
                CTIME
 
102
        },
 
103
        {
 
104
                CINTR, CQUIT, CERASE, CKILL,
 
105
                _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
 
106
                _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
 
107
                _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
 
108
                CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
 
109
                _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
 
110
                0
 
111
        },
 
112
        {
 
113
                0, 0, 0, 0,
 
114
                0, 0, 0, 0,
 
115
                0, 0, 0, 0,
 
116
                0, 0, 0, 0,
 
117
                0, 0, 0, 0,
 
118
                0, 0, 0, 0,
 
119
                0
 
120
        }
 
121
};
 
122
 
 
123
private const ttymap_t tty_map[] = {
 
124
#ifdef VERASE
 
125
        {C_ERASE, VERASE,
 
126
        {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
 
127
#endif /* VERASE */
 
128
#ifdef VERASE2
 
129
        {C_ERASE2, VERASE2,
 
130
        {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
 
131
#endif /* VERASE2 */
 
132
#ifdef VKILL
 
133
        {C_KILL, VKILL,
 
134
        {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
 
135
#endif /* VKILL */
 
136
#ifdef VKILL2
 
137
        {C_KILL2, VKILL2,
 
138
        {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
 
139
#endif /* VKILL2 */
 
140
#ifdef VEOF
 
141
        {C_EOF, VEOF,
 
142
        {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
 
143
#endif /* VEOF */
 
144
#ifdef VWERASE
 
145
        {C_WERASE, VWERASE,
 
146
        {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
 
147
#endif /* VWERASE */
 
148
#ifdef VREPRINT
 
149
        {C_REPRINT, VREPRINT,
 
150
        {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
 
151
#endif /* VREPRINT */
 
152
#ifdef VLNEXT
 
153
        {C_LNEXT, VLNEXT,
 
154
        {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
 
155
#endif /* VLNEXT */
 
156
        {(Int)-1, (Int)-1,
 
157
        {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
 
158
};
 
159
 
 
160
private const ttymodes_t ttymodes[] = {
 
161
#ifdef  IGNBRK
 
162
        {"ignbrk", IGNBRK, MD_INP},
 
163
#endif /* IGNBRK */
 
164
#ifdef  BRKINT
 
165
        {"brkint", BRKINT, MD_INP},
 
166
#endif /* BRKINT */
 
167
#ifdef  IGNPAR
 
168
        {"ignpar", IGNPAR, MD_INP},
 
169
#endif /* IGNPAR */
 
170
#ifdef  PARMRK
 
171
        {"parmrk", PARMRK, MD_INP},
 
172
#endif /* PARMRK */
 
173
#ifdef  INPCK
 
174
        {"inpck", INPCK, MD_INP},
 
175
#endif /* INPCK */
 
176
#ifdef  ISTRIP
 
177
        {"istrip", ISTRIP, MD_INP},
 
178
#endif /* ISTRIP */
 
179
#ifdef  INLCR
 
180
        {"inlcr", INLCR, MD_INP},
 
181
#endif /* INLCR */
 
182
#ifdef  IGNCR
 
183
        {"igncr", IGNCR, MD_INP},
 
184
#endif /* IGNCR */
 
185
#ifdef  ICRNL
 
186
        {"icrnl", ICRNL, MD_INP},
 
187
#endif /* ICRNL */
 
188
#ifdef  IUCLC
 
189
        {"iuclc", IUCLC, MD_INP},
 
190
#endif /* IUCLC */
 
191
#ifdef  IXON
 
192
        {"ixon", IXON, MD_INP},
 
193
#endif /* IXON */
 
194
#ifdef  IXANY
 
195
        {"ixany", IXANY, MD_INP},
 
196
#endif /* IXANY */
 
197
#ifdef  IXOFF
 
198
        {"ixoff", IXOFF, MD_INP},
 
199
#endif /* IXOFF */
 
200
#ifdef  IMAXBEL
 
201
        {"imaxbel", IMAXBEL, MD_INP},
 
202
#endif /* IMAXBEL */
 
203
 
 
204
#ifdef  OPOST
 
205
        {"opost", OPOST, MD_OUT},
 
206
#endif /* OPOST */
 
207
#ifdef  OLCUC
 
208
        {"olcuc", OLCUC, MD_OUT},
 
209
#endif /* OLCUC */
 
210
#ifdef  ONLCR
 
211
        {"onlcr", ONLCR, MD_OUT},
 
212
#endif /* ONLCR */
 
213
#ifdef  OCRNL
 
214
        {"ocrnl", OCRNL, MD_OUT},
 
215
#endif /* OCRNL */
 
216
#ifdef  ONOCR
 
217
        {"onocr", ONOCR, MD_OUT},
 
218
#endif /* ONOCR */
 
219
#ifdef ONOEOT
 
220
        {"onoeot", ONOEOT, MD_OUT},
 
221
#endif /* ONOEOT */
 
222
#ifdef  ONLRET
 
223
        {"onlret", ONLRET, MD_OUT},
 
224
#endif /* ONLRET */
 
225
#ifdef  OFILL
 
226
        {"ofill", OFILL, MD_OUT},
 
227
#endif /* OFILL */
 
228
#ifdef  OFDEL
 
229
        {"ofdel", OFDEL, MD_OUT},
 
230
#endif /* OFDEL */
 
231
#ifdef  NLDLY
 
232
        {"nldly", NLDLY, MD_OUT},
 
233
#endif /* NLDLY */
 
234
#ifdef  CRDLY
 
235
        {"crdly", CRDLY, MD_OUT},
 
236
#endif /* CRDLY */
 
237
#ifdef  TABDLY
 
238
        {"tabdly", TABDLY, MD_OUT},
 
239
#endif /* TABDLY */
 
240
#ifdef  XTABS
 
241
        {"xtabs", XTABS, MD_OUT},
 
242
#endif /* XTABS */
 
243
#ifdef  BSDLY
 
244
        {"bsdly", BSDLY, MD_OUT},
 
245
#endif /* BSDLY */
 
246
#ifdef  VTDLY
 
247
        {"vtdly", VTDLY, MD_OUT},
 
248
#endif /* VTDLY */
 
249
#ifdef  FFDLY
 
250
        {"ffdly", FFDLY, MD_OUT},
 
251
#endif /* FFDLY */
 
252
#ifdef  PAGEOUT
 
253
        {"pageout", PAGEOUT, MD_OUT},
 
254
#endif /* PAGEOUT */
 
255
#ifdef  WRAP
 
256
        {"wrap", WRAP, MD_OUT},
 
257
#endif /* WRAP */
 
258
 
 
259
#ifdef  CIGNORE
 
260
        {"cignore", CIGNORE, MD_CTL},
 
261
#endif /* CBAUD */
 
262
#ifdef  CBAUD
 
263
        {"cbaud", CBAUD, MD_CTL},
 
264
#endif /* CBAUD */
 
265
#ifdef  CSTOPB
 
266
        {"cstopb", CSTOPB, MD_CTL},
 
267
#endif /* CSTOPB */
 
268
#ifdef  CREAD
 
269
        {"cread", CREAD, MD_CTL},
 
270
#endif /* CREAD */
 
271
#ifdef  PARENB
 
272
        {"parenb", PARENB, MD_CTL},
 
273
#endif /* PARENB */
 
274
#ifdef  PARODD
 
275
        {"parodd", PARODD, MD_CTL},
 
276
#endif /* PARODD */
 
277
#ifdef  HUPCL
 
278
        {"hupcl", HUPCL, MD_CTL},
 
279
#endif /* HUPCL */
 
280
#ifdef  CLOCAL
 
281
        {"clocal", CLOCAL, MD_CTL},
 
282
#endif /* CLOCAL */
 
283
#ifdef  LOBLK
 
284
        {"loblk", LOBLK, MD_CTL},
 
285
#endif /* LOBLK */
 
286
#ifdef  CIBAUD
 
287
        {"cibaud", CIBAUD, MD_CTL},
 
288
#endif /* CIBAUD */
 
289
#ifdef CRTSCTS
 
290
#ifdef CCTS_OFLOW
 
291
        {"ccts_oflow", CCTS_OFLOW, MD_CTL},
 
292
#else
 
293
        {"crtscts", CRTSCTS, MD_CTL},
 
294
#endif /* CCTS_OFLOW */
 
295
#endif /* CRTSCTS */
 
296
#ifdef CRTS_IFLOW
 
297
        {"crts_iflow", CRTS_IFLOW, MD_CTL},
 
298
#endif /* CRTS_IFLOW */
 
299
#ifdef CDTRCTS
 
300
        {"cdtrcts", CDTRCTS, MD_CTL},
 
301
#endif /* CDTRCTS */
 
302
#ifdef MDMBUF
 
303
        {"mdmbuf", MDMBUF, MD_CTL},
 
304
#endif /* MDMBUF */
 
305
#ifdef RCV1EN
 
306
        {"rcv1en", RCV1EN, MD_CTL},
 
307
#endif /* RCV1EN */
 
308
#ifdef XMT1EN
 
309
        {"xmt1en", XMT1EN, MD_CTL},
 
310
#endif /* XMT1EN */
 
311
 
 
312
#ifdef  ISIG
 
313
        {"isig", ISIG, MD_LIN},
 
314
#endif /* ISIG */
 
315
#ifdef  ICANON
 
316
        {"icanon", ICANON, MD_LIN},
 
317
#endif /* ICANON */
 
318
#ifdef  XCASE
 
319
        {"xcase", XCASE, MD_LIN},
 
320
#endif /* XCASE */
 
321
#ifdef  ECHO
 
322
        {"echo", ECHO, MD_LIN},
 
323
#endif /* ECHO */
 
324
#ifdef  ECHOE
 
325
        {"echoe", ECHOE, MD_LIN},
 
326
#endif /* ECHOE */
 
327
#ifdef  ECHOK
 
328
        {"echok", ECHOK, MD_LIN},
 
329
#endif /* ECHOK */
 
330
#ifdef  ECHONL
 
331
        {"echonl", ECHONL, MD_LIN},
 
332
#endif /* ECHONL */
 
333
#ifdef  NOFLSH
 
334
        {"noflsh", NOFLSH, MD_LIN},
 
335
#endif /* NOFLSH */
 
336
#ifdef  TOSTOP
 
337
        {"tostop", TOSTOP, MD_LIN},
 
338
#endif /* TOSTOP */
 
339
#ifdef  ECHOCTL
 
340
        {"echoctl", ECHOCTL, MD_LIN},
 
341
#endif /* ECHOCTL */
 
342
#ifdef  ECHOPRT
 
343
        {"echoprt", ECHOPRT, MD_LIN},
 
344
#endif /* ECHOPRT */
 
345
#ifdef  ECHOKE
 
346
        {"echoke", ECHOKE, MD_LIN},
 
347
#endif /* ECHOKE */
 
348
#ifdef  DEFECHO
 
349
        {"defecho", DEFECHO, MD_LIN},
 
350
#endif /* DEFECHO */
 
351
#ifdef  FLUSHO
 
352
        {"flusho", FLUSHO, MD_LIN},
 
353
#endif /* FLUSHO */
 
354
#ifdef  PENDIN
 
355
        {"pendin", PENDIN, MD_LIN},
 
356
#endif /* PENDIN */
 
357
#ifdef  IEXTEN
 
358
        {"iexten", IEXTEN, MD_LIN},
 
359
#endif /* IEXTEN */
 
360
#ifdef  NOKERNINFO
 
361
        {"nokerninfo", NOKERNINFO, MD_LIN},
 
362
#endif /* NOKERNINFO */
 
363
#ifdef  ALTWERASE
 
364
        {"altwerase", ALTWERASE, MD_LIN},
 
365
#endif /* ALTWERASE */
 
366
#ifdef  EXTPROC
 
367
        {"extproc", EXTPROC, MD_LIN},
 
368
#endif /* EXTPROC */
 
369
 
 
370
#if defined(VINTR)
 
371
        {"intr", C_SH(C_INTR), MD_CHAR},
 
372
#endif /* VINTR */
 
373
#if defined(VQUIT)
 
374
        {"quit", C_SH(C_QUIT), MD_CHAR},
 
375
#endif /* VQUIT */
 
376
#if defined(VERASE)
 
377
        {"erase", C_SH(C_ERASE), MD_CHAR},
 
378
#endif /* VERASE */
 
379
#if defined(VKILL)
 
380
        {"kill", C_SH(C_KILL), MD_CHAR},
 
381
#endif /* VKILL */
 
382
#if defined(VEOF)
 
383
        {"eof", C_SH(C_EOF), MD_CHAR},
 
384
#endif /* VEOF */
 
385
#if defined(VEOL)
 
386
        {"eol", C_SH(C_EOL), MD_CHAR},
 
387
#endif /* VEOL */
 
388
#if defined(VEOL2)
 
389
        {"eol2", C_SH(C_EOL2), MD_CHAR},
 
390
#endif /* VEOL2 */
 
391
#if defined(VSWTCH)
 
392
        {"swtch", C_SH(C_SWTCH), MD_CHAR},
 
393
#endif /* VSWTCH */
 
394
#if defined(VDSWTCH)
 
395
        {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
 
396
#endif /* VDSWTCH */
 
397
#if defined(VERASE2)
 
398
        {"erase2", C_SH(C_ERASE2), MD_CHAR},
 
399
#endif /* VERASE2 */
 
400
#if defined(VSTART)
 
401
        {"start", C_SH(C_START), MD_CHAR},
 
402
#endif /* VSTART */
 
403
#if defined(VSTOP)
 
404
        {"stop", C_SH(C_STOP), MD_CHAR},
 
405
#endif /* VSTOP */
 
406
#if defined(VWERASE)
 
407
        {"werase", C_SH(C_WERASE), MD_CHAR},
 
408
#endif /* VWERASE */
 
409
#if defined(VSUSP)
 
410
        {"susp", C_SH(C_SUSP), MD_CHAR},
 
411
#endif /* VSUSP */
 
412
#if defined(VDSUSP)
 
413
        {"dsusp", C_SH(C_DSUSP), MD_CHAR},
 
414
#endif /* VDSUSP */
 
415
#if defined(VREPRINT)
 
416
        {"reprint", C_SH(C_REPRINT), MD_CHAR},
 
417
#endif /* VREPRINT */
 
418
#if defined(VDISCARD)
 
419
        {"discard", C_SH(C_DISCARD), MD_CHAR},
 
420
#endif /* VDISCARD */
 
421
#if defined(VLNEXT)
 
422
        {"lnext", C_SH(C_LNEXT), MD_CHAR},
 
423
#endif /* VLNEXT */
 
424
#if defined(VSTATUS)
 
425
        {"status", C_SH(C_STATUS), MD_CHAR},
 
426
#endif /* VSTATUS */
 
427
#if defined(VPAGE)
 
428
        {"page", C_SH(C_PAGE), MD_CHAR},
 
429
#endif /* VPAGE */
 
430
#if defined(VPGOFF)
 
431
        {"pgoff", C_SH(C_PGOFF), MD_CHAR},
 
432
#endif /* VPGOFF */
 
433
#if defined(VKILL2)
 
434
        {"kill2", C_SH(C_KILL2), MD_CHAR},
 
435
#endif /* VKILL2 */
 
436
#if defined(VBRK)
 
437
        {"brk", C_SH(C_BRK), MD_CHAR},
 
438
#endif /* VBRK */
 
439
#if defined(VMIN)
 
440
        {"min", C_SH(C_MIN), MD_CHAR},
 
441
#endif /* VMIN */
 
442
#if defined(VTIME)
 
443
        {"time", C_SH(C_TIME), MD_CHAR},
 
444
#endif /* VTIME */
 
445
        {NULL, 0, -1},
 
446
};
 
447
 
 
448
 
 
449
 
 
450
#define tty__gettabs(td)        ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
 
451
#define tty__geteightbit(td)    (((td)->c_cflag & CSIZE) == CS8)
 
452
#define tty__cooked_mode(td)    ((td)->c_lflag & ICANON)
 
453
 
 
454
private int     tty_getty(EditLine *, struct termios *);
 
455
private int     tty_setty(EditLine *, int, const struct termios *);
 
456
private int     tty__getcharindex(int);
 
457
private void    tty__getchar(struct termios *, unsigned char *);
 
458
private void    tty__setchar(struct termios *, unsigned char *);
 
459
private speed_t tty__getspeed(struct termios *);
 
460
private int     tty_setup(EditLine *);
 
461
 
 
462
#define t_qu    t_ts
 
463
 
 
464
/* tty_getty():
 
465
 *      Wrapper for tcgetattr to handle EINTR
 
466
 */
 
467
private int
 
468
tty_getty(EditLine *el, struct termios *t)
 
469
{
 
470
        int rv;
 
471
        while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
 
472
                continue;
 
473
        return rv;
 
474
}
 
475
 
 
476
/* tty_setty():
 
477
 *      Wrapper for tcsetattr to handle EINTR
 
478
 */
 
479
private int
 
480
tty_setty(EditLine *el, int action, const struct termios *t)
 
481
{
 
482
        int rv;
 
483
        while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
 
484
                continue;
 
485
        return rv;
 
486
}
 
487
 
 
488
/* tty_setup():
 
489
 *      Get the tty parameters and initialize the editing state
 
490
 */
 
491
private int
 
492
tty_setup(EditLine *el)
 
493
{
 
494
        int rst = 1;
 
495
 
 
496
        if (el->el_flags & EDIT_DISABLED)
 
497
                return 0;
 
498
 
 
499
        if (!isatty(el->el_outfd)) {
 
500
#ifdef DEBUG_TTY
 
501
                (void) fprintf(el->el_errfile,
 
502
                    "tty_setup: isatty: %s\n", strerror(errno));
 
503
#endif /* DEBUG_TTY */
 
504
                return -1;
 
505
        }
 
506
        if (tty_getty(el, &el->el_tty.t_ed) == -1) {
 
507
#ifdef DEBUG_TTY
 
508
                (void) fprintf(el->el_errfile,
 
509
                    "tty_setup: tty_getty: %s\n", strerror(errno));
 
510
#endif /* DEBUG_TTY */
 
511
                return -1;
 
512
        }
 
513
        el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
 
514
 
 
515
        el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
 
516
        el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
 
517
        el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
 
518
 
 
519
        el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
 
520
        el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
 
521
 
 
522
        el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
 
523
        el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
 
524
 
 
525
        el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
 
526
        el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
 
527
 
 
528
        el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
 
529
        el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
 
530
 
 
531
        /*
 
532
         * Reset the tty chars to reasonable defaults
 
533
         * If they are disabled, then enable them.
 
534
         */
 
535
        if (rst) {
 
536
                if (tty__cooked_mode(&el->el_tty.t_ts)) {
 
537
                        tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
 
538
                        /*
 
539
                         * Don't affect CMIN and CTIME for the editor mode
 
540
                         */
 
541
                        for (rst = 0; rst < C_NCC - 2; rst++)
 
542
                                if (el->el_tty.t_c[TS_IO][rst] !=
 
543
                                      el->el_tty.t_vdisable
 
544
                                    && el->el_tty.t_c[ED_IO][rst] !=
 
545
                                      el->el_tty.t_vdisable)
 
546
                                        el->el_tty.t_c[ED_IO][rst] =
 
547
                                            el->el_tty.t_c[TS_IO][rst];
 
548
                        for (rst = 0; rst < C_NCC; rst++)
 
549
                                if (el->el_tty.t_c[TS_IO][rst] !=
 
550
                                    el->el_tty.t_vdisable)
 
551
                                        el->el_tty.t_c[EX_IO][rst] =
 
552
                                            el->el_tty.t_c[TS_IO][rst];
 
553
                }
 
554
                tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
 
555
                if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
 
556
#ifdef DEBUG_TTY
 
557
                        (void) fprintf(el->el_errfile,
 
558
                            "tty_setup: tty_setty: %s\n",
 
559
                            strerror(errno));
 
560
#endif /* DEBUG_TTY */
 
561
                        return -1;
 
562
                }
 
563
        }
 
564
 
 
565
        el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
 
566
        el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
 
567
 
 
568
        el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
 
569
        el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
 
570
 
 
571
        el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
 
572
        el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
 
573
 
 
574
        el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
 
575
        el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
 
576
 
 
577
        tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
 
578
        tty_bind_char(el, 1);
 
579
        return 0;
 
580
}
 
581
 
 
582
protected int
 
583
tty_init(EditLine *el)
 
584
{
 
585
 
 
586
        el->el_tty.t_mode = EX_IO;
 
587
        el->el_tty.t_vdisable = _POSIX_VDISABLE;
 
588
        (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
 
589
        (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
 
590
        return tty_setup(el);
 
591
}
 
592
 
 
593
 
 
594
/* tty_end():
 
595
 *      Restore the tty to its original settings
 
596
 */
 
597
protected void
 
598
/*ARGSUSED*/
 
599
tty_end(EditLine *el __attribute__((__unused__)))
 
600
{
 
601
 
 
602
        /* XXX: Maybe reset to an initial state? */
 
603
}
 
604
 
 
605
 
 
606
/* tty__getspeed():
 
607
 *      Get the tty speed
 
608
 */
 
609
private speed_t
 
610
tty__getspeed(struct termios *td)
 
611
{
 
612
        speed_t spd;
 
613
 
 
614
        if ((spd = cfgetispeed(td)) == 0)
 
615
                spd = cfgetospeed(td);
 
616
        return spd;
 
617
}
 
618
 
 
619
/* tty__getspeed():
 
620
 *      Return the index of the asked char in the c_cc array
 
621
 */
 
622
private int
 
623
tty__getcharindex(int i)
 
624
{
 
625
        switch (i) {
 
626
#ifdef VINTR
 
627
        case C_INTR:
 
628
                return VINTR;
 
629
#endif /* VINTR */
 
630
#ifdef VQUIT
 
631
        case C_QUIT:
 
632
                return VQUIT;
 
633
#endif /* VQUIT */
 
634
#ifdef VERASE
 
635
        case C_ERASE:
 
636
                return VERASE;
 
637
#endif /* VERASE */
 
638
#ifdef VKILL
 
639
        case C_KILL:
 
640
                return VKILL;
 
641
#endif /* VKILL */
 
642
#ifdef VEOF
 
643
        case C_EOF:
 
644
                return VEOF;
 
645
#endif /* VEOF */
 
646
#ifdef VEOL
 
647
        case C_EOL:
 
648
                return VEOL;
 
649
#endif /* VEOL */
 
650
#ifdef VEOL2
 
651
        case C_EOL2:
 
652
                return VEOL2;
 
653
#endif /* VEOL2 */
 
654
#ifdef VSWTCH
 
655
        case C_SWTCH:
 
656
                return VSWTCH;
 
657
#endif /* VSWTCH */
 
658
#ifdef VDSWTCH
 
659
        case C_DSWTCH:
 
660
                return VDSWTCH;
 
661
#endif /* VDSWTCH */
 
662
#ifdef VERASE2
 
663
        case C_ERASE2:
 
664
                return VERASE2;
 
665
#endif /* VERASE2 */
 
666
#ifdef VSTART
 
667
        case C_START:
 
668
                return VSTART;
 
669
#endif /* VSTART */
 
670
#ifdef VSTOP
 
671
        case C_STOP:
 
672
                return VSTOP;
 
673
#endif /* VSTOP */
 
674
#ifdef VWERASE
 
675
        case C_WERASE:
 
676
                return VWERASE;
 
677
#endif /* VWERASE */
 
678
#ifdef VSUSP
 
679
        case C_SUSP:
 
680
                return VSUSP;
 
681
#endif /* VSUSP */
 
682
#ifdef VDSUSP
 
683
        case C_DSUSP:
 
684
                return VDSUSP;
 
685
#endif /* VDSUSP */
 
686
#ifdef VREPRINT
 
687
        case C_REPRINT:
 
688
                return VREPRINT;
 
689
#endif /* VREPRINT */
 
690
#ifdef VDISCARD
 
691
        case C_DISCARD:
 
692
                return VDISCARD;
 
693
#endif /* VDISCARD */
 
694
#ifdef VLNEXT
 
695
        case C_LNEXT:
 
696
                return VLNEXT;
 
697
#endif /* VLNEXT */
 
698
#ifdef VSTATUS
 
699
        case C_STATUS:
 
700
                return VSTATUS;
 
701
#endif /* VSTATUS */
 
702
#ifdef VPAGE
 
703
        case C_PAGE:
 
704
                return VPAGE;
 
705
#endif /* VPAGE */
 
706
#ifdef VPGOFF
 
707
        case C_PGOFF:
 
708
                return VPGOFF;
 
709
#endif /* VPGOFF */
 
710
#ifdef VKILL2
 
711
        case C_KILL2:
 
712
                return VKILL2;
 
713
#endif /* KILL2 */
 
714
#ifdef VMIN
 
715
        case C_MIN:
 
716
                return VMIN;
 
717
#endif /* VMIN */
 
718
#ifdef VTIME
 
719
        case C_TIME:
 
720
                return VTIME;
 
721
#endif /* VTIME */
 
722
        default:
 
723
                return -1;
 
724
        }
 
725
}
 
726
 
 
727
/* tty__getchar():
 
728
 *      Get the tty characters
 
729
 */
 
730
private void
 
731
tty__getchar(struct termios *td, unsigned char *s)
 
732
{
 
733
 
 
734
#ifdef VINTR
 
735
        s[C_INTR] = td->c_cc[VINTR];
 
736
#endif /* VINTR */
 
737
#ifdef VQUIT
 
738
        s[C_QUIT] = td->c_cc[VQUIT];
 
739
#endif /* VQUIT */
 
740
#ifdef VERASE
 
741
        s[C_ERASE] = td->c_cc[VERASE];
 
742
#endif /* VERASE */
 
743
#ifdef VKILL
 
744
        s[C_KILL] = td->c_cc[VKILL];
 
745
#endif /* VKILL */
 
746
#ifdef VEOF
 
747
        s[C_EOF] = td->c_cc[VEOF];
 
748
#endif /* VEOF */
 
749
#ifdef VEOL
 
750
        s[C_EOL] = td->c_cc[VEOL];
 
751
#endif /* VEOL */
 
752
#ifdef VEOL2
 
753
        s[C_EOL2] = td->c_cc[VEOL2];
 
754
#endif /* VEOL2 */
 
755
#ifdef VSWTCH
 
756
        s[C_SWTCH] = td->c_cc[VSWTCH];
 
757
#endif /* VSWTCH */
 
758
#ifdef VDSWTCH
 
759
        s[C_DSWTCH] = td->c_cc[VDSWTCH];
 
760
#endif /* VDSWTCH */
 
761
#ifdef VERASE2
 
762
        s[C_ERASE2] = td->c_cc[VERASE2];
 
763
#endif /* VERASE2 */
 
764
#ifdef VSTART
 
765
        s[C_START] = td->c_cc[VSTART];
 
766
#endif /* VSTART */
 
767
#ifdef VSTOP
 
768
        s[C_STOP] = td->c_cc[VSTOP];
 
769
#endif /* VSTOP */
 
770
#ifdef VWERASE
 
771
        s[C_WERASE] = td->c_cc[VWERASE];
 
772
#endif /* VWERASE */
 
773
#ifdef VSUSP
 
774
        s[C_SUSP] = td->c_cc[VSUSP];
 
775
#endif /* VSUSP */
 
776
#ifdef VDSUSP
 
777
        s[C_DSUSP] = td->c_cc[VDSUSP];
 
778
#endif /* VDSUSP */
 
779
#ifdef VREPRINT
 
780
        s[C_REPRINT] = td->c_cc[VREPRINT];
 
781
#endif /* VREPRINT */
 
782
#ifdef VDISCARD
 
783
        s[C_DISCARD] = td->c_cc[VDISCARD];
 
784
#endif /* VDISCARD */
 
785
#ifdef VLNEXT
 
786
        s[C_LNEXT] = td->c_cc[VLNEXT];
 
787
#endif /* VLNEXT */
 
788
#ifdef VSTATUS
 
789
        s[C_STATUS] = td->c_cc[VSTATUS];
 
790
#endif /* VSTATUS */
 
791
#ifdef VPAGE
 
792
        s[C_PAGE] = td->c_cc[VPAGE];
 
793
#endif /* VPAGE */
 
794
#ifdef VPGOFF
 
795
        s[C_PGOFF] = td->c_cc[VPGOFF];
 
796
#endif /* VPGOFF */
 
797
#ifdef VKILL2
 
798
        s[C_KILL2] = td->c_cc[VKILL2];
 
799
#endif /* KILL2 */
 
800
#ifdef VMIN
 
801
        s[C_MIN] = td->c_cc[VMIN];
 
802
#endif /* VMIN */
 
803
#ifdef VTIME
 
804
        s[C_TIME] = td->c_cc[VTIME];
 
805
#endif /* VTIME */
 
806
}                               /* tty__getchar */
 
807
 
 
808
 
 
809
/* tty__setchar():
 
810
 *      Set the tty characters
 
811
 */
 
812
private void
 
813
tty__setchar(struct termios *td, unsigned char *s)
 
814
{
 
815
 
 
816
#ifdef VINTR
 
817
        td->c_cc[VINTR] = s[C_INTR];
 
818
#endif /* VINTR */
 
819
#ifdef VQUIT
 
820
        td->c_cc[VQUIT] = s[C_QUIT];
 
821
#endif /* VQUIT */
 
822
#ifdef VERASE
 
823
        td->c_cc[VERASE] = s[C_ERASE];
 
824
#endif /* VERASE */
 
825
#ifdef VKILL
 
826
        td->c_cc[VKILL] = s[C_KILL];
 
827
#endif /* VKILL */
 
828
#ifdef VEOF
 
829
        td->c_cc[VEOF] = s[C_EOF];
 
830
#endif /* VEOF */
 
831
#ifdef VEOL
 
832
        td->c_cc[VEOL] = s[C_EOL];
 
833
#endif /* VEOL */
 
834
#ifdef VEOL2
 
835
        td->c_cc[VEOL2] = s[C_EOL2];
 
836
#endif /* VEOL2 */
 
837
#ifdef VSWTCH
 
838
        td->c_cc[VSWTCH] = s[C_SWTCH];
 
839
#endif /* VSWTCH */
 
840
#ifdef VDSWTCH
 
841
        td->c_cc[VDSWTCH] = s[C_DSWTCH];
 
842
#endif /* VDSWTCH */
 
843
#ifdef VERASE2
 
844
        td->c_cc[VERASE2] = s[C_ERASE2];
 
845
#endif /* VERASE2 */
 
846
#ifdef VSTART
 
847
        td->c_cc[VSTART] = s[C_START];
 
848
#endif /* VSTART */
 
849
#ifdef VSTOP
 
850
        td->c_cc[VSTOP] = s[C_STOP];
 
851
#endif /* VSTOP */
 
852
#ifdef VWERASE
 
853
        td->c_cc[VWERASE] = s[C_WERASE];
 
854
#endif /* VWERASE */
 
855
#ifdef VSUSP
 
856
        td->c_cc[VSUSP] = s[C_SUSP];
 
857
#endif /* VSUSP */
 
858
#ifdef VDSUSP
 
859
        td->c_cc[VDSUSP] = s[C_DSUSP];
 
860
#endif /* VDSUSP */
 
861
#ifdef VREPRINT
 
862
        td->c_cc[VREPRINT] = s[C_REPRINT];
 
863
#endif /* VREPRINT */
 
864
#ifdef VDISCARD
 
865
        td->c_cc[VDISCARD] = s[C_DISCARD];
 
866
#endif /* VDISCARD */
 
867
#ifdef VLNEXT
 
868
        td->c_cc[VLNEXT] = s[C_LNEXT];
 
869
#endif /* VLNEXT */
 
870
#ifdef VSTATUS
 
871
        td->c_cc[VSTATUS] = s[C_STATUS];
 
872
#endif /* VSTATUS */
 
873
#ifdef VPAGE
 
874
        td->c_cc[VPAGE] = s[C_PAGE];
 
875
#endif /* VPAGE */
 
876
#ifdef VPGOFF
 
877
        td->c_cc[VPGOFF] = s[C_PGOFF];
 
878
#endif /* VPGOFF */
 
879
#ifdef VKILL2
 
880
        td->c_cc[VKILL2] = s[C_KILL2];
 
881
#endif /* VKILL2 */
 
882
#ifdef VMIN
 
883
        td->c_cc[VMIN] = s[C_MIN];
 
884
#endif /* VMIN */
 
885
#ifdef VTIME
 
886
        td->c_cc[VTIME] = s[C_TIME];
 
887
#endif /* VTIME */
 
888
}                               /* tty__setchar */
 
889
 
 
890
 
 
891
/* tty_bind_char():
 
892
 *      Rebind the editline functions
 
893
 */
 
894
protected void
 
895
tty_bind_char(EditLine *el, int force)
 
896
{
 
897
 
 
898
        unsigned char *t_n = el->el_tty.t_c[ED_IO];
 
899
        unsigned char *t_o = el->el_tty.t_ed.c_cc;
 
900
        Char new[2], old[2];
 
901
        const ttymap_t *tp;
 
902
        el_action_t *map, *alt;
 
903
        const el_action_t *dmap, *dalt;
 
904
        new[1] = old[1] = '\0';
 
905
 
 
906
        map = el->el_map.key;
 
907
        alt = el->el_map.alt;
 
908
        if (el->el_map.type == MAP_VI) {
 
909
                dmap = el->el_map.vii;
 
910
                dalt = el->el_map.vic;
 
911
        } else {
 
912
                dmap = el->el_map.emacs;
 
913
                dalt = NULL;
 
914
        }
 
915
 
 
916
        for (tp = tty_map; tp->nch != (Int)-1; tp++) {
 
917
                new[0] = t_n[tp->nch];
 
918
                old[0] = t_o[tp->och];
 
919
                if (new[0] == old[0] && !force)
 
920
                        continue;
 
921
                /* Put the old default binding back, and set the new binding */
 
922
                keymacro_clear(el, map, old);
 
923
                map[UC(old[0])] = dmap[UC(old[0])];
 
924
                keymacro_clear(el, map, new);
 
925
                /* MAP_VI == 1, MAP_EMACS == 0... */
 
926
                map[UC(new[0])] = tp->bind[el->el_map.type];
 
927
                if (dalt) {
 
928
                        keymacro_clear(el, alt, old);
 
929
                        alt[UC(old[0])] = dalt[UC(old[0])];
 
930
                        keymacro_clear(el, alt, new);
 
931
                        alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
 
932
                }
 
933
        }
 
934
}
 
935
 
 
936
 
 
937
/* tty_rawmode():
 
938
 *      Set terminal into 1 character at a time mode.
 
939
 */
 
940
protected int
 
941
tty_rawmode(EditLine *el)
 
942
{
 
943
 
 
944
        if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
 
945
                return 0;
 
946
 
 
947
        if (el->el_flags & EDIT_DISABLED)
 
948
                return 0;
 
949
 
 
950
        if (tty_getty(el, &el->el_tty.t_ts) == -1) {
 
951
#ifdef DEBUG_TTY
 
952
                (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n",
 
953
                    strerror(errno));
 
954
#endif /* DEBUG_TTY */
 
955
                return -1;
 
956
        }
 
957
        /*
 
958
         * We always keep up with the eight bit setting and the speed of the
 
959
         * tty. But we only believe changes that are made to cooked mode!
 
960
         */
 
961
        el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
 
962
        el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
 
963
 
 
964
        if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
 
965
            tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
 
966
                (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
 
967
                (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
 
968
                (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
 
969
                (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
 
970
        }
 
971
        if (tty__cooked_mode(&el->el_tty.t_ts)) {
 
972
                if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
 
973
                        el->el_tty.t_ex.c_cflag =
 
974
                            el->el_tty.t_ts.c_cflag;
 
975
                        el->el_tty.t_ex.c_cflag &=
 
976
                            ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
 
977
                        el->el_tty.t_ex.c_cflag |=
 
978
                            el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
 
979
 
 
980
                        el->el_tty.t_ed.c_cflag =
 
981
                            el->el_tty.t_ts.c_cflag;
 
982
                        el->el_tty.t_ed.c_cflag &=
 
983
                            ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
 
984
                        el->el_tty.t_ed.c_cflag |=
 
985
                            el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
 
986
                }
 
987
                if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
 
988
                    (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
 
989
                        el->el_tty.t_ex.c_lflag =
 
990
                            el->el_tty.t_ts.c_lflag;
 
991
                        el->el_tty.t_ex.c_lflag &=
 
992
                            ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
 
993
                        el->el_tty.t_ex.c_lflag |=
 
994
                            el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
 
995
 
 
996
                        el->el_tty.t_ed.c_lflag =
 
997
                            el->el_tty.t_ts.c_lflag;
 
998
                        el->el_tty.t_ed.c_lflag &=
 
999
                            ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
 
1000
                        el->el_tty.t_ed.c_lflag |=
 
1001
                            el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
 
1002
                }
 
1003
                if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
 
1004
                    (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
 
1005
                        el->el_tty.t_ex.c_iflag =
 
1006
                            el->el_tty.t_ts.c_iflag;
 
1007
                        el->el_tty.t_ex.c_iflag &=
 
1008
                            ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
 
1009
                        el->el_tty.t_ex.c_iflag |=
 
1010
                            el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
 
1011
 
 
1012
                        el->el_tty.t_ed.c_iflag =
 
1013
                            el->el_tty.t_ts.c_iflag;
 
1014
                        el->el_tty.t_ed.c_iflag &=
 
1015
                            ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
 
1016
                        el->el_tty.t_ed.c_iflag |=
 
1017
                            el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
 
1018
                }
 
1019
                if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
 
1020
                    (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
 
1021
                        el->el_tty.t_ex.c_oflag =
 
1022
                            el->el_tty.t_ts.c_oflag;
 
1023
                        el->el_tty.t_ex.c_oflag &=
 
1024
                            ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
 
1025
                        el->el_tty.t_ex.c_oflag |=
 
1026
                            el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
 
1027
 
 
1028
                        el->el_tty.t_ed.c_oflag =
 
1029
                            el->el_tty.t_ts.c_oflag;
 
1030
                        el->el_tty.t_ed.c_oflag &=
 
1031
                            ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
 
1032
                        el->el_tty.t_ed.c_oflag |=
 
1033
                            el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
 
1034
                }
 
1035
                if (tty__gettabs(&el->el_tty.t_ex) == 0)
 
1036
                        el->el_tty.t_tabs = 0;
 
1037
                else
 
1038
                        el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
 
1039
 
 
1040
                {
 
1041
                        int i;
 
1042
 
 
1043
                        tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
 
1044
                        /*
 
1045
                         * Check if the user made any changes.
 
1046
                         * If he did, then propagate the changes to the
 
1047
                         * edit and execute data structures.
 
1048
                         */
 
1049
                        for (i = 0; i < C_NCC; i++)
 
1050
                                if (el->el_tty.t_c[TS_IO][i] !=
 
1051
                                    el->el_tty.t_c[EX_IO][i])
 
1052
                                        break;
 
1053
 
 
1054
                        if (i != C_NCC) {
 
1055
                                /*
 
1056
                                 * Propagate changes only to the unprotected
 
1057
                                 * chars that have been modified just now.
 
1058
                                 */
 
1059
                                for (i = 0; i < C_NCC; i++) {
 
1060
                                        if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
 
1061
                                            && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
 
1062
                                                el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
 
1063
                                        if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
 
1064
                                                el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
 
1065
                                }
 
1066
                                tty_bind_char(el, 0);
 
1067
                                tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
 
1068
 
 
1069
                                for (i = 0; i < C_NCC; i++) {
 
1070
                                        if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
 
1071
                                            && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
 
1072
                                                el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
 
1073
                                        if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
 
1074
                                                el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
 
1075
                                }
 
1076
                                tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
 
1077
                        }
 
1078
                }
 
1079
        }
 
1080
        if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
 
1081
#ifdef DEBUG_TTY
 
1082
                (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
 
1083
                    strerror(errno));
 
1084
#endif /* DEBUG_TTY */
 
1085
                return -1;
 
1086
        }
 
1087
        el->el_tty.t_mode = ED_IO;
 
1088
        return 0;
 
1089
}
 
1090
 
 
1091
 
 
1092
/* tty_cookedmode():
 
1093
 *      Set the tty back to normal mode
 
1094
 */
 
1095
protected int
 
1096
tty_cookedmode(EditLine *el)
 
1097
{                               /* set tty in normal setup */
 
1098
 
 
1099
        if (el->el_tty.t_mode == EX_IO)
 
1100
                return 0;
 
1101
 
 
1102
        if (el->el_flags & EDIT_DISABLED)
 
1103
                return 0;
 
1104
 
 
1105
        if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
 
1106
#ifdef DEBUG_TTY
 
1107
                (void) fprintf(el->el_errfile,
 
1108
                    "tty_cookedmode: tty_setty: %s\n",
 
1109
                    strerror(errno));
 
1110
#endif /* DEBUG_TTY */
 
1111
                return -1;
 
1112
        }
 
1113
        el->el_tty.t_mode = EX_IO;
 
1114
        return 0;
 
1115
}
 
1116
 
 
1117
 
 
1118
/* tty_quotemode():
 
1119
 *      Turn on quote mode
 
1120
 */
 
1121
protected int
 
1122
tty_quotemode(EditLine *el)
 
1123
{
 
1124
        if (el->el_tty.t_mode == QU_IO)
 
1125
                return 0;
 
1126
 
 
1127
        el->el_tty.t_qu = el->el_tty.t_ed;
 
1128
 
 
1129
        el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
 
1130
        el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
 
1131
 
 
1132
        el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
 
1133
        el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
 
1134
 
 
1135
        el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
 
1136
        el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
 
1137
 
 
1138
        el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
 
1139
        el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
 
1140
 
 
1141
        if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
 
1142
#ifdef DEBUG_TTY
 
1143
                (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
 
1144
                    strerror(errno));
 
1145
#endif /* DEBUG_TTY */
 
1146
                return -1;
 
1147
        }
 
1148
        el->el_tty.t_mode = QU_IO;
 
1149
        return 0;
 
1150
}
 
1151
 
 
1152
 
 
1153
/* tty_noquotemode():
 
1154
 *      Turn off quote mode
 
1155
 */
 
1156
protected int
 
1157
tty_noquotemode(EditLine *el)
 
1158
{
 
1159
 
 
1160
        if (el->el_tty.t_mode != QU_IO)
 
1161
                return 0;
 
1162
        if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
 
1163
#ifdef DEBUG_TTY
 
1164
                (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
 
1165
                    strerror(errno));
 
1166
#endif /* DEBUG_TTY */
 
1167
                return -1;
 
1168
        }
 
1169
        el->el_tty.t_mode = ED_IO;
 
1170
        return 0;
 
1171
}
 
1172
 
 
1173
 
 
1174
/* tty_stty():
 
1175
 *      Stty builtin
 
1176
 */
 
1177
protected int
 
1178
/*ARGSUSED*/
 
1179
tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
 
1180
{
 
1181
        const ttymodes_t *m;
 
1182
        char x;
 
1183
        int aflag = 0;
 
1184
        const Char *s, *d;
 
1185
        char name[EL_BUFSIZ];
 
1186
        struct termios *tios = &el->el_tty.t_ex;
 
1187
        int z = EX_IO;
 
1188
 
 
1189
        if (argv == NULL)
 
1190
                return -1;
 
1191
        strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
 
1192
        name[sizeof(name) - 1] = '\0';
 
1193
 
 
1194
        while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
 
1195
                switch (argv[0][1]) {
 
1196
                case 'a':
 
1197
                        aflag++;
 
1198
                        argv++;
 
1199
                        break;
 
1200
                case 'd':
 
1201
                        argv++;
 
1202
                        tios = &el->el_tty.t_ed;
 
1203
                        z = ED_IO;
 
1204
                        break;
 
1205
                case 'x':
 
1206
                        argv++;
 
1207
                        tios = &el->el_tty.t_ex;
 
1208
                        z = EX_IO;
 
1209
                        break;
 
1210
                case 'q':
 
1211
                        argv++;
 
1212
                        tios = &el->el_tty.t_ts;
 
1213
                        z = QU_IO;
 
1214
                        break;
 
1215
                default:
 
1216
                        (void) fprintf(el->el_errfile,
 
1217
                            "%s: Unknown switch `%c'.\n",
 
1218
                            name, argv[0][1]);
 
1219
                        return -1;
 
1220
                }
 
1221
 
 
1222
        if (!argv || !*argv) {
 
1223
                int i = -1;
 
1224
                size_t len = 0, st = 0, cu;
 
1225
                for (m = ttymodes; m->m_name; m++) {
 
1226
                        if (m->m_type != i) {
 
1227
                                (void) fprintf(el->el_outfile, "%s%s",
 
1228
                                    i != -1 ? "\n" : "",
 
1229
                                    el->el_tty.t_t[z][m->m_type].t_name);
 
1230
                                i = m->m_type;
 
1231
                                st = len =
 
1232
                                    strlen(el->el_tty.t_t[z][m->m_type].t_name);
 
1233
                        }
 
1234
                        if (i != -1) {
 
1235
                            x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
 
1236
                                ?  '+' : '\0';
 
1237
 
 
1238
                            if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
 
1239
                                x = '-';
 
1240
                        } else {
 
1241
                            x = '\0';
 
1242
                        }
 
1243
 
 
1244
                        if (x != '\0' || aflag) {
 
1245
 
 
1246
                                cu = strlen(m->m_name) + (x != '\0') + 1;
 
1247
 
 
1248
                                if (len + cu >= (size_t)el->el_terminal.t_size.h) {
 
1249
                                        (void) fprintf(el->el_outfile, "\n%*s",
 
1250
                                            (int)st, "");
 
1251
                                        len = st + cu;
 
1252
                                } else
 
1253
                                        len += cu;
 
1254
 
 
1255
                                if (x != '\0')
 
1256
                                        (void) fprintf(el->el_outfile, "%c%s ",
 
1257
                                            x, m->m_name);
 
1258
                                else
 
1259
                                        (void) fprintf(el->el_outfile, "%s ",
 
1260
                                            m->m_name);
 
1261
                        }
 
1262
                }
 
1263
                (void) fprintf(el->el_outfile, "\n");
 
1264
                return 0;
 
1265
        }
 
1266
        while (argv && (s = *argv++)) {
 
1267
                const Char *p;
 
1268
                switch (*s) {
 
1269
                case '+':
 
1270
                case '-':
 
1271
                        x = (char)*s++;
 
1272
                        break;
 
1273
                default:
 
1274
                        x = '\0';
 
1275
                        break;
 
1276
                }
 
1277
                d = s;
 
1278
                p = Strchr(s, '=');
 
1279
                for (m = ttymodes; m->m_name; m++)
 
1280
                        if ((p ? strncmp(m->m_name, ct_encode_string(d, &el->el_scratch), (size_t)(p - d)) :
 
1281
                            strcmp(m->m_name, ct_encode_string(d, &el->el_scratch))) == 0 &&
 
1282
                            (p == NULL || m->m_type == MD_CHAR))
 
1283
                                break;
 
1284
 
 
1285
                if (!m->m_name) {
 
1286
                        (void) fprintf(el->el_errfile,
 
1287
                            "%s: Invalid argument `" FSTR "'.\n", name, d);
 
1288
                        return -1;
 
1289
                }
 
1290
                if (p) {
 
1291
                        int c = ffs((int)m->m_value);
 
1292
                        int v = *++p ? parse__escape(&p) :
 
1293
                            el->el_tty.t_vdisable;
 
1294
                        assert(c != 0);
 
1295
                        c--;
 
1296
                        c = tty__getcharindex(c);
 
1297
                        assert(c != -1);
 
1298
                        tios->c_cc[c] = (cc_t)v;
 
1299
                        continue;
 
1300
                }
 
1301
                switch (x) {
 
1302
                case '+':
 
1303
                        el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
 
1304
                        el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
 
1305
                        break;
 
1306
                case '-':
 
1307
                        el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
 
1308
                        el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
 
1309
                        break;
 
1310
                default:
 
1311
                        el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
 
1312
                        el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
 
1313
                        break;
 
1314
                }
 
1315
        }
 
1316
 
 
1317
        if (el->el_tty.t_mode == z) {
 
1318
                if (tty_setty(el, TCSADRAIN, tios) == -1) {
 
1319
#ifdef DEBUG_TTY
 
1320
                        (void) fprintf(el->el_errfile,
 
1321
                            "tty_stty: tty_setty: %s\n", strerror(errno));
 
1322
#endif /* DEBUG_TTY */
 
1323
                        return -1;
 
1324
                }
 
1325
        }
 
1326
 
 
1327
        return 0;
 
1328
}
 
1329
 
 
1330
 
 
1331
#ifdef notyet
 
1332
/* tty_printchar():
 
1333
 *      DEbugging routine to print the tty characters
 
1334
 */
 
1335
private void
 
1336
tty_printchar(EditLine *el, unsigned char *s)
 
1337
{
 
1338
        ttyperm_t *m;
 
1339
        int i;
 
1340
 
 
1341
        for (i = 0; i < C_NCC; i++) {
 
1342
                for (m = el->el_tty.t_t; m->m_name; m++)
 
1343
                        if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
 
1344
                                break;
 
1345
                if (m->m_name)
 
1346
                        (void) fprintf(el->el_errfile, "%s ^%c ",
 
1347
                            m->m_name, s[i] + 'A' - 1);
 
1348
                if (i % 5 == 0)
 
1349
                        (void) fprintf(el->el_errfile, "\n");
 
1350
        }
 
1351
        (void) fprintf(el->el_errfile, "\n");
 
1352
}
 
1353
#endif /* notyet */