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