/*****************************************
 * Chad Feller				 *
 * feller@seismo.unr.edu		 *
 *					 *
 * Binary file converter for IEEE to	 *
 * pentium float.			 *
 *					 *
 * 24 September 2003	     converter.c *
 ****************************************/ 
/*****************************************
 * cogs "image" converter added		 *
 * 2 October 2003			 *
 * **************************************/
#include "converter.h"

int main(int argc, char **argv){

  char *infile=NULL, *outfile=NULL;
  int ret_val=0;
  short img_flg=false, *image_flag=NULL;
  image_flag=&img_flg;

  if((valid_args(argc, argv, &infile, &outfile,&image_flag))==0){
    if((process_file(infile,outfile,*image_flag))==1){
      ret_val=1;
    }
  }
  else{
    /* exit here so we don't free unallocated memory */
    return(1);
  }

  /* clean up */
  free(infile);
  free(outfile);
  
  return(ret_val);
}
/******************************************/
int process_file(char *fname_in, char *fname_out,short flag){

  short count=0;  /* counter for swaptwo() calls */
  int fd_in, fd_out;  /* file descriptors */
  ssize_t num_read; /* to hold num of bytes read */

  /* create swap arrays, four one-byte elements */
  unsigned char buffer[BUFFSIZE], newbuff[BUFFSIZE];

  fprintf(stdout, "current file being read ==> %s\n",fname_in);
  fprintf(stdout, "output file is	   ==> %s\n",fname_out);

  if((fd_in=open(fname_in,O_RDONLY))==-1){
    perror("converter: file open failed for input file");
    return(1);
  }
  if((fd_out=open(fname_out,O_WRONLY|O_CREAT,PERMS))==-1){
    perror("converter: file open failed for output file");
    return(1);
  }
  
  /* read input file in BUFFSIZE blocks */
  while((num_read=read(fd_in,buffer,BUFFSIZE))>0){
    /* reorder the four bytes just read */

    if(flag==true){  /* then cogs "image" data */
      swaptwo(buffer,newbuff);
      /* we only want this for the first eight bytes, so... */
      ++count;
      if(count>=2){  /* then swap the rest normally */
	flag=false;
      }
    }
    else{
      swapfour(buffer,newbuff);
    }

    /* write from buffer to outfile */
    if(write(fd_out,newbuff,num_read)<num_read){ /* short write error */
      /* clean up before we bail out */
      close(fd_in);
      close(fd_out);
      perror("converter: i/o error ");
      return(1);
    }
  }

  /* clean up */
  close(fd_in);
  close(fd_out);
  return(0);
}
/******************************************/
int swapfour(unsigned char *oldbuffer,unsigned char *newbuffer){

  short i;

  for(i=0;i<BUFFSIZE;++i){
    newbuffer[(BUFFSIZE-1)-i]=oldbuffer[i];
  }

  return(0);
}
/******************************************/
int swaptwo(unsigned char *oldbuffer, unsigned char *newbuffer){

  newbuffer[1]=oldbuffer[0];
  newbuffer[0]=oldbuffer[1];
  newbuffer[3]=oldbuffer[2];
  newbuffer[2]=oldbuffer[3];

  return(0);
}
/******************************************/
int valid_args(int argc,char **argv,char **inname,char **outname,short **imgflag){

  int i,flag1=false,flag2=false;

  errno=0;

  if(! ((argc>=5) && (argc<=6)) ){ /* argc has to be 5 or 6 */
    usage();
    return(1);
  }
  else{ 

    for(i=1;i<argc;++i){
      /*** for input file ***/
      if(strcmp(argv[i],"-i")==0){ /* check for infile flag */
        if(strlen(argv[i+1])>(FNAMEMAX-1)){ /* prevent buffer overflows */
	  errno=ENAMETOOLONG;
	  break;
        }
        /* size is good, allocate buffer */
        *inname=malloc((strlen(argv[i+1])+1)*sizeof(char));
	if(errno==ENOMEM){ /* check for allocation success */
	  break;
	}
        strcpy(*inname,argv[i+1]);
        flag1=true;
      }

      /*** for output file ***/
      if(strcmp(argv[i],"-o")==0){ /* check for outfile flag */
        if(strlen(argv[i+1])>(FNAMEMAX-1)){ /* prevent buffer overflows */
	  errno=ENAMETOOLONG;
	  break;
        }
        /* size is good, allocate buffer */
        *outname=malloc((strlen(argv[i+1])+1)*sizeof(char));
	if(errno==ENOMEM){ /* check for allocation success */
	  break;
	}
        strcpy(*outname,argv[i+1]);
        flag2=true;
      }

      /*** for cogs "image" files ***/
      if(argc==6){  /* the extra arg must be for "image" processing */
        if( (strcmp(argv[i],"--image")) == 0){
          **imgflag=true;
	}
      }
		      

    } /* end "for" loop */

    if((flag2==0) || (flag1==0) || (errno!=0) || ((argc==6) && (**imgflag==false))){
      /* check for allocated buffer   
       * this is possible if partial arguments are correct   
       * or the unlikely event that one buffer was allocated 
       * and one was not
       */
      if(flag1==true){
        free(*inname);
      }
      if(flag2==true){
        free(*outname);
      }
      if(errno==0){
        errno=EINVAL;
      }
      perror("converter error");
      if(errno!=ENOMEM){ /* if it is user error */ 
        usage();
      }
      return(1);
    } /* if flags */   

  } /* else */
  return(0);
}
/******************************************/
int usage(void){

 fprintf(stdout,
        "\n\tUsage: converter [option] [file] [option] [file]\
	\n\t       converter [processing option] [option] [file] [option] [file]\
	\n\n\tOptions:\
	\n\t-i is used to specify the input file\
	\n\t-o is used to specify the output file\
	\n\tProcessing options:\
	\n\t--image is used to specify a cogs \"image\" file\
	\n\n\te.g.: converter -i input_file -o output_file\
	\n\n\tor\
	\n\n\tconverter -i input_file -o output_file --image\
	\n\n");

 return(0);
}
/******************************************/
