/* Copyright (C) 1995 NetWin World, New Zealand, All rights reserved. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifndef WIN32
#ifndef NOUNISTD
#include <unistd.h>
#endif
#endif
#ifdef isunix
#include <signal.h>
#endif
#include "dnews.h"
#include "conf.h"
#include "lib.h"
#include "sary.h"
#include "emsg.h"
#include "nntp.h"
void nprintf(int chan,char * arg_list, ...);
int article_sendihave(void);
void send_bag(char *name);

void send_item(char *name);
int article_read(void);
int article_save(void);
int article_send(void);
void nprintf(int chan,char * arg_list, ...);
int ngetline(int chan, char *bf);
int article_munge(void);
void wild_send(void);

#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif
char *hide_data(char *a, char *b, char *c);
char *unhide_data(char *s);
int debug_lvl;
char dnews_conf[BFSZ];
int do_register(void);
static char tosite[BFSZ];
static int chan;
static String *article;
FILE *flog;
static char spool[BFSZ];
char logfile[300];
static int doexit;
static int max_size= 900000;
char *svc_getargs(char *svcname);
static int tryagain,failed;
void suck_setexit(void)
{
	doexit  = TRUE;
}
void sig_init(void)
{
#ifdef isunix
        signal(SIGHUP,SIG_IGN);
        signal(SIGPIPE,SIG_IGN);
#ifdef SIGIOT 
        signal(SIGIOT,SIG_IGN);
#endif
#endif
}
#ifdef WIN32
int ServiceMain(int xargc, char *xargv[])
#else
int main(int argc, char *argv[])
#endif
{
	char bf[300];
	char *s;
	int i;
	int once;
#ifdef WIN32
	int argc;
	char *argv[20];
	char *cmd;

	svc_init(xargv[0]);
	sig_init();
	cmd = svc_getargs(xargv[0]);
	if (strlen(cmd)==0) {
		for (argc=0; argc<xargc; argc++) {
			argv[argc] = xargv[argc];
		}
	} else {
	  for (argc=0;TRUE;argc++) {
		s = get_word(cmd,argc); if (strlen(s)==0) break;
		argv[argc] = strdup(s);
	  }
	}
#endif
	
	once=0;

	if (argc<2) {
	 	printf("Usage: dposter -to nntp.site[:port] -dir c:\ntmail\news [-once] \n");
/*
		While debugging to run as a command.
		strcpy(spool,"c:\\ntmail\\news");
		strcpy(tosite,"161.29.1.123");
*/
		strcpy(spool,"d:\\uucp");
		strcpy(tosite,"161.29.2.1");
goto cont1;
	}

	for (i=1; i<argc; i++) {
		if (strcmp(argv[i],"-dir")==0) {strcpy(spool,argv[++i]);}
		else if (strcmp(argv[i],"-to")==0) {strcpy(tosite,argv[++i]);}
		else if (strcmp(argv[i],"-max_size")==0) {max_size = atoi(argv[++i]);}
		else if (strcmp(argv[i],"-once")==0) {once=1;}
                else if (strncmp(argv[i],"-c",2)==0) strcpy(dnews_conf,argv[++i]);
	}

cont1:
	/* Open the input file if it isn't stdin*/
	strcpy(bf,tosite);
	for (s=bf;*s!=0; s++) {
		if (*s=='.') *s = '_';
		if (*s=='+') *s = '_';
		if (*s=='-') *s = '_';
		if (*s==':') *s = '_';
	}
#ifndef	unix
	bf[8] = 0;
#endif
	sprintf(logfile,"%s/%s.log",spool,bf);
	emsg("Service started {%s} {%s} \n",spool,tosite);
	if(once) {
	  wild_send();
	} else {
	  for (;!doexit;) {
	    wild_send();
	    for (i=0; (i<10) && (!doexit); i++) sleep(1);
	  }
	}
	emsg("Service exiting\n");
#ifdef WIN32
	svc_exit();
#endif
	return 0;
}
static int isuucp;
char *main_msg(void)
{
	return "DPOSTER running, minimize window";
}
void wild_send(void)
{
	Sary *ls;
	char bf[BFSZ];
	int i;
	char *s;

	chan = -1;
	
	ls = s_alloc();
	isuucp = FALSE;
	s_wild(ls,spool,"*.itm");
	if (s_len(ls)==0) {
		s_wild(ls,spool,"*.bag");
		if (s_len(ls)==0) {
			goto doexit;
		}
		isuucp = TRUE;
	}

	nntp_startup();
	nntp_alwaysblock();
	chan = nntp_open(tosite); 
	if (chan<0) { emsg("Couldn't open nntp to == {%s}\n",tosite); goto doexit;}
	nntp_setblock(chan,TRUE); /* Set to blocking IO */
	if (!ngetline(chan,bf)) {emsg("Error:1 channel closed\n"); goto doexit ;}
	if (atoi(bf)!=200) {emsg("Error, posting not ok: %s",bf); goto doexit ;}

	for (i=0; i<s_len(ls); i++) {
		s = s_line(ls,i);
		emsg("Processing %s \n",s);
		if (isuucp) send_bag(s);
		else send_item(s);
	}
	nprintf(chan,"quit\015\012");
	if (!ngetline(chan,bf)) {emsg("quit failed \n"); goto doexit ;}
doexit:
	if (chan>=0) nntp_doclose(chan);
	s_free(ls);
}
#define BIGBF 10000
void send_item(char *name)
{
	FILE *f;
	char oldname[BFSZ],newname[BFSZ];
	char bf[BIGBF];
	char *s;

 	sprintf(oldname,"%s/%s",spool,name);
	sprintf(newname,"%s/%s",spool,name);
	strlwr(newname);
	s = strstr(newname,".itm");
	if (s!=NULL) strcpy(s,".tmp");
	if (remove(newname)!=0) if (errno!=ENOENT) emsg("Couldn't remove (%s) %s\n",newname,strerror(errno));
	if (rename(oldname,newname)!=0) emsg("Couldn't rename (%s)  (%s) %s\n",oldname,newname,strerror(errno));

	f = fopen(newname,"r");
	if (f==NULL) {emsg("Couldn't read {%s} (%s)\n",newname,strerror(errno)); return;}

	article = str_new();

 	for (;!feof(f);) {
	  if (fgets(bf,BIGBF-10,f)!=NULL) {
		s = strchr(bf,'\015'); if (s!=NULL) *s = 0;
		s = strchr(bf,'\012'); if (s!=NULL) *s = 0;
		s = bf + strlen(bf);
		strcpy(s,"\015\012");
		str_addsn(article,bf);
	  }
	  if (str_len(article)>max_size) break;
	}
	fclose(f);
	if (str_len(article)>max_size) {
		emsg("ARticle is too large\n");
		remove(newname);
	} else {
		if (article_send()) {
			remove(newname);
		}
	}
	str_free(article);
}
int article_send(void)
{
	int lp;
	char bf[BFSZ];
	nprintf(chan,"post\015\012");
	if (!ngetline(chan,bf)) {emsg("Error:2 channel closed\n"); return 0;}
	if (atoi(bf)!=340) {emsg("Error:3 %s",bf); return FALSE;}
	
	nntp_write(chan,article);
	for (lp=0;nntp_isbusy(chan) && lp<10000;lp++) {
		nntp_write_now(chan);
	}
	nprintf(chan,".\015\012");
	if (!ngetline(chan,bf)) {emsg("Error:4 channel closed\n"); return 0;}
   	if (atoi(bf)!=240) {emsg("Error:5 %s",bf); return FALSE;}
	emsg("Article successfully posted :-) \n");
	return TRUE;
}
void nprintf(int chan,char * arg_list, ...)
{
 	va_list arg_ptr;
 	char *format, output[1000];
 	va_start(arg_ptr, arg_list);
 	format = arg_list;
	vsprintf(output, format, arg_ptr);
	nntp_write_s(chan,output,strlen(output));
/*	printf("nntpcmd [%d] %s",chan,output); */
}

int ngetline(int chan, char *bf)
{
	int n;
	char reason[BFSZ];
	n = nntp_read_timed(chan,bf,500,10000,reason);
	if (n<=0) return FALSE;
	return TRUE;	 	
}
int ngetlinex(int chan, char *bf)
{
	int n;
	n = nntp_read(chan,bf,500);
	if (n<0) return FALSE;
	return TRUE;	 	
}

char *group_name(int i)
{
	return "(none)";
}


void log_write(char *bf);
int dmsg(char * arg_list, ...)
{
	return 0;
}
int filemsg(char * arg_list, ...)
{
 	va_list arg_ptr;
 	char *format, output[1000];
 	va_start(arg_ptr, arg_list);
 	format = arg_list;
	vsprintf(output, format, arg_ptr);
	perror("File error:");
	printf("%s",output);
	log_write(output);
	return 0;

}
int imsg(const char * arg_list, ...)
{
 	va_list arg_ptr;
 	char *format, output[1000];
 	va_start(arg_ptr, arg_list);
 	format = arg_list;
	vsprintf(output, format, arg_ptr);
/* printf("%s",output); */
	log_write(output);
	return 0;
}
int wmsg(char * arg_list, ...)
{
 	va_list arg_ptr;
 	char *format, output[1000];
 	va_start(arg_ptr, arg_list);
 	format = arg_list;
	vsprintf(output, format, arg_ptr);
	printf("%s",output);
	log_write(output);
	return 0;
}
int emsg(char * arg_list, ...)
{
 	va_list arg_ptr;
 	char *format, output[1000];
 	va_start(arg_ptr, arg_list);
 	format = arg_list;
	vsprintf(output, format, arg_ptr);
	printf("%s",output);
	log_write(output);
	return 0;
}
void log_write(char *bf)
{
	time_t t;
	char tstr[30];
	struct tm *tt; 

	t = time(NULL);
	tt = localtime(&t);

	strcpy(tstr,ctime(&t));
	tstr[19] = 0;

	if (strlen(logfile)==0) return;
	flog = fopen(logfile,"a");
	if (flog!=NULL) {
		fprintf(flog,"%s %s",tstr+8,bf);
		fclose(flog);
	}
}
#ifndef unix
int lib_mail_file(char *to, char *subj, char *fname)
{
	return TRUE;
}
int lib_freespace(char *s)
{
	return 100000;
}
#endif
int diskuse_get(void)
{
	return 0;
}
char *nt_pcname(void);

char *lib_findfile(char *x)
{
	return NULL;
}
void dnews_manager_report(char *s)
{
	
}
int post_local(String *xitem, char *addr, int ismod)
{
	return TRUE;
}
void dnews_exit(char *reason, char *file, int line)
{
	printf("Crashing\n");
	exit(1);
}
static char msgid[BFSZ];
void send_bag(char *name)
{
	FILE *f;
	char fname[BFSZ],failname[BFSZ];
	char bf[BIGBF];
	int hlen;
	char *s;

	sprintf(fname,"%s/%s",spool,name);
	sprintf(failname,"%s/%s",spool,name);
	strlwr(fname);
	s = strstr(failname,".bag");
	if (s!=NULL) strcpy(s,".failed");

	f = fopen(fname,"r");
	if (f==NULL) {emsg("Couldn't read {%s} \n",fname); return;}

	article = str_new();
	tryagain = FALSE;
	failed = FALSE;
	hlen = 0;
 	for (;!feof(f);) {
	  if (fgets(bf,BIGBF-10,f)!=NULL) {		
		s = strchr(bf,'\015'); if (s!=NULL) *s = 0;
		s = strchr(bf,'\012'); if (s!=NULL) *s = 0;
		if (hlen<0) emsg("hlen = %d, thats odd: %s\n",hlen,bf);
		if (hlen<=0) {
			if (strncmp(bf,"#! rnews",8)!=0) {
				emsg("Invalid header record, %s\n",bf);
				goto fail;
			}
			hlen = atoi(bf+9);		 	   	
		} else {
			hlen -= (strlen(bf) + 1);
			if (strcmp(bf,".")==0) strcpy(bf,"..");
			if (strlen(msgid)==0) {
			 	if (strncmp(bf,"Message-ID:",11)==0) {
					strcpy(msgid,bf+12);
				}
			}
			s = bf + strlen(bf);
			strcpy(s,"\015\012");
			str_addsn(article,bf);
		}
		if (hlen==0) {
			article_sendihave();
			str_clear(article);
			strcpy(msgid,"");
		}
		if (tryagain) break;
	  }
	}
	fclose(f);
	if (!tryagain) remove(fname);
	return;
fail:
	if (f!=NULL) fclose(f);
	rename(fname,failname);

}

/*
   235 article transferred ok
   335 send article to be transferred.  End with <CR-LF>.<CR-LF>
   435 article not wanted - do not send it
   436 transfer failed - try again later
   437 article rejected - do not try again
*/
int article_sendihave(void)
{
	int lp;
	int nntperr;
	char bf[BFSZ];
	nprintf(chan,"ihave %s\015\012",msgid);
	if (!ngetline(chan,bf)) {emsg("Error:2 channel closed\n"); return 0;}
	nntperr = atoi(bf);
	if (nntperr==436) {emsg("Try later %s %s\n",msgid,bf);  tryagain = TRUE; return 0;}
	if (nntperr!=335) {emsg("Transfer failed: %s %s\n",msgid,bf);  return 0; }
	nntp_write(chan,article);
	for (lp=0;nntp_isbusy(chan) && lp<10000;lp++) {
		nntp_write_now(chan);
	}

	nprintf(chan,".\015\012");
	if (!ngetline(chan,bf)) {emsg("Error:4 channel closed\n"); return 0;}
	nntperr = atoi(bf);
	if (nntperr==436) {emsg("Try later %s\n",bf); tryagain = TRUE; return 0;}
	if (nntperr!=235) { emsg("Transfer failed: %s",bf); return FALSE;}
	emsg("Sent ok %s \n",msgid);
	return TRUE;
}
void fimsg(char * arg_list, ...)
{
        va_list arg_ptr;
        char *format;
        int len;
        char bf[BFSZ];
	char output[5000];

        ncpy(bf,strerror(errno),BFSZ-1);

        va_start(arg_ptr, arg_list);
        format = arg_list;
        len = vsprintf(output, format, arg_ptr);
        emsg("(%s) %s",bf,output);
}
int lib_msec(void)
{
	return 1;
}