Question: In C programming: I'm working on a shell and I have a function to parse and a function to expand variables. I need help with
In C programming:
I'm working on a shell and I have a function to parse and a function to expand variables. I need help with the execute_command function near the bottom of the main. Thank you!
Here's what I have so far:
#include
#include
#include
#include
#include
#include
#define MAX_ARGS 512
#define MAX_INPUT 2048
// Function to expand environment variables in a given string
void expand_vars(char* input) {
char* var_start;
char* var_end;
char* var_value;
char var_name[MAX_INPUT];
char output[MAX_INPUT];
char* out_pos = output;
while ((var_start = strchr(input, '$')) != NULL) {
if (*(var_start + 1) == '$') {
sprintf(out_pos, "%d", getpid());
out_pos += strlen(out_pos);
input = var_start + 2;
continue;
}
if (*(var_start + 1) == '?') {
sprintf(out_pos, "%d", WEXITSTATUS(EXIT_SUCCESS));
out_pos += strlen(out_pos);
input = var_start + 2;
continue;
}
if (*(var_start + 1) == '!') {
sprintf(out_pos, "%d", getpid());
out_pos += strlen(out_pos);
input = var_start + 2;
continue;
}
var_end = strpbrk(var_start + 1, " \t \"\'$\\");
if (var_end == NULL) {
var_end = var_start + strlen(var_start);
}
strncpy(var_name, var_start + 1, var_end - var_start - 1);
var_name[var_end - var_start - 1] = '\0';
var_value = getenv(var_name);
if (var_value == NULL) {
var_value = "";
}
*out_pos++ = '"';
strcpy(out_pos, var_value);
out_pos += strlen(var_value);
*out_pos++ = '"';
input = var_end;
}
strcpy(out_pos, input);
strcpy(input, output);
}
// Function to parse a command line into tokens
int parse_command(char* input, char** args, char** input_file, char** output_file, int* background) {
int i = 0;
char* token;
char* saveptr;
// Check for input redirection
if ((token = strstr(input, "<")) != NULL && (token == input || *(token-1) == ' ' || *(token-1) == '\t')) {
*token = '\0';
token++;
*input_file = strtok_r(token, " \t ", &saveptr);
expand_vars(*input_file);
}
// Check for output redirection
if ((token = strstr(input, ">")) != NULL && (token == input || *(token-1) == ' ' || *(token-1) == '\t')) {
*token = '\0';
token++;
*output_file = strtok_r(token, " \t ", &saveptr);
expand_vars(*output_file);
}
// Check for background execution
if ((token = strstr(input, "&")) != NULL && (token == input + strlen(input) - 1)) {
*background = 1;
*token = '\0';
}
// Parse the command and its arguments
while ((token = strtok_r(input, " \t ", &saveptr)) != NULL) {
input = NULL;
args[i] = (char*)malloc(strlen(token) + 1);
strcpy(args[i], token);
// Expand any environment variables in each argument
expand_vars(args[i]);
i++;
// Execute the command
execvp(args[0], args);
perror("execvp");
exit(EXIT_FAILURE);
} else {
// Parent process
// Wait for the child to complete if not running in the background
if (!background) {
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
exit_code = WEXITSTATUS(status);
}
}
}
return exit_code;
}
int main(int argc, char** argv) {
char* args[MAX_ARGS];
char input[MAX_INPUT];
char* input_file;
char* output_file;
int background;
int exit_code = 0;
while (1) {
input_file = NULL;
output_file = NULL;
background = 0;
printf("shell> ");
fflush(stdout);
// Read the command line from input
if (fgets(input, MAX_INPUT, stdin) == NULL) {
break;
}
// Parse the command line into tokens
if (parse_command(input, args, &input_file, &output_file, &background) < 0) {
continue;
}
// THIS FUNCTION
exit_code = execute_command(args, input_file, output_file, background);
// Free memory allocated for args
for (int i = 0; args[i] != NULL; i++) {
free(args[i]);
}
}
return exit_code;
}
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
