/* iffar - IFF CAT archiver, main()

   By Karl Lehenbauer, version 1.2, release date 5/9/88.
   This code is released to the public domain.
   See the README file for more information.

*/

/* iffar - iff 'cat' archiver, 3/26/88 */

#include <stdio.h>
#include "assert.h"

/* options */
int verbose = 0;
int insert_after = 0;
int insert_before = 0;
int suppress_creation_message = 0;

/* if insert_after or insert_before is set, this global has the relevant
 * name */
char *location_modifier_name;

/* variables */
int number_of_arguments;	/* number of args to the program, a global */

/* this'll point to the command line's command char string */
char *cmdkeys;

/* this'll be the name of the archive file */
char *archive_name;

/* this'll contain the command */
char command_key;

/* if a command must have some names as arguments, must_have_names can be 
 * called to insure that arguments were supplied.
 * Note that what constitutes the presence of arguments varies whether
 * a positional modifier ('i', 'b' or 'a') was specified.
 */
must_have_names()
{
	if ((insert_before || insert_after) && (number_of_arguments < 5))
	{
		fprintf(stderr,"a positioning element and at least one other element must be specified for\n");
		fprintf(stderr,"the combination of options you have requested.\n");
		usage();
	}
	if (number_of_arguments < 4)
	{
		fprintf(stderr,"at least one archive element must be specified for this option\n");
		usage();
	}
}

header()
{
	fprintf(stderr,"iffar - public domain IFF CAT archiver, Version 1.1, by Karl Lehenbauer\n\n");
	fprintf(stderr,"This program maintains archives of IFF FORM, CAT and LIST files\n");
	fprintf(stderr,"in a manner that complies with the IFF CAT specification.\n");
}

/* usage  print usage text and exit */
usage()
{
	fprintf(stderr,"\nUsage: iffar key [posname] afile name ...\n\n");
	fprintf(stderr,"key can be one of the following:\n");
	fprintf(stderr,"\td\tdelete\n\tr\treplace\n\tq\tquick append\n");
	fprintf(stderr,"\tt\ttable of contents\n\tx\textract\n");
	fprintf(stderr,"and zero or more of the following options:\n");
	fprintf(stderr,"\tv\tverbose\n\ta\tafter\n\ti,b\tbefore\n");
	fprintf(stderr,"\tc\tsuppress creation message\n");
	cleanup();
	exit(1);
}

main(argc,argv)
int argc;
char *argv[];
{
	int i, j;
	int archive_fd, files;
	char *nameptr;
	char **entryname_pointers;
	int entrycount;

	number_of_arguments = argc;

	if (argc < 3)
	{
		header();
		usage();
	}

	/* assign nice variable names to various command line arguments */
	cmdkeys = argv[1];
	command_key = *cmdkeys;
	archive_name = argv[2];
	location_modifier_name = (char *)NULL;
	entryname_pointers = &argv[3];
	entrycount = argc - 3;

	/* figure out any modifiers specified to the main function requested */
	for (i = 1; i < strlen(cmdkeys); i++)
	{
		switch(cmdkeys[i])
		{
			case 'v':				/* verbose selected, set verbose flag */
				verbose = 1;
				break;

			/* 'after' option, make sure they've selected 'r' or 'm' as
			 * the main command.  Also, make sure they haven't already
			 * chosen the insert_before option.  After that, we're OK,
			 * so twiddle parameters and break
			 */
			case 'a':
				if (command_key != 'r' && command_key != 'm')
				{
					fprintf(stderr,"i, b and a modifiers are only good for r and m options\n");
					usage();
				}
				if (insert_before)
				{
					fprintf(stderr,"you can't select 'insert before' and 'insert after'\n");
					usage();
				}
				insert_after = 1;
				location_modifier_name = argv[3];
				entryname_pointers = &argv[4];
				entrycount = argc - 4;
				break;

			/* 'insert before' option, make sure they've selected 'r' or
			 * 'm' as the main command.  Also, make sure they haven't already
			 * chosen the insert_after option.  After that, we're OK,
			 * so twiddle parameters and break
			 */
			case 'i':				/* insert; before */
			case 'b':
				if (command_key != 'r' && command_key != 'm')
				{
					fprintf(stderr,"i, b and a modifiers are only good for r and m options\n");
					usage();
				}
				if (insert_after)
				{
					fprintf(stderr,"you can't select 'insert before' and 'insert after'\n");
					usage();
				}
				insert_before = 1;
				location_modifier_name = argv[3];
				entryname_pointers = &argv[4];
				entrycount = argc - 4;
				break;

			case 'c':				/* supress creation message */
				suppress_creation_message = 1;
				break;

			default:				/* unrecognized option */
				fprintf(stderr,"option '%c' unrecognized\n",cmdkeys[i]);
				usage();
		}
	}

	/* now execute the major command */

	switch(command_key)
	{
		case 'd':		/* delete */
			must_have_names();
			delete_entries(archive_name,entryname_pointers,entrycount);
			break;

		/* replace - if the archive doesn't exist, fall through to
		 * quick append */
		case 'r':
			must_have_names();
			if ((archive_fd = open(archive_name,O_RDONLY)) != -1)
			{
				close(archive_fd);
				replace_entries(archive_name,entryname_pointers,entrycount);
				break;
			}
		case 'q':		/* quick append */
			must_have_names();
			checknew(archive_name);
			if ((archive_fd = open_quick_append(archive_name)) == -1)
				break;
			quickappend_entries(archive_fd,entryname_pointers,entrycount);
			break;
		case 't':		/* table of contents */
			table_of_contents(archive_name);
			break;

		case 'm':		/* move */
			fprintf(stderr,"move option not implemented\n");
			must_have_names();
			break;
		case 'x':		/* extract */
			extract(archive_name,entryname_pointers,entrycount);
			break;

		default:
			fprintf(stderr,"requested command (%c) is invalid\n",command_key);
			usage();
	}
	cleanup();
	exit(0);
}

/* end of main.c */
