Skip to content

Instantly share code, notes, and snippets.

@achequisde
Last active August 26, 2022 19:40
Show Gist options
  • Save achequisde/47647f1dc11024b1957030c5639d5487 to your computer and use it in GitHub Desktop.
Save achequisde/47647f1dc11024b1957030c5639d5487 to your computer and use it in GitHub Desktop.
Simple shell in C that executes commands without macro expansion
// DONE: Check error when calling "ls -la --color=auto" or "cal -n 2" -- Changed `execv' with `execvp'
// TODO: Test with waitpid()
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "string.h"
char *buffer;
char *PS = "(zebes@arata)^ ";
int main() {
buffer = malloc(sizeof(char) * BUFFER_SIZE);
if (buffer == NULL) {
perror("Unable to allocate buffer.");
exit(EXIT_FAILURE);
}
size_t buffer_size = BUFFER_SIZE;
size_t length;
pid_t pid = 0;
int status;
char **args;
for (;;) {
printf("%s", PS);
getline(&buffer, &buffer_size, stdin);
// Remove newline at the end
buffer[strlen(buffer) - 1] = '\0';
if (strcmp(buffer, "exit") == 0) {
break;
}
length = split_whitespace(buffer, &args);
if (strcmp(args[0], "cd") == 0) {
chdir(args[1]);
continue;
}
pid = fork();
// PID == 0 -- Child process
// PID > 0 -- Parent process
if (pid == 0) {
execvp(args[0], args);
// If exec fails, the following two lines will be executed
printf("%s: %s: command not found\n", "arata", args[0]);
exit(EXIT_FAILURE);
} else if (pid > 0) {
wait(&status);
} else {
perror("In fork(): ");
}
for (int i = 0; i < length; i++) {
free(args[i]);
}
free(args);
}
free(buffer);
return EXIT_SUCCESS;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "string.h"
size_t split_whitespace(char *str, char ***array) {
size_t length = 1;
for (int i = 0, ch = str[i]; ch != '\0'; i++, ch = str[i])
if (isspace(ch)) length++;
char **result = malloc(sizeof(char*) * (length + 1));
if (result == NULL) {
perror("Could not allocate memory.");
exit(EXIT_FAILURE);
}
char *tokens = strtok(str, " ");
for (int i = 0; i < length; i++) {
result[i] = malloc(sizeof(char) * strlen(tokens));
strcpy(result[i], tokens);
tokens = strtok(NULL, " ");
}
result[length] = NULL;
*array = result;
return length;
}
#pragma once
#define BUFFER_SIZE 1024
size_t split_whitespace(char*, char***);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment