reformat and refactor mkpty.*
This commit is contained in:
parent
2893caf8ab
commit
d04f14c038
2 changed files with 46 additions and 36 deletions
62
cli/mkpty.c
62
cli/mkpty.c
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
20
cli/mkpty.h
20
cli/mkpty.h
|
|
@ -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 */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue