Skip to content

cumisar/SuperShell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Unix Shell Implementation

This project is a custom Unix shell implementation, designed to mimic the behavior of a standard shell with support for various command-line operations, including pipelines, input/output redirection, background execution, and conditional command execution.

Features

  • Command Execution: Supports execution of simple commands, pipelines, and conditional commands (&&, ||).
  • Input/Output Redirection: Supports input redirection (<), output redirection (>), and appending output (>>).
  • Background Execution: Commands can be executed in the background using the & operator.
  • Command Grouping: Commands can be grouped using parentheses () to execute them in a subshell.
  • Pipeline Support: Supports command pipelines (|) where the output of one command is passed as input to the next.
  • Built-in cd Command: Includes a built-in cd command for changing directories.
  • Error Handling: Properly handles errors and ensures no zombie processes are left after command execution.

Building the Project

The project is built using a Makefile.

Assembling and executing:

make run

Usage

Once the shell is running, you can enter commands just like you would in a standard Unix shell. Below are some examples of supported operations:

Simple Command Execution

  • Bash
 ls -l
  • Pipeline
 ls | grep .txt
  • Input Redirection
 wc -l < input.txt
  • Output Redirection
 ls > output.txt
  • Appending Output
 echo "Hello, World!" >> output.txt
  • Background Execution
 sleep 10 &
  • Conditional Execution
 ls && echo "Command succeeded"
 ls || echo "Command failed"
  • Command Grouping with Parentheses
 (cd /tmp; ls)
  • Built-in cd Command
 cd /path/to/directory

Project Structure

The project is implemented using an Abstract Syntax Tree (AST) to parse and execute commands. The AST is a tree representation of the syntactic structure of the command line input, allowing for efficient parsing and execution of complex commands, including pipelines, redirections, and conditional operations.

Here’s an overview of the key files and their roles in the project:

  • ast.c and ast.h: These files define the structure and functions for building and manipulating the AST. The AST nodes represent different types of commands (e.g., simple commands, pipelines, redirections, etc.), and the tree is constructed during the parsing phase.

  • exec.c and exec.h: These files contain the logic for traversing and executing the AST. The execution engine walks the AST and performs the appropriate actions for each node, such as executing commands, handling pipelines, and managing input/output redirections.

  • lexer.c and lexer.h: The lexer is responsible for tokenizing the input command line. It breaks the input string into tokens (e.g., command names, operators, filenames) that are used by the parser to build the AST.

  • parse.c and parse.h: The parser takes the tokens generated by the lexer and constructs the AST. It handles the grammar of the shell, including command grouping, pipelines, and conditional execution.

  • nodes.h: This file defines the structures for the AST nodes. Each node type corresponds to a specific command or operation (e.g., simple command, pipeline, redirection).

  • shell_main.c: The main entry point of the shell. It initializes the shell, reads input from the user, and coordinates the lexing, parsing, and execution phases.

  • tokens.h: Defines the token types used by the lexer and parser. Tokens represent the basic building blocks of the command line input (e.g., command names, operators, filenames).

AST Implementation Details

The AST is central to the shell's operation. Here’s how it works:

  1. Lexing: The input command line is tokenized by the lexer, which produces a stream of tokens.
  2. Parsing: The parser reads the tokens and constructs the AST based on the shell's grammar. For example:
    • A simple command like ls -l becomes a single AST node.
    • A pipeline like ls | grep .txt becomes a parent node with two child nodes representing the commands ls and grep.
    • Redirections like ls > output.txt are represented as nodes with additional information about the input/output files.
  3. Execution: The executor traverses the AST and executes the commands. For pipelines, it sets up the necessary pipes and forks processes to handle each command in the pipeline. For redirections, it manages file descriptors to redirect input/output.

This AST-based approach ensures that the shell can handle complex command structures efficiently and provides a clear separation between parsing and execution.


Thanks for checking :)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors