Select Git revision

Wendy Nguyen authored
dshlib.c 9.76 KiB
#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"
/*
* 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()
*/
void printDragon(){
const char dragon[39][103] = {
" @%%%% \n",
" %%%%%% \n",
" %%%%%% \n",
" % %%%%%%% @ \n",
" %%%%%%%%%% %%%%%%% \n",
" %%%%%%% %%%%@ %%%%%%%%%%%%@ %%%%%% @%%%% \n",
" %%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%% \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%% %%%%%%%%%%%%%%% \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%% %%% \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%@ @%%%%%%%%%%%%%%%%%% %% \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%% \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@%%%%%%@ \n",
" %%%%%%%%@ %%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%% %% \n",
" %%%%%%%%%%%%% %%@%%%%%%%%%%%% %%%%%%%%%%% %%%%%%%%%%%% @% \n",
" %%%%%%%%%% %%% %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%% \n",
" %%%%%%%%% % %%%%%%%%%%%%% %%%%%%%%%%%%@%%%%%%%%%%% \n",
"%%%%%%%%%@ % %%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%% \n",
"%%%%%%%%@ %%@%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%%%%% \n",
"%%%%%%%@ %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \n",
"%%%%%%%%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% \n",
"%%%%%%%%%@ @%%%%%%%%%%%%%% %%%%%%%%%%%%@ %%%% %%%%%%%%%%%%%%%%% %%%%%%%%\n",
"%%%%%%%%%% %%%%%%%%%%%%%%%%% %%%%%%%%%%%%% %%%%%%%%%%%%%%%%%% %%%%%%%%%\n",
"%%%%%%%%%@%%@ %%%%%%%%%%%%%%%%@ %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%% %%\n",
" %%%%%%%%%% % %%%%%%%%%%%%%%@ %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%% %%\n",
" %%%%%%%%%%%% @ %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% \n",
" %%%%%%%%%%%%% %% % %@ %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% \n",
" %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%% \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% \n",
" @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%% \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%% %%%%%%% \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%% @%%%%%%%%% \n",
" %%%%%%%%%%%%%%%%%%%% @%@% @%%%%%%%%%%%%%%%%%% %%% \n",
" %%%%%%%%%%%%%%% %%%%%%%%%% %%%%%%%%%%%%%%% % \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%% \n",
" %%%%%%%%%%%%%%%%%%%%%%%%%% %%%% %%% %%%%%%%%%% %%%@ \n",
" %%%%%%%%%%%%%%%%%%% %%%%%% %% %%%%%%%%%%%%%@ \n",
" %%%%%%%@ \n"
};
for (int i = 0; i < sizeof(dragon) / sizeof(dragon[0]); i++) {
for (int j = 0; j < sizeof(dragon[0]) / sizeof(dragon[0][0]); j++) {
if (dragon[i][j] == 0) break;
putchar((char)dragon[i][j]);
}
}
}
int exec_local_cmd_loop()
{
char *cmd_buff;
int rc = 0;
cmd_buff_t cmd;
// TODO IMPLEMENT MAIN LOOP
// TODO IMPLEMENT parsing input to cmd_buff_t *cmd_buff
cmd_buff = malloc(SH_CMD_MAX);
if (!cmd_buff) return ERR_MEMORY;
while(1) {
printf("%s", SH_PROMPT);
if (fgets(cmd_buff, ARG_MAX, stdin) == NULL) {
printf("\n");
break;
}
// Remove trailing newline
cmd_buff[strcspn(cmd_buff, "\n")] = '\0';
// Skip empty commands
if (strlen(cmd_buff) == 0) {
printf(CMD_WARN_NO_CMD);
continue;
}
// Parse command and arguments
char *exe = strtok(cmd_buff, " ");
char *args = strtok(NULL, "");
if (exe) {
cmd.argc = 0;
cmd.argv[cmd.argc++] = exe;
if (args) {
char* lastChar = args + strlen(args) - 1;
// removing space after the
while (*lastChar == ' ') {
*lastChar = '\0';
lastChar--;
}
char *argsNoQuotes = malloc(ARG_MAX);
int numQuotes = 0;
int argQuoteLength = strlen(args);
int argLength = 0;
while (*args != '\0') {
if (*args == '\"') {
numQuotes++;
args++;
} else {
*argsNoQuotes = *args;
argLength++;
args++;
argsNoQuotes++;
}
}
argsNoQuotes -= argLength;
cmd.argv[cmd.argc++] = argsNoQuotes;
}
else {
cmd.argv[cmd.argc] = NULL;
}
}
// TODO IMPLEMENT if built-in command, execute builtin logic for exit, cd (extra credit: dragon)
// the cd command should chdir to the provided directory; if no directory is provided, do nothing
if (strcmp(cmd.argv[0], EXIT_CMD) == 0) {
break;
} else if (strcmp(cmd.argv[0], "cd") == 0) {
if (cmd.argv[1]) {
if (chdir(cmd.argv[1]) != 0) {
perror("cd");
rc = ERR_CMD_ARGS_BAD;
}
}
continue;
} else if (strcmp(cmd.argv[0], "dragon") == 0) {
printDragon();
continue;
}
else if (strcmp(cmd.argv[0], "rc") == 0) {
printf("%d\n", rc);
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(CMD_ERR_EXECUTE);
return ERR_MEMORY;
} else if (pid == 0) {
execvp(cmd.argv[0], cmd.argv);
// printf(CMD_ERR_EXECUTE);
exit(errno);
} else {
// parent process
wait(&rc);
if (WIFEXITED(rc)) {
rc = WEXITSTATUS(rc); // Store last return code
} else {
rc = ERR_EXEC_CMD;
}
// wait(NULL);
}
}
}