Skip to content

Commit

Permalink
v0.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
VHSgunzo committed Feb 13, 2023
1 parent 8652fc7 commit f5cf8a5
Show file tree
Hide file tree
Showing 15 changed files with 979 additions and 0 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
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 }}
18 changes: 18 additions & 0 deletions Makefile
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)
13 changes: 13 additions & 0 deletions PKGBUILD
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}" ; }
26 changes: 26 additions & 0 deletions README.md
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)
```
47 changes: 47 additions & 0 deletions driver.c
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.
*/
}
125 changes: 125 additions & 0 deletions error.c
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 */
}
69 changes: 69 additions & 0 deletions loop.c
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 */
}
Loading

0 comments on commit f5cf8a5

Please sign in to comment.