1f08c3bdfSopenharmony_ci/******************************************************************************/ 2f08c3bdfSopenharmony_ci/* */ 3f08c3bdfSopenharmony_ci/* Copyright (c) International Business Machines Corp., 2005 */ 4f08c3bdfSopenharmony_ci/* */ 5f08c3bdfSopenharmony_ci/* This program is free software; you can redistribute it and/or modify */ 6f08c3bdfSopenharmony_ci/* it under the terms of the GNU General Public License as published by */ 7f08c3bdfSopenharmony_ci/* the Free Software Foundation; either version 2 of the License, or */ 8f08c3bdfSopenharmony_ci/* (at your option) any later version. */ 9f08c3bdfSopenharmony_ci/* */ 10f08c3bdfSopenharmony_ci/* This program is distributed in the hope that it will be useful, */ 11f08c3bdfSopenharmony_ci/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 12f08c3bdfSopenharmony_ci/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ 13f08c3bdfSopenharmony_ci/* the GNU General Public License for more details. */ 14f08c3bdfSopenharmony_ci/* */ 15f08c3bdfSopenharmony_ci/* You should have received a copy of the GNU General Public License */ 16f08c3bdfSopenharmony_ci/* along with this program; if not, write to the Free Software */ 17f08c3bdfSopenharmony_ci/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 18f08c3bdfSopenharmony_ci/* */ 19f08c3bdfSopenharmony_ci/******************************************************************************/ 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci/* 22f08c3bdfSopenharmony_ci * File: 23f08c3bdfSopenharmony_ci * ns-udpserver.c 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * Description: 26f08c3bdfSopenharmony_ci * This is UDP traffic server. 27f08c3bdfSopenharmony_ci * Received UDP datagram from a client, then send it to the client 28f08c3bdfSopenharmony_ci * 29f08c3bdfSopenharmony_ci * Author: 30f08c3bdfSopenharmony_ci * Mitsuru Chinen <mitch@jp.ibm.com> 31f08c3bdfSopenharmony_ci * 32f08c3bdfSopenharmony_ci * History: 33f08c3bdfSopenharmony_ci * Oct 19 2005 - Created (Mitsuru Chinen) 34f08c3bdfSopenharmony_ci *---------------------------------------------------------------------------*/ 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci#include "ns-traffic.h" 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci/* 39f08c3bdfSopenharmony_ci * Standard Include Files 40f08c3bdfSopenharmony_ci */ 41f08c3bdfSopenharmony_ci#include <stdio.h> 42f08c3bdfSopenharmony_ci#include <stdlib.h> 43f08c3bdfSopenharmony_ci#include <string.h> 44f08c3bdfSopenharmony_ci#include <errno.h> 45f08c3bdfSopenharmony_ci#include <fcntl.h> 46f08c3bdfSopenharmony_ci#include <netdb.h> 47f08c3bdfSopenharmony_ci#include <time.h> 48f08c3bdfSopenharmony_ci#include <unistd.h> 49f08c3bdfSopenharmony_ci#include <sys/select.h> 50f08c3bdfSopenharmony_ci#include <sys/socket.h> 51f08c3bdfSopenharmony_ci#include <sys/stat.h> 52f08c3bdfSopenharmony_ci#include <sys/types.h> 53f08c3bdfSopenharmony_ci#include <sys/wait.h> 54f08c3bdfSopenharmony_ci#include <netinet/in.h> 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci/* 57f08c3bdfSopenharmony_ci * Gloval variables 58f08c3bdfSopenharmony_ci */ 59f08c3bdfSopenharmony_cistruct sigaction handler; /* Behavior for a signal */ 60f08c3bdfSopenharmony_ciint catch_sighup; /* When catch the SIGHUP, set to non-zero */ 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci/* 63f08c3bdfSopenharmony_ci * Function: usage() 64f08c3bdfSopenharmony_ci * 65f08c3bdfSopenharmony_ci * Descripton: 66f08c3bdfSopenharmony_ci * Print the usage of this program. Then, terminate this program with 67f08c3bdfSopenharmony_ci * the specified exit value. 68f08c3bdfSopenharmony_ci * 69f08c3bdfSopenharmony_ci * Argument: 70f08c3bdfSopenharmony_ci * exit_value: exit value 71f08c3bdfSopenharmony_ci * 72f08c3bdfSopenharmony_ci * Return value: 73f08c3bdfSopenharmony_ci * This function does not return. 74f08c3bdfSopenharmony_ci */ 75f08c3bdfSopenharmony_civoid usage(char *program_name, int exit_value) 76f08c3bdfSopenharmony_ci{ 77f08c3bdfSopenharmony_ci FILE *stream = stdout; /* stream where the usage is output */ 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci if (exit_value == EXIT_FAILURE) 80f08c3bdfSopenharmony_ci stream = stderr; 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci fprintf(stream, "%s [OPTION]\n" 83f08c3bdfSopenharmony_ci "\t-f\tprotocol family\n" 84f08c3bdfSopenharmony_ci "\t\t 4 : IPv4\n" 85f08c3bdfSopenharmony_ci "\t\t 6 : IPv6\n" 86f08c3bdfSopenharmony_ci "\t-p\tport number\n" 87f08c3bdfSopenharmony_ci "\t\tthe port number specified by -p option would be the first port number\n" 88f08c3bdfSopenharmony_ci "\t-b\twork in the background\n" 89f08c3bdfSopenharmony_ci "\t-o\tfilename where the server infomation is outputted\n" 90f08c3bdfSopenharmony_ci "\t-d\twork in the debug mode\n" 91f08c3bdfSopenharmony_ci "\t-h\tdisplay this usage\n" 92f08c3bdfSopenharmony_ci "" "*) Server works till it receives SIGHUP\n", program_name); 93f08c3bdfSopenharmony_ci exit(exit_value); 94f08c3bdfSopenharmony_ci} 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci/* 97f08c3bdfSopenharmony_ci * Function: set_signal_flag() 98f08c3bdfSopenharmony_ci * 99f08c3bdfSopenharmony_ci * Description: 100f08c3bdfSopenharmony_ci * This function sets global variable according to the signal. 101f08c3bdfSopenharmony_ci * Once a signal is caught, the signal is ignored after that. 102f08c3bdfSopenharmony_ci * 103f08c3bdfSopenharmony_ci * Argument: 104f08c3bdfSopenharmony_ci * type: type of signal 105f08c3bdfSopenharmony_ci * 106f08c3bdfSopenharmony_ci * Return value: 107f08c3bdfSopenharmony_ci * None 108f08c3bdfSopenharmony_ci */ 109f08c3bdfSopenharmony_civoid set_signal_flag(int type) 110f08c3bdfSopenharmony_ci{ 111f08c3bdfSopenharmony_ci /* Set SIG_IGN against the caught signal */ 112f08c3bdfSopenharmony_ci handler.sa_handler = SIG_IGN; 113f08c3bdfSopenharmony_ci if (sigaction(type, &handler, NULL) < 0) 114f08c3bdfSopenharmony_ci fatal_error("sigaction()"); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci if (debug) 117f08c3bdfSopenharmony_ci fprintf(stderr, "Catch signal. type is %d\n", type); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci switch (type) { 120f08c3bdfSopenharmony_ci case SIGHUP: 121f08c3bdfSopenharmony_ci catch_sighup = 1; 122f08c3bdfSopenharmony_ci break; 123f08c3bdfSopenharmony_ci default: 124f08c3bdfSopenharmony_ci fprintf(stderr, "Unexpected signal (%d) is caught\n", type); 125f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 126f08c3bdfSopenharmony_ci } 127f08c3bdfSopenharmony_ci} 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci/* 130f08c3bdfSopenharmony_ci * Function: respond_to_client() 131f08c3bdfSopenharmony_ci * 132f08c3bdfSopenharmony_ci * Description: 133f08c3bdfSopenharmony_ci * Recieve the client data. Then, return the data to client. 134f08c3bdfSopenharmony_ci * 135f08c3bdfSopenharmony_ci * Argument: 136f08c3bdfSopenharmony_ci * sock_fd: socket file descriptor 137f08c3bdfSopenharmony_ci * 138f08c3bdfSopenharmony_ci * Return value: 139f08c3bdfSopenharmony_ci * None 140f08c3bdfSopenharmony_ci */ 141f08c3bdfSopenharmony_civoid respond_to_client(int sock_fd) 142f08c3bdfSopenharmony_ci{ 143f08c3bdfSopenharmony_ci char *msgbuf; /* Pointer to the message */ 144f08c3bdfSopenharmony_ci size_t msgbuf_size; /* size of msgbuf */ 145f08c3bdfSopenharmony_ci ssize_t msglen; /* the length of message */ 146f08c3bdfSopenharmony_ci socklen_t sock_optlen; /* size of the result parameter */ 147f08c3bdfSopenharmony_ci struct sockaddr_storage client_addr; /* address of a client */ 148f08c3bdfSopenharmony_ci socklen_t client_addr_len; /* length of `client_addr' */ 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci sock_optlen = sizeof(sock_optlen); 151f08c3bdfSopenharmony_ci if (getsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, 152f08c3bdfSopenharmony_ci &msgbuf_size, &sock_optlen) < 0) { 153f08c3bdfSopenharmony_ci perror("getsockopt()"); 154f08c3bdfSopenharmony_ci close(sock_fd); 155f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 156f08c3bdfSopenharmony_ci } 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_ci /* Allocate the memory for a message */ 159f08c3bdfSopenharmony_ci msgbuf = malloc(msgbuf_size + 1); 160f08c3bdfSopenharmony_ci if (msgbuf == NULL) { 161f08c3bdfSopenharmony_ci fprintf(stderr, "malloc() is failed.\n"); 162f08c3bdfSopenharmony_ci close(sock_fd); 163f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 164f08c3bdfSopenharmony_ci } 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_ci /* Receive a message */ 167f08c3bdfSopenharmony_ci client_addr_len = sizeof(client_addr); 168f08c3bdfSopenharmony_ci if ((msglen = recvfrom(sock_fd, msgbuf, msgbuf_size, 0, 169f08c3bdfSopenharmony_ci (struct sockaddr *)&client_addr, 170f08c3bdfSopenharmony_ci &client_addr_len)) < 0) 171f08c3bdfSopenharmony_ci fatal_error("recvfrom()"); 172f08c3bdfSopenharmony_ci msgbuf[msglen] = '\0'; 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci if (debug) 175f08c3bdfSopenharmony_ci fprintf(stderr, "Message is %s\n", msgbuf); 176f08c3bdfSopenharmony_ci 177f08c3bdfSopenharmony_ci /* Return the message to the client */ 178f08c3bdfSopenharmony_ci if (sendto(sock_fd, msgbuf, msglen, 0, 179f08c3bdfSopenharmony_ci (struct sockaddr *)&client_addr, 180f08c3bdfSopenharmony_ci sizeof(client_addr)) != msglen) 181f08c3bdfSopenharmony_ci fatal_error("sendto()"); 182f08c3bdfSopenharmony_ci free(msgbuf); 183f08c3bdfSopenharmony_ci} 184f08c3bdfSopenharmony_ci 185f08c3bdfSopenharmony_ci/* 186f08c3bdfSopenharmony_ci * 187f08c3bdfSopenharmony_ci * Function: main() 188f08c3bdfSopenharmony_ci * 189f08c3bdfSopenharmony_ci */ 190f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 191f08c3bdfSopenharmony_ci{ 192f08c3bdfSopenharmony_ci char *program_name = argv[0]; 193f08c3bdfSopenharmony_ci int optc; /* option */ 194f08c3bdfSopenharmony_ci sa_family_t family; /* protocol family */ 195f08c3bdfSopenharmony_ci char *portnum = NULL; /* port number */ 196f08c3bdfSopenharmony_ci int sock_fd; /* socket binded open ports */ 197f08c3bdfSopenharmony_ci int background = 0; /* work in the background if non-zero */ 198f08c3bdfSopenharmony_ci fd_set read_fds; /* list of file descriptor for reading */ 199f08c3bdfSopenharmony_ci int max_read_fd = 0; /* maximum number in the read fds */ 200f08c3bdfSopenharmony_ci FILE *info_fp = stdout; /* FILE pointer to a information file */ 201f08c3bdfSopenharmony_ci int on; /* on/off at an socket option */ 202f08c3bdfSopenharmony_ci int err; /* return value of getaddrinfo */ 203f08c3bdfSopenharmony_ci struct addrinfo hints; /* hints for getaddrinfo() */ 204f08c3bdfSopenharmony_ci struct addrinfo *res; /* pointer to addrinfo */ 205f08c3bdfSopenharmony_ci 206f08c3bdfSopenharmony_ci debug = 0; 207f08c3bdfSopenharmony_ci family = PF_UNSPEC; 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci /* Retrieve the options */ 210f08c3bdfSopenharmony_ci while ((optc = getopt(argc, argv, "f:p:bo:dh")) != EOF) { 211f08c3bdfSopenharmony_ci switch (optc) { 212f08c3bdfSopenharmony_ci case 'f': 213f08c3bdfSopenharmony_ci if (strncmp(optarg, "4", 1) == 0) 214f08c3bdfSopenharmony_ci family = PF_INET; /* IPv4 */ 215f08c3bdfSopenharmony_ci else if (strncmp(optarg, "6", 1) == 0) 216f08c3bdfSopenharmony_ci family = PF_INET6; /* IPv6 */ 217f08c3bdfSopenharmony_ci else { 218f08c3bdfSopenharmony_ci fprintf(stderr, 219f08c3bdfSopenharmony_ci "protocol family should be 4 or 6.\n"); 220f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 221f08c3bdfSopenharmony_ci } 222f08c3bdfSopenharmony_ci break; 223f08c3bdfSopenharmony_ci 224f08c3bdfSopenharmony_ci case 'p': 225f08c3bdfSopenharmony_ci { 226f08c3bdfSopenharmony_ci unsigned long int num; 227f08c3bdfSopenharmony_ci num = strtoul(optarg, NULL, 0); 228f08c3bdfSopenharmony_ci if (num < PORTNUMMIN || PORTNUMMAX < num) { 229f08c3bdfSopenharmony_ci fprintf(stderr, 230f08c3bdfSopenharmony_ci "The range of port is from %u to %u\n", 231f08c3bdfSopenharmony_ci PORTNUMMIN, PORTNUMMAX); 232f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 233f08c3bdfSopenharmony_ci } 234f08c3bdfSopenharmony_ci portnum = strdup(optarg); 235f08c3bdfSopenharmony_ci } 236f08c3bdfSopenharmony_ci break; 237f08c3bdfSopenharmony_ci 238f08c3bdfSopenharmony_ci case 'b': 239f08c3bdfSopenharmony_ci background = 1; 240f08c3bdfSopenharmony_ci break; 241f08c3bdfSopenharmony_ci 242f08c3bdfSopenharmony_ci case 'o': 243f08c3bdfSopenharmony_ci if ((info_fp = fopen(optarg, "w")) == NULL) { 244f08c3bdfSopenharmony_ci fprintf(stderr, "Cannot open %s\n", optarg); 245f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 246f08c3bdfSopenharmony_ci } 247f08c3bdfSopenharmony_ci break; 248f08c3bdfSopenharmony_ci 249f08c3bdfSopenharmony_ci case 'd': 250f08c3bdfSopenharmony_ci debug = 1; 251f08c3bdfSopenharmony_ci break; 252f08c3bdfSopenharmony_ci 253f08c3bdfSopenharmony_ci case 'h': 254f08c3bdfSopenharmony_ci usage(program_name, EXIT_SUCCESS); 255f08c3bdfSopenharmony_ci break; 256f08c3bdfSopenharmony_ci 257f08c3bdfSopenharmony_ci default: 258f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 259f08c3bdfSopenharmony_ci } 260f08c3bdfSopenharmony_ci } 261f08c3bdfSopenharmony_ci 262f08c3bdfSopenharmony_ci /* Check the family is spefied. */ 263f08c3bdfSopenharmony_ci if (family == PF_UNSPEC) { 264f08c3bdfSopenharmony_ci fprintf(stderr, "protocol family should be specified.\n"); 265f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 266f08c3bdfSopenharmony_ci } 267f08c3bdfSopenharmony_ci 268f08c3bdfSopenharmony_ci /* At first, SIGHUP is ignored. */ 269f08c3bdfSopenharmony_ci handler.sa_handler = SIG_IGN; 270f08c3bdfSopenharmony_ci if (sigfillset(&handler.sa_mask) < 0) 271f08c3bdfSopenharmony_ci fatal_error("sigfillset()"); 272f08c3bdfSopenharmony_ci handler.sa_flags = 0; 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci if (sigaction(SIGHUP, &handler, NULL) < 0) 275f08c3bdfSopenharmony_ci fatal_error("sigaction()"); 276f08c3bdfSopenharmony_ci 277f08c3bdfSopenharmony_ci /* Set the hints to addrinfo() */ 278f08c3bdfSopenharmony_ci memset(&hints, '\0', sizeof(struct addrinfo)); 279f08c3bdfSopenharmony_ci hints.ai_family = family; 280f08c3bdfSopenharmony_ci hints.ai_socktype = SOCK_DGRAM; 281f08c3bdfSopenharmony_ci hints.ai_protocol = IPPROTO_UDP; 282f08c3bdfSopenharmony_ci hints.ai_flags = AI_PASSIVE; 283f08c3bdfSopenharmony_ci 284f08c3bdfSopenharmony_ci /* Translate the network and service information of the server */ 285f08c3bdfSopenharmony_ci err = getaddrinfo(NULL, portnum, &hints, &res); 286f08c3bdfSopenharmony_ci if (err) { 287f08c3bdfSopenharmony_ci fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(err)); 288f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 289f08c3bdfSopenharmony_ci } 290f08c3bdfSopenharmony_ci if (res->ai_next) { 291f08c3bdfSopenharmony_ci fprintf(stderr, "getaddrinfo(): multiple address is found."); 292f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 293f08c3bdfSopenharmony_ci } 294f08c3bdfSopenharmony_ci 295f08c3bdfSopenharmony_ci /* Create a socket for listening. */ 296f08c3bdfSopenharmony_ci sock_fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 297f08c3bdfSopenharmony_ci if (sock_fd < 0) 298f08c3bdfSopenharmony_ci fatal_error("socket()"); 299f08c3bdfSopenharmony_ci 300f08c3bdfSopenharmony_ci#ifdef IPV6_V6ONLY 301f08c3bdfSopenharmony_ci /* Don't accept IPv4 mapped address if the protocol family is IPv6 */ 302f08c3bdfSopenharmony_ci if (res->ai_family == PF_INET6) { 303f08c3bdfSopenharmony_ci on = 1; 304f08c3bdfSopenharmony_ci if (setsockopt 305f08c3bdfSopenharmony_ci (sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(int))) 306f08c3bdfSopenharmony_ci fatal_error("setsockopt()"); 307f08c3bdfSopenharmony_ci } 308f08c3bdfSopenharmony_ci#endif 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci /* Enable to reuse the socket */ 311f08c3bdfSopenharmony_ci on = 1; 312f08c3bdfSopenharmony_ci if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int))) 313f08c3bdfSopenharmony_ci fatal_error("setsockopt()"); 314f08c3bdfSopenharmony_ci 315f08c3bdfSopenharmony_ci /* Bind to the local address */ 316f08c3bdfSopenharmony_ci if (bind(sock_fd, res->ai_addr, res->ai_addrlen) < 0) 317f08c3bdfSopenharmony_ci fatal_error("bind()"); 318f08c3bdfSopenharmony_ci 319f08c3bdfSopenharmony_ci freeaddrinfo(res); 320f08c3bdfSopenharmony_ci 321f08c3bdfSopenharmony_ci /* If -b option is specified, work as a daemon */ 322f08c3bdfSopenharmony_ci if (background) 323f08c3bdfSopenharmony_ci if (daemon(0, 0) < 0) 324f08c3bdfSopenharmony_ci fatal_error("daemon()"); 325f08c3bdfSopenharmony_ci 326f08c3bdfSopenharmony_ci /* Output any server information to the information file */ 327f08c3bdfSopenharmony_ci fprintf(info_fp, "PID: %u\n", getpid()); 328f08c3bdfSopenharmony_ci fflush(info_fp); 329f08c3bdfSopenharmony_ci if (info_fp != stdout) 330f08c3bdfSopenharmony_ci if (fclose(info_fp)) 331f08c3bdfSopenharmony_ci fatal_error("fclose()"); 332f08c3bdfSopenharmony_ci 333f08c3bdfSopenharmony_ci /* Catch SIGHUP */ 334f08c3bdfSopenharmony_ci handler.sa_handler = set_signal_flag; 335f08c3bdfSopenharmony_ci if (sigaction(SIGHUP, &handler, NULL) < 0) 336f08c3bdfSopenharmony_ci fatal_error("sigaction()"); 337f08c3bdfSopenharmony_ci 338f08c3bdfSopenharmony_ci /* Loop to wait a client access */ 339f08c3bdfSopenharmony_ci FD_ZERO(&read_fds); 340f08c3bdfSopenharmony_ci FD_SET(sock_fd, &read_fds); 341f08c3bdfSopenharmony_ci max_read_fd = sock_fd; 342f08c3bdfSopenharmony_ci for (;;) { 343f08c3bdfSopenharmony_ci int select_ret; /* return value of select() */ 344f08c3bdfSopenharmony_ci fd_set active_fds; /* list of the active file descriptor */ 345f08c3bdfSopenharmony_ci struct timeval select_timeout; /* timeout for select() */ 346f08c3bdfSopenharmony_ci 347f08c3bdfSopenharmony_ci /* When catch SIGHUP, exit the loop */ 348f08c3bdfSopenharmony_ci if (catch_sighup) 349f08c3bdfSopenharmony_ci break; 350f08c3bdfSopenharmony_ci 351f08c3bdfSopenharmony_ci active_fds = read_fds; 352f08c3bdfSopenharmony_ci select_timeout.tv_sec = 0; /* 0.5 sec */ 353f08c3bdfSopenharmony_ci select_timeout.tv_usec = 500000; 354f08c3bdfSopenharmony_ci 355f08c3bdfSopenharmony_ci select_ret = select(max_read_fd + 1, &active_fds, 356f08c3bdfSopenharmony_ci NULL, NULL, &select_timeout); 357f08c3bdfSopenharmony_ci if (select_ret < 0) { 358f08c3bdfSopenharmony_ci if (catch_sighup) 359f08c3bdfSopenharmony_ci break; 360f08c3bdfSopenharmony_ci else 361f08c3bdfSopenharmony_ci fatal_error("select()"); 362f08c3bdfSopenharmony_ci } else if (select_ret == 0) { 363f08c3bdfSopenharmony_ci continue; 364f08c3bdfSopenharmony_ci } else { 365f08c3bdfSopenharmony_ci if (FD_ISSET(sock_fd, &active_fds)) 366f08c3bdfSopenharmony_ci respond_to_client(sock_fd); 367f08c3bdfSopenharmony_ci } 368f08c3bdfSopenharmony_ci } 369f08c3bdfSopenharmony_ci 370f08c3bdfSopenharmony_ci /* Close the sockets */ 371f08c3bdfSopenharmony_ci if (close(sock_fd)) 372f08c3bdfSopenharmony_ci fatal_error("close()"); 373f08c3bdfSopenharmony_ci 374f08c3bdfSopenharmony_ci exit(EXIT_SUCCESS); 375f08c3bdfSopenharmony_ci} 376