mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-08 10:09:32 +08:00
Cygwin: AF_UNIX: update tests
This commit is contained in:
parent
6841fcb82f
commit
a2e279eb68
@ -19,7 +19,8 @@ EXE = ud_ucase_sv ud_ucase_cl \
|
||||
fork_socketpair \
|
||||
select_sv select_cl \
|
||||
is_seqnum_v2_sv is_seqnum_v3_sv is_seqnum_v2_cl \
|
||||
recv_pty_slave send_pty_slave
|
||||
recv_pty_slave send_pty_slave \
|
||||
recv_pty_master send_pty_master
|
||||
|
||||
all: ${EXE}
|
||||
|
||||
@ -54,6 +55,8 @@ is_seqnum_v2_sv.o is_seqnum_v3_sv.o is_seqnum_v2_cl.o: is_seqnum_v2.h
|
||||
|
||||
recv_pty_slave.o send_pty_slave.o: pty_slave.h
|
||||
|
||||
recv_pty_master.o send_pty_master.o: pty_master.h
|
||||
|
||||
clean:
|
||||
cd lib; ${MAKE} clean
|
||||
${RM} *.exe *.o ${AF_UNIX_LIB}
|
||||
|
@ -210,7 +210,6 @@
|
||||
|
||||
# Terminal 2:
|
||||
$ ./send_pty_slave.exe
|
||||
$ ./send_pty_slave.exe
|
||||
hello
|
||||
|
||||
#Terminal 1 now shows:
|
||||
@ -232,3 +231,49 @@
|
||||
(c) 2019 Microsoft Corporation. All rights reserved.
|
||||
|
||||
C:\Users\kbrown\src\cygdll\af_unix\winsup\cygwin\socket_tests>exit
|
||||
|
||||
12. Ancillary data test (SCM_RIGHTS, pty master descriptor).
|
||||
send_pty_master creates pty pair and a shell subprocess connected
|
||||
to the slave. It then does the same as in 11, except that it
|
||||
sends the master descriptor instead of the slave descriptor.
|
||||
recv_pty_master writes "ps\n" to the received master fd. The
|
||||
shell created by send_pty_master reads and executes this.
|
||||
|
||||
In two terminals:
|
||||
|
||||
# Terminal 1:
|
||||
$ ./recv_pty_master.exe
|
||||
Waiting for sender to connect and send descriptor...
|
||||
|
||||
# Terminal 2:
|
||||
$ ./send_pty_master.exe
|
||||
ps
|
||||
|
||||
$ ps
|
||||
PID PPID PGID WINPID TTY UID STIME COMMAND
|
||||
934 933 934 138392 pty2 197609 13:47:22 /usr/bin/bash
|
||||
937 934 937 109052 pty2 197609 13:47:22 /usr/bin/ps
|
||||
887 886 887 51496 pty1 197609 13:11:25 /usr/bin/bash
|
||||
875 874 875 30396 pty0 197609 13:11:21 /usr/bin/bash
|
||||
874 1 874 23516 ? 197609 13:11:21 /usr/bin/mintty
|
||||
886 1 886 118428 ? 197609 13:11:25 /usr/bin/mintty
|
||||
933 887 933 59856 pty1 197609 13:47:22 /home/kbrown/src/cygdll/af_unix/winsup/cygwin/socket_tests/send_pty_master
|
||||
932 875 932 115304 pty0 197609 13:46:30 /home/kbrown/src/cygdll/af_unix/winsup/cygwin/socket_tests/recv_pty_master
|
||||
|
||||
[Why is ps echoed twice?]
|
||||
|
||||
|
||||
#Terminal 1 now shows:
|
||||
$ ./recv_pty_master.exe
|
||||
Waiting for sender to connect and send descriptor...
|
||||
Received descriptor 5.
|
||||
Writing "ps" to that descriptor.
|
||||
This should appear in the other terminal
|
||||
and be executed by the shell running there.
|
||||
Waiting for sender to finish...
|
||||
|
||||
Can now exit the shell in terminal 2 and both programs exit.
|
||||
|
||||
This doesn't work if we use SHELL=cmd in terminal 2. "ps" gets
|
||||
echoed but not executed. I'm not sure if we should expect it to
|
||||
work.
|
||||
|
5
winsup/cygwin/socket_tests/pty_master.h
Normal file
5
winsup/cygwin/socket_tests/pty_master.h
Normal file
@ -0,0 +1,5 @@
|
||||
/* pty_slave.h
|
||||
|
||||
Header file for send_pty_master.c and recv_pty_master.c
|
||||
*/
|
||||
#define SOCK_PATH "/tmp/pty_master"
|
40
winsup/cygwin/socket_tests/recv_pty_master.c
Normal file
40
winsup/cygwin/socket_tests/recv_pty_master.c
Normal file
@ -0,0 +1,40 @@
|
||||
#include "af_unix_hdr.h"
|
||||
#include "pty_master.h"
|
||||
#define BUF_SIZE 100
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int lfd, connfd, ptyfd, junk;
|
||||
|
||||
if (remove (SOCK_PATH) == -1 && errno != ENOENT)
|
||||
errExit ("remove-%s", SOCK_PATH);
|
||||
|
||||
lfd = unixBind (SOCK_PATH, SOCK_STREAM);
|
||||
if (lfd < 0)
|
||||
errExit ("unixBind");
|
||||
printf ("Waiting for sender to connect and send descriptor...\n");
|
||||
if (listen (lfd, 5) < 0)
|
||||
errExit ("listen");
|
||||
connfd = accept (lfd, NULL, NULL);
|
||||
if (connfd < 0)
|
||||
errExit ("accept");
|
||||
ptyfd = recvfd (connfd);
|
||||
if (ptyfd < 0)
|
||||
errExit ("recvfd");
|
||||
printf ("Received descriptor %d.\n", ptyfd);
|
||||
printf ("Writing \"ps\" to that descriptor.\n"
|
||||
"This should appear in the other terminal\n"
|
||||
"and be executed by the shell running there.\n");
|
||||
if (write (ptyfd, "ps\n", 3) != 3)
|
||||
errExit ("write");
|
||||
printf ("Waiting for sender to finish...\n");
|
||||
if (read (connfd, &junk, sizeof junk) < 0)
|
||||
errExit ("read");
|
||||
if (close (ptyfd) < 0)
|
||||
errMsg ("close");
|
||||
if (close (lfd) < 0)
|
||||
errMsg ("close");
|
||||
if (close (connfd) < 0)
|
||||
errMsg ("close");
|
||||
}
|
143
winsup/cygwin/socket_tests/send_pty_master.c
Normal file
143
winsup/cygwin/socket_tests/send_pty_master.c
Normal file
@ -0,0 +1,143 @@
|
||||
/* Adapted from Kerrisk's script.c by Ken Brown */
|
||||
|
||||
/*
|
||||
Create a pty pair and fork/exec a shell running on the slave. Send
|
||||
the master fd across an AF_UNIX socket to a process running
|
||||
recv_pty_slave.
|
||||
*/
|
||||
|
||||
/*************************************************************************\
|
||||
* Copyright (C) Michael Kerrisk, 2018. *
|
||||
* *
|
||||
* This program is free software. You may use, modify, and redistribute it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation, either version 3 or (at your option) any *
|
||||
* later version. This program is distributed without any warranty. See *
|
||||
* the file COPYING.gpl-v3 for details. *
|
||||
\*************************************************************************/
|
||||
|
||||
/* Listing 64-3 */
|
||||
|
||||
/* script.c
|
||||
|
||||
A simple version of script(1).
|
||||
*/
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <termios.h>
|
||||
#if ! defined(__hpux)
|
||||
/* HP-UX 11 doesn't have this header file */
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#include "pty_fork.h" /* Declaration of ptyFork() */
|
||||
#include "tty_functions.h" /* Declaration of ttySetRaw() */
|
||||
#include "af_unix_hdr.h"
|
||||
#include "pty_master.h"
|
||||
|
||||
#define BUF_SIZE 256
|
||||
#define MAX_SNAME 1000
|
||||
|
||||
struct termios ttyOrig;
|
||||
|
||||
static void /* Reset terminal mode on program exit */
|
||||
ttyReset(void)
|
||||
{
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &ttyOrig) == -1)
|
||||
errExit("tcsetattr");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char slaveName[MAX_SNAME];
|
||||
char *shell;
|
||||
int masterFd, connFd, junk;
|
||||
struct winsize ws;
|
||||
fd_set inFds;
|
||||
char buf[BUF_SIZE];
|
||||
ssize_t numRead;
|
||||
pid_t childPid;
|
||||
|
||||
/* Retrieve the attributes of terminal on which we are started */
|
||||
|
||||
if (tcgetattr(STDIN_FILENO, &ttyOrig) == -1)
|
||||
errExit("tcgetattr");
|
||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0)
|
||||
errExit("ioctl-TIOCGWINSZ");
|
||||
|
||||
/* Create a child process, with parent and child connected via a
|
||||
pty pair. The child is connected to the pty slave and its terminal
|
||||
attributes are set to be the same as those retrieved above. */
|
||||
|
||||
childPid = ptyFork(&masterFd, slaveName, MAX_SNAME, &ttyOrig, &ws);
|
||||
if (childPid == -1)
|
||||
errExit("ptyFork");
|
||||
|
||||
if (childPid == 0) { /* Child: execute a shell on pty slave */
|
||||
|
||||
/* If the SHELL variable is set, use its value to determine
|
||||
the shell execed in child. Otherwise use /bin/sh. */
|
||||
|
||||
shell = getenv("SHELL");
|
||||
if (shell == NULL || *shell == '\0')
|
||||
shell = "/bin/sh";
|
||||
|
||||
execlp(shell, shell, (char *) NULL);
|
||||
errExit("execlp"); /* If we get here, something went wrong */
|
||||
}
|
||||
|
||||
/* Parent */
|
||||
|
||||
if ((connFd = unixConnect (SOCK_PATH, SOCK_STREAM)) < 0)
|
||||
errExit ("unixConnect");
|
||||
|
||||
/* Send master fd across the socket. */
|
||||
if (sendfd (connFd, masterFd) < 0)
|
||||
errExit ("sendfd");
|
||||
|
||||
/* Place terminal in raw mode so that we can pass all terminal
|
||||
input to the pseudoterminal master untouched */
|
||||
|
||||
ttySetRaw(STDIN_FILENO, &ttyOrig);
|
||||
|
||||
if (atexit(ttyReset) != 0)
|
||||
errExit("atexit");
|
||||
|
||||
/* Loop monitoring terminal and pty master for input. If the
|
||||
terminal is ready for input, then read some bytes and write
|
||||
them to the pty master. If the pty master is ready for input,
|
||||
then read some bytes and write them to the terminal. */
|
||||
|
||||
for (;;) {
|
||||
FD_ZERO(&inFds);
|
||||
FD_SET(STDIN_FILENO, &inFds);
|
||||
FD_SET(masterFd, &inFds);
|
||||
|
||||
if (select(masterFd + 1, &inFds, NULL, NULL, NULL) == -1)
|
||||
errExit("select");
|
||||
|
||||
if (FD_ISSET(STDIN_FILENO, &inFds)) { /* stdin --> pty */
|
||||
numRead = read(STDIN_FILENO, buf, BUF_SIZE);
|
||||
if (numRead <= 0)
|
||||
break;
|
||||
|
||||
if (write(masterFd, buf, numRead) != numRead)
|
||||
fatal("partial/failed write (masterFd)");
|
||||
}
|
||||
|
||||
if (FD_ISSET(masterFd, &inFds)) { /* pty --> stdout */
|
||||
numRead = read(masterFd, buf, BUF_SIZE);
|
||||
if (numRead <= 0)
|
||||
break;
|
||||
|
||||
if (write(STDOUT_FILENO, buf, numRead) != numRead)
|
||||
fatal("partial/failed write (STDOUT_FILENO)");
|
||||
}
|
||||
}
|
||||
/* Notify receiver that we're done. */
|
||||
if (write (connFd, &junk, sizeof junk) != sizeof junk)
|
||||
errMsg ("write");
|
||||
if (close (connFd) < 0)
|
||||
errMsg ("close");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user