1 /* vi:set ts=8 sts=4 sw=4: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 /* 10 * The stuff in this file mostly comes from the "screen" program. 11 * Included with permission from Juergen Weigert. 12 * Copied from "pty.c". "putenv.c" was used for putenv() in misc2.c. 13 * 14 * It has been modified to work better with Vim. 15 * The parts that are not used in Vim have been deleted. 16 * See the "screen" sources for the complete stuff. 17 * 18 * This specific version is distibuted under the Vim license (attribution by 19 * Juergen Weigert), the GPL applies to the original version, see the 20 * copyright notice below. 21 */ 22 23 /* Copyright (c) 1993 24 * Juergen Weigert ([email protected]) 25 * Michael Schroeder ([email protected]) 26 * Copyright (c) 1987 Oliver Laumann 27 * 28 * This program is free software; you can redistribute it and/or modify 29 * it under the terms of the GNU General Public License as published by 30 * the Free Software Foundation; either version 2, or (at your option) 31 * any later version. 32 * 33 * This program is distributed in the hope that it will be useful, 34 * but WITHOUT ANY WARRANTY; without even the implied warranty of 35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 36 * GNU General Public License for more details. 37 * 38 * You should have received a copy of the GNU General Public License 39 * along with this program (see the file COPYING); if not, write to the 40 * Free Software Foundation, Inc., 41 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 42 */ 43 44 #include "vim.h" 45 46 #include <signal.h> 47 48 #ifdef __CYGWIN32__ 49 # include <sys/termios.h> 50 #endif 51 52 #ifdef HAVE_SYS_IOCTL_H 53 # include <sys/ioctl.h> 54 #endif 55 56 #if HAVE_STROPTS_H 57 #include <sys/types.h> 58 #ifdef sinix 59 #define buf_T __system_buf_t__ 60 #endif 61 #include <stropts.h> 62 #ifdef sinix 63 #undef buf_T 64 #endif 65 # ifdef sun 66 # include <sys/conf.h> 67 # endif 68 #endif 69 70 #ifdef HAVE_UNISTD_H 71 # include <unistd.h> 72 #endif 73 74 #if HAVE_TERMIO_H 75 # include <termio.h> 76 #else 77 # ifdef HAVE_TERMIOS_H 78 # include <termios.h> 79 # endif 80 #endif 81 82 #if HAVE_SYS_STREAM_H 83 # include <sys/stream.h> 84 #endif 85 86 #if HAVE_SYS_PTEM_H 87 # include <sys/ptem.h> 88 #endif 89 90 #if !defined(sun) && !defined(VMS) && !defined(MACOS) 91 # include <sys/ioctl.h> 92 #endif 93 94 #if defined(sun) && defined(LOCKPTY) && !defined(TIOCEXCL) 95 # include <sys/ttold.h> 96 #endif 97 98 #ifdef ISC 99 # include <sys/tty.h> 100 # include <sys/sioctl.h> 101 # include <sys/pty.h> 102 #endif 103 104 #ifdef sgi 105 # include <sys/sysmacros.h> 106 #endif 107 108 #if defined(_INCLUDE_HPUX_SOURCE) && !defined(hpux) 109 # define hpux 110 #endif 111 112 /* 113 * if no PTYRANGE[01] is in the config file, we pick a default 114 */ 115 #ifndef PTYRANGE0 116 # define PTYRANGE0 "qprs" 117 #endif 118 #ifndef PTYRANGE1 119 # define PTYRANGE1 "0123456789abcdef" 120 #endif 121 122 /* SVR4 pseudo ttys don't seem to work with SCO-5 */ 123 #ifdef M_UNIX 124 # undef HAVE_SVR4_PTYS 125 #endif 126 127 static void initmaster __ARGS((int)); 128 129 /* 130 * Open all ptys with O_NOCTTY, just to be on the safe side. 131 */ 132 #ifndef O_NOCTTY 133 # define O_NOCTTY 0 134 #endif 135 136 static void 137 initmaster(f) 138 int f UNUSED; 139 { 140 #ifndef VMS 141 # ifdef POSIX 142 tcflush(f, TCIOFLUSH); 143 # else 144 # ifdef TIOCFLUSH 145 (void)ioctl(f, TIOCFLUSH, (char *) 0); 146 # endif 147 # endif 148 # ifdef LOCKPTY 149 (void)ioctl(f, TIOCEXCL, (char *) 0); 150 # endif 151 #endif 152 } 153 154 /* 155 * This causes a hang on some systems, but is required for a properly working 156 * pty on others. Needs to be tuned... 157 */ 158 int 159 SetupSlavePTY(fd) 160 int fd; 161 { 162 if (fd < 0) 163 return 0; 164 #if defined(I_PUSH) && defined(HAVE_SVR4_PTYS) && !defined(sgi) && !defined(linux) && !defined(__osf__) && !defined(M_UNIX) 165 # if defined(HAVE_SYS_PTEM_H) || defined(hpux) 166 if (ioctl(fd, I_PUSH, "ptem") != 0) 167 return -1; 168 # endif 169 if (ioctl(fd, I_PUSH, "ldterm") != 0) 170 return -1; 171 # ifdef sun 172 if (ioctl(fd, I_PUSH, "ttcompat") != 0) 173 return -1; 174 # endif 175 #endif 176 return 0; 177 } 178 179 180 #if defined(OSX) && !defined(PTY_DONE) 181 #define PTY_DONE 182 int 183 OpenPTY(ttyn) 184 char **ttyn; 185 { 186 int f; 187 static char TtyName[32]; 188 189 if ((f = open_controlling_pty(TtyName)) < 0) 190 return -1; 191 initmaster(f); 192 *ttyn = TtyName; 193 return f; 194 } 195 #endif 196 197 #if (defined(sequent) || defined(_SEQUENT_)) && defined(HAVE_GETPSEUDOTTY) \ 198 && !defined(PTY_DONE) 199 #define PTY_DONE 200 int 201 OpenPTY(ttyn) 202 char **ttyn; 203 { 204 char *m, *s; 205 int f; 206 /* used for opening a new pty-pair: */ 207 static char PtyName[32]; 208 static char TtyName[32]; 209 210 if ((f = getpseudotty(&s, &m)) < 0) 211 return -1; 212 #ifdef _SEQUENT_ 213 fvhangup(s); 214 #endif 215 vim_strncpy((char_u *)PtyName, (char_u *)m, sizeof(PtyName) - 1); 216 vim_strncpy((char_u *)TtyName, (char_u *)s, sizeof(TtyName) - 1); 217 initmaster(f); 218 *ttyn = TtyName; 219 return f; 220 } 221 #endif 222 223 #if defined(__sgi) && !defined(PTY_DONE) 224 #define PTY_DONE 225 int 226 OpenPTY(ttyn) 227 char **ttyn; 228 { 229 int f; 230 char *name; 231 RETSIGTYPE (*sigcld)__ARGS(SIGPROTOARG); 232 233 /* 234 * SIGCHLD set to SIG_DFL for _getpty() because it may fork() and 235 * exec() /usr/adm/mkpts 236 */ 237 sigcld = signal(SIGCHLD, SIG_DFL); 238 name = _getpty(&f, O_RDWR | O_NONBLOCK | O_EXTRA, 0600, 0); 239 signal(SIGCHLD, sigcld); 240 241 if (name == 0) 242 return -1; 243 initmaster(f); 244 *ttyn = name; 245 return f; 246 } 247 #endif 248 249 #if defined(MIPS) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE) 250 #define PTY_DONE 251 int 252 OpenPTY(ttyn) 253 char **ttyn; 254 { 255 int f; 256 struct stat buf; 257 /* used for opening a new pty-pair: */ 258 static char TtyName[32]; 259 260 if ((f = open("/dev/ptc", O_RDWR | O_NOCTTY | O_NONBLOCK | O_EXTRA, 0)) < 0) 261 return -1; 262 if (mch_fstat(f, &buf) < 0) 263 { 264 close(f); 265 return -1; 266 } 267 sprintf(TtyName, "/dev/ttyq%d", minor(buf.st_rdev)); 268 initmaster(f); 269 *ttyn = TtyName; 270 return f; 271 } 272 #endif 273 274 #if defined(HAVE_SVR4_PTYS) && !defined(PTY_DONE) && !defined(hpux) && !defined(MACOS_X) 275 276 /* NOTE: Even though HPUX can have /dev/ptmx, the code below doesn't work! 277 * Same for Mac OS X Leopard. */ 278 #define PTY_DONE 279 int 280 OpenPTY(ttyn) 281 char **ttyn; 282 { 283 int f; 284 char *m; 285 char *(ptsname __ARGS((int))); 286 int unlockpt __ARGS((int)); 287 int grantpt __ARGS((int)); 288 RETSIGTYPE (*sigcld)__ARGS(SIGPROTOARG); 289 /* used for opening a new pty-pair: */ 290 static char TtyName[32]; 291 292 if ((f = open("/dev/ptmx", O_RDWR | O_NOCTTY | O_EXTRA, 0)) == -1) 293 return -1; 294 295 /* 296 * SIGCHLD set to SIG_DFL for grantpt() because it fork()s and 297 * exec()s pt_chmod 298 */ 299 sigcld = signal(SIGCHLD, SIG_DFL); 300 if ((m = ptsname(f)) == NULL || grantpt(f) || unlockpt(f)) 301 { 302 signal(SIGCHLD, sigcld); 303 close(f); 304 return -1; 305 } 306 signal(SIGCHLD, sigcld); 307 vim_strncpy((char_u *)TtyName, (char_u *)m, sizeof(TtyName) - 1); 308 initmaster(f); 309 *ttyn = TtyName; 310 return f; 311 } 312 #endif 313 314 #if defined(_AIX) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE) 315 #define PTY_DONE 316 317 #ifdef _IBMR2 318 int aixhack = -1; 319 #endif 320 321 int 322 OpenPTY(ttyn) 323 char **ttyn; 324 { 325 int f; 326 /* used for opening a new pty-pair: */ 327 static char TtyName[32]; 328 329 /* a dumb looking loop replaced by mycrofts code: */ 330 if ((f = open("/dev/ptc", O_RDWR | O_NOCTTY | O_EXTRA)) < 0) 331 return -1; 332 vim_strncpy((char_u *)TtyName, (char_u *)ttyname(f), sizeof(TtyName) - 1); 333 if (geteuid() != ROOT_UID && mch_access(TtyName, R_OK | W_OK)) 334 { 335 close(f); 336 return -1; 337 } 338 initmaster(f); 339 # ifdef _IBMR2 340 if (aixhack >= 0) 341 close(aixhack); 342 if ((aixhack = open(TtyName, O_RDWR | O_NOCTTY | O_EXTRA, 0)) < 0) 343 { 344 close(f); 345 return -1; 346 } 347 # endif 348 *ttyn = TtyName; 349 return f; 350 } 351 #endif 352 353 #ifndef PTY_DONE 354 355 # ifdef hpux 356 static char PtyProto[] = "/dev/ptym/ptyXY"; 357 static char TtyProto[] = "/dev/pty/ttyXY"; 358 # else 359 # ifdef __BEOS__ 360 static char PtyProto[] = "/dev/pt/XY"; 361 static char TtyProto[] = "/dev/tt/XY"; 362 # else 363 static char PtyProto[] = "/dev/ptyXY"; 364 static char TtyProto[] = "/dev/ttyXY"; 365 # endif 366 # endif 367 368 int 369 OpenPTY(ttyn) 370 char **ttyn; 371 { 372 char *p, *q, *l, *d; 373 int f; 374 /* used for opening a new pty-pair: */ 375 static char PtyName[32]; 376 static char TtyName[32]; 377 378 strcpy(PtyName, PtyProto); 379 strcpy(TtyName, TtyProto); 380 for (p = PtyName; *p != 'X'; p++) 381 ; 382 for (q = TtyName; *q != 'X'; q++) 383 ; 384 for (l = PTYRANGE0; (*p = *l) != '\0'; l++) 385 { 386 for (d = PTYRANGE1; (p[1] = *d) != '\0'; d++) 387 { 388 #if !defined(MACOS) || defined(USE_CARBONIZED) 389 if ((f = open(PtyName, O_RDWR | O_NOCTTY | O_EXTRA, 0)) == -1) 390 #else 391 if ((f = open(PtyName, O_RDWR | O_NOCTTY | O_EXTRA)) == -1) 392 #endif 393 continue; 394 q[0] = *l; 395 q[1] = *d; 396 #ifndef MACOS 397 if (geteuid() != ROOT_UID && mch_access(TtyName, R_OK | W_OK)) 398 { 399 close(f); 400 continue; 401 } 402 #endif 403 #if defined(sun) && defined(TIOCGPGRP) && !defined(SUNOS3) 404 /* Hack to ensure that the slave side of the pty is 405 * unused. May not work in anything other than SunOS4.1 406 */ 407 { 408 int pgrp; 409 410 /* tcgetpgrp does not work (uses TIOCGETPGRP)! */ 411 if (ioctl(f, TIOCGPGRP, (char *)&pgrp) != -1 || errno != EIO) 412 { 413 close(f); 414 continue; 415 } 416 } 417 #endif 418 initmaster(f); 419 *ttyn = TtyName; 420 return f; 421 } 422 } 423 return -1; 424 } 425 #endif 426