[Subject Prev][Subject Next][Thread Prev][Thread Next][Subject Index][Thread Index]

Fwd: Re: Shell-Creation. A simulation Code



Hi Madhu,
Please see the attached code of a very basic simulated shell which i had
written two yrs ago... It is just a basic code to make u understand.
I have mined this code from my old data CD and it is working at least. Still I
am in search of the code which is a complete shell (clone of csh) and written
by me in the early last year. As soon as I get it, I will give u the code.

Please compile the file using 
	$gcc sunix.c
under bash ... Linux 

Please don't use Wall to compile as it will give u hell warning .... Currently
I don't have time to remove those :>)

Thanx
Archan Paul
Lateral Linux Labs
archanp@xxxxxxxxxxx

PS. Thaths, Please allow this mail to be posted in the list along with
attachment. :)


On Tue, 22 Aug 2000, you wrote:
> hi madhu
> 	i've a very simple, crude, barebones program that does a sort of
> create a shell. i remember i used it to escape the command logging by bash
> and also the display of commands by w.it's old and uses gets() which u r
> not supposed to.
> --------start of program------
> #include<stdio.h>
> void main()
> {
> 	do {
> 		printf("command:>");
> 		gets(str);
> 		if (strcmp(str,"exit")==0)
> 			exit(0);
> 		system(str);
> 	  } while 1;
> }
> --------end------------
> 	me thinks it works( it worked long ago) , but i dont know if it
> has mistakes. *BUT YOU CANNOT USE ANY INTERNAL COMMANDS !!!!!! *. means
> cd also wont work ! hope this gives u the idea ;-)
> 
> cheers
> cheedu
> 
>  On Mon, 14 Aug 2000, Madhu Sudhan.S wrote:
> 
> > Hello Everybody,
> > 
> > Can any one on the list please educate me on how to Create a private
> > Unix Shell of my own, allowing only a few basic simple commands on that
> > to work on that, like the ls, cd, etc.,. Other commands, like su, etc.,
> > should
> > throw an error "Command not found".
> > 
> > Anticipating quick reply ......
> > 
> > Regards
> > Madhu Sudhan.S
> > 
> > 
> 



-------------------------------------------------------


/*
 *         Simulation of UNIX           
 *         (c) Archan Paul' Dec1998 <archanp@xxxxxxxxxxx>
*/

/*
 * Please don't compile this file using Wall, .......... It is give u hell warning ;)
 * Just do 
 * 	$gcc suunix.c
 * 
 * This is just my very very very OLD code in my early days.... Enjoy the simple shell simulation...... 
 *
 * 
 * Please create a file called alogin.dat in the same directory as the executable
 * with the following content
 * root root
 * */
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define TRUE 1
#define FALSE 0
#define SIZE 256

int ttyOpenFlag = TRUE, aLoginFlag = FALSE, aLoginCount;
char vLoginName[10], fLoginName[10], vPassword[10], fPassword[10];
FILE *fpLoginFile;

/* veriables requred for shell */ 
char consoleInput[256], com[256], argument1[256], argument2[256];
int validCommandLineFlag;
int shellChildPID, shellPID; 
int consoleCode, status;
int i, j, registerSpace[256];

/* veriables requred for functionCat */
char catBuffer[SIZE];
int catStatus;
int fpCatSource;

/* veriables requred for functionCp*/
char cpBuffer[SIZE];
int cpStatus;
int fpCpSource, fpCpDestination;

/* veriables used by functionDate*/
int tm;

/* veriables used by functionAddUser*/
char addUserName[10], addUserOldPassword[10], addUserNewPassword[10];
FILE *fpAddUser;

/*
 * The following function simalutes the LOGIN process which is exec-ed by
 * INIT when getty() succeeds by successfully opening the tty-line.
 * In our Simulated UNIX it is considered that tty-line open is absolutely
 * successful and it is denoted by making ttyOpenFlag = TRUE.
 *
*/
alogin(void)
{
	/* getty process executes */
	/* set process group (setpgrp()) */
	/* open tty line */

	if (ttyOpenFlag == TRUE)
		{
		/* exec login program */
		/* the user will be offered for login until 'aLoginFlag' becomes
		 * TRUE and the number of unsuccessful login is checked by
		 * 'aLoginCount'. When 'aLoginCount' becomes greater than 10,
		 * no more offer of login is granted and the system is Shutdown. 
		*/
		printf("\nYou may use login name 'root' and password 'root'\n"); 
		printf("\nUse 'man' to see the commands available and to quit, use 'shutdown' or 'logout'\n"); 
		
		while ((aLoginFlag == FALSE) && (aLoginCount <= 10))
			{
			fpLoginFile = fopen("./alogin.dat", "r");
			if (fpLoginFile == NULL)
				{
				printf("\nSystem Error !! Can't open ./alogin.dat File\n");
				exit();
				}
			printf("\nLogin : ");
			printf("\033[01;33m");
			scanf("%s", &vLoginName);
			printf("\033[m");
			printf("Password : ");
			printf("\033[30m");
			scanf("%s", &vPassword);
			printf("\033[m");
			aLoginFlag = FALSE;

			while(1)
			{
				if(feof(fpLoginFile)) break;	
				fscanf(fpLoginFile, "%s %s\n", fLoginName, fPassword);
				if (strcmp(vLoginName, fLoginName) == 0)
				{
					if (strcmp(vPassword, fPassword) == 0)
					{
						aLoginFlag = TRUE;
						break;
					}
				}				
			}

			if (aLoginFlag == TRUE) /* login successful */ 		
				{	
				printf("\033[01;36mLogin successful\033[m\n");				
				/* INIT prcess exec-ed shell from here */
				ashell();
				aLoginFlag = FALSE;
				aLoginCount = 0;
				}
			else
				{		
				/* login is not successful */
				printf("\033[01;31mLogin incorrect\033[m\n");
				aLoginCount ++;
				}
			} /* while loop ends here */	
		if (aLoginCount > 10)
			{
			printf("\nNumber of Login Attempts exceeded.");
			printf("\nSystem is Locked for possible Intrusion..\n");                              
			printf("\nSending all the process term-end signal........");
			printf("\nSimulated Unix has Shutdown.....");		
			kill(0, SIGKILL);
			}
		fclose(fpLoginFile);
		}		
}		

/*
 * The follwing function simulates the shell for the Simulated UNIX.
*/
ashell(void)
{
	printf("Simulated INIT process has exec-ed shell having pid %d", getpid());
	while (1)
	{	printf("\n$>");
		/* to parent to ignore the death of any child */
		signal(SIGCLD, SIG_IGN);
		perseInput();
		extractCommand();

		/* if the 'shutdown' command is entered, all the process which 
		 * are the child of the simulated INIT process and the 
		 * simulated INIT are killed and the Simulated UNIX environment
		 * comes to an end.
		*/ 		
		if (strcmp(com, "shutdown") == 0)
			{
			printf("\nSending all the process term-end signal........");
			printf("\nSimulated Unix has Shutdown.....");		
			kill(0, SIGKILL);
			}

		/*
		 * if the 'logout' command is entered, the program control is
		 * taken outside of the while-loop and the subsequent login
		 * process is initialised. Please check-out the control logic
		 * flow carefully. 
		 */
		if (strcmp(com, "logout") == 0)
			{
			break;
			}
	
		if (strcmp(com, "date") == 0)
			{
			if (fork() == 0) functionDate();
			wait(&status);
			}

		if (strcmp(com, "ls") == 0)
			{
			if (fork() == 0) functionLs();
			wait(&status);
			}
			
		if (strcmp(com, "cat") == 0)
			{
			if (fork() == 0) functionCat();
			wait(&status);
			}
			
		if (strcmp(com, "cp") == 0)
			{
			if (fork() == 0) functionCp();
			wait(&status);
			}
		
		if (strcmp(com, "clear") == 0)
			{
			if (fork() == 0) functionClear();
			wait(&status);
			}
			
		if (strcmp(com, "man") == 0)
			{
			if (fork() == 0) functionMan();
			wait(&status);
			}
			
		if (strcmp(com, "adduser") == 0)
			{
			if (fork() == 0) functionAddUser();
			wait(&status);
			}										
	}
}		


/*
 * The follwing 4 functions i.e. 'perseInput()' , 'extractCommand()',
 * 'extractArgument1()', 'extractArgument2()' are used for persing the 
 * console input of the command-line stored in 'consoleInput[]' array.
 *	'perseInput()' -- This function is used to perse through the
 *			command line entered in the Simulated UNIX shell
 *			and to register the position of occurance of space 
 *			in the command-line (as demarkation between the 
 *			command and arguments) to another array 'registerSpace[]'
 *
 *	'extractCommand()' -- This function is used to extract the command
 *			    from the whole command-line stored in the 
 *			    array 'consoleInput[]' by the efficient use of
 *			    veriable 'registerSpace[0]'.
 *			    Here 'register[0]' is used as it contains the
 *			    first demarkation position located in the
 *			    command-line 'consoleInput[]' and concerned 
 *			    command is transferred to 'com[]' as a string.
 *
 *	'extractArgument1() -- This function is used to extract the first
 *			     argument from the 'consoleInput[]' to 
 *			     'argument1[]' as a string, with the use of
 *			     'registerSpace[1]'. Here the 'registerSpace[1]'
 *			     is used as it contains the position of the second
 *			     demarkation in the command-line.
 *
 *	'extractArgument2()' -- This function is used to extract second argument
 *			      from the command-line. The further expaltion is as 
 *			      as previous.					       	
 **/
perseInput(void)
{
	/* read form the console */
	i=0;
	while ((consoleInput[i] = getchar()) != '\n') i++;
	consoleInput[i]='\0';
	
	for (i=0,j=0;i<256;i++)
	{
		if (consoleInput[i] == ' ' || consoleInput[i] == '\0')
			{
			registerSpace[j] = i;
			j++;
			}		
	}
}

extractCommand(void)
{
	for(i=0;i< registerSpace[0]; i++)
		{
		com[i] = consoleInput[i];
		}
	com[i] = '\0';	
}

extractArgument1(void)
{
	for(i=(registerSpace[0]+1);i< registerSpace[1]; i++)
		{
		argument1[i-(registerSpace[0]+1)] = consoleInput[i];
		}
	argument1[i] = '\0';	
}

extractArgument2(void)
{
	for(i=(registerSpace[1]+1);i< registerSpace[2]; i++)
		{
		argument2[i-(registerSpace[1]+1)] = consoleInput[i];
		}
	argument2[i] = '\0';	
}

/* The following function simulates CAT in the Simulated UNIX environment
 * when it is invoked by CAT command with or without valid argument in the 
 * Simulated UNIX shell.
 * Please refer to the 'printf()' statement for understanding of the process
 * executing the cat-function.
 * Here there is two instances of 'cat' command. When no argument is supplied
 * with the 'cat' command, the source-file of the cat-command is taken as
 * standard-input device. The corresponding code implemented here has a
 * known bug. If user wants to quit from this by ^z then all the process
 * terminates abruptly.
 * Otherwise if argument is supplied with cat command, then the concerned
 * file is opened and read and output is written in the standard-output
 * device. 
*/
functionCat(void)
{
	printf("%s command is executed by child process (pid %d) of parent process (pid %d)", com, getpid(), getppid());
	extractArgument1();
	if (argument1[0] == '\0')
		{
		/* 
		 * the first argument, 0 in the read function, depicts standard
		 * input device and the first argument, 1 in the write function
		 * depicts standard output device.
		 */
		while ( (catStatus = read(0, catBuffer, sizeof(catBuffer))) > 0)
			write(1, catBuffer, catStatus);
		}
	else
		{
		if ( (fpCatSource = open(argument1, 0)) != -1)
			{
			printf("\n");
			while ( (catStatus = read(fpCatSource, catBuffer, sizeof(catBuffer))) > 0)
				write(1, catBuffer, catStatus);		
			}
		else	printf("\nERROR !! Unable to open file %s......", argument1);
		close(fpCatSource);	
		}	
	exit(0);	
}

/* The following function simalates the CP in the Simulated UNIX 
 * environment when it is invoked by  'cp' command in the Simulated UNIX shell.
 * Please refer to the 'printf()' statement for understanding of the process
 * executing the cp-function.
*/
functionCp(void)
{
	printf("%s command is executed by child process (pid %d) of parent process (pid %d)", com, getpid(), getppid());
	extractArgument1();
	extractArgument2();
	if ((fpCpSource = open(argument1, 0)) == -1)
		{
		printf("ERROR !! Can't open source %s", argument1);
		exit(0);
		}
	if ((fpCpDestination = creat(argument2, 0666)) == -1)
		if ((fpCpDestination = open(argument2, 1)) == -1)
				{
				printf("ERROR !! Can't creat or overwrite destination file %s", argument2);	
				exit(0);
				}
	while ( (cpStatus = read(fpCpSource, cpBuffer, sizeof(cpBuffer))) > 0)
		write(fpCpDestination, cpBuffer, cpStatus);
	printf("\nCopying from %s to %s is successful. ", argument1, argument2);								
	exit(0);
}

functionClear(void)
{
	printf("%s command is executed by child process (pid %d) of parent process (pid %d)", com, getpid(), getppid());
	system("tput clear");
	exit(0);
}


/* The following function prints the date in the Simulated UNIX environment
 * when it is invoked by date command in the Simulated UNIX shell.
 * Please refer to the 'printf()' statement for understanding of the process
 * executing the date-function.
*/
functionDate(void)
{
	printf("%s command is executed by child process (pid %d) of parent process (pid %d)", com, getpid(), getppid());
	time(&tm);
	printf("\n %s", asctime(localtime(&tm)));
	exit(0);
}


/* The following function simulates 'ls' in the Simulated UNIX environment
 * when it is invoked by date command in the Simulated UNIX shell.
 * Please refer to the 'printf()' statement for understanding of the process
 * executing the ls-function.
*/
functionLs(void)
{
	printf("%s command is executed by child process (pid %d) of parent process (pid %d)", com, getpid(), getppid());
	system("ls");
	exit(0);
}

/* The following function simulates the man-command in the Simulated UNIX
 * environment.
*/
functionMan(void)
{
	printf("%s command is executed by child process (pid %d) of parent process (pid %d)", com, getpid(), getppid());
	printf("\n\nThe following Commands are avilable in the Simulated UNIX env");
	printf("\nclear date   ls   cat   cp   clear   man   logout   shutdown\n");
	exit(0);	
}

/*
 * The following function simulates the adduser-function in simulated UNIX
 * environment. This command is executed only when the user has login as
 * root. No validity checking is implemented in the following code, if user
 * is allready in the database. 
*/
functionAddUser(void)
{
	if (strcmp(vLoginName, "root") == 0)
		{
		if ( (fpAddUser = fopen("alogin.dat", "a+")) == NULL)
			{
			printf("\nERROR opening file 'alogin.dat'.....");
			}
		else
			{
			printf("\nEnter Login Name : ");
			scanf("%s", &addUserName);
			printf("Enter Password : ");
			printf("\033[30m");
			scanf("%s", &addUserOldPassword);
			printf("\033[m");
			printf("ReEnter Password : ");
			printf("\033[30m");
			scanf("%s", &addUserNewPassword);
			printf("\033[m");
			if (strcmp(addUserOldPassword, addUserNewPassword) == 0)
				{
					fprintf(fpAddUser, "%s %s\n", addUserName, addUserOldPassword);
					printf("\nPassword File is updated.");
				}	
			else
				{
				printf("\nDesparity in password rechecking");
				}	
			}	
		fclose(fpAddUser);	
		}
	else
		{
		printf("\nPermission Denied !! To use this command, login as root");
		}	
	exit(0);	
}

main(void)
{
	system("tput clear");
	while(1) {
		printf("Here the simulated INIT process has pid %d ", getpid());
		alogin();
	}	
}
root root