finish mkpty.c

This commit is contained in:
Emile Clark-Boman 2025-09-09 17:35:37 +10:00
parent 8adc42aabc
commit e599801f2e

View file

@ -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 <stdlib.h> pty/ptmx/pts declarations. */ /* _XOPEN_SOURCE unlocks <stdlib.h> pty/ptmx/pts declarations. */
#define _XOPEN_SOURCE 600 #define _XOPEN_SOURCE 600
/* _GNU_SOURCE unlocks the ptsname_r declaration*/ /* _GNU_SOURCE unlocks the ptsname_r declaration*/
#define _GNU_SOURCE #define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <asm/termbits.h> /* TIOC* constants */ #include <asm/termbits.h> /* TIOC* constants */
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include "mkpty.h"
#ifdef PATH_MAX #ifdef PATH_MAX
# define SNAME_MAX PATH_MAX # define TTYNAME_MAX PATH_MAX
#else #else
# define SNAME_MAX 512 # define TTYNAME_MAX 512
#endif /* PATH_MAX */ #endif /* PATH_MAX */
/* Allocate PTY master and slave file descriptors. /* Allocate PTY master and slave file descriptors.
@ -19,11 +32,11 @@
* *
* NOTE: This function is my alternative to GLibC's * NOTE: This function is my alternative to GLibC's
* openpty() function. It exists as a learning resource. * 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 mkpty(int *fdmx, int *fds) {
int _fdmx = -1, _fds = -1; int _fdmx = -1, _fds = -1;
char sname[SNAME_MAX]; char sname[TTYNAME_MAX];
// Configure PTY master (file descriptor) // Configure PTY master (file descriptor)
_fdmx = posix_openpt(O_RDWR | O_NOCTTY); _fdmx = posix_openpt(O_RDWR | O_NOCTTY);
@ -64,7 +77,41 @@ fail:
return EXIT_FAILURE; 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() { pid_t forkmkpty() {
int fdmx, fds; int fdmx, fds;
@ -80,6 +127,7 @@ pid_t forkmkpty() {
case 0: case 0:
/* Child Process */ /* Child Process */
close(fdmx); close(fdmx);
bindpty(fds);
break; break;
default: default:
@ -107,7 +155,7 @@ int setptsxy(const unsigned short rows, const unsigned short cols, const int fds
.ws_col = cols, .ws_col = cols,
}; };
if (ioctl(fds, TIOCSWINSZ, &win)) if (ioctl(fds, TIOCSWINSZ, &win) == -1)
return EXIT_FAILURE; return EXIT_FAILURE;
return EXIT_SUCCESS; return EXIT_SUCCESS;
#endif /* TIOCSWINSZ */ #endif /* TIOCSWINSZ */
@ -123,10 +171,11 @@ int getptsxy(unsigned short *rows, unsigned short *cols, const int fds) {
return -1; return -1;
#else #else
struct winsize win = (struct winsize){ 0 }; struct winsize win = (struct winsize){ 0 };
if (ioctl(fds, TIOCGWINSZ, &win)) if (ioctl(fds, TIOCGWINSZ, &win) == -1)
return EXIT_FAILURE; return EXIT_FAILURE;
*rows = win.ws_row; *rows = win.ws_row;
*cols = win.ws_col; *cols = win.ws_col;
return EXIT_SUCCESS; return EXIT_SUCCESS;
#endif /* TIOCGWINSZ */ #endif /* TIOCGWINSZ */
} }