1 /*
2 * Copyright (c) 1994 Sony Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL SONY CORPORATION BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Except as contained in this notice, the name of Sony Corporation
24 * shall not be used in advertising or otherwise to promote the sale, use
25 * or other dealings in this Software without prior written authorization
26 * from Sony Corporation.
27 *
28 */
29
30 /*
31 * $SonyRCSfile: ttytest.c,v $
32 * $SonyRevision: 1.1 $
33 * $SonyDate: 1994/06/03 08:03:31 $
34 */
35
36
37 #include <signal.h>
38 #include <termio.h>
39 #include <stdio.h>
40 #include <fcntl.h>
41 #include <stropts.h>
42 #include <sys/types.h>
43
44 #define PTY_MASTER "/dev/ptmx"
45 #define BUFFSIZE 512
46 #define err_sys(x) fprintf(stderr, (x))
47 #define err_quit(x) { \
48 fprintf(stderr, (x)); \
49 exit(0); \
50 }
51
52
53 static struct termio tty_termio;
54 static struct termio tty_mode;
55 static int sigcaught;
56
exec_shell(fd,argv,envp)57 exec_shell(fd, argv, envp)
58 int fd;
59 char **argv;
60 char **envp;
61 {
62 char *shell;
63 char *getenv(), *rindex();
64 struct termio b;
65
66 close(0); close(1); close(2);
67 if (dup(fd) != 0 || dup(fd) != 1 || dup(fd) != 2)
68 err_sys("dup error");
69 close(fd);
70
71 if ((shell = getenv("SHELL")) == NULL)
72 shell = "/bin/sh";
73 if ((argv[0] = rindex(shell, '/')) != NULL)
74 argv[0]++;
75 else
76 argv[0] = shell;
77
78 if (ioctl(0, TCGETA, (char *) &b) < 0)
79 return(-1);
80 fprintf(stderr, "erase=%x\n", b.c_cc[VERASE]);
81 execve(shell, argv, envp);
82 err_sys("execve error");
83 }
84
pass_all(fd,childpid)85 pass_all(fd, childpid)
86 int fd;
87 int childpid;
88 {
89 int newpid, nread;
90 int sig_term();
91 char buff[BUFFSIZE];
92
93 if ((newpid = fork()) < 0) {
94 err_sys("parent1: can't fork");
95 } else if (newpid == 0) {
96 for ( ; ; ) {
97 nread = read(0, buff, BUFFSIZE);
98 if (nread < 0)
99 err_sys("read error fram stdin");
100 else if (nread == 0)
101 break;
102
103 if (write(fd, buff, nread) != nread)
104 err_sys("writen error to stream pipe");
105 }
106 kill(getppid(), SIGTERM);
107 exit(0);
108 }
109
110
111 sigcaught = 0;
112
113
114 for ( ; ; ) {
115 if ((nread = read(fd, buff, BUFFSIZE)) <= 0)
116 break;
117
118 if (write(1, buff, nread) != nread)
119 err_sys("write error to stdout");
120 }
121
122 if (sigcaught == 0)
123 kill(newpid, SIGTERM);
124
125 return;
126 }
127
128 int
pty_master()129 pty_master()
130 {
131 int master_fd;
132
133 if ((master_fd = open(PTY_MASTER, O_RDWR)) < 0)
134 return(-1);
135
136 return(master_fd);
137 }
138
139 int
pty_slave(master_fd)140 pty_slave(master_fd)
141 int master_fd;
142 {
143 int slave_fd;
144 char *slavename;
145 int grantpt();
146 int unlockpt();
147 char *ptsname();
148
149 if (grantpt(master_fd) < 0) {
150 close(master_fd);
151 return(-1);
152 }
153
154 if (unlockpt(master_fd) < 0) {
155 close(master_fd);
156 return(-1);
157 }
158
159 slavename = ptsname(master_fd);
160 if (slavename == NULL) {
161 close(master_fd);
162 return(-1);
163 }
164
165 slave_fd = open(slavename, O_RDWR);
166 if (slave_fd < 0) {
167 close(master_fd);
168 return(-1);
169 }
170
171 if (ioctl(slave_fd, I_PUSH, "ptem") < 0 ) {
172 close(master_fd);
173 return(-1);
174 }
175
176 if (ioctl(slave_fd, I_PUSH, "ldterm") < 0) {
177 close(master_fd);
178 return(-1);
179 }
180 return(slave_fd);
181 }
182
183 int
tty_raw(fd)184 tty_raw(fd)
185 int fd;
186 {
187 struct termio temp_mode;
188
189 if (ioctl(fd, TCGETA, (char *) &temp_mode) < 0)
190 return(-1);
191
192 tty_mode = temp_mode;
193
194 temp_mode.c_iflag = 0;
195 temp_mode.c_oflag &= ~OPOST;
196 temp_mode.c_lflag &= ~(ISIG | ICANON | ECHO | XCASE);
197 temp_mode.c_cflag &= ~(CSIZE | PARENB);
198 temp_mode.c_cflag |= CS8;
199 temp_mode.c_cc[VMIN] = 1;
200 temp_mode.c_cc[VTIME] = 1;
201
202 if (ioctl(fd, TCSETA, (char *) &temp_mode) <0)
203 return(-1);
204
205 return(0);
206 }
207
208 int
tty_reset(fd)209 tty_reset(fd)
210 int fd;
211 {
212 if (ioctl(fd, TCSETA, (char *) &tty_mode) < 0)
213 return(-1);
214
215 return(0);
216 }
217
tty_getmode(oldfd)218 int tty_getmode(oldfd)
219 int oldfd;
220 {
221 if (ioctl(oldfd, TCGETA, (char *) &tty_termio) < 0)
222 return(-1);
223 fprintf(stderr, "tty_getmode erase=%x\n", tty_termio.c_cc[VERASE]);
224 return(0);
225 }
226
227 int
tty_setmode(newfd)228 tty_setmode(newfd)
229 int newfd;
230 {
231 if (ioctl(newfd, TCSETA, (char *) &tty_termio) < 0)
232 return(-1);
233
234 fprintf(stderr, "tty_setmode erase=%x\n", tty_termio.c_cc[VERASE]);
235 return(0);
236 }
237
main(argc,argv,envp)238 main(argc, argv, envp)
239 int argc;
240 char **argv;
241 char **envp;
242 {
243 int master_fd, slave_fd, childpid;
244
245 if (!isatty(0) || !isatty(1))
246 err_quit("stdin and stdout must be a terminal");
247
248 if ((master_fd = pty_master()) < 0)
249 err_sys("can't open master pty");
250 if(tty_getmode(0) < 0)
251 err_sys("can't get tty mode of standard input");
252
253 if ((childpid = fork()) < 0)
254 err_sys("can't fork");
255 else if (childpid == 0) {
256 setpgrp();
257 if ((slave_fd = pty_slave(master_fd)) < 0)
258 err_sys("can't open pty slave");
259 close(master_fd);
260 if (tty_setmode(slave_fd) < 0)
261 err_sys("can't set tty mode of pty slave");
262
263 exec_shell(slave_fd, argv, envp);
264 }
265
266
267 if (tty_raw(0) < 0)
268 err_sys("tty_raw error");
269 pass_all(master_fd, childpid);
270
271 if (tty_reset(0) < 0)
272 err_sys("tty_reset error");
273
274 exit(0);
275