Compare commits

...

3 commits

Author SHA1 Message Date
60b9863f08 Deleted README.md 2026-02-19 14:22:37 +01:00
2825aa5d88 Added README 2026-02-19 14:22:07 +01:00
7bbfb75566 basic shell 2026-02-19 14:22:07 +01:00
3 changed files with 129 additions and 3 deletions

View file

@ -1,3 +0,0 @@
# arsh
Simple shell for Unix-like systems written in C

12
README.org Normal file
View file

@ -0,0 +1,12 @@
#+title: arsh - ARchaic SHell
#+options: toc:nil
Simple shell for Unix-like systems written in C, that has a funny name (for germans).
* Features
- Can run one command at a given time (no | , &&, ||, functions, etc)
- ~cd~ builtin command
- ~exit~ builtin command
* Build
To build it, you need ~readline~ library. Then use
#+begin_src shell
gcc main.c -O3 -lreadline -o arsh
#+end_src

117
main.c Normal file
View file

@ -0,0 +1,117 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <readline/readline.h>
#include <sys/wait.h>
#include <signal.h>
#include <setjmp.h>
static sigjmp_buf restart_jmp_buf;
static const int restart_value = 69;
static volatile sig_atomic_t jump_active = 0;
void sigint_handler(int signo)
{
if(!jump_active)
{
return;
}
siglongjmp(restart_jmp_buf, restart_value);
}
char** split_input(char* input)
{
const size_t alloc_size = ((strlen(input) + 1) / 2) + 1;
char** command = malloc(alloc_size * sizeof(char*));
if (command == NULL)
{
perror("malloc failed");
exit(1);
}
const char* separator = " ";
char* parsed;
uint32_t index = 0;
parsed = strtok(input, separator);
while (parsed != NULL)
{
command[index] = parsed;
index++;
parsed = strtok(NULL, separator);
}
command[index] = NULL;
return command;
}
int cd(char* path)
{
return chdir(path);
}
int main()
{
struct sigaction s;
s.sa_handler = sigint_handler;
sigemptyset(&s.sa_mask);
s.sa_flags = SA_RESTART;
struct sigaction s_old;
sigaction(SIGINT, &s, &s_old);
int stat_loc;
if(sigsetjmp(restart_jmp_buf, 1) == restart_value)
{
printf("\n");
}
jump_active = 1;
while(true)
{
char* input = readline("arsh> ");
if(input == NULL) //CTRL + D
{
continue;
}
char** command = split_input(input);
if(strcmp(command[0], "cd") == 0)
{
if (cd(command[1]) < 0)
{
perror(command[1]);
}
continue; //skip fork()
}
if(strcmp(command[0], "exit") == 0)
{
int32_t status_code = command[1] != NULL ? atoi(command[1]) : 0;
exit(status_code);
}
pid_t child_pid = fork();
if (child_pid < 0)
{
perror("Fork failed");
exit(1);
}
if (child_pid == 0)
{
sigaction(SIGINT, &s_old, NULL);
//never returns if call is successful
if(execvp(command[0], command) < 0)
{
perror(command[0]);
exit(1);
}
}
else
{
waitpid(child_pid, &stat_loc, WUNTRACED);
}
free(input);
free(command);
}
}