#include <stdio.h>
#include <string.h>
#include <dir.h>
#include <stdlib.h>
#include <process.h>
#include "regexp.h"

#define	FALSE	0
#define TRUE	1
#define MAXREG	10              /* Maximum number -s options allowed */

main (int argc,char *argv[],char *env[])

{
	/* Extern routines */

	extern	char	*optarg;
	extern	int	optind;
	extern  int	getopt();
	extern  char	*cdrom();
	extern	char	*unzip();
	extern  char	*unarc();
	extern	char	*tmpdir();
	extern  void 	createdir();
	extern	char	*getindex();
	extern	void	usage();

	/* Declarations */

	FILE	*fp;
	char	name[BUFSIZ];
	char	line[BUFSIZ];
	char	directory[BUFSIZ];
	char	description[BUFSIZ];
	char	search[BUFSIZ];
	char	command[BUFSIZ];
	char	todir[BUFSIZ];
	char	ext[BUFSIZ];

	int	c;
	int	desc;
	int	found;
	int	unpack;
	int 	copy;
	int	delete;
	int	force;
	int	and;
	int	expr;
	int	prev;
	int	batch;
	int     extension;

	struct	regexp	*exp[MAXREG];
	int	neg[MAXREG];

	/* Set the default values */

	strcpy (todir,tmpdir());
	strcpy (name,getindex());
	strcpy (search,"");
	strcpy (directory,"");
	strcpy (ext,"*.*");
	desc   	  = TRUE;
	unpack 	  = FALSE;
	copy   	  = FALSE;
	delete    = FALSE;
	force	  = FALSE;
	and       = TRUE;
	batch     = FALSE;
	extension = FALSE;
	expr	  = 0;
	prev	  = '\0';

	/* Option handling */

	while ((c = getopt(argc, argv, "i:s:t:e:fucdnorgbh?")) != EOF)
	{

		switch (c)
		{
		case 'I':
		case 'i':
			strcpy (name,optarg);
			break;
		case 'N':
		case 'n':
			break;
		case 'S':
		case 's':
			strcpy (search,optarg);

			/* Every search string is mapped to lower case */
			/* to make search more easily		       */

			strlwr (search);

			/* If previous option letter is an 'n' or 'N'   */
			/* then this means negate the following regular */
			/* expression					*/

			if (prev == 'n' || prev == 'N')
			{
				neg[expr] = TRUE;
			}
			else
			{
				neg[expr] = FALSE;
			}

			/* Skip this regular expression if maximum exceeded */

			if (expr > MAXREG - 1)
			{
				printf ("Skipping search string %s more %d regular expressions exceeded\n",optarg,MAXREG);
			}
			else
			{
				/* Compile this regular expression */
				exp[expr] = regcomp(search);
				expr++;
			}
			break;
		case 'F':
		case 'f':
			/* Full path names only used in search */
			desc = FALSE;
			break;
		case 'U':
		case 'u':
			if (copy)
			{
				printf ("Options -u and -c are mutal exclusive\n");
				exit (1);
			}
			unpack = TRUE;
			break;
		case 'C':
		case 'c':
			if (unpack)
			{
				printf ("Options -u and -c are mutual exclusive\n");
				exit (1);
			}

			copy   = TRUE;
			break;
		case 'T':
		case 't':
			/* Target dir */
			strcpy(todir,optarg);
			break;
		case 'D':
		case 'd':
			/* Wipe target dir */
			delete  = TRUE;
			break;
		case 'R':
		case 'r':
			/* Forced wipe */
			force   = TRUE;
			break;
		case 'O':
		case 'o':
			/* Match if one of the search options matches */
			/* Default it has to match all search options */

			and     =  FALSE;
			break;
		case 'B':
		case 'b':
			/* Output only the commands but do nothing */
			batch   =  TRUE;
			break;
		case 'E':
		case 'e':
			/* Filenames to be extracted default all files */
			strcpy(ext,optarg);
			extension = TRUE;
			break;
		case 'h':
		case 'H':
		case '?':
			/* HELP !!!! */
			usage();
			exit (1);
			break;
		default:
			/* ILLEGAL OPTION BUT ANYWAY HELP !!!! */
			usage();
			exit (1);
			break;
		}

		prev = c;
	}
	/* -b option in conjuction with -u or -c is useful */

	if (batch && !(copy || unpack))
	{
		printf ("-b option is only useful together with -c or -u option \n");
		exit (1);
	}

	if (extension && !unpack)
	{
		printf ("-e option can only be used together with -u option\n");
		exit (1);
	}

	/* If no search expression is given match everything */

	if (expr == 0)
	{
		exp[0] = regcomp ("");
		neg[0] = FALSE;
		expr++;
	}

	/* If target directory doesn't exsist create it */

	if (!batch && !isdir(todir))
	{
		createdir(todir);
	}

	/* If target directory is only the drive letter then use */
	/* force option to wipe it 				 */

	if (delete && !force && todir[1] == ':' && todir[2] == '\0')
	{
		printf ("Use -r -d to delete an entire disk\n");
		exit (1);
	}

	/* If target directory is the current directory the use */
	/* force option to wipe it				*/

	if (delete && !force && (strcmp(todir,".") == 0))
	{
		printf ("Not purging current directory\n");
		printf ("Use -d -r to remove data in current directory");
		exit (1);
	}

	if (delete)
	{
		/* We may wipe target directory clean */
		 cleanup (todir);
	}

	/* Quit after we have wiped target dir but nothing */
	/* to do afterwards				   */

	if (delete && !unpack && !copy) exit(1);

	/* Open index file */

	if ((fp = fopen (name,"r")) == (FILE *) NULL)
	{
		printf ("Error opening file %s\n",name);
		exit (1);
	}

	/* We use the string name later again so initialise it */
	strcpy (name,"");

	/* Read lines from index file */
	while (fgets(line,BUFSIZ,fp) != (char *) NULL)
	{
		/* If entry is directory */
		if (strncmp (line,"Directory",7) == 0)
		{
			/* Scan directory name in line */

			sscanf (line,"%*s %s\n",directory);

			/* Map directory name to lowercase */

			strlwr(directory);

			/* Replace every forward slash by a backward slash */

			for (c=0 ; c < strlen(directory) ; c++)
			{
				if (directory[c] == '/') directory[c]= '\\';
			}

			continue;
		}

		/* Skip lines that do not contain any useful information */

		if (strncmp (line," Filename   Type Length   Date   Description",15) == 0 ) continue;
		if (strncmp (line,"==============================================",10) == 0 ) continue;

		/* And also empty lines */

		if (strlen(line) < 2) continue;

		/* Map line to lower case and remove newline at end of line */

		strlwr(line);
		line[strlen(line)-1] = '\0';

		/* We haven't found a thing yet */

		found=FALSE;

		/* Use only the filenames from the line if description       */
		/* is not to be used in search and add full path do filename */
		if (!desc)
		{
			sscanf  (line,"%s %*s",name);
			sprintf (line,"%s\\%s%s",cdrom(),directory,name);
		}

		/* Flush standard output and stderr               */
		/* I noticed some trouble with output redirection */
		/* These lines fix this problem 	          */

		fflush(stdout);
		fflush(stderr);


		if (and)
		{
			/* We have a match if all regular expressions */
			/* match the line	         	      */

			for (c=0; c < expr ; c++)
			{
				if (neg[c] == TRUE ? regexec(exp[c],line) == 0 : regexec(exp[c],line) != 0)
				{
					found = TRUE;
				}
				else
				{
					found = FALSE;
					break;
				}
			}
		}
		else
		{
			/* We have a match if a single expression matches the line */

			for (c=0; c < expr ; c++)
			{
				if (neg[c] == TRUE ? regexec(exp[c],line) == 0 : regexec(exp[c],line) != 0)
				{
					found = TRUE;
					break;
				}
			}
		}

		/* If search only print the matching line */

		if (found)
		{
			if (!unpack && !copy && !batch) printf ("%s\n",line);
		}

		/* Remove description,date and size from line */

		if (desc)
		{
			sscanf (line,"%s %*s",name);
		}

		if (found && unpack)
		{
			/* Build command line for zip files */

			if (strcmp(strrchr(name,'.'),".zip") == 0)
			{
				sprintf (command,"%s %s\\%s%s %s %s",unzip(),cdrom(),directory,name,todir,ext);
				printf  ("%s\n",command);
				if (!batch) system  (command);
				continue;
			}

			/* The same for arc files */

			if (strcmp(strrchr(name,'.'),".arc") == 0)
			{
				sprintf (command,"%s %s\\%s%s %s %s",unarc(),cdrom(),directory,name,todir,ext);
				printf  ("%s\n",command);
				if (!batch) system  (command);
				continue;
			}

			/* Copy the rest that matches */

			sprintf (command,"copy %s\\%s%s %s",cdrom(),directory,name,todir);
			printf  ("%s\n",command);
			if (!batch) system  (command);

		}

		if (found && copy)
		{
			/* Build copy command for matching line */

			sprintf (command,"copy %s\\%s%s %s",cdrom(),directory,name,todir);
			printf  ("%s\n",command);
			if (!batch) system  (command);
		}
	}

	fclose (fp);

	/* Execute command set by POST environment variable */
	/* if something is copied or unpacked               */
	/* Useful for virus scanning the target directory   */

	if ((getenv("POST") != NULL) && (copy || unpack) && !batch)
	{
		system (getenv("POST"));
	}

}




