1 /* @(#)ttymodes.c 1.35 16/08/14 Copyright 1986,1995-2016 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)ttymodes.c 1.35 16/08/14 Copyright 1986,1995-2016 J. Schilling";
6 #endif
7 /*
8 * ttymodes.c
9 *
10 * Terminal handling for bsh
11 *
12 * Copyright (c) 1986,1995-2016 J. Schilling
13 */
14 /*
15 * The contents of this file are subject to the terms of the
16 * Common Development and Distribution License, Version 1.0 only
17 * (the "License"). You may not use this file except in compliance
18 * with the License.
19 *
20 * See the file CDDL.Schily.txt in this distribution for details.
21 * A copy of the CDDL is also available via the Internet at
22 * http://www.opensource.org/licenses/cddl1.txt
23 *
24 * When distributing Covered Code, include this CDDL HEADER in each
25 * file and include the License file CDDL.Schily.txt from this distribution.
26 */
27
28 #include <schily/stdio.h>
29 #include <schily/unistd.h>
30 #define putch dos_putch /* Avoid DOS/curses putch() type clash */
31 #define ungetch dos_ungetch /* Avoid DOS/curses ungetch() type clash */
32 #include <schily/termios.h>
33 #undef putch /* Restore our old value */
34 #undef ungetch /* Restore our old value */
35
36 #include "bsh.h"
37
38 #ifdef INTERACTIVE
39
40 #define OLD_MODE 1
41 #define INS_MODE 2
42 #define APP_MODE 3
43
44 extern pid_t mypgrp;
45
46 BOOL ins_mode = FALSE;
47 BOOL i_should_echo = FALSE;
48
49 LOCAL BOOL cmdmodes = FALSE;
50
51
52 LOCAL BOOL tty_init = FALSE;
53
54 #ifdef USE_V7_TTY
55
56 LOCAL struct sgttyb ins = {0};
57 LOCAL struct sgttyb app = {0};
58 LOCAL struct sgttyb old = {0};
59 LOCAL struct tchars oldt = {0};
60 LOCAL struct tchars inst = {0};
61 LOCAL struct tchars appt = {0};
62 #ifdef TIOCSLTC
63 LOCAL struct ltchars oldl = {0};
64 LOCAL struct ltchars insl = {0};
65 LOCAL struct ltchars appl = {0};
66 #endif
67
68 #ifdef NTTYDISC
69 LOCAL int olddisc = -1;
70 LOCAL int disc = NTTYDISC;
71 #endif /* NTTYDISC */
72
73 #else /* !USE_V7_TTY */
74
75 #ifdef USE_TERMIOS
76 LOCAL struct termios ins = {0};
77 LOCAL struct termios app = {0};
78 LOCAL struct termios old = {0};
79 #endif
80
81 #endif /* !USE_V7_TTY */
82
83 #ifdef JOBCONTROL
84 LOCAL pid_t oldpgrp = 0;
85 #endif /* JOBCONTROL */
86
87 EXPORT void reset_line_disc __PR((void));
88 EXPORT void reset_tty_pgrp __PR((void));
89 EXPORT void reset_tty_modes __PR((void));
90 EXPORT void set_append_modes __PR((FILE *f));
91 EXPORT void set_insert_modes __PR((FILE *f));
92 #ifdef JOBCONTROL
93 LOCAL void init_tty_pgrp __PR((void));
94 #endif
95 EXPORT void get_tty_modes __PR((FILE *f));
96 LOCAL void init_tty_modes __PR((void));
97 LOCAL void set_tty_modes __PR((FILE *f, int mode));
98 EXPORT pid_t tty_getpgrp __PR((int f));
99 EXPORT int tty_setpgrp __PR((int f, pid_t pgrp));
100
101 EXPORT void
reset_line_disc()102 reset_line_disc()
103 {
104 #if defined(USE_V7_TTY) && defined(NTTYDISC)
105 FILE *f;
106
107 if ((f = getinfile()) && olddisc != NTTYDISC)
108 ioctl(fdown(f), TIOCSETD, (char *)&olddisc);
109
110 #endif /* defined(USE_V7_TTY) && defined(NTTYDISC) */
111 }
112
113 EXPORT void
reset_tty_pgrp()114 reset_tty_pgrp()
115 {
116 #ifdef JOBCONTROL
117 FILE *f;
118
119 if ((f = getinfile()) != 0 && oldpgrp != 0)
120 tty_setpgrp(fdown(f), oldpgrp);
121 #endif /* JOBCONTROL */
122 }
123
124 EXPORT void
reset_tty_modes()125 reset_tty_modes()
126 {
127 #if defined(USE_V7_TTY) && defined(NTTYDISC)
128
129 if (olddisc < 0)
130 init_line_disc();
131
132 #endif /* defined(USE_V7_TTY) && defined(NTTYDISC) */
133
134 set_tty_modes(getinfile(), OLD_MODE);
135 cmdmodes = FALSE;
136 }
137
138 EXPORT void
set_append_modes(f)139 set_append_modes(f)
140 FILE *f;
141 {
142 if (ins_mode) {
143 set_tty_modes(f, APP_MODE);
144 i_should_echo = TRUE;
145 ins_mode = FALSE;
146 cmdmodes = TRUE;
147 }
148 }
149
150 EXPORT void
set_insert_modes(f)151 set_insert_modes(f)
152 FILE *f;
153 {
154 if (!ins_mode) {
155 set_tty_modes(f, INS_MODE);
156 ins_mode = TRUE;
157 cmdmodes = TRUE;
158 }
159 }
160
161 /*
162 * Beim Umschalten der Linedisziplin geht der Input verloren.
163 * Um nach dem Starten des 'bsh' jederzeit Kommandos eingeben zu
164 * koennen wird nur einmal vor dem Starten des ersten
165 * interaktven Kommandos auf die neue Linedisziplin umgeschaltet.
166 * Dies geschieht in 'reset_tty_modes()'.
167 * Die erste Zeile wird mit der davor aktiven Disziplin editiert.
168 * Da die neue Linedisziplin nur fuer die Prozesskontrolle von
169 * laufenden Kommandos benoetigt wird, ist das kein Fehler.
170 */
171 #if defined(USE_V7_TTY) && defined(NTTYDISC)
172 EXPORT void
init_line_disc()173 init_line_disc()
174 {
175 int fno;
176 FILE *f;
177
178 if (f = getinfile()) {
179 fno = fdown(f);
180 ioctl(fno, TIOCGETD, (char *)&olddisc);
181 if (olddisc != NTTYDISC)
182 ioctl(fno, TIOCSETD, (char *)&disc);
183 }
184 }
185 #endif /* defined(USE_V7_TTY) && defined(NTTYDISC) */
186
187 #ifdef JOBCONTROL
188 LOCAL void
init_tty_pgrp()189 init_tty_pgrp()
190 {
191 int fno;
192 FILE *f;
193
194 if ((f = getinfile()) != NULL) {
195 fno = fdown(f);
196 oldpgrp = tty_getpgrp(fno);
197 tty_setpgrp(fno, mypgrp);
198 }
199 }
200 #endif /* JOBCONTROL */
201
202 EXPORT void
get_tty_modes(f)203 get_tty_modes(f)
204 FILE *f;
205 {
206 if (!cmdmodes) {
207 #ifdef USE_V7_TTY
208 ioctl(fdown(f), TIOCGETP, (char *)&old);
209 ins.sg_ispeed = old.sg_ispeed;
210 ins.sg_ospeed = old.sg_ospeed;
211 app.sg_ispeed = old.sg_ispeed;
212 app.sg_ospeed = old.sg_ospeed;
213 ins.sg_flags = old.sg_flags;
214 app.sg_flags = old.sg_flags;
215 ins.sg_flags |= (CBREAK|CRMOD);
216 ins.sg_flags &= ~(ECHO|RAW);
217 app.sg_flags |= (CBREAK|CRMOD);
218 app.sg_flags &= ~(ECHO|RAW);
219 ioctl(fdown(f), TIOCGETC, (char *)&oldt);
220 inst.t_startc = oldt.t_startc;
221 inst.t_stopc = oldt.t_stopc;
222 appt.t_startc = oldt.t_startc;
223 appt.t_stopc = oldt.t_stopc;
224 #ifdef TIOCSLTC
225 ioctl(fdown(f), TIOCGLTC, (char *)&oldl);
226 #endif
227 #else /* !USE_V7_TTY */
228 #ifdef USE_TERMIOS
229 #ifdef TCSANOW
230 tcgetattr(fdown(f), &old);
231 #else
232 ioctl(fdown(f), TCGETS, (char *)&old);
233 #endif
234
235 app.c_iflag = ins.c_iflag = old.c_iflag;
236 app.c_oflag = ins.c_oflag = old.c_oflag;
237 app.c_cflag = ins.c_cflag = old.c_cflag;
238 app.c_lflag = ins.c_lflag = old.c_lflag;
239
240 ins.c_iflag |= (IGNBRK);
241 ins.c_iflag &= ~(BRKINT|INLCR|ICRNL);
242 ins.c_oflag |= (OPOST);
243 ins.c_lflag &= ~(ISIG|ICANON|ECHO);
244
245 app.c_iflag |= (IGNBRK);
246 app.c_iflag &= ~(BRKINT|INLCR|ICRNL);
247 app.c_oflag |= (OPOST);
248 app.c_lflag &= ~(ISIG|ICANON|ECHO);
249 #endif /* USE_TERMIOS */
250 #endif /* !USE_V7_TTY */
251 if (!tty_init) {
252 init_tty_modes();
253 #ifdef JOBCONTROL
254 init_tty_pgrp();
255 #endif /* JOBCONTROL */
256 tty_init = TRUE;
257 }
258 }
259 }
260
261
262 LOCAL void
init_tty_modes()263 init_tty_modes()
264 {
265 #ifdef USE_V7_TTY
266 movebytes((char *)&old, (char *)&app, sizeof (old));
267 movebytes((char *)&old, (char *)&ins, sizeof (old));
268 ins.sg_erase = -1;
269 ins.sg_kill = -1;
270 app.sg_erase = -1;
271 app.sg_kill = -1;
272 ins.sg_flags |= (CBREAK|CRMOD);
273 ins.sg_flags &= ~(ECHO|RAW);
274 app.sg_flags |= (CBREAK|CRMOD);
275 app.sg_flags &= ~(ECHO|RAW);
276 movebytes((char *)&oldt, (char *)&inst, sizeof (inst));
277 inst.t_intrc = -1;
278 inst.t_quitc = -1;
279 #ifdef __never__
280 /* Auf keinen Fall !!! */
281 inst.t_startc = -1;
282 inst.t_stopc = -1;
283 #endif
284 inst.t_eofc = -1;
285 inst.t_brkc = -1;
286 #ifdef TIOCSLTC
287 insl.t_suspc = -1;
288 insl.t_dsuspc = -1;
289 insl.t_rprntc = -1;
290 insl.t_flushc = -1;
291 insl.t_werasc = -1;
292 insl.t_lnextc = -1;
293 movebytes((char *)&insl, (char *)&appl, sizeof (insl));
294 #endif
295 movebytes((char *)&inst, (char *)&appt, sizeof (inst));
296 #else
297 #ifdef USE_TERMIOS
298 movebytes((char *)&old, (char *)&app, sizeof (old));
299 movebytes((char *)&old, (char *)&ins, sizeof (old));
300
301 ins.c_iflag |= (IGNBRK);
302 ins.c_iflag &= ~(BRKINT|INLCR|ICRNL);
303 ins.c_oflag |= (OPOST);
304 ins.c_lflag &= ~(ISIG|ICANON|ECHO);
305 ins.c_cc[VMIN] = 1;
306 ins.c_cc[VTIME] = 0;
307 #ifdef VREPRINT
308 ins.c_cc[VREPRINT] = _POSIX_VDISABLE;
309 #endif
310 #ifdef VDISCARD
311 ins.c_cc[VDISCARD] = _POSIX_VDISABLE;
312 #endif
313 #ifdef VWERASE
314 ins.c_cc[VWERASE] = _POSIX_VDISABLE;
315 #endif
316 #ifdef VLNEXT
317 ins.c_cc[VLNEXT] = _POSIX_VDISABLE;
318 #endif
319 app.c_iflag |= (IGNBRK);
320 app.c_iflag &= ~(BRKINT|INLCR|ICRNL);
321 app.c_oflag |= (OPOST);
322 app.c_lflag &= ~(ISIG|ICANON|ECHO);
323 app.c_cc[VMIN] = 1;
324 app.c_cc[VTIME] = 0;
325 #ifdef VREPRINT
326 app.c_cc[VREPRINT] = _POSIX_VDISABLE;
327 #endif
328 #ifdef VDISCARD
329 app.c_cc[VDISCARD] = _POSIX_VDISABLE;
330 #endif
331 #ifdef VWERASE
332 app.c_cc[VWERASE] = _POSIX_VDISABLE;
333 #endif
334 #ifdef VLNEXT
335 app.c_cc[VLNEXT] = _POSIX_VDISABLE;
336 #endif
337 #endif /* USE_TERMIOS */
338 #endif /* USE_V7_TTY */
339 }
340
341
342 LOCAL void
set_tty_modes(f,mode)343 set_tty_modes(f, mode)
344 FILE *f;
345 int mode;
346 {
347 int fno;
348
349 if (f == NULL)
350 return;
351
352 fno = fdown(f);
353
354 switch (mode) {
355
356 #ifdef USE_V7_TTY
357 case OLD_MODE:
358 ioctl(fno, TIOCSETN, (char *)&old);
359 ioctl(fno, TIOCSETC, (char *)&oldt);
360 #ifdef TIOCSLTC
361 ioctl(fno, TIOCSLTC, (char *)&oldl);
362 #endif
363 break;
364 case APP_MODE:
365 ioctl(fno, TIOCSETN, (char *)&app);
366 ioctl(fno, TIOCSETC, (char *)&appt);
367 #ifdef TIOCSLTC
368 ioctl(fno, TIOCSLTC, (char *)&appl);
369 #endif
370 break;
371 case INS_MODE:
372 ioctl(fno, TIOCSETN, (char *)&ins);
373 ioctl(fno, TIOCSETC, (char *)&inst);
374 #ifdef TIOCSLTC
375 ioctl(fno, TIOCSLTC, (char *)&insl);
376 #endif
377 break;
378 #else
379 #ifdef USE_TERMIOS
380 #ifdef TCSANOW
381
382 case OLD_MODE:
383 tcsetattr(fno, TCSADRAIN, &old);
384 break;
385 case APP_MODE:
386 tcsetattr(fno, TCSADRAIN, &app);
387 break;
388 case INS_MODE:
389 tcsetattr(fno, TCSADRAIN, &ins);
390 break;
391 #else /* !TCSANOW */
392
393 case OLD_MODE:
394 ioctl(fno, TCSETSW, (char *)&old);
395 break;
396 case APP_MODE:
397 ioctl(fno, TCSETSW, (char *)&app);
398 break;
399 case INS_MODE:
400 ioctl(fno, TCSETSW, (char *)&ins);
401 break;
402 #endif /* !TCSANOW */
403 #endif /* USE_TERMIOS */
404 #endif /* USE_V7_TTY */
405 }
406 }
407
408 #endif /* INTERACTIVE */
409
410 #ifdef JOBCONTROL
411 EXPORT pid_t
tty_getpgrp(f)412 tty_getpgrp(f)
413 int f;
414 {
415 #ifdef HAVE_TCGETPGRP
416 return (tcgetpgrp(f));
417 #else
418 #ifdef TIOCGPGRP
419 pid_t pgrp;
420
421 if (ioctl(f, TIOCGPGRP, (char *)&pgrp) < 0)
422 return ((pid_t)-1);
423 return (pgrp);
424 #else
425 #ifdef ENOSYS
426 seterrno(ENOSYS);
427 #else
428 seterrno(EINVAL);
429 #endif
430 return ((pid_t)-1);
431 #endif
432 #endif /* HAVE_TCGETPGRP */
433 }
434
435 #ifdef PROTOTYPES
436 EXPORT int
tty_setpgrp(int f,pid_t pgrp)437 tty_setpgrp(int f, pid_t pgrp)
438 #else
439 EXPORT int
440 tty_setpgrp(f, pgrp)
441 int f;
442 pid_t pgrp;
443 #endif
444 {
445 #ifdef HAVE_TCGETPGRP
446 return (tcsetpgrp(f, pgrp));
447 #else
448 #ifdef TIOCSPGRP
449 return (ioctl(f, TIOCSPGRP, (char *)&pgrp));
450 #else
451 return (0);
452 #endif
453 #endif /* HAVE_TCSETPGRP */
454 }
455 #else
456 EXPORT pid_t
tty_getpgrp(f)457 tty_getpgrp(f)
458 int f;
459 {
460 #ifdef ENOSYS
461 seterrno(ENOSYS);
462 #else
463 seterrno(EINVAL);
464 #endif
465 return ((pid_t)-1);
466 }
467
468 EXPORT int
tty_setpgrp(f,pgrp)469 tty_setpgrp(f, pgrp)
470 int f;
471 pid_t pgrp;
472 {
473 return (0);
474 }
475 #endif
476