]>
diplodocus.org Git - nmh/blob - test/runpty.c
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.
15 #include <sys/types.h>
17 #include <sys/select.h>
21 #define COMMAND_TIMEOUT 30
24 main(int argc
, char *argv
[])
26 int master_in
, master_out
, slave
, cc
, status
;
27 time_t starttime
, now
;
28 const char *slavename
;
30 unsigned char readbuf
[1024];
34 fprintf(stderr
, "Usage: %s output-filename command [arguments ...]\n",
39 if ((master_in
= posix_openpt(O_RDWR
| O_NOCTTY
)) < 0) {
40 fprintf(stderr
, "Unable to open master pseudo-tty: %s\n",
45 if ((master_out
= posix_openpt(O_RDWR
| O_NOCTTY
)) < 0) {
46 fprintf(stderr
, "Unable to open master pseudo-tty: %s\n",
51 if (grantpt(master_in
) < 0) {
52 fprintf(stderr
, "Unable to grant permissions to master pty: %s\n",
57 if (grantpt(master_out
) < 0) {
58 fprintf(stderr
, "Unable to grant permissions to master pty: %s\n",
63 if (unlockpt(master_in
) < 0) {
64 fprintf(stderr
, "Unable to unlock master pty: %s\n", strerror(errno
));
68 if (unlockpt(master_out
) < 0) {
69 fprintf(stderr
, "Unable to unlock master pty: %s\n", strerror(errno
));
76 * Start the child process if we are in the child; open the two
77 * slave pseudo-ttys and close the masters after we are done with them.
81 if (!(slavename
= ptsname(master_in
))) {
82 fprintf(stderr
, "Unable to determine name of slave pty: %s\n",
87 if ((slave
= open(slavename
, O_RDWR
)) < 0) {
88 fprintf(stderr
, "Unable to open slave pty \"%s\": %s\n", slavename
,
93 dup2(slave
, STDIN_FILENO
);
97 if (!(slavename
= ptsname(master_out
))) {
98 fprintf(stderr
, "Unable to determine name of slave pty: %s\n",
103 if ((slave
= open(slavename
, O_RDWR
| O_NOCTTY
)) < 0) {
104 fprintf(stderr
, "Unable to open slave pty \"%s\": %s\n", slavename
,
109 dup2(slave
, STDOUT_FILENO
);
110 dup2(slave
, STDERR_FILENO
);
114 execvp(argv
[2], argv
+ 2);
116 fprintf(stderr
, "execvp(%s) failed: %s\n", argv
[2], strerror(errno
));
119 } else if (child
< 0) {
120 fprintf(stderr
, "fork() failed: %s\n", strerror(errno
));
124 if (!(output
= fopen(argv
[1], "w"))) {
125 fprintf(stderr
, "Unable to open \"%s\" for output: %s\n", argv
[1],
130 starttime
= time(NULL
);
138 FD_SET(master_out
, &readfds
);
141 * After we get our first bit of data, close the master pty
142 * connected to standard input on our slave; that will generate
146 tv
.tv_sec
= starttime
+ COMMAND_TIMEOUT
- time(NULL
);
151 cc
= select(master_out
+ 1, &readfds
, NULL
, NULL
, &tv
);
154 fprintf(stderr
, "select() failed: %s\n", strerror(errno
));
158 if (cc
> 0 && FD_ISSET(master_out
, &readfds
)) {
159 cc
= read(master_out
, readbuf
, sizeof(readbuf
));
164 fwrite(readbuf
, 1, cc
, output
);
166 if (master_in
!= -1) {
173 if (now
>= starttime
+ COMMAND_TIMEOUT
) {
174 fprintf(stderr
, "Command execution timed out: %ld to %ld: %d\n",
185 waitpid(child
, &status
, 0);