#include "src/include/pmix_config.h"
#ifdef HAVE_SYS_CDEFS_H
# include <sys/cdefs.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <sys/stat.h>
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#else
# ifdef HAVE_TERMIO_H
# include <termio.h>
# endif
#endif
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdio.h>
#include <string.h>
#ifdef HAVE_GRP_H
# include <grp.h>
#endif
#ifdef HAVE_PTY_H
# include <pty.h>
#endif
#ifdef HAVE_UTMP_H
# include <utmp.h>
#endif
#ifdef HAVE_PTSNAME
# include <stdlib.h>
# ifdef HAVE_STROPTS_H
# include <stropts.h>
# endif
#endif
#ifdef HAVE_UTIL_H
# include <util.h>
#endif
#include "src/util/pmix_pty.h"
#if PMIX_ENABLE_PTY_SUPPORT == 0
int pmix_openpty(int *amaster, int *aslave, char *name, void *termp, void *winpp)
{
return -1;
}
#elif defined(HAVE_OPENPTY)
int pmix_openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp)
{
return openpty(amaster, aslave, name, termp, winp);
}
#else
static int ptym_open(char *pts_name);
static int ptys_open(int fdm, char *pts_name);
int pmix_openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp)
{
char line[20];
*amaster = ptym_open(line);
if (*amaster < 0) {
return -1;
}
*aslave = ptys_open(*amaster, line);
if (*aslave < 0) {
close(*amaster);
return -1;
}
if (name) {
pmix_string_copy(name, line, sizeof(line));
}
# ifndef TCSAFLUSH
# define TCSAFLUSH TCSETAF
# endif
if (termp) {
(void) tcsetattr(*aslave, TCSAFLUSH, termp);
}
# ifdef TIOCSWINSZ
if (winp) {
(void) ioctl(*aslave, TIOCSWINSZ, (char *) winp);
}
# endif
return 0;
}
static int ptym_open(char *pts_name)
{
int fdm;
# ifdef HAVE_PTSNAME
char *ptr;
# ifdef _AIX
strcpy(pts_name, "/dev/ptc");
# else
strcpy(pts_name, "/dev/ptmx");
# endif
fdm = open(pts_name, O_RDWR);
if (fdm < 0) {
return -1;
}
if (grantpt(fdm) < 0) {
close(fdm);
return -2;
}
if (unlockpt(fdm) < 0) {
close(fdm);
return -3;
}
ptr = ptsname(fdm);
if (ptr == NULL) {
close(fdm);
return -4;
}
strcpy(pts_name, ptr);
return fdm;
# else
char *ptr1, *ptr2;
strcpy(pts_name, "/dev/ptyXY");
for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
pts_name[8] = *ptr1;
for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
pts_name[9] = *ptr2;
fdm = open(pts_name, O_RDWR);
if (fdm < 0) {
if (errno == ENOENT) {
return -1;
} else {
continue;
}
}
pts_name[5] = 't';
return fdm;
}
}
return -1;
# endif
}
static int ptys_open(int fdm, char *pts_name)
{
int fds;
# ifdef HAVE_PTSNAME
fds = open(pts_name, O_RDWR);
if (fds < 0) {
close(fdm);
return -5;
}
# if defined(__SVR4) && defined(__sun)
if (ioctl(fds, I_PUSH, "ptem") < 0) {
close(fdm);
close(fds);
return -6;
}
if (ioctl(fds, I_PUSH, "ldterm") < 0) {
close(fdm);
close(fds);
return -7;
}
# endif
return fds;
# else
int gid;
struct group *grptr;
grptr = getgrnam("tty");
if (grptr != NULL) {
gid = grptr->gr_gid;
} else {
gid = -1;
}
lchown(pts_name, getuid(), gid); chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP);
fds = open(pts_name, O_RDWR);
if (fds < 0) {
close(fdm);
return -1;
}
return fds;
# endif
}
#endif