<aside>
<aside>
readlinechar *readline(const char *prompt);
readline is a library that gives us a nice interactive input line like in bash
Enter it returns the line as a char *Ctrl D it returns NULLTypical usage
while (1)
{
char *line = readline("minishell$ ");
if (!line) // the user has pressed Ctrl D
{
// print "exit" like bash
printf("exit\\n");
break;
}
if (*line) // line is not empty
add_history(line); // store in history (see below)
// pass `line` to the lexer/parser/executor
process_line(line);
free(line);
}
</aside>
<aside>
add_historyvoid add_history(const char *line);
Takes the given line and adds it to readline’s history list (list used by ↑ ↓ arrows)
<aside>
rl_clear_historyvoid rl_clear_history(void);
Belongs to the same library as readline and acts on its internal history as it resets the history
readline internally stores every line we add (with add_history)In Minishell, it’s used on exit to clean up memory (good practice but not mandatory)
void cleanup_shell(t_shell *sh)
{
// free our structures (env, ASTs, etc...)
rl_clear_history(); // clear readline’s internal history
}
</aside>
<aside>
rl_on_new_linevoid rl_on_new_line(void);
Used in combination with signals and redisplaying the prompt.
<aside>
Imagine this scenario
User is typing minishell$ ec and then hits Ctrl C
We want to cancel the current input, move to a new line and redisplay a fresh prompt
But readline still believes it’s in the middle of editing the old line
</aside>
rl_on_new_line tells readline to forget the old idea of where the cursor is and start a new empty line now. It doesn’t do anything by itself, it just updates readline’s internal state to be ready for a new line.
#include <readline/readline.h>
#include <readline/history.h>
void sigint_handler(int sig)
{
(void)sig;
write(1, "\\n", 1); // move to new line
rl_on_new_line(); // tell readline we are on a new line
rl_replace_line("", 0); // clear current input buffer (see below)
rl_redisplay(); // redisplay prompt (see below)
}
</aside>
<aside>
rl_replace_linevoid rl_replace_line(const char *text, int clear_undo);
Changes the current line that readline is editing
rl_replace_line("test", 0); tells it to forget what the user was typing. Now the line is exactly “test”It doesn’t print anything by itself!!! It changes the internal text that readline thinks is on the line
</aside>
<aside>
rl_redisplayvoid rl_redisplay(void);
Tells readline to redraw the prompt and the current line on the terminal
Readline knows
But when printing \\n or calling rl_replace_line the screen needs to be synchronized with readline’s internal buffer. And that’s why we use this function at the end
Without it the user wouldn’t see the new prompt and readline would be updated internally but that won’t be reflected on the screen
</aside>
</aside>
<aside>
<aside>
accessint access(const char *pathname, int mode);
Checks user’s permissions for a file
Returns 0 on success and -1 on error (and sets errno)
Examples for mode:
F_OK → file existsX_OK → executableR_OK → readableW_OK → writableTypical usage
if (access(full_path, X_OK) == 0)
// we found an executable
</aside>
<aside>
openint open(const char *pathname, int flags, mode_t mode);
Opens a file and returns a file descriptor
If it fails → returns -1 and sets errno
flags decides how I open
O_RDONLY read onlyO_WRONLY | O_CREAT | O_TRUNC write, create if missing, empty fileO_WRONLY | O_CREAT | O_APPEND append at end, keep contentmode is used only when creating a file (O_CREAT) for example 0644
</aside><aside>
readssize_t read(int fd, void *buf, size_t count);
Reads up to count bytes from fd into buf
Returns number of bytes read, 0 on EOF or -1 on error
</aside>
<aside>
closeint close(int fd);
Closes a file descriptor and frees the underlying kernel resource
</aside>
</aside>
<aside>
</aside>
<aside>
</aside>
<aside>
</aside>
<aside>
</aside>
<aside>
</aside>
<aside>
</aside>
<aside> 🤔
</aside>
<aside>
</aside>
<aside>
</aside>
<aside>
</aside>
<aside>
</aside>
<aside>
</aside>
<aside>
</aside>