Building a Simple Shell in C
shells are great, aren't they?
I am a Student, who finds beauty in simple things. I like to teach sometimes.
Ever thought about creating your own shell? It might seem tough, but with C programming, it's pretty simple. Let's break down a basic shell implementation step-by-step.
What This Code Does
This code is a basic shell program that lets users execute commands in a terminal. It reads user input, parses the command, and executes it. Here’s how it works:
Header Files and other ish
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MAX_COMMAND_LENGTH 1024
#define MAX_ARGS 64
#define MAX_ARG_LENGTH 256
#define DELIMETERS " \t\r\n\a"
Key Components
Prompt Display:
void print_prompt() { printf("sell-shell> "); }- This function displays a simple prompt ("sell-shell> ") to indicate that the shell is ready to accept commands.
Reading Commands:
void read_command(char *cmd) { fgets(cmd, MAX_COMMAND_LENGTH, stdin); }- This function reads the user input from the terminal and stores it in the
cmdarray.
- This function reads the user input from the terminal and stores it in the
Parsing Commands:
void parse_command(char *cmd, char **args) { int index = 0; char *token = strtok(cmd, DELIMETERS); while (token != NULL) { args[index++] = token; token = strtok(NULL, DELIMETERS); } args[index] = NULL; }- Here, the input command is split into separate arguments using
strtok. For example, if the user typesls -l,parse_commandwill split it into["ls", "-l", NULL].
- Here, the input command is split into separate arguments using
Background Execution:
int is_background(char **args) { int i = 0; while (args[i] != NULL) { if (strcmp(args[i], "&") == 0) { args[i] = NULL; return 1; } i++; } return 0; }- This function checks if the user wants to run the command in the background by looking for an
&at the end of the command. If found, it removes the&and returns1, otherwise0.
- This function checks if the user wants to run the command in the background by looking for an
Executing Commands:
void execute_command(char **args, int background) { pid_t pid = fork(); if (pid == 0) { if (execvp(args[0], args) == -1) { perror("simple-shell"); } exit(EXIT_FAILURE); } else if (pid < 0) { perror("simple-shell"); } else { if (!background) { int status; waitpid(pid, &status, 0); } } }- This function forks a new process to execute the command. If the command is not meant to run in the background, it waits for the command to complete.
Main Loop:
int main() { char cmd[MAX_COMMAND_LENGTH]; char *args[MAX_ARGS]; int background; while (1) { print_prompt(); read_command(cmd); if (strlen(cmd) == 1 && cmd[0] == '\n') { continue; } parse_command(cmd, args); background = is_background(args); execute_command(args, background); } return 0; }- The main loop keeps running (like a pig), displaying the prompt, reading user input, parsing it, checking for background execution, and finally executing the command.
Summary
This basic shell in C shows essential shell functions: showing a prompt, reading commands, parsing arguments, and executing them. It also lets you run commands in the background. If you're new to systems programming, this is a great way to learn how shells operate!