-/* $OpenBSD: manager.c,v 1.8 2024/04/26 04:44:43 jsg Exp $ */
+/* $OpenBSD: manager.c,v 1.9 2024/06/03 08:02:22 anton Exp $ */
/*
* Copyright (c) 2015 Sebastien Marie <semarie@openbsd.org>
*
#include <unistd.h>
#include "manager.h"
+#include "pty.h"
extern char *__progname;
static int
-grab_syscall(pid_t pid)
+grab_syscall(pid_t pid, char *output)
{
int ret = -1;
char *pattern;
regex_t regex;
regmatch_t matches[2];
- FILE *fd;
- char line[1024];
int error;
const char *errstr;
/* build searched string */
error = asprintf(&pattern,
- "^%s\\[%d\\]: pledge \"[a-z]+\", syscall ([0-9]+)\n?$",
+ "%s\\[%d\\]: pledge \"[a-z]+\", syscall ([0-9]+)",
__progname, pid);
if (error <= 0) {
warn("asprintf pattern");
goto out;
}
- /* call dmesg */
- if ((fd = popen("/sbin/dmesg", "r")) == NULL) {
- warn("popen /sbin/dmesg");
+ /* search the string */
+ error = regexec(®ex, output, 2, matches, 0);
+ if (error == REG_NOMATCH) {
+ ret = 0;
goto out;
}
-
- /* search the string */
- while (1) {
- /* read a line */
- fgets(line, sizeof(line), fd);
-
- /* error checking */
- if (ferror(fd)) {
- ret = -1;
- goto out;
- }
-
- /* quit */
- if (feof(fd))
- break;
-
- /* check if found */
- error = regexec(®ex, line, 2, matches, 0);
- if (error == REG_NOMATCH)
- continue;
- if (error) {
- warnx("regexec pattern=%s line=%s error=%d",
- pattern, line, error);
- ret = -1;
- goto out;
- }
-
- /* convert it */
- line[matches[1].rm_eo] = '\0';
- ret = strtonum(&line[matches[1].rm_so], 0, 255, &errstr);
- if (errstr) {
- warnx("strtonum: number=%s error=%s",
- &line[matches[1].rm_so], errstr);
- ret = -1;
- goto out;
- }
+ if (error) {
+ warnx("regexec pattern=%s output=%s error=%d",
+ pattern, output, error);
+ ret = -1;
+ goto out;
}
- /* cleanup */
- if (pclose(fd) == -1)
+ /* convert it */
+ output[matches[1].rm_eo] = '\0';
+ ret = strtonum(&output[matches[1].rm_so], 0, 255, &errstr);
+ if (errstr) {
+ warnx("strtonum: number=%s error=%s",
+ &output[matches[1].rm_so], errstr);
+ ret = -1;
goto out;
-
- /* not found */
- if (ret == -1)
- ret = 0;
+ }
out:
free(pattern);
_start_test(int *ret, const char *test_name, const char *request,
void (*test_func)(void))
{
+ struct pty pty = {0};
int fildes[2];
pid_t pid;
int status;
return;
}
+ if (pty_open(&pty)) {
+ *ret = EXIT_FAILURE;
+ return;
+ }
+
/* fork and launch the test */
switch (pid = fork()) {
case -1:
if (errno != EINTR)
err(errno, "dup2");
+ if (pty_detach(&pty)) {
+ *ret = EXIT_FAILURE;
+ return;
+ }
+
/* create a new session (for kill) */
setsid();
+ if (pty_attach(&pty)) {
+ *ret = EXIT_FAILURE;
+ return;
+ }
+
/* set pledge policy */
if (request && pledge(request, NULL) != 0)
err(errno, "pledge");
/* NOTREACHED */
}
+ if (pty_drain(&pty)) {
+ *ret = EXIT_FAILURE;
+ return;
+ }
+
/* copy pipe to output */
(void)close(fildes[1]);
if (drainfd(fildes[0], STDOUT_FILENO) != 0) {
/* grab pledged syscall from dmesg */
if (signal == SIGKILL || signal == SIGABRT) {
- int syscall = grab_syscall(pid);
+ int syscall = grab_syscall(pid, pty_buffer(&pty));
switch (syscall) {
case -1: /* error */
warn("test(%s): grab_syscall pid=%d", test_name,
if (WIFSTOPPED(status))
printf(" stop=%d", WSTOPSIG(status));
+ pty_close(&pty);
+
printf("\n");
}
--- /dev/null
+/* $OpenBSD: pty.c,v 1.1 2024/06/03 08:02:22 anton Exp $ */
+
+#include <sys/ioctl.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "pty.h"
+
+int
+pty_open(struct pty *pty)
+{
+ int master, slave;
+
+ master = posix_openpt(O_RDWR);
+ if (master == -1) {
+ warn("posix_openpt");
+ return 1;
+ }
+ if (grantpt(master) == -1) {
+ warn("grantpt");
+ return 1;
+ }
+ if (unlockpt(master) == -1) {
+ warn("unlockpt");
+ return 1;
+ }
+
+ slave = open(ptsname(master), O_RDWR);
+ if (slave == -1) {
+ warn("%s", ptsname(master));
+ return 1;
+ }
+
+ pty->master = master;
+ pty->slave = slave;
+ return 0;
+}
+
+void
+pty_close(struct pty *pty)
+{
+ close(pty->slave);
+ close(pty->master);
+}
+
+/*
+ * Disconnect the controlling tty, if present.
+ */
+int
+pty_detach(struct pty *pty)
+{
+ int fd;
+
+ fd = open("/dev/tty", O_RDWR | O_NOCTTY);
+ if (fd >= 0) {
+ (void)ioctl(fd, TIOCNOTTY, NULL);
+ close(fd);
+ }
+ return 0;
+}
+
+/*
+ * Connect the slave as the controlling tty.
+ */
+int
+pty_attach(struct pty *pty)
+{
+ if (ioctl(pty->slave, TIOCSCTTY, NULL) == -1) {
+ warn("TIOCSCTTY");
+ return 1;
+ }
+ return 0;
+}
+
+int
+pty_drain(struct pty *pty)
+{
+ for (;;) {
+ char *buf = &pty->buf.storage[pty->buf.len];
+ size_t bufsize = sizeof(pty->buf.storage) - pty->buf.len;
+ ssize_t n;
+
+ n = read(pty->master, buf, bufsize);
+ if (n == -1) {
+ warn("read");
+ return 1;
+ }
+ if (n == 0)
+ break;
+
+ /* Ensure space for NUL-terminator. */
+ if ((size_t)n >= bufsize) {
+ warnx("pty buffer too small");
+ return 1;
+ }
+ pty->buf.len += n;
+ }
+
+ return 0;
+}