-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
979 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
name: CI | ||
|
||
on: | ||
push: | ||
branches: | ||
- action | ||
tags: | ||
- '*' | ||
|
||
jobs: | ||
build_and_release: | ||
name: ptyspawn | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
steps: | ||
|
||
- name: Checkout | ||
uses: actions/checkout@v2 | ||
|
||
- name: Build | ||
run: > | ||
sudo bash -c 'apt update && apt install make musl musl-dev musl-tools -y'; | ||
make; | ||
- name: Build archlinux package | ||
uses: countstarlight/arch-makepkg-action@master | ||
with: | ||
scripts: makepkg | ||
|
||
- name: Release | ||
uses: softprops/action-gh-release@v1 | ||
if: startsWith(github.ref, 'refs/tags/') | ||
with: | ||
files: | | ||
ptyspawn | ||
ptyspawn*.pkg.tar.zst | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
PROG = ptyspawn | ||
OBJS = main.o loop.o driver.o error.o ptyfork.o ttymodes.o ptyopen.o signalintr.o spipe.o writen.o | ||
CFLAGS = -g -Wall -static -s -Os -pipe | ||
CC = $(shell which musl-gcc 2>/dev/null||echo cc) | ||
|
||
all: ptyspawn | ||
|
||
ptyspawn: $(OBJS) | ||
$(CC) $(CFLAGS) -o $(PROG) $(OBJS) | ||
|
||
clean: | ||
rm -vf $(PROG) *.o | ||
|
||
install: all | ||
install -vDm755 $(PROG) "/usr/bin/$(PROG)" | ||
|
||
uninstall: | ||
rm -vf /usr/bin/$(PROG) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Maintainer: VHSgunzo <vhsgunzo.github.io> | ||
pkgname='ptyspawn' | ||
pkgver='0.0.1' | ||
pkgrel='1' | ||
pkgdesc='Tool for executing a command in a new PTY (pseudo-terminal)' | ||
arch=("x86_64") | ||
url='https://github.com/VHSgunzo/ptyspawn' | ||
provides=("${pkgname}") | ||
conflicts=("${pkgname}") | ||
source=("${pkgname}::https://github.com/VHSgunzo/${pkgname}/releases/download/v${pkgver}/${pkgname}") | ||
sha256sums=('SKIP') | ||
|
||
package() { install -Dm755 ${pkgname} "$pkgdir/usr/bin/${pkgname}" ; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,28 @@ | ||
# ptyspawn | ||
Tool for executing a command in a new PTY (pseudo-terminal) | ||
|
||
## To get started: | ||
|
||
* **Download the latest revision** | ||
``` | ||
git clone https://github.com/VHSgunzo/ptyspawn.git && cd ptyspawn | ||
``` | ||
|
||
* **Build** | ||
``` | ||
make | ||
``` | ||
|
||
* Or take an already precompiled binary file from the [releases](https://github.com/VHSgunzo/ptyspawn/releases) | ||
|
||
* **Usage** | ||
``` | ||
./ptyspawn [ -d driver -einvrh ] command {command args} | ||
-h Print this help | ||
-d Set driver for stdin/stdout | ||
-e Noecho for slave pty's line discipline | ||
-i Ignore EOF on standard input | ||
-n Not interactive | ||
-v Verbose | ||
-r Return exec code (enabled by default) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#include "ptyspawn.h" | ||
|
||
void | ||
do_driver(char * driver) { | ||
pid_t child; | ||
int pipe[2]; | ||
|
||
/* | ||
* Create a full-duplex pipe to communicate with the driver. | ||
*/ | ||
if (fd_pipe(pipe) < 0) | ||
err_sys("can't create stream pipe"); | ||
|
||
if ((child = fork()) < 0) { | ||
err_sys("fork error"); | ||
} else if (child == 0) { | ||
/* child */ | ||
close(pipe[1]); | ||
|
||
/* stdin for driver */ | ||
if (dup2(pipe[0], STDIN_FILENO) != STDIN_FILENO) | ||
err_sys("dup2 error to stdin"); | ||
|
||
/* stdout for driver */ | ||
if (dup2(pipe[0], STDOUT_FILENO) != STDOUT_FILENO) | ||
err_sys("dup2 error to stdout"); | ||
if (pipe[0] != STDIN_FILENO && pipe[0] != STDOUT_FILENO) | ||
close(pipe[0]); | ||
|
||
/* leave stderr for driver alone */ | ||
execlp(driver, driver, (char * ) 0); | ||
err_sys("execlp error for: %s", driver); | ||
} | ||
|
||
close(pipe[0]); /* parent */ | ||
if (dup2(pipe[1], STDIN_FILENO) != STDIN_FILENO) | ||
err_sys("dup2 error to stdin"); | ||
if (dup2(pipe[1], STDOUT_FILENO) != STDOUT_FILENO) | ||
err_sys("dup2 error to stdout"); | ||
if (pipe[1] != STDIN_FILENO && pipe[1] != STDOUT_FILENO) | ||
close(pipe[1]); | ||
|
||
/* | ||
* Parent returns, but with stdin and stdout connected | ||
* to the driver. | ||
*/ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
#include "ptyspawn.h" | ||
#include <errno.h> /* for definition of errno */ | ||
#include <stdarg.h> /* ISO C variable aruments */ | ||
|
||
static void err_doit(int, int, | ||
const char * , va_list); | ||
|
||
/* | ||
* Nonfatal error related to a system call. | ||
* Print a message and return. | ||
*/ | ||
void | ||
err_ret(const char * fmt, ...) { | ||
va_list ap; | ||
|
||
va_start(ap, fmt); | ||
err_doit(1, errno, fmt, ap); | ||
va_end(ap); | ||
} | ||
|
||
/* | ||
* Fatal error related to a system call. | ||
* Print a message and terminate. | ||
*/ | ||
void | ||
err_sys(const char * fmt, ...) { | ||
va_list ap; | ||
|
||
va_start(ap, fmt); | ||
err_doit(1, errno, fmt, ap); | ||
va_end(ap); | ||
exit(1); | ||
} | ||
|
||
/* | ||
* Nonfatal error unrelated to a system call. | ||
* Error code passed as explict parameter. | ||
* Print a message and return. | ||
*/ | ||
void | ||
err_cont(int error, | ||
const char * fmt, ...) { | ||
va_list ap; | ||
|
||
va_start(ap, fmt); | ||
err_doit(1, error, fmt, ap); | ||
va_end(ap); | ||
} | ||
|
||
/* | ||
* Fatal error unrelated to a system call. | ||
* Error code passed as explict parameter. | ||
* Print a message and terminate. | ||
*/ | ||
void | ||
err_exit(int error, | ||
const char * fmt, ...) { | ||
va_list ap; | ||
|
||
va_start(ap, fmt); | ||
err_doit(1, error, fmt, ap); | ||
va_end(ap); | ||
exit(1); | ||
} | ||
|
||
/* | ||
* Fatal error related to a system call. | ||
* Print a message, dump core, and terminate. | ||
*/ | ||
void | ||
err_dump(const char * fmt, ...) { | ||
va_list ap; | ||
|
||
va_start(ap, fmt); | ||
err_doit(1, errno, fmt, ap); | ||
va_end(ap); | ||
abort(); /* dump core and terminate */ | ||
exit(1); /* shouldn't get here */ | ||
} | ||
|
||
/* | ||
* Nonfatal error unrelated to a system call. | ||
* Print a message and return. | ||
*/ | ||
void | ||
err_msg(const char * fmt, ...) { | ||
va_list ap; | ||
|
||
va_start(ap, fmt); | ||
err_doit(0, 0, fmt, ap); | ||
va_end(ap); | ||
} | ||
|
||
/* | ||
* Fatal error unrelated to a system call. | ||
* Print a message and terminate. | ||
*/ | ||
void | ||
err_quit(const char * fmt, ...) { | ||
va_list ap; | ||
|
||
va_start(ap, fmt); | ||
err_doit(0, 0, fmt, ap); | ||
va_end(ap); | ||
exit(1); | ||
} | ||
|
||
/* | ||
* Print a message and return to caller. | ||
* Caller specifies "errnoflag". | ||
*/ | ||
static void | ||
err_doit(int errnoflag, int error, | ||
const char * fmt, va_list ap) { | ||
char buf[MAXLINE]; | ||
|
||
vsnprintf(buf, MAXLINE - 1, fmt, ap); | ||
if (errnoflag) | ||
snprintf(buf + strlen(buf), MAXLINE - strlen(buf) - 1, ": %s", | ||
strerror(error)); | ||
strcat(buf, "\n"); | ||
fflush(stdout); /* in case stdout and stderr are the same */ | ||
fputs(buf, stderr); | ||
fflush(NULL); /* flushes all stdio output streams */ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#include "ptyspawn.h" | ||
|
||
#define BUFFSIZE 512 | ||
|
||
static void sig_term(int); | ||
static volatile sig_atomic_t sigcaught; /* set by signal handler */ | ||
|
||
void | ||
loop(int ptym, int ignoreeof) { | ||
pid_t child; | ||
int nread; | ||
char buf[BUFFSIZE]; | ||
|
||
if ((child = fork()) < 0) { | ||
err_sys("fork error"); | ||
} else if (child == 0) { | ||
/* child copies stdin to ptym */ | ||
for (;;) { | ||
if ((nread = read(STDIN_FILENO, buf, BUFFSIZE)) < 0) | ||
err_sys("read error from stdin"); | ||
else if (nread == 0) | ||
break; /* EOF on stdin means we're done */ | ||
if (writen(ptym, buf, nread) != nread) | ||
err_sys("writen error to master pty"); | ||
} | ||
|
||
/* | ||
* We always terminate when we encounter an EOF on stdin, | ||
* but we notify the parent only if ignoreeof is 0. | ||
*/ | ||
if (ignoreeof == 0) | ||
kill(getppid(), SIGTERM); /* notify parent */ | ||
exit(0); /* and terminate; child can't return */ | ||
} | ||
|
||
/* | ||
* Parent copies ptym to stdout. | ||
*/ | ||
if (signal_intr(SIGTERM, sig_term) == SIG_ERR) | ||
err_sys("signal_intr error for SIGTERM"); | ||
|
||
for (;;) { | ||
if ((nread = read(ptym, buf, BUFFSIZE)) <= 0) | ||
break; /* signal caught, error, or EOF */ | ||
if (writen(STDOUT_FILENO, buf, nread) != nread) | ||
err_sys("writen error to stdout"); | ||
} | ||
|
||
/* | ||
* There are three ways to get here: sig_term() below caught the | ||
* SIGTERM from the child, we read an EOF on the pty master (which | ||
* means we have to signal the child to stop), or an error. | ||
*/ | ||
if (sigcaught == 0) /* tell child if it didn't send us the signal */ | ||
kill(child, SIGTERM); | ||
|
||
/* | ||
* Parent returns to caller. | ||
*/ | ||
} | ||
|
||
/* | ||
* The child sends us SIGTERM when it gets EOF on the pty slave or | ||
* when read() fails. We probably interrupted the read() of ptym. | ||
*/ | ||
static void | ||
sig_term(int signo) { | ||
sigcaught = 1; /* just set flag and return */ | ||
} |
Oops, something went wrong.