]> diplodocus.org Git - nmh/blobdiff - test/runpty.c
Normalize some #include paths.
[nmh] / test / runpty.c
index 2645d6792f30c31cc00dd65e8a323f40faf73f5f..661d8753c343175cd5dabf7d2fc6620eacd5f4a7 100644 (file)
@@ -1,5 +1,4 @@
-/*
- * runpty.c - Run a process under a pseudo-tty
+/* runpty.c - Run a process under a pseudo-tty
  *
  * This code is Copyright (c) 2017, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
  *
  * This code is Copyright (c) 2017, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -9,6 +8,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdarg.h>
 #include <fcntl.h>
 #include <termios.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <termios.h>
 #include <unistd.h>
 
 #define COMMAND_TIMEOUT 30
 
 
 #define COMMAND_TIMEOUT 30
 
+static void run_command(char *argv[], int master_in, int master_out);
+static int open_master_pty(const char *desc);
+static void die(const char *fmt, ...);
+
 int
 main(int argc, char *argv[])
 {
 int
 main(int argc, char *argv[])
 {
-    int master_in, master_out, slave, cc, status;
-    time_t starttime;
-    const char *slavename;
+    int master_in, master_out, cc, status;
+    time_t starttime, now;
     pid_t child;
     unsigned char readbuf[1024];
     FILE *output;
 
     if (argc < 3) {
     pid_t child;
     unsigned char readbuf[1024];
     FILE *output;
 
     if (argc < 3) {
-       fprintf(stderr, "Usage: %s output-filename command [arguments ...]\n",
-               argv[0]);
-       exit(1);
-    }
-
-    if ((master_in = posix_openpt(O_RDWR | O_NOCTTY)) < 0) {
-       fprintf(stderr, "Unable to open master pseudo-tty: %s\n",
-               strerror(errno));
-       exit(1);
+        die("%s: too few arguments\n"
+            "usage: %s output-filename command [arguments...]\n",
+            *argv, *argv);
     }
 
     }
 
-    if ((master_out = posix_openpt(O_RDWR | O_NOCTTY)) < 0) {
-       fprintf(stderr, "Unable to open master pseudo-tty: %s\n",
-               strerror(errno));
-       exit(1);
-    }
-
-    if (grantpt(master_in) < 0) {
-       fprintf(stderr, "Unable to grant permissions to master pty: %s\n",
-               strerror(errno));
-       exit(1);
-    }
+    master_in = open_master_pty("input");
+    master_out = open_master_pty("output");
 
 
-    if (grantpt(master_out) < 0) {
-       fprintf(stderr, "Unable to grant permissions to master pty: %s\n",
-               strerror(errno));
-       exit(1);
+    if ((child = fork()) == -1) {
+       die("fork() failed: %s\n", strerror(errno));
     }
     }
-
-    if (unlockpt(master_in) < 0) {
-       fprintf(stderr, "Unable to unlock master pty: %s\n", strerror(errno));
-       exit(1);
-    }
-
-    if (unlockpt(master_out) < 0) {
-       fprintf(stderr, "Unable to unlock master pty: %s\n", strerror(errno));
-       exit(1);
-    }
-
-    child = fork();
-
-    /*
-     * Start the child process if we are in the child; open the two
-     * slave pseudo-ttys and close the masters after we are done with them.
-     */
-
     if (child == 0) {
     if (child == 0) {
-       if (!(slavename = ptsname(master_in))) {
-           fprintf(stderr, "Unable to determine name of slave pty: %s\n",
-                   strerror(errno));
-           exit(1);
-       }
-
-       if ((slave = open(slavename, O_RDWR)) < 0) {
-           fprintf(stderr, "Unable to open slave pty \"%s\": %s\n", slavename,
-                   strerror(errno));
-           exit(1);
-       }
-
-       dup2(slave, STDIN_FILENO);
-       close(slave);
-       close(master_in);
-
-       if (!(slavename = ptsname(master_out))) {
-           fprintf(stderr, "Unable to determine name of slave pty: %s\n",
-                   strerror(errno));
-           exit(1);
-       }
-
-       if ((slave = open(slavename, O_RDWR | O_NOCTTY)) < 0) {
-           fprintf(stderr, "Unable to open slave pty \"%s\": %s\n", slavename,
-                   strerror(errno));
-           exit(1);
-       }
-
-       dup2(slave, STDOUT_FILENO);
-       dup2(slave, STDERR_FILENO);
-       close(slave);
-       close(master_out);
-
-       execvp(argv[2], argv + 2);
-
-       fprintf(stderr, "execvp(%s) failed: %s\n", argv[2], strerror(errno));
-       exit(1);
-
-    } else if (child < 0) {
-       fprintf(stderr, "fork() failed: %s\n", strerror(errno));
-       exit(1);
+        run_command(argv + 2, master_in, master_out); /* Does not return. */
     }
 
     if (!(output = fopen(argv[1], "w"))) {
     }
 
     if (!(output = fopen(argv[1], "w"))) {
-       fprintf(stderr, "Unable to open \"%s\" for output: %s\n", argv[1],
-               strerror(errno));
-       exit(1);
+       die("Unable to open \"%s\" for output: %s\n", argv[1],
+            strerror(errno));
     }
 
     starttime = time(NULL);
     }
 
     starttime = time(NULL);
@@ -151,8 +78,7 @@ main(int argc, char *argv[])
        cc = select(master_out + 1, &readfds, NULL, NULL, &tv);
 
        if (cc < 0) {
        cc = select(master_out + 1, &readfds, NULL, NULL, &tv);
 
        if (cc < 0) {
-           fprintf(stderr, "select() failed: %s\n", strerror(errno));
-           exit(1);
+           die("select() failed: %s\n", strerror(errno));
        }
 
        if (cc > 0 && FD_ISSET(master_out, &readfds)) {
        }
 
        if (cc > 0 && FD_ISSET(master_out, &readfds)) {
@@ -169,8 +95,10 @@ main(int argc, char *argv[])
            }
        }
 
            }
        }
 
-       if (time(NULL) >= starttime + COMMAND_TIMEOUT) {
-           fprintf(stderr, "Command execution timed out\n");
+        now = time(NULL);
+       if (now >= starttime + COMMAND_TIMEOUT) {
+           fprintf(stderr, "Command execution timed out: %ld to %ld: %d\n",
+                starttime, now, cc);
            break;
        }
     }
            break;
        }
     }
@@ -184,3 +112,77 @@ main(int argc, char *argv[])
 
     exit(0);
 }
 
     exit(0);
 }
+
+static void
+run_command(char *argv[], int master_in, int master_out)
+{
+    const char *slavename;
+    int slave;
+
+    /* Open the two slave pseudo-ttys and close the masters after we are
+     * done with them. */
+
+    if (!(slavename = ptsname(master_in))) {
+        die("Unable to determine name of slave pty: %s\n",
+            strerror(errno));
+    }
+
+    if ((slave = open(slavename, O_RDWR)) == -1) {
+        die("Unable to open slave pty \"%s\": %s\n", slavename,
+            strerror(errno));
+    }
+
+    dup2(slave, STDIN_FILENO);
+    close(slave);
+    close(master_in);
+
+    if (!(slavename = ptsname(master_out))) {
+        die("Unable to determine name of slave pty: %s\n",
+            strerror(errno));
+    }
+
+    if ((slave = open(slavename, O_RDWR | O_NOCTTY)) < 0) {
+        die("Unable to open slave pty \"%s\": %s\n", slavename,
+            strerror(errno));
+    }
+
+    dup2(slave, STDOUT_FILENO);
+    dup2(slave, STDERR_FILENO);
+    close(slave);
+    close(master_out);
+
+    execvp(*argv, argv);
+
+    die("execvp(%s) failed: %s\n", *argv, strerror(errno));
+}
+
+static int
+open_master_pty(const char *desc)
+{
+    int fd;
+
+    if ((fd = posix_openpt(O_RDWR | O_NOCTTY)) == -1) {
+       die("Unable to open master %s pseudo-tty: %s\n", desc, strerror(errno));
+    }
+    if (grantpt(fd) == -1) {
+       die("Unable to grant permissions to master %s pty: %s\n", desc,
+            strerror(errno));
+    }
+    if (unlockpt(fd) == -1) {
+       die("Unable to unlock master %s pty: %s\n", desc, strerror(errno));
+    }
+
+    return fd;
+}
+
+static void
+die(const char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+
+    exit(1);
+}