mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-15 05:29:10 +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 \
|
fork_socketpair \
|
||||||
select_sv select_cl \
|
select_sv select_cl \
|
||||||
is_seqnum_v2_sv is_seqnum_v3_sv is_seqnum_v2_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}
|
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_slave.o send_pty_slave.o: pty_slave.h
|
||||||
|
|
||||||
|
recv_pty_master.o send_pty_master.o: pty_master.h
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
cd lib; ${MAKE} clean
|
cd lib; ${MAKE} clean
|
||||||
${RM} *.exe *.o ${AF_UNIX_LIB}
|
${RM} *.exe *.o ${AF_UNIX_LIB}
|
||||||
|
@ -210,7 +210,6 @@
|
|||||||
|
|
||||||
# Terminal 2:
|
# Terminal 2:
|
||||||
$ ./send_pty_slave.exe
|
$ ./send_pty_slave.exe
|
||||||
$ ./send_pty_slave.exe
|
|
||||||
hello
|
hello
|
||||||
|
|
||||||
#Terminal 1 now shows:
|
#Terminal 1 now shows:
|
||||||
@ -232,3 +231,49 @@
|
|||||||
(c) 2019 Microsoft Corporation. All rights reserved.
|
(c) 2019 Microsoft Corporation. All rights reserved.
|
||||||
|
|
||||||
C:\Users\kbrown\src\cygdll\af_unix\winsup\cygwin\socket_tests>exit
|
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