diff --git a/cli/mkpty.c b/cli/mkpty.c index 4344a85..1455f48 100644 --- a/cli/mkpty.c +++ b/cli/mkpty.c @@ -1,17 +1,30 @@ +/* WARNING: The mkpty(), forkmkpty(), & bindpty() functions are based on + * WARNING: the glibc openpty(), forkpty(), & login_tty() functions respectively. + * WARNING: + * WARNING: The GNU C Library's COPYING & COPYING.LIB licenses are available at + * WARNING: LICENSES/GLIBC-COPYING & LICENSES/GLIBC-COPYING.LIB in this repo. + * WARNING: + * WARNING: login_tty() maintains the original University of California license + * WARNING: available at LICENSES/UC-LICENSE in this repo. + */ + /* _XOPEN_SOURCE unlocks pty/ptmx/pts declarations. */ #define _XOPEN_SOURCE 600 /* _GNU_SOURCE unlocks the ptsname_r declaration*/ #define _GNU_SOURCE +#include #include #include #include #include /* TIOC* constants */ #include +#include "mkpty.h" + #ifdef PATH_MAX -# define SNAME_MAX PATH_MAX +# define TTYNAME_MAX PATH_MAX #else -# define SNAME_MAX 512 +# define TTYNAME_MAX 512 #endif /* PATH_MAX */ /* Allocate PTY master and slave file descriptors. @@ -19,11 +32,11 @@ * * NOTE: This function is my alternative to GLibC's * openpty() function. It exists as a learning resource. - * REF: glibc.git:/login/openpty.c + * REF: https://sourceware.org/git/glibc.git -> ./login/openpty.c */ int mkpty(int *fdmx, int *fds) { int _fdmx = -1, _fds = -1; - char sname[SNAME_MAX]; + char sname[TTYNAME_MAX]; // Configure PTY master (file descriptor) _fdmx = posix_openpt(O_RDWR | O_NOCTTY); @@ -64,7 +77,41 @@ fail: return EXIT_FAILURE; } -/* +/* Set fdty as the controlling terminal for the calling process. + * Returns 0 on success, and 1 on failure. + * NOTE: This function is my alternative to GLibC's + * login_tty() function. It exists as a learning resource. + * REF: https://sourceware.org/git/glibc.git -> ./login/login_tty.c + * WARNING: This function maintains the original University of California + * WARNING: LICENSE (1990-1993) as per glibc.git:/login/login_tty.c + * WARNING: available at LICENSES/UC-LICENSE in this repo. + */ +int bindpty(const int fdty) { + /* We assume any kernel compiling this defines TIOCSCTTY, + * otherwise this implementation won't exactly work... + */ + if (ioctl(fdty, TIOCSCTTY, 0) == -1) + return EXIT_FAILURE; + + /* Adjust stdin/stdout/stderr to refer to fd*/ + while (dup2(fdty, STDIN_FILENO) == -1 && errno == EBUSY) + ; + while (dup2(fdty, STDOUT_FILENO) == -1 && errno == EBUSY) + ; + while (dup2(fdty, STDERR_FILENO) == -1 && errno == EBUSY) + ; + if (fdty > 2) + close(fdty); + + return EXIT_SUCCESS; +} + +/* Allocate a PTY and fork, binding the parent to ptmx (master), + * and the child to pts (slave). + * Return value is indentical to fork(2). + * NOTE: This function is my alternative to GLibC's + * forkpty() function. It exists as a learning resource. + * REF: https://sourceware.org/git/glibc.git -> ./login/forkpty.c */ pid_t forkmkpty() { int fdmx, fds; @@ -80,6 +127,7 @@ pid_t forkmkpty() { case 0: /* Child Process */ close(fdmx); + bindpty(fds); break; default: @@ -107,7 +155,7 @@ int setptsxy(const unsigned short rows, const unsigned short cols, const int fds .ws_col = cols, }; - if (ioctl(fds, TIOCSWINSZ, &win)) + if (ioctl(fds, TIOCSWINSZ, &win) == -1) return EXIT_FAILURE; return EXIT_SUCCESS; #endif /* TIOCSWINSZ */ @@ -123,10 +171,11 @@ int getptsxy(unsigned short *rows, unsigned short *cols, const int fds) { return -1; #else struct winsize win = (struct winsize){ 0 }; - if (ioctl(fds, TIOCGWINSZ, &win)) + if (ioctl(fds, TIOCGWINSZ, &win) == -1) return EXIT_FAILURE; *rows = win.ws_row; *cols = win.ws_col; return EXIT_SUCCESS; #endif /* TIOCGWINSZ */ } +