#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <fcntl.h>  
#include <errno.h>
#ifndef isunix  
#include <process.h>  
#include <io.h>    
#include <direct.h>    
#endif
#include "pipelib.h"
char *myncpy(char *dst, char *src, int len);
void lib_mkdir(char *s);
void child_log(char *s);
void cfilemsg(char * arg_list, ...);
void cemsg(char * arg_list, ...);

#ifndef FALSE
#define TRUE (!FALSE)
#define FALSE 0
#endif
static int log_id;
void pipe_child(int hread, int hwrite)
{
	char cmd[CMD_SIZE];
	log_id = hread;
	strcpy(cmd,"Writer 1.0");
	cemsg("Child %d %d Starting, send back %s\n",hread,hwrite,cmd);
	if (pipe_write(hwrite,cmd,CMD_SIZE)<CMD_SIZE) {
		cfilemsg("Error writing to pipe\n");
		return ;
	}
	for (;TRUE;) {
		if (pipe_read(hread,cmd,CMD_SIZE) < CMD_SIZE) { cfilemsg("pipe_read(cmd) failed"); return;}
		if (strcmp(cmd,"exit") == 0) {
			cemsg("Exit requested by parent dnews process\n");
			return;
		}
		else if (strcmp(cmd,"sync") == 0) do_sync(hwrite);
		else do_write(hread,cmd); 
	}
}
/* write isnew len gid num len name  */
void do_write(int hread, char *cmd)
{
	FILE *fout;
	char *mde;
	char cmdcpy[BFSZ];
	char fname[BFSZ];
	int isnew,gid,num,flen,rest,chunk,len,l;
	char *s;
	char bf[PIPE_BIG];
	strcpy(cmdcpy,cmd);
	s = strtok(cmd," "); if (s==NULL) goto fail;
	s = strtok(NULL," "); if (s==NULL) goto fail;
	isnew = atoi(s);
	s = strtok(NULL," "); if (s==NULL) goto fail;
	len = atoi(s);
	s = strtok(NULL," "); if (s==NULL) goto fail;
	gid = atoi(s);
	s = strtok(NULL," "); if (s==NULL) goto fail;
	num = atoi(s);
	s = strtok(NULL," "); if (s==NULL) goto fail;
	flen = atoi(s);
	s = strtok(NULL," "); if (s==NULL) goto fail;
	strncpy(fname,s,200);
	rest = len;
	mde = "ab";
	if (isnew) mde = "wb";
	fout = fopen(fname,mde);
	if (fout==NULL) {
		if (errno==ENOENT) {
			cemsg("Creating directory for %s\n",fname);
		 	lib_mkdir(fname);
			fout = fopen(fname,mde);
		}
		if (fout==NULL) {
			sprintf(cmd,"error Couldn't open %s %s",fname,strerror(errno));
			sendback(cmd);
		}
	}
	if (fout!=NULL) {
		l = filelength(fileno(fout)) + rest;
		if (flen>=0) if (l!=flen) {
			cemsg("(disabled) Correct file length for %d:%d was %d should be %d\n",gid,num,flen,l);
		 	/* Disabled just for testing purposes.
		 	sprintf(cmd,"fixlength %d %d",gid,num); 
			sendback(cmd);*/
		}
	}
	for (;rest>0;) {
		chunk = PIPE_BIG;
		if (chunk>rest) chunk = rest;
		if (pipe_read(hread,bf,chunk)<chunk) {cfilemsg("pipe_read(data) failed"); return;}
		if (fout!=NULL) if (fwrite(bf,1,chunk,fout)<(unsigned int) chunk) {sendback("error Write failed");}
		rest -= chunk;
	}
	if (fout!=NULL) fclose(fout); /* Remove this when optimizing (put fflush instead) */
	return;
fail:
	cemsg("Major failure in pchild {%s}\n",cmdcpy);
}
static char *err_stack[100];
static int nerr;
void do_sync(int h)
{
	int i;
	char cmd[CMD_SIZE];
 	for (i=0; i<nerr; i++) {
		pipe_write(h,err_stack[i],CMD_SIZE);
	}
	nerr = 0;
	strcpy(cmd,"ok ok");
	pipe_write(h,cmd,CMD_SIZE);
}
void sendback(char *s)
{
	if (nerr>0) if (strcmp(s,err_stack[nerr-1])==0) return;
	cemsg("SendBack %s\n",s);
	if (nerr>90) {cemsg("Couldn't send error back to parent\n"); return;}
 	if (err_stack[nerr]==NULL) err_stack[nerr] = malloc(BFSZ);
 	strcpy(err_stack[nerr],s);
	nerr++;
}
void lib_mkdir(char *s)
{
   int r;
   char bf[BFSZ];
   
   myncpy(bf,s,BFSZ-1);
   if (strlen(s)<2) return;
   s = bf+2;
   for (;*s!=0; s++)  {
      if ((*s=='/') || (*s == '\\'))  {
         *s = 0;
#ifdef isunix
	r = mkdir(bf,0770);
#else
         r = mkdir(bf);
#endif
         *s = '/';
      }
   }
}
char *myncpy(char *dst, char *src, int len)
{
        char *xdst = dst;
        int xlen = len;
        for (;(*src !=0) && (len>0); ) {*dst++  = *src++; len--;}
        *dst++ = 0;
        xdst[xlen] = 0;
        return xdst;
}
void cemsg(char * arg_list, ...)
{
        va_list arg_ptr;
        char *format;
        char output[10000];
        int len;
        va_start(arg_ptr, arg_list);
        format = arg_list;
        len = vsprintf(output, format, arg_ptr);
	child_log(output);
}
void cfilemsg(char * arg_list, ...)
{
        va_list arg_ptr;
        char *format;
        char output[10000];
        int len;
        va_start(arg_ptr, arg_list);
        format = arg_list;
        len = vsprintf(output, format, arg_ptr);
	child_log(output);
	sprintf(output,"%s\n",strerror(errno));
	child_log(output);
}
void child_log(char *s)
{
	char bf[BFSZ];
 	static FILE *f;
        time_t t;
        char tstr[30];
        struct tm *tt; 
        t = time(NULL);
        tt = localtime(&t);
        strcpy(tstr,ctime(&t));
        tstr[19] = 0;


	if (f==NULL) {
		sprintf(bf,"pchild%d.log",log_id);
		f = fopen(bf,"w");
		if (f==NULL) {perror(bf); return;}			
	} 
 	fprintf(f,"%s %s",tstr+8,s);
	fflush(f);
}

#ifdef isunix
int filelength(int x)
{
	return file_length(x);
}
#endif
