scroll

scrollbackbuffer program for st
git clone git://git.suckless.org//gitrepos
Log | Files | Refs

commit 6f9f727ca8ca5e76b05b181293c50930e359be43
parent 7e1f280882a96995f7f26e4693aa83632ca8ed97
Author: Jan Klemkow <j.klemkow@wemelug.de>
Date:   Mon, 10 Feb 2020 20:44:24 +0100

add ptty tool for testing

ptty: starts program within a pseudo tty for
non-tty test environments

Diffstat:
MMakefile | 8++++----
Aptty.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/Makefile b/Makefile @@ -10,9 +10,9 @@ install: scroll cp scroll ${BINDIR} cp scroll.1 ${MAN1DIR} -test: scroll +test: scroll ptty # check usage - if ./scroll; then exit 1; fi + if ./ptty ./scroll; then exit 1; fi # check exit passthrough of child - if ! ./scroll true; then exit 1; fi - if ./scroll false; then exit 1; fi + if ! ./ptty ./scroll true; then exit 1; fi + if ./ptty ./scroll false; then exit 1; fi diff --git a/ptty.c b/ptty.c @@ -0,0 +1,90 @@ +#include <sys/wait.h> + +#include <errno.h> +#include <inttypes.h> +#include <limits.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> +#include <util.h> + +void +die(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + + exit(EXIT_FAILURE); +} + +void +usage(void) +{ + fputs("ptty cmd\n", stderr); + exit(EXIT_FAILURE); +} + +int +main(int argc, char *argv[]) +{ + struct winsize ws = {.ws_row = 25, .ws_col = 80, 0, 0}; + int ch; + + while ((ch = getopt(argc, argv, "c:r:h")) != -1) { + switch (ch) { + case 'c': /* cols */ + ws.ws_col = strtoimax(optarg, NULL, 10); + if (errno != 0) + die("strtoimax: %s", optarg); + break; + case 'r': /* lines */ + ws.ws_row = strtoimax(optarg, NULL, 10); + if (errno != 0) + die("strtoimax: %s", optarg); + break; + case 'h': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + + int mfd; + pid_t pid = forkpty(&mfd, NULL, NULL, &ws); + switch (pid) { + case -1: + die("forkpty"); + case 0: /* child */ + execvp(argv[0], argv); + die("exec"); + } + + /* parent */ + FILE *fh = fdopen(mfd, "rw"); + if (fh == NULL) + die("fdopen"); + + char buf[BUFSIZ]; + while (fgets(buf, sizeof buf, fh) != NULL); + + int status; + waitpid(pid, &status, 0); + + return WEXITSTATUS(status); +}