<aside>

➤ Readline

<aside>

readline

char *readline(const char *prompt);

readline is a library that gives us a nice interactive input line like in bash

Typical 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_history

void add_history(const char *line);

Takes the given line and adds it to readline’s history list (list used by ↑ ↓ arrows)

<aside>

rl_clear_history

void rl_clear_history(void);

Belongs to the same library as readline and acts on its internal history as it resets the 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_line

void 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_line

void rl_replace_line(const char *text, int clear_undo);

Changes the current line that readline is editing

It doesn’t print anything by itself!!! It changes the internal text that readline thinks is on the line

</aside>

<aside>

rl_redisplay

void 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>

➤ Files & I/O

<aside>

access

int 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:

Typical usage

if (access(full_path, X_OK) == 0)
// we found an executable

</aside>

<aside>

open

int 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

<aside>

read

ssize_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>

close

int 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>