1 #include <sys/types.h> 2 #include <sys/socket.h> 3 #include <sys/wait.h> 4 5 #include <arpa/inet.h> 6 #include <netinet/in.h> 7 8 #include <err.h> 9 #include <errno.h> 10 #include <signal.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <unistd.h> 15 16 static void 17 usage(const char *cmd) 18 { 19 fprintf(stderr, "%s -p port\n", cmd); 20 exit(1); 21 } 22 23 static void 24 connect_client(int port) 25 { 26 struct sockaddr_in in; 27 int s; 28 29 s = socket(AF_INET, SOCK_STREAM, 0); 30 if (s < 0) 31 err(1, "client socket failed"); 32 33 memset(&in, 0, sizeof(in)); 34 in.sin_family = AF_INET; 35 in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 36 in.sin_port = htons(port); 37 if (connect(s, (const struct sockaddr *)&in, sizeof(in)) < 0) 38 err(1, "connect failed"); 39 40 pause(); 41 exit(0); 42 } 43 44 int 45 main(int argc, char *argv[]) 46 { 47 struct sockaddr_in in; 48 int serv_s, s; 49 int opt, port, dummy, n, status, panic, ex; 50 pid_t pid; 51 52 ex = 1; 53 panic = 0; 54 55 port = 0; 56 while ((opt = getopt(argc, argv, "p:")) != -1) { 57 char *endptr; 58 59 switch (opt) { 60 case 'p': 61 port = strtol(optarg, &endptr, 0); 62 if (*endptr != '\0') 63 errx(1, "invalid -p"); 64 break; 65 66 default: 67 usage(argv[0]); 68 } 69 } 70 if (port <= 0) 71 usage(argv[0]); 72 73 serv_s = socket(AF_INET, SOCK_STREAM, 0); 74 if (serv_s < 0) 75 err(1, "socket failed"); 76 77 memset(&in, 0, sizeof(in)); 78 in.sin_family = AF_INET; 79 in.sin_port = htons(port); 80 if (bind(serv_s, (const struct sockaddr *)&in, sizeof(in)) < 0) 81 err(1, "bind failed"); 82 83 if (listen(serv_s, 0) < 0) 84 err(1, "listen failed"); 85 86 pid = fork(); 87 if (pid < 0) { 88 err(1, "fork failed"); 89 } else if (pid == 0) { 90 connect_client(port); 91 abort(); 92 } 93 94 s = accept4(serv_s, NULL, NULL, SOCK_NONBLOCK); 95 if (s < 0) { 96 warn("accept4 failed"); 97 goto done; 98 } 99 panic = 1; 100 101 n = read(s, &dummy, sizeof(dummy)); 102 if (n < 0) { 103 int error = errno; 104 105 if (error != EAGAIN) { 106 warnx("invaid errno %d", error); 107 goto done; 108 } 109 } else { 110 warnx("read works"); 111 goto done; 112 } 113 114 ex = 0; 115 panic = 0; 116 fprintf(stderr, "passed\n"); 117 done: 118 kill(pid, SIGKILL); 119 waitpid(pid, &status, 0); 120 if (panic) 121 abort(); 122 exit(ex); 123 } 124