Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #include<sys/wait.h>
- #include<signal.h>
- #include <time.h>
- #define clear() printf("\033[H\033[J")
- #define LINEMAX 500 // MAX LIMIT FOR USER CHARACTER INPUT
- #define TOKENSMAX 20 // MAX LIMIT FOR COMMAND TOKEN
- #define pwd 1
- #define cd 2
- #define ls 3
- void signalHandler(int sig_num); //FUNCTION TO RECORD THE SIGCHILD SIGNAL IN LOG FILE
- void changeDir(char * args[]); //UTILITY FUNCTION TO CHANGE DIRECTORY
- void printDir(); // UTILITY FUNCTION TO PRINT CURRENT DIRECTORY
- void commandHandler(char * args[], int args_count); //FUNCTION TO HANDLE ENTERED COMMANDS
- int parseInput(char line[], char * tokens[]); // PARSE INPUT BY SEPARATING WITH SPACE
- char* getCurrentTime();
- int main()
- {
- char input[LINEMAX]; // USER INPUT
- char * commands[TOKENSMAX]; // COMMAND TOKENS
- int commands_count=0,exit_flag=1;
- struct sigaction sig; // DEFINING SIGACTION STRUCT TO HANDLE SIGNALS
- sig.sa_handler = signalHandler; // LINKING SA_HANDLER WITH IMPLEMENTATION OF SIGNAL HANDLER
- sigemptyset(&sig.sa_mask); // SET ZEROES
- sigaction(SIGCHLD,&sig,NULL); // CALL SIGNAL HANDLER ON CHILD TERMINATION
- printf("\t\t\t\tWelcome @%s\n\n",getenv("USER")); // WELCOME MESSAGE
- printf("The aim of this project is to create a simple Unix Shell program\ncapable of launching child processes. The project was created as a partial\nsimulation of the actual Unix terminal\n");
- while(exit_flag==1)
- {
- printDir(); //PRINT CURRENT DIRECTORY AFTER EACH LOOP
- fgets(input, LINEMAX, stdin); // READ USER INPUT
- commands_count=parseInput(input,commands); // PARSE USER'S INPUT AND STORE TOKEN COUNT
- if(commands_count==0)
- {
- continue;
- }
- if(strcmp(commands[0],"exit()") == 0) // IF COMMAND IS EXT(), TERMINATE
- {
- exit_flag=0;
- exit(0);
- }
- commandHandler(commands,commands_count); // HANDLE THE PARSED COMMANDS
- }
- return 0;
- }
- //FUNCTION TO RECORD THE SIGCHILD SIGNAL IN LOG FILE
- void signalHandler(int sig_num)
- {
- FILE *fp;
- char time[40];
- strcpy(time,getCurrentTime());
- fp=fopen("MYSIMPLESHELL.log","a+");
- if(fp == NULL)
- printf("\nERROR: OPENING FILE FAILED");
- else fprintf(fp,"%sCHILD PROCESS TERMINATED SUCCESSFULLY SIGNUM %d\n",time,sig_num);
- fclose(fp);
- }
- char* getCurrentTime()
- {
- time_t rawtime;
- struct tm * timeinfo;
- time ( &rawtime );
- timeinfo = localtime (&rawtime);
- return asctime (timeinfo);
- }
- // UTILITY FUNCTION TO PRINT CURRENT DIRECTORY
- void printDir()
- {
- char currentDir[1024];
- getcwd(currentDir, sizeof(currentDir));
- printf("\nDir: %s :~$ ", currentDir);
- }
- //UTILITY FUNCTION TO CHANGE DIRECTORY
- void changeDir(char * args[])
- {
- if (args[1] == NULL)
- chdir(getenv("HOME")); // ONLY CD written
- else
- {
- if (chdir(args[1]) == -1)
- printf(" %s: ERROR: DIRECTORY NOT AVAILABLE\n", args[1]);
- }
- }
- //FUNCTION TO HANDLE COMMANDS ENTERED
- void commandHandler(char * args[], int args_count)
- {
- int count = args_count;
- int back_flag = 0; //SET BACKGROUND FLAG TO NO
- if(!(strcmp(args[count-1],"&"))) //CHECK FOR BACKGROUND PROCESS INDICATOR '&'
- {
- back_flag=1; //SET BACKGROUND FLAG TO YES
- args[count-1]='\0'; //REMOVING *&
- count--;
- }
- // EXECUTE THE ENTERED COMMAND
- pid_t pid=fork(); //PROCESS ID
- if (pid >= 0) // FORKING SUCCESSFUL
- {
- if(pid == 0) //CHILD EXECUTING
- { if(execvp(args[0],args)<0)
- {
- printf("ERROR: COMMAND COULDN'T BE EXECUTED!");
- }
- }
- else
- {
- if(back_flag==1)
- return;
- else
- {
- wait(NULL);
- // SUSPEND PARENT TILL CHILD CHANGES STATE
- }
- }
- }
- else
- printf("\nFORKING FAILED!");
- }
- // PARSE INPUT BY SEPARATING BY WHITESPACES
- int parseInput(char line[], char * command_tokens[])
- {
- int i=0;
- if((command_tokens[i] = strtok(line," \n\t")) == NULL)
- return 0; // CASE OF NO INPUT, RETURN 0
- i=1;
- while((command_tokens[i] = strtok(NULL, " \n\t")) != NULL) // SEPARATE USER INPUT BY SPACES
- i++; // COUNTING TOKENS
- tokens[i]= NULL; // MAKING SURE LAST ELEMENT IS NULL
- return i;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement