#include <stdio.h>

/*
 * BSPLIT -- Split a large binary file up into a series of smaller files.
 *
 * Usage:	 bsplit [-p prefix] [-s suffix] [-b bytes] [-v] file
 *
 * The output filenames are of the form [prefix]NN[suffix] where NN is the
 * sequence number 00, 01, etc.  A "cat prefix*" will reconstruct the
 * original file.  The default prefix is "part", the default suffix is none,
 * and the befault output file segment size is 512000 bytes.
 */

#define	PREFIX		"part"
#define	SUFFIX		""
#define	SEGSIZE		512000
#define	BUFSIZE		32768
#define	SZ_PREFIX	32
#define	SZ_FNAME	256
#define	MODE		0644
#define min(a,b)	((a)<(b)?(a):(b))

main (argc, argv)
int	argc;
char	*argv[];
{
	char	buf[BUFSIZE];
	char	prefix[SZ_PREFIX];
	char	suffix[SZ_PREFIX];
	char	fname[SZ_FNAME];
	char	*argp, *infile = "";
	int	segsize, verbose, nfiles;
	int	arg, nb, in, out, nleft, total;

	strcpy (prefix, PREFIX);
	strcpy (suffix, SUFFIX);
	segsize = SEGSIZE;
	verbose = 0;

	/* Process the argument list. */
	for (arg=1;  arg <= argc && (argp = argv[arg]);  arg++) {
	    if (*argp == '-') {
		if (strcmp (argp, "-p") == 0)
		    strcpy (prefix, argv[++arg]);
		else if (strcmp (argp, "-s") == 0)
		    strcpy (suffix, argv[++arg]);
		else if (strcmp (argp, "-b") == 0)
		    segsize = atoi (argv[++arg]);
		else if (strcmp (argp, "-v") == 0)
		    verbose++;
		else {
		    fprintf (stderr, "unknown switch %s\n", argp);
		    exit (1);
		}
	    } else
		infile = argp;
	}

	/* Open the input file. */
	if (*infile == '\0' || strcmp(infile,"-") == 0)
	    in = 0;
	else if ((in = open (infile, 0)) == -1) {
	    fprintf (stderr, "cannot open %s\n", infile);
	    exit (2);
	}

	/* Process the input stream. */
	for (nfiles=0;  nfiles <= 99;  nfiles++) {
	    /* Open the output file. */
	    sprintf (fname, "%s%02d%s", prefix, nfiles, suffix);
	    if ((out = creat (fname, MODE)) == -1) {
		fprintf (stderr, "cannot create file %s\n", fname);
		exit (3);
	    }

	    /* Write the file data. */
	    for (nb=total=0, nleft=segsize;  nleft > 0;  nleft -= nb)
		if ((nb = read (in, buf, min(nleft,BUFSIZE))) > 0) {
		    if (write (out, buf, nb) != nb) {
			fprintf (stderr, "file write error on %s\n", fname);
			close (out);
			exit (4);
		    }
		    total += nb;
		} else
		    break;

	    /* Close the output file, and quit if no more data. */
	    close (out);
	    if (total <= 0) {
		unlink (fname);
		if (nfiles <= 0)
		    fprintf (stderr, "null length file, no output\n");
		else if (verbose)
		    printf ("\n");
		break;
	    } else if (verbose) {
		printf ("%02d ", nfiles);
		fflush (stdout);
	    }
	}

	/* The following would be easy to avoid, but isn't worth it. */
	if (nfiles > 99) {
	    fprintf (stderr, "too many output files\n");
	    exit (99);
	}

	close (in);
	exit (0);
}
