xref: /openbsd-src/regress/lib/libpthread/setsockopt/3a/setsockopt3a.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: setsockopt3a.c,v 1.2 2010/01/03 23:02:34 fgsch Exp $	*/
2 /*
3  * Federico G. Schwindt <fgsch@openbsd.org>, 2009. Public Domain.
4  */
5 
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <err.h>
10 #include <fcntl.h>
11 #include <netdb.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include "test.h"
16 
17 static void
18 alarm_handler(int sig)
19 {
20 	_exit(NOTOK);
21 }
22 
23 int
24 check_timeout(int s, int sec, struct timeval *to)
25 {
26 	struct timeval t1, t2;
27 	struct timeval e, d;
28 	char buf[BUFSIZ];
29 
30 	ASSERT(signal(SIGALRM, alarm_handler) != SIG_ERR);
31 	CHECKe(alarm(sec));
32 	CHECKe(gettimeofday(&t1, NULL));
33 	ASSERT(read(s, &buf, sizeof(buf)) == -1);
34 	CHECKe(gettimeofday(&t2, NULL));
35 	ASSERT(errno == EAGAIN);
36 	timersub(&t2, &t1, &e);
37 	timersub(&e, to, &d);
38 	return ((d.tv_sec > 1 || (d.tv_usec / 1000) > 100) ? 1 : 0);
39 }
40 
41 static void *
42 sock_accept(void *arg)
43 {
44 	struct sockaddr_in sin;
45 	struct timeval to;
46 	int s, s2, s3;
47 
48 	CHECKe(s = strtol(arg, NULL, 10));
49 	bzero(&sin, sizeof(sin));
50 	sin.sin_family = AF_INET;
51 	sin.sin_len = sizeof(sin);
52 	sin.sin_port = htons(6543);
53 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
54 	CHECKe(connect(s, (struct sockaddr *)&sin, sizeof(sin)));
55 	to.tv_sec = 2;
56 	to.tv_usec = 0.5 * 1e6;
57 	CHECKr(check_timeout(s, 3, &to));
58 	CHECKe(s2 = dup(s));
59 	CHECKe(s3 = fcntl(s, F_DUPFD, s));
60 	CHECKr(check_timeout(s2, 3, &to));
61 	CHECKr(check_timeout(s3, 3, &to));
62 	return (NULL);
63 }
64 
65 int
66 main(int argc, char **argv)
67 {
68 	pthread_t accept_thread;
69 
70 	if (argc != 2)
71 		exit(NOTOK);
72 	CHECKr(pthread_create(&accept_thread, NULL, sock_accept, argv[1]));
73 	CHECKr(pthread_join(accept_thread, NULL));
74 	SUCCEED;
75 }
76