Skip to content

Instantly share code, notes, and snippets.

@Shougo
Created September 6, 2015 03:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Shougo/19a478f29c6e7d10124a to your computer and use it in GitHub Desktop.
Save Shougo/19a478f29c6e7d10124a to your computer and use it in GitHub Desktop.
pty test
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <stddef.h>
#include <dlfcn.h>
#include <ctype.h>
#include <dirent.h>
#if !defined __APPLE__
# include <sys/types.h>
# include <sys/ioctl.h>
#endif
#include <signal.h>
#include <fcntl.h>
/* for poll() */
#if defined __APPLE__
# include "fakepoll.h"
#else
# include <poll.h>
#endif
/* for forkpty() / login_tty() */
#if (defined __linux__ || defined __CYGWIN__) && !defined __ANDROID__
# include <pty.h>
# include <utmp.h>
#elif defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__
# include <util.h>
#else
# include <termios.h>
# include <libutil.h>
#endif
#ifdef __linux__
# define VP_SET_NONBLOCK_IF_NEEDED(_fd) (void)fd_set_nonblock(_fd)
#else
# define VP_SET_NONBLOCK_IF_NEEDED(_fd) do { /* nop */ } while (0)
#endif
/* for ioctl() */
#ifdef __APPLE__
# include <sys/ioctl.h>
#endif
/* for tc* and ioctl */
#include <sys/types.h>
#include <termios.h>
#ifndef TIOCGWINSZ
# include <sys/ioctl.h> /* 4.3+BSD requires this too */
#endif
/* for waitpid() */
#include <sys/types.h>
#include <sys/wait.h>
#if defined __NetBSD__
# define WIFCONTINUED(x) (_WSTATUS(x) == _WSTOPPED && WSTOPSIG(x) == 0x13)
#elif defined __ANDROID__
# define WIFCONTINUED(x) (WIFSTOPPED(x) && WSTOPSIG(x) == 0x13)
#endif
/* for socket */
#if defined __FreeBSD__
# define __BSD_VISIBLE 1
# include <arpa/inet.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
static int fd_set_nonblock(int fd)
{
#if defined(F_GETFL) && defined(F_SETFL) && defined(O_NONBLOCK)
int flag;
if ((flag = fcntl(fd, F_GETFL, 0)) == -1)
return -1;
if (!(flag & O_NONBLOCK))
return fcntl(fd, F_SETFL, flag | O_NONBLOCK);
#endif
return 0;
}
int vp_pty_open(char *args)
{
#define VP_GOTO_ERROR(_fmt) do { errfmt = (_fmt); goto error; } while(0)
int argc = 1;
int fd[3][2] = {{0}};
pid_t pid;
struct winsize ws = {0, 0, 0, 0};
int fdm;
int npipe = 3;
char *errfmt;
if (openpty(&fd[2][0], &fd[2][1], NULL, NULL, &ws) < 0) {
return -1;
}
VP_SET_NONBLOCK_IF_NEEDED(fd[2][0]);
pid = forkpty(&fdm, NULL, NULL, &ws);
if (pid < 0) {
VP_GOTO_ERROR("fork() error: %s");
} else if (pid == 0) {
/* child */
char **argv;
int i;
argv = malloc(sizeof(char *) * (argc+1));
if (argv == NULL) {
goto child_error;
}
argv[0] = args;
argv[argc] = NULL;
execv(argv[0], argv);
/* error */
goto child_error;
} else {
/* parent */
return fdm;
}
/* DO NOT REACH HERE */
return -1;
/* error */
error:
close(fd[0][0]);
close(fd[0][1]);
close(fd[1][0]);
close(fd[1][1]);
close(fd[2][0]);
close(fd[2][1]);
return -1;
child_error:
write(STDOUT_FILENO, strerror(errno), strlen(strerror(errno)));
_exit(EXIT_FAILURE);
#undef VP_GOTO_ERROR
}
int vp_pty_read(int fd)
{
#ifdef __linux__
# define VP_POLLIN (POLLIN | POLLHUP)
#else
# define VP_POLLIN (POLLIN)
#endif
int timeout = 0;
char buf[4096];
struct pollfd pfd = {0, POLLIN, 0};
pfd.fd = fd;
while (1) {
int n;
n = poll(&pfd, 1, -1);
if (n == -1) {
/* eof or error */
printf("eof or error\n");
break;
} else if (n == 0) {
/* timeout */
break;
}
if (pfd.revents & VP_POLLIN) {
n = read(fd, buf, sizeof(buf));
if (n == -1) {
if (pfd.revents & POLLHUP) {
/* eof */
printf("eof\n");
break;
}
return 1;
} else if (n == 0) {
/* eof */
printf("eof\n");
break;
}
printf("%s\n", buf);
/* try read more bytes without waiting */
timeout = 0;
continue;
} else if (pfd.revents & (POLLERR | POLLHUP)) {
/* eof or error */
break;
} else if (pfd.revents & POLLNVAL) {
printf("POLLNVAL\n");
return -1;
}
/* DO NOT REACH HERE */
return -1;
}
return 0;
#undef VP_POLLIN
}
int main(int argc, const char *argv[])
{
int fd;
fd = vp_pty_open("/usr/bin/ls");
if (fd > 0) {
printf("read = %d", vp_pty_read(fd));
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment