/*
 * chttpd/1.0
 * *   socket handling routines
 * *   Copyright (C) 2000  Greg Olszewski
 * *
 * *   This program is free software; you can redistribute it and/or modify
 * *   it under the terms of the GNU General Public License as published by
 * *   the Free Software Foundation; either version 2 of the License, or
 * *   (at your option) any later version.
 * *
 * *   This program is distributed in the hope that it will be useful,
 * *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 * *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * *   GNU General Public License for more details.
 * *
 * *   You should have received a copy of the GNU General Public License
 * *   along with this program; if not, write to the Free Software
 * *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <errno.h>
#include <netdb.h>

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <socket.h>
#include <log.h>
extern int      errno;

/*
 * get_listen_sock
 *   Start up the socket listening routines and return a filedescriptor
 *   for that socket
 */
int
get_listen_sock(int portnum, struct listen_sock *sock)
{
    int             status;
    int             one;

    status = 0;
    one = 1;
    memset(&(sock->sin), 0, sizeof(sock->sin));
    sock->sin.sin_family = AF_INET;
    sock->sin.sin_addr.s_addr = htonl(0);
    sock->sin.sin_port = htons(portnum);

    status = sock->socket = socket(AF_INET, SOCK_STREAM, 0);

    if (status != -1)
	status =
	    setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR,
		       (char *) &one, sizeof(one));

    if (!status)
	status =
	    bind(sock->socket, (struct sockaddr *) &(sock->sin),
		 sizeof((sock->sin)));
    if (!status)
	status = listen(sock->socket, 5);
    if (status) {
	shutdown(sock->socket, 2);
	sock->socket = -1;
    }
    return (sock->socket);
}

/*
 * accept_sock:
 * accepts a new socket and returns the file descriptor
 */
int
accept_sock(struct listen_sock socket)
{
    int             n_sock;
    socklen_t       size = sizeof((socket.sin));
    n_sock = accept((socket.socket),(struct sockaddr*)&(socket.sin), &size);
    if (n_sock < 0)
	log_error("%s", strerror(errno));
    return n_sock;

}

void
shutdown_sock(struct listen_sock socket)
{
    if (socket.socket != -1)
	shutdown(socket.socket, 2);
}

/*
 * get_active_sock:
 * sets up FILE* for http socket.
 * returns 0 for failure 1 for success
 */
int
get_active_sock(struct active_sock *a_sock, const int socketd)
{
    a_sock->socket = socketd;
    a_sock->io = fdopen(a_sock->socket, "w+");
    if (!(a_sock->io)) {
	log_error("%s", strerror(errno));
	close(a_sock->socket);
	return (-1);
    }
    return 0;
}
