/*
 *  Splitter
 *
 *  A small program to split files in several protions with a defined
 *  size or number and join them together again.
 *
 *  Version 1.0 on 18-Oct-1993   Fully reliable version.
 *  Version 1.1 on 18-Oct-1993   Replaced fclose()/fopen() by rewind().
 *  Version 1.2 on 24-Nov-1993   Works now with MSDOS systems;
 *                               file buffer extended.
 *  Version 1.21 on 25-Nov-1993  Removed a small bug in the output.
 *
 *
 *  Usage: Splitter <file> [<spath>] [-j] [-p n] [-s n] [-d]
 *
 *   file  the file to split
 *   spath optional path of the splitted parts
 *   -j    join splitted parts
 *   -p    split into n portions
 *   -s    split into protions of n bytes size each
 *   -d    MSDOS option, uses extension for marking and "\" for paths
 *
 *
 *  DISCLAIMER: As usual, I can't take any responsibility for anything
 *              that might happen to you or your computer when you use
 *              this program.
 *
 *  This is freeware, i.e. you may give this program to anyone you like
 *  and upload it to any mailbox, bulletin board or software server as
 *  long as you leave this file as it is. If you have any ideas on how
 *  to advance the reliability or funtionality of this program, please
 *  let me know. But you may not use this code for anything commercial
 *  nor are you allowed to distibute any changed version on your self.
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define info "\nSplitter V1.21 on 11/25/1993\n\
(c)1993 by Martin Schlodder\n\n\
Usage: Splitter <file> [<dest>] [-j] [-p n] [-s n] [-d]\n\
 file  the file to split\n\
 spath optional path of the splitted parts\n\
 -j    join splitted path\n\
 -p    split into n portions\n\
 -s    split into protions of n bytes size each\n\
 -d    MSDOS option, uses extension for marking and \"\\\" for paths\n\n\
Address:\n\
 Martin Schlodder\n\
 Uhlandstr. 18\n\
 D 72336 Balingen\n\n\
Internet:\n\
 schlodder@student.uni-tuebingen.de\n"
#define nofile "\nPlease give me the name of the file you want me to split.\n"
#define lessarg "\nPlease give me at least the filename and one argument,\n\
or shall i guess what to do?\n"
#define errinparg "\nPlease give me the number of protions in the form of '-p 7' or '-s12'.\n"
#define errinsarg "\nPlease give me the size of the protions in the form '-s 12000' or '-s880000'.\n"
#define wrongarg "\nI don't know this option.\n"
#define noarg "\nPlease give me one (or more) of the three options '-j', '-p' or '-s'.\n"
#define wrongfile "\nCouldn't open file.\n"
#define nooutfile "\nCouldn't open output file!\n"
#define seekerr "\nCouldn't split file because i couldn't ascertain the file's size!\n"
#define fileempty "\nFile not splitted. Why should i split an ampty file?\n"

#ifndef SEEK_END
#define SEEK_END 2
#endif

char sfile[257],dfile[257],ext[257];
char *version="$VER: Splitter 1.21 (25.11.93)   ©1993 by Martin Schlodder";
char tmp[257];
short fbuf[16384];

main(int argc,char **argv){
  FILE *sfh=NULL,*dfh=NULL;
  char *filename=0,*pathname=0;
  char *name;
  int portions=0,i;
  long size=0,j;
  long dos=0;
  long join=0;
  int c=0;

  switch(argc){
  case 1:
    puts(info);
    exit(5);
  case 2:
    if(strchr(argv[1],'?')){
      puts(info);
      exit(0);
    }
    else if(strstr(argv[1],"-h")){
      puts(info);
      exit(0);
    }
    puts(lessarg);
    exit(5);
  }

  for(i=1;i<argc;++i){
    if(argv[i][0]!='-'){
      if(!filename)
	filename=argv[i];
      else
	pathname=argv[i];
    }else
      switch(argv[i][1]){
      case 'j':
	join=1;
	break;
      case 'p':
	if(argv[i][2]!=0){
	  if(!(portions=atoi(argv[i]+2))){
	    puts(errinparg);
	    exit(5);
	  }
	}
	else if(!(portions=atoi(argv[++i]))){
	  puts(errinparg);
	  exit(5);
	}
	break;
      case 's':
	if(argv[i][2]!=0){
	  if(!(size=atol(argv[i]+2))){
	    puts(errinsarg);
	    exit(5);
	  }
	}
	else if(!(size=atol(argv[++i]))){
	  puts(errinsarg);
	  exit(5);
	}
	break;
      case 'd':
	dos=1;
	break;
      default:
	puts(wrongarg);
	exit(5);
      }
  }

  if(!filename){
    puts(nofile);
    exit(5);
  }
  strcpy(sfile,filename);
  i=0;
  if(pathname){
    strcpy(dfile,pathname);
    i=strlen(dfile);
    if(i&&(dfile[i-1]!=':'))
      if(dos){
	if(dfile[i-1]!='\\')
	  dfile[i++]='\\';
      }else
	if(dfile[i-1]!='/')
	  dfile[i++]='/';
    if(dos)
      name=(char *)strrchr(sfile,'\\');
    else
      name=(char *)strrchr(sfile,'/');
    if(!name)
      name=(char *)strchr(sfile,':');
    if(name)
      strcpy(dfile+i,name+1);
    else
      strcpy(dfile+i,sfile);
  }else
    strcpy(dfile,sfile);
  ext[0]=0;
  if(name=(char *)strrchr(dfile,'.')){
    if(name>strrchr(dfile,':')){
      if(dos)
	i=(name>(char *)strrchr(dfile,'\\'));
      else
	i=(name>(char *)strrchr(dfile,'/'));
      if(i){
	if(!dos)
	  strcpy(ext,name);
	*name=0;
      }
    }
  }
  
  if(!(join||size||portions)){
    puts(noarg);
    exit(5);
  }

  if(!join){
    if(size){
      if(!(sfh=fopen(sfile,"rb"))){
	puts(wrongfile);
	exit(5);
      }
      setvbuf(sfh,(char *)fbuf,_IOFBF,sizeof(fbuf));
      if(portions){
	for(i=1;(i<=portions)&&c!=EOF;++i){
	  if(dos)
	    sprintf(tmp,"%s.%d",dfile,i);
	  else
	    sprintf(tmp,"%s_%d%s",dfile,i,ext);
	  if(!(dfh=fopen(tmp,"wb"))){
	    fclose(sfh);
	    puts(nooutfile);
	    exit(20);
	  }
	  for(j=0;(j<size)&&c!=EOF;++j){
	    c=fgetc(sfh);
	    if(c!=EOF)
	      fputc((char)c,dfh);
	  }
	  fclose(dfh);
	}
	if(feof(sfh))
	  j--;
	if(i==2)
	  printf("Splitted file %s into one portion with %ld Bytes.\n",sfile,j);
	else if(j==size)
	  printf("Splitted file %s into %d portions with %ld Bytes.\n",sfile,i-1,size);
	else
	  printf("Splitted file %s into\n  - %d portion%s with %ld Bytes and\n  - one portion with %ld Bytes.\n",sfile,i-2,(i==3)?"":"s",size,j);
      }else{
	for(i=1;c!=EOF;++i){
	  if(dos)
	    sprintf(tmp,"%s.%d",dfile,i);
	  else
	    sprintf(tmp,"%s_%d%s",dfile,i,ext);
	  if(!(dfh=fopen(tmp,"wb"))){
	    fclose(sfh);
	    puts(nooutfile);
	    exit(20);
	  }
	  for(j=0;(j<size)&&c!=EOF;++j){
	    c=fgetc(sfh);
	    if(c!=EOF)
	      fputc((char)c,dfh);
	  }
	  fclose(dfh);
	}
	if(i==2)
	  printf("Splitted file %s into one portion with %ld Bytes.\n",sfile,j-1);
	else
	  printf("Splitted file %s into\n  - %d portion%s with %ld Bytes and\n  - one portion with %ld Bytes.\n",sfile,i-2,(i==3)?"":"s",size,j-1);
      }
      fclose(sfh);
    }else{
      if(!(sfh=fopen(sfile,"rb"))){
	puts(wrongfile);
	exit(5);
      }
      setvbuf(sfh,(char *)fbuf,_IOFBF,sizeof(fbuf));
      if(fseek(sfh,0L,SEEK_END)){
	puts(seekerr);
	exit(20);
      }
      if(!(size=ftell(sfh))){
	puts(fileempty);
	exit(5);
      }
      rewind(sfh);
      size=(size+portions)/portions;
      for(i=1;i<=portions;++i){
	if(dos)
	  sprintf(tmp,"%s.%d",dfile,i);
	else
	  sprintf(tmp,"%s_%d%s",dfile,i,ext);
	if(!(dfh=fopen(tmp,"wb"))){
	  fclose(sfh);
	  puts(nooutfile);
	  exit(20);
	}
	for(j=0;(j<size)&&c!=EOF;++j){
	  c=fgetc(sfh);
	  if(c!=EOF)
	    fputc((char)c,dfh);
	}
	fclose(dfh);
      }
      fclose(sfh);
      j--;
      if(portions==1)
	printf("Splitted file %s into one portion with %ld Bytes.\n",sfile,j);
      else if(j==size)
	printf("Splitted file %s into %d portions with %ld Bytes.\n",sfile,portions,size);
      else
	printf("Splitted file %s into\n  - %d portion%s with %ld Bytes and\n  - one portion with %ld Bytes.\n",sfile,portions-1,(portions==2)?"":"s",size,j);
    }
  }else{
    if(!(sfh=fopen(sfile,"wb"))){
      puts(wrongfile);
      exit(5);
    }
    printf("Joined ");
    setvbuf(sfh,(char *)fbuf,_IOFBF,sizeof(fbuf));
    for(i=1;i>0;++i){
      if(dos)
	sprintf(tmp,"%s.%d",dfile,i);
      else
	sprintf(tmp,"%s_%d%s",dfile,i,ext);
      if(!(dfh=fopen(tmp,"rb"))){
	fclose(sfh);
	i=-1;
      }
      else{
	printf("'%s' ",tmp);
	if(fseek(dfh,0L,SEEK_END)){
	  puts(seekerr);
	  exit(20);
	}
	if(!(size=ftell(dfh))){
	  puts(fileempty);
	  exit(5);
	}
	rewind(dfh);
	for(j=0;(j<size);++j)
	  fputc(fgetc(dfh),sfh);
	fclose(dfh);
      }
    }
    fclose(sfh);
    printf("to '%s'.\n",sfile);
  }
}
