417 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			417 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* test 2 */
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <sys/times.h>
 | |
| #include <sys/wait.h>
 | |
| #include <errno.h>
 | |
| #include <signal.h>
 | |
| #include <stdlib.h>
 | |
| #include <unistd.h>
 | |
| #include <time.h>
 | |
| #include <stdio.h>
 | |
| 
 | |
| #define ITERATIONS 5
 | |
| #define MAX_ERROR 4
 | |
| 
 | |
| int is, array[4], parsigs, parcum, sigct, cumsig, errct, subtest;
 | |
| int iteration, kk = 0, errct = 0;
 | |
| char buf[2048];
 | |
| 
 | |
| _PROTOTYPE(int main, (int argc, char *argv []));
 | |
| _PROTOTYPE(void test2a, (void));
 | |
| _PROTOTYPE(void test2b, (void));
 | |
| _PROTOTYPE(void test2c, (void));
 | |
| _PROTOTYPE(void test2d, (void));
 | |
| _PROTOTYPE(void test2e, (void));
 | |
| _PROTOTYPE(void test2f, (void));
 | |
| _PROTOTYPE(void test2g, (void));
 | |
| _PROTOTYPE(void test2h, (void));
 | |
| _PROTOTYPE(void sigpip, (int s));
 | |
| _PROTOTYPE(void quit, (void));
 | |
| _PROTOTYPE(void e, (int n));
 | |
| 
 | |
| int main(argc, argv)
 | |
| int argc;
 | |
| char *argv[];
 | |
| {
 | |
|   int i, m = 0xFFFF;
 | |
| 
 | |
|   sync();
 | |
| 
 | |
|   if (argc == 2) m = atoi(argv[1]);
 | |
| 
 | |
|   printf("Test  2 ");
 | |
|   fflush(stdout);		/* have to flush for child's benefit */
 | |
| 
 | |
|   system("rm -rf DIR_02; mkdir DIR_02");
 | |
|   chdir("DIR_02");
 | |
| 
 | |
|   for (i = 0; i < ITERATIONS; i++) {
 | |
| 	iteration = i;
 | |
| 	if (m & 0001) test2a();
 | |
| 	if (m & 0002) test2b();
 | |
| 	if (m & 0004) test2c();
 | |
| 	if (m & 0010) test2d();
 | |
| 	if (m & 0020) test2e();
 | |
| 	if (m & 0040) test2f();
 | |
| 	if (m & 0100) test2g();
 | |
| 	if (m & 0200) test2h();
 | |
|   }
 | |
|   subtest = 100;
 | |
|   if (cumsig != ITERATIONS) e(101);
 | |
|   quit();
 | |
|   return(-1);			/* impossible */
 | |
| }
 | |
| 
 | |
| 
 | |
| void test2a()
 | |
| {
 | |
| /* Test pipes */
 | |
| 
 | |
|   int fd[2];
 | |
|   int n, i, j, q = 0;
 | |
| 
 | |
|   subtest = 1;
 | |
|   if (pipe(fd) < 0) {
 | |
| 	printf("pipe error.  errno= %d\n", errno);
 | |
| 	errct++;
 | |
| 	quit();
 | |
|   }
 | |
|   i = fork();
 | |
|   if (i < 0) {
 | |
| 	printf("fork failed\n");
 | |
| 	errct++;
 | |
| 	quit();
 | |
|   }
 | |
|   if (i != 0) {
 | |
| 	/* Parent code */
 | |
| 	close(fd[0]);
 | |
| 	for (i = 0; i < 2048; i++) buf[i] = i & 0377;
 | |
| 	for (q = 0; q < 8; q++) {
 | |
| 		if (write(fd[1], buf, 2048) < 0) {
 | |
| 			printf("write pipe err.  errno=%d\n", errno);
 | |
| 			errct++;
 | |
| 			quit();
 | |
| 		}
 | |
| 	}
 | |
| 	close(fd[1]);
 | |
| 	wait(&q);
 | |
| 	if (q != 256 * 58) {
 | |
| 		printf("wrong exit code %d\n", q);
 | |
| 		errct++;
 | |
| 		quit();
 | |
| 	}
 | |
|   } else {
 | |
| 	/* Child code */
 | |
| 	close(fd[1]);
 | |
| 	for (q = 0; q < 32; q++) {
 | |
| 		n = read(fd[0], buf, 512);
 | |
| 		if (n != 512) {
 | |
| 			printf("read yielded %d bytes, not 512\n", n);
 | |
| 			errct++;
 | |
| 			quit();
 | |
| 		}
 | |
| 		for (j = 0; j < n; j++)
 | |
| 			if ((buf[j] & 0377) != (kk & 0377)) {
 | |
| 				printf("wrong data: %d %d %d \n ", 
 | |
| 						j, buf[j] & 0377, kk & 0377);
 | |
| 			} else {
 | |
| 				kk++;
 | |
| 			}
 | |
| 	}
 | |
| 	exit(58);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void test2b()
 | |
| {
 | |
|   int fd[2], n;
 | |
|   char buf[4];
 | |
| 
 | |
|   subtest = 2;
 | |
|   sigct = 0;
 | |
|   signal(SIGPIPE, sigpip);
 | |
|   pipe(fd);
 | |
|   if (fork()) {
 | |
| 	/* Parent */
 | |
| 	close(fd[0]);
 | |
| 	while (sigct == 0) {
 | |
| 		write(fd[1], buf, 1);
 | |
| 	}
 | |
| 	wait(&n);
 | |
|   } else {
 | |
| 	/* Child */
 | |
| 	close(fd[0]);
 | |
| 	close(fd[1]);
 | |
| 	exit(0);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void test2c()
 | |
| {
 | |
|   int n;
 | |
| 
 | |
|   subtest = 3;
 | |
|   signal(SIGINT, SIG_DFL);
 | |
|   is = 0;
 | |
|   if ((array[is++] = fork()) > 0) {
 | |
| 	if ((array[is++] = fork()) > 0) {
 | |
| 		if ((array[is++] = fork()) > 0) {
 | |
| 			if ((array[is++] = fork()) > 0) {
 | |
| 				signal(SIGINT, SIG_IGN);
 | |
| 				kill(array[0], SIGINT);
 | |
| 				kill(array[1], SIGINT);
 | |
| 				kill(array[2], SIGINT);
 | |
| 				kill(array[3], SIGINT);
 | |
| 				wait(&n);
 | |
| 				wait(&n);
 | |
| 				wait(&n);
 | |
| 				wait(&n);
 | |
| 			} else {
 | |
| 				pause();
 | |
| 			}
 | |
| 		} else {
 | |
| 			pause();
 | |
| 		}
 | |
| 	} else {
 | |
| 		pause();
 | |
| 	}
 | |
|   } else {
 | |
| 	pause();
 | |
|   }
 | |
| }
 | |
| 
 | |
| void test2d()
 | |
| {
 | |
| 
 | |
|   int pid, stat_loc, s;
 | |
| 
 | |
|   /* Test waitpid. */
 | |
|   subtest = 4;
 | |
| 
 | |
|   /* Test waitpid(pid, arg2, 0) */
 | |
|   pid = fork();
 | |
|   if (pid < 0) e(1);
 | |
|   if (pid > 0) {
 | |
| 	/* Parent. */
 | |
| 	s = waitpid(pid, &stat_loc, 0);
 | |
| 	if (s != pid) e(2);
 | |
| 	if (WIFEXITED(stat_loc) == 0) e(3);
 | |
| 	if (WIFSIGNALED(stat_loc) != 0) e(4);
 | |
| 	if (WEXITSTATUS(stat_loc) != 22) e(5);
 | |
|   } else {
 | |
| 	/* Child */
 | |
| 	exit(22);
 | |
|   }
 | |
| 
 | |
|   /* Test waitpid(-1, arg2, 0) */
 | |
|   pid = fork();
 | |
|   if (pid < 0) e(6);
 | |
|   if (pid > 0) {
 | |
| 	/* Parent. */
 | |
| 	s = waitpid(-1, &stat_loc, 0);
 | |
| 	if (s != pid) e(7);
 | |
| 	if (WIFEXITED(stat_loc) == 0) e(8);
 | |
| 	if (WIFSIGNALED(stat_loc) != 0) e(9);
 | |
| 	if (WEXITSTATUS(stat_loc) != 33) e(10);
 | |
|   } else {
 | |
| 	/* Child */
 | |
| 	exit(33);
 | |
|   }
 | |
| 
 | |
|   /* Test waitpid(0, arg2, 0) */
 | |
|   pid = fork();
 | |
|   if (pid < 0) e(11);
 | |
|   if (pid > 0) {
 | |
| 	/* Parent. */
 | |
| 	s = waitpid(0, &stat_loc, 0);
 | |
| 	if (s != pid) e(12);
 | |
| 	if (WIFEXITED(stat_loc) == 0) e(13);
 | |
| 	if (WIFSIGNALED(stat_loc) != 0) e(14);
 | |
| 	if (WEXITSTATUS(stat_loc) != 44) e(15);
 | |
|   } else {
 | |
| 	/* Child */
 | |
| 	exit(44);
 | |
|   }
 | |
| 
 | |
|   /* Test waitpid(0, arg2, WNOHANG) */
 | |
|   signal(SIGTERM, SIG_DFL);
 | |
|   pid = fork();
 | |
|   if (pid < 0) e(16);
 | |
|   if (pid > 0) {
 | |
| 	/* Parent. */
 | |
| 	s = waitpid(0, &stat_loc, WNOHANG);
 | |
| 	if (s != 0) e(17);
 | |
| 	if (kill(pid, SIGTERM) != 0) e(18);
 | |
| 	if (waitpid(pid, &stat_loc, 0) != pid) e(19);
 | |
| 	if (WIFEXITED(stat_loc) != 0) e(20);
 | |
| 	if (WIFSIGNALED(stat_loc) == 0) e(21);
 | |
| 	if (WTERMSIG(stat_loc) != SIGTERM) e(22);
 | |
|   } else {
 | |
| 	/* Child */
 | |
| 	pause();
 | |
|   }
 | |
| 
 | |
|   /* Test some error conditions. */
 | |
|   errno = 9999;
 | |
|   if (waitpid(0, &stat_loc, 0) != -1) e(23);
 | |
|   if (errno != ECHILD) e(24);
 | |
|   errno = 9999;
 | |
|   if (waitpid(0, &stat_loc, WNOHANG) != -1) e(25);
 | |
|   if (errno != ECHILD) e(26);
 | |
| }
 | |
| 
 | |
| 
 | |
| void test2e()
 | |
| {
 | |
| 
 | |
|   int pid1, pid2, stat_loc, s;
 | |
| 
 | |
|   /* Test waitpid with two children. */
 | |
|   subtest = 5;
 | |
|   if (iteration > 1) return;		/* slow test, don't do it too much */
 | |
|   if ( (pid1 = fork())) {
 | |
| 	/* Parent. */
 | |
| 	if ( (pid2 = fork()) ) {
 | |
| 		/* Parent. Collect second child first. */
 | |
| 		s = waitpid(pid2, &stat_loc, 0);
 | |
| 		if (s != pid2) e(1);
 | |
| 		if (WIFEXITED(stat_loc) == 0) e(2);
 | |
| 		if (WIFSIGNALED(stat_loc) != 0) e(3);
 | |
| 		if (WEXITSTATUS(stat_loc) != 222) e(4);
 | |
| 
 | |
| 		/* Now collect first child. */
 | |
| 		s = waitpid(pid1, &stat_loc, 0);
 | |
| 		if (s != pid1) e(5);
 | |
| 		if (WIFEXITED(stat_loc) == 0) e(6);
 | |
| 		if (WIFSIGNALED(stat_loc) != 0) e(7);
 | |
| 		if (WEXITSTATUS(stat_loc) != 111) e(8);
 | |
| 	} else {
 | |
| 		/* Child 2. */
 | |
| 		sleep(2);		/* child 2 delays before exiting. */
 | |
| 		exit(222);
 | |
| 	}
 | |
|   } else {
 | |
| 	/* Child 1. */
 | |
| 	exit(111);			/* child 1 exits immediately */
 | |
|   }
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| void test2f()
 | |
| {
 | |
| /* test getpid, getppid, getuid, etc. */
 | |
| 
 | |
|   pid_t pid, pid1, ppid, cpid, stat_loc, err;
 | |
| 
 | |
|   subtest = 6;
 | |
|   errno = -2000;
 | |
|   err = 0;
 | |
|   pid = getpid();
 | |
|   if ( (pid1 = fork())) {
 | |
| 	/* Parent.  Do nothing. */
 | |
| 	if (wait(&stat_loc) != pid1) e(1);
 | |
| 	if (WEXITSTATUS(stat_loc) != (pid1 & 0377)) e(2);
 | |
|   } else {
 | |
| 	/* Child.  Get ppid. */
 | |
| 	cpid = getpid();
 | |
| 	ppid = getppid();
 | |
| 	if (ppid != pid) err = 3;
 | |
| 	if (cpid == ppid) err = 4;
 | |
| 	exit(cpid & 0377);
 | |
|   }
 | |
|   if (err != 0) e(err);
 | |
| }
 | |
| 
 | |
| void test2g()
 | |
| {
 | |
| /* test time(), times() */
 | |
| 
 | |
|   time_t t1, t2;
 | |
|   clock_t t3, t4;
 | |
|   struct tms tmsbuf;
 | |
| 
 | |
|   subtest = 7;
 | |
|   errno = -7000;
 | |
| 
 | |
|   /* First time(). */
 | |
|   t1 = -1;
 | |
|   t2 = -2;
 | |
|   t1 = time(&t2);
 | |
|   if (t1 < 650000000L) e(1);	/* 650000000 is Sept. 1990 */
 | |
|   if (t1 != t2) e(2);
 | |
|   t1 = -1;
 | |
|   t1 = time( (time_t *) NULL);
 | |
|   if (t1 < 650000000L) e(3);
 | |
|   t3 = times(&tmsbuf);
 | |
|   sleep(1);
 | |
|   t2 = time( (time_t *) NULL);
 | |
|   if (t2 < 0L) e(4);
 | |
|   if (t2 - t1 < 1) e(5);
 | |
| 
 | |
|   /* Now times(). */
 | |
|   t4 = times(&tmsbuf);
 | |
|   if ( t4 == (clock_t) -1) e(6);
 | |
|   if (t4 - t3 < CLOCKS_PER_SEC) e(7);
 | |
|   if (tmsbuf.tms_utime < 0) e(8);
 | |
|   if (tmsbuf.tms_stime < 0) e(9);
 | |
|   if (tmsbuf.tms_cutime < 0) e(10);
 | |
|   if (tmsbuf.tms_cstime < 0) e(11);
 | |
| }
 | |
| 
 | |
| void test2h()
 | |
| {
 | |
| /* Test getgroups(). */
 | |
| 
 | |
|   gid_t g[10];
 | |
| 
 | |
|   subtest = 8;
 | |
|   errno = -8000;
 | |
|   if (getgroups(10, g) != 0) e(1);
 | |
|   if (getgroups(1, g) != 0) e(2);
 | |
|   if (getgroups(0, g) != 0) e(3);
 | |
| }
 | |
| 
 | |
| 
 | |
| void sigpip(s)
 | |
| int s;				/* for ANSI */
 | |
| {
 | |
|   sigct++;
 | |
|   cumsig++;
 | |
| }
 | |
| 
 | |
| void quit()
 | |
| {
 | |
| 
 | |
|   chdir("..");
 | |
|   system("rm -rf DIR*");
 | |
| 
 | |
|   if (errct == 0) {
 | |
| 	printf("ok\n");
 | |
| 	exit(0);
 | |
|   } else {
 | |
| 	printf("%d errors\n", errct);
 | |
| 	exit(4);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void e(n)
 | |
| int n;
 | |
| {
 | |
|   int err_num = errno;		/* save errno in case printf clobbers it */
 | |
| 
 | |
|   printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
 | |
|   errno = err_num;		/* restore errno, just in case */
 | |
|   perror("");
 | |
|   if (errct++ > MAX_ERROR) {
 | |
| 	printf("Too many errors;  test aborted\n");
 | |
| 	chdir("..");
 | |
| 	system("rm -rf DIR*");
 | |
| 	exit(1);
 | |
|   }
 | |
| }
 | 
