]> diplodocus.org Git - nmh/blobdiff - test/runpty.c
mhparse.c: Cast ptrdiff_t from subtraction to long.
[nmh] / test / runpty.c
index e5de14e0c05f31aaa774de75f20e569154347c86..1585df94b832404036f27946887ba26d0edf5a7f 100644 (file)
@@ -23,8 +23,8 @@
 int
 main(int argc, char *argv[])
 {
-    int master, slave, cc, sendeof = 0, status;
-    time_t starttime;
+    int master_in, master_out, slave, cc, status;
+    time_t starttime, now;
     const char *slavename;
     pid_t child;
     unsigned char readbuf[1024];
@@ -36,59 +36,91 @@ main(int argc, char *argv[])
        exit(1);
     }
 
-    if ((master = posix_openpt(O_RDWR | O_NOCTTY)) < 0) {
+    if ((master_in = posix_openpt(O_RDWR | O_NOCTTY)) < 0) {
        fprintf(stderr, "Unable to open master pseudo-tty: %s\n",
                strerror(errno));
        exit(1);
     }
 
-    if (grantpt(master) < 0) {
-       fprintf(stderr, "Unable to grant permissions to master pty: %s\n",
+    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 (unlockpt(master) < 0) {
-       fprintf(stderr, "Unable to unlock master pty: %s\n", strerror(errno));
+    if (grantpt(master_in) < 0) {
+       fprintf(stderr, "Unable to grant permissions to master pty: %s\n",
+               strerror(errno));
        exit(1);
     }
 
-    if (!(slavename = ptsname(master))) {
-       fprintf(stderr, "Unable to determine name of slave pty: %s\n",
+    if (grantpt(master_out) < 0) {
+       fprintf(stderr, "Unable to grant permissions to master 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));
+    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; close the master
-     * as we are supposed to only use the slave ptys here.
+     * 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) {
-       close(master);
+       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);
     }
 
-    close(slave);
-
     if (!(output = fopen(argv[1], "w"))) {
        fprintf(stderr, "Unable to open \"%s\" for output: %s\n", argv[1],
                strerror(errno));
@@ -103,65 +135,51 @@ main(int argc, char *argv[])
 
        FD_ZERO(&readfds);
 
-       FD_SET(master, &readfds);
+       FD_SET(master_out, &readfds);
 
        /*
-        * Okay, what's going on here?
-        *
-        * We want to send the EOF character (to simulate a "end of file",
-        * as if we redirected stdin to /dev/null).  We can't just close
-        * master, because we won't be able to get any data back.  So,
-        * after we get SOME data, set sendeof, and that will cause us to
-        * send the EOF character after the first select call.  If we are
-        * doing sendeof, set the timeout to 1 second; otherwise, set the
-        * timeout to COMMAND_TIMEOUT seconds remaining.
+        * After we get our first bit of data, close the master pty
+        * connected to standard input on our slave; that will generate
+        * an EOF.
         */
 
-       if (sendeof) {
-           tv.tv_sec = 1;
-       } else {
-           tv.tv_sec = starttime + COMMAND_TIMEOUT - time(NULL);
-           if (tv.tv_sec < 0)
-               tv.tv_sec = 0;
-       }
+       tv.tv_sec = starttime + COMMAND_TIMEOUT - time(NULL);
+       if (tv.tv_sec < 0)
+           tv.tv_sec = 0;
        tv.tv_usec = 0;
 
-       cc = select(master + 1, &readfds, NULL, NULL, &tv);
+       cc = select(master_out + 1, &readfds, NULL, NULL, &tv);
 
        if (cc < 0) {
            fprintf(stderr, "select() failed: %s\n", strerror(errno));
            exit(1);
        }
 
-       if (cc > 0 && FD_ISSET(master, &readfds)) {
-           cc = read(master, readbuf, sizeof(readbuf));
+       if (cc > 0 && FD_ISSET(master_out, &readfds)) {
+           cc = read(master_out, readbuf, sizeof(readbuf));
 
            if (cc <= 0)
                break;
 
            fwrite(readbuf, 1, cc, output);
-       }
-
-       if (cc == 0 && sendeof) {
-           struct termios rtty;
 
-           if (tcgetattr(master, &rtty) < 0) {
-               fprintf(stderr, "tcgetattr() failed: %s\n", strerror(errno));
-               exit(1);
+           if (master_in != -1) {
+               close(master_in);
+               master_in = -1;
            }
+       }
 
-           if (rtty.c_lflag & ICANON)
-               write(master, &rtty.c_cc[VEOF], 1);
-       } else if (!sendeof)
-           sendeof = 1;
-
-       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;
        }
     }
 
-    close(master);
+    if (master_in != -1)
+       close(master_in);
+    close(master_out);
     fclose(output);
 
     waitpid(child, &status, 0);