I’m stuck on Stage #(The Software Pro's Best Kept Secret.).
The test passing locally here is the screen shot
Here are my logs:
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 954 bytes | 954.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
remote: ------------------------------------------------------------------------
remote:
remote:
remote: ___ _ ___ __ _
remote: / __\ ___ __| | ___ / __\_ __ __ _ / _|| |_ ___ _ __ ___
remote: / / / _ \ / _` | / _ \ / / | '__|/ _` || |_ | __|/ _ \| '__|/ __|
remote: / /___| (_) || (_| || __// /___| | | (_| || _|| |_| __/| | \__
remote: \____/ \___/ \__,_| \___|\____/|_| \__,_||_| \__|\___||_| |___/
remote:
remote:
remote: Welcome to CodeCrafters! Your commit was received successfully.
remote:
remote: ------------------------------------------------------------------------
remote:
remote: Welcome back! Your first build could take slightly longer, please bear with us.
remote: Subsequent ones will be snappy ⚡
remote:
remote: Streaming build logs...
remote:
remote: [build] Starting build...
remote: [build] If you don't see logs for 60s+, please contact us at hello@codecrafters.io
remote: [build] Step 1 complete.
remote: [build] Step 2 complete.
remote: [build] Step 3 complete.
remote: [build] Step 4 complete.
remote: [build] Step 5 complete.
remote: [build] Step 6 complete.
remote: [build] Step 7 complete.
remote: [build] Step 8 complete.
remote: [build] Step 9 complete.
remote: [build] Step 10 complete.
remote: [build] Step 11 complete.
remote: [build] Step 10 complete.
remote: [build] Step 12 complete.
remote: [build] Step 13 complete.
remote: [build] Step 14 complete.
remote: [build] Step 15 complete.
remote: [build] Step 16 complete.
remote: [build] Step 17 complete.
remote: [build] > All requested packages are currently installed.
remote: [build] > Total install time: 32.1 us
remote: [build] Step 18 complete.
remote: [build] Step 19 complete.
remote: [build] Step 20 complete.
remote: [build] Step 21 complete.
remote: [build] Step 22 complete.
remote: [build] Step 23 complete.
remote: [build] Step 24 complete.
remote: [build] Step 25 complete.
remote: [build] Step 27 complete.
remote: [build] Step 26 complete.
remote: [build] Build successful.
remote:
remote:
remote: Running tests on your code. Logs should appear shortly...
remote:
remote: [compile] -- Running vcpkg install
remote: [compile] All requested packages are currently installed.
remote: [compile] Total install time: 93.2 us
remote: [compile] -- Running vcpkg install - done
remote: [compile] -- The C compiler identification is GNU 14.2.0
remote: [compile] -- The CXX compiler identification is GNU 14.2.0
remote: [compile] -- Detecting C compiler ABI info
remote: [compile] -- Detecting C compiler ABI info - done
remote: [compile] -- Check for working C compiler: /usr/bin/cc - skipped
remote: [compile] -- Detecting C compile features
remote: [compile] -- Detecting C compile features - done
remote: [compile] -- Detecting CXX compiler ABI info
remote: [compile] -- Detecting CXX compiler ABI info - done
remote: [compile] -- Check for working CXX compiler: /usr/local/bin/c++ - skipped
remote: [compile] -- Detecting CXX compile features
remote: [compile] -- Detecting CXX compile features - done
remote: [compile] -- Configuring done (0.7s)
remote: [compile] -- Generating done (0.0s)
remote: [compile] -- Build files have been written to: /app/build
remote: [compile] [ 50%] Building C object CMakeFiles/shell.dir/src/main.c.o
remote: [compile] [100%] Linking C executable shell
remote: [compile] [100%] Built target shell
remote: [compile] Moved ./.codecrafters/run.sh → ./your_program.sh
remote: [compile] Compilation successful.
remote:
remote: Debug = true
remote:
remote: [tester::#MG5] Running tests for Stage #MG5 (The type builtin: executable files)
remote: [tester::#MG5] [setup] export PATH=/tmp/bar:$PATH
remote: [tester::#MG5] [setup] export PATH=/tmp/baz:$PATH
remote: [tester::#MG5] [setup] PATH is now: /tmp/baz:/tmp/bar:/vcpkg:/cmake/bin:...
remote: [tester::#MG5] [setup] Available executables:
remote: [tester::#MG5] [setup] - my_exe
remote: [tester::#MG5] Running ./your_program.sh
remote: [your-program] $ type cat
remote: [your-program] cat is /usr/bin/cat
remote: [tester::#MG5] ✓ Received expected response
remote: [your-program] $ type cp
remote: [your-program] cp: not found
remote: [tester::#MG5] Output does not match expected value
remote: [tester::#MG5] Expected: "cp is /usr/bin/cp"
remote: [tester::#MG5] Received: "cp: not found"
remote: [your-program] $
remote: [tester::#MG5] Assertion failed.
remote: [tester::#MG5] Test failed
remote:
remote: Try our CLI to run tests faster without Git: https://codecrafters.io/cli
remote:
remote: View our article on debugging test failures: https://codecrafters.io/debug
remote:
To https://git.codecrafters.io/c65fb99ee6f91785
2327cac..5bbf61d master -> master
And here’s a snippet of my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#define TOKEN_BUFFER_SIZE 100
char **parse_input(char *input) {
int buf_size = TOKEN_BUFFER_SIZE, position = 0;
char **tokens = malloc(sizeof(char *) * buf_size);
char *token;
if (tokens == NULL) {
perror("allocation error\n");
exit(EXIT_FAILURE);
}
token = strtok(input, " ");
while (token != NULL) {
tokens[position] = token;
position++;
if (position >= buf_size) {
buf_size += TOKEN_BUFFER_SIZE;
tokens = realloc(tokens, sizeof(char *) * buf_size);
if (tokens == NULL) {
perror("allocation error\n");
exit(EXIT_FAILURE);
}
}
token = strtok(NULL, " ");
}
tokens[position] = NULL;
return tokens;
}
typedef struct Path {
char **paths;
int length;
} Path_t;
Path_t *parse_path(char *input) {
int buf_size = TOKEN_BUFFER_SIZE, position = 0;
char **paths = malloc(sizeof(char *) * buf_size);
char *path;
if (paths == NULL) {
perror("allocation error\n");
exit(EXIT_FAILURE);
}
path = strtok(input, ":");
while (path != NULL) {
paths[position] = path;
position++;
if (position >= buf_size) {
buf_size += TOKEN_BUFFER_SIZE;
paths = realloc(paths, sizeof(char *) * buf_size);
if (paths == NULL) {
perror("allocation error\n");
exit(EXIT_FAILURE);
}
}
path = strtok(NULL, ":");
}
paths[position] = NULL;
Path_t *p = malloc(sizeof(Path_t));
p->paths = paths;
p->length = position;
return p;
}
int launch_command(char **args) {
pid_t pid, wpid;
int status;
pid = fork();
if (pid == 0) {
if (execvp(args[0], args) == -1) {
fprintf(stderr, "%s: command not found\n", args[0]);
}
exit(EXIT_FAILURE);
} else if (pid < 0) {
perror("error\n");
} else {
do {
wpid = waitpid(pid, &status, WUNTRACED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
}
// Shell built in
const char *shell_builtin[] = {"cd", "echo", "type", "exit"};
int is_shell_builtin(char *cmd) {
for (int i = 0; i < 5; i++) {
if (strcmp(cmd, shell_builtin[i]) == 0) {
return 1;
}
}
return 0;
}
char *is_in_path(char *arg) {
char *PATH = getenv("PATH");
if (PATH == NULL) {
return 0;
}
Path_t *path = parse_path(PATH);
for (int i = 0; i < path->length; i++) {
size_t len = strlen(path->paths[i]) + strlen(arg) + 1;
char *file = malloc(len * sizeof(char *));
snprintf(file, len + 1, "%s/%s", path->paths[i], arg);
if (access(file, F_OK) == 0) {
return file;
}
}
return NULL;
}
// Build in declarations
int echo(char **args);
int sh_exit(char **args);
int type(char **args);
int cd(char **args);
int (*builtin_func[])(char **) = {&cd, &echo, &type, &sh_exit};
int cd(char **args) {
if (args[1] == NULL) {
fprintf(stderr, "sh: expected argument to cd\n");
} else {
if (chdir(args[1]) != 0) {
perror("error\n");
}
}
return 1;
}
int echo(char **args) {
if (args[1] == NULL) {
fprintf(stderr, "sh: expected argument to echo\n");
} else {
int i = 1;
while (args[i] != NULL) {
fprintf(stdout, "%s ", args[i]);
i++;
}
fprintf(stderr, "\n");
}
return 0;
}
int sh_exit(char **args) {
if (args[1] == NULL) {
exit(EXIT_SUCCESS);
} else {
exit(atoi(args[1]));
}
}
char *path;
int type(char **args) {
if (args[1] == NULL) {
fprintf(stderr, "sh: expected argument to type\n");
} else if (is_shell_builtin(args[1])) {
fprintf(stdout, "%s is a shell builtin\n", args[1]);
} else if ((path = is_in_path(args[1])) != NULL) {
fprintf(stdout, "%s is %s \n", args[1], path);
} else {
fprintf(stdout, "%s: not found\n", args[1]);
}
return 1;
}
int exce(char **args) {
if (strcmp(args[0], "exit") == 0) {
return sh_exit(args);
}
for (int i = 0; i < 5; i++) {
if (strcmp(args[0], shell_builtin[i]) == 0) {
return (*builtin_func[i])(args);
}
}
return launch_command(args);
}
int main(int argc, char *argv[]) {
int status;
while (true) {
// Flush after every printf
setbuf(stdout, NULL);
// Uncomment this block to pass the first stage
printf("$ ");
// Wait for user input
char input[100];
fgets(input, 100, stdin);
input[strcspn(input, "\r\n")] = 0;
char **tokens = parse_input(input);
if (tokens == NULL) {
return 1;
}
status = exce(tokens);
}
return 0;
}