Building a Minimal Linux Shell Implementation

Project Overview

This project involves creating a minimal shell implementation in Linux that supports basic file and directory operations. The shell should provide an interactive command-line interface and execute common system commands.

Core Functionality Requirements

  • Display command prompt with current directory
  • Process user input commands
  • Parse command strings and agruments
  • Implement basic file operations: ls, touch, rm, mkdir, rmdir, cd, cp, mv, pwd, cat, chmod, ln
  • Log command execution with timestamps
  • Integrate all functions into a cohesive application
  • Package the final executable

Command Prompt Display

The shell displays the current working directory in a simplified format, showing only the last subdirectory component.

int display_prompt(void)
{
    char path_buffer[1024] = {0};
    char *path_ptr = NULL;
    
    getcwd(path_buffer, sizeof(path_buffer));
    path_ptr = path_buffer;
    
    while(*path_ptr != '\0') {
        path_ptr++;
    }
    
    while(*path_ptr != '/') {
        path_ptr--;
    }
    
    if(strcmp(path_buffer, "/") != 0) {
        path_ptr++;
    }
    
    printf("[user@linux:%s]$ ", path_ptr);
    return 0;
}

Input Processing

User input is captured and processed, with logging functionality to record commands with timestamps.

int get_input(char *command_buffer, int buffer_size)
{
    FILE *log_file = NULL;
    time_t current_time;
    struct tm *time_info = NULL;
    
    fgets(command_buffer, buffer_size, stdin);
    command_buffer[strlen(command_buffer)-1] = '\0';
    
    time(&current_time);
    time_info = localtime(&current_time);
    
    log_file = fopen("command_log.txt", "a+");
    fprintf(log_file, "[%04d-%02d-%02d %02d:%02d:%02d] ", 
            time_info->tm_year+1900, time_info->tm_mon+1, 
            time_info->tm_mday, time_info->tm_hour, 
            time_info->tm_min, time_info->tm_sec);
    fwrite(command_buffer, strlen(command_buffer), 1, log_file);
    fputc('\n', log_file);
    fclose(log_file);
    
    return 0;
}

Command Parsing and Execution

Input commands are parsed and routed to appropriate handler functions.

int parse_and_execute(char *input_cmd)
{
    if(!strcmp(input_cmd, "exit")) {
        return -1;
    }
    
    if(!strncmp(input_cmd, "cd", 2)) {
        char *token = strtok(input_cmd, " ");
        token = strtok(NULL, " ");
        change_directory(token);
    }
    else if(!strncmp(input_cmd, "cp", 2)) {
        char *source = NULL;
        char *destination = NULL;
        char *token = strtok(input_cmd, " ");
        source = strtok(NULL, " ");
        destination = strtok(NULL, " ");
        copy_file(source, destination);
    }
    else if(!strncmp(input_cmd, "chmod", 5)) {
        char *filename = NULL;
        char *mode_str = NULL;
        char *token = strtok(input_cmd, " ");
        filename = strtok(NULL, " ");
        mode_str = strtok(NULL, " ");
        change_permissions(filename, mode_str);
    }
    else if(!strcmp(input_cmd, "ls")) {
        list_directory();
    }
    else if(!strncmp(input_cmd, "ls -a", 5)) {
        list_all_files();
    }
    else if(!strncmp(input_cmd, "mkdir", 5)) {
        char *token = strtok(input_cmd, " ");
        token = strtok(NULL, " ");
        create_directory(token);
    }
    else if(!strcmp(input_cmd, "pwd")) {
        print_working_directory();
    }
    
    return 0;
}

Core Command Implementations

Directory Listing

int list_directory(void)
{
    char current_path[256] = {0};
    DIR *dir_stream = NULL;
    struct dirent *dir_entry = NULL;
    
    getcwd(current_path, sizeof(current_path));
    dir_stream = opendir(current_path);
    
    while((dir_entry = readdir(dir_stream)) != NULL) {
        if(dir_entry->d_name[0] == '.') {
            continue;
        }
        printf("%s  ", dir_entry->d_name);
    }
    printf("\n");
    closedir(dir_stream);
    return 0;
}

File Creation

int create_file(char *filename)
{
    FILE *file_handle = fopen(filename, "w");
    if(file_handle != NULL) {
        fclose(file_handle);
    }
    return 0;
}

File Copy

int copy_file(char *source_file, char *dest_file)
{
    FILE *source = fopen(source_file, "r");
    FILE *destination = fopen(dest_file, "w");
    int character;
    
    while((character = fgetc(source)) != EOF) {
        fputc(character, destination);
    }
    
    fclose(source);
    fclose(destination);
    return 0;
}

File Display

int display_file(char *filename)
{
    FILE *file_handle = fopen(filename, "r");
    int character;
    
    while((character = fgetc(file_handle)) != EOF) {
        fputc(character, stdout);
    }
    printf("\n");
    fclose(file_handle);
    return 0;
}

Permission Modification

int change_permissions(char *filename, char *mode_string)
{
    mode_t permission_mode = strtol(mode_string, NULL, 8);
    chmod(filename, permission_mode);
    return 0;
}

Header File Integration

#ifndef __SHELL_HEADER_H__
#define __SHELL_HEADER_H__

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <stdlib.h>
#include <string.h>

extern int list_directory(void);
extern int list_all_files(void);
extern int create_file(char *filename);
extern int remove_file(char *filename);
extern int create_directory(char *dirname);
extern int remove_directory(char *dirname);
extern int change_directory(char *path);
extern int copy_file(char *source, char *destination);
extern int move_file(char *source, char *destination);
extern int print_working_directory(void);
extern int change_permissions(char *filename, char *mode);
extern int display_file(char *filename);
extern int create_link(char *source, char *linkname);

#endif

Build Configuration

TARGET = minishell
SOURCES = main.c file_ops.c dir_ops.c utils.c

$(TARGET): $(SOURCES)
	gcc $^ -o $@

clean:
	rm -f $(TARGET)

Applicaiton Packaging

The final executable can be packaged using tar compression:

tar -czf minishell.tar.gz minishell

Tags: Linux Shell file-operations directory-management system-calls

Posted on Mon, 25 May 2026 18:46:02 +0000 by anothersystem