Hey Guys. I’m working on the shell challenge to learn C and I’m at the test where we implement for echo. When I run ./your-program.sh directly and input exit 0 , the shell promptly exits. However, when I run the test using codecrafters test , exit somehow fails to work properly.
CODECRAFTERS TEST OUTPUT
Here’s the code`
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "array_list.h"
char* EXIT_COMMAND = "exit";
char* ECHO_COMMAND = "echo";
typedef struct {
char* command;
ArrayList* inputs;
} Command;
void free_command(Command* cmd) {
free(cmd->command);
free_array_list(cmd->inputs);
free(cmd);
}
Command* parse_command(char* command) {
Command* cmd = malloc(sizeof(Command));
cmd->inputs = new_array_list(10);
char* token = strtok(command, " ");
while (token != NULL) {
int length = strlen(token);
if (cmd->command == NULL) {
cmd->command = malloc(sizeof(char) * length);
strcpy(cmd->command, token);
} else {
add_array_list(cmd->inputs, token);
}
token = strtok(NULL, " ");
}
return cmd;
}
void perform_echo(Command* cmd) {
if (cmd->inputs == NULL || cmd->inputs->size == 0) {
return;
}
for (int i=0; i<cmd->inputs->size; i++) {
printf("%s", get_element_from_list(cmd->inputs, i));
if (i != cmd->inputs->size-1) {
printf(" ");
}
}
printf("\n");
}
// Captures the user's command in the "command" variable
char command[1024];
int main(int argc, char *argv[]) {
// Flush after every printf
setbuf(stdout, NULL);
while (1)
{
printf("$ ");
// Captures the user's command in the "command" variable
char command[1024];
fgets(command, sizeof(command), stdin);
command[strcspn(command, "\n")] = '\0';
Command* cmd = parse_command(command);
if (cmd == NULL) {
continue;
}
if (strcmp(cmd->command, EXIT_COMMAND) == 0) {
return 0;
}
if (strcmp(cmd->command, ECHO_COMMAND) == 0) {
perform_echo(cmd);
continue;
}
printf("%s: command not found\n", command);
free_command(cmd);
}
return 0;
}
array_list.c
#include <stdlib.h>
#include <string.h>
#include "array_list.h"
ArrayList* new_array_list(int capacity) {
if (capacity <= 0) {
return NULL;
}
ArrayList* list = malloc(sizeof(ArrayList));
if (list == NULL) {
return NULL;
}
list->capacity = capacity;
list->size = 0;
list->inputs = malloc(capacity * sizeof(char*));
if (list->inputs == NULL) {
free(list);
return NULL;
}
return list;
}
void add_array_list(ArrayList* list, char* element) {
if (list == NULL || element == NULL) {
return;
}
// Check if we need to resize
if (list->size >= list->capacity) {
// Double the capacity
int new_capacity = list->capacity * 2;
char** new_inputs = realloc(list->inputs, new_capacity * sizeof(char*));
if (new_inputs == NULL) {
return; // Failed to resize, could not add element
}
list->inputs = new_inputs;
list->capacity = new_capacity;
}
// Allocate memory for the string copy
list->inputs[list->size] = malloc((strlen(element) + 1) * sizeof(char));
if (list->inputs[list->size] == NULL) {
return;
}
// Copy the string
strcpy(list->inputs[list->size], element);
list->size++;
}
char* get_element_from_list(ArrayList* list, int index) {
if (list == NULL || index < 0 || index >= list->size) {
return NULL;
}
return list->inputs[index];
}
void free_array_list(ArrayList* list) {
if (list == NULL) {
return;
}
// Free all allocated strings
for (int i = 0; i < list->size; i++) {
if (list->inputs[i] != NULL) {
free(list->inputs[i]);
}
}
// Free the array of pointers
free(list->inputs);
// Free the list structure itself
free(list);
}
int array_list_size(ArrayList* list) {
if (list == NULL) {
return -1;
}
return list->size;
}
int array_list_capacity(ArrayList* list) {
if (list == NULL) {
return -1;
}
return list->capacity;
}

