Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/user/lib/hostcompat/hostcompat.c
734 views
1
/*
2
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3
* The President and Fellows of Harvard College.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. Neither the name of the University nor the names of its contributors
14
* may be used to endorse or promote products derived from this software
15
* without specific prior written permission.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
#include <unistd.h>
31
#include <termios.h>
32
#include <signal.h>
33
#include <stdlib.h>
34
#include <stdio.h>
35
36
#include "hostcompat.h"
37
38
/*
39
* The program name.
40
* This is used in err.c.
41
*/
42
const char *hostcompat_progname = NULL;
43
44
/*
45
* Unix tty state, for when we're running and to put it back the way it was,
46
* respectively.
47
*/
48
static struct termios hostcompat_runtios;
49
static struct termios hostcompat_savetios;
50
51
/*
52
* Put the tty state back the way it was.
53
*/
54
static
55
void
56
hostcompat_ttyreset(void)
57
{
58
tcsetattr(STDIN_FILENO, TCSADRAIN, &hostcompat_savetios);
59
}
60
61
/*
62
* Set the tty state back to the way we want it for running.
63
*/
64
static
65
void
66
hostcompat_ttyresume(void)
67
{
68
tcsetattr(STDIN_FILENO, TCSADRAIN, &hostcompat_runtios);
69
}
70
71
/*
72
* Set up the tty state stuff.
73
*/
74
static
75
int
76
hostcompat_ttysetup(void)
77
{
78
struct termios tios;
79
80
/* Get the current tty state. */
81
if (tcgetattr(STDIN_FILENO, &tios) < 0) {
82
/* stdin is not a tty */
83
return -1;
84
}
85
86
hostcompat_savetios = tios;
87
88
/* Turn off canonical ("cooked") input. */
89
tios.c_lflag &= ~ICANON;
90
91
/*
92
* With canonical input off, this says how many characters must be
93
* typed before read() will return.
94
*/
95
tios.c_cc[VMIN] = 1;
96
97
/* This can be used to set up read timeouts, but we don't need that. */
98
tios.c_cc[VTIME] = 0;
99
100
/* Turn off echoing of keypresses. */
101
tios.c_lflag &= ~(ECHO|ECHONL|ECHOCTL);
102
103
/* Do not support XON/XOFF flow control. */
104
tios.c_iflag &= ~(IXON|IXOFF);
105
106
/* On input, we want no CR/LF translation. */
107
tios.c_iflag &= ~(INLCR|IGNCR|ICRNL);
108
109
/* However, on output we want LF ('\n') mapped to CRLF. */
110
#ifdef OCRNL /* missing on OS X */
111
tios.c_oflag &= ~(OCRNL);
112
#endif
113
tios.c_oflag |= OPOST|ONLCR;
114
115
/* Enable keyboard signals (^C, ^Z, etc.) because they're useful. */
116
tios.c_lflag |= ISIG;
117
118
/* Set the new tty state. */
119
hostcompat_runtios = tios;
120
tcsetattr(STDIN_FILENO, TCSADRAIN, &tios);
121
122
return 0;
123
}
124
125
/*
126
* Signal handler for all the fatal signals (SIGSEGV, SIGTERM, etc.)
127
*/
128
static
129
void
130
hostcompat_die(int sig)
131
{
132
/* Set the tty back to the way we found it */
133
hostcompat_ttyreset();
134
135
/* Make sure the default action will occur when we get another signal*/
136
signal(sig, SIG_DFL);
137
138
/* Post the signal back to ourselves, to cause the right exit status.*/
139
kill(getpid(), sig);
140
141
/* Just in case. */
142
_exit(255);
143
}
144
145
/*
146
* Signal handler for the stop signals (SIGTSTP, SIGTTIN, etc.)
147
*/
148
static
149
void
150
hostcompat_stop(int sig)
151
{
152
/* Set the tty back to the way we found it */
153
hostcompat_ttyreset();
154
155
/* Make sure the default action will occur when we get another signal*/
156
signal(sig, SIG_DFL);
157
158
/* Post the signal back to ourselves. */
159
kill(getpid(), sig);
160
}
161
162
/*
163
* Signal handler for SIGCONT.
164
*/
165
static
166
void
167
hostcompat_cont(int sig)
168
{
169
(void)sig;
170
171
/* Set the tty to the way we want it for running. */
172
hostcompat_ttyresume();
173
174
/*
175
* Reload the signal handlers for stop/continue signals, in case
176
* they were set up with one-shot signals.
177
*/
178
signal(SIGTTIN, hostcompat_stop);
179
signal(SIGTTOU, hostcompat_stop);
180
signal(SIGTSTP, hostcompat_stop);
181
signal(SIGCONT, hostcompat_cont);
182
}
183
184
/*
185
* Initialize the hostcompat library.
186
*/
187
void
188
hostcompat_init(int argc, char *argv[])
189
{
190
/* Set the program name */
191
if (argc > 0 && argv[0] != NULL) {
192
hostcompat_progname = argv[0];
193
}
194
195
/* Set the tty modes */
196
if (hostcompat_ttysetup() < 0) {
197
return;
198
}
199
200
/* When exit() is called, clean up */
201
atexit(hostcompat_ttyreset);
202
203
/* stdout/stderr should be unbuffered */
204
setvbuf(stdout, NULL, _IONBF, 0);
205
setvbuf(stderr, NULL, _IONBF, 0);
206
207
/* Catch all the fatal signals, so we can clean up */
208
signal(SIGHUP, hostcompat_die);
209
signal(SIGINT, hostcompat_die);
210
signal(SIGQUIT, hostcompat_die);
211
signal(SIGILL, hostcompat_die);
212
signal(SIGTRAP, hostcompat_die);
213
signal(SIGABRT, hostcompat_die);
214
#ifdef SIGEMT
215
signal(SIGEMT, hostcompat_die);
216
#endif
217
signal(SIGFPE, hostcompat_die);
218
signal(SIGBUS, hostcompat_die);
219
signal(SIGSEGV, hostcompat_die);
220
signal(SIGSYS, hostcompat_die);
221
signal(SIGPIPE, hostcompat_die);
222
signal(SIGALRM, hostcompat_die);
223
signal(SIGTERM, hostcompat_die);
224
signal(SIGXCPU, hostcompat_die);
225
signal(SIGXFSZ, hostcompat_die);
226
signal(SIGVTALRM, hostcompat_die);
227
signal(SIGPROF, hostcompat_die);
228
signal(SIGUSR1, hostcompat_die);
229
signal(SIGUSR2, hostcompat_die);
230
231
/* Catch the stop signals, so we can adjust the tty */
232
signal(SIGTTIN, hostcompat_stop);
233
signal(SIGTTOU, hostcompat_stop);
234
signal(SIGTSTP, hostcompat_stop);
235
236
/* Catch the continue signal, so we can adjust the tty */
237
signal(SIGCONT, hostcompat_cont);
238
}
239
240