#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <ctype.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdarg.h>

#include "both.h"
/*-----------------------------------------------------*/
/* get next number in string */
char *number(char *sp, int *intPtr) {
	int i,c;

	if(sp==NULL) {
		*intPtr=0; 
		return(sp);
	}

	for (i=0;sp[i]!=' ';i++) {
		if(sp[i]=='\0') {
			break;
		}
	}
	c=sp[i];
	sp[i]='\0';
	sscanf(sp,"%d",intPtr);
	sp[i++]=c;
	return sp+i;
}
/*---------------------------------------------*/
struct hostent *get_hostent(char *host) {
	struct in_addr saddr;
	int c;
	struct hostent *hi = NULL;

	if(host==NULL) { 
		fprintf(stderr,"No hostname given !\r\n"); 
	}
	else {
		c=*host;
		if(isdigit(c)) {
 			saddr.s_addr = inet_addr(host); 
 			hi = gethostbyaddr((char *)&saddr,sizeof(struct in_addr),AF_INET);
		}
		else {
			hi = gethostbyname(host);
		}
	}
	return hi;
}
/*--------------------------------------------*/
int connect_to_nntphost(char *host, struct hostent **hi) {
	char *ptr;
	struct in_addr *aptr;
	struct in_addr saddr;
	struct sockaddr_in address;
	int sockfd = -1;

	/* Find the internet address of the NNTP server */
 	*hi = get_hostent(host);
 	if(*hi == NULL) {
		fprintf(stderr,"%s :",host);
  		perror("Could not get host information:");
 	}
	else {
		fprintf(stderr,"Official host name: %s\r\n", (*hi)->h_name );
 		while((ptr = *((*hi)->h_aliases)) != NULL) {
			fprintf(stderr,"Alias %s\r\n", ptr );
			(*hi)->h_aliases++;
		}
 		if((*hi)->h_addrtype != AF_INET) {
  			fprintf(stderr,"Unsupported address type.\r\n" );
		}
		else {
			while((aptr = (struct in_addr *)*((*hi)->h_addr_list)++) != NULL) {
				saddr = *aptr;
				fprintf(stderr,"Address: %s\r\n", inet_ntoa(*aptr));
			}

			/* Create a socket */
 			if((sockfd = socket( AF_INET, SOCK_STREAM, 0)) == -1) {
				perror("Socket failed:");
			}
			else { 
				address.sin_family = AF_INET;
				address.sin_port = htons(119);  /* NNTP port */
				address.sin_addr= saddr;

				/* Establish a connection */
				if(connect(sockfd, (struct sockaddr *)&address, sizeof address ) == -1) {
					perror("Connect failed:");
					close(sockfd);
					sockfd = -1;
				}
				else {
					fprintf(stderr,"Connected to %s\r\n",(*hi)->h_name);
				}
			}
		}
	}
	return sockfd;
}
/*----------------------------------------------------------------*/
int sputline(int fd, char *outbuf) {

#ifdef DEBUG1
	do_debug("\nSENT: %s", outbuf);
#endif
	return send(fd, outbuf, strlen(outbuf), 0);
}
/*------------------------------------------------------------*/
char *full_path(char *dir, char *fname) {

	static char path[PATH_MAX+1];
	char *ptr;

	path[0] = '\0';	/* just to be on the side */

	ptr = dir;

	/* if it contains a dit, then change to full path */
	if(dir[0] == '.') {
		if(getcwd(path, PATH_MAX) == NULL) {
			perror(path);
		}
		else {
			ptr = dir+1;
		}
	}		
	strcat(path, ptr);
	if(path[strlen(path)-1] != '/') {
		strcat(path, "/");
	}
	strcat(path, fname);

	return path;
}
/*-------------------------------------------------------------*/
#ifdef DEBUG
void do_debug(char *fmt, ...) {

	FILE *fptr = NULL;
	va_list args;

	if((fptr = fopen(full_path(N_PATH, N_DEBUG), "a")) == NULL) {
		fptr = stderr;
	}
		
	va_start(args, fmt);
	vfprintf(fptr, fmt, args);
	va_end(args);

	if(fptr != stderr) {
		fclose(fptr);
	}
}
/*------------------------------------------------------------*/
void MyPerror(char *message) {
	
	perror(message);
	do_debug("%s\n", message);
}	
#endif
/*-----------------------------------------------------------*/
int sgetline(int fd, char **inbuf) {

	static char buf[MAXLINLEN+MAXLINLEN+6];
	static char *start = buf;
	static char *eob = buf;		/* end of buffer */
	int ret, i, len;
	char *ptr;

	ret = 0;

	if((ptr = strstr(start,"\r\n")) == NULL) {
		/* not a full line in buffer */
		i = eob-start; 	/* length of partial line in buf */
		if((eob - buf) > MAXLINLEN) {
#ifdef DO_DEBUG1
			do_debug("SHIFTING BUFFER\n");
#endif
			/* not enuf room in buffer for a full recv */
			memmove(buf, start, i); 	/* move to start of buf */;
			eob = buf + i;
			*eob = '\0';
			start = buf;			/* reset pointers */
		}
		len = i;
		/* try to get a line in, up to maxlen */
		do {
			i = recv(fd, eob, MAXLINLEN-len, 0);	/* get line */
			*(eob+i) = '\0';	/* for strstr to work */
#ifdef DEBUG1
		do_debug("\nGOT: %.*s",i,eob);
#endif 
			if(i < 1) {
				perror("Socket error:");
				ret = -1;
			}
			else {
				eob += i;
				len += i;				
				ptr = strstr(start, "\r\n");		
			}
		} while(ptr == NULL && len < MAXLINLEN && ret == 0);
	}
	if(ptr != NULL) {
		/* we have a full line left in buffer */
		*ptr++ = '\n';	/* change \r\n to just \n */
		*ptr++ = '\0';	/* null terminate */
		*inbuf = start;
		ret = (ptr-1) - start;	/* length of string */
		start = ptr; 	/* skip \r\n */
		
	}
	else if(ret == 0) {
		/* partial line in buffer */
		/* null terminate */
		*eob = '\0';
		*inbuf = start;
		ret = (eob-1) - start;	/* length of string */
		start = ++eob;	/* point both past end */
	}
#ifdef DEBUG1
	if(ret > 0) {
		do_debug("\nRETURNING len %d: %s", ret, *inbuf);
	}
#endif  
	return ret;
}		
