BRL-CAD
termio.c
Go to the documentation of this file.
1 /* T E R M I O . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2007-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file libtermio/termio.c
21  *
22  */
23 
24 #include "common.h"
25 
26 #ifdef HAVE_SYS_FILE_H
27 # include <sys/file.h>
28 #endif
29 
30 #ifdef HAVE_SYS_IOCTL_COMPAT_H
31 # if defined(__FreeBSD__) && !defined(COMPAT_43TTY) /* TODO: figure out a better way, mebbe 43bsd tty semantics isn't right anymore? */
32 # define COMPAT_43TTY 1
33 # endif
34 # include <sys/ioctl_compat.h>
35 # if !defined(OCRNL)
36 # define OCRNL 0000010
37 # endif
38 #endif
39 
40 #include "bio.h"
41 
42 /*
43  * This file will work IFF one of these three flags is set:
44  * HAVE_TERMIOS_H use POXIX termios and tcsetattr() call with XOPEN flags
45  * SYSV use SysV Rel3 termio and TCSETA ioctl
46  * BSD use Version 7 / BSD sgttyb and TIOCSETP ioctl
47  */
48 
49 #if defined(HAVE_MEMORY_H)
50 # include <memory.h>
51 #endif
52 
53 
54 /*
55  * Figure out the maximum number of files that can simultaneously be open
56  * by a process.
57  */
58 
59 #if !defined(FOPEN_MAX) && defined(_NFILE)
60 # define FOPEN_MAX _NFILE
61 #endif
62 #if !defined(FOPEN_MAX) && defined(NOFILE)
63 # define FOPEN_MAX NOFILE
64 #endif
65 #if !defined(FOPEN_MAX) && defined(OPEN_MAX)
66 # define FOPEN_MAX OPEN_MAX
67 #endif
68 #if !defined(FOPEN_MAX) && defined(_SYS_OPEN)
69 # define FOPEN_MAX _SYS_OPEN
70 #endif
71 #if !defined(FOPEN_MAX)
72 # define FOPEN_MAX 32
73 #endif
74 
75 
76 /* figure out how to do tab-expansion */
77 #if !defined(TAB_EXPANSION) && defined(TAB3)
78 # define TAB_EXPANSION TAB3
79 #endif
80 #if !defined(TAB_EXPANSION) && defined(XTABS)
81 # define TAB_EXPANSION XTABS
82 #endif
83 #if !defined(TAB_EXPANSION) && defined(OXTABS)
84 # define TAB_EXPANSION OXTABS
85 #endif
86 #if !defined(TAB_EXPANSION) && defined(TAB1) && defined(TAB2)
87 # define TAB_EXPANSION (TAB1 | TAB2) /* obsolete */
88 #endif
89 #ifndef TAB_EXPANSION
90 # define TAB_EXPANSION 0 /* punt */
91 #endif
92 
93 
94 #if defined(HAVE_TERMIOS_H)
95 # undef SYSV
96 # undef BSD
97 # include <termios.h>
98 
99 static struct termios save_tio[FOPEN_MAX], curr_tio[FOPEN_MAX];
100 
101 #else /* !defined(HAVE_TERMIOS_H) */
102 
103 # ifdef SYSV
104 # undef BSD
105 # include <termio.h>
106 # include <memory.h>
107 static struct termio save_tio[FOPEN_MAX], curr_tio[FOPEN_MAX];
108 # endif /* SYSV */
109 
110 # ifdef BSD
111 # undef SYSV
112 # include <sys/ioctl.h>
113 
114 static struct sgttyb save_tio[FOPEN_MAX], curr_tio[FOPEN_MAX];
115 # endif /* BSD */
116 
117 #endif /* HAVE_TERMIOS_H */
118 
119 #include "libtermio.h"
120 
121 
122 static int fileStatus[FOPEN_MAX];
123 
124 
125 /*
126  Clear CBREAK mode, for file descriptor 'fd'.
127 */
128 void
129 clr_Cbreak(int fd)
130 {
131 #ifdef BSD
132  curr_tio[fd].sg_flags &= ~CBREAK; /* CBREAK mode OFF. */
133  (void) ioctl(fd, TIOCSETP, &curr_tio[fd]);
134 #endif
135 #ifdef SYSV
136  curr_tio[fd].c_lflag |= ICANON; /* Canonical input ON. */
137  curr_tio[fd].c_cc[VEOF] = 4; /* defaults! */
138  curr_tio[fd].c_cc[VEOL] = 0; /* best we can do.... */
139  (void) ioctl(fd, TCSETA, &curr_tio[fd]);
140 #endif
141 #ifdef HAVE_TERMIOS_H
142  curr_tio[fd].c_lflag |= ICANON; /* Canonical input ON. */
143  curr_tio[fd].c_cc[VEOF] = 4; /* defaults! */
144  curr_tio[fd].c_cc[VEOL] = 0; /* best we can do.... */
145  (void)tcsetattr(fd, TCSAFLUSH, &curr_tio[fd]);
146 #endif
147  return;
148 }
149 
150 /*
151  Set CBREAK mode, 'fd'.
152 */
153 void
154 set_Cbreak(int fd)
155 {
156 #ifdef BSD
157  curr_tio[fd].sg_flags |= CBREAK; /* CBREAK mode ON. */
158  (void) ioctl(fd, TIOCSETP, &curr_tio[fd]);
159 #endif
160 #ifdef SYSV
161  curr_tio[fd].c_lflag &= ~ICANON; /* Canonical input OFF. */
162  curr_tio[fd].c_cc[VMIN] = 1;
163  curr_tio[fd].c_cc[VTIME] = 0;
164  (void) ioctl(fd, TCSETA, &curr_tio[fd]);
165 #endif
166 #ifdef HAVE_TERMIOS_H
167  curr_tio[fd].c_lflag &= ~ICANON; /* Canonical input OFF. */
168  curr_tio[fd].c_cc[VMIN] = 1;
169  curr_tio[fd].c_cc[VTIME] = 0;
170  (void)tcsetattr(fd, TCSANOW, &curr_tio[fd]);
171 #endif
172  return;
173 }
174 
175 /*
176  Set cooked mode, 'fd'.
177 */
178 void
179 clr_Raw(int fd)
180 {
181 #ifdef BSD
182  curr_tio[fd].sg_flags &= ~RAW; /* Raw mode OFF. */
183  (void) ioctl(fd, TIOCSETP, &curr_tio[fd]);
184 #endif
185 #ifdef SYSV
186  curr_tio[fd].c_lflag |= ICANON; /* Canonical input ON. */
187  curr_tio[fd].c_lflag |= ISIG; /* Signals ON. */
188  curr_tio[fd].c_cc[VEOF] = 4; /* defaults! */
189  curr_tio[fd].c_cc[VEOL] = 0; /* best we can do.... */
190  (void) ioctl(fd, TCSETA, &curr_tio[fd]);
191 #endif
192 #ifdef HAVE_TERMIOS_H
193  curr_tio[fd].c_lflag |= ICANON; /* Canonical input ON. */
194  curr_tio[fd].c_lflag |= ISIG; /* Signals ON. */
195  curr_tio[fd].c_cc[VEOF] = 4; /* defaults! */
196  curr_tio[fd].c_cc[VEOL] = 0; /* best we can do.... */
197  (void)tcsetattr(fd, TCSAFLUSH, &curr_tio[fd]);
198 #endif
199  return;
200 }
201 
202 /*
203  Set raw mode, 'fd'.
204 */
205 void
206 set_Raw(int fd)
207 {
208 #ifdef BSD
209  curr_tio[fd].sg_flags |= RAW; /* Raw mode ON. */
210  (void) ioctl(fd, TIOCSETP, &curr_tio[fd]);
211 #endif
212 #ifdef SYSV
213  curr_tio[fd].c_lflag &= ~ICANON; /* Canonical input OFF. */
214  curr_tio[fd].c_lflag &= ~ISIG; /* Signals OFF. */
215  curr_tio[fd].c_cc[VMIN] = 1;
216  curr_tio[fd].c_cc[VTIME] = 0;
217  (void) ioctl(fd, TCSETA, &curr_tio[fd]);
218 #endif
219 #ifdef HAVE_TERMIOS_H
220  curr_tio[fd].c_lflag &= ~ICANON; /* Canonical input OFF. */
221  curr_tio[fd].c_lflag &= ~ISIG; /* Signals OFF. */
222  curr_tio[fd].c_cc[VMIN] = 1;
223  curr_tio[fd].c_cc[VTIME] = 0;
224  (void)tcsetattr(fd, TCSANOW, &curr_tio[fd]);
225 #endif
226  return;
227 }
228 
229 /*
230  Set echo mode, 'fd'.
231 */
232 void
233 set_Echo(int fd)
234 {
235 #ifdef BSD
236  curr_tio[fd].sg_flags |= ECHO; /* Echo mode ON. */
237  (void) ioctl(fd, TIOCSETP, &curr_tio[fd]);
238 #endif
239 #ifdef SYSV
240  curr_tio[fd].c_lflag |= ECHO; /* Echo mode ON. */
241  (void) ioctl(fd, TCSETA, &curr_tio[fd]);
242 #endif
243 #ifdef HAVE_TERMIOS_H
244  curr_tio[fd].c_lflag |= ECHO; /* Echo mode ON. */
245  (void)tcsetattr(fd, TCSANOW, &curr_tio[fd]);
246 #endif
247  return;
248 }
249 
250 /*
251  Clear echo mode, 'fd'.
252 */
253 void
254 clr_Echo(int fd)
255 {
256 #ifdef BSD
257  curr_tio[fd].sg_flags &= ~ECHO; /* Echo mode OFF. */
258  (void) ioctl(fd, TIOCSETP, &curr_tio[fd]);
259 #endif
260 #ifdef SYSV
261  curr_tio[fd].c_lflag &= ~ECHO; /* Echo mode OFF. */
262  (void) ioctl(fd, TCSETA, &curr_tio[fd]);
263 #endif
264 #ifdef HAVE_TERMIOS_H
265  curr_tio[fd].c_lflag &= ~ECHO; /* Echo mode OFF. */
266  (void)tcsetattr(fd, TCSANOW, &curr_tio[fd]);
267 #endif
268  return;
269 }
270 
271 /*
272  Turn on tab expansion, 'fd'.
273 */
274 void
275 set_Tabs(int fd)
276 {
277 #ifdef BSD
278  curr_tio[fd].sg_flags |= TAB_EXPANSION; /* Tab expansion ON. */
279  (void) ioctl(fd, TIOCSETP, &curr_tio[fd]);
280 #endif
281 
282 #ifdef SYSV
283  curr_tio[fd].c_oflag |= TAB_EXPANSION; /* Tab expansion ON. */
284  (void) ioctl(fd, TCSETA, &curr_tio[fd]);
285 #endif
286 
287 #ifdef HAVE_TERMIOS_H
288  curr_tio[fd].c_oflag |= TAB_EXPANSION; /* Tab expansion ON. */
289  (void)tcsetattr(fd, TCSANOW, &curr_tio[fd]);
290 #endif
291  return;
292 }
293 
294 /*
295  Turn off tab expansion, 'fd'.
296 */
297 void
298 clr_Tabs(int fd)
299 {
300 #ifdef BSD
301  curr_tio[fd].sg_flags &= ~TAB_EXPANSION; /* Tab expans. OFF. */
302  (void) ioctl(fd, TIOCSETP, &curr_tio[fd]);
303 #endif
304 #ifdef SYSV
305  curr_tio[fd].c_oflag &= ~TAB_EXPANSION; /* Tab expans. OFF. */
306  (void) ioctl(fd, TCSETA, &curr_tio[fd]);
307 #endif
308 #ifdef HAVE_TERMIOS_H
309  curr_tio[fd].c_oflag &= ~TAB_EXPANSION; /* Tab expans. OFF. */
310  (void)tcsetattr(fd, TCSANOW, &curr_tio[fd]);
311 #endif
312  return;
313 }
314 
315 /*
316  Turn on "Hang up on last close", 'fd'.
317 */
318 void
319 set_HUPCL(int fd)
320 {
321 #ifdef BSD
322  (void) ioctl(fd, TIOCHPCL, NULL);
323 #endif
324 
325 #ifdef SYSV
326  curr_tio[fd].c_cflag |= HUPCL;
327  (void) ioctl(fd, TCSETA, &curr_tio[fd]);
328 #endif
329 
330 #ifdef HAVE_TERMIOS_H
331  curr_tio[fd].c_cflag |= HUPCL;
332  (void)tcsetattr(fd, TCSANOW, &curr_tio[fd]);
333 #endif
334  return;
335 }
336 
337 /*
338  Turn off CR/LF mapping, fd.
339 */
340 void
341 clr_CRNL(int fd)
342 {
343 #ifdef BSD
344  curr_tio[fd].sg_flags &= ~CRMOD;
345  (void) ioctl(fd, TIOCSETP, &curr_tio[fd]);
346 #endif
347 #ifdef SYSV
348  curr_tio[fd].c_oflag &= ~(ONLCR|OCRNL);
349  curr_tio[fd].c_iflag &= ~(ICRNL|INLCR);
350  (void) ioctl(fd, TCSETA, &curr_tio[fd]);
351 #endif
352 #ifdef HAVE_TERMIOS_H
353  curr_tio[fd].c_oflag &= ~(ONLCR|OCRNL);
354  curr_tio[fd].c_iflag &= ~(ICRNL|INLCR);
355  (void)tcsetattr(fd, TCSAFLUSH, &curr_tio[fd]);
356 #endif
357 }
358 
359 /*
360  Get the terminals output speed, 'fd'.
361 */
362 unsigned short
363 get_O_Speed(int fd)
364 {
365 #ifdef BSD
366  return (unsigned short) save_tio[fd].sg_ospeed;
367 #endif
368 #ifdef SYSV
369  return save_tio[fd].c_cflag & CBAUD;
370 #endif
371 #ifdef HAVE_TERMIOS_H
372  return cfgetospeed(&save_tio[fd]);
373 #endif
374 }
375 
376 static void
377 copy_Tio(
378 #if defined(BSD)
379  struct sgttyb *to, struct sgttyb *from
380 #elif defined(SYSV)
381  struct termio *to, struct termio *from
382 #elif defined(HAVE_TERMIOS_H)
383  struct termios *to, struct termios*from
384 #endif
385 )
386 {
387  (void)memcpy((char *) to, (char *) from, sizeof(*from));
388  return;
389 }
390 
391 /*
392  Get and save terminal parameters, 'fd'.
393 */
394 void
395 save_Tty(int fd)
396 {
397 #ifdef BSD
398  (void) ioctl(fd, TIOCGETP, &save_tio[fd]);
399 #endif
400 #ifdef SYSV
401  (void) ioctl(fd, TCGETA, &save_tio[fd]);
402 #endif
403 #ifdef HAVE_TERMIOS_H
404  (void)tcgetattr(fd, &save_tio[fd]);
405 #endif
406  copy_Tio(&curr_tio[fd], &save_tio[fd]);
407  return;
408 }
409 
410 /*
411  Set the terminal back to the mode that the user had last time
412  save_Tty() was called for 'fd'.
413 */
414 void
415 reset_Tty(int fd)
416 {
417 #ifdef BSD
418  (void) ioctl(fd, TIOCSETP, &save_tio[fd]); /* Write setting. */
419 #endif
420 #ifdef SYSV
421  (void) ioctl(fd, TCSETA, &save_tio[fd]); /* Write setting. */
422 #endif
423 #ifdef HAVE_TERMIOS_H
424  (void)tcsetattr(fd, TCSAFLUSH, &save_tio[fd]);
425 #endif
426  return;
427 }
428 
429 /*
430  Save file status flags for 'fd'.
431 */
432 int
434 {
435  return fileStatus[fd] = fcntl(fd, F_GETFL, 0);
436 }
437 
438 /*
439  Restore file status flags for file desc. 'fd' to what they were the
440  last time saveFilStat(fd) was called.
441 */
442 int
444 {
445  return fcntl(fd, F_SETFL, fileStatus[fd]);
446 }
447 
448 /*
449  Set non-blocking read on 'fd'.
450 */
451 int
453 {
454 #if defined(O_NDELAY)
455  return fcntl(fd, F_SETFL, O_NDELAY);
456 #else
457 # if defined(HAVE_TERMIOS_H)
458  return fcntl(fd, F_SETFL, FNDELAY);
459 # endif
460 #endif
461 }
462 
463 void
465  char *msg,
466 #if defined(BSD)
467  struct sgttyb *tio_ptr
468 #elif defined(SYSV)
469  struct termio *tio_ptr
470 #elif defined(HAVE_TERMIOS_H)
471  struct termios *tio_ptr
472 #else
473  void *tio_ptr
474 #endif
475 )
476 {
477  register int i;
478  (void) fprintf(stderr, "%s :\n\r", msg);
479 #if defined(BSD)
480  (void) fprintf(stderr, "\tsg_ispeed=%d\n\r", (int) tio_ptr->sg_ispeed);
481  (void) fprintf(stderr, "\tsg_ospeed=%d\n\r", (int) tio_ptr->sg_ospeed);
482  (void) fprintf(stderr, "\tsg_erase='%c'\n\r", tio_ptr->sg_erase);
483  (void) fprintf(stderr, "\tsg_kill='%c'\n\r", tio_ptr->sg_kill);
484  (void) fprintf(stderr, "\tsg_flags=0x%x\n\r", tio_ptr->sg_flags);
485 #elif defined(SYSV)
486  (void) fprintf(stderr, "\tc_iflag=0x%x\n\r", tio_ptr->c_iflag);
487  (void) fprintf(stderr, "\tc_oflag=0x%x\n\r", tio_ptr->c_oflag);
488  (void) fprintf(stderr, "\tc_cflag=0x%x\n\r", tio_ptr->c_cflag);
489  (void) fprintf(stderr, "\tc_lflag=0x%x\n\r", tio_ptr->c_lflag);
490  (void) fprintf(stderr, "\tc_line=%c\n\r", tio_ptr->c_line);
491  for (i = 0; i < NCC; ++i) {
492  (void) fprintf(stderr,
493  "\tc_cc[%d]=0%o\n\r",
494  i,
495  tio_ptr->c_cc[i]
496  );
497  }
498 #elif defined(HAVE_TERMIOS_H)
499  (void) fprintf(stderr, "\tc_iflag=0x%x\n\r", (unsigned int)tio_ptr->c_iflag);
500  (void) fprintf(stderr, "\tc_oflag=0x%x\n\r", (unsigned int)tio_ptr->c_oflag);
501  (void) fprintf(stderr, "\tc_cflag=0x%x\n\r", (unsigned int)tio_ptr->c_cflag);
502  (void) fprintf(stderr, "\tc_lflag=0x%x\n\r", (unsigned int)tio_ptr->c_lflag);
503  for (i = 0; i < NCCS; ++i) {
504  (void) fprintf(stderr,
505  "\tc_cc[%d]=0%o\n\r",
506  i,
507  tio_ptr->c_cc[i]
508  );
509  }
510 #endif
511  return;
512 }
513 
514 /*
515  * Local Variables:
516  * mode: C
517  * tab-width: 8
518  * indent-tabs-mode: t
519  * c-file-style: "stroustrup"
520  * End:
521  * ex: shiftwidth=4 tabstop=8
522  */
Header file for the BRL-CAD common definitions.
void reset_Tty(int fd)
Definition: termio.c:415
void save_Tty(int fd)
Definition: termio.c:395
void clr_CRNL(int fd)
Definition: termio.c:341
void set_Cbreak(int fd)
Definition: termio.c:154
int reset_Fil_Stat(int fd)
Definition: termio.c:443
int save_Fil_Stat(int fd)
Definition: termio.c:433
void prnt_Tio(char *msg, void *tio_ptr)
Definition: termio.c:464
unsigned short get_O_Speed(int fd)
Definition: termio.c:363
void clr_Raw(int fd)
Definition: termio.c:179
void clr_Cbreak(int fd)
Definition: termio.c:129
int set_O_NDELAY(int fd)
Definition: termio.c:452
void set_Echo(int fd)
Definition: termio.c:233
void clr_Echo(int fd)
Definition: termio.c:254
void set_Raw(int fd)
Definition: termio.c:206
#define FOPEN_MAX
Definition: termio.c:72
void clr_Tabs(int fd)
Definition: termio.c:298
#define TAB_EXPANSION
Definition: termio.c:90
void set_HUPCL(int fd)
Definition: termio.c:319
void set_Tabs(int fd)
Definition: termio.c:275