123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /* pseudotty - open pseudo-terminal and print name of slave device to
- standard output. Read and ignore any data sent to terminal. This
- is so we can run tests interactively without messing up the screen.
- Copyright 2014, 2015, 2016 Free Software Foundation, Inc.
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- Originally written by Gavin Smith. */
- #define _XOPEN_SOURCE 600
- /* for posix_openpt */
- #include <config.h>
- #include <errno.h>
- #include <error.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/select.h>
- #include <stdlib.h>
- #include <string.h>
- #if HAVE_STROPTS_H
- #include <stropts.h>
- #endif
- #include "termdep.h"
- /* Used by "error" function. */
- const char *program_name = "pseudotty";
- int
- main (int argc, char *argv[])
- {
- int master, slave, control;
- char *name;
- fd_set read_set;
- error (0, 0, "getting pty master fd");
- master = posix_openpt (O_RDWR);
- if (master == -1)
- exit (1);
- error (0, 0, "unlocking slave device");
- if (grantpt (master) < 0 || unlockpt (master) < 0)
- exit (1);
- error (0, 0, "getting file name of slave device...");
- name = ptsname (master);
- if (!name)
- exit (1);
- error (0, 0, "%s", name);
- #ifdef HAVE_STROPTS_H
- error (0, 0, "opening slave device");
- slave = open (name, O_RDWR);
- if (slave == -1)
- exit (1);
- if (!isatty (slave))
- {
- error (0, 0, "performing STREAMS ioctl's on slave");
- if (isastream (slave))
- {
- if (ioctl (slave, I_PUSH, "ptem") < 0
- || ioctl (slave, I_PUSH, "ldterm") < 0)
- error (1, 0, "STREAMS ioctl's failed");
- }
- }
- /* Don't close it because it just leads to an EOF read at the master end. */
- /*
- error (0, 0, "closing slave device");
- close (slave);
- error (0, 0, "...closed");
- */
- #endif
- #if defined (HAVE_TERMIOS_H)
- {
- struct termios t;
- long int disable;
- disable = fpathconf (slave, _PC_VDISABLE);
- if (tcgetattr (slave, &t) == -1)
- error (0, 0, "error calling tcgetattr");
- else
- {
- t.c_cc[VSTART] = disable; /* C-q */
- t.c_cc[VSTOP] = disable; /* C-s */
- t.c_cc[VKILL] = disable; /* C-u */
- t.c_cc[VINTR] = disable; /* C-c */
- if (tcsetattr (slave, TCSANOW, &t) == -1)
- error (0, 0, "error calling tcsetattr");
- }
- }
- #endif
- #if defined (TIOCSWINSZ)
- {
- struct winsize ws;
- ws.ws_col = ws.ws_row = 0;
- error (0, 0, "attempting to set window size");
- if (ioctl (master, TIOCSWINSZ, &ws) == 0)
- error (0, 0, "...succeeded");
- else
- error (0, 0, "...failed");
- }
- #endif
- printf ("%s\n", name);
- if (fclose (stdout) != 0)
- error (1, 0, "error closing stdout: aborting");
- error (0, 0, "opening control channel");
- control = open (argv[1], O_RDONLY);
- if (control == -1)
- error (1, 0, "error opening control channel: aborting");
- FD_ZERO (&read_set);
- error (0, 0, "entering main loop");
- while (1)
- {
- FD_SET (master, &read_set);
- FD_SET (control, &read_set);
- select (FD_SETSIZE, &read_set, 0, 0, 0);
- if (FD_ISSET (control, &read_set))
- {
- char c;
- int success;
- errno = 0;
- while (1)
- {
- error (0, 0, "trying to read");
- success = read (control, &c, 1);
- if (success < 0)
- {
- if (errno != EINTR)
- error (1, errno, "read error on control channel");
- }
- else if (success == 0)
- {
- error (1, 0, "end of file on control channel");
- }
- else if (success == 1)
- {
- error (0, 0, "read byte 0x%02X", c);
- break;
- }
- }
- /* Feed any read bytes to the program being controlled. */
- do
- {
- success = write (master, &c, 1);
- if (success == 0)
- {
- error (0, 0, "couldn't send byte!");
- sleep (1);
- continue;
- }
- }
- while (success == -1 && errno == EINTR);
- if (success != 1)
- {
- /* The controlled process has probably exited, or been killed. */
- error (0, 0, "couldn't send byte (giving up)");
- sleep (1);
- }
- }
- if (FD_ISSET (master, &read_set))
- {
- char c;
- int success;
- errno = 0;
- do
- {
- success = read (master, &c, 1);
- }
- while (success == -1 && errno == EINTR);
- if (success == -1)
- {
- /* The controlled process has probably exited, or been killed. */
- error (0, 0, "read error on master fd");
- sleep (1);
- }
- }
- }
- return 0; /* NOTREACHED */
- }
|