]>
diplodocus.org Git - nmh/blob - test/runpty.c
e8db35f2ebdf2451fa0f3e0841da4cde59e2a69a
2 * runpty.c - Run a process under a pseudo-tty
4 * This code is Copyright (c) 2017, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
16 #include <sys/types.h>
18 #include <sys/select.h>
22 #define COMMAND_TIMEOUT 30
24 static void die(const char *fmt
, ...);
27 main(int argc
, char *argv
[])
29 int master_in
, master_out
, slave
, cc
, status
;
30 time_t starttime
, now
;
31 const char *slavename
;
33 unsigned char readbuf
[1024];
37 die("%s: too few arguments\n"
38 "usage: %s output-filename command [arguments...]\n",
42 if ((master_in
= posix_openpt(O_RDWR
| O_NOCTTY
)) < 0) {
43 die("Unable to open master pseudo-tty: %s\n", strerror(errno
));
46 if ((master_out
= posix_openpt(O_RDWR
| O_NOCTTY
)) < 0) {
47 die("Unable to open master pseudo-tty: %s\n", strerror(errno
));
50 if (grantpt(master_in
) < 0) {
51 die("Unable to grant permissions to master pty: %s\n",
55 if (grantpt(master_out
) < 0) {
56 die("Unable to grant permissions to master pty: %s\n",
60 if (unlockpt(master_in
) < 0) {
61 die("Unable to unlock master pty: %s\n", strerror(errno
));
64 if (unlockpt(master_out
) < 0) {
65 die("Unable to unlock master pty: %s\n", strerror(errno
));
71 * Start the child process if we are in the child; open the two
72 * slave pseudo-ttys and close the masters after we are done with them.
76 if (!(slavename
= ptsname(master_in
))) {
77 die("Unable to determine name of slave pty: %s\n",
81 if ((slave
= open(slavename
, O_RDWR
)) < 0) {
82 die("Unable to open slave pty \"%s\": %s\n", slavename
,
86 dup2(slave
, STDIN_FILENO
);
90 if (!(slavename
= ptsname(master_out
))) {
91 die("Unable to determine name of slave pty: %s\n",
95 if ((slave
= open(slavename
, O_RDWR
| O_NOCTTY
)) < 0) {
96 die("Unable to open slave pty \"%s\": %s\n", slavename
,
100 dup2(slave
, STDOUT_FILENO
);
101 dup2(slave
, STDERR_FILENO
);
105 execvp(argv
[2], argv
+ 2);
107 die("execvp(%s) failed: %s\n", argv
[2], strerror(errno
));
109 } else if (child
< 0) {
110 die("fork() failed: %s\n", strerror(errno
));
113 if (!(output
= fopen(argv
[1], "w"))) {
114 die("Unable to open \"%s\" for output: %s\n", argv
[1],
118 starttime
= time(NULL
);
126 FD_SET(master_out
, &readfds
);
129 * After we get our first bit of data, close the master pty
130 * connected to standard input on our slave; that will generate
134 tv
.tv_sec
= starttime
+ COMMAND_TIMEOUT
- time(NULL
);
139 cc
= select(master_out
+ 1, &readfds
, NULL
, NULL
, &tv
);
142 die("select() failed: %s\n", strerror(errno
));
145 if (cc
> 0 && FD_ISSET(master_out
, &readfds
)) {
146 cc
= read(master_out
, readbuf
, sizeof(readbuf
));
151 fwrite(readbuf
, 1, cc
, output
);
153 if (master_in
!= -1) {
160 if (now
>= starttime
+ COMMAND_TIMEOUT
) {
161 fprintf(stderr
, "Command execution timed out: %ld to %ld: %d\n",
172 waitpid(child
, &status
, 0);
178 die(const char *fmt
, ...)
183 vfprintf(stderr
, fmt
, args
);