reformat and refactor mkpty.*

This commit is contained in:
Emile Clark-Boman 2025-09-09 21:03:40 +10:00
parent 2893caf8ab
commit d04f14c038
2 changed files with 46 additions and 36 deletions

View file

@ -12,26 +12,18 @@
#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 <asm/termbits.h> /* TIOC* constants */ #include <asm/termbits.h> /* TIOC* constants */
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include "mkpty.h" #include "mkpty.h"
#ifdef PATH_MAX
# define TTYNAME_MAX PATH_MAX
#else
# define TTYNAME_MAX 512
#endif /* PATH_MAX */
/* Allocate PTY master and slave file descriptors. /* Allocate PTY master and slave file descriptors.
* errno will have been set if newpty() fails. * errno will have been set if newpty() fails.
* *
* 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. * NOTE: openpty() function. It exists as a learning resource.
* REF: https://sourceware.org/git/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) {
@ -80,59 +72,63 @@ fail:
/* Set fdty as the controlling terminal for the calling process. /* Set fdty as the controlling terminal for the calling process.
* Returns 0 on success, and 1 on failure. * Returns 0 on success, and 1 on failure.
* NOTE: This function is my alternative to GLibC's * NOTE: This function is my alternative to GLibC's
* login_tty() function. It exists as a learning resource. * NOTE: login_tty() function. It exists as a learning resource.
* REF: https://sourceware.org/git/glibc.git -> ./login/login_tty.c * REF: https://sourceware.org/git/glibc.git -> ./login/login_tty.c
*/
inline int setctty(const int fdty) {
/* We assume any kernel compiling this defines TIOCSCTTY,
* otherwise this implementation won't exactly work... */
return (ioctl(fdty, TIOCSCTTY, 0) != -1);
}
/* Bind fdty (terminal fd) to stdin/stdout/stderr for the calling process.
* This functions blocks until the EBUSY (see `man dup2`) race condition lifts.
* NOTE: This function is my alternative to GLibC's
* NOTE: login_tty() function. It exists as a learning resource.
* WARNING: This function maintains the original University of California * WARNING: This function maintains the original University of California
* WARNING: LICENSE (1990-1993) as per glibc.git:/login/login_tty.c * WARNING: LICENSE (1990-1993) as per glibc.git:/login/login_tty.c
* WARNING: available at LICENSES/UC-LICENSE in this repo. * WARNING: available at LICENSES/UC-LICENSE in this repo.
* REF: https://sourceware.org/git/glibc.git -> ./login/login_tty.c
*/ */
int bindpty(const int fdty) { inline void 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*/ /* Adjust stdin/stdout/stderr to refer to fd*/
while (dup2(fdty, STDIN_FILENO) == -1 && errno == EBUSY) BIND(fdty, STDIN_FILENO);
; BIND(fdty, STDOUT_FILENO);
while (dup2(fdty, STDOUT_FILENO) == -1 && errno == EBUSY) BIND(fdty, STDERR_FILENO);
;
while (dup2(fdty, STDERR_FILENO) == -1 && errno == EBUSY)
;
if (fdty > 2) if (fdty > 2)
close(fdty); close(fdty);
return EXIT_SUCCESS;
} }
/* Allocate a PTY and fork, binding the parent to ptmx (master), /* Allocate a PTY and fork, giving ptmx (master) to the parent
* and the child to pts (slave). * and binding the child's stdin/stdout/stderr to pts (slave).
* Return value is indentical to fork(2). * Return value is indentical to fork(2).
* NOTE: This function is my alternative to GLibC's * NOTE: This function is my alternative to GLibC's
* forkpty() function. It exists as a learning resource. * NOTE: forkpty() function. It exists as a learning resource.
* REF: https://sourceware.org/git/glibc.git -> ./login/forkpty.c * REF: https://sourceware.org/git/glibc.git -> ./login/forkpty.c
*/ */
pid_t forkmkpty(void) { pid_t forkmkpty(int *fdmx) {
int fdmx, fds; int _fdmx, fds;
pid_t pid; pid_t pid;
if (mkpty(&fdmx, &fds)) if (mkpty(&_fdmx, &fds))
return EXIT_FAILURE; return EXIT_FAILURE;
switch (pid = fork()) { switch (pid = fork()) {
case -1: case -1:
close(fdmx); close(_fdmx);
close(fds); close(fds);
return -1; return -1;
case 0: case 0:
/* Child Process */ /* Child Process */
close(fdmx); close(_fdmx);
setctty(fds);
bindpty(fds); bindpty(fds);
break; break;
default: default:
/* Parent Process */ /* Parent Process */
close(fds); close(fds);
// propagate ptmx (master) fd
*fdmx = _fdmx;
break; break;
} }

View file

@ -1,16 +1,30 @@
#ifndef DORNE_MKPTY_H #ifndef DORNE_MKPTY_H
#define DORNE_MKPTY_H #define DORNE_MKPTY_H
#include <errno.h>
#include <limits.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h>
#ifdef PATH_MAX
#define TTYNAME_MAX PATH_MAX
#else
#define TTYNAME_MAX 512
#endif /* PATH_MAX */
#define BIND(fdsrc, fddst) \
while (dup2(fdsrc, fddst) == -1 && errno == EBUSY) \
;
/* Custom implementation of glibc::openpty() */ /* Custom implementation of glibc::openpty() */
int mkpty(int *fdmx, int *fds); int mkpty(int *fdmx, int *fds);
/* Custom implementation of glibc::login_tty() */ /* Custom implementation of glibc::login_tty() */
int bindpty(const int fdty); void bindpty(const int fdty);
/* Custom implementation of glibc::forkpty() */ /* Custom implementation of glibc::forkpty() */
pid_t forkmkpty(void); pid_t forkmkpty(int *fdmx);
int setptsxy(const unsigned short rows, const unsigned short cols, const int fds); int setptsxy(const unsigned short rows, const unsigned short cols,
const int fds);
int getptsxy(unsigned short *rows, unsigned short *cols, const int fds); int getptsxy(unsigned short *rows, unsigned short *cols, const int fds);
#endif /* DORNE_MKPTY_H */ #endif /* DORNE_MKPTY_H */