/* Yek.c
 *
 * Split large files into smaller ones
 *
 * Yek is copyright (c) 1993 by Daniel Kussendrager
 *
 * Version     Date     Author                  Comment
 * =======     ======   ==================      ==============================
 * 0.x                                          Before written history
 * 1.0         140792   Daniel Kussendrager     Cosmetic changes to the source
 * 1.1         231092   Daniel Kussendrager     Added default outname
 * 1.2         070193   Daniel Kussendrager     First public release
 *
*/

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

#ifndef EXIT_FAILURE
   #define EXIT_FAILURE 1
#endif

#define DEFAULT_BUFSIZE 100000
#define DEFAULT_MAXLENGTH 730000
#define DEFAULT_OUTFILENAME "YekOut"

static const char *version = "\0$VER: Yek 1.2 (07.01.93)";
static char *usagestring =
"Usage: Yek [-v(erbose)] [-f <output filename>] [-b <buffersize>]\n"
"           [-l <output file length>] <file>";
static char *ErrorNoInput = "Couldn't open inputfile";
static char *ErrorNoOutput = "Couldn't open outputfile";

void createname( char * );
void bump( char * );
void usage( void );
void gracefulexit( char * );

FILE *ifp, *ofp;

void main(int argc, char **argv)
{
   int      verbose = 0, i, bytesread, bytefill, outlength,
            bufsize = DEFAULT_BUFSIZE, maxlength = DEFAULT_MAXLENGTH;
   char     Option, Infile[80], Outfile[80] = DEFAULT_OUTFILENAME;
   unsigned char *buffer;

   if (argc < 2)
      usage();
   i = 1;
   while (argv[i][0] == '-')
   {
      Option = argv[i++][1];
      switch (Option) {
      case 'v':
         verbose = 1;
         break;
      case 'f':
         if (argv[i])
         {
            strcpy(Outfile, argv[i++]);
            break;
         }
         else
            usage();
   
      case 'b':
         if (argv[i])
         {
            bufsize = atoi(argv[i++]);
            break;
         }
         else
            usage();
   
      case 'l':
         if (argv[i])
         {
            maxlength = atoi(argv[i++]);
            break;
         }
         else
            usage();
   
      default:
         printf("Unknown option %c\n", Option);
      }
   }
   if (i == argc)
      usage();

   if (!(buffer = (unsigned char *) malloc(bufsize)))
      gracefulexit("Couldn't allocate a buffer");

   strcpy(Infile, argv[i]);
   
   createname(Outfile);

   if ((ifp = fopen(Infile, "r"))) {
      if (!(ofp = fopen(Outfile, "w")))
         gracefulexit(ErrorNoOutput);

      outlength = 0;
      while ((bytesread = fread(buffer, 1, bufsize, ifp)))
      {
         if (verbose)
            printf("%d bytes read\n", bytesread);
         if (outlength + bytesread <= maxlength)
         {
            fwrite(buffer, 1, bytesread, ofp);
            outlength += bytesread;
         }
         else
         {
            unsigned char *tbuffer = buffer;
            int bytesleft = bytesread;
            while (bytesleft - (bytefill = (maxlength - outlength)) > 0)
            {
               fwrite(tbuffer, 1, bytefill, ofp);
               bytesleft -= bytefill;
               tbuffer += bytefill;
               fclose(ofp);
               bump(Outfile);
               if (!(ofp = fopen(Outfile, "w")))
                  gracefulexit(ErrorNoOutput);
               outlength = 0;
            }
            fwrite(tbuffer, 1, bytesleft, ofp);
            outlength = bytesleft;
         }
      }
   }
   else
      gracefulexit(ErrorNoInput);

   fclose(ifp);
   fclose(ofp);
   puts("Operation complete.");
}

void usage()
{
   puts(usagestring);
   exit(0);
}

void createname(char *name)
{
   strcat(name, ".000");
}

void bump(char *name)
{
   int curnum;
   char suffix[4];
   curnum = atoi(name + strlen(name) - 3);
   curnum++;
   sprintf(suffix, "%03d", curnum);
   strcpy(name + strlen(name) - 3, suffix);
}

void gracefulexit(char *message)
{
   puts(message);
   if (ifp)
      fclose(ifp);
   if (ofp)
      fclose(ofp);
   exit(EXIT_FAILURE);
}
