Semi working - garbedge in args**
This commit is contained in:
commit
5a7914e9d7
4 changed files with 250 additions and 0 deletions
41
Makefile
Normal file
41
Makefile
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# Sagi Dayan - Makefile
|
||||||
|
#
|
||||||
|
|
||||||
|
# compiler
|
||||||
|
CC=gcc
|
||||||
|
|
||||||
|
# compile arguments
|
||||||
|
CFLAGS+=-c -g -Wall
|
||||||
|
|
||||||
|
# linker flags
|
||||||
|
LDFLAGS+=
|
||||||
|
|
||||||
|
# libraries
|
||||||
|
LIBS+=
|
||||||
|
|
||||||
|
# our source files
|
||||||
|
SOURCES=main.c
|
||||||
|
|
||||||
|
# a macro to define the objects from sources
|
||||||
|
OBJECTS=$(SOURCES:.c=.o)
|
||||||
|
|
||||||
|
# executable name
|
||||||
|
EXECUTABLE=myTerminal
|
||||||
|
|
||||||
|
$(EXECUTABLE): $(OBJECTS)
|
||||||
|
@echo "Building target" $@ "..."
|
||||||
|
$(CC) $(LDFLAGS) $(OBJECTS) -o $@ $(LIBS)
|
||||||
|
@echo "Done!"
|
||||||
|
|
||||||
|
# a rule for generating object files given their c files
|
||||||
|
.c.o:
|
||||||
|
@echo "Compiling" $< "..."
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Done!"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "Ceaning up *.o Files..."
|
||||||
|
rm -rf *s *o $(EXECUTABLE)
|
||||||
|
@echo "Done!"
|
||||||
|
|
||||||
|
.PHONY: all clean
|
209
main.c
Normal file
209
main.c
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define LEN 512
|
||||||
|
#define PATH "/bin/"
|
||||||
|
#define ERROR -1
|
||||||
|
#define EXIT_1 256
|
||||||
|
|
||||||
|
int getHostName(char* host);
|
||||||
|
int getUserName(char* name);
|
||||||
|
int runExec(char** args);
|
||||||
|
void PrintTokens (char** tokens);
|
||||||
|
char** ReadTokens(FILE* stream) ;
|
||||||
|
void FreeTokens(char** tokens) ;
|
||||||
|
void checkIfQuit(char* word);
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int exitCode = 0;
|
||||||
|
char* host_n = (char *)malloc(sizeof(char));
|
||||||
|
char* user_n = (char *)malloc(sizeof(char));
|
||||||
|
char** args;
|
||||||
|
|
||||||
|
if(getHostName(host_n) == ERROR)
|
||||||
|
goto quit;
|
||||||
|
if(getUserName(user_n) == ERROR)
|
||||||
|
goto quit;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
printf("%d %s@%s$ ",exitCode, user_n, host_n);
|
||||||
|
args = ReadTokens(stdin);
|
||||||
|
if(args != NULL)
|
||||||
|
{
|
||||||
|
exitCode = runExec(args);
|
||||||
|
FreeTokens(args); //in case of error while trying to create process - this method will free the memory already
|
||||||
|
if(exitCode == ERROR)
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quit:
|
||||||
|
free(host_n);
|
||||||
|
free(user_n);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getHostName(char* host)
|
||||||
|
{
|
||||||
|
if(gethostname(host, 10) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", "Error: while getting host name");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getUserName(char* name)
|
||||||
|
{
|
||||||
|
if(getlogin_r(name, 10) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", "Error: while getting User name");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function will atempt to create a new Process.
|
||||||
|
* and will return the exit status code of the child
|
||||||
|
* @param args - an array of strings that contains all the arguments from the user
|
||||||
|
* @return int - exit status of child
|
||||||
|
*/
|
||||||
|
int runExec(char** args)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
pid_t pid;
|
||||||
|
char* path = (char *)malloc(sizeof(char));
|
||||||
|
strcpy(path, PATH);
|
||||||
|
strcat(path, args[0]);
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
|
||||||
|
if(pid < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", "Error: Could not create a new process");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
else if(pid == 0) // child
|
||||||
|
{
|
||||||
|
if(execv(path, args) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s%s%s\n", "myTerminal: ", args[0] ,": command not found");
|
||||||
|
exit(1); //child error - chield needs to be closed manually. exit code 225;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //pid > 0 father
|
||||||
|
waitpid(pid,&status,0);
|
||||||
|
free(path);
|
||||||
|
if(status == EXIT_1) //in my computer exit(1) returns 256 - ex demands wanted 255
|
||||||
|
return status-1;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this func will read a full line and will store all the arguments in an array (of char*).
|
||||||
|
* if the line will have only 1 word - it will call afunction to check if the word is "quit".
|
||||||
|
*
|
||||||
|
* @param stream FILE* - in our case stdin
|
||||||
|
* @return if all went well , an Array of arguements from the input line.
|
||||||
|
*/
|
||||||
|
char** ReadTokens(FILE* stream)
|
||||||
|
{
|
||||||
|
char** returnArr;
|
||||||
|
char input[LEN]; // the var to hold the line
|
||||||
|
char temp[LEN]; // will be a copy of the input line - so we can figure how many words we have
|
||||||
|
int wordCnt = 0; // word counter
|
||||||
|
int i = 0; //index for second iteration
|
||||||
|
fgets(input, LEN, stream); // get the linei
|
||||||
|
|
||||||
|
strcpy(temp, input); // copy the line
|
||||||
|
|
||||||
|
//strkot first iteration to count words (corrups temp var)
|
||||||
|
char* tok;
|
||||||
|
tok = strtok(temp," \n");
|
||||||
|
while (tok != NULL)
|
||||||
|
{
|
||||||
|
wordCnt++;
|
||||||
|
tok = strtok(NULL, " \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(wordCnt == 0) //if there are no "words" in input - return null
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
|
returnArr = (char**)malloc((wordCnt + 1)*sizeof(char*)); //allocates the memory for the array
|
||||||
|
if(returnArr == NULL) //check if the malloc func finished successfuly
|
||||||
|
{
|
||||||
|
fprintf(stderr,"%s\n", "ERROR: unable to allocate memory.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//strtok second iteration - puts all words in an index of the array
|
||||||
|
tok = strtok(input," \n");
|
||||||
|
while (tok != NULL)
|
||||||
|
{
|
||||||
|
returnArr[i] = tok;
|
||||||
|
if(wordCnt == 1)
|
||||||
|
checkIfQuit(tok);
|
||||||
|
tok = strtok(NULL, " \n");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnArr[wordCnt] = NULL; // the last index will be NULL - so we know where the end is.
|
||||||
|
|
||||||
|
return returnArr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if there is only one word in the input nile the ReadTokens func will call this func.
|
||||||
|
* it will check if user want to exit our program
|
||||||
|
*
|
||||||
|
* @param word - the one word to check
|
||||||
|
*/
|
||||||
|
void checkIfQuit(char* word)
|
||||||
|
{
|
||||||
|
if(strcmp(word, "quit") == 0)
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this func will print an array of char*, it will know when to finish if the
|
||||||
|
* last index is NULL!
|
||||||
|
* @param tokens - char* Array
|
||||||
|
*/
|
||||||
|
void PrintTokens (char** tokens)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; tokens[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
printf("%s\n", tokens[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this will make sure no memory leeks will occurd.
|
||||||
|
* runs through all indexes change them to null and then free them.
|
||||||
|
* after that it will fraa the array pinter itself.
|
||||||
|
* @param tokens - an array to free
|
||||||
|
*/
|
||||||
|
void FreeTokens(char** tokens)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while(tokens[i] != NULL) // free all the indexes except the last one (NULL)
|
||||||
|
{
|
||||||
|
tokens[i] = NULL;
|
||||||
|
free(tokens[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
free(tokens[i]); // free the last index
|
||||||
|
tokens = NULL; // free the array
|
||||||
|
free(tokens);
|
||||||
|
}
|
BIN
main.o
Normal file
BIN
main.o
Normal file
Binary file not shown.
BIN
myTerminal
Executable file
BIN
myTerminal
Executable file
Binary file not shown.
Loading…
Reference in a new issue