update Debian standards version
[debian/sudo] / term.c
1 /*
2  * Copyright (c) 2009 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <config.h>
18
19 #include <sys/types.h>
20 #include <sys/param.h>
21 #include <stdio.h>
22 #ifdef STDC_HEADERS
23 # include <stdlib.h>
24 # include <stddef.h>
25 #else
26 # ifdef HAVE_STDLIB_H
27 #  include <stdlib.h>
28 # endif
29 #endif /* STDC_HEADERS */
30 #ifdef HAVE_STRING_H
31 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
32 #  include <memory.h>
33 # endif
34 # include <string.h>
35 #else
36 # ifdef HAVE_STRINGS_H
37 #  include <strings.h>
38 # endif
39 #endif /* HAVE_STRING_H */
40 #ifdef HAVE_TERMIOS_H
41 # include <termios.h>
42 #else
43 # ifdef HAVE_TERMIO_H
44 #  include <termio.h>
45 # else
46 #  include <sgtty.h>
47 #  include <sys/ioctl.h>
48 # endif /* HAVE_TERMIO_H */
49 #endif /* HAVE_TERMIOS_H */
50
51 #include "sudo.h"
52
53 #ifndef lint
54 __unused static const char rcsid[] = "$Sudo: term.c,v 1.4 2009/02/25 10:47:12 millert Exp $";
55 #endif /* lint */
56
57 #ifndef TCSASOFT
58 # define TCSASOFT       0
59 #endif
60 #ifndef ECHONL
61 # define ECHONL         0
62 #endif
63 #ifndef IEXTEN
64 # define IEXTEN         0
65 #endif
66
67 #ifndef _POSIX_VDISABLE
68 # ifdef VDISABLE
69 #  define _POSIX_VDISABLE       VDISABLE
70 # else
71 #  define _POSIX_VDISABLE       0
72 # endif
73 #endif
74
75 /*
76  * Compat macros for non-termios systems.
77  */
78 #ifndef HAVE_TERMIOS_H
79 # ifdef HAVE_TERMIO_H
80 #  undef termios
81 #  define termios               termio
82 #  define tcgetattr(f, t)       ioctl(f, TCGETA, t)
83 #  define tcsetattr(f, a, t)    ioctl(f, a, t)
84 #  undef TCSAFLUSH
85 #  define TCSAFLUSH             TCSETAF
86 # else /* SGTTY */
87 #  undef termios
88 #  define termios               sgttyb
89 #  define c_lflag               sg_flags
90 #  define tcgetattr(f, t)       ioctl(f, TIOCGETP, t)
91 #  define tcsetattr(f, a, t)    ioctl(f, a, t)
92 #  undef TCSAFLUSH
93 #  define TCSAFLUSH             TIOCSETP
94 # endif /* HAVE_TERMIO_H */
95 #endif /* HAVE_TERMIOS_H */
96
97 typedef struct termios sudo_term_t;
98
99 static sudo_term_t term, oterm;
100 static int changed;
101 int term_erase;
102 int term_kill;
103
104 int
105 term_restore(fd)
106     int fd;
107 {
108     if (changed) {
109         if (tcsetattr(fd, TCSAFLUSH|TCSASOFT, &oterm) != 0)
110             return(0);
111         changed = 0;
112     }
113     return(1);
114 }
115
116 int
117 term_noecho(fd)
118     int fd;
119 {
120     if (!changed && tcgetattr(fd, &oterm) != 0)
121         return(0);
122     (void) memcpy(&term, &oterm, sizeof(term));
123     CLR(term.c_lflag, ECHO|ECHONL);
124 #ifdef VSTATUS
125     term.c_cc[VSTATUS] = _POSIX_VDISABLE;
126 #endif
127     if (tcsetattr(fd, TCSAFLUSH|TCSASOFT, &term) == 0) {
128         changed = 1;
129         return(1);
130     }
131     return(0);
132 }
133
134 #if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)
135 int
136 term_raw(fd)
137     int fd;
138 {
139     if (!changed && tcgetattr(fd, &oterm) != 0)
140         return(0);
141     (void) memcpy(&term, &oterm, sizeof(term));
142     /* Set terminal to half-cooked mode */
143     term.c_cc[VMIN] = 1;
144     term.c_cc[VTIME] = 0;
145     CLR(term.c_lflag, ECHO | ECHONL | ICANON | IEXTEN);
146     SET(term.c_lflag, ISIG);
147 #ifdef VSTATUS
148     term.c_cc[VSTATUS] = _POSIX_VDISABLE;
149 #endif
150     if (tcsetattr(fd, TCSAFLUSH|TCSASOFT, &term) == 0) {
151         term_erase = term.c_cc[VERASE];
152         term_kill = term.c_cc[VKILL];
153         changed = 1;
154         return(1);
155     }
156     return(0);
157 }
158
159 #else /* SGTTY */
160
161 int
162 term_raw(fd)
163     int fd;
164 {
165     if (!changed && ioctl(fd, TIOCGETP, &oterm) != 0)
166         return(0);
167     (void) memcpy(&term, &oterm, sizeof(term));
168     /* Set terminal to half-cooked mode */
169     CLR(term.c_lflag, ECHO);
170     SET(term.sg_flags, CBREAK);
171     if (ioctl(fd, TIOCSETP, &term) == 0) {
172         term_erase = term.sg_erase;
173         term_kill = term.sg_kill;
174         changed = 1;
175         return(1);
176     }
177     return(0);
178 }
179
180 #endif