#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/wait.h>
#include "both.h"

/* function declarations */
int do_article(int, FILE *);
int do_batch(int, char *, char *,int, int, char *[]);
int do_filter(int, char *[]);
/*------------------------------------------------*/
void main(int argc, char *argv[]) {
	char *inbuf, *host, *batch, *prefix;
	int sockfd, response, retval, loop, filter;
	struct hostent *hi;
	
	retval = 0;
	batch = prefix = NULL;
	filter = -1;

	/* allow no args, only the hostname, or hostname as first arg */
	if(argc == 1) { 
		host = getenv("NNTPSERVER");		/* the default */
	}
	else {
		host = argv[1];			
		for(loop=2;loop<argc;loop++) {
			if(argv[loop][0] == '-') {
				switch(argv[loop][1]) {
				  case 'b':	/* batch file Mode, next arg = batch file */
					if(loop+1 == argc) {
						fprintf(stderr, "No Batch file Specified\n");
						retval = -1;
					}
					else { 
						batch = argv[++loop];
					}
					break;
				  case 'p':	/* specify directory prefix for files in batch file */
					if(loop+1 == argc) {
						fprintf(stderr, "No prefix Supplied\n");
						retval = -1;
					}
					else {
						prefix = argv[++loop];
					}
					break;
				  case 'f':	/* filter prg, rest of cmd line is args */
					if(loop+1 == argc) {
						fprintf(stderr, "No args to use for filter\n");
						retval = -1;
					}
					else {
						filter = loop+1;	/* point filter to first arg */
						loop = argc;		/* terminate main loop */
					}
					break;	
				  default:
					fprintf(stderr, "Invalid argument, ignoring: %s\n", argv[loop]);
					break;
				}			
			}
			else {
				fprintf(stderr, "Invalid argument, ignoring: %s\n", argv[loop]);
			}	
		}
	}
	if(retval == -1) {
		fprintf(stderr, "\nUsage: %s hostname [-b batch_file -p dir_prefix -f filter_args] <Return>\n", argv[0]);
		fprintf(stderr, "\t	If used, -f filter_args MUST be last argument on line");
	}
	else {
		/* we processed args okay */
		sockfd = connect_to_nntphost( host, &hi);
		if(sockfd < 0) {
			retval = -1;
		}
		else {
			/* Get the announcement line */
			sgetline(sockfd, &inbuf);
			fprintf(stderr,"%s", inbuf );
	
			number(inbuf, &response);
			if(response != 200) {
				fprintf(stderr, "Sorry, Can't post to this host\n");
				retval = -1;
			}
			else if(batch == NULL) {
				/* do one article from stdin */
				retval = do_article(sockfd, stdin);
			}
			else {
				/* batch mode */
				retval = do_batch(sockfd, batch, prefix, filter, argc, argv);				
			}		
			fprintf(stderr,"Closing connection to %s\n", hi->h_name);
			sputline( sockfd, "quit\r\n" );
 			close(sockfd);
		}
	}
	exit(retval);
}
/*----------------------------------------------------------------------------------*/
int do_article(int sockfd, FILE *fptr) {

	int len, response, retval;
	char buf[MAXLINLEN+1], *inbuf;

	retval = 0;

	/* Initiate post mode */
	sputline(sockfd, "POST\r\n");
	sgetline(sockfd, &inbuf);
	fprintf(stderr, "%s", inbuf);
#ifdef DEBUG3
	do_debug("POST response: %s", inbuf);
#endif

	number(inbuf, &response);
	if(response!=340) {
		fprintf(stderr,"Bad luck. You can't use this server.\n");
		retval = -1;
	}
	else {
		while(fgets(buf, MAXLINLEN-2, fptr) != NULL) {
			len=strlen(buf);
			if(buf[0]=='.')  {
			/* Yup, this has to be doubled */
				bcopy(buf+1,buf,++len);
				buf[0]='.';
   			}
   			strncpy(&buf[len-1],"\r\n",3);
   			sputline(sockfd, buf);
#ifdef DEBUG3
			do_debug("MSG: %s", buf);
#endif
		}
		sputline(sockfd, ".\r\n");
#ifdef DEBUG3
		do_debug("MSG END\n");
#endif
		sgetline(sockfd, &inbuf);
		fprintf(stderr,"%s",inbuf);
#ifdef DEBUG3
		do_debug("RESPONSE: %s", inbuf);
#endif

		number(inbuf, &response);
	 	if(response!=240) {
			fprintf(stderr,"Malfunction. Unable to post Article!\n");
			retval = -1;
		}
	}
	return retval;
}
/*--------------------------------------------------------------------------------*/
int do_batch(int sockfd, char *batchfile, char *prefix, int filter, int argc, char *argv[]) {

	int i, loop, argon, infilenr, retval = 0;
	FILE *fpi_batch, *fpi_msg;
	char buf[MAXLINLEN+1], file[MAXLINLEN+1];
	char *outfile, *infile, *ourargs[RPOST_MAXARGS];

	outfile = NULL;
	retval = 0;
	argon = infilenr = -1;

	if((fpi_batch = fopen(batchfile, "r")) == NULL) {
		perror(batchfile);
		retval = -1;
	}
	else {
		if(filter >= 0) {
			/* build filter args */
 
			i = strlen(RPOST_FILTER_OUT);

			/* build array of args to past to fork, execl */
			/* if see RPOST_FILTER_IN as arg, substitute the infile name */
			/* if see RPOST_FILTER_OUT as first part of arg, get outfile name */
			for(argon = 0, loop = filter; loop < argc; loop++) {
				if(strcmp(argv[loop], RPOST_FILTER_IN) == 0) {
					/* substitute infile name */
					infilenr = argon++;
				}
				else if(strncmp(argv[loop], RPOST_FILTER_OUT, i) == 0) {
					/* arg should be RPOST_FILTER_OUT=filename */
					if(argv[loop][i] != '=') {
						fprintf(stderr, "Invalid argument: %s\n", argv[loop]);
					}
					else {
						outfile = &(argv[loop][i+1]);
					}
				}
				else {
					ourargs[argon++] = argv[loop];
				}			
			}
			ourargs[argon] = NULL;	/* just to be on the safe side */
			if(outfile == NULL) {
				/* no outfile defined, use built-in default */
				outfile = tmpnam(NULL);
				fprintf(stderr, "Using Built-In default %s\n", outfile);
			}
			if(infilenr < 0) {
				fprintf(stderr, "No infile specification, aborting\n");
				retval = -1;
			}
		}
		while((retval == 0) && (fgets(buf, MAXLINLEN, fpi_batch) != NULL)) {
			/* build file name */
			if(prefix == NULL) {
				strcpy(file, buf);
			}
			else {
				strcpy(file, prefix);
				if(file[strlen(file)-1] != '/') {
					strcat(file, "/");
				}
				strcat(file, buf);
			}
			/* strip off nl */
			i = strlen(file);
			if(file[i-1] == '\n') {
				file[i-1] = '\0';
			}
			/* okay here have file name */
#ifdef DEBUG3
			do_debug("Article Name: %s\n", file);
#endif
			/* if we are using a filter, use outfilename */
			/* else just use regular file name */
			if(filter >= 0) {
				ourargs[infilenr] =  file;
				retval = do_filter(argon, ourargs);
				infile = outfile;
			}
			else {
				infile = file;
			}

			if(infile == NULL) {
				fprintf(stderr, "No file to process, aborting\n");
				retval = -1;
			}
			else if((fpi_msg = fopen(infile, "r")) == NULL) {
				perror(infile);
				retval = -1;
			}
			else {
				do_article(sockfd, fpi_msg);
				fclose(fpi_msg);
			}	
		}
	 	fclose(fpi_batch);
	}
	return retval;
}
/*--------------------------------------------------------------------*/
int do_filter(int argc, char *argv[]) {
	int retval = 0;

#ifdef DEBUG3
	{
		int xxxi;
		do_debug("ARGS:");
		for(xxxi=0;xxxi<argc;xxxi++) {
			do_debug(" %d=%s", xxxi, argv[xxxi]);
		}
		do_debug("\n");
	}
#endif
	switch(fork()) {
	  case 0:	/* in child, do execl */
		if(execvp(argv[0], argv) == -1) {
			perror("Execl");
			retval = -1;
		}
		break;
	  case -1:	/* should never get here */
		perror("Fork");
		retval = -1;
		break;
	  default:	/* in parent, wait for child to finish */
		wait(NULL);		/* no status check on finish */
	}					

	return retval;
}
