Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <errno.h>
- #define MAX_LENGTH 1024
- #define MAX 256
- #define CMD_MAX 10
- //A method which returns the number of tokens
- int make_tokenlist(char *buf, char* tokens[]) {
- char input_line[MAX]; //string to hold input
- char *line = buf; //pointer pointing to input buf
- int i=0; //counter
- //tokenizing input string
- tokens[i] = strtok(line, " ");
- do {
- i++; //incrementing i
- line = NULL; //setting line to null
- tokens[i] = strtok(line, " "); //getting the next token, placing it in next position in array
- } while (tokens[i] != NULL); //do while there are more tokens
- return i; //return number of strings
- }
- //A method which returns the two commands of a one pipe command
- void onePipeSplit(char *tokens[], char *command1[], char *command2[], int numTokens) {
- int i=0, j=0;
- //while the current token is not a pipe, do
- while (strcmp(tokens[j], "|")!=0) {
- command1[i] = malloc(sizeof(tokens[j])+1); //allocate memory
- strcpy(command1[i], tokens[j]); //copy current token to command1
- i++; j++; //increment i and j
- }
- j++; //Increment j
- i=0; //reset i
- //while j < the number of tokens, do
- while (j < numTokens) {
- command2[i] = malloc(sizeof(tokens[j])+1); //allocate memory
- strcpy(command2[i], tokens[j]); //copy current token to command2
- i++; j++; //increment i and j
- }
- }
- //A method which counts the number of pipes in the user's input
- int countPipes(int size, char *tokens[]) {
- int numPipes = 0; //Value which holds number of pipes
- for (int i=0; i<size; i++) { //for i to number of tokens, do
- if (strcmp(tokens[i], "|")==0) { //if tokens[i] equals '|', then
- numPipes++; //increment numPipes
- }
- }
- return numPipes; //return numPipes
- }
- //A method which adds the current command to history
- void updateHistory(char *history[], char command[], int histIndex) {
- history[histIndex] = realloc(history[histIndex], MAX_LENGTH); //Allocating space
- strcpy(history[histIndex], command); //Put the current command in history
- }
- //A method which increments the histIndex
- int incrementIndex(int index) {
- if (index != 9)
- return index+1;
- else
- return 0;
- }
- //A method which prints out our history
- void getHistory(char *history[], int histIndex) {
- //Loop through the current index to 10 and print out commands
- for (int i=histIndex; i < 10; i++) {
- if (history[i]!=NULL) //If it isn't null, then print
- printf("%s\n", history[i]);
- }
- //Loop through 0 to the current index and print out commands
- for (int i=0; i<histIndex; i++) {
- if (history[i]!=NULL) //If it isn't null, then print
- printf("%s\n", history[i]);
- }
- }
- ////////////////////// MAIN ////////////////////////
- ///////////////////////////////////////////////////////////////////////
- int main(int argc, char *argv[]) {
- char *path = "/bin/"; //Path to commands
- char input[MAX], *tokens[CMD_MAX]; //strings to input and token
- int i, j, numTokens, numPipes; //initializing ints
- char *piped_input; //string holding input when the user uses a pipe
- char *history[10]; //An array holding the last 10 commands
- int histIndex = 0; //An int which keeps track of the current position in history
- for (int i=0; i<10; i++) { //Initialize the values in history
- history[i] = malloc(MAX_LENGTH);
- if (history[i]==NULL) { //If history at position i is null, then it failed
- printf("Unable to allocate memory.\n"); //allocating memory, so exit
- exit(EXIT_FAILURE);
- }
- }
- //while true, do
- while (1) {
- printf("%s> ", getenv("USER")); //print out the user's name + >
- fgets(input, MAX, stdin); //Get the users input
- strtok(input, "\n"); //Take the entire line and set it to input
- updateHistory(history, input, histIndex);
- histIndex = incrementIndex(histIndex);
- if (strcmp(input, "exit")==0) { //If the input is exit, then exit
- for (int i=0; i<10; i++) { //Freeing the space allocated to history
- free(history[i]);
- }
- exit(0);
- }
- //Else if the current command is history, then print the last 10 commands
- else if (strcmp(input, "history")==0) {
- getHistory(history, histIndex);
- }
- //Otherwise, do
- else {
- numTokens = make_tokenlist(input, tokens); //Counting the number of tokens
- tokens[numTokens] = NULL; //Initializing an array of each token
- char cmd[MAX_LENGTH]; //string which holds the user's command
- strcpy(cmd, tokens[0]); //copying the command to the cmd string
- pid_t pid = fork(); //Creating child 1
- if (pid < 0) { //if pid is < 0 then we have an error
- perror("Problem forking.");
- exit(EXIT_FAILURE);
- }
- else if (pid > 0) { //else if pid > 0 then this is the parent, so wait
- wait(NULL);
- }
- else { //Otherwise make the child execute cmd
- //Count the number of pipes in the input
- numPipes = countPipes(numTokens, tokens);
- if (numPipes == 0) { //if the number of pipes is 0, then
- execvp(cmd, tokens); //execute the command
- perror("Error"); //if the command doesn't execute, then we have an error
- exit(EXIT_FAILURE); //exit
- }
- //Otherwise if we have a single pipe, then do
- else if (numPipes == 1) {
- char *command1[CMD_MAX]; //string holding the first command
- char *command2[CMD_MAX]; //string holding the second command
- int fds[2]; //create file descriptors for the parent and child
- pid_t new_pid; //create new pid_t obj
- onePipeSplit(tokens, command1, command2, numTokens); //Getting each command for pipe
- if (pipe(fds) < 0) { //use the pipe command. If < 0
- perror("Pipe failure."); //we have an error, so exit
- exit(EXIT_FAILURE);
- }
- //Creating child 2
- new_pid = fork();
- //if pid < 0 then we have an error. Exit.
- if (new_pid < 0) {
- perror("Fork failure.");
- exit(EXIT_FAILURE);
- }
- //Else we have the child (2) process
- else if (new_pid == 0) {
- close(fds[0]); //Close read
- //sending stdin to the shared file descriptor
- if (dup2(fds[1], STDOUT_FILENO)<0) {
- perror("Can't dup");
- exit(EXIT_FAILURE);
- }
- execvp(command1[0], command1); //Execute the next command
- perror("Exec failure");
- exit(EXIT_FAILURE);
- }
- //Else if we have the parent process
- else {
- pid_t child = fork(); //Creating child 3
- if (new_pid < 0) { //if pid < 0, error, exit
- perror("Fork failure.");
- exit(EXIT_FAILURE);
- }
- //else if pid > 0 we have the parent wait until children execute
- else if (new_pid > 0) {
- wait(NULL);
- }
- //else we have the child (3)
- else {
- close(fds[1]); //Close write
- //Sending stdout to the shared file descriptor
- if (dup2(fds[0], STDIN_FILENO) < 0) {
- perror("Can't dup");
- exit(EXIT_FAILURE);
- }
- execvp(command2[0], command2); //Execute the command
- perror("Exec failure");
- exit(EXIT_FAILURE);
- }
- }
- }
- //////////////////////////////////////////TODO: COMPLETE 2 PIPES/////////////////////////////////////////////
- else if (numPipes == 2) {
- }
- else {
- printf("\nCan't use more than 2 pipes.\n");
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement