Skip to content
Snippets Groups Projects
Select Git revision
  • 82b503724df1c1cd1429df3382483cadd07ad7e3
  • main default
2 results

README.md

Blame
  • dshlib.c NaN GiB
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #include <stdbool.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/wait.h>
    #include <errno.h>
    #include "dshlib.h"
    
    int numInstanceOf(char *str, const char c) {
    	int count = 0;
    	while (*str != '\0') {
    		if (*str == c) count++;
    		str++;
    	}
    	return count;
    }
    
    int alloc_cmd_buff(cmd_buff_t *cmd_buff) {
    	if (cmd_buff == NULL) {
    		return ERR_MEMORY;
    	}
    	cmd_buff->argc = 0;
    	
    	cmd_buff->argv = (char**)malloc(CMD_ARGV_MAX * sizeof(char *));
    	if (cmd_buff->argv == NULL) {
        	free(cmd_buff);
        	return ERR_MEMORY;
    	}
    
    	for (int i = 0; i < CMD_ARGV_MAX; i++) {
            cmd_buff->argv[i] = (char *)malloc(ARG_MAX);
            if (cmd_buff->argv[i] == NULL) {
                for (int j = 0; j < i; j++) {
                    free(cmd_buff->argv[j]);
                }
                free(cmd_buff->argv);
                return ERR_MEMORY;
            }
        }
    
    	cmd_buff->_cmd_buffer = (char *)malloc(SH_CMD_MAX);
    	if (cmd_buff->_cmd_buffer == NULL) {
            free(cmd_buff->_cmd_buffer);
    		for (int i = 0; i < CMD_ARGV_MAX; i++) {
                free(cmd_buff->argv[i]);
            }
            free(cmd_buff->argv);
            return ERR_MEMORY;
        }
    
    
    	return OK_EXIT;
    }
    
    int free_cmd_buff(cmd_buff_t *cmd_buff) {
    	free(cmd_buff->_cmd_buffer);
    	 
    	for (int i = 0; i < CMD_ARGV_MAX - 1; i++) free(cmd_buff->argv[i]);
    	free(cmd_buff);
    	return OK_EXIT;
    }
    
    int clear_cmd_buff(cmd_buff_t *cmd_buff) {
    	cmd_buff->argc = 0;
    	free(cmd_buff->_cmd_buffer);
    	
    	for (int i = 0; i < CMD_ARGV_MAX; i++) cmd_buff->argv[i] = NULL;
    	return OK_EXIT;
    }
    
    char* trim_whitespace(char *str) {
    	int start = 0;
    	while (isspace((unsigned char)str[start])) {
    		start++;
    	}
    
      	int end = strlen(str) - 1;
      	while (end > start && isspace((unsigned char)str[end])) {
        	end--;
      	}
    
      	int j = 0;
      	for (int i = start; i <= end; i++) {
        	str[j++] = str[i];
      	}
      	str[j] = '\0';
      	
      	return str;
    }
    
    int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff) {
    	if ((int)strlen(cmd_line) > SH_CMD_MAX) return ERR_CMD_OR_ARGS_TOO_BIG;
    
    	if ((int)strlen(cmd_line) == 0) return WARN_NO_CMDS;	
    	
    	cmd_buff->_cmd_buffer = strdup(trim_whitespace(cmd_line));
    	if (cmd_buff->_cmd_buffer == NULL) {
    		free(cmd_buff);
    		return ERR_MEMORY;
    	}
    	
    	char *token = cmd_buff->_cmd_buffer;
    	bool quotes = false;
    	char *p = NULL;
    
    	while (*token) {
    		if (*token == DOUBLE_QUOTE_CHAR) {
    			quotes = !quotes;
    			if (quotes) p = token + 1;
    			else *token = '\0';
    		} else if (!quotes && (*token == SPACE_CHAR || *token == '\t')) {
    			*token = '\0';
    
    			if (p != NULL) {
    				cmd_buff->argv[cmd_buff->argc++] = p;
    				p = NULL;
    			}
    		} else if (p == NULL) {
    			p = token;
    		}
    		token++;
    	}
    
    	if (p != NULL) cmd_buff->argv[cmd_buff->argc++] = p;
    
    	cmd_buff->argv[cmd_buff->argc] = NULL;
    	return OK_EXIT;
    }
    /*
     * Implement your exec_local_cmd_loop function by building a loop that prompts the 
     * user for input.  Use the SH_PROMPT constant from dshlib.h and then
     * use fgets to accept user input.
     * 
     *      while(1){
     *        printf("%s", SH_PROMPT);
     *        if (fgets(cmd_buff, ARG_MAX, stdin) == NULL){
     *           printf("\n");
     *           break;
     *        }
     *        //remove the trailing \n from cmd_buff
     *        cmd_buff[strcspn(cmd_buff,"\n")] = '\0';
     * 
     *        //IMPLEMENT THE REST OF THE REQUIREMENTS
     *      }
     * 
     *   Also, use the constants in the dshlib.h in this code.  
     *      SH_CMD_MAX              maximum buffer size for user input
     *      EXIT_CMD                constant that terminates the dsh program
     *      SH_PROMPT               the shell prompt
     *      OK                      the command was parsed properly
     *      WARN_NO_CMDS            the user command was empty
     *      ERR_TOO_MANY_COMMANDS   too many pipes used
     *      ERR_MEMORY              dynamic memory management failure
     * 
     *   errors returned
     *      OK                     No error
     *      ERR_MEMORY             Dynamic memory management failure
     *      WARN_NO_CMDS           No commands parsed
     *      ERR_TOO_MANY_COMMANDS  too many pipes used
     *   
     *   console messages
     *      CMD_WARN_NO_CMD        print on WARN_NO_CMDS
     *      CMD_ERR_PIPE_LIMIT     print on ERR_TOO_MANY_COMMANDS
     *      CMD_ERR_EXECUTE        print on execution failure of external command
     * 
     *  Standard Library Functions You Might Want To Consider Using (assignment 1+)
     *      malloc(), free(), strlen(), fgets(), strcspn(), printf()
     * 
     *  Standard Library Functions You Might Want To Consider Using (assignment 2+)
     *      fork(), execvp(), exit(), chdir()
     */
    int exec_local_cmd_loop()
    {
        char *cmd_buff = malloc(ARG_MAX * sizeof(char));
    	int rc = 0;
        cmd_buff_t *cmd = malloc(CMD_ARGV_MAX * sizeof(char *));
    	
    	if ((rc = alloc_cmd_buff(cmd)) != OK_EXIT) exit(rc);
    
        // TODO IMPLEMENT MAIN LOOP
    	while(1){
     		printf("%s", SH_PROMPT);
     		if (fgets(cmd_buff, ARG_MAX, stdin) == NULL){
     			printf("\n");
     			break;
     		}
     		//remove the trailing \n from cmd_buff
     		cmd_buff[strcspn(cmd_buff,"\n")] = '\0';
    
     		//IMPLEMENT THE REST OF THE REQUIREMENTS
    		if (strcmp(cmd_buff, EXIT_CMD) == 0) {
                exit(rc);
            }
    
            if (strcmp(cmd_buff, "rc") == 0) {
            	printf("%d\n", rc);
    			if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
    			continue;
    		}
    
            if (strcmp(cmd_buff, "\0") == 0) {
                rc = WARN_NO_CMDS;
                printf(CMD_WARN_NO_CMD);
                //if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
                continue;
            }
    		
    		// TODO IMPLEMENT parsing input to cmd_buff_t *cmd_buff
    		if ((rc = build_cmd_buff(cmd_buff, cmd)) != OK_EXIT) {
                exit(rc);
                rc = 0;
        	}
    		/*
    		if (strcmp(cmd->argv[0], "echo") == 0) {
    			for (int i = 1; i < CMD_ARGV_MAX; i++) {
    				printf("%s ", cmd->argv[i]);
    			}
    			printf("\n");
    			if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
    			continue;
    		}*/
    		
    		// TODO IMPLEMENT if built-in command, execute builtin logic for exit, cd (extra credit: dragon)
    		if (strcmp(cmd_buff, "dragon") == 0) {
                print_dragon();
                if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
                rc = 0;
                continue;
            }
    
        	// the cd command should chdir to the provided directory; if no directory is provided, do nothing
        	if (strcmp(cmd->argv[0], "cd") == 0) {
    			if (cmd->argc < 2) {
    				if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
    				rc = 0;
    				continue;
    			}
    			if (chdir(cmd->argv[1]) != 0) {
    				perror("chdir failed");
    				rc = 1;
    			}
    			if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
    			rc = 0;
    			continue;
        	}
    
        	// TODO IMPLEMENT if not built-in command, fork/exec as an external command
        	// for example, if the user input is "ls -l", you would fork/exec the command "ls" with the arg "-l"
        	pid_t pid = fork();
        	if (pid < 0) {
    			printf("fork failed");
    			if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
    			continue;
        	} else if (pid == 0) {
    			execvp(cmd->argv[0], cmd->argv);
    			perror(CMD_ERR_EXECUTE);
    			exit(1);
        	} else {
    			int status;
    			waitpid(pid, &status, 0);
    			if (WIFEXITED(status)) {
    				rc = WEXITSTATUS(status);
    			} else {
    				rc = 1;
    			}
        	}
    		if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
    	}
    	free(cmd_buff);
    	free_cmd_buff(cmd);
        return OK;
    }