}
/* Why is NeXT excluded here (and not in os_unixx.h)? */
-#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
+#if defined(ECHOE) && defined(ICANON) \
+ && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) \
+ && !defined(__NeXT__)
# define NEW_TTY_SYSTEM
#endif
#ifndef VMS
+/*
+ * Get the file descriptor to use for tty operations.
+ */
+ static int
+get_tty_fd(int fd)
+{
+ int tty_fd = fd;
+
+#if defined(HAVE_SVR4_PTYS) && defined(SUN_SYSTEM)
+ // On SunOS: Get the terminal parameters from "fd", or the slave device of
+ // "fd" when it is a master device.
+ if (mch_isatty(fd) > 1)
+ {
+ char *name;
+
+ name = ptsname(fd);
+ if (name == NULL)
+ return -1;
+
+ tty_fd = open(name, O_RDONLY | O_NOCTTY | O_EXTRA, 0);
+ if (tty_fd < 0)
+ return -1;
+ }
+#endif
+ return tty_fd;
+}
+
+ static int
+mch_tcgetattr(int fd, void *term)
+{
+ int tty_fd;
+ int retval = -1;
+
+ tty_fd = get_tty_fd(fd);
+ if (tty_fd >= 0)
+ {
+#ifdef NEW_TTY_SYSTEM
+# ifdef HAVE_TERMIOS_H
+ retval = tcgetattr(tty_fd, (struct termios *)term);
+# else
+ retval = ioctl(tty_fd, TCGETA, (struct termio *)term);
+# endif
+#else
+ // for "old" tty systems
+ retval = ioctl(tty_fd, TIOCGETP, (struct sgttyb *)term);
+#endif
+ if (tty_fd != fd)
+ close(tty_fd);
+ }
+ return retval;
+}
+
void
mch_settmode(int tmode)
{
if (first)
{
first = FALSE;
-# if defined(HAVE_TERMIOS_H)
- tcgetattr(read_cmd_fd, &told);
-# else
- ioctl(read_cmd_fd, TCGETA, &told);
-# endif
+ mch_tcgetattr(read_cmd_fd, &told);
}
tnew = told;
if (first)
{
first = FALSE;
- ioctl(read_cmd_fd, TIOCGETP, &ttybold);
+ mch_tcgetattr(read_cmd_fd, &ttybold);
}
ttybnew = ttybold;
struct termio keys;
# endif
- if (
-# if defined(HAVE_TERMIOS_H)
- tcgetattr(fd, &keys) != -1
-# else
- ioctl(fd, TCGETA, &keys) != -1
-# endif
- )
+ if (mch_tcgetattr(fd, &keys) != -1)
{
info->backspace = keys.c_cc[VERASE];
info->interrupt = keys.c_cc[VINTR];
/* for "old" tty systems */
struct sgttyb keys;
- if (ioctl(fd, TIOCGETP, &keys) != -1)
+ if (mch_tcgetattr(fd, &keys) != -1)
{
info->backspace = keys.sg_erase;
info->interrupt = keys.sg_kill;
int
mch_report_winsize(int fd, int rows, int cols)
{
-# ifdef TIOCSWINSZ
- struct winsize ws;
+ int tty_fd;
+ int retval = -1;
- ws.ws_col = cols;
- ws.ws_row = rows;
- ws.ws_xpixel = cols * 5;
- ws.ws_ypixel = rows * 10;
- if (ioctl(fd, TIOCSWINSZ, &ws) == 0)
+ tty_fd = get_tty_fd(fd);
+ if (tty_fd >= 0)
{
- ch_log(NULL, "ioctl(TIOCSWINSZ) success");
- return OK;
- }
- ch_log(NULL, "ioctl(TIOCSWINSZ) failed");
-# else
-# ifdef TIOCSSIZE
- struct ttysize ts;
+# if defined(TIOCSWINSZ)
+ struct winsize ws;
- ts.ts_cols = cols;
- ts.ts_lines = rows;
- if (ioctl(fd, TIOCSSIZE, &ws) == 0)
- {
- ch_log(NULL, "ioctl(TIOCSSIZE) success");
- return OK;
- }
- ch_log(NULL, "ioctl(TIOCSSIZE) failed");
-# endif
+ ws.ws_col = cols;
+ ws.ws_row = rows;
+ ws.ws_xpixel = cols * 5;
+ ws.ws_ypixel = rows * 10;
+ retval = ioctl(tty_fd, TIOCSWINSZ, &ws);
+ ch_log(NULL, "ioctl(TIOCSWINSZ) %s",
+ retval == 0 ? "success" : "failed");
+# elif defined(TIOCSSIZE)
+ struct ttysize ts;
+
+ ts.ts_cols = cols;
+ ts.ts_lines = rows;
+ retval = ioctl(tty_fd, TIOCSSIZE, &ts);
+ ch_log(NULL, "ioctl(TIOCSSIZE) %s",
+ retval == 0 ? "success" : "failed");
# endif
- return FAIL;
+ if (tty_fd != fd)
+ close(tty_fd);
+ }
+ return retval == 0 ? OK : FAIL;
}
#endif
{
char *tty_name;
- *pty_master_fd = OpenPTY(&tty_name); /* open pty */
+ *pty_master_fd = mch_openpty(&tty_name); // open pty
if (*pty_master_fd >= 0)
{
/* Leaving out O_NOCTTY may lead to waitpid() always returning
{
/* push stream discipline modules */
if (options & SHELL_COOKED)
- SetupSlavePTY(pty_slave_fd);
+ setup_slavepty(pty_slave_fd);
# ifdef TIOCSCTTY
/* Try to become controlling tty (probably doesn't work,
* unless run by root) */
if (pty_slave_fd >= 0)
{
/* push stream discipline modules */
- SetupSlavePTY(pty_slave_fd);
+ setup_slavepty(pty_slave_fd);
# ifdef TIOCSCTTY
/* Try to become controlling tty (probably doesn't work,
* unless run by root) */
#endif
#if HAVE_STROPTS_H
-#include <sys/types.h>
-#ifdef sinix
-#define buf_T __system_buf_t__
-#endif
-#include <stropts.h>
-#ifdef sinix
-#undef buf_T
-#endif
+# include <sys/types.h>
+# ifdef sinix
+# define buf_T __system_buf_t__
+# endif
+# include <stropts.h>
+# ifdef sinix
+# undef buf_T
+# endif
# ifdef SUN_SYSTEM
# include <sys/conf.h>
+# if defined(HAVE_SYS_PTMS_H) && defined(HAVE_SVR4_PTYS)
+# include <sys/ptms.h>
+# endif
# endif
#endif
* pty on others. Needs to be tuned...
*/
int
-SetupSlavePTY(int fd)
+setup_slavepty(int fd)
{
if (fd < 0)
return 0;
-#if defined(I_PUSH) && defined(HAVE_SVR4_PTYS) && !defined(sgi) && !defined(linux) && !defined(__osf__) && !defined(M_UNIX)
+#if defined(I_PUSH) && defined(HAVE_SVR4_PTYS) && !defined(sgi) \
+ && !defined(linux) && !defined(__osf__) && !defined(M_UNIX)
# if defined(HAVE_SYS_PTEM_H) || defined(hpux)
if (ioctl(fd, I_PUSH, "ptem") != 0)
return -1;
#if defined(OSX) && !defined(PTY_DONE)
#define PTY_DONE
int
-OpenPTY(char **ttyn)
+mch_openpty(char **ttyn)
{
int f;
static char TtyName[32];
&& !defined(PTY_DONE)
#define PTY_DONE
int
-OpenPTY(char **ttyn)
+mch_openpty(char **ttyn)
{
char *m, *s;
int f;
#if defined(__sgi) && !defined(PTY_DONE)
#define PTY_DONE
int
-OpenPTY(char **ttyn)
+mch_openpty(char **ttyn)
{
int f;
char *name;
#if defined(MIPS) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE)
#define PTY_DONE
int
-OpenPTY(char **ttyn)
+mch_openpty(char **ttyn)
{
int f;
stat_T buf;
* Same for Mac OS X Leopard (10.5). */
#define PTY_DONE
int
-OpenPTY(char **ttyn)
+mch_openpty(char **ttyn)
{
int f;
char *m;
#endif
int
-OpenPTY(char **ttyn)
+mch_openpty(char **ttyn)
{
int f;
/* used for opening a new pty-pair: */
# endif
int
-OpenPTY(char **ttyn)
+mch_openpty(char **ttyn)
{
char *p, *q, *l, *d;
int f;
}
#endif
-#endif /* FEAT_GUI || FEAT_TERMINAL */
+/*
+ * Call isatty(fd), except for SunOS where it's done differently.
+ */
+ int
+mch_isatty(int fd)
+{
+# if defined(I_STR) && defined(HAVE_SYS_PTMS_H) && defined(HAVE_SVR4_PTYS) \
+ && defined(SUN_SYSTEM)
+ // On SunOS, isatty() for /dev/ptmx returns false or sometimes can hang up
+ // in the inner ioctl(), and therefore first determine whether "fd" is a
+ // master device.
+ struct strioctl istr;
+
+ istr.ic_cmd = ISPTM;
+ istr.ic_timout = 0;
+ istr.ic_dp = NULL;
+ istr.ic_len = 0;
+
+ if (ioctl(fd, I_STR, &istr) == 0)
+ // Trick: return 2 in order to advice the caller that "fd" is a master
+ // device. cf. src/os_unix.c:get_tty_fd()
+ return 2;
+# endif
+ return isatty(fd);
+}
+
+#endif /* FEAT_GUI || FEAT_JOB_CHANNEL */