/* Copyright (C) 2004 Stefan Bellon <sbellon@sbellon.de>
 *
 * This file is part of RemotePrinterFS.
 *
 * RemotePrinterFS 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.
 *
 * RemotePrinterFS 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include <socklib.h>
#include <inetlib.h>
#include <sys/ioctl.h>
#include <sys/errno.h>

#define BUFSIZE 8192

static FILE *file = 0;
static int   sock = 0;
static int   conn = 0;

static const char *ok = "\000";
static char buf[BUFSIZE];
static int n;

void cleanup(void)
{
    if (conn)
        close(conn);
    if (sock)
        close(sock);
    if (file)
        fclose(file);
}

int main(void)
{
    atexit(cleanup);
    
    file = fopen("$.log_serv", "wb");

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        fprintf(file, "Error opening socket\n");
        cleanup();
        return 1;
    }
    
    int j = 1;
    ioctl(sock, FIOSLEEPTW, &j);
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &j, sizeof(j));

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family      = AF_INET;
    addr.sin_port        = htons(515);
    addr.sin_addr.s_addr = 0x00000000;
    if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) == EOF) {
        fprintf(file, "Error binding socket\n");
        cleanup();
        return 1;
    }

    if (listen(sock, 5) == EOF) {
        fprintf(file, "Error listening\n");
        cleanup();
        return 1;
    }

    for (;;) {
        struct sockaddr_in from;
        int len = sizeof(from);
        
        conn = accept(sock, (struct sockaddr *) &from, &len);
        if (conn < 0) {
            fprintf(file, "%i, %s\n", errno, strerror(errno));
            if (errno != EINTR) {
                continue;
            }
        }
        fprintf(file, "Connection from %i.%i.%i.%i established\n",
                (from.sin_addr.s_addr & 0x000000ff) >>  0,
                (from.sin_addr.s_addr & 0x0000ff00) >>  8,
                (from.sin_addr.s_addr & 0x00ff0000) >> 16,
                (from.sin_addr.s_addr & 0xff000000) >> 24);

        for (;;) {
            n = recv(conn, buf, BUFSIZE, 0);
            if (n == 0) {
                fprintf(file, "\nConnection closed by remote\n");
                break;
            }
            if (n < 0) {
                if (errno == EINTR) {
                    break;
                } else if (errno == ECONNRESET) {
                    fprintf(file, "\nConnection closed by remote\n");
                    break;
                } else {
                    fprintf(file, "\nerrno = %i\n", errno);
                    continue;
                }
            }

            if (buf[n-1] == '\012' || buf[n-1] == '\000') {
                if (write(conn, ok, 1) != 1) {
                    fprintf(file, "\nError: no char sent!\n");
                }
            }
          
            fwrite(buf, 1, n, file);
        }

        fprintf(file, "About to close connection\n");
        close(conn);
        conn = 0;
    }
}
