tests: add test77 for opening/closing PTYs
Change-Id: I30e3418f75137aa08037fa6581ff3d4cce32a114
This commit is contained in:
parent
20173cb5d7
commit
4211c5d267
4 changed files with 491 additions and 3 deletions
|
@ -5657,6 +5657,7 @@
|
||||||
./usr/tests/minix-posix/test74 minix-sys
|
./usr/tests/minix-posix/test74 minix-sys
|
||||||
./usr/tests/minix-posix/test75 minix-sys
|
./usr/tests/minix-posix/test75 minix-sys
|
||||||
./usr/tests/minix-posix/test76 minix-sys
|
./usr/tests/minix-posix/test76 minix-sys
|
||||||
|
./usr/tests/minix-posix/test77 minix-sys
|
||||||
./usr/tests/minix-posix/test8 minix-sys
|
./usr/tests/minix-posix/test8 minix-sys
|
||||||
./usr/tests/minix-posix/test9 minix-sys
|
./usr/tests/minix-posix/test9 minix-sys
|
||||||
./usr/tests/minix-posix/testinterp minix-sys
|
./usr/tests/minix-posix/testinterp minix-sys
|
||||||
|
|
|
@ -32,6 +32,7 @@ COPTS.test68.c= -O0
|
||||||
# Some have special libraries
|
# Some have special libraries
|
||||||
LDADD.test59= -lmthread
|
LDADD.test59= -lmthread
|
||||||
LDADD.test76= -lutil
|
LDADD.test76= -lutil
|
||||||
|
LDADD.test77= -lutil
|
||||||
|
|
||||||
# Some have an extra file
|
# Some have an extra file
|
||||||
OBJS.test57= test57loop.o
|
OBJS.test57= test57loop.o
|
||||||
|
@ -54,7 +55,7 @@ MINIX_TESTS= \
|
||||||
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
||||||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
||||||
41 42 43 44 45 46 48 49 50 52 53 54 55 56 58 59 60 \
|
41 42 43 44 45 46 48 49 50 52 53 54 55 56 58 59 60 \
|
||||||
61 64 65 66 67 68 69 70 71 72 73 74 75 76
|
61 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
||||||
|
|
||||||
.if ${MACHINE_ARCH} == "i386"
|
.if ${MACHINE_ARCH} == "i386"
|
||||||
MINIX_TESTS+= \
|
MINIX_TESTS+= \
|
||||||
|
|
4
test/run
4
test/run
|
@ -21,14 +21,14 @@ badones= # list of tests that failed
|
||||||
|
|
||||||
# Programs that require setuid
|
# Programs that require setuid
|
||||||
setuids="test11 test33 test43 test44 test46 test56 test60 test61 test65 \
|
setuids="test11 test33 test43 test44 test46 test56 test60 test61 test65 \
|
||||||
test69 test76" # test73"
|
test69 test76 test77" # test73"
|
||||||
# Scripts that require to be run as root
|
# Scripts that require to be run as root
|
||||||
rootscripts="testisofs"
|
rootscripts="testisofs"
|
||||||
|
|
||||||
alltests="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
alltests="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
||||||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
||||||
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
|
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
|
||||||
61 62 63 64 65 66 67 68 69 70 71 72 75 76 \
|
61 62 63 64 65 66 67 68 69 70 71 72 75 76 77 \
|
||||||
sh1 sh2 interp mfs isofs"
|
sh1 sh2 interp mfs isofs"
|
||||||
tests_no=`expr 0`
|
tests_no=`expr 0`
|
||||||
|
|
||||||
|
|
486
test/test77.c
Normal file
486
test/test77.c
Normal file
|
@ -0,0 +1,486 @@
|
||||||
|
/* Tests for opening/closing pseudo terminals - by D.C. van Moolenbroek */
|
||||||
|
/* This test needs to be run as root; otherwise, openpty() won't work. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
#define ITERATIONS 10
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
static int sighups; /* number of SIGHUP signals received */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal handler for SIGHUP and SIGUSR1.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
signal_handler(int sig)
|
||||||
|
{
|
||||||
|
if (sig == SIGHUP)
|
||||||
|
sighups++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the slave side of the pseudo terminal to raw mode. This simplifies
|
||||||
|
* testing communication.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
make_raw(int slavefd)
|
||||||
|
{
|
||||||
|
struct termios tios;
|
||||||
|
|
||||||
|
if (tcgetattr(slavefd, &tios) < 0) e(100);
|
||||||
|
|
||||||
|
cfmakeraw(&tios);
|
||||||
|
|
||||||
|
if (tcsetattr(slavefd, TCSANOW, &tios) < 0) e(101);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See if the given pseudo terminal can successfully perform basic
|
||||||
|
* communication between master and slave.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
test_comm(int masterfd, int slavefd)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
|
||||||
|
make_raw(slavefd);
|
||||||
|
|
||||||
|
c = 'A';
|
||||||
|
if (write(masterfd, &c, sizeof(c)) != sizeof(c)) e(200);
|
||||||
|
if (read(slavefd, &c, sizeof(c)) != sizeof(c)) e(201);
|
||||||
|
if (c != 'A') e(202);
|
||||||
|
|
||||||
|
c = 'B';
|
||||||
|
if (write(slavefd, &c, sizeof(c)) != sizeof(c)) e(203);
|
||||||
|
if (read(masterfd, &c, sizeof(c)) != sizeof(c)) e(204);
|
||||||
|
if (c != 'B') e(205);
|
||||||
|
|
||||||
|
c = 'C';
|
||||||
|
if (write(masterfd, &c, sizeof(c)) != sizeof(c)) e(206);
|
||||||
|
if (read(slavefd, &c, sizeof(c)) != sizeof(c)) e(207);
|
||||||
|
if (c != 'C') e(208);
|
||||||
|
|
||||||
|
c = 'D';
|
||||||
|
if (write(slavefd, &c, sizeof(c)) != sizeof(c)) e(209);
|
||||||
|
if (read(masterfd, &c, sizeof(c)) != sizeof(c)) e(210);
|
||||||
|
if (c != 'D') e(211);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get device node names for the master and slave end of a free pseudo
|
||||||
|
* terminal. We don't want to replicate the entire openpty(3) logic here, so
|
||||||
|
* start by letting openpty(3) do the work for us. We make the assumption that
|
||||||
|
* nobody snatches the pair while we are running.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
get_names(char pname[PATH_MAX], char tname[PATH_MAX])
|
||||||
|
{
|
||||||
|
int len, masterfd, slavefd;
|
||||||
|
|
||||||
|
if (openpty(&masterfd, &slavefd, tname, NULL, NULL) < 0) e(300);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* openpty(3) gives us only the slave name, but we also need the master
|
||||||
|
* name.
|
||||||
|
*/
|
||||||
|
strlcpy(pname, tname, PATH_MAX);
|
||||||
|
len = strlen(_PATH_DEV);
|
||||||
|
|
||||||
|
if (strncmp(pname, _PATH_DEV, len)) e(301);
|
||||||
|
|
||||||
|
/* If this fails, this test needs to be updated. */
|
||||||
|
if (pname[len] != 't') e(302);
|
||||||
|
|
||||||
|
pname[len] = 'p';
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if (close(masterfd) < 0) e(303);
|
||||||
|
if (close(slavefd) < 0) e(304);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test various orders of opening and closing the master and slave sides of a
|
||||||
|
* pseudo terminal, as well as opening/closing one side without ever opening
|
||||||
|
* the other.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
test77a(void)
|
||||||
|
{
|
||||||
|
struct sigaction act, oact;
|
||||||
|
char pname[PATH_MAX], tname[PATH_MAX];
|
||||||
|
int masterfd, slavefd;
|
||||||
|
|
||||||
|
subtest = 1;
|
||||||
|
|
||||||
|
/* We do not want to get SIGHUP signals in this test. */
|
||||||
|
memset(&act, 0, sizeof(act));
|
||||||
|
act.sa_handler = SIG_IGN;
|
||||||
|
if (sigaction(SIGHUP, &act, &oact) < 0) e(1);
|
||||||
|
|
||||||
|
/* Get master and slave device names for a free pseudo terminal. */
|
||||||
|
get_names(pname, tname);
|
||||||
|
|
||||||
|
/* Try opening and then closing the master. */
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(2);
|
||||||
|
|
||||||
|
if (close(masterfd) < 0) e(3);
|
||||||
|
|
||||||
|
/* Now see if we can reopen the master as well as the slave. */
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(4);
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(5);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
/* In the meantime, test different closing orders. This is order A. */
|
||||||
|
if (close(slavefd) < 0) e(6);
|
||||||
|
if (close(masterfd) < 0) e(7);
|
||||||
|
|
||||||
|
/* Now try opening the pair again. */
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(8);
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(9);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if (close(slavefd) < 0) e(10);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try reopening the slave after closing it. It is not very important
|
||||||
|
* that this works, but the TTY driver should currently support it.
|
||||||
|
*/
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(11);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
/* This is closing order B. This may or may not cause a SIGHUP. */
|
||||||
|
if (close(masterfd) < 0) e(12);
|
||||||
|
if (close(slavefd) < 0) e(13);
|
||||||
|
|
||||||
|
/* Try the normal open procedure. */
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(14);
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(15);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if (close(slavefd) < 0) e(16);
|
||||||
|
if (close(masterfd) < 0) e(17);
|
||||||
|
|
||||||
|
/* Try reopening and closing the slave, without opening the master. */
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(18);
|
||||||
|
|
||||||
|
if (close(slavefd) < 0) e(19);
|
||||||
|
|
||||||
|
/* Again, try the normal open procedure. */
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(20);
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(21);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if (close(slavefd) < 0) e(22);
|
||||||
|
if (close(masterfd) < 0) e(23);
|
||||||
|
|
||||||
|
/* Finally, try opening the slave first. */
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(24);
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(25);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if (close(slavefd) < 0) e(26);
|
||||||
|
if (close(masterfd) < 0) e(27);
|
||||||
|
|
||||||
|
if (sigaction(SIGHUP, &oact, NULL) < 0) e(28);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test opening a single side multiple times.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
test77b(void)
|
||||||
|
{
|
||||||
|
char pname[PATH_MAX], tname[PATH_MAX];
|
||||||
|
int masterfd, slavefd, extrafd;
|
||||||
|
|
||||||
|
subtest = 2;
|
||||||
|
|
||||||
|
/* Get master and slave device names for a free pseudo terminal. */
|
||||||
|
get_names(pname, tname);
|
||||||
|
|
||||||
|
/* It must not be possible to open the master multiple times. */
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(1);
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(2);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if ((extrafd = open(pname, O_RDWR | O_NOCTTY)) >= 0) e(3);
|
||||||
|
if (errno != EIO) e(4);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if (close(slavefd) < 0) e(5);
|
||||||
|
if (close(masterfd) < 0) e(6);
|
||||||
|
|
||||||
|
/* The slave can be opened multiple times, though. */
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(7);
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(8);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if ((extrafd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(9);
|
||||||
|
|
||||||
|
test_comm(masterfd, extrafd);
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if (close(slavefd) < 0) e(10);
|
||||||
|
if (close(extrafd) < 0) e(11);
|
||||||
|
if (close(masterfd) < 0) e(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test communication on half-open pseudo terminals.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
test77c(void)
|
||||||
|
{
|
||||||
|
struct sigaction act, oact;
|
||||||
|
char pname[PATH_MAX], tname[PATH_MAX];
|
||||||
|
int masterfd, slavefd;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
subtest = 3;
|
||||||
|
|
||||||
|
/* We do not want to get SIGHUP signals in this test. */
|
||||||
|
memset(&act, 0, sizeof(act));
|
||||||
|
act.sa_handler = SIG_IGN;
|
||||||
|
if (sigaction(SIGHUP, &act, &oact) < 0) e(1);
|
||||||
|
|
||||||
|
/* Get master and slave device names for a free pseudo terminal. */
|
||||||
|
get_names(pname, tname);
|
||||||
|
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(2);
|
||||||
|
|
||||||
|
/* Writes to the master should be buffered until there is a slave. */
|
||||||
|
c = 'E';
|
||||||
|
if (write(masterfd, &c, sizeof(c)) != sizeof(c)) e(3);
|
||||||
|
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(4);
|
||||||
|
|
||||||
|
make_raw(slavefd);
|
||||||
|
|
||||||
|
if (read(slavefd, &c, sizeof(c)) != sizeof(c)) e(5);
|
||||||
|
if (c != 'E') e(6);
|
||||||
|
|
||||||
|
/* Discard the echo on the master. */
|
||||||
|
if (tcflush(slavefd, TCOFLUSH) != 0) e(7);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if (close(slavefd) < 0) e(8);
|
||||||
|
|
||||||
|
/* Writes to the master after the slave has been closed should fail. */
|
||||||
|
if (write(masterfd, &c, sizeof(c)) >= 0) e(9);
|
||||||
|
if (errno != EIO) e(10);
|
||||||
|
|
||||||
|
if (close(masterfd) < 0) e(11);
|
||||||
|
|
||||||
|
/* Writes to the slave should be buffered until there is a master. */
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(12);
|
||||||
|
|
||||||
|
make_raw(slavefd);
|
||||||
|
|
||||||
|
c = 'F';
|
||||||
|
if (write(slavefd, &c, sizeof(c)) != sizeof(c)) e(13);
|
||||||
|
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(14);
|
||||||
|
|
||||||
|
if (read(masterfd, &c, sizeof(c)) != sizeof(c)) e(15);
|
||||||
|
if (c != 'F') e(16);
|
||||||
|
|
||||||
|
test_comm(masterfd, slavefd);
|
||||||
|
|
||||||
|
if (close(masterfd) < 0) e(17);
|
||||||
|
|
||||||
|
if (write(slavefd, &c, sizeof(c)) >= 0) e(18);
|
||||||
|
if (errno != EIO) e(19);
|
||||||
|
|
||||||
|
if (close(slavefd) < 0) e(20);
|
||||||
|
|
||||||
|
if (sigaction(SIGHUP, &oact, NULL) < 0) e(21);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test opening the slave side with and without the O_NOCTTY flag.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
test77d(void)
|
||||||
|
{
|
||||||
|
char pname[PATH_MAX], tname[PATH_MAX];
|
||||||
|
int masterfd, slavefd;
|
||||||
|
|
||||||
|
subtest = 4;
|
||||||
|
|
||||||
|
/* Get master and slave device names for a free pseudo terminal. */
|
||||||
|
get_names(pname, tname);
|
||||||
|
|
||||||
|
/* Make ourselves process group leader if we aren't already. */
|
||||||
|
(void) setsid();
|
||||||
|
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Opening the slave with O_NOCTTY should not change its controlling
|
||||||
|
* terminal.
|
||||||
|
*/
|
||||||
|
switch (fork()) {
|
||||||
|
case 0:
|
||||||
|
if (setsid() < 0) e(2);
|
||||||
|
|
||||||
|
if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(3);
|
||||||
|
|
||||||
|
if (open("/dev/tty", O_RDWR) >= 0) e(4);
|
||||||
|
if (errno != ENXIO) e(5);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
case -1:
|
||||||
|
e(6);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait(NULL) <= 0) e(7);
|
||||||
|
|
||||||
|
if (close(masterfd) < 0) e(8);
|
||||||
|
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(9);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Opening the slave without O_NOCTTY should change its controlling
|
||||||
|
* terminal, though.
|
||||||
|
*/
|
||||||
|
switch (fork()) {
|
||||||
|
case 0:
|
||||||
|
if (setsid() < 0) e(10);
|
||||||
|
|
||||||
|
if ((slavefd = open(tname, O_RDWR)) < 0) e(11);
|
||||||
|
|
||||||
|
if (open("/dev/tty", O_RDWR) < 0) e(12);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
case -1:
|
||||||
|
e(13);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait(NULL) <= 0) e(14);
|
||||||
|
|
||||||
|
if (close(masterfd) < 0) e(15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test receiving of SIGHUP on master hang-up. All of the tests so far have
|
||||||
|
* ignored SIGHUP, and probably would not have received one anyway, since the
|
||||||
|
* process was not its own session leader. Time to test this aspect.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
test77e(void)
|
||||||
|
{
|
||||||
|
struct sigaction act, hup_oact, usr_oact;
|
||||||
|
sigset_t set, oset;
|
||||||
|
char pname[PATH_MAX], tname[PATH_MAX];
|
||||||
|
int masterfd, slavefd;
|
||||||
|
|
||||||
|
subtest = 5;
|
||||||
|
|
||||||
|
/* Get master and slave device names for a free pseudo terminal. */
|
||||||
|
get_names(pname, tname);
|
||||||
|
|
||||||
|
memset(&act, 0, sizeof(act));
|
||||||
|
act.sa_handler = signal_handler;
|
||||||
|
if (sigaction(SIGHUP, &act, &hup_oact) < 0) e(1);
|
||||||
|
|
||||||
|
memset(&act, 0, sizeof(act));
|
||||||
|
act.sa_handler = signal_handler;
|
||||||
|
if (sigaction(SIGUSR1, &act, &usr_oact) < 0) e(2);
|
||||||
|
|
||||||
|
sigemptyset(&set);
|
||||||
|
sigaddset(&set, SIGHUP);
|
||||||
|
sigaddset(&set, SIGUSR1);
|
||||||
|
if (sigprocmask(SIG_BLOCK, &set, &oset) < 0) e(3);
|
||||||
|
|
||||||
|
sighups = 0;
|
||||||
|
|
||||||
|
/* Make ourselves process group leader if we aren't already. */
|
||||||
|
(void) setsid();
|
||||||
|
|
||||||
|
if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(4);
|
||||||
|
|
||||||
|
switch (fork()) {
|
||||||
|
case 0:
|
||||||
|
if (close(masterfd) < 0) e(5);
|
||||||
|
|
||||||
|
/* Become session leader. */
|
||||||
|
if (setsid() < 0) e(6);
|
||||||
|
|
||||||
|
if ((slavefd = open(tname, O_RDWR)) < 0) e(7);
|
||||||
|
|
||||||
|
/* Tell the parent we are ready. */
|
||||||
|
kill(getppid(), SIGUSR1);
|
||||||
|
|
||||||
|
/* We should now get a SIGHUP. */
|
||||||
|
set = oset;
|
||||||
|
if (sigsuspend(&set) >= 0) e(8);
|
||||||
|
|
||||||
|
if (sighups != 1) e(9);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
case -1:
|
||||||
|
e(10);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for SIGUSR1 from the child. */
|
||||||
|
set = oset;
|
||||||
|
if (sigsuspend(&set) >= 0) e(11);
|
||||||
|
|
||||||
|
/* Closing the master should now raise a SIGHUP signal in the child. */
|
||||||
|
if (close(masterfd) < 0) e(12);
|
||||||
|
|
||||||
|
if (wait(NULL) <= 0) e(13);
|
||||||
|
|
||||||
|
if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0) e(14);
|
||||||
|
|
||||||
|
if (sigaction(SIGHUP, &hup_oact, NULL) < 0) e(15);
|
||||||
|
if (sigaction(SIGUSR1, &usr_oact, NULL) < 0) e(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i, m;
|
||||||
|
|
||||||
|
start(77);
|
||||||
|
|
||||||
|
if (argc == 2)
|
||||||
|
m = atoi(argv[1]);
|
||||||
|
else
|
||||||
|
m = 0xFF;
|
||||||
|
|
||||||
|
for (i = 0; i < ITERATIONS; i++) {
|
||||||
|
if (m & 0x01) test77a();
|
||||||
|
if (m & 0x02) test77b();
|
||||||
|
if (m & 0x04) test77c();
|
||||||
|
if (m & 0x08) test77d();
|
||||||
|
if (m & 0x10) test77e();
|
||||||
|
}
|
||||||
|
|
||||||
|
quit();
|
||||||
|
}
|
Loading…
Reference in a new issue