Skip to main content

Command Palette

Search for a command to run...

Building a Simple Shell in C

shells are great, aren't they?

Updated
3 min read
A

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

  1. 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.
  2. 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 cmd array.
  3. 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 types ls -l, parse_command will split it into ["ls", "-l", NULL].
  4. 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 returns 1, otherwise 0.
  5. 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.
  6. 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;
     }
    
    1. 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!

More from this blog

Aman Pathak

58 posts

Things I would speak if the person in front of me is me