7901d653 |
1 | --- ../mosh/src/frontend/pty.cc 2016-04-29 00:42:37.207832463 +1000 |
2 | +++ ./src/frontend/pty.cc 2016-04-29 00:40:31.306486322 +1000 |
3 | @@ -0,0 +1,147 @@ |
4 | +/* |
5 | + Mosh: the mobile shell |
6 | + Copyright 2012 Keith Winstein |
7 | + |
8 | + This program is free software: you can redistribute it and/or modify |
9 | + it under the terms of the GNU General Public License as published by |
10 | + the Free Software Foundation, either version 3 of the License, or |
11 | + (at your option) any later version. |
12 | + |
13 | + This program is distributed in the hope that it will be useful, |
14 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | + GNU General Public License for more details. |
17 | + |
18 | + You should have received a copy of the GNU General Public License |
19 | + along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | +*/ |
21 | + |
22 | +#include "config.h" |
23 | + |
24 | +#include <sys/types.h> |
25 | +#include <sys/stat.h> |
26 | +#include <sys/ioctl.h> |
27 | +#include <fcntl.h> |
28 | +#include <termios.h> |
29 | +#include <unistd.h> |
30 | +#include <stdlib.h> |
31 | +#include <errno.h> |
32 | +#include <string.h> |
33 | +#include <pty.h> |
34 | + |
35 | +#ifndef HAVE_OPENPTY |
36 | +/* from dropbear 0.53.1 sshpty.c, original license: "can be used freely for any purpose." */ |
37 | +int my_openpty (int *amaster, int *aslave, char *name, const struct termios *termp, |
38 | + const struct winsize *winp) |
39 | +{ |
40 | + int master, slave; |
41 | + char *name_slave; |
42 | + |
43 | + master = open("/dev/ptmx", O_RDWR); |
44 | + if (master == -1) { |
45 | +// TRACE(("Fail to open master")) |
46 | + return -1; |
47 | + } |
48 | + |
49 | + if (grantpt(master)) |
50 | + goto fail; |
51 | + |
52 | + if (unlockpt(master)) |
53 | + goto fail; |
54 | + |
55 | + name_slave = ptsname(master); |
56 | +// TRACE(("openpty: slave name %s", name_slave)) |
57 | + slave = open(name_slave, O_RDWR | O_NOCTTY); |
58 | + if (slave == -1) |
59 | + { |
60 | + goto fail; |
61 | + } |
62 | + |
63 | + if(termp) |
64 | + tcsetattr(slave, TCSAFLUSH, termp); |
65 | + if (winp) |
66 | + ioctl (slave, TIOCSWINSZ, winp); |
67 | + |
68 | + *amaster = master; |
69 | + *aslave = slave; |
70 | + if (name != NULL) |
71 | + strcpy(name, name_slave); |
72 | + |
73 | + return 0; |
74 | + |
75 | + fail: |
76 | + close (master); |
77 | + return -1; |
78 | +} |
79 | +#endif |
80 | + |
81 | +#ifndef HAVE_LOGIN_TTY |
82 | +/* from glibc 2.14, login/login_tty.c, under the BSD license */ |
83 | +int login_tty(int fd) |
84 | +{ |
85 | + (void) setsid(); |
86 | +#ifdef TIOCSCTTY |
87 | + if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) |
88 | + return (-1); |
89 | +#else |
90 | + { |
91 | + /* This might work. */ |
92 | + char *fdname = ttyname (fd); |
93 | + int newfd; |
94 | + if (fdname) |
95 | + { |
96 | + if (fd != 0) |
97 | + (void) close (0); |
98 | + if (fd != 1) |
99 | + (void) close (1); |
100 | + if (fd != 2) |
101 | + (void) close (2); |
102 | + newfd = open (fdname, O_RDWR); |
103 | + (void) close (newfd); |
104 | + } |
105 | + } |
106 | +#endif |
107 | + while (dup2(fd, 0) == -1 && errno == EBUSY) |
108 | + ; |
109 | + while (dup2(fd, 1) == -1 && errno == EBUSY) |
110 | + ; |
111 | + while (dup2(fd, 2) == -1 && errno == EBUSY) |
112 | + ; |
113 | + if (fd > 2) |
114 | + (void) close(fd); |
115 | + return (0); |
116 | +} |
117 | +#endif |
118 | + |
119 | +int my_forkpty (int *amaster, char *name, const struct termios *termp, const struct winsize *winp) { |
120 | +#ifdef HAVE_FORKPTY |
121 | +//return forkpty(amaster, name, termp, winp); |
122 | +#else |
123 | +/* from glibc 2.14, login/forkpty.c, under the LGPL 2.1 (or later) license */ |
124 | + int master, slave, pid; |
125 | + |
126 | + if (openpty (&master, &slave, name, termp, winp) == -1) |
127 | + return -1; |
128 | + |
129 | + switch (pid = fork ()) |
130 | + { |
131 | + case -1: |
132 | + close (master); |
133 | + close (slave); |
134 | + return -1; |
135 | + case 0: |
136 | + /* Child. */ |
137 | + close (master); |
138 | + if (login_tty (slave)) |
139 | + _exit (1); |
140 | + |
141 | + return 0; |
142 | + default: |
143 | + /* Parent. */ |
144 | + *amaster = master; |
145 | + close (slave); |
146 | + |
147 | + return pid; |
148 | + } |
149 | +#endif |
150 | +} |