]>
Dogcows Code - chaz/tar/blob - tests/ttyemu.c
1 /* Run program with its first three file descriptors attached to a tty.
3 Copyright 2014 Free Software Foundation, Inc.
5 This file is part of GNU tar.
7 GNU tar is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 GNU tar is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #define _XOPEN_SOURCE 600
25 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/select.h>
36 #include <sys/ioctl.h>
52 # define DEBUG(c) fprintf (stderr, "%s\n", c)
66 #define shut(fildes) \
69 DEBUG (("closing " #fildes)); \
75 #define bufinit(buffer,all) \
78 (buffer).avail = (buffer).written = 0; \
79 (buffer).ts = time (NULL); \
85 #define bufisempty(buffer) ((buffer).avail == (buffer).written)
86 #define bufavail(buffer) (BUF_SIZE - (buffer).avail)
88 #define bufread(buffer,fildes,tty) \
91 int r = read (fildes, (buffer).buf + (buffer).avail, \
92 BUF_SIZE - (buffer).avail); \
93 (buffer).ts = time (NULL); \
98 if (tty && errno == EIO) \
102 fprintf (stderr, "%s:%d: reading from %s: %s", \
103 __FILE__,__LINE__,#fildes, strerror (errno)); \
110 (buffer).avail += r; \
114 #define bufwrite(buffer,fildes) \
117 int r = write (fildes, (buffer).buf + (buffer).written, \
118 (buffer).avail - (buffer).written); \
119 (buffer).ts = time (NULL); \
122 if (errno == EINTR) \
128 perror ("writing"); \
135 (buffer).written += r; \
140 tr (struct buffer
*bp
)
144 for (i
= j
= bp
->written
; i
< bp
->avail
;)
146 if (bp
->buf
[i
] == '\r')
156 if (bp
->buf
[i
] != '\n')
159 bp
->buf
[j
++] = bp
->buf
[i
++];
171 DEBUG (("child exited"));
181 if (tcgetattr (fd
, &to
))
183 perror ("tcgetattr");
186 to
.c_lflag
|= ICANON
;
187 to
.c_lflag
&= ~(ECHO
| ISIG
);
188 to
.c_cc
[VEOF
] = C_EOT
;
189 if (tcsetattr (fd
, TCSAFLUSH
| TCSASOFT
, &to
))
191 perror ("tcsetattr");
196 char *usage_text
[] = {
197 "usage: ttyemu [-ah] [-i INFILE] [-o OUTFILE] [-t TIMEOUT] PROGRAM [ARGS...]",
198 "ttyemu runs PROGRAM with its first three file descriptors connected to a"
203 " -a append output to OUTFILE, instead of overwriting it",
204 " -i INFILE read input from INFILE",
205 " -o OUTFILE write output to OUTFILE",
206 " -t TIMEOUT set I/O timeout",
207 " -h print this help summary",
209 "Report bugs and suggestions to <bug-tar@gnu.org>.",
218 for (i
= 0; usage_text
[i
]; i
++)
220 fputs (usage_text
[i
], stderr
);
221 fputc ('\n', stderr
);
226 main (int argc
, char **argv
)
232 struct buffer ibuf
, obuf
;
234 char *infile
= NULL
, *outfile
= NULL
;
235 int outflags
= O_TRUNC
;
240 while ((i
= getopt (argc
, argv
, "ai:o:t:h")) != EOF
)
245 outflags
&= ~O_TRUNC
;
257 timeout
= atoi (optarg
);
280 in
= open (infile
, O_RDONLY
);
290 out
= open (outfile
, O_RDWR
|O_CREAT
|outflags
, 0666);
298 master
= posix_openpt (O_RDWR
);
301 perror ("posix_openpty");
305 if (grantpt (master
))
311 if (unlockpt (master
))
317 signal (SIGCHLD
, sigchld
);
328 slave
= open (ptsname (master
), O_RDWR
);
336 for (i
= 0; i
< 3; i
++)
341 if (dup (slave
) != i
)
348 for (i
= sysconf (_SC_OPEN_MAX
) - 1; i
> 2; --i
)
353 ioctl (0, TIOCSCTTY
, 1);
355 execvp (argv
[0], argv
);
379 FD_SET (master
, &rdset
);
381 FD_SET (master
, &wrset
);
394 if (select (maxfd
+ 1, &rdset
, &wrset
, NULL
, NULL
) < 0)
404 time_t now
= time (NULL
);
405 if (now
- ibuf
.ts
> timeout
|| now
- obuf
.ts
> timeout
)
407 fprintf (stderr
, "ttyemu: I/O timeout\n");
414 if (bufavail (ibuf
) && FD_ISSET (in
, &rdset
))
415 bufread (ibuf
, in
, 0);
417 else if (master
== -1)
420 if (master
>= 0 && FD_ISSET (master
, &wrset
))
422 if (!bufisempty (ibuf
))
423 bufwrite (ibuf
, master
);
424 else if (in
== -1 && eot
)
426 DEBUG (("sent EOT"));
427 if (write (master
, &eot
, 1) <= 0)
436 if (master
>= 0 && bufavail (obuf
) && FD_ISSET (master
, &rdset
))
437 bufread (obuf
, master
, 1);
439 if (bufisempty (obuf
))
444 bufwrite (obuf
, out
);
447 if (bufisempty (ibuf
))
451 if (WIFEXITED (status
))
452 return WEXITSTATUS (status
);
454 if (WIFSIGNALED (status
))
455 fprintf (stderr
, "ttyemu: child process %s failed on signal %d\n",
456 argv
[0], WTERMSIG (status
));
458 fprintf (stderr
, "ttyemu: child process %s failed\n", argv
[0]);
This page took 0.053561 seconds and 4 git commands to generate.