/*

$Id: stuff.c,v 1.1 1995/05/17 08:33:41 mwhitson Exp $

*/

#include "extern.h"
#include "proto.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <errno.h>

/*
 *  open_socket creates a non-blocking server socket on the specified
 *  port.  It returns the file descriptor for the (yet unaccepted)
 *  socket, or -1 in case of failure.
 */
int open_socket(int port)
{
  struct sockaddr_in sock;
  int s;

  if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
    return -1 ;

  if ((fcntl(s, F_SETFL, O_NDELAY)) < 0)
    return -1;

  memset(&sock, 0, sizeof(sock));
  sock.sin_family = AF_INET;
  sock.sin_port = htons(port);
  sock.sin_addr.s_addr = htonl(INADDR_ANY);

  if (bind(s, (struct sockaddr*)&sock, sizeof(sock)) < 0)
    return -1;

  if (listen(s, SRV_SOCK_BACKLOG) < 0)
    return -1;

  return s ;
}

/*
 *  duplicate a string by allocating space and copying
 */
char *strdup(char *str)
{
  char *ret;

  if (! str) return NULL;
  ret = (char*)malloc(strlen(str)+1);
  CHECK_MALLOC(ret);
  return strcpy(ret,str);
}

/*
 *  This finds the hostname of the client and returns it.
 *  The returned host name is either the canonical machine name from
 *  gethostbyaddr, or the dotted IP address.
 */
char *find_peer_name(struct sockaddr_in *addr)
{
  char *host;
  struct hostent *peer;
  long ip_addr;

  peer = gethostbyaddr(&(addr->sin_addr.s_addr),
		       sizeof(addr->sin_addr.s_addr), AF_INET);

  if (peer && peer->h_name) {              /* we got a name */
    host = (char*)malloc(strlen(peer->h_name)+1);
    CHECK_MALLOC(host);
    strcpy(host, peer->h_name);
  } else {                             /* we didn't get a name-- use IP #s */
    ip_addr = htonl(addr->sin_addr.s_addr);
    host = (char*)malloc(20);
    CHECK_MALLOC(host);
    sprintf(host, "%d.%d.%d.%d",
	    (int)((ip_addr >> 24) & 0xff),
	    (int)((ip_addr >> 16) & 0xff),
	    (int)((ip_addr >>  8) & 0xff),
	    (int)(ip_addr & 0xff));
  }

  return host;
}

/*
 *  This will set up for running as daemon (w/o tty, etc)
 */
void background(void)
{
  pid_t pid;

  close(STDIN_FILENO);
  close(STDOUT_FILENO);
  close(STDERR_FILENO);
  chdir(SRV_ROOT_DIR);   
  umask(SRV_UMASK);

  if ((pid=fork()) < 0) {
    SYSLOG_ERROR("initial fork failed");
    exit(1) ;
  } else if (pid != 0) {
    exit(0);
  }

  setsid();
}
