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:
M | Makefile | | | 8 | ++++---- |
A | ptty.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);
+}