text: /*
  ** t_listen.c - Test daemon for pnscan
  **
  ** Copyright (c) 2002-2020, Peter Eriksson <pen@lysator.liu.se>
  ** All rights reserved.
  ** 
  ** Redistribution and use in source and binary forms, with or without
  ** modification, are permitted provided that the following conditions are met:
  ** 
  ** 1. Redistributions of source code must retain the above copyright notice, this
  **    list of conditions and the following disclaimer.
  ** 
  ** 2. Redistributions in binary form must reproduce the above copyright notice,
  **    this list of conditions and the following disclaimer in the documentation
  **    and/or other materials provided with the distribution.
  ** 
  ** 3. Neither the name of the copyright holder nor the names of its
  **    contributors may be used to endorse or promote products derived from
  **    this software without specific prior written permission.
  ** 
  ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <errno.h>
  #include <unistd.h>
  #include <fcntl.h>
  #include <signal.h>
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <arpa/inet.h>
  #include <netinet/in.h>
  
  int port_base = 32768;
  int port_len  = 16384;
  
  int timeout = 10;
  
  const char *msg = "Hello, World!\n";
  
  void
  error(const char *msg) {
    fprintf(stderr, "Error: %s: %s\n", msg, strerror(errno));
    exit(1);
  }
  
  int
  main(int argc,
       char *argv[]) {
    int s_fd, r_fd, port, rc, n;
    struct sockaddr_in s_sin, r_sin;
    socklen_t r_sin_len;
    
  
    s_fd = socket(PF_INET, SOCK_STREAM, 0);
    if (s_fd < 0)
      error("socket");
    
    n = 0;
    do {
      port = (random()%port_len)+port_base;
      
      memset(&s_sin, 0, sizeof(s_sin));
      s_sin.sin_family = AF_INET;
      s_sin.sin_addr.s_addr = INADDR_ANY;
      s_sin.sin_port = htons(port);
  
      rc = bind(s_fd, (struct sockaddr *) &s_sin, sizeof(s_sin));
    } while (rc < 0 && (errno == EINTR || errno == EADDRINUSE) && n++ < 10);
    if (rc < 0)
      error("bind");
    
    if (listen(s_fd, 10) < 0)
      error("listen");
  
  #if 0
    signal(SIGPIPE, SIG_IGN);
  #endif
    
    rc = fork();
    if (rc < 0)
      error("fork");
    
    if (rc) {
      printf("%d\n", port);
      exit(0);
    }
  
    close(0);
    dup2(open("/dev/null", O_RDONLY), 0);
    close(1);
    dup2(open("/dev/null", O_WRONLY), 1);
  
    alarm(timeout);
    
    do {
      r_sin_len = sizeof(r_sin);
      r_fd = accept(s_fd, (struct sockaddr *) &r_sin, &r_sin_len);
    } while (r_fd < 0 && errno == EINTR);
    
    if (r_fd < 0)
      error("accept");
    
    if (write(r_fd, msg, strlen(msg)) < 0)
      error("write");
    
    close(r_fd);
    _exit(0);
  }
  
  