#include #include #include #include #include #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)); char* exe = (char *)malloc(sizeof(char)); strcpy(exe,args[0]); strcpy(path, PATH); strcat(path, exe); printf("try: %s \n",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] = (char *)malloc(strlen(tok)*sizeof(char)); //returnArr[i] = tok; strcpy(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); }