Switched from GNU Readline to custom Readline function

to make arsh more compatible with other Unix-Like systems

- Fixed small memory leak
This commit is contained in:
Aleksandr Lebedev 2026-02-19 16:13:34 +01:00
parent b5b02da752
commit e96ae4b4a2
2 changed files with 37 additions and 6 deletions

View file

@ -6,8 +6,9 @@ Simple shell for Unix-like systems written in C, that has a funny name (for germ
- ~cd~ builtin command - ~cd~ builtin command
- ~exit~ builtin command - ~exit~ builtin command
- ~CTRL+C~ stops running command - ~CTRL+C~ stops running command
- Custom ~readline~ function
* Build * Build
To build it, you need ~readline~ library. Then use To build it, you don't need any external dependencies. Example with ~gcc~:
#+begin_src shell #+begin_src shell
gcc main.c -O3 -lreadline -o arsh gcc main.c -O3 -o arsh
#+end_src #+end_src

38
main.c
View file

@ -3,7 +3,6 @@
#include <unistd.h> #include <unistd.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <readline/readline.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <signal.h> #include <signal.h>
#include <setjmp.h> #include <setjmp.h>
@ -20,6 +19,31 @@ void sigint_handler(int signo)
} }
siglongjmp(restart_jmp_buf, restart_value); siglongjmp(restart_jmp_buf, restart_value);
} }
static constexpr size_t max_line = 1024;
static char string_buffer[max_line];
char* readline(char* print)
{
if(print)
{
printf("%s", print);
}
if((fgets(string_buffer, max_line, stdin) == NULL) && ferror(stdin))
{
perror("fgets error");
}
size_t length = strlen(string_buffer);
if(length == 0)
{
return NULL;
}
//Remove trailing \n
if (length > 0 && string_buffer[length - 1] == '\n')
{
string_buffer[length - 1] = '\0';
}
return string_buffer;
}
char** split_input(char* input) char** split_input(char* input)
{ {
@ -71,9 +95,14 @@ int main()
char* input = readline("arsh> "); char* input = readline("arsh> ");
if(input == NULL) //CTRL + D if(input == NULL) //CTRL + D
{ {
continue; printf("\nexit\n");
exit(0);
} }
char** command = split_input(input); char** command = split_input(input);
if(command[0] == NULL)
{
goto cleanup;
}
if(strcmp(command[0], "cd") == 0) if(strcmp(command[0], "cd") == 0)
{ {
@ -82,7 +111,7 @@ int main()
perror(command[1]); perror(command[1]);
} }
continue; //skip fork() goto cleanup; //skip fork()
} }
if(strcmp(command[0], "exit") == 0) if(strcmp(command[0], "exit") == 0)
{ {
@ -111,7 +140,8 @@ int main()
waitpid(child_pid, &stat_loc, WUNTRACED); waitpid(child_pid, &stat_loc, WUNTRACED);
} }
free(input); cleanup:
free(command); free(command);
} }
} }