diff --git a/test/test37.c b/test/test37.c index 45e2a40d0..90de49701 100644 --- a/test/test37.c +++ b/test/test37.c @@ -1,265 +1,1049 @@ -/* test37: pipe() Author: Jan-Mark Wams (jms@cs.vu.nl) */ +/* test 37 - signals */ #include -#include +#include +#ifdef _MINIX +#include +#endif #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include #include -#define MAX_ERROR 4 -#define ITERATIONS 60 +#define ITERATIONS 2 +#define SIGS 14 +#define MAX_ERROR 4 -#define Fstat(a,b) if (fstat(a,b) != 0) printf("Can't fstat %d\n", a) -#define Time(t) if (time(t) == (time_t)-1) printf("Time error\n") +int iteration, cumsig, subtest, errct = 0, sig1, sig2; -int errct = 0; -int subtest = 1; -char MaxName[NAME_MAX + 1]; /* Name of maximum length */ -char MaxPath[PATH_MAX]; /* Same for path */ -char ToLongName[NAME_MAX + 2]; /* Name of maximum +1 length */ -char ToLongPath[PATH_MAX + 1]; /* Same for path, both too long */ +int sigarray[SIGS] = {SIGHUP, SIGILL, SIGTRAP, SIGABRT, SIGIOT, SIGUNUSED, + SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, + SIGTERM}; -_PROTOTYPE(void main, (int argc, char *argv[])); +/* Prototypes produced automatically by mkptypes. */ +_PROTOTYPE(int main, (int argc, char *argv [])); _PROTOTYPE(void test37a, (void)); +_PROTOTYPE(void func1, (int sig)); +_PROTOTYPE(void func2, (int sig)); _PROTOTYPE(void test37b, (void)); -_PROTOTYPE(void e, (int number)); +_PROTOTYPE(void catch1, (int signo)); +_PROTOTYPE(void catch2, (int signo)); +_PROTOTYPE(void test37c, (void)); +_PROTOTYPE(void catch3, (int signo)); +_PROTOTYPE(void test37d, (void)); +_PROTOTYPE(void catch4, (int signo)); +_PROTOTYPE(void test37e, (void)); +_PROTOTYPE(void catch5, (int signo)); +_PROTOTYPE(void test37f, (void)); +_PROTOTYPE(void sigint_handler, (int signo)); +_PROTOTYPE(void sigpipe_handler, (int signo)); +_PROTOTYPE(void test37g, (void)); +_PROTOTYPE(void sighup8, (int signo)); +_PROTOTYPE(void sigpip8, (int signo)); +_PROTOTYPE(void sigter8, (int signo)); +_PROTOTYPE(void test37h, (void)); +_PROTOTYPE(void sighup9, (int signo)); +_PROTOTYPE(void sigter9, (int signo)); +_PROTOTYPE(void test37i, (void)); +_PROTOTYPE(void sighup10, (int signo)); +_PROTOTYPE(void sigalrm_handler10, (int signo)); +_PROTOTYPE(void test37j, (void)); +_PROTOTYPE(void test37k, (void)); +_PROTOTYPE(void test37l, (void)); +_PROTOTYPE(void func_m1, (void)); +_PROTOTYPE(void func_m2, (void)); +_PROTOTYPE(void test37m, (void)); +_PROTOTYPE(void longjerr, (void)); +_PROTOTYPE(void catch14, (int signo, int code, struct sigcontext * scp)); +_PROTOTYPE(void test37n, (void)); +_PROTOTYPE(void catch15, (int signo)); +_PROTOTYPE(void test37o, (void)); +_PROTOTYPE(void clearsigstate, (void)); _PROTOTYPE(void quit, (void)); +_PROTOTYPE(void wait_for, (int pid)); +_PROTOTYPE(void e, (int n)); -void main(argc, argv) +int main(argc, argv) int argc; char *argv[]; { int i, m = 0xFFFF; sync(); + if (argc == 2) m = atoi(argv[1]); + printf("Test 37 "); - fflush(stdout); + fflush(stdout); /* have to flush for child's benefit */ + + system("rm -rf DIR_37; mkdir DIR_37"); + chdir("DIR_37"); for (i = 0; i < ITERATIONS; i++) { - if (m & 0001) test37a(); - if (m & 0002) test37b(); + iteration = i; + if (m & 0000001) test37a(); + if (m & 0000002) test37b(); + if (m & 0000004) test37c(); + if (m & 0000010) test37d(); + if (m & 0000020) test37e(); + if (m & 0000040) test37f(); + if (m & 0000100) test37g(); + if (m & 0000200) test37h(); + if (m & 0000400) test37i(); + if (m & 0001000) test37j(); + if (m & 0002000) test37k(); + if (m & 0004000) test37l(); + if (m & 0010000) test37m(); + if (m & 0020000) test37n(); + if (m & 0040000) test37o(); } + quit(); + return(-1); /* impossible */ } void test37a() -{ /* Test fcntl flags. */ - int tube[2], t1[2], t2[2], t3[2]; - time_t time1, time2; - char buf[128]; - struct stat st1, st2; - int stat_loc, flags; +{ +/* Test signal set management. */ + + sigset_t s; subtest = 1; + clearsigstate(); - /* Check if lowest fds are returned. */ - if (pipe(tube) != 0) e(1); - if (tube[0] != 3 && tube[1] != 3) e(2); - if (tube[1] != 4 && tube[0] != 4) e(3); - if (tube[1] == tube[0]) e(4); - if (pipe(t1) != 0) e(5); - if (t1[0] != 5 && t1[1] != 5) e(6); - if (t1[1] != 6 && t1[0] != 6) e(7); - if (t1[1] == t1[0]) e(8); - if (close(t1[0]) != 0) e(9); - if (close(tube[0]) != 0) e(10); - if (pipe(t2) != 0) e(11); - if (t2[0] != tube[0] && t2[1] != tube[0]) e(12); - if (t2[1] != t1[0] && t2[0] != t1[0]) e(13); - if (t2[1] == t2[0]) e(14); - if (pipe(t3) != 0) e(15); - if (t3[0] != 7 && t3[1] != 7) e(16); - if (t3[1] != 8 && t3[0] != 8) e(17); - if (t3[1] == t3[0]) e(18); - if (close(tube[1]) != 0) e(19); - if (close(t1[1]) != 0) e(20); - if (close(t2[0]) != 0) e(21); - if (close(t2[1]) != 0) e(22); - if (close(t3[0]) != 0) e(23); - if (close(t3[1]) != 0) e(24); + /* Create an empty set and see if any bits are on. */ + if (sigemptyset(&s) != 0) e(1); + if (sigismember(&s, SIGHUP) != 0) e(2); + if (sigismember(&s, SIGINT) != 0) e(3); + if (sigismember(&s, SIGQUIT) != 0) e(4); + if (sigismember(&s, SIGILL) != 0) e(5); + if (sigismember(&s, SIGTRAP) != 0) e(6); + if (sigismember(&s, SIGABRT) != 0) e(7); + if (sigismember(&s, SIGIOT) != 0) e(8); + if (sigismember(&s, SIGUNUSED) != 0) e(9); + if (sigismember(&s, SIGFPE) != 0) e(10); + if (sigismember(&s, SIGKILL) != 0) e(11); + if (sigismember(&s, SIGUSR1) != 0) e(12); + if (sigismember(&s, SIGSEGV) != 0) e(13); + if (sigismember(&s, SIGUSR2) != 0) e(14); + if (sigismember(&s, SIGPIPE) != 0) e(15); + if (sigismember(&s, SIGALRM) != 0) e(16); + if (sigismember(&s, SIGTERM) != 0) e(17); - /* All time fields should be marked for update. */ - Time(&time1); - if (pipe(tube) != 0) e(25); - Fstat(tube[0], &st1); - Fstat(tube[1], &st2); - Time(&time2); - if (st1.st_atime < time1) e(26); - if (st1.st_ctime < time1) e(27); - if (st1.st_mtime < time1) e(28); - if (st1.st_atime > time2) e(29); - if (st1.st_ctime > time2) e(30); - if (st1.st_mtime > time2) e(31); - if (st2.st_atime < time1) e(32); - if (st2.st_ctime < time1) e(33); - if (st2.st_mtime < time1) e(34); - if (st2.st_atime > time2) e(35); - if (st2.st_ctime > time2) e(36); - if (st2.st_mtime > time2) e(37); + /* Create a full set and see if any bits are off. */ + if (sigfillset(&s) != 0) e(19); + if (sigemptyset(&s) != 0) e(20); + if (sigfillset(&s) != 0) e(21); + if (sigismember(&s, SIGHUP) != 1) e(22); + if (sigismember(&s, SIGINT) != 1) e(23); + if (sigismember(&s, SIGQUIT) != 1) e(24); + if (sigismember(&s, SIGILL) != 1) e(25); + if (sigismember(&s, SIGTRAP) != 1) e(26); + if (sigismember(&s, SIGABRT) != 1) e(27); + if (sigismember(&s, SIGIOT) != 1) e(28); + if (sigismember(&s, SIGUNUSED) != 1) e(29); + if (sigismember(&s, SIGFPE) != 1) e(30); + if (sigismember(&s, SIGKILL) != 1) e(31); + if (sigismember(&s, SIGUSR1) != 1) e(32); + if (sigismember(&s, SIGSEGV) != 1) e(33); + if (sigismember(&s, SIGUSR2) != 1) e(34); + if (sigismember(&s, SIGPIPE) != 1) e(35); + if (sigismember(&s, SIGALRM) != 1) e(36); + if (sigismember(&s, SIGTERM) != 1) e(37); - /* Check the file characteristics. */ - if ((flags = fcntl(tube[0], F_GETFD)) != 0) e(38); - if ((flags & FD_CLOEXEC) != 0) e(39); - if ((flags = fcntl(tube[0], F_GETFL)) != 0) e(40); - if ((flags & O_RDONLY) != O_RDONLY) e(41); - if ((flags & O_NONBLOCK) != 0) e(42); - if ((flags & O_RDWR) != 0) e(43); - if ((flags & O_WRONLY) != 0) e(44); + /* Create an empty set, then turn on bits individually. */ + if (sigemptyset(&s) != 0) e(39); + if (sigaddset(&s, SIGHUP) != 0) e(40); + if (sigaddset(&s, SIGINT) != 0) e(41); + if (sigaddset(&s, SIGQUIT) != 0) e(42); + if (sigaddset(&s, SIGILL) != 0) e(43); + if (sigaddset(&s, SIGTRAP) != 0) e(44); - if ((flags = fcntl(tube[1], F_GETFD)) != 0) e(45); - if ((flags & FD_CLOEXEC) != 0) e(46); - if ((flags = fcntl(tube[1], F_GETFL)) == -1) e(47); - if ((flags & O_WRONLY) != O_WRONLY) e(48); - if ((flags & O_NONBLOCK) != 0) e(49); - if ((flags & O_RDWR) != 0) e(50); - if ((flags & O_RDONLY) != 0) e(51); + /* See if the bits just turned on are indeed on. */ + if (sigismember(&s, SIGHUP) != 1) e(45); + if (sigismember(&s, SIGINT) != 1) e(46); + if (sigismember(&s, SIGQUIT) != 1) e(47); + if (sigismember(&s, SIGILL) != 1) e(48); + if (sigismember(&s, SIGTRAP) != 1) e(49); - /* Check if we can read and write. */ - switch (fork()) { - case -1: printf("Can't fork\n"); break; - case 0: - alarm(20); - if (close(tube[0]) != 0) e(52); - if (write(tube[1], "Hello", 6) != 6) e(53); - if (close(tube[1]) != 0) e(54); - exit(0); - default: - if (read(tube[0], buf, sizeof(buf)) != 6) e(55); - if (strncmp(buf, "Hello", 6) != 0) e(56); - wait(&stat_loc); - if (stat_loc != 0) e(57); /* Alarm? */ - } - if (close(tube[0]) != 0) e(58); - if (close(tube[1]) != 0) e(59); + /* The others should be turned off. */ + if (sigismember(&s, SIGABRT) != 0) e(50); + if (sigismember(&s, SIGIOT) != 0) e(51); + if (sigismember(&s, SIGUNUSED) != 0) e(52); + if (sigismember(&s, SIGFPE) != 0) e(53); + if (sigismember(&s, SIGKILL) != 0) e(54); + if (sigismember(&s, SIGUSR1) != 0) e(55); + if (sigismember(&s, SIGSEGV) != 0) e(56); + if (sigismember(&s, SIGUSR2) != 0) e(57); + if (sigismember(&s, SIGPIPE) != 0) e(58); + if (sigismember(&s, SIGALRM) != 0) e(59); + if (sigismember(&s, SIGTERM) != 0) e(60); + + /* Now turn them off and see if all are off. */ + if (sigdelset(&s, SIGHUP) != 0) e(62); + if (sigdelset(&s, SIGINT) != 0) e(63); + if (sigdelset(&s, SIGQUIT) != 0) e(64); + if (sigdelset(&s, SIGILL) != 0) e(65); + if (sigdelset(&s, SIGTRAP) != 0) e(66); + + if (sigismember(&s, SIGHUP) != 0) e(67); + if (sigismember(&s, SIGINT) != 0) e(68); + if (sigismember(&s, SIGQUIT) != 0) e(69); + if (sigismember(&s, SIGILL) != 0) e(70); + if (sigismember(&s, SIGTRAP) != 0) e(71); + if (sigismember(&s, SIGABRT) != 0) e(72); + if (sigismember(&s, SIGIOT) != 0) e(73); + if (sigismember(&s, SIGUNUSED) != 0) e(74); + if (sigismember(&s, SIGFPE) != 0) e(75); + if (sigismember(&s, SIGKILL) != 0) e(76); + if (sigismember(&s, SIGUSR1) != 0) e(77); + if (sigismember(&s, SIGSEGV) != 0) e(78); + if (sigismember(&s, SIGUSR2) != 0) e(79); + if (sigismember(&s, SIGPIPE) != 0) e(80); + if (sigismember(&s, SIGALRM) != 0) e(81); + if (sigismember(&s, SIGTERM) != 0) e(82); +} + +void func1(sig) +int sig; +{ + sig1++; +} + +void func2(sig) +int sig; +{ + sig2++; } void test37b() { - int tube[2], child2parent[2], parent2child[2]; - int i, nchild = 0, nopen = 3, stat_loc; - int fd; - int forkfailed = 0; - char c; +/* Test sigprocmask and sigpending. */ + int i; + pid_t p; + sigset_t s, s1, s_empty, s_full, s_ill, s_ill_pip, s_nokill; + struct sigaction sa, osa; subtest = 2; + clearsigstate(); - /* Take all the pipes we can get. */ - while (nopen < OPEN_MAX - 2) { - if (pipe(tube) != 0) { - /* We have not reached OPEN_MAX yet, so we have ENFILE. */ - if (errno != ENFILE) e(1); - sleep(2); /* Wait for others to (maybe) closefiles. */ - break; - } - nopen += 2; - } + /* Construct s_ill = {SIGILL} and s_ill_pip {SIGILL | SIGPIP}, etc. */ + if (sigemptyset(&s_empty) != 0) e(1); + if (sigemptyset(&s_ill) != 0) e(2); + if (sigemptyset(&s_ill_pip) != 0) e(3); + if (sigaddset(&s_ill, SIGILL) != 0) e(4); + if (sigaddset(&s_ill_pip, SIGILL) != 0) e(5); + if (sigaddset(&s_ill_pip, SIGPIPE) != 0) e(6); + if (sigfillset(&s_full) != 0) e(7); + s_nokill = s_full; + if (sigdelset(&s_nokill, SIGKILL) != 0) e(8); +#ifndef _MINIX /* XXX - should unsupported signals be <= _NSIG? */ + if (SIGSTOP > _NSIG) e(666); + if (SIGSTOP <= _NSIG && sigdelset(&s_nokill, SIGSTOP) != 0) e(888); +#endif /* _MINIX */ - if (nopen < OPEN_MAX - 2) { - if (pipe(tube) != -1) e(2); - switch (errno) { - case EMFILE: /* Errno value is ok. */ - break; - case ENFILE: /* No process can open files any more. */ - switch (fork()) { - case -1: - printf("Can't fork\n"); - break; - case 0: - alarm(20); - if (open("/", O_RDONLY) != -1) e(3); - if (errno != ENFILE) e(4); - exit(0); - default: - wait(&stat_loc); - if (stat_loc != 0) e(5); /* Alarm? */ - } - break; - default: /* Wrong value for errno. */ - e(6); - } - } + /* Now get most of the signals into default state. Don't change SIGINT + * or SIGQUIT, so this program can be killed. SIGKILL is also special. + */ + sa.sa_handler = SIG_DFL; + sa.sa_mask = s_empty; + sa.sa_flags = 0; + for (i = 0; i < SIGS; i++) sigaction(i, &sa, &osa); - /* Close all but stdin,out,err. */ - for (i = 3; i < OPEN_MAX; i++) (void) close(i); + /* The second argument may be zero. See if it wipes out the system. */ + for (i = 0; i < SIGS; i++) sigaction(i, (struct sigaction *) NULL, &osa); - /* ENFILE test. Have children each grab OPEN_MAX fds. */ - if (pipe(child2parent) != 0) e(7); - if (pipe(parent2child) != 0) e(8); - while (!forkfailed && (fd = open("/", O_RDONLY)) != -1) { - close(fd); - switch (fork()) { - case -1: - forkfailed = 1; - break; - case 0: - alarm(60); + /* Install a signal handler. */ + sa.sa_handler = func1; + sa.sa_mask = s_ill; + sa.sa_flags = SA_NODEFER | SA_NOCLDSTOP; + osa.sa_handler = SIG_IGN; + osa.sa_mask = s_empty; + osa.sa_flags = 0; + if (sigaction(SIGHUP, &sa, &osa) != 0) e(9); + if (osa.sa_handler != SIG_DFL) e(10); + if (osa.sa_mask != 0) e(11); + if (osa.sa_flags != s_empty) e(12); - /* Grab all the fds. */ - while (pipe(tube) != -1); - while (open("/", O_RDONLY) != -1); + /* Replace action and see if old value is read back correctly. */ + sa.sa_handler = func2; + sa.sa_mask = s_ill_pip; + sa.sa_flags = SA_RESETHAND | SA_NODEFER; + osa.sa_handler = SIG_IGN; + osa.sa_mask = s_empty; + osa.sa_flags = 0; + if (sigaction(SIGHUP, &sa, &osa) != 0) e(13); + if (osa.sa_handler != func1) e(14); + if (osa.sa_mask != s_ill) e(15); + if (osa.sa_flags != SA_NODEFER + && osa.sa_flags != (SA_NODEFER | SA_NOCLDSTOP)) e(16); - /* Signal parent OPEN_MAX fds gone. */ - if (write(child2parent[1], "*", 1) != 1) e(9); + /* Replace action once more and check what is read back. */ + sa.sa_handler = SIG_DFL; + sa.sa_mask = s_empty; + osa.sa_handler = SIG_IGN; + osa.sa_mask = s_empty; + osa.sa_flags = 0; + if (sigaction(SIGHUP, &sa, &osa) != 0) e(17); + if (osa.sa_handler != func2) e(18); + if (osa.sa_mask != s_ill_pip) e(19); + if (osa.sa_flags != (SA_RESETHAND | SA_NODEFER)) e(20); - /* Wait for parent befor freeing all the fds. */ - if (read(parent2child[0], &c, 1) != 1) e(10); - exit(0); - default: + /* Test sigprocmask(SIG_SETMASK, ...). */ + if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(18); /* block all */ + if (sigemptyset(&s1) != 0) e(19); + if (sigprocmask(SIG_SETMASK, &s_empty, &s1) != 0) e(20); /* block none */ + if (s1 != s_nokill) e(21); + if (sigprocmask(SIG_SETMASK, &s_ill, &s1) != 0) e(22); /* block SIGILL */ + if (s1 != s_empty) e(23); + if (sigprocmask(SIG_SETMASK, &s_ill_pip, &s1) != 0) e(24); /* SIGILL+PIP */ + if (s1 != s_ill) e(25); + if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(26); /* block all */ + if (s1 != s_ill_pip) e(27); - /* Wait for child to grab OPEN_MAX fds. */ - if (read(child2parent[0], &c, 1) != 1) e(11); - nchild++; - break; - } - } + /* Test sigprocmask(SIG_UNBLOCK, ...) */ + if (sigprocmask(SIG_UNBLOCK, &s_ill, &s1) != 0) e(28); + if (s1 != s_nokill) e(29); + if (sigprocmask(SIG_UNBLOCK, &s_ill_pip, &s1) != 0) e(30); + s = s_nokill; + if (sigdelset(&s, SIGILL) != 0) e(31); + if (s != s1) e(32); + if (sigprocmask(SIG_UNBLOCK, &s_empty, &s1) != 0) e(33); + s = s_nokill; + if (sigdelset(&s, SIGILL) != 0) e(34); + if (sigdelset(&s, SIGPIPE) != 0) e(35); + if (s != s1) e(36); + s1 = s_nokill; + if (sigprocmask(SIG_SETMASK, &s_empty, &s1) != 0) e(37); + if (s != s1) e(38); - if (!forkfailed) { - if (pipe(tube) != -1) e(12); - if (errno != ENFILE) e(13); - } + /* Test sigprocmask(SIG_BLOCK, ...) */ + if (sigprocmask(SIG_BLOCK, &s_ill, &s1) != 0) e(39); + if (s1 != s_empty) e(40); + if (sigprocmask(SIG_BLOCK, &s_ill_pip, &s1) != 0) e(41); + if (s1 != s_ill) e(42); + if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(43); + if (s1 != s_ill_pip) e(44); - /* Signal children to die and wait for it. */ - while (nchild-- > 0) { - if (write(parent2child[1], "*", 1) != 1) e(14); - wait(&stat_loc); - if (stat_loc != 0) e(15); /* Alarm? */ - } + /* Check error condition. */ + errno = 0; + if (sigprocmask(20000, &s_full, &s1) != -1) e(45); + if (errno != EINVAL) e(46); + if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(47); + if (s1 != s_nokill) e(48); - /* Close all but stdin,out,err. */ - for (i = 3; i < OPEN_MAX; i++) (void) close(i); + /* If second arg is 0, nothing is set. */ + if (sigprocmask(SIG_SETMASK, (sigset_t *) NULL, &s1) != 0) e(49); + if (s1 != s_nokill) e(50); + if (sigprocmask(SIG_SETMASK, &s_ill_pip, &s1) != 0) e(51); + if (s1 != s_nokill) e(52); + if (sigprocmask(SIG_SETMASK, (sigset_t *) NULL, &s1) != 0) e(53); + if (s1 != s_ill_pip) e(54); + if (sigprocmask(SIG_BLOCK, (sigset_t *) NULL, &s1) != 0) e(55); + if (s1 != s_ill_pip) e(56); + if (sigprocmask(SIG_UNBLOCK, (sigset_t *) NULL, &s1) != 0) e(57); + if (s1 != s_ill_pip) e(58); + + /* Trying to block SIGKILL is not allowed, but is not an error, either. */ + s = s_empty; + if (sigaddset(&s, SIGKILL) != 0) e(59); + if (sigprocmask(SIG_BLOCK, &s, &s1) != 0) e(60); + if (s1 != s_ill_pip) e(61); + if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(62); + if (s1 != s_ill_pip) e(63); + + /* Test sigpending. At this moment, all signals are blocked. */ + sa.sa_handler = func2; + sa.sa_mask = s_empty; + if (sigaction(SIGHUP, &sa, &osa) != 0) e(64); + p = getpid(); + kill(p, SIGHUP); /* send SIGHUP to self */ + if (sigpending(&s) != 0) e(65); + if (sigemptyset(&s1) != 0) e(66); + if (sigaddset(&s1, SIGHUP) != 0) e(67); + if (s != s1) e(68); + sa.sa_handler = SIG_IGN; + if (sigaction(SIGHUP, &sa, &osa) != 0) e(69); + if (sigpending(&s) != 0) e(70); + if (s != s_empty) e(71); } -void e(n) -int n; -{ - int err_num = errno; /* Save in case printf clobbers it. */ +/*---------------------------------------------------------------------------*/ +int x; +sigset_t glo_vol_set; - printf("Subtest %d, error %d errno=%d: ", subtest, n, errno); - errno = err_num; - perror(""); - if (errct++ > MAX_ERROR) { - printf("Too many errors; test aborted\n"); - chdir(".."); - system("rm -rf DIR*"); - exit(1); +void catch1(signo) +int signo; +{ + x = 42; +} + +void catch2(signo) +int signo; +{ + if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, (sigset_t *) &glo_vol_set) != 0) + e(1); +} + +/* Verify that signal(2), which is now built on top of sigaction(2), still +* works. +*/ +void test37c() +{ + pid_t pid; + sigset_t sigset_var; + + subtest = 3; + clearsigstate(); + x = 0; + + /* Verify an installed signal handler persists across a fork(2). */ + if (signal(SIGTERM, catch1) == SIG_ERR) e(1); + switch (pid = fork()) { + case 0: /* child */ + errct = 0; + while (x == 0); + if (x != 42) e(2); + exit(errct == 0 ? 0 : 1); + case -1: e(3); break; + default: /* parent */ + sleep(1); + if (kill(pid, SIGTERM) != 0) e(4); + wait_for(pid); + break; } - errno = 0; + + /* Verify that the return value is the previous handler. */ + signal(SIGINT, SIG_IGN); + if (signal(SIGINT, catch2) != SIG_IGN) e(5); + if (signal(SIGINT, catch1) != catch2) e(6); + if (signal(SIGINT, SIG_DFL) != catch1) e(7); + if (signal(SIGINT, catch1) != SIG_DFL) e(8); + if (signal(SIGINT, SIG_DFL) != catch1) e(9); + if (signal(SIGINT, SIG_DFL) != SIG_DFL) e(10); + if (signal(SIGINT, catch1) != SIG_DFL) e(11); + + /* Verify that SIG_ERR is correctly generated. */ + if (signal(_NSIG + 1, catch1) != SIG_ERR) e(12); + if (signal(0, catch1) != SIG_ERR) e(13); + if (signal(-1, SIG_DFL) != SIG_ERR) e(14); + + /* Verify that caught signals are automatically reset to the default, + * and that further instances of the same signal are not blocked here + * or in the signal handler. + */ + if (signal(SIGTERM, catch1) == SIG_ERR) e(15); + switch ((pid = fork())) { + case 0: /* child */ + errct = 0; + while (x == 0); + if (x != 42) e(16); + if (sigismember((sigset_t *) &glo_vol_set, SIGTERM)) e(17); + if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &sigset_var) != 0) e(18); + if (sigismember(&sigset_var, SIGTERM)) e(19); + +#if 0 +/* Use this if you have compiled signal() to have the broken SYSV behaviour. */ + if (signal(SIGTERM, catch1) != SIG_DFL) e(20); +#else + if (signal(SIGTERM, catch1) != catch1) e(20); +#endif + exit(errct == 0 ? 0 : 1); + default: /* parent */ + sleep(1); + if (kill(pid, SIGTERM) != 0) e(21); + wait_for(pid); + break; + case -1: e(22); break; + } +} + +/*---------------------------------------------------------------------------*/ +/* Test that the signal handler can be invoked recursively with the +* state being properly saved and restored. +*/ + +static int y; +static int z; + +void catch3(signo) +int signo; +{ + if (z == 1) { /* catching a nested signal */ + y = 2; + return; + } + z = 1; + if (kill(getpid(), SIGHUP) != 0) e(1); + while (y != 2); + y = 1; +} + +void test37d() +{ + struct sigaction act; + + subtest = 4; + clearsigstate(); + y = 0; + z = 0; + + act.sa_handler = catch3; + act.sa_mask = 0; + act.sa_flags = SA_NODEFER; /* Otherwise, nested occurence of + * SIGINT is blocked. */ + if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) != 0) e(2); + if (kill(getpid(), SIGHUP) != 0) e(3); + if (y != 1) e(4); +} + +/*---------------------------------------------------------------------------*/ + +/* Test that the signal mask in effect for the duration of a signal handler +* is as specified in POSIX Section 3, lines 718 -724. Test that the +* previous signal mask is restored when the signal handler returns. +*/ + +void catch4(signo) +int signo; +{ + sigset_t oset; + sigset_t set; + + if (sigemptyset(&set) == -1) e(5001); + if (sigaddset(&set, SIGTERM) == -1) e(5002); + if (sigaddset(&set, SIGHUP) == -1) e(5003); + if (sigaddset(&set, SIGINT) == -1) e(5004); + if (sigaddset(&set, SIGPIPE) == -1) e(5005); + if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &oset) != 0) e(5006); + if (oset != set) e(5007); +} + +void test37e() +{ + struct sigaction act, oact; + sigset_t set, oset; + + subtest = 5; + clearsigstate(); + + act.sa_handler = catch4; + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask, SIGTERM); + sigaddset(&act.sa_mask, SIGHUP); + act.sa_flags = 0; + if (sigaction(SIGINT, &act, &oact) == -1) e(2); + + if (sigemptyset(&set) == -1) e(3); + if (sigaddset(&set, SIGPIPE) == -1) e(4); + if (sigprocmask(SIG_SETMASK, &set, &oset) == -1) e(5); + if (kill(getpid(), SIGINT) == -1) e(6); + if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &oset) == -1) e(7); + if (sigemptyset(&set) == -1) e(8); + if (sigaddset(&set, SIGPIPE) == -1) e(9); + if (set != oset) e(10); +} + +/*---------------------------------------------------------------------------*/ + +/* Test the basic functionality of sigsuspend(2). */ + +void catch5(signo) +int signo; +{ + x = 1; +} + +void test37f() +{ + sigset_t set; + int r; + struct sigaction act; + pid_t pid; + + subtest = 6; + clearsigstate(); + + switch (pid = fork()) { + case 0: /* child */ + errct = 0; + sleep(1); + if (kill(getppid(), SIGINT) == -1) e(1); + exit(errct == 0 ? 0 : 1); + case -1: e(2); break; + default: /* parent */ + if (sigemptyset(&act.sa_mask) == -1) e(3); + act.sa_flags = 0; + act.sa_handler = catch5; + if (sigaction(SIGINT, &act, (struct sigaction *) NULL) == -1) e(4); + + if (sigemptyset(&set) == -1) e(5); + r = sigsuspend(&set); + + if (r != -1 || errno != EINTR || x != 1) e(6); + wait_for(pid); + break; + } +} + +/*----------------------------------------------------------------------*/ + +/* Test that sigsuspend() does block the signals specified in its +* argument, and after sigsuspend returns, the previous signal +* mask is restored. +* +* The child sends two signals to the parent SIGINT and then SIGPIPE, +* separated by a long delay. The parent executes sigsuspend() with +* SIGINT blocked. It is expected that the parent's SIGPIPE handler +* will be invoked, then sigsuspend will return restoring the +* original signal mask, and then the SIGPIPE handler will be +* invoked. +*/ + +void sigint_handler(signo) +int signo; +{ + x = 1; + z++; +} + +void sigpipe_handler(signo) +int signo; +{ + x = 2; + z++; +} + +void test37g() +{ + sigset_t set; + int r; + struct sigaction act; + pid_t pid; + + subtest = 7; + clearsigstate(); + x = 0; + z = 0; + + switch (pid = fork()) { + case 0: /* child */ + errct = 0; + sleep(1); + if (kill(getppid(), SIGINT) == -1) e(1); + sleep(1); + if (kill(getppid(), SIGPIPE) == -1) e(2); + exit(errct == 0 ? 0 : 1); + case -1: e(3); break; + default: /* parent */ + if (sigemptyset(&act.sa_mask) == -1) e(3); + act.sa_flags = 0; + act.sa_handler = sigint_handler; + if (sigaction(SIGINT, &act, (struct sigaction *) NULL) == -1) e(4); + + act.sa_handler = sigpipe_handler; + if (sigaction(SIGPIPE, &act, (struct sigaction *) NULL) == -1) e(5); + + if (sigemptyset(&set) == -1) e(6); + if (sigaddset(&set, SIGINT) == -1) e(7); + r = sigsuspend(&set); + if (r != -1) e(8); + if (errno != EINTR) e(9); + if (z != 2) e(10); + if (x != 1) e(11); + wait_for(pid); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +/* Test that sigsuspend() does block the signals specified in its +* argument, and after sigsuspend returns, the previous signal +* mask is restored. +* +* The child sends three signals to the parent: SIGHUP, then SIGPIPE, +* and then SIGTERM, separated by a long delay. The parent executes +* sigsuspend() with SIGHUP and SIGPIPE blocked. It is expected that +* the parent's SIGTERM handler will be invoked first, then sigsuspend() +* will return restoring the original signal mask, and then the other +* two handlers will be invoked. +*/ + +void sighup8(signo) +int signo; +{ + x = 1; + z++; +} + +void sigpip8(signo) +int signo; +{ + x = 1; + z++; +} + +void sigter8(signo) +int signo; +{ + x = 2; + z++; +} + +void test37h() +{ + sigset_t set; + int r; + struct sigaction act; + pid_t pid; + + subtest = 8; + clearsigstate(); + x = 0; + z = 0; + + switch (pid = fork()) { + case 0: /* child */ + errct = 0; + sleep(1); + if (kill(getppid(), SIGHUP) == -1) e(1); + sleep(1); + if (kill(getppid(), SIGPIPE) == -1) e(2); + sleep(1); + if (kill(getppid(), SIGTERM) == -1) e(3); + exit(errct == 0 ? 0 : 1); + case -1: e(5); break; + default: /* parent */ + if (sigemptyset(&act.sa_mask) == -1) e(6); + act.sa_flags = 0; + act.sa_handler = sighup8; + if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) == -1) e(7); + + act.sa_handler = sigpip8; + if (sigaction(SIGPIPE, &act, (struct sigaction *) NULL) == -1) e(8); + + act.sa_handler = sigter8; + if (sigaction(SIGTERM, &act, (struct sigaction *) NULL) == -1) e(9); + + if (sigemptyset(&set) == -1) e(10); + if (sigaddset(&set, SIGHUP) == -1) e(11); + if (sigaddset(&set, SIGPIPE) == -1) e(12); + r = sigsuspend(&set); + if (r != -1) e(13); + if (errno != EINTR) e(14); + if (z != 3) e(15); + if (x != 1) e(16); + wait_for(pid); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +/* Block SIGHUP and SIGTERM with sigprocmask(), send ourself SIGHUP +* and SIGTERM, unblock these signals with sigprocmask, and verify +* that these signals are delivered. +*/ + +void sighup9(signo) +int signo; +{ + y++; +} + +void sigter9(signo) +int signo; +{ + z++; +} + +void test37i() +{ + sigset_t set; + struct sigaction act; + + subtest = 9; + clearsigstate(); + y = 0; + z = 0; + + if (sigemptyset(&act.sa_mask) == -1) e(1); + act.sa_flags = 0; + + act.sa_handler = sighup9; + if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) == -1) e(2); + + act.sa_handler = sigter9; + if (sigaction(SIGTERM, &act, (struct sigaction *) NULL) == -1) e(3); + + if (sigemptyset(&set) == -1) e(4); + if (sigaddset(&set, SIGTERM) == -1) e(5); + if (sigaddset(&set, SIGHUP) == -1) e(6); + if (sigprocmask(SIG_SETMASK, &set, (sigset_t *)NULL) == -1) e(7); + + if (kill(getpid(), SIGHUP) == -1) e(8); + if (kill(getpid(), SIGTERM) == -1) e(9); + if (y != 0) e(10); + if (z != 0) e(11); + + if (sigemptyset(&set) == -1) e(12); + if (sigprocmask(SIG_SETMASK, &set, (sigset_t *)NULL) == -1) e(12); + if (y != 1) e(13); + if (z != 1) e(14); +} + +/*---------------------------------------------------------------------------*/ + +/* Block SIGINT and then send this signal to ourself. +* +* Install signal handlers for SIGALRM and SIGINT. +* +* Set an alarm for 6 seconds, then sleep for 7. +* +* The SIGALRM should interrupt the sleep, but the SIGINT +* should remain pending. +*/ + +void sighup10(signo) +int signo; +{ + y++; +} + +void sigalrm_handler10(signo) +int signo; +{ + z++; +} + +void test37j() +{ + sigset_t set, set2; + struct sigaction act; + + subtest = 10; + clearsigstate(); + y = 0; + z = 0; + + if (sigemptyset(&act.sa_mask) == -1) e(1); + act.sa_flags = 0; + + act.sa_handler = sighup10; + if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) == -1) e(2); + + act.sa_handler = sigalrm_handler10; + if (sigaction(SIGALRM, &act, (struct sigaction *) NULL) == -1) e(3); + + if (sigemptyset(&set) == -1) e(4); + if (sigaddset(&set, SIGHUP) == -1) e(5); + if (sigprocmask(SIG_SETMASK, &set, (sigset_t *)NULL) == -1) e(6); + + if (kill(getpid(), SIGHUP) == -1) e(7); + if (sigpending(&set) == -1) e(8); + if (sigemptyset(&set2) == -1) e(9); + if (sigaddset(&set2, SIGHUP) == -1) e(10); + if (set2 != set) e(11); + alarm(6); + sleep(7); + if (sigpending(&set) == -1) e(12); + if (set != set2) e(13); + if (y != 0) e(14); + if (z != 1) e(15); +} + +/*--------------------------------------------------------------------------*/ + +void test37k() +{ + subtest = 11; +} +void test37l() +{ + subtest = 12; +} + +/*---------------------------------------------------------------------------*/ + +/* Basic test for setjmp/longjmp. This includes testing that the +* signal mask is properly restored. +*/ + +void test37m() +{ + jmp_buf jb; + sigset_t ss; + + subtest = 13; + clearsigstate(); + + ss = 0x32; + if (sigprocmask(SIG_SETMASK, &ss, (sigset_t *)NULL) == -1) e(1); + if (setjmp(jb)) { + if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &ss) == -1) e(2); + if (ss != 0x32) e(388); + return; + } + ss = 0x3abc; + if (sigprocmask(SIG_SETMASK, &ss, (sigset_t *)NULL) == -1) e(4); + longjmp(jb, 1); +} + +void longjerr() +{ + e(5); +} + +/*--------------------------------------------------------------------------*/ + +/* Test for setjmp/longjmp. +* +* Catch a signal. While in signal handler do setjmp/longjmp. +*/ + +void catch14(signo, code, scp) +int signo; +int code; +struct sigcontext *scp; +{ + jmp_buf jb; + + if (setjmp(jb)) { + x++; + sigreturn(scp); + e(1); + } + y++; + longjmp(jb, 1); + e(2); +} + +void test37n() +{ + struct sigaction act; + typedef _PROTOTYPE( void (*sighandler_t), (int sig) ); + + subtest = 14; + clearsigstate(); + x = 0; + y = 0; + + act.sa_flags = 0; + act.sa_mask = 0; + act.sa_handler = (sighandler_t) catch14; /* fudge */ + if (sigaction(SIGSEGV, &act, (struct sigaction *) NULL) == -1) e(3); + if (kill(getpid(), SIGSEGV) == -1) e(4); + + if (x != 1) e(5); + if (y != 1) e(6); +} + +/*---------------------------------------------------------------------------*/ + +/* Test for setjmp/longjmp. + * + * Catch a signal. Longjmp out of signal handler. + */ +jmp_buf glo_jb; + +void catch15(signo) +int signo; +{ + z++; + longjmp(glo_jb, 7); + e(1); + +} + +void test37o() +{ + struct sigaction act; + int k; + + subtest = 15; + clearsigstate(); + z = 0; + + act.sa_flags = 0; + act.sa_mask = 0; + act.sa_handler = catch15; + if (sigaction(SIGALRM, &act, (struct sigaction *) NULL) == -1) e(2); + + if ((k = setjmp(glo_jb))) { + if (z != 1) e(399); + if (k != 7) e(4); + return; + } + if (kill(getpid(), SIGALRM) == -1) e(5); +} + +void clearsigstate() +{ + int i; + sigset_t sigset_var; + + /* Clear the signal state. */ + for (i = 1; i <= _NSIG; i++) signal(i, SIG_IGN); + for (i = 1; i <= _NSIG; i++) signal(i, SIG_DFL); + sigfillset(&sigset_var); + sigprocmask(SIG_UNBLOCK, &sigset_var, (sigset_t *)NULL); } void quit() { + + chdir(".."); + system("rm -rf DIR*"); + if (errct == 0) { printf("ok\n"); exit(0); } else { printf("%d errors\n", errct); + exit(4); + } +} + +void wait_for(pid) +pid_t pid; +{ +/* Expect exactly one child, and that it exits with 0. */ + + int r; + int status; + + errno = 0; + while (1) { + errno = 0; + r = wait(&status); + if (r == pid) { + errno = 0; + if (status != 0) e(90); + return; + } + if (r < 0) { + e(91); + return; + } + e(92); + } +} + +void e(n) +int n; +{ + char msgbuf[80]; + + sprintf(msgbuf, "Subtest %d, error %d errno=%d ", subtest, n, errno); + perror(msgbuf); + if (errct++ > MAX_ERROR) { + fprintf(stderr, "Too many errors; test aborted\n"); + chdir(".."); + system("rm -rf DIR*"); exit(1); } } diff --git a/test/test8.c b/test/test8.c index f16bdfef3..9eb215f20 100644 --- a/test/test8.c +++ b/test/test8.c @@ -1,1049 +1,265 @@ -/* test 8 - signals */ +/* test8: pipe() Author: Jan-Mark Wams (jms@cs.vu.nl) */ #include -#include -#ifdef _MINIX -#include -#endif +#include #include -#include -#include -#include #include #include +#include +#include +#include +#include +#include #include -#define ITERATIONS 2 -#define SIGS 14 -#define MAX_ERROR 4 +#define MAX_ERROR 4 +#define ITERATIONS 60 -int iteration, cumsig, subtest, errct = 0, sig1, sig2; +#define Fstat(a,b) if (fstat(a,b) != 0) printf("Can't fstat %d\n", a) +#define Time(t) if (time(t) == (time_t)-1) printf("Time error\n") -int sigarray[SIGS] = {SIGHUP, SIGILL, SIGTRAP, SIGABRT, SIGIOT, SIGUNUSED, - SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, - SIGTERM}; +int errct = 0; +int subtest = 1; +char MaxName[NAME_MAX + 1]; /* Name of maximum length */ +char MaxPath[PATH_MAX]; /* Same for path */ +char ToLongName[NAME_MAX + 2]; /* Name of maximum +1 length */ +char ToLongPath[PATH_MAX + 1]; /* Same for path, both too long */ -/* Prototypes produced automatically by mkptypes. */ -_PROTOTYPE(int main, (int argc, char *argv [])); +_PROTOTYPE(void main, (int argc, char *argv[])); _PROTOTYPE(void test8a, (void)); -_PROTOTYPE(void func1, (int sig)); -_PROTOTYPE(void func2, (int sig)); _PROTOTYPE(void test8b, (void)); -_PROTOTYPE(void catch1, (int signo)); -_PROTOTYPE(void catch2, (int signo)); -_PROTOTYPE(void test8c, (void)); -_PROTOTYPE(void catch3, (int signo)); -_PROTOTYPE(void test8d, (void)); -_PROTOTYPE(void catch4, (int signo)); -_PROTOTYPE(void test8e, (void)); -_PROTOTYPE(void catch5, (int signo)); -_PROTOTYPE(void test8f, (void)); -_PROTOTYPE(void sigint_handler, (int signo)); -_PROTOTYPE(void sigpipe_handler, (int signo)); -_PROTOTYPE(void test8g, (void)); -_PROTOTYPE(void sighup8, (int signo)); -_PROTOTYPE(void sigpip8, (int signo)); -_PROTOTYPE(void sigter8, (int signo)); -_PROTOTYPE(void test8h, (void)); -_PROTOTYPE(void sighup9, (int signo)); -_PROTOTYPE(void sigter9, (int signo)); -_PROTOTYPE(void test8i, (void)); -_PROTOTYPE(void sighup10, (int signo)); -_PROTOTYPE(void sigalrm_handler10, (int signo)); -_PROTOTYPE(void test8j, (void)); -_PROTOTYPE(void test8k, (void)); -_PROTOTYPE(void test8l, (void)); -_PROTOTYPE(void func_m1, (void)); -_PROTOTYPE(void func_m2, (void)); -_PROTOTYPE(void test8m, (void)); -_PROTOTYPE(void longjerr, (void)); -_PROTOTYPE(void catch14, (int signo, int code, struct sigcontext * scp)); -_PROTOTYPE(void test8n, (void)); -_PROTOTYPE(void catch15, (int signo)); -_PROTOTYPE(void test8o, (void)); -_PROTOTYPE(void clearsigstate, (void)); +_PROTOTYPE(void e, (int number)); _PROTOTYPE(void quit, (void)); -_PROTOTYPE(void wait_for, (int pid)); -_PROTOTYPE(void e, (int n)); -int main(argc, argv) +void main(argc, argv) int argc; char *argv[]; { int i, m = 0xFFFF; sync(); - if (argc == 2) m = atoi(argv[1]); - printf("Test 8 "); - fflush(stdout); /* have to flush for child's benefit */ - - system("rm -rf DIR_08; mkdir DIR_08"); - chdir("DIR_08"); + fflush(stdout); for (i = 0; i < ITERATIONS; i++) { - iteration = i; - if (m & 0000001) test8a(); - if (m & 0000002) test8b(); - if (m & 0000004) test8c(); - if (m & 0000010) test8d(); - if (m & 0000020) test8e(); - if (m & 0000040) test8f(); - if (m & 0000100) test8g(); - if (m & 0000200) test8h(); - if (m & 0000400) test8i(); - if (m & 0001000) test8j(); - if (m & 0002000) test8k(); - if (m & 0004000) test8l(); - if (m & 0010000) test8m(); - if (m & 0020000) test8n(); - if (m & 0040000) test8o(); + if (m & 0001) test8a(); + if (m & 0002) test8b(); } - quit(); - return(-1); /* impossible */ } void test8a() -{ -/* Test signal set management. */ - - sigset_t s; +{ /* Test fcntl flags. */ + int tube[2], t1[2], t2[2], t3[2]; + time_t time1, time2; + char buf[128]; + struct stat st1, st2; + int stat_loc, flags; subtest = 1; - clearsigstate(); - /* Create an empty set and see if any bits are on. */ - if (sigemptyset(&s) != 0) e(1); - if (sigismember(&s, SIGHUP) != 0) e(2); - if (sigismember(&s, SIGINT) != 0) e(3); - if (sigismember(&s, SIGQUIT) != 0) e(4); - if (sigismember(&s, SIGILL) != 0) e(5); - if (sigismember(&s, SIGTRAP) != 0) e(6); - if (sigismember(&s, SIGABRT) != 0) e(7); - if (sigismember(&s, SIGIOT) != 0) e(8); - if (sigismember(&s, SIGUNUSED) != 0) e(9); - if (sigismember(&s, SIGFPE) != 0) e(10); - if (sigismember(&s, SIGKILL) != 0) e(11); - if (sigismember(&s, SIGUSR1) != 0) e(12); - if (sigismember(&s, SIGSEGV) != 0) e(13); - if (sigismember(&s, SIGUSR2) != 0) e(14); - if (sigismember(&s, SIGPIPE) != 0) e(15); - if (sigismember(&s, SIGALRM) != 0) e(16); - if (sigismember(&s, SIGTERM) != 0) e(17); + /* Check if lowest fds are returned. */ + if (pipe(tube) != 0) e(1); + if (tube[0] != 3 && tube[1] != 3) e(2); + if (tube[1] != 4 && tube[0] != 4) e(3); + if (tube[1] == tube[0]) e(4); + if (pipe(t1) != 0) e(5); + if (t1[0] != 5 && t1[1] != 5) e(6); + if (t1[1] != 6 && t1[0] != 6) e(7); + if (t1[1] == t1[0]) e(8); + if (close(t1[0]) != 0) e(9); + if (close(tube[0]) != 0) e(10); + if (pipe(t2) != 0) e(11); + if (t2[0] != tube[0] && t2[1] != tube[0]) e(12); + if (t2[1] != t1[0] && t2[0] != t1[0]) e(13); + if (t2[1] == t2[0]) e(14); + if (pipe(t3) != 0) e(15); + if (t3[0] != 7 && t3[1] != 7) e(16); + if (t3[1] != 8 && t3[0] != 8) e(17); + if (t3[1] == t3[0]) e(18); + if (close(tube[1]) != 0) e(19); + if (close(t1[1]) != 0) e(20); + if (close(t2[0]) != 0) e(21); + if (close(t2[1]) != 0) e(22); + if (close(t3[0]) != 0) e(23); + if (close(t3[1]) != 0) e(24); - /* Create a full set and see if any bits are off. */ - if (sigfillset(&s) != 0) e(19); - if (sigemptyset(&s) != 0) e(20); - if (sigfillset(&s) != 0) e(21); - if (sigismember(&s, SIGHUP) != 1) e(22); - if (sigismember(&s, SIGINT) != 1) e(23); - if (sigismember(&s, SIGQUIT) != 1) e(24); - if (sigismember(&s, SIGILL) != 1) e(25); - if (sigismember(&s, SIGTRAP) != 1) e(26); - if (sigismember(&s, SIGABRT) != 1) e(27); - if (sigismember(&s, SIGIOT) != 1) e(28); - if (sigismember(&s, SIGUNUSED) != 1) e(29); - if (sigismember(&s, SIGFPE) != 1) e(30); - if (sigismember(&s, SIGKILL) != 1) e(31); - if (sigismember(&s, SIGUSR1) != 1) e(32); - if (sigismember(&s, SIGSEGV) != 1) e(33); - if (sigismember(&s, SIGUSR2) != 1) e(34); - if (sigismember(&s, SIGPIPE) != 1) e(35); - if (sigismember(&s, SIGALRM) != 1) e(36); - if (sigismember(&s, SIGTERM) != 1) e(37); + /* All time fields should be marked for update. */ + Time(&time1); + if (pipe(tube) != 0) e(25); + Fstat(tube[0], &st1); + Fstat(tube[1], &st2); + Time(&time2); + if (st1.st_atime < time1) e(26); + if (st1.st_ctime < time1) e(27); + if (st1.st_mtime < time1) e(28); + if (st1.st_atime > time2) e(29); + if (st1.st_ctime > time2) e(30); + if (st1.st_mtime > time2) e(31); + if (st2.st_atime < time1) e(32); + if (st2.st_ctime < time1) e(33); + if (st2.st_mtime < time1) e(34); + if (st2.st_atime > time2) e(35); + if (st2.st_ctime > time2) e(36); + if (st2.st_mtime > time2) e(37); - /* Create an empty set, then turn on bits individually. */ - if (sigemptyset(&s) != 0) e(39); - if (sigaddset(&s, SIGHUP) != 0) e(40); - if (sigaddset(&s, SIGINT) != 0) e(41); - if (sigaddset(&s, SIGQUIT) != 0) e(42); - if (sigaddset(&s, SIGILL) != 0) e(43); - if (sigaddset(&s, SIGTRAP) != 0) e(44); + /* Check the file characteristics. */ + if ((flags = fcntl(tube[0], F_GETFD)) != 0) e(38); + if ((flags & FD_CLOEXEC) != 0) e(39); + if ((flags = fcntl(tube[0], F_GETFL)) != 0) e(40); + if ((flags & O_RDONLY) != O_RDONLY) e(41); + if ((flags & O_NONBLOCK) != 0) e(42); + if ((flags & O_RDWR) != 0) e(43); + if ((flags & O_WRONLY) != 0) e(44); - /* See if the bits just turned on are indeed on. */ - if (sigismember(&s, SIGHUP) != 1) e(45); - if (sigismember(&s, SIGINT) != 1) e(46); - if (sigismember(&s, SIGQUIT) != 1) e(47); - if (sigismember(&s, SIGILL) != 1) e(48); - if (sigismember(&s, SIGTRAP) != 1) e(49); + if ((flags = fcntl(tube[1], F_GETFD)) != 0) e(45); + if ((flags & FD_CLOEXEC) != 0) e(46); + if ((flags = fcntl(tube[1], F_GETFL)) == -1) e(47); + if ((flags & O_WRONLY) != O_WRONLY) e(48); + if ((flags & O_NONBLOCK) != 0) e(49); + if ((flags & O_RDWR) != 0) e(50); + if ((flags & O_RDONLY) != 0) e(51); - /* The others should be turned off. */ - if (sigismember(&s, SIGABRT) != 0) e(50); - if (sigismember(&s, SIGIOT) != 0) e(51); - if (sigismember(&s, SIGUNUSED) != 0) e(52); - if (sigismember(&s, SIGFPE) != 0) e(53); - if (sigismember(&s, SIGKILL) != 0) e(54); - if (sigismember(&s, SIGUSR1) != 0) e(55); - if (sigismember(&s, SIGSEGV) != 0) e(56); - if (sigismember(&s, SIGUSR2) != 0) e(57); - if (sigismember(&s, SIGPIPE) != 0) e(58); - if (sigismember(&s, SIGALRM) != 0) e(59); - if (sigismember(&s, SIGTERM) != 0) e(60); - - /* Now turn them off and see if all are off. */ - if (sigdelset(&s, SIGHUP) != 0) e(62); - if (sigdelset(&s, SIGINT) != 0) e(63); - if (sigdelset(&s, SIGQUIT) != 0) e(64); - if (sigdelset(&s, SIGILL) != 0) e(65); - if (sigdelset(&s, SIGTRAP) != 0) e(66); - - if (sigismember(&s, SIGHUP) != 0) e(67); - if (sigismember(&s, SIGINT) != 0) e(68); - if (sigismember(&s, SIGQUIT) != 0) e(69); - if (sigismember(&s, SIGILL) != 0) e(70); - if (sigismember(&s, SIGTRAP) != 0) e(71); - if (sigismember(&s, SIGABRT) != 0) e(72); - if (sigismember(&s, SIGIOT) != 0) e(73); - if (sigismember(&s, SIGUNUSED) != 0) e(74); - if (sigismember(&s, SIGFPE) != 0) e(75); - if (sigismember(&s, SIGKILL) != 0) e(76); - if (sigismember(&s, SIGUSR1) != 0) e(77); - if (sigismember(&s, SIGSEGV) != 0) e(78); - if (sigismember(&s, SIGUSR2) != 0) e(79); - if (sigismember(&s, SIGPIPE) != 0) e(80); - if (sigismember(&s, SIGALRM) != 0) e(81); - if (sigismember(&s, SIGTERM) != 0) e(82); -} - -void func1(sig) -int sig; -{ - sig1++; -} - -void func2(sig) -int sig; -{ - sig2++; + /* Check if we can read and write. */ + switch (fork()) { + case -1: printf("Can't fork\n"); break; + case 0: + alarm(20); + if (close(tube[0]) != 0) e(52); + if (write(tube[1], "Hello", 6) != 6) e(53); + if (close(tube[1]) != 0) e(54); + exit(0); + default: + if (read(tube[0], buf, sizeof(buf)) != 6) e(55); + if (strncmp(buf, "Hello", 6) != 0) e(56); + wait(&stat_loc); + if (stat_loc != 0) e(57); /* Alarm? */ + } + if (close(tube[0]) != 0) e(58); + if (close(tube[1]) != 0) e(59); } void test8b() { -/* Test sigprocmask and sigpending. */ - int i; - pid_t p; - sigset_t s, s1, s_empty, s_full, s_ill, s_ill_pip, s_nokill; - struct sigaction sa, osa; + int tube[2], child2parent[2], parent2child[2]; + int i, nchild = 0, nopen = 3, stat_loc; + int fd; + int forkfailed = 0; + char c; subtest = 2; - clearsigstate(); - /* Construct s_ill = {SIGILL} and s_ill_pip {SIGILL | SIGPIP}, etc. */ - if (sigemptyset(&s_empty) != 0) e(1); - if (sigemptyset(&s_ill) != 0) e(2); - if (sigemptyset(&s_ill_pip) != 0) e(3); - if (sigaddset(&s_ill, SIGILL) != 0) e(4); - if (sigaddset(&s_ill_pip, SIGILL) != 0) e(5); - if (sigaddset(&s_ill_pip, SIGPIPE) != 0) e(6); - if (sigfillset(&s_full) != 0) e(7); - s_nokill = s_full; - if (sigdelset(&s_nokill, SIGKILL) != 0) e(8); -#ifndef _MINIX /* XXX - should unsupported signals be <= _NSIG? */ - if (SIGSTOP > _NSIG) e(666); - if (SIGSTOP <= _NSIG && sigdelset(&s_nokill, SIGSTOP) != 0) e(888); -#endif /* _MINIX */ - - /* Now get most of the signals into default state. Don't change SIGINT - * or SIGQUIT, so this program can be killed. SIGKILL is also special. - */ - sa.sa_handler = SIG_DFL; - sa.sa_mask = s_empty; - sa.sa_flags = 0; - for (i = 0; i < SIGS; i++) sigaction(i, &sa, &osa); - - /* The second argument may be zero. See if it wipes out the system. */ - for (i = 0; i < SIGS; i++) sigaction(i, (struct sigaction *) NULL, &osa); - - /* Install a signal handler. */ - sa.sa_handler = func1; - sa.sa_mask = s_ill; - sa.sa_flags = SA_NODEFER | SA_NOCLDSTOP; - osa.sa_handler = SIG_IGN; - osa.sa_mask = s_empty; - osa.sa_flags = 0; - if (sigaction(SIGHUP, &sa, &osa) != 0) e(9); - if (osa.sa_handler != SIG_DFL) e(10); - if (osa.sa_mask != 0) e(11); - if (osa.sa_flags != s_empty) e(12); - - /* Replace action and see if old value is read back correctly. */ - sa.sa_handler = func2; - sa.sa_mask = s_ill_pip; - sa.sa_flags = SA_RESETHAND | SA_NODEFER; - osa.sa_handler = SIG_IGN; - osa.sa_mask = s_empty; - osa.sa_flags = 0; - if (sigaction(SIGHUP, &sa, &osa) != 0) e(13); - if (osa.sa_handler != func1) e(14); - if (osa.sa_mask != s_ill) e(15); - if (osa.sa_flags != SA_NODEFER - && osa.sa_flags != (SA_NODEFER | SA_NOCLDSTOP)) e(16); - - /* Replace action once more and check what is read back. */ - sa.sa_handler = SIG_DFL; - sa.sa_mask = s_empty; - osa.sa_handler = SIG_IGN; - osa.sa_mask = s_empty; - osa.sa_flags = 0; - if (sigaction(SIGHUP, &sa, &osa) != 0) e(17); - if (osa.sa_handler != func2) e(18); - if (osa.sa_mask != s_ill_pip) e(19); - if (osa.sa_flags != (SA_RESETHAND | SA_NODEFER)) e(20); - - /* Test sigprocmask(SIG_SETMASK, ...). */ - if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(18); /* block all */ - if (sigemptyset(&s1) != 0) e(19); - if (sigprocmask(SIG_SETMASK, &s_empty, &s1) != 0) e(20); /* block none */ - if (s1 != s_nokill) e(21); - if (sigprocmask(SIG_SETMASK, &s_ill, &s1) != 0) e(22); /* block SIGILL */ - if (s1 != s_empty) e(23); - if (sigprocmask(SIG_SETMASK, &s_ill_pip, &s1) != 0) e(24); /* SIGILL+PIP */ - if (s1 != s_ill) e(25); - if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(26); /* block all */ - if (s1 != s_ill_pip) e(27); - - /* Test sigprocmask(SIG_UNBLOCK, ...) */ - if (sigprocmask(SIG_UNBLOCK, &s_ill, &s1) != 0) e(28); - if (s1 != s_nokill) e(29); - if (sigprocmask(SIG_UNBLOCK, &s_ill_pip, &s1) != 0) e(30); - s = s_nokill; - if (sigdelset(&s, SIGILL) != 0) e(31); - if (s != s1) e(32); - if (sigprocmask(SIG_UNBLOCK, &s_empty, &s1) != 0) e(33); - s = s_nokill; - if (sigdelset(&s, SIGILL) != 0) e(34); - if (sigdelset(&s, SIGPIPE) != 0) e(35); - if (s != s1) e(36); - s1 = s_nokill; - if (sigprocmask(SIG_SETMASK, &s_empty, &s1) != 0) e(37); - if (s != s1) e(38); - - /* Test sigprocmask(SIG_BLOCK, ...) */ - if (sigprocmask(SIG_BLOCK, &s_ill, &s1) != 0) e(39); - if (s1 != s_empty) e(40); - if (sigprocmask(SIG_BLOCK, &s_ill_pip, &s1) != 0) e(41); - if (s1 != s_ill) e(42); - if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(43); - if (s1 != s_ill_pip) e(44); - - /* Check error condition. */ - errno = 0; - if (sigprocmask(20000, &s_full, &s1) != -1) e(45); - if (errno != EINVAL) e(46); - if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(47); - if (s1 != s_nokill) e(48); - - /* If second arg is 0, nothing is set. */ - if (sigprocmask(SIG_SETMASK, (sigset_t *) NULL, &s1) != 0) e(49); - if (s1 != s_nokill) e(50); - if (sigprocmask(SIG_SETMASK, &s_ill_pip, &s1) != 0) e(51); - if (s1 != s_nokill) e(52); - if (sigprocmask(SIG_SETMASK, (sigset_t *) NULL, &s1) != 0) e(53); - if (s1 != s_ill_pip) e(54); - if (sigprocmask(SIG_BLOCK, (sigset_t *) NULL, &s1) != 0) e(55); - if (s1 != s_ill_pip) e(56); - if (sigprocmask(SIG_UNBLOCK, (sigset_t *) NULL, &s1) != 0) e(57); - if (s1 != s_ill_pip) e(58); - - /* Trying to block SIGKILL is not allowed, but is not an error, either. */ - s = s_empty; - if (sigaddset(&s, SIGKILL) != 0) e(59); - if (sigprocmask(SIG_BLOCK, &s, &s1) != 0) e(60); - if (s1 != s_ill_pip) e(61); - if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(62); - if (s1 != s_ill_pip) e(63); - - /* Test sigpending. At this moment, all signals are blocked. */ - sa.sa_handler = func2; - sa.sa_mask = s_empty; - if (sigaction(SIGHUP, &sa, &osa) != 0) e(64); - p = getpid(); - kill(p, SIGHUP); /* send SIGHUP to self */ - if (sigpending(&s) != 0) e(65); - if (sigemptyset(&s1) != 0) e(66); - if (sigaddset(&s1, SIGHUP) != 0) e(67); - if (s != s1) e(68); - sa.sa_handler = SIG_IGN; - if (sigaction(SIGHUP, &sa, &osa) != 0) e(69); - if (sigpending(&s) != 0) e(70); - if (s != s_empty) e(71); -} - -/*---------------------------------------------------------------------------*/ -int x; -sigset_t glo_vol_set; - -void catch1(signo) -int signo; -{ - x = 42; -} - -void catch2(signo) -int signo; -{ - if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, (sigset_t *) &glo_vol_set) != 0) - e(1); -} - -/* Verify that signal(2), which is now built on top of sigaction(2), still -* works. -*/ -void test8c() -{ - pid_t pid; - sigset_t sigset_var; - - subtest = 3; - clearsigstate(); - x = 0; - - /* Verify an installed signal handler persists across a fork(2). */ - if (signal(SIGTERM, catch1) == SIG_ERR) e(1); - switch (pid = fork()) { - case 0: /* child */ - errct = 0; - while (x == 0); - if (x != 42) e(2); - exit(errct == 0 ? 0 : 1); - case -1: e(3); break; - default: /* parent */ - sleep(1); - if (kill(pid, SIGTERM) != 0) e(4); - wait_for(pid); - break; - } - - /* Verify that the return value is the previous handler. */ - signal(SIGINT, SIG_IGN); - if (signal(SIGINT, catch2) != SIG_IGN) e(5); - if (signal(SIGINT, catch1) != catch2) e(6); - if (signal(SIGINT, SIG_DFL) != catch1) e(7); - if (signal(SIGINT, catch1) != SIG_DFL) e(8); - if (signal(SIGINT, SIG_DFL) != catch1) e(9); - if (signal(SIGINT, SIG_DFL) != SIG_DFL) e(10); - if (signal(SIGINT, catch1) != SIG_DFL) e(11); - - /* Verify that SIG_ERR is correctly generated. */ - if (signal(_NSIG + 1, catch1) != SIG_ERR) e(12); - if (signal(0, catch1) != SIG_ERR) e(13); - if (signal(-1, SIG_DFL) != SIG_ERR) e(14); - - /* Verify that caught signals are automatically reset to the default, - * and that further instances of the same signal are not blocked here - * or in the signal handler. - */ - if (signal(SIGTERM, catch1) == SIG_ERR) e(15); - switch ((pid = fork())) { - case 0: /* child */ - errct = 0; - while (x == 0); - if (x != 42) e(16); - if (sigismember((sigset_t *) &glo_vol_set, SIGTERM)) e(17); - if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &sigset_var) != 0) e(18); - if (sigismember(&sigset_var, SIGTERM)) e(19); - -#if 0 -/* Use this if you have compiled signal() to have the broken SYSV behaviour. */ - if (signal(SIGTERM, catch1) != SIG_DFL) e(20); -#else - if (signal(SIGTERM, catch1) != catch1) e(20); -#endif - exit(errct == 0 ? 0 : 1); - default: /* parent */ - sleep(1); - if (kill(pid, SIGTERM) != 0) e(21); - wait_for(pid); - break; - case -1: e(22); break; - } -} - -/*---------------------------------------------------------------------------*/ -/* Test that the signal handler can be invoked recursively with the -* state being properly saved and restored. -*/ - -static int y; -static int z; - -void catch3(signo) -int signo; -{ - if (z == 1) { /* catching a nested signal */ - y = 2; - return; - } - z = 1; - if (kill(getpid(), SIGHUP) != 0) e(1); - while (y != 2); - y = 1; -} - -void test8d() -{ - struct sigaction act; - - subtest = 4; - clearsigstate(); - y = 0; - z = 0; - - act.sa_handler = catch3; - act.sa_mask = 0; - act.sa_flags = SA_NODEFER; /* Otherwise, nested occurence of - * SIGINT is blocked. */ - if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) != 0) e(2); - if (kill(getpid(), SIGHUP) != 0) e(3); - if (y != 1) e(4); -} - -/*---------------------------------------------------------------------------*/ - -/* Test that the signal mask in effect for the duration of a signal handler -* is as specified in POSIX Section 3, lines 718 -724. Test that the -* previous signal mask is restored when the signal handler returns. -*/ - -void catch4(signo) -int signo; -{ - sigset_t oset; - sigset_t set; - - if (sigemptyset(&set) == -1) e(5001); - if (sigaddset(&set, SIGTERM) == -1) e(5002); - if (sigaddset(&set, SIGHUP) == -1) e(5003); - if (sigaddset(&set, SIGINT) == -1) e(5004); - if (sigaddset(&set, SIGPIPE) == -1) e(5005); - if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &oset) != 0) e(5006); - if (oset != set) e(5007); -} - -void test8e() -{ - struct sigaction act, oact; - sigset_t set, oset; - - subtest = 5; - clearsigstate(); - - act.sa_handler = catch4; - sigemptyset(&act.sa_mask); - sigaddset(&act.sa_mask, SIGTERM); - sigaddset(&act.sa_mask, SIGHUP); - act.sa_flags = 0; - if (sigaction(SIGINT, &act, &oact) == -1) e(2); - - if (sigemptyset(&set) == -1) e(3); - if (sigaddset(&set, SIGPIPE) == -1) e(4); - if (sigprocmask(SIG_SETMASK, &set, &oset) == -1) e(5); - if (kill(getpid(), SIGINT) == -1) e(6); - if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &oset) == -1) e(7); - if (sigemptyset(&set) == -1) e(8); - if (sigaddset(&set, SIGPIPE) == -1) e(9); - if (set != oset) e(10); -} - -/*---------------------------------------------------------------------------*/ - -/* Test the basic functionality of sigsuspend(2). */ - -void catch5(signo) -int signo; -{ - x = 1; -} - -void test8f() -{ - sigset_t set; - int r; - struct sigaction act; - pid_t pid; - - subtest = 6; - clearsigstate(); - - switch (pid = fork()) { - case 0: /* child */ - errct = 0; - sleep(1); - if (kill(getppid(), SIGINT) == -1) e(1); - exit(errct == 0 ? 0 : 1); - case -1: e(2); break; - default: /* parent */ - if (sigemptyset(&act.sa_mask) == -1) e(3); - act.sa_flags = 0; - act.sa_handler = catch5; - if (sigaction(SIGINT, &act, (struct sigaction *) NULL) == -1) e(4); - - if (sigemptyset(&set) == -1) e(5); - r = sigsuspend(&set); - - if (r != -1 || errno != EINTR || x != 1) e(6); - wait_for(pid); - break; - } -} - -/*----------------------------------------------------------------------*/ - -/* Test that sigsuspend() does block the signals specified in its -* argument, and after sigsuspend returns, the previous signal -* mask is restored. -* -* The child sends two signals to the parent SIGINT and then SIGPIPE, -* separated by a long delay. The parent executes sigsuspend() with -* SIGINT blocked. It is expected that the parent's SIGPIPE handler -* will be invoked, then sigsuspend will return restoring the -* original signal mask, and then the SIGPIPE handler will be -* invoked. -*/ - -void sigint_handler(signo) -int signo; -{ - x = 1; - z++; -} - -void sigpipe_handler(signo) -int signo; -{ - x = 2; - z++; -} - -void test8g() -{ - sigset_t set; - int r; - struct sigaction act; - pid_t pid; - - subtest = 7; - clearsigstate(); - x = 0; - z = 0; - - switch (pid = fork()) { - case 0: /* child */ - errct = 0; - sleep(1); - if (kill(getppid(), SIGINT) == -1) e(1); - sleep(1); - if (kill(getppid(), SIGPIPE) == -1) e(2); - exit(errct == 0 ? 0 : 1); - case -1: e(3); break; - default: /* parent */ - if (sigemptyset(&act.sa_mask) == -1) e(3); - act.sa_flags = 0; - act.sa_handler = sigint_handler; - if (sigaction(SIGINT, &act, (struct sigaction *) NULL) == -1) e(4); - - act.sa_handler = sigpipe_handler; - if (sigaction(SIGPIPE, &act, (struct sigaction *) NULL) == -1) e(5); - - if (sigemptyset(&set) == -1) e(6); - if (sigaddset(&set, SIGINT) == -1) e(7); - r = sigsuspend(&set); - if (r != -1) e(8); - if (errno != EINTR) e(9); - if (z != 2) e(10); - if (x != 1) e(11); - wait_for(pid); - break; - } -} - -/*--------------------------------------------------------------------------*/ - -/* Test that sigsuspend() does block the signals specified in its -* argument, and after sigsuspend returns, the previous signal -* mask is restored. -* -* The child sends three signals to the parent: SIGHUP, then SIGPIPE, -* and then SIGTERM, separated by a long delay. The parent executes -* sigsuspend() with SIGHUP and SIGPIPE blocked. It is expected that -* the parent's SIGTERM handler will be invoked first, then sigsuspend() -* will return restoring the original signal mask, and then the other -* two handlers will be invoked. -*/ - -void sighup8(signo) -int signo; -{ - x = 1; - z++; -} - -void sigpip8(signo) -int signo; -{ - x = 1; - z++; -} - -void sigter8(signo) -int signo; -{ - x = 2; - z++; -} - -void test8h() -{ - sigset_t set; - int r; - struct sigaction act; - pid_t pid; - - subtest = 8; - clearsigstate(); - x = 0; - z = 0; - - switch (pid = fork()) { - case 0: /* child */ - errct = 0; - sleep(1); - if (kill(getppid(), SIGHUP) == -1) e(1); - sleep(1); - if (kill(getppid(), SIGPIPE) == -1) e(2); - sleep(1); - if (kill(getppid(), SIGTERM) == -1) e(3); - exit(errct == 0 ? 0 : 1); - case -1: e(5); break; - default: /* parent */ - if (sigemptyset(&act.sa_mask) == -1) e(6); - act.sa_flags = 0; - act.sa_handler = sighup8; - if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) == -1) e(7); - - act.sa_handler = sigpip8; - if (sigaction(SIGPIPE, &act, (struct sigaction *) NULL) == -1) e(8); - - act.sa_handler = sigter8; - if (sigaction(SIGTERM, &act, (struct sigaction *) NULL) == -1) e(9); - - if (sigemptyset(&set) == -1) e(10); - if (sigaddset(&set, SIGHUP) == -1) e(11); - if (sigaddset(&set, SIGPIPE) == -1) e(12); - r = sigsuspend(&set); - if (r != -1) e(13); - if (errno != EINTR) e(14); - if (z != 3) e(15); - if (x != 1) e(16); - wait_for(pid); - break; - } -} - -/*--------------------------------------------------------------------------*/ - -/* Block SIGHUP and SIGTERM with sigprocmask(), send ourself SIGHUP -* and SIGTERM, unblock these signals with sigprocmask, and verify -* that these signals are delivered. -*/ - -void sighup9(signo) -int signo; -{ - y++; -} - -void sigter9(signo) -int signo; -{ - z++; -} - -void test8i() -{ - sigset_t set; - struct sigaction act; - - subtest = 9; - clearsigstate(); - y = 0; - z = 0; - - if (sigemptyset(&act.sa_mask) == -1) e(1); - act.sa_flags = 0; - - act.sa_handler = sighup9; - if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) == -1) e(2); - - act.sa_handler = sigter9; - if (sigaction(SIGTERM, &act, (struct sigaction *) NULL) == -1) e(3); - - if (sigemptyset(&set) == -1) e(4); - if (sigaddset(&set, SIGTERM) == -1) e(5); - if (sigaddset(&set, SIGHUP) == -1) e(6); - if (sigprocmask(SIG_SETMASK, &set, (sigset_t *)NULL) == -1) e(7); - - if (kill(getpid(), SIGHUP) == -1) e(8); - if (kill(getpid(), SIGTERM) == -1) e(9); - if (y != 0) e(10); - if (z != 0) e(11); - - if (sigemptyset(&set) == -1) e(12); - if (sigprocmask(SIG_SETMASK, &set, (sigset_t *)NULL) == -1) e(12); - if (y != 1) e(13); - if (z != 1) e(14); -} - -/*---------------------------------------------------------------------------*/ - -/* Block SIGINT and then send this signal to ourself. -* -* Install signal handlers for SIGALRM and SIGINT. -* -* Set an alarm for 6 seconds, then sleep for 7. -* -* The SIGALRM should interrupt the sleep, but the SIGINT -* should remain pending. -*/ - -void sighup10(signo) -int signo; -{ - y++; -} - -void sigalrm_handler10(signo) -int signo; -{ - z++; -} - -void test8j() -{ - sigset_t set, set2; - struct sigaction act; - - subtest = 10; - clearsigstate(); - y = 0; - z = 0; - - if (sigemptyset(&act.sa_mask) == -1) e(1); - act.sa_flags = 0; - - act.sa_handler = sighup10; - if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) == -1) e(2); - - act.sa_handler = sigalrm_handler10; - if (sigaction(SIGALRM, &act, (struct sigaction *) NULL) == -1) e(3); - - if (sigemptyset(&set) == -1) e(4); - if (sigaddset(&set, SIGHUP) == -1) e(5); - if (sigprocmask(SIG_SETMASK, &set, (sigset_t *)NULL) == -1) e(6); - - if (kill(getpid(), SIGHUP) == -1) e(7); - if (sigpending(&set) == -1) e(8); - if (sigemptyset(&set2) == -1) e(9); - if (sigaddset(&set2, SIGHUP) == -1) e(10); - if (set2 != set) e(11); - alarm(6); - sleep(7); - if (sigpending(&set) == -1) e(12); - if (set != set2) e(13); - if (y != 0) e(14); - if (z != 1) e(15); -} - -/*--------------------------------------------------------------------------*/ - -void test8k() -{ - subtest = 11; -} -void test8l() -{ - subtest = 12; -} - -/*---------------------------------------------------------------------------*/ - -/* Basic test for setjmp/longjmp. This includes testing that the -* signal mask is properly restored. -*/ - -void test8m() -{ - jmp_buf jb; - sigset_t ss; - - subtest = 13; - clearsigstate(); - - ss = 0x32; - if (sigprocmask(SIG_SETMASK, &ss, (sigset_t *)NULL) == -1) e(1); - if (setjmp(jb)) { - if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &ss) == -1) e(2); - if (ss != 0x32) e(388); - return; - } - ss = 0x3abc; - if (sigprocmask(SIG_SETMASK, &ss, (sigset_t *)NULL) == -1) e(4); - longjmp(jb, 1); -} - -void longjerr() -{ - e(5); -} - -/*--------------------------------------------------------------------------*/ - -/* Test for setjmp/longjmp. -* -* Catch a signal. While in signal handler do setjmp/longjmp. -*/ - -void catch14(signo, code, scp) -int signo; -int code; -struct sigcontext *scp; -{ - jmp_buf jb; - - if (setjmp(jb)) { - x++; - sigreturn(scp); - e(1); - } - y++; - longjmp(jb, 1); - e(2); -} - -void test8n() -{ - struct sigaction act; - typedef _PROTOTYPE( void (*sighandler_t), (int sig) ); - - subtest = 14; - clearsigstate(); - x = 0; - y = 0; - - act.sa_flags = 0; - act.sa_mask = 0; - act.sa_handler = (sighandler_t) catch14; /* fudge */ - if (sigaction(SIGSEGV, &act, (struct sigaction *) NULL) == -1) e(3); - if (kill(getpid(), SIGSEGV) == -1) e(4); - - if (x != 1) e(5); - if (y != 1) e(6); -} - -/*---------------------------------------------------------------------------*/ - -/* Test for setjmp/longjmp. - * - * Catch a signal. Longjmp out of signal handler. - */ -jmp_buf glo_jb; - -void catch15(signo) -int signo; -{ - z++; - longjmp(glo_jb, 7); - e(1); - -} - -void test8o() -{ - struct sigaction act; - int k; - - subtest = 15; - clearsigstate(); - z = 0; - - act.sa_flags = 0; - act.sa_mask = 0; - act.sa_handler = catch15; - if (sigaction(SIGALRM, &act, (struct sigaction *) NULL) == -1) e(2); - - if ((k = setjmp(glo_jb))) { - if (z != 1) e(399); - if (k != 7) e(4); - return; - } - if (kill(getpid(), SIGALRM) == -1) e(5); -} - -void clearsigstate() -{ - int i; - sigset_t sigset_var; - - /* Clear the signal state. */ - for (i = 1; i <= _NSIG; i++) signal(i, SIG_IGN); - for (i = 1; i <= _NSIG; i++) signal(i, SIG_DFL); - sigfillset(&sigset_var); - sigprocmask(SIG_UNBLOCK, &sigset_var, (sigset_t *)NULL); -} - -void quit() -{ - - chdir(".."); - system("rm -rf DIR*"); - - if (errct == 0) { - printf("ok\n"); - exit(0); - } else { - printf("%d errors\n", errct); - exit(4); - } -} - -void wait_for(pid) -pid_t pid; -{ -/* Expect exactly one child, and that it exits with 0. */ - - int r; - int status; - - errno = 0; - while (1) { - errno = 0; - r = wait(&status); - if (r == pid) { - errno = 0; - if (status != 0) e(90); - return; + /* Take all the pipes we can get. */ + while (nopen < OPEN_MAX - 2) { + if (pipe(tube) != 0) { + /* We have not reached OPEN_MAX yet, so we have ENFILE. */ + if (errno != ENFILE) e(1); + sleep(2); /* Wait for others to (maybe) closefiles. */ + break; } - if (r < 0) { - e(91); - return; - } - e(92); + nopen += 2; } + + if (nopen < OPEN_MAX - 2) { + if (pipe(tube) != -1) e(2); + switch (errno) { + case EMFILE: /* Errno value is ok. */ + break; + case ENFILE: /* No process can open files any more. */ + switch (fork()) { + case -1: + printf("Can't fork\n"); + break; + case 0: + alarm(20); + if (open("/", O_RDONLY) != -1) e(3); + if (errno != ENFILE) e(4); + exit(0); + default: + wait(&stat_loc); + if (stat_loc != 0) e(5); /* Alarm? */ + } + break; + default: /* Wrong value for errno. */ + e(6); + } + } + + /* Close all but stdin,out,err. */ + for (i = 3; i < OPEN_MAX; i++) (void) close(i); + + /* ENFILE test. Have children each grab OPEN_MAX fds. */ + if (pipe(child2parent) != 0) e(7); + if (pipe(parent2child) != 0) e(8); + while (!forkfailed && (fd = open("/", O_RDONLY)) != -1) { + close(fd); + switch (fork()) { + case -1: + forkfailed = 1; + break; + case 0: + alarm(60); + + /* Grab all the fds. */ + while (pipe(tube) != -1); + while (open("/", O_RDONLY) != -1); + + /* Signal parent OPEN_MAX fds gone. */ + if (write(child2parent[1], "*", 1) != 1) e(9); + + /* Wait for parent befor freeing all the fds. */ + if (read(parent2child[0], &c, 1) != 1) e(10); + exit(0); + default: + + /* Wait for child to grab OPEN_MAX fds. */ + if (read(child2parent[0], &c, 1) != 1) e(11); + nchild++; + break; + } + } + + if (!forkfailed) { + if (pipe(tube) != -1) e(12); + if (errno != ENFILE) e(13); + } + + /* Signal children to die and wait for it. */ + while (nchild-- > 0) { + if (write(parent2child[1], "*", 1) != 1) e(14); + wait(&stat_loc); + if (stat_loc != 0) e(15); /* Alarm? */ + } + + /* Close all but stdin,out,err. */ + for (i = 3; i < OPEN_MAX; i++) (void) close(i); } void e(n) int n; { - char msgbuf[80]; + int err_num = errno; /* Save in case printf clobbers it. */ - sprintf(msgbuf, "Subtest %d, error %d errno=%d ", subtest, n, errno); - perror(msgbuf); + printf("Subtest %d, error %d errno=%d: ", subtest, n, errno); + errno = err_num; + perror(""); if (errct++ > MAX_ERROR) { - fprintf(stderr, "Too many errors; test aborted\n"); + printf("Too many errors; test aborted\n"); chdir(".."); system("rm -rf DIR*"); exit(1); } + errno = 0; +} + +void quit() +{ + if (errct == 0) { + printf("ok\n"); + exit(0); + } else { + printf("%d errors\n", errct); + exit(1); + } }