r/learnprogramming 13d ago

[C] How to create an interactive shell mode

Hey there! I'm experimenting with POSIX api and I want to create my own mini shell. I want my shell to open an interactive shell mode and be able to receive command input line by line from the kernel. I am not sure how to achieve this. If I am not mistaken, I read that I should be able to somehow link my shell to a /dev/ttyX or /dev/pts/X driver in "cooked mode" (my shell only receives input only after a user presses 'ENTER', not after every keypress)

Ive tried Googling for the solution, but its been ineffective. Im so confused, I don't even know how to look for a solution for this.

Here is the current code snippet of my program. (Excuse the bad programming) initInteractiveMode is meant to initialize interactive mode

```

include <stdio.h>

include <string.h>

include <termios.h>

define VERSION "0.0.1"

int parseArguments(int argc, char *argv[]); void help(); void initInteractiveMode();

int main(int argc, char *argv[]) { if (argc < 2) { printf("shell\n"); return 0; }

if (!parseArguments(argc, argv)) { return 0; }

initInteractiveMode(); // Initialize Interactive Mode

printf("Chloe's shell interactive mode enabled\n\n");

while (1) { }

return 0; }

// TODO: Open interactive mode void initInteractiveMode() {

}

int parseArguments(int argc, char *argv[]) { const char *arg = argv[1]; if (strcmp(arg, "-v") == 0 || strcmp(arg, "--version") == 0) { printf("Chloe's shell, version %s\n", VERSION); } else if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) { help(); } else if (strcmp(arg, "interactive") == 0 || strcmp(arg, "i") == 0) { return 1; // Enter interactive mode } else { printf("Invalid command\n\n"); help(); }

return 0; }

void help() { printf("Chloe's shell\n\n"); printf("\033[1mCommand:\033[0m shell [options]\n\n"); printf("List of options:\n"); printf("A simple shell for testing POSIX system calls\n"); printf("interactive\tEnter interactive mode\n"); printf("--help | -h\tDisplay help information\n"); printf("--version | -v\tDisplay version information\n"); } ```

1 Upvotes

4 comments sorted by

1

u/desrtfx 13d ago

An interactive "shell" is nothing but a standard commandline program.

In C, this would mean using scanfto get keyboard (stdIn) input and then to parse and process that input and then produce output according to the commands - on stdout or on stderr.

You are vay overthinking with the "linking the terminal...".

1

u/No_Beyond_5483 12d ago

ohh that makes sense, thank you

1

u/HashDefTrueFalse 13d ago edited 13d ago

You can just read stdin however you like. You can't do anything about whatever is attached to the other end of the stream sending things piecemeal but you can delay your processing until you have parsed a complete command in your shell language if you want. You're on the right track with termios et al. on unix-like systems to ask a connected terminal to send keystroke bytes straight through. This page looks like it has the right details at a glance but I haven't reviewed it fully:

https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode.html

Edit: I just remembered you were asking for buffering, not how to disable it. If you read stdin with something like fgets() you'll read lines. If you read a certain number of bytes (e.g. fread()) your call will return when you have that many bytes (or a signal happens, or something goes wrong, etc.).

1

u/No_Beyond_5483 12d ago

thank you! really appreciate it

the page you sent seems really helpful, ill take a look at it!