/*	Assignment #4 CSE 5306
	Anan Tongprasith
	Compile:cc test.c -lcurses	*/
/********************************/
/*
Phase IV
The following modules have been added:
	
	mysearch()	used for retrieving and interpreting user search
criterias

	subsearch()	used for doing recursive search into subdir.
"strstr()" function is used.

	selectdir()	used for retrieving and compile user request
after directory search

	selectfile()	used for retrieving and compile user request
after file search

	strsearch()	used for string searching for Search command

	editbinary()	used for editing data content for EditBinary

	displaybinary()	used for displaying data content for EditBinary
*/
/*
	1. main()	manage windows, read and interpret input, and call other functions.
	2. listfile()	read current directory and put into buffer
	3. printdir()	print directory content from buffer	
	4. changedir()	handle Change Dir command
	5. myedit()	handle Edit and View command
	6. mycompile()	handle Compile command
	7. mycreate()	handle Create command
	8. mycopy()	handle Copy command
	9. mychmod()	handle Chmod command
	10. mymove()	handle Move command
	11. myrun()	handle Run command
	12. readhist()	read the history content from file
	13. printhist()	handle History command
	14. callhelp()	handle Help command
	15. checkfile() check/create .fileSystem
	16. readftable()	read dir contents of .fileSystem
	17. printftable()	display dir contents of .fileSystem
	18. rdln()	read a line
	19. countblock()	count available block left in .fileSystem
	20. updatetable()	update dir contents of .fileSystem
	21. fscopy()	handle cpTo command
	22. cpfrom()	handle cpFrom command
	23. rmfrom()	handle rmFrom command
	24. runfrom()	handle runFrom command
	25. comp()	compress file
	26. exp()	decompress file
	27. decrypt()	decrypt message
	28. encrypt()	encrypt message
	29. checkpass()	check password
	30. setpasswd()	set system password
	31. setfilepasswd()	set file password
*/
/********************************/
/* .fileSystem is a file with 400KB space for storing data, divided into 256 
byte blocks (total 1600 blocks), plus extra space for storing information. 
Access to data must be done in block.
*/

/* Password encyption uses a simple algorithm by shifting the first
character ascii code to 10 more, the second to 11 more, and so on.
The shift range returns to 10 when it reaches 20
*/

/* Compression and decompression use dynamic markov compression
algorithm which was developed by Gordon V. Cormack */

/*********************************/ 
/* Pico was used as an editor and viewer (with readonly flag). */

/* Directory content is saved in filelist[] variable. */

/* History contents is saved in /tmp/utaunixmenu.hist	*/

/* Gcc is used as a compiler	*/
/* Error type:
	- input file number out of range	-	simply ignore
	- obvious error, such as, nonexist file	-	prompt error
*/
/********************************/

#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include 
#include 
#include 
#include 
#include 

/* New type of directory entry */

typedef struct mydirent	{
	char name[40];		/*File name*/
	char date[20];		/*File date (last modified)*/
	char perm[11];		/*File mode*/
	long size;		/*File size*/
		
} mydirent;
struct filetable {
	char name[40];
	int ptr;
	long size;
	long origsize;
	mode_t mode;
	time_t time;
	time_t origtime;
	char passwd[20];
	};
/*****************************/

FILE *myfp;				/* history file */
char histlist[10][1024];int max;	/* history var */
int myfd,fcount,fptr[1600];struct filetable ftable[32];
WINDOW *wbtest;char mypasswd[20];
/* List of functions */ 

/* Function 1 - read directory and store in filelist */
int listfile(struct mydirent filelist[50]);

/* Function 2 - printout filelist */
void printdir(WINDOW *mywb,struct mydirent *filelist, int mypage,int max);

/* Function 3 - read and change directory */
int changedir(WINDOW *mywb,struct mydirent *filelist,int mytotal);

/* Function 4 - edit or view a file */
int myedit(WINDOW *mywb, struct mydirent *filelist,int mytotal,int c);

/* Function 5 - compile a file using gcc with additional flag from user*/
int mycompile(WINDOW *mywb,struct mydirent *filelist,int mytotal);

/* Function 6 - Create a file or a directory with mode from user */
int mycreate(WINDOW *mywb,struct mydirent *filelist);

/* Function 7 - Copy a file */
int mycopy(WINDOW *mywb,struct mydirent *filelist,int mytotal);

/* Function 8 - Change file or directory mode */
int mychmod(WINDOW *mywb,struct mydirent *filelist,int mytotal);

/* Function 9 - Move file */
int mymove(WINDOW *mywb,struct mydirent *filelist,int mytotal);

/* Function 10 - Run a file */
int myrun(WINDOW *mywb, struct mydirent *filelist,int mytotal);

/* Function 11 - Read a history file */
int readhist(void);

/* Function 12 - Print a history session */
int printhist(WINDOW *wb0,WINDOW *wb2);

/* Function 13 - Display help */
int callhelp(WINDOW *wb2,WINDOW *wb0);

/* function 14 - Check and/or Create .fileSystem */
int checkfile(void);

/* function 15 - Read directory of .fileSystem*/
void readftable(void);

/* function 16 - Display directory contents of .fileSystem */
void printftable(WINDOW *wb0);

/* function 17 - Read a single line from .fileSystem */
int rdln(char *buf1);

/* function 18 - Count available blocks left in .fileSystem */
int countblock(void);

/* function 19 - Update directory of .fileSystem */
void updatetable(void);

/* function 20 - Execute cpTo command */
int fscopy(WINDOW *mywb,struct mydirent *filelist);

/* function 21 - Execute cpFrom command */
int cpfrom(WINDOW *mywb,struct mydirent *filelist);

/* function 22 - Execute rmFrom command */
int rmfrom(WINDOW *mywb,struct mydirent *filelist);

/* function 23 - Execute runFrom command */
int runfrom(WINDOW *mywb);

/* function 24 - Perform compression*/
void comp(FILE *fd1,FILE *fd2);

/* function 25 - Perform decompression */
void exp(FILE *fd1,FILE *fd2);

/* function 26 - Decrypt message */
void decrypt(char *message);

/* function 27 - Encrypt message */
void encrypt(char *message);

/* function 28 - Check password */
int checkpass(WINDOW *mywb,char *testpass);

/* function 29 - Set system password */
int setpasswd(WINDOW *mywb,char* pass);

/* function 30 - Set file password */
int setfilepasswd(WINDOW *mywb);
void mysearch(WINDOW *mywb0, WINDOW *mywb1,WINDOW *mywb2);
void subsearch(char *c1, char *c2, char *slist,char *subname);
void display(WINDOW *mywb0,char result[20][25],int count[20],int max);
void selectdir(WINDOW *mywb2,char result[20][25],int max);
void selectfile(WINDOW *mywb0,WINDOW *mywb1,WINDOW *mywb2,char result[20][25],int max);
int strsearch(char *filename,char *substr);
int editbinary(WINDOW *mywb0,WINDOW *mywb2,struct mydirent *filelist,int mytotal);
void displaybinary(WINDOW *mywb0,int hex,char *content,long blockno);


/*********************/



main() 
{ 
  WINDOW *wb[3]; time_t begin,now;
  int myindex=0,mytotal=0,start,max,flag=1;
  int i, j, n, p,nonhist; pid_t pid;
  char buf[256], buf1[256];char pico[]="/usr/local/bin/pico";
  struct mydirent filelist[256];mode_t newmode;
  struct stat fp;

  char mymenu1[]="Operation: V)View, R)Compile, E)Edit, C)Chgdir, P)Prev, N)Next, S)EditBinary";
  char mymenu2[]=" A)Create, O)Copy, D)Chmod, M)Move, U)Run, I)History, H)Help, /)Search, X)Exit";
  char mymenu3[]=" B)cpTo, F)cpFrom, G)rmFrom, J)runFrom, K)dirFrom, L)SetPass, Q)setFilePass";
  
	time(&begin);		/*Mark beginning time*/
	myfd=checkfile();
	readftable();
	nonhist=readhist();		/*Read history file*/
	myfp=fopen("/tmp/utaunixmenu.hist","a");	/*Open history file*/
	chmod("/tmp/utaunixmenu.hist",511);

	strcpy(buf1,"User: ");strcat(buf1,getlogin());strcat(buf1,"\n");	/*write data*/
	strcat(buf1,"Terminal: ");strcat(buf1,getenv("TERM"));strcat(buf1,"\n");
	strcat(buf1,"Shell: ");strcat(buf1,getenv("SHELL"));strcat(buf1,"\n");
	strcat(buf1,"Time of usage: ");strcat(buf1,ctime(&begin));
	strcat(buf1,"Commands Used:\n");
	fprintf(myfp,buf1);

/* Initialize Curse Terminal */
	initscr(); 
	cbreak();raw(); noecho();
	nonl(); 
	wb[0]=newwin(17,73,2,2);
	wb[1]=newwin(20,79,0,0);	/*Create new windows*/
	wb[2]=newwin(4,79,20,0); 
	scrollok(wb[1],FALSE);
	scrollok(wb[2],FALSE);
	i=0;
wbtest=wb[0];

	mvwaddstr(wb[1],0,32,"UTA UNIX MENU"); /* header */

	mytotal=listfile(filelist);	/*Reading directory*/
	printdir(wb[1],filelist,myindex,mytotal); /*Print dir*/
	refresh();
	if(checkpass(wb[2],mypasswd)<0)	flag=0;

/********** Main loop - reading command****************/
	while(flag)
	{	
	/* Redraw screen */
		printdir(wb[1],filelist,myindex,mytotal);
		box(wb[1],'|','-');
		mvwaddstr(wb[1],0,32,"UTA UNIX MENU");
		mvwaddstr(wb[2],0,0,mymenu1); /*Print menu*/
		mvwaddstr(wb[2],1,0,mymenu2); 
		mvwaddstr(wb[2],2,0,mymenu3); 
			

		for(i=1;i<70;i++) mvwdelch(wb[2],3,i);
		for(i=1;i<70;i++) mvwdelch(wb[2],3,i);	/*Clear*/
		mvwaddstr(wb[2],3,0,"Enter your selection:"); /*Echo prompt*/

		wrefresh(wb[1]);
		wrefresh(wb[2]);

	/* Read command */
		n=getch();
		for(i=1;i<70;i++) mvwdelch(wb[2],3,i);	/*Clear*/
//fprintf(stderr,"=%d=",n);getch();
		switch(n)	/*Check for command type*/
		{
		  case 47:	/*Search */
			mysearch(wb[0],wb[1],wb[2]);
			break;
		  case 115:	/*Edit Binary*/
		  case 83:

			editbinary(wb[0],wb[2],filelist,mytotal);
			break;
		  case 113:	/*set file password*/
		  case 81:
			printftable(wb[0]);
			setfilepasswd(wb[2]);
			break;
		  case 108:	/*set shell password*/
		  case 76:
			setpasswd(wb[2],mypasswd);
			break;
		  case 103:	/*rm from .fileSystem to Unix*/
		  case 71:
			printftable(wb[0]);
			rmfrom(wb[2],filelist);
			break;
		  case 102:	/*copy from .fileSystem*/
		  case 70:
			printftable(wb[0]);
			cpfrom(wb[2],filelist);
			break;
		  case 98:	/*copy to .fileSystem*/
		  case 66:
			if(fscopy(wb[2],filelist)==-1)
			{	printftable(wb[0]);
				mvwaddstr(wb[2],3,0,"Error copying file! Press any key to continue");
			}
			else
			{	mvwaddstr(wb[2],3,0,"Copying successfully. Press any key to continue");
			}	
			wrefresh(wb[2]);
			printftable(wb[0]);
			getch();
			break;
		  case 106:	/*run from .fileSystem*/
		  case 74:
			printftable(wb[0]);
			runfrom(wb[2]);
			break;
		  case 107:	/*list .fileSystem*/
		  case 75:
			fprintf(myfp,"K \n");
			wclear(wb[2]);wrefresh(wb[2]);
			printftable(wb[0]);
			mvwaddstr(wb[2],3,0,"Press any key to continue");wrefresh(wb[2]);
			getch();
			break;
		  case 120:	/*exit*/
		  case 88 :
			flag=0;
			break;
		  case 99:	/*change dir*/
	 	  case 67:
			switch (changedir(wb[2],filelist,mytotal)) /*call changdir func*/
			{	
				case 0:		/*cd successfully*/
					mytotal=listfile(filelist);
					myindex=0;
					break;
				case -1:	/*cannot cd*/
					mvwaddstr(wb[2],3,0,"Error cannot change directory. Press any key to continue.");
					wrefresh(wb[2]);
					getch();
					
					break;
				case -2:	/*not a dir*/
					mvwaddstr(wb[2],3,0," This is not a directory. Press any key to continue.");
					wrefresh(wb[2]);
					getch();	
					break;
			}

			break;
		  case 101:	/*edit*/
		  case 69:
			if (myedit(wb[2],filelist,mytotal,1)==-1) /*call edit func*/
			{	mvwaddstr(wb[2],3,0,"Cannot edit a directory. Press any key to continue.");
				wrefresh(wb[2]);
				getch();
			}
			wrefresh(wb[1]);wrefresh(wb[2]);
			break;
		  case 118:	/*view*/
		  case 86:
			if (myedit(wb[2],filelist,mytotal,0)==-1) /*call view func*/
			{	mvwaddstr(wb[2],3,0,"Cannot view a directory. Press any key to continue.");
				wrefresh(wb[2]);
				getch();
			}
			wrefresh(wb[1]);wrefresh(wb[2]);
			break;
		  case 114:	/*compile*/
		  case 82 :
			if (mycompile(wb[2],filelist,mytotal)==-1) /*call compile func*/
			{	mvwaddstr(wb[2],3,0,"Cannot compile a directory. Press any key to continue.");
				wrefresh(wb[2]);
				fprintf(myfp,"\n");
				getch();break;
			}
			fprintf(myfp,"\n");
		/* Reread the directory */
			mytotal=listfile(filelist);
			break;

		  case 112:	/*previous*/ 
		  case 80:
		/* Page number - 1 */
			myindex-=1;if(myindex<0) myindex=0;
		/* Reprint filelist */
			printdir(wb[1],filelist,myindex,mytotal);
			fprintf(myfp,"P\n");
			break;

		  case 110:	/*next*/
		  case 78:
		/* Page number + 1 */
			myindex+=1;if(myindex*7+1>mytotal) myindex-=1;
		/* Reprint filelist */
			printdir(wb[1],filelist,myindex,mytotal);
			fprintf(myfp,"N\n");
			break;
		  case 97:	/*create*/
		  case 65:
			if(mycreate(wb[2],filelist)!=-1)	/*call create func*/
			{	mytotal=listfile(filelist);
			}
			fprintf(myfp,"\n");
			break;
		  case 111:	/*copy*/
		  case 79:
			if(mycopy(wb[2],filelist,mytotal)==-1)	/*call copy func*/
			{
			  mvwaddstr(wb[2],3,0,"Error copying file!");
			  wrefresh(wb[2]);
			  getch();
			}
			else
			{	mytotal=listfile(filelist);
			}
			fprintf(myfp,"\n");
			break;
		  case 100:	/*chmod*/
		  case 68:
			if(mychmod(wb[2],filelist,mytotal)==-1)	/*call chmod func*/
			{ mvwaddstr(wb[2],3,0,"Error changing mode!");
			  wrefresh(wb[2]);
			  getch();
			}
			else
			{	mytotal=listfile(filelist);
			}
			fprintf(myfp,"\n");
			break;
		  case 109:	/*move*/
		  case 77:
			if (mymove(wb[2],filelist,mytotal)==0)	/*call move func*/
				mytotal=listfile(filelist);
			fprintf(myfp,"\n");
			break;
		  case 117:	/*run*/
		  case 85:
			myrun(wb[2],filelist,mytotal);		/*call run func*/
			fprintf(myfp,"\n");
			break;
		  case 105:	/*history*/
		  case 73:
			if(nonhist==-1)	/*call printhist func*/
			{	mvwaddstr(wb[2],3,0,"No History yet!");
				wrefresh(wb[2]);getch();
				fprintf(myfp,"I \n");
			}
			else
				printhist(wb[0],wb[2]);	/*call printhist func*/
			break;
		  case 104:	/*help*/
		  case 72:	
			callhelp(wb[2],wb[0]);			/*call help func*/
			break;
		}

	}
	time(&now);		/* check exit time */
	fprintf(myfp,"X\n");
	fprintf(myfp,"Total Time of usage:");
	if(now-begin<60)
	{ sprintf(buf1,"%d seconds\n",(now-begin));
	}
	else
	{ sprintf(buf1,"%d minutes\n",(now-begin)/60);
	}
	fprintf(myfp,buf1);
	fprintf(myfp,"+\n");fclose(myfp);
	echo(); endwin(); exit(0);
}

/*Function 1 - Read directory content */

int listfile(struct mydirent filelist[50])
{ int i=0;DIR *dfd;
	struct dirent *dp;struct stat fp;
	struct tm *mytime;char buf[50];

	dfd=opendir(".");
	sprintf(filelist[i].name,"%s\0","..");	/* ".." */
	i++;
	while((dp=readdir(dfd))!=NULL)
	{

	/* Skip . and .. */
	  if (!(strcmp(dp->d_name,".")==0||strcmp(dp->d_name,"..")==0))
	  {	
	/* Record file properties */
		lstat(dp->d_name,&fp);
		mytime=localtime(&(fp.st_mtime));
		sprintf(buf,"%o",((fp.st_mode)&(0000777)));
		sprintf(filelist[i].name,"%s\0",dp->d_name);
		filelist[i].size=fp.st_size;
		sprintf(buf,"%i",filelist[i].size);
		asctime_r(mytime,filelist[i].date);
		filelist[i].date[19]='\0';
		/*consider file mode*/
		strcpy(filelist[i].perm,"----------");	
		if (S_ISDIR(fp.st_mode))
			filelist[i].perm[0]='d';
		if ((fp.st_mode)&(0000400)) 
			filelist[i].perm[1]='r';
		if ((fp.st_mode)&(0000200)) 
			filelist[i].perm[2]='w';
		if ((fp.st_mode)&(0000100)) 
			filelist[i].perm[3]='x';
		if ((fp.st_mode)&(0000040)) 
			filelist[i].perm[4]='r';
		if ((fp.st_mode)&(0000020)) 
			filelist[i].perm[5]='w';
		if ((fp.st_mode)&(0000010)) 
			filelist[i].perm[6]='x';
		if ((fp.st_mode)&(0000004)) 
			filelist[i].perm[7]='r';
		if ((fp.st_mode)&(0000002)) 
			filelist[i].perm[8]='w';
		if ((fp.st_mode)&(0000001)) 
			filelist[i].perm[9]='x';

	  i+=1;	/* Counting file */
	  }
	}
	return i;
}

/*Function 2 - print directory content */

void printdir(WINDOW *mywb,struct mydirent *filelist, int mypage,int max)
{ int i;char buf[50];

/*display top */
	wclear(mywb);
	getcwd(buf,50);
	mvwaddstr(mywb,2,3,"Current dir:");
	mvwaddstr(mywb,4,3,"Files:");
	mvwaddstr(mywb,2,16,buf);

/*Print current page only*/
	for(i=mypage*7;i<7+mypage*7&&i0)	waddstr(mywb,buf);
		waddstr(mywb,filelist[i].perm);
	}
}

int changedir(WINDOW *mywb,struct mydirent *filelist,int mytotal)
{ char buf[50]; struct stat fp;int i;

	/* which dir to go to */
			mvwaddstr(mywb,3,0,"Goto directory number:");
               		touchwin(mywb); wrefresh(mywb); 
			echo();
			wgetstr(mywb,buf);	/*where to cd to*/
			noecho();
			fprintf(myfp,"C ");
			fprintf(myfp,"%s\n",buf);
			i=atoi(buf);
			if(i<0 || i>=mytotal || strcmp(buf,"")==0)
				return -3;	/*bad input*/ 
			lstat(filelist[i].name,&fp);
			if(S_ISDIR(fp.st_mode)) /*Is it a directory?*/
			{
			    /*check for error*/	
				if(chdir(filelist[i].name)==0)
				{ 
					return 0; /* cd OK! */
				}
				else
				{ 
					return -1; /*cannot cd*/
				}
			}
			else	/*Not a directory*/
			{
				return -2;	
			}
}

int myedit(WINDOW *mywb, struct mydirent *filelist,int mytotal,int c)
{ int i;char pico[]="/usr/local/bin/pico";
  pid_t pid;char buf[50]; struct stat fp;

/* is it a view or edit? */
	if (c)
	{	mvwaddstr(mywb,3,0,"Edit file number:"); /*which file*/
		fprintf(myfp,"E ");
	}
	else
	{	mvwaddstr(mywb,3,0,"View file number:");
		fprintf(myfp,"V ");
	}

	wrefresh(mywb); 
	echo();
	wgetstr(mywb,buf);
	noecho();
	i=atoi(buf);	/* file number */
	fprintf(myfp,buf);fprintf(myfp,"\n");
/* Out of range */
	if(i<0 || i>=mytotal || strcmp(buf,"")==0) 				return -3;
	lstat(filelist[i].name,&fp);
	if(S_ISDIR(fp.st_mode)) /*Check for a dir*/
		return -1;
	
	/*Editing the file*/
	pid=fork();
	if(pid==0) 
	{  if(c)
		execl(pico,"",filelist[i].name,(char *)0);	/*Child process*/
	   else
		execl(pico,"","-v",filelist[i].name,(char *)0);	
	}
	else
	{	wait(NULL);	/*Parent*/
	}
}

int mycompile(WINDOW *mywb,struct mydirent *filelist,int mytotal)
{ char buf1[50],buf[50];struct stat fp;pid_t pid;int i;

/* which file to be compiled? */
	mvwaddstr(mywb,3,0,"Compile file number:"); /*which file*/
	wrefresh(mywb); 
	echo();
	wgetstr(mywb,buf);
	noecho();
	fprintf(myfp,"R ");fprintf(myfp,buf);fprintf(myfp," ");
	i=atoi(buf);	/* file number */
/* Out of range */
	if(i<0 || i>=mytotal || strcmp(buf,"")==0)	return -3;

	lstat(filelist[i].name,&fp);
	if(S_ISDIR(fp.st_mode)) /*Is it a dir?*/
		return -1;
	mvwaddstr(mywb,3,0,"    Additional flag: ");
	echo();
	wgetstr(mywb,buf1);	/* get additional flag */
	noecho();
	fprintf(myfp,buf1);
	wclear(mywb);wrefresh(mywb);
	def_prog_mode(); /* save current tty modes */
	endwin();

	/*system(buf);*/
	pid=fork();
	if(pid==0) 
	{	
		if(strcmp(buf1,"")==0)
/* No additional flag */			execlp("/usr/local/bin/gcc","",filelist[i].name,(char *)0);
		else
/* Additional flag */				execl("/usr/local/bin/gcc","",filelist[i].name,buf1,(char *)0);
	}
	else
	{	wait(NULL);raw();	/*Parent*/
		getch();
	}
}

int mycreate(WINDOW *mywb,struct mydirent *filelist)
{ char buf[50],buf1[50];int i,j;mode_t newmode;
  struct stat fp;

	mvwaddstr(mywb,3,0,"Enter new entry name:"); /*get new name*/
	wrefresh(mywb); 
	echo();
	wgetstr(mywb,buf);
	noecho();
	fprintf(myfp,"A ");fprintf(myfp,buf);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
	/* checking */
	if(stat(buf,&fp)==0)
	{	mvwaddstr(mywb,3,0,"Name already exists!");
		wrefresh(mywb);
		getch();
		return -1;	/* file already exists */
	}
	else
	{	mvwaddstr(mywb,3,0,"Enter new mode:");/*get new mode*/
         	wrefresh(mywb); 
		echo();
		wgetstr(mywb,buf1);
		noecho();
		fprintf(myfp," ");fprintf(myfp,buf1);
		for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
		newmode=0;i=0;
		for(j=strlen(buf1)-1;j>-1;j--)
		{ if(buf1[j]=='x')	i+=1;
		  if(buf1[j]=='w')	i+=2;
		  if(buf1[j]=='r')	i+=4;
		  if(buf1[j]=='o')	{ newmode+=i; i=0; }
		  if(buf1[j]=='g')	{ newmode+=i*8; i=0; }
		  if(buf1[j]=='u')	{ newmode+=i*64; i=0; }
		}
		j++;
		if(buf1[j]=='d')
		{ mkdir(buf,newmode);	/*change mode to user need*/
		  if(newmode==0)	chmod(buf,448);		/*default mode*/
		  else		chmod(buf,newmode);
		}
		else		
		{ fclose(fopen(buf,"w"));
		  if (newmode==0)	chmod(buf,448);
		  else		chmod(buf,newmode);
		}
	}
}
int mycopy(WINDOW *mywb,struct mydirent *filelist,int mytotal)
{ int i;char buf[50],buf1[50];

/*source file*/
	mvwaddstr(mywb,3,0,"Enter source file number or name:"); 
	wrefresh(mywb); 
	echo();
	wgetstr(mywb,buf);
	noecho();
	fprintf(myfp,"O %s ",buf);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/

	i=atoi(buf);
	if(i>0)		/*check if it's a number or a name*/
	{ 	/*given source file number*/
		strcpy(buf,filelist[i].name);
	}
/* out of range */
	if(i<0 || i>=mytotal || strcmp(buf,"")==0)	return -3;

/*destination*/
	mvwaddstr(mywb,3,0,"Enter destination file name:"); 
	echo();
	wgetstr(mywb,buf1);wrefresh(mywb);
	noecho();
	fprintf(myfp,buf1);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/

/* copying */
	if(link(buf,buf1)!=0)
		return -1;	/* error copying file */
	else	
	{
		return 0;
	}
}

int mychmod(WINDOW *mywb,struct mydirent *filelist,int mytotal)
{ char buf[50],buf1[50];int i,j;mode_t newmode;

/*get file name*/
	mvwaddstr(mywb,3,0,"Enter file number or name:"); 
	wrefresh(mywb); 
	echo();
	wgetstr(mywb,buf);
	noecho();
	fprintf(myfp,"D %s ",buf);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
	i=atoi(buf);
	if(i>0)		/*check if it's a number or a name*/
	{ 	/*given source file number*/
 		strcpy(buf,filelist[i].name);
	}
/* out of range */
	if(i<0 || i>mytotal || strcmp(buf,"")==0)	return -3;

/*get new mode*/
	mvwaddstr(mywb,3,0,"Enter new mode:"); 
	wrefresh(mywb); 
	echo();
	wgetstr(mywb,buf1);
	noecho();
	fprintf(myfp,buf1);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
	newmode=0;i=0;
	for(j=strlen(buf1)-1;j>-1;j--)
	{ if(buf1[j]=='x')	i+=1;
	  if(buf1[j]=='w')	i+=2;
	  if(buf1[j]=='r')	i+=4;
	  if(buf1[j]=='o')	{ newmode+=i; i=0; }
	  if(buf1[j]=='g')	{ newmode+=i*8; i=0; }
	  if(buf1[j]=='u')	{ newmode+=i*64; i=0; }
	}
	if (newmode==0)	newmode=448;	/*default mode */
/*changing mode */
	if(chmod(buf,newmode)!=0)
		return -1;
	else		
		return 0;
}

int mymove(WINDOW *mywb,struct mydirent *filelist,int mytotal)
{ char buf[50],buf1[50];int i;

/*source file*/
	mvwaddstr(mywb,3,0,"Enter source file number or name:"); 
	wrefresh(mywb); 
	echo();
	wgetstr(mywb,buf);
	noecho();
	fprintf(myfp,"M %s ",buf);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
	i=atoi(buf);
	if(i>0)		/*check if it's a number or a name*/
	{ 	/*given source file number*/
	    strcpy(buf,filelist[i].name);
	}
/* out of range */
	if(i<0 || i>mytotal || strcmp(buf,"")==0)	return -3;

/*destination*/
	mvwaddstr(mywb,3,0,"Enter destination file name:"); 
	wrefresh(mywb);
	echo();
	wgetstr(mywb,buf1);
	noecho();
	fprintf(myfp,buf1);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
/*Moving*/
	if(link(buf,buf1)!=0)
	{ mvwaddstr(mywb,3,0,"Error moving file!");
	  wrefresh(mywb);
	  getch();
	}
	else
	{ if(unlink(buf)!=0)	/*cannot delete old file */
	  { mvwaddstr(mywb,3,0,"Error moving file!");
	    wrefresh(mywb);
	    unlink(buf1);	/*remove new file*/
	    getch();
	  }
	  else
	  { 
	    return 0;
	  }
	}
}

int myrun(WINDOW *mywb, struct mydirent *filelist,int mytotal)
{ char buf[50],buf1[50]; int i;pid_t pid;

/*Get program file*/
	mvwaddstr(mywb,3,0,"Enter program file name or number:"); 
	wrefresh(mywb); 
	echo();
	wgetstr(mywb,buf);
	noecho();
	fprintf(myfp,"U %s ",buf);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/

	i=atoi(buf);	/*file number*/
	if(i>0)		/*check if it's a number or a name*/	
	{ 	/*given source file number*/
	    strcpy(buf,filelist[i].name);
	}
/* out of range */
	if(i<0 || i>mytotal || strcmp(buf,"")==0)	return -3;

/*Get argument*/
	mvwaddstr(mywb,3,0,"Additional argument:");
	echo();
	wgetstr(mywb,buf1);
	noecho();
	fprintf(myfp,buf1);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
/*running*/
	pid=fork();
	if(pid==0)
	{ 
	  execl(buf,"",buf1,(char *)0);	/*Child process*/
	  strcpy(buf1,"Error,cannot run ");
	  strcat(buf1,buf);strcat(buf1,"!\0");
	  mvwaddstr(mywb,3,0,buf1);
	  wrefresh(mywb); 
	  exit(0);
	}
	else
	{ wait(NULL);			/*Parent*/
	  mvwaddstr(mywb,3,0,"Press any key to continue");
	  wrefresh(mywb);
	  raw();
	  getch();
	}
}


int readhist(void)
{ FILE *fp;int i,start=1;char newline[50];

	for(i=0;i<10;i++)	strcpy(histlist[i],"\0");	
	fp=fopen("/tmp/utaunixmenu.hist","r");
	if(fp==(FILE *)0)
		return -1;
	i=0;
	while (fgets(newline,50,fp)!=NULL)
	{ if (strcmp(newline,"+\n")==0)
	  {	i+=1;start=1;
		if (i==10)	i=0;
	  }
	  else
	  {	if(start)
		{	strcpy(histlist[i],newline);
			start=0;}
		else
		{	strcat(histlist[i],newline);
		}
	  }
	}
	max=i;
	fclose(fp);
}

int printhist(WINDOW *wb0,WINDOW *wb2)
{ int i=max-1,flag=1,n;

	fprintf(myfp,"I \n");
	if(i==10)	i=0;if (i<0) i=10;
	while(strcmp(histlist[i],"")==0)	/*find starting point*/
	{	i++;
		if (i==10)	i=0;
		if(i==max)	return -1;

	
	}
	do
	{
		wclear(wb0);
		mvwaddstr(wb0,0,0,histlist[i]);
		touchwin(wb0);
		wrefresh(wb0);
		wclear(wb2);
		mvwaddstr(wb2,0,0,"P previous, N next, Q quit");
		wrefresh(wb2);
		n=getch();
		switch(n)
		{
		  case 110:	/*next*/
		  case 78: 
			do
			{ i+=1; if(i==10) i=0;
			}while(strcmp(histlist[i],"")==0);
			break;
		  case 112:	/*previous*/
		  case 80:
			do
			{i-=1; if(i<0) i=9;
			}while(strcmp(histlist[i],"")==0);
			break;
		  case 113:	/*quit*/
		  case 81:
			flag=0;
			break;
		}
	}while(flag);

}
int callhelp(WINDOW *wb2,WINDOW *wb0)
{  int n;
        mvwaddstr(wb2,3,0,"Which command?:");wrefresh(wb2);
        n=getch();	/*read input*/
	fprintf(myfp,"H %c\n",n);
        wclear(wb0);
        switch(n)
        { 
	  case 115:
	  case 83:
                mvwaddstr(wb0,0,0,"EditBinary:");
                mvwaddstr(wb0,2,0,"Use this command to edit a binary file.");
                mvwaddstr(wb0,4,0,"subcommand:");
                mvwaddstr(wb0,6,0,"	w  ");
                mvwaddstr(wb0,7,0,"	Edit this byte with a new value.");
                mvwaddstr(wb0,9,0,"	y");
                mvwaddstr(wb0,10,0,"	Goto previous block.");
                mvwaddstr(wb0,12,0,"	z");
                mvwaddstr(wb0,13,0,"	Goto next block.");
                mvwaddstr(wb0,15,0,"	t");
                mvwaddstr(wb0,16,0,"	Toggle the display between ASCII and Hex.");

		break;
	  case 47:
                mvwaddstr(wb0,0,0,"Search:");
                mvwaddstr(wb0,2,0,"Use this command to search for a file, a directory or a word.");
		mvwaddstr(wb0,4,0,"Criteria:");
		mvwaddstr(wb0,6,0,"	d dir1\n search for a directory named dir1");	
		mvwaddstr(wb0,9,0,"	f file1\n search for a file named file1");	
		mvwaddstr(wb0,12,0,"	word1\n search for files which contain word1 ");
		break;
	  case 113:
	  case 81:
                mvwaddstr(wb0,0,0,"setfilePass:");
                mvwaddstr(wb0,2,0,"Use this command to set or change password for a file in .fileSystem.");
                break;
	  case 108:
	  case 76:
                mvwaddstr(wb0,0,0,"setPass:");
                mvwaddstr(wb0,2,0,"Use this command to change the password for the shell.");
                break;
		 
	  case 103:
          case 71:
                mvwaddstr(wb0,0,0,"rmFrom:");
                mvwaddstr(wb0,2,0,"Use this command to remove a file from .fileSystem to Unix.");
                break;
	  case 102:
          case 70:
                mvwaddstr(wb0,0,0,"cpFrom:");
                mvwaddstr(wb0,2,0,"Use this command to copy a file from .fileSystem to Unix.");
                break;
	  case 98:
          case 66:
                mvwaddstr(wb0,0,0,"cpTo:");
                mvwaddstr(wb0,2,0,"Use this command to copy a file from Unix to .fileSystem.");
                break;
	  case 106:
          case 74:
                mvwaddstr(wb0,0,0,"runFrom:");
                mvwaddstr(wb0,2,0,"Use this command to run a program in .fileSystem.");
                break;
	  case 107:
          case 75:
                mvwaddstr(wb0,0,0,"dirFrom:");
                mvwaddstr(wb0,2,0,"Use this command to list the contents of .fileSystem.");
                break;
	
	  case 120:
          case 88:
                mvwaddstr(wb0,0,0,"Exit:");
                mvwaddstr(wb0,2,0,"Use this command to exit the program.");
                break;
          case 99:
          case 67:
                mvwaddstr(wb0,0,0,"Change Dir:");
                mvwaddstr(wb0,2,0,"Use this command to change current directory.");
		mvwaddstr(wb0,4,0,"Please follow instruction on the prompt.");
		break;
          case 101:
          case 69:
                mvwaddstr(wb0,0,0,"Edit:");
                mvwaddstr(wb0,2,0,"Use this command to edit a file.");
		mvwaddstr(wb0,4,0,"Please follow instruction on the prompt.");
		break;

          case 118:
          case 86:
                mvwaddstr(wb0,0,0,"View:");
                mvwaddstr(wb0,2,0,"Use this command to view a file.");
		mvwaddstr(wb0,4,0,"Please follow instruction on the prompt.");
		break;
          case 114:
          case 82:
                mvwaddstr(wb0,0,0,"Compile:");
                mvwaddstr(wb0,2,0,"Use this command to compile a file.");
		mvwaddstr(wb0,4,0,"Please follow instruction on the prompt.");
		break;
          case 112:
          case 80:
                mvwaddstr(wb0,0,0,"Previous:");
                mvwaddstr(wb0,2,0,"Use this command to view previous part of current directory.");
		break;
          case 110:
          case 78:
                mvwaddstr(wb0,0,0,"Next:");
                mvwaddstr(wb0,2,0,"Use this command to view next part of current directory.");
		break;
          case 97:
          case 65:
                mvwaddstr(wb0,0,0,"Create:");
                mvwaddstr(wb0,2,0,"Use this command to create a file or a directory.");
		mvwaddstr(wb0,4,0,"Please follow instruction on the prompt.");
		mvwaddstr(wb0,6,0,"File mode: urwxgrwxorwx");
		mvwaddstr(wb0,8,0,"Directory mode: durwxgrwxorwx");
		mvwaddstr(wb0,10,0,"To create a directory, indicates directory mode.");
		break;

          case 111:
          case 79:
                mvwaddstr(wb0,0,0,"Copy:");
                mvwaddstr(wb0,2,0,"Use this command to copy a file.");
		mvwaddstr(wb0,4,0,"Please follow instruction on the prompt.");
		break;
          case 100:
          case 68:
                mvwaddstr(wb0,0,0,"Chmod:");
                mvwaddstr(wb0,2,0,"Use this command to change file or directory mode.");
		mvwaddstr(wb0,4,0,"Please follow instruction on the prompt.");
		break;
          case 109:
          case 77:
                mvwaddstr(wb0,0,0,"Move:");
                mvwaddstr(wb0,2,0,"Use this command to move a file.");
		mvwaddstr(wb0,4,0,"Please follow instruction on the prompt.");
		break;
          case 117:
          case 85:
                mvwaddstr(wb0,0,0,"Run:");
                mvwaddstr(wb0,2,0,"Use this command to run a file.");
		mvwaddstr(wb0,4,0,"Please follow instruction on the prompt.");
		break;
          case 105:
          case 73:
                mvwaddstr(wb0,0,0,"History:");
                mvwaddstr(wb0,2,0,"Use this command to show history of previous sessions.");
		mvwaddstr(wb0,4,0,"Please follow instruction on the prompt.");
		break;
	  case 104:
	  case 72:
		mvwaddstr(wb0,0,0,"Help:");
		mvwaddstr(wb0,2,0,"Use this command to display help.");
		break;
	  default:
		mvwaddstr(wb0,0,0,"Don't know this command.");
		break;
        }
	touchwin(wb0);wrefresh(wb0);
	mvwaddstr(wb2,3,0,"Press any key to continue.");wrefresh(wb2);
	getch();
}

int checkfile(void)
{
  int i,fd,j;struct stat fp;char *a="@";	
	if (stat(".fileSystem",&fp)<0)	/*check if .fileSystem exist*/
	{	fd=creat(".fileSystem",0666);	/*create new one*/
		for(i=0;i<1600;i++)
		{	for(j=0;j<256;j++)
				write(fd,a,1);
		}

		sprintf(a,"-1\n");
		for(i=0;i<1600;i++)
			write(fd,a,3);
		write(fd,"0 ;=?AC\n",8);
		close(fd);
		fd=open(".fileSystem",O_RDWR);
	}
	else	
	{	fd=open(".fileSystem",O_RDWR);	/*read existing one*/
	}
	return fd;
}
int rdln(char *buf1)
{ char *t="0",buf[128]=" ";

	if(read(myfd,t,1)<0)
		return -1;
	while(*t!='\n')
	{	strcat(buf,t);
		read(myfd,t,1);
	}
	sprintf(buf1,"%s",buf);
	return 0;
}
void readftable(void)
{
  int i,count;	
  char name[40],sptr[5],s[8],os[8],m[8],t[10],ot[10],p[20],buf[256];

	lseek(myfd,409600,SEEK_SET);	/*goto dir content*/
	for(i=0;i<1600;i++)
	{
		rdln(buf);		/*reading dir contents*/
		fptr[i]=atoi(buf);
	}
	rdln(buf);sscanf(buf,"%s %s",s,mypasswd);
	i=0;count=atoi(s);
	fcount=count;	
	while(count>0)			/*storing in memory*/
	{
		rdln(buf);strcpy(p,"");
		sscanf(buf,"%s %s %s %s %s %s %s %s",name,sptr,s,os,m,t,ot,p);
		strcpy(ftable[i].name,name);
		ftable[i].ptr=atoi(sptr);
		ftable[i].size=atol(s);
		ftable[i].origsize=atol(os);
		ftable[i].mode=(mode_t)atol(m);
		ftable[i].time=(time_t)atol(t);
		ftable[i].origtime=(time_t)atol(ot);
		strcpy(ftable[i].passwd,p);
		count-=1;i+=1;
	}
}
int countblock(void)
{
  int i,count=0;char buf1[256];

	for (i=0;i<1600;i++)
	{	if(fptr[i]<0)	count++;	/*counting available blocks*/
	}
	return count;
}

void printftable(WINDOW *wb0)
{
  int i=0;char buf[40];
	wclear(wb0);touchwin(wb0);wrefresh(wb0);
	sprintf(buf,".fileSystem : Total %d files",fcount);
	mvwaddstr(wb0,0,0,buf);
	while(i0)		/*check if it's a number or a name*/
	{ 	/*given source file number*/
		strcpy(buf,filelist[i].name);
	}
	while(count>=0)	/*looking for existing file in .fileSystem*/
	{ if(strcmp(ftable[count].name,buf)==0)	break;
	  count--;
	}

	/*Check for 1)cannot open 2)directory 3) existed in .fileSystem*/
	if(lstat(buf,&fp)<0||S_ISDIR(fp.st_mode)||count>=0	)
		return -1;
	else
	{
		f1=fopen(buf,"r");
		f2=fopen("dmctest","w");
		comp(f1,f2);			/*compress before copying*/
		fclose(f1);fclose(f2);
		lstat("dmctest",&ffp);
		i=countblock();
		if(ffp.st_size>i*256)
		{
			unlink("dmctest");	/*not enough space*/
			return -1;
		}
		size=(ffp.st_size+255)/256;
		i=0;
		while(fptr[i]>=0)
			i++;
		strcpy(ftable[fcount].name,buf);	/*copy information*/
		ftable[fcount].size=ffp.st_size;
		ftable[fcount].origsize=fp.st_size;
		ftable[fcount].mode=fp.st_mode;
		ftable[fcount].time=ffp.st_mtime;
		ftable[fcount].origtime=fp.st_mtime;
		ftable[fcount].ptr=i;	/*firstpage*/
		size-=1;
		while(size>0)				/*locate blocks to be used*/
		{	j=i+1;
			while(fptr[j]>0) j++;
			fptr[i]=j;
			size--;i=j;
		}
		fptr[i]=2000;
		fdd=open("dmctest",O_RDONLY);
		if(fdd<0)	
		{	unlink("dmctest");	return -1; }
		i=ftable[fcount].ptr;
		while (i<1600)			/*copying data */
		{
			read(fdd,buf,256);
			lseek(myfd,i*256,SEEK_SET);
			write(myfd,buf,256);
			i=fptr[i];
		}
		close(fdd);
		unlink("dmctest");
		fcount+=1;
		updatetable();
		
	}
}
void updatetable(void)
{ int i;char buf[256];

	lseek(myfd,409600,SEEK_SET);	/*goto dir content*/
	for (i=0;i<1600;i++)
	{	sprintf(buf,"%d\n",fptr[i]);
		write(myfd,buf,strlen(buf));	/*writing dir content*/
	}
	sprintf(buf,"%d %s\n",fcount,mypasswd);
	write(myfd,buf,strlen(buf));
	for(i=0;i<32;i++)
	{  if(ftable[i].ptr>=0)
	   {	
		sprintf(buf,"%s %d %d %d %d %d %d %s\n",ftable[i].name,ftable[i].ptr,ftable[i].size,ftable[i].origsize,ftable[i].mode,ftable[i].time,ftable[i].origtime,ftable[i].passwd);
		write(myfd,buf,strlen(buf));
	   }
	}
}
int cpfrom(WINDOW *mywb,struct mydirent *filelist)
{ int i,count,sptr=-1,fdd;long size;char buf[256],pas[20];FILE *f1,*f2;

/*source file*/
	mvwaddstr(mywb,3,0,"Enter source file name:"); 
	wrefresh(mywb); 
	echo();
	wgetstr(mywb,buf);
	noecho();
	fprintf(myfp,"F %s\n",buf);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
	count=fcount-1;
	while(count>=0)	/*looking for existing file in .fileSystem*/
	{	if(strcmp(ftable[count].name,buf)==0) 
		{	sptr=ftable[count].ptr;
			size=ftable[count].size;
			strcpy(pas,ftable[count].passwd);
			break;
		}
		count--;
	}
	if(sptr<0||count<0)
	{	mvwaddstr(mywb,3,0,"Unable to find the file; press any key to continue.");
		wrefresh(mywb);getch();
		return -1;
	}
	else
	{	if(strlen(pas)>0)	/*Check password*/
			if (checkpass(mywb,pas)<0)
				return -1;
		unlink("ftmp");
		fdd=creat("ftmp",0666);
		while(sptr<1600)
		{	if(fptr[sptr]<1600)
				i=256;
			else
				i=(int) size%256;
			if(i==0)	i=256;
			lseek(myfd,sptr*256,SEEK_SET);
			read(myfd,buf,i); 
			write(fdd,buf,i);
			sptr=fptr[sptr];
		}
		close(fdd);
		f1=fopen("ftmp","r");
		unlink(ftable[count].name);
		f2=fopen(ftable[count].name,"w");
		exp(f1,f2);
		unlink("ftmp");
		chmod(ftable[count].name,ftable[count].mode);
		mvwaddstr(mywb,3,0,"Copy successfully. Press any key to continue");
		wrefresh(mywb);
		getch();
		return 0;
	}
}
int rmfrom(WINDOW *mywb,struct mydirent *filelist)
{ int i,count,sptr=-1,fdd;long size;char buf[256];
  FILE *f1,*f2;char pas[20];
/*source file*/
	mvwaddstr(mywb,3,0,"Enter source file name:"); 
	wrefresh(mywb); 
	echo();
	wgetstr(mywb,buf);
	noecho();
	fprintf(myfp,"G %s\n",buf);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	
	count=fcount-1;
	while(count>=0)
	{	/*looking for existing file in .fileSystem*/
		if(strcmp(ftable[count].name,buf)==0) 
		{	sptr=ftable[count].ptr;
			size=ftable[count].size;
			strcpy(pas,ftable[count].passwd);
			break;
		}
		count--;
	}
	if(sptr<0)
	{	mvwaddstr(mywb,3,0,"Unable to find the file; press any key to continue.");
		wrefresh(mywb);getch();
		return -1;
	}
	else
	{	if(strlen(pas)>0)	/*Check password*/
			if (checkpass(mywb,pas)<0)
				return -1;
		ftable[count].ptr=-1;
		unlink("ftmp");
		fdd=creat("ftmp",0666);
		while(sptr<1600)	/*writing data to temp file*/
		{	if(fptr[sptr]<1600)
				i=256;
			else
			{	i=(int) size%256;
				if(i==0)	i=256;
			}
			lseek(myfd,sptr*256,SEEK_SET);
			read(myfd,buf,i); 
			write(fdd,buf,i);
			i=sptr;
			sptr=fptr[sptr];
			fptr[i]=-1;
		}
		close(fdd);
		unlink(ftable[count].name);
		f1=fopen("ftmp","r");
		f2=fopen(ftable[count].name,"w");
		exp(f1,f2);		/*decompress tempfile */
		fclose(f1);fclose(f2);
		fcount-=1;
		chmod(ftable[count].name,ftable[count].mode);
		mvwaddstr(mywb,3,0,"Remove successfully. Press any key to continue");
		wrefresh(mywb);
		unlink("ftmp");
		updatetable();		/*update dir table*/
		readftable();
	}	
}
/*Dynamic markov*/

float predict();	
int pinit();
int pupdate();

int memsize = 0x1000000;
typedef struct nnn {
           float count[2];
           struct nnn    *next[2];
} node;

static int threshold = 2, bigthresh = 2; 

static node *p, *new, nodes[256][256];

static node *nodebuf;
static node *nodemaxp;
static node *nodesptr;

#include 

void comp(FILE *fd1,FILE *fd2){
   int max = 0x1000000,
       min = 0,
       mid,
       c,i,
       inbytes = 0, 
       outbytes =3,
       pout = 3,
       bit;
   
   pinit(memsize);		/*allocate main table*/
   while((c=getc(fd1))!=EOF)
   {
      for (i=0;i<8;i++){
         bit = (c << i) & 0x80;
         mid = min + (max-min-1) * predict();	/*estimate data*/
         pupdate(bit != 0);	/*update data table*/
         if (mid == min) mid++;
         if (mid == (max-1)) mid--;
   
         if (bit) { 
            min = mid;		/*change range*/
         } else {
            max = mid;
         }
         while ((max-min) < 256) {	/*adjust range*/
            if(bit)max--;
            putc(min >> 16,fd2);
            outbytes++;
            min = (min << 8) & 0xffff00;
            max = ((max << 8) & 0xffff00 ) ;
            if (min >= max) max = 0x1000000;
         }
      }
      if(!(++inbytes & 0xff)){
         if (outbytes - pout > 256) { /* compression failing */
            pflush();		/*clear main table*/
         }
         pout = outbytes;
      }
   }
   min = max-1;			/*end point*/
   putc(min>>16,fd2);
   putc((min>>8) & 0xff,fd2);
   putc(min & 0x00ff,fd2);
fclose(fd1);fclose(fd2);free(nodebuf);
}


void exp(FILE *fd1,FILE *fd2){
   int max = 0x1000000,
       min = 0,
       mid,
       val,
       i,
       inbytes=3,
       pin=3,
       outbytes=0,
       bit,
       c;
   
   pinit(memsize);		/*allocate maintable*/
   
   val = getc(fd1)<<16;		/*starting point*/
   val += getc(fd1)<<8;
   val += getc(fd1);
   while(1) {
      c = 0;
      if (val == (max-1))  {	/*found end point*/
	 break;
      }
      for (i=0;i<8;i++){
         mid = min + (max-min-1)*predict();	/*estimate real data*/
         if (mid == min) mid++;
         if (mid == (max-1)) mid--;
         if (val >= mid) {
            bit = 1;
            min = mid;
         } else {
            bit = 0;
            max = mid;
         }
         pupdate(bit != 0);	/*update data table*/
         c = c + c + bit;
         while ((max-min) < 256) {	/*adjust range*/
            if(bit)max--;
            inbytes++;
            val = (val << 8) & 0xffff00 | (getc(fd1)& 0xff);
            min = (min << 8) & 0xffff00;
            max = ((max << 8) & 0xffff00 ) ;
            if (min >= max) max = 0x1000000;
         }
      }
      putc(c,fd2);	/*writing output*/
      if(!(++outbytes & 0xff)){
         if (inbytes - pin > 256) { /* compression was failing */
            pflush();
         }
         pin = inbytes;
      }
   }
   fclose(fd1);fclose(fd2);free(nodebuf);
}


int pinit(memsize)
   int memsize;
{
   nodebuf = (node *) malloc (memsize);
   if (nodebuf == (node *) NULL) {
      fprintf(stderr,"not enough memory!; try again later\n");
      exit(1);
   }
   nodemaxp = nodebuf + (memsize/sizeof(node)) - 20;
   pflush();
}

int pflush(){
   int i,j;
   for (j=0;j<256;j++){
      for (i=0;i<127;i++) {
         nodes[j][i].count[0] = 0.2;
         nodes[j][i].count[1] = 0.2;
         nodes[j][i].next[0] = &nodes[j][2*i + 1];
         nodes[j][i].next[1] = &nodes[j][2*i + 2];
      }
      for (i=127;i<255;i++) {
         nodes[j][i].count[0] = 0.2;
         nodes[j][i].count[1] = 0.2;
         nodes[j][i].next[0] = &nodes[i+1][0];
         nodes[j][i].next[1] = &nodes[i-127][0];
      }
   }
   nodesptr = nodebuf;
   preset();
}

preset(){
   p = &nodes[0][0];
}

float predict(){
   return   p->count[0] / (p->count[0] + p->count[1]);
}

pupdate(b)
   int b;
{
   float r;
   if (p->count[b] >= threshold &&
      p->next[b]->count[0]+p->next[b]->count[1]
       >= bigthresh + p->count[b]){
      new = nodesptr++;
      p->next[b]->count[0] -= new->count[0] =
         p->next[b]->count[0] * 
         (r = p->count[b]/(p->next[b]->count[1]+p->next[b]->count[0]));
     p->next[b]->count[1] -= new->count[1] =
         p->next[b]->count[1] * r;
      new->next[0] = p->next[b]->next[0];
      new->next[1] = p->next[b]->next[1];
      p->next[b] = new;
   }
   p->count[b]++;
   p = p->next[b];
   if (nodesptr > nodemaxp){
      fprintf(stderr,"flushing ...\n");
      pflush();
   }
}

void encrypt(char *message)
{ int c,i,a=10;
	for(i=0;i20) a=10;
		message[i]=c;
	}
	message[i]='\0';

}
void decrypt(char *message)
{ int c,i,a=10;
	for(i=0;i20) a=10;
		message[i]=c;
	}
	message[i]='\0';
}

int runfrom(WINDOW *mywb)
{ int i,count,sptr=-1,fdd;long size;char buf[256];FILE *f1,*f2;
  pid_t pid;char pas[20];
/*source file*/
        mvwaddstr(mywb,3,0,"Enter source file name:");
        wrefresh(mywb);
        echo();
        wgetstr(mywb,buf);
        noecho();
        fprintf(myfp,"J %s\n",buf);
        for(i=1;i<50;i++) mvwdelch(mywb,3,i);   /*Clear*/
        count=fcount-1;
        while(count>=0)		/*looking for existing file in .fileSystem*/
        {       if(strcmp(ftable[count].name,buf)==0)
                {       sptr=ftable[count].ptr;
                        size=ftable[count].size;
			strcpy(pas,ftable[count].passwd);
                        break;
                }
                count--;
        }
        if(sptr<0||count<0)
	{	mvwaddstr(mywb,3,0,"Unable to find the file; press any key to continue.");
		wrefresh(mywb);getch();
		return -1;
	}
        else
	{	if(strlen(pas)>0)		/*Check password*/
			if (checkpass(mywb,pas)<0)
				return -1;
                unlink("ftmp");
                fdd=creat("ftmp",0666);
                while(sptr<1600)		/*writing data to temp file*/
                {       if(fptr[sptr]<1600)
                                i=256;
                        else
                                i=(int) size%256;
                        if(i==0)        i=256;
                        lseek(myfd,sptr*256,SEEK_SET);
                        read(myfd,buf,i);
                        write(fdd,buf,i);
                        sptr=fptr[sptr];
                }
                close(fdd);
		unlink("run.tmp");
                f1=fopen("ftmp","r");
                f2=fopen("run.tmp","w");
                exp(f1,f2);
		chmod("run.tmp",448);
	def_prog_mode(); /* save current tty modes */
	endwin();
		pid=fork();
		if(pid==0)
        	{ 
                   execl("run.tmp",ftable[count].name,(char *)0);      /*Child process*/
        	}
        	else
        	{       wait(NULL);     /*Parent*/
			raw();noecho();
			unlink("run.tmp");
			unlink("ftmp");
			getch();
        	}
	}
}
int checkpass(WINDOW *mywb,char *testpass)
{ char readpass[20];int i;
	mvwaddstr(mywb,3,0,"Enter password:");
	wgetstr(mywb,readpass);
	encrypt(readpass);
	if(strcmp(readpass,testpass)==0)
	{	return 0;
	}
	else
	{	mvwaddstr(mywb,3,0,"Sorry, wrong passwd; press any key to continue.");
		wrefresh(mywb);getch();
		for(i=0;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
		wrefresh(mywb);
		return -1;
	}
}
int setpasswd(WINDOW *mywb,char* pass)
{ char newpass[20],buf[256],newpass1[20];
  int i;
	
	fprintf(myfp,"L \n");
	mvwaddstr(mywb,3,0,"Enter new password:");
	wgetstr(mywb,newpass);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
	mvwaddstr(mywb,3,0,"Verify new password:");
	wgetstr(mywb,newpass1);
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
	if(strcmp(newpass,newpass1)==0)
	{
		encrypt(newpass);
		strcpy(mypasswd,newpass);
		updatetable();
	}
	else
	{	mvwaddstr(mywb,3,0,"Sorry, password unmatch. Press any key.");
		wrefresh(mywb);
		getch();
		for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
	}
}
int setfilepasswd(WINDOW *mywb)
{ char newpass[20],buf[256],newpass1[20],filename[20],oldpass[20];
  int count,i;
	
	fprintf(myfp,"Q \n");
	mvwaddstr(mywb,3,0,"Enter file name:");wrefresh(mywb);
	echo();
	wgetstr(mywb,filename);
	noecho();
	for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
        count=fcount-1;
        while(count>=0)		/*looking for existing file in .fileSystem*/
        {       if(strcmp(ftable[count].name,filename)==0)
		{
                        break;
                }
                count--;
        }
        if(count<0)
	{	mvwaddstr(mywb,3,0,"Unable to find the file; press any key to continue.");
		wrefresh(mywb);getch();
		return -1;
	}
        else
        {
		if(strlen(ftable[count].passwd)>0)
		{ mvwaddstr(mywb,3,0,"Enter old password:");
		  wgetstr(mywb,oldpass);
		  for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
		  encrypt(oldpass);
		  if(strcmp(oldpass,ftable[count].passwd)!=0)
		  {	mvwaddstr(mywb,3,0,"Sorry, password unmatch. Press any key.");
			wrefresh(mywb);
			getch();
			for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
			return -1;
		  }
		}
		mvwaddstr(mywb,3,0,"Enter new password:");
		wgetstr(mywb,newpass);
		for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
		mvwaddstr(mywb,3,0,"Verify new password:");
		wgetstr(mywb,newpass1);
		for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
		if(strcmp(newpass,newpass1)==0)
		{
			encrypt(newpass);
			if(strcmp(newpass1,"\n")==0) strcpy(newpass,"");
			strcpy(ftable[count].passwd,newpass);
			updatetable();
		}
		else
		{	mvwaddstr(mywb,3,0,"Sorry, password unmatch. Press any key.");
			wrefresh(mywb);
			getch();
			for(i=1;i<50;i++) mvwdelch(mywb,3,i);	/*Clear*/
		}
	}
}
void mysearch(WINDOW *mywb0, WINDOW *mywb1, WINDOW *mywb2)
{ char current[50],buf1[512]="",buf2[50],c1[20]="",c2[20]="",slist[512]="";
  char tmp[512],result[20][25],counttmp[10];
  int i=0,j=0,k=0,count[20];

//	getcwd(current,50);
	fprintf(myfp,"/ ");
	wclear(mywb2);
	wrefresh(mywb2);

//	Asking for search criterias

	mvwaddstr(mywb2,3,0,"Enter search criteria:");
	echo();
	wgetstr(mywb2,buf2);
	noecho();
	fprintf(myfp,buf2);fprintf(myfp,"\n");
	sscanf(buf2,"%s %s",c1,c2);

//	Doing search

	if(strlen(c1)+strlen(c2)>0)
		subsearch(c1,c2,slist,"");
	wclear(mywb0);
	while(j0)
	{ 	if(strcmp(c1,"d")==0)	
			selectdir(mywb2,result,i);
		else
		{	
			if(strcmp(c1,"f")==0||strlen(c2)==0)	
				selectfile(mywb0,mywb1,mywb2,result,i);
		}
	}
	else	/*(i==0)*/
	{	for(i=1;i<70;i++) mvwdelch(mywb2,3,i);	/*Clear*/
		mvwaddstr(mywb2,3,0,"Press any key to continue.");
		wrefresh(mywb2);
		getch();
	}

}
void subsearch(char *c1, char *c2, char *slist,char *subname)
{ struct mydirent tmplist[50];int maxfile,i;char buf1[50]="",testchar;
  int n;char tmpchar[10];

	if(strcmp(c1,"d")==0)	testchar='d';	/* looking for dir */
	if(strcmp(c1,"f")==0)	testchar='-';	/* looking for file */
	maxfile=listfile(tmplist);	/* count file */
	for(i=1;i0)
		{ if(strlen(subname)>0)
		  {	strcat(slist,subname);
			strcat(slist,"/");
		  }
		  strcat(slist,tmplist[i].name);
		  strcat(slist," ");
		  sprintf(tmpchar,"%d",n);
		  strcat(slist,tmpchar);
		  strcat(slist,"\n");
		}
	   }
	   else			/* search for dir or file */
	   {
		if(strcmp(tmplist[i].name,c2)==0&&tmplist[i].perm[0]==testchar)
		{ if(strlen(subname)>0)
		  { 	strcat(slist,subname);
			strcat(slist,"/");
		  }
		  strcat(slist,c2);
	  	  strcat(slist,"\n");
		}
	   }
	   if(tmplist[i].perm[0]=='d')	/* a dir found, going in */
	   {
		if(strlen(subname)>0)
		{	strcat(buf1,subname);
			strcat(buf1,"/");
		}
		strcat(buf1,tmplist[i].name);
		chdir(tmplist[i].name);
		subsearch(c1,c2,slist,buf1);
		chdir("..");
		strcpy(buf1,"");
	   }
	}
}
		
void display(WINDOW *mywb0,char result[20][25],int count[20],int max)
{ int i=0;char buf1[50];

/* display search result */

	while(i0&&i<=max)
		{	v=0;
			chdir(result[i-1]);	/* change to that dir */
		}
		if(strcmp(buf1,"q")==0)	
			v=0;
		for(i=1;i<70;i++) mvwdelch(mywb2,3,i);	/*Clear*/
	}
	
}
void selectfile(WINDOW *mywb0,WINDOW *mywb1,WINDOW *mywb2,char result[20][25],int max)
{ char buf1[3];int i,v=1,n,w=1;
  char pico[]="/usr/local/bin/pico";
  pid_t pid;

	while(v)
	{	
		wclear(mywb2);
		mvwaddstr(mywb2,1,0,"V) View E) Edit Q) Quit");
		wrefresh(mywb2);
		n=getch();	/* get user command */
		switch(n)
		{
		 case 118:     /*view*/
                 case 86:
			mvwaddstr(mywb2,3,0,"Enter file number:");
			wrefresh(mywb2);
			echo();
			wgetstr(mywb2,buf1);
			noecho();
			for(i=1;i<70;i++) mvwdelch(mywb2,3,i);/*Clear*/
			i=atoi(buf1);
			if(i>0&&i<=max)
			{
        		  pid=fork();
        		  if(pid==0)
        		  {  
                	    execl(pico,"","-v",result[i-1],(char *)0);
        		  }
        		  else
        		  {       wait(NULL);     /*Parent*/
        		  }	
			}
	 		break;
		 case 101:     /*edit*/
                 case 69:
			mvwaddstr(mywb2,3,0,"Enter file number:");
			wrefresh(mywb2);
			echo();
			wgetstr(mywb2,buf1);
			noecho();
			for(i=1;i<70;i++) mvwdelch(mywb2,3,i);/*Clear*/
			i=atoi(buf1);
			if(i>0&&i<=max)
			{
        		  pid=fork();
        		  if(pid==0)
        		  {  
                	    execlp(pico,"",result[i-1],(char *)0);
        		  }
        		  else
        		  {       wait(NULL);     /*Parent*/
        		  }	
			}
	 		break;
		  case 113:	/*quit*/
		  case 81:
			v=0;
			break;
		}
	redrawwin(mywb1);
	touchwin(mywb0);
	wrefresh(mywb1);
	wrefresh(mywb0);
	}
}

int strsearch(char *filename,char *substr)
{ struct stat fp;int block=0,lastchunk,count=0,fdtmp;
  char input[512],*buf;
  int sublength;

/* open file */	
	lstat(filename,&fp);
	fdtmp=open(filename,O_RDONLY);
	if(!S_ISDIR(fp.st_mode)&&fdtmp>0)
	{	lastchunk=fp.st_size;	
		sublength=strlen(substr);
		while(lastchunk>=512)
		{	lseek(fdtmp,block*(512-sublength+1),SEEK_SET);
			read(fdtmp,input,512);	/* reading one block */
			buf=(char *)strstr(input,substr);
			while(buf!=NULL)
			{ count++;
			  strcpy(input,buf+1);
			  buf=(char *)strstr(input,substr);
			}
			lastchunk-=512-sublength+1;
			block+=1;
		}
		/*don't forget last block*/
		if(lastchunk>0)
		{	lseek(fdtmp,block*(512-sublength+1),SEEK_SET);
			read(fdtmp,input,lastchunk);	/* reading last block */
			buf=(char *)strstr(input,substr);
			while(buf!=NULL)
			{ count++;
			  strcpy(input,buf+1);
			  buf=(char *)strstr(input,substr);
			}
		}
	}
close(fdtmp);
	return count;	/* return # of byte read */
}

int editbinary(WINDOW *mywb0,WINDOW *mywb2,struct mydirent *filelist,int mytotal)
{ int index,i,fdtmp;long blockindex[40];
  char content[40][256],buf1[10],filename[40],buf[10];
  long blockno,max;int fileno,x,y,hex,myindex=0;struct stat fp;
  int bytehex,offset,posx,posy;
 
	fprintf(myfp,"s "); 
/*clear buffer*/
	for(i=0;i<40;i++)	
	{	blockindex[i]=-1; 
		strcpy(content[i],"\0");
	}
/*get file and block no*/
	mvwaddstr(mywb2,3,0,"Edit file number :");
	wrefresh(mywb2);
	echo();
	wgetstr(mywb2,buf1);
	fprintf(myfp,buf1);fprintf(myfp," ");
	noecho();
	fileno=atoi(buf1);
	if(strlen(buf1)==0||fileno>mytotal-1)	
		return -1;
	strcpy(filename,filelist[fileno].name);
	mvwaddstr(mywb2,3,0," Edit block number :");
	wrefresh(mywb2);
	echo();
	wgetstr(mywb2,buf1);
	noecho();
	fprintf(myfp,buf1);fprintf(myfp,"\n");
	if(strlen(buf1)==0)	
		blockno=0;
	else
		blockno=atol(buf1);
	lstat(filename,&fp);
	max=fp.st_size/256;
	if(fp.st_size%256>0)	max++;
	if(blockno>max-1)	blockno=max-1;
	fdtmp=open(filename,O_RDWR);
	if(fdtmp<0)
	{	mvwaddstr(mywb2,3,0,"Error! cannot open file for edit.  Press any key to continue.");
		wrefresh(mywb2);
		getch();
		return -1;
	}
	lseek(fdtmp,blockno*256,SEEK_SET);
	strcpy(content[myindex],"\0");
	read(fdtmp,content[myindex],256);
	blockindex[myindex]=blockno;
	hex=0;y=1;
/* display panel */
	wclear(mywb2);
	mvwaddstr(mywb2,0,0,"T) Toggle(Hex/Asc), W) Edit, Y) Prev block, Z) Next Block, Q) Quit");
	wrefresh(mywb2);
	displaybinary(mywb0,hex,content[myindex],blockno);
	posx=12;posy=2;
	while(y)
	{
		wmove(mywb0,posy,posx);wrefresh(mywb0);
		x=getch();	/* get user command */
		switch(x)
		{
		 case 121:
		 case 89:	/* y previous  block*/
			if(blockno==0)	break;
			myindex--;
			if(myindex<0)	myindex=39;
			blockno--;
			if(blockno!=blockindex[myindex]);
			{	lseek(fdtmp,blockno*256,SEEK_SET);
				strcpy(content[myindex],"\0");
				read(fdtmp,content[myindex],256);
				blockindex[myindex]=blockno;
			}
			displaybinary(mywb0,hex,content[myindex],blockno);
			break;
		 case 122:
		 case 90:	/* z next block*/
			if(blockno==max-1)	break;
			myindex++;
			if(myindex>39) index=0;
			blockno++;
			if(blockno!=blockindex[myindex])
			{	lseek(fdtmp,blockno*256,SEEK_SET);
				strcpy(content[myindex],"\0");
				read(fdtmp,content[myindex],256);
				blockindex[myindex]=blockno;
			}
			displaybinary(mywb0,hex,content[myindex],blockno);
			break;
		 case 119:
		 case 87:	/* w edit block*/
			offset=256;
			while(offset>255||offset<0)
			{
			 mvwaddstr(mywb2,3,0,"Enter offset(0-255):");
			 wrefresh(mywb2);
			 echo();
			 wgetstr(mywb2,buf1);
			 offset=atoi(buf1);
			 for(i=0;i<50;i++) mvwaddstr(mywb2,3,i," "); /*Clear*/
			}	
			bytehex=256;
			while(bytehex>255||bytehex<0)
			{
			 mvwaddstr(mywb2,3,0,"Enter new hexbyte(00-ff):");
			 wrefresh(mywb2);
			 wgetstr(mywb2,buf1);
			 for(i=50;i>=0;i--) mvwaddstr(mywb2,3,i," "); /*Clear*/
			 noecho();	
			 if(strlen(buf1)==0)	bytehex=0;
			 else	bytehex=strtol(buf1,(char *)NULL,16);
			}
			content[myindex][offset]=(char)bytehex;
			displaybinary(mywb0,hex,content[myindex],blockno);
			lseek(fdtmp,blockno*256+offset,SEEK_SET);
			write(fdtmp,&(char)bytehex,1);
			wrefresh(mywb2);
			break;
		 case 113:	/* q quit */
		 case 81:
			y=0;
			break;
		 case 116:	/* t toggle */
		 case 84:
			if(hex==0)	hex=1;
			else	hex=0;
			displaybinary(mywb0,hex,content[myindex],blockno);
			break;
		 case 68:	/*left arrow*/
			posx=posx-(1+hex);
			if(posx<12)	posx=12;
			wmove(mywb0,posy,posx);wrefresh(mywb0);
			break;
		 case 66:	/*down arrow*/
			posy=posy+1;
			if(posy>14)	posy=14;
			wmove(mywb0,posy,posx);wrefresh(mywb0);
			break;
		 case 65:	/*up arrow*/
			posy=posy-1;
			if(posy<2)	posy=2;
			wmove(mywb0,posy,posx);wrefresh(mywb0);
			break;
		 case 67:	/*right arrow*/
			posx=posx+1+hex;
			if(posx>31+hex*20)	posx=31+hex*19;
			wmove(mywb0,posy,posx);wrefresh(mywb0);
			break;
		}
	}
	close(fdtmp);
	
}
void displaybinary(WINDOW *mywb0,int hex,char *content,long blockno)
{ char buf1[50];int i,x,y,len;

//display
	wclear(mywb0);
	sprintf(buf1,"Block #%d",blockno);
	mvwaddstr(mywb0,0,60,buf1);
	mvwaddstr(mywb0,0,0,"Address			Data");
	for(i=0;i<13;i++)
	{	sprintf(buf1,"%d",blockno*256+i*20);
		mvwaddstr(mywb0,i+2,0,buf1);
	}
	len=strlen(content);
	if(hex)
	{
		for(i=0;i<256;i++)	/* display in hex */
		{
			x=(i%20)*2+12;
			y=i/20+2;
			sprintf(buf1,"%02X",content[i]);
			mvwaddnstr(mywb0,y,x,buf1,2);
			if(i==len-1)	i=256;
		}
	}
	else
	{
		for(i=0;i<256;i++)	/* display in ASCII */
		{
			x=(i%20)+12;
			y=i/20+2;
			mvwaddnstr(mywb0,y,x,content+i,1);
		if(i==len-1)	i=256;
		}
	}
	wrefresh(mywb0);
}

    Source: geocities.com/vienna/7079/src

               ( geocities.com/vienna/7079)                   ( geocities.com/vienna)