/*
   The Open DNS Update Daemon (dnsd)
   Copyright (C) 1998 Aaron Sethman <asethman@mandate-inc.com>

   The read_line() function was borrowed from Eric S. Raymond's fetchmail
   program.  Fetchmail is Copyright (C) Eric S. Raymond.
   
   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.
 */
/*
        File status: finished.....
        Last modified: April 16, 1999 asethman@mandate-inc.com
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <fcntl.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
// #include <sys/poll.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "client.h"
void do_select2(int socket, int tv_sec);

char *getip(int s)
{
	char *ptr;
	struct sockaddr_in *sin;
	int len;
	len = sizeof(struct sockaddr_in);
	sin = malloc(len);
	if (getpeername(s, (struct sockaddr *)sin, &len) >= 0 && (sin != NULL))
	{
		ptr = strdup(inet_ntoa(sin->sin_addr));
		free(sin);
		return(ptr);
	}
	return NULL;
}
int mydprintf(int s, char *fmt,...)
{
	int x;
	char *ptr;
	va_list ap;
	va_start(ap, fmt);
	myvasprintf(&ptr, fmt, ap);
	x = write(s, ptr, strlen(ptr));
	free(ptr);
	return(x);	
}
void do_select2(int socket, int tv_sec)
{
	fd_set rfds;
	struct timeval tv;
	struct timeval *t;
	FD_ZERO(&rfds);
	FD_SET(socket, &rfds);	
	tv.tv_sec = tv_sec;
	tv.tv_usec = 0;
	t = &tv;
	if(tv_sec == -1)
		t = NULL;
	select(socket + 1, &rfds, NULL, NULL, t);
}

void do_select(int socket)
{
	do_select2(socket, -1);
}

int read_line(int sock, char **buf)
{
	/* Rewritten to do something mildly intelliegent.... */
	int len = 8192;
	int x;
	int flags = MSG_PEEK,  broken = 0;
	char *ptr, *r, *p, *q;
	ptr = malloc(len);
	if (sock < 0)
		return -1;
	do_select(sock);
start:
	while ((x = recv(sock, ptr, len, flags)) > 0) 
	{
		q = memchr(ptr, '\n', x);
		p = memchr(ptr, '\r', x);
		if(p != NULL && q != NULL)
			break;
		if((p == NULL) && (q == NULL))
		{
			if(x == len)
			{
				len = len * 2;
				ptr = realloc(ptr, len);
			} else
				if(x == 1)
				{
					if(broken == 1)
						return -1;
					broken = 1;
					
				}
			goto start;		
		}
		if((p == NULL) || (q == NULL))
		{
			if(x == len)		
			{
				len = len * 2;
				ptr = realloc(ptr, len);
			} else
				break;

		}
	}
	if ((r = mymemmem(ptr, x, "\n\r", 2)) != NULL)
		x = (r - ptr) + 2;
	else if ((r = mymemmem(ptr, x, "\r\n", 2)) != NULL)
		x = (r - ptr) + 2;
	else if ((r = mymemmem(ptr, x, "\r", 1)) != NULL)
		x = (r - ptr) + 1;
	else if ((r = mymemmem(ptr, x, "\n", 1)) != NULL)
		x = (r - ptr) + 1;
	ptr = realloc(ptr, x);
	x = recv(sock, ptr, x, 0);
	*buf = malloc(x);
	memcpy(*buf, ptr, x);
	free(ptr);
	if(broken)
		fcntl(sock, F_SETFL, O_NONBLOCK);
	return x;
	

}

int do_tcpconnect(char *hostname, int port)
{
	struct hostent *host;
	struct sockaddr_in in;
	int s;
	if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
		return -1;
	if ((host = gethostbyname(hostname)) == NULL) {
		return -1;
	}
	in.sin_family = AF_INET;
	in.sin_port = htons(port);
	in.sin_addr.s_addr = *(unsigned long *) host->h_addr;
	if (connect(s, (struct sockaddr *) &in, sizeof(struct sockaddr_in))) {
		return -1;
	}
	return (s);
}



syntax highlighted by Code2HTML, v. 0.9.1