interpret arrow keys in raw mode (posix) - c

I'm trying to create a shell (nothing serious just messing around) and want to read the arrow keys in raw mode to avoid control characters being printed to the screen, and actually be able to use them to go back and edit a line before I hit enter. It's probably possible to do with termios but is there an easier way of doing this? Or is it perhaps easy to do with termios? It just seems like a rather large subject that has to be studied in full.
I'm reading in lines from stdin in a loop and call fork > execvp with an argument vector that I create from the input string.

It's probably possible to do with termios but is there an easier way
of doing this
By far the easiest approach would be to use the readline library which offers everything and more than what you're mentioning. It should be fairly easy to make your shell behave like a full-blown bash (line editing, command history) with relative ease.

Unless you actually want to do it yourself, I'd recommend you the GNU Readline Library which does these things for you.

Related

Scan all characters entered until see a tab char

I want to autocomplete on a command line application a but like in bash you can use tab key which will complete the command. But getchar() seems to wait until a newline char is received before it starts reading any characters.
scanf seems to work the same way.
Is there any way I can scan characters one at a time no matter if they are whitespace or control characters?
I want to be able to read char by char as entered building up a command and then as soon as tab char received I will attempt to lookup how to complete and print full command in my application.
Don't reinvent the wheel.
Use what other projects use to build command lines: Libraries that implement that job for you.
Many CLI prompts depend on GNU readline, which I think is fine, if a bit cluttered and heavy. Also, it's GPL, so depends on whether you like that or not.
I'd look into linenoise. It's very lightweight, and if you decide you really want to implement user interface yourself rather than including one or two files, OK, do that, but look at the rather concise reference implementation that seems to be. Caveat: haven't used it myself, so far. The API is pretty simple, though, as can be seen in their example.
A popular alternative is libedit/editline.
You need the GNU Readline Library. Use the rl_bind_key() function to add a filename-completion processing function whenever the users presses a key ('\t', in your case).
You are in for a world of hurt if you try to roll your own readline style function.
(If you are on Windows.)

How to implement previous-command-scroll in a standalone shell program?

For a class project we have to implement a basic Linux shell. As it stands now I have everything working to fully implement basic functionality except for the "UP" key previous command scrolling feature.
How might something like this be implemented? I realize it may be as simple as retaining an array of char* to the input strings, but how do we capture "UP" key button presses?
Once we have the above implemented, how can you write to stdout without making it permanent? That is, when you press "UP" again then it erases what was previously written with another command.
A practical way to implement the up key would be to use GNU readline library (and its history sub-library). BTW, some shells actually do use GNU readline (it is under GPL license). And you'll get line edition also. And you could implement completion with the tab key, etc.
There are other ways, like using ncurses or termcap etc... Or emitting ANSI escape codes on a raw terminal. See also the tty demystified & termios(3)...
BTW, most Linux shells are free software, so you could study their source code.
If you are using non-buffered character-by-character input directly from STDIN (which means, among other things, control characters such as CTRL+C are not handled automatically), then you will be reading byte-by-byte. Arrow keys, unlike ASCII symbols, put multiple bytes on STDIN because they are excape sequences. These bytes differ from system to system. The easiest way to determine the escape sequence on your system is to execute the cat command with no arguments, then hit the arrow keys. Something like ^[[A will be displayed, you will need to convert that sequence from ASCII to hex bytes.
Once you've done that, you can read the bytes one at a time with get_char(), just like you're probably already doing in your input function anyway.

What are some best practices for file I/O in C?

I'm writing a fairly basic program for personal use but I really want to make sure I use good practices, especially if I decide to make it more robust later on or something.
For all intents and purposes, the program accepts some input files as arguments, opens them using fopen() read from the files, does stuff with that information, and then saves the output as a few different files in a subfolder. eg, if the program is in ~/program then the output files are saved in ~/program/csv/
I just output directly to the files, for example output = fopen("./csv/output.csv", "w");, print to it with fprintf(output,"%f,%f", data1, data2); in a loop, and then close with fclose(output); and I just feel like that is bad practice.
Should I be saving it in a temp directory wile it's being written to and then moving it when it's finished? Should I be using more advanced file i/o libraries? Am I just completely overthinking this?
Best practices in my eyes:
Check every call to fopen, printf, puts, fprintf, fclose etc. for errors
use getchar if you must, fread if you can
use putchar if you must, fwrite if you can
avoid arbitrary limits on input line length (might require malloc/realloc)
know when you need to open output files in binary mode
use Standard C, forget conio.h :-)
newlines belong at the end of a line, not at the beginning of some text, i.e. it is printf ("hello, world\n"); and not "\nHello, world" like those mislead by the Mighty William H. often write to cope with the sillyness of their command shell. Outputting newlines first breaks line buffered I/O.
if you need more than 7bit ASCII, chose Unicode (the most common encoding is UTF-8 which is ASCII compatible). It's the last encoding you'll ever need to learn. Stay away from codepages and ISO-8859-*.
Am I just completely overthinking this?
You are. If the task's simple, don't make a complicated solution on purpose just because it feels "more professional". While you're a beginner, focus on code readability, it will facilitate your and others' lives.
It's fine. I/O is fully buffered by default with stdio file functions, so you won't be writing to the file with every single call of fprintf. In fact, in many cases, nothing will be written to it until you call fclose.
It's good practice to check the return of fopen, to close your files when finished, etc. Let the OS and the compiler do their job in making the rest efficient, for simple programs like this.
If no other program is checking for the presence of ~/program/csv/output.csv for further processing, then what you're doing is just fine.
Otherwise you can consider writing to a FILE * obtained by a call to tmpfile in stdio.h or some similar library call, and when finished copy the file to the final destination. You could also put down a lock file output.csv.lck and remove that when you're done, but that depends on you being able to modify the other program's behaviour.
You can make your own cat, cp, mv programs for practice.

Backspace character does not move the cursor back to the previous line in terminal

I am using Ubuntu 12.10, while making a program i observed that the backspace character ('\b') can move the cursor one position back on the same line inside the terminal, but didn't worked when i wanted it to move back to the previous line?
How can i achieve this using C language?
This is really a question about the behavior of your terminal, not C. I don't know any easy way to "backspace to the previous line" aside from "move up one line" followed by "move to end of line" or similar. On Linux, man console_codes will give you good documentation of standard terminal escapes. All relevant terminals are sufficiently similar that, if you just want to do cursor positioning and not fancy color stuff, you should just be able to hard-code the codes.
As Peter said, you could also use a higher-level library like ncurses if you prefer. Whether this makes sense depends a lot on the scope of what you're doing.
the normal terminal is line-orientated, so you have to take a more complex path, like using the curses-library and do the semantics yourself

Standard (or convenient) method to read and write tabular data to a text file in c

This might sound rather awkward, but I want to ask if there is a commonly practiced way of storing tabular data in a text file to be read and written in C.
Like in python you can load a full text file nto an array by f.readlines then go through all the lines and split each line by a specific character or sequence of characters (delimiter).
How do you approach this problem in C?
Pretty much the same way you would in any other language. Pick a field separator (I.E., tab character), open the text file for reading and parse each line.
Of course, in C it will never be as easy as it is in Python, but approaches are similar.
Whoa. I am a bit baffled by the other answers which make me feel like I'm on Mainframes.stackexchange.com instead of stackoverflow.com
Why don't you pick a modern data format like JSON or XML and follow best practices for the data format of your choice?
If you want a good JSON reader/writer for C, I've used Jansson, and it's very easy and fast.
If you want a good XML reader/writer for C, I've used miniXML and it's also easy and fast. Also has SAX *and * DOM support depending on how you want to read in the XML.
Obviously there are a wealth of other libraries available as well.
Please don't give the next guy to come along and support your program some wacky custom file format to deal with.
I find getline() and strtok() to be quite convenient (getline was a gnu extension, standardized in POSIX.1-2008).
There's a handful of mechanisms, but there's a reason why scripting languages have become so popular over the least twenty years -- some of the tasks that seem simple in scripting languages are ponderous in C.
You could use flex and bison to write a parser for your tables. This really only works if the format is very well defined and "static". They're amazing tools that can do more than you might suspect, but it is very heavy machinery for what could be done simply with a split() in a scripting language.
You could read individual fields using getdelim(3). However, this was only standardized with POSIX.1-2008, so this is far from ubiquitous. (Every Linux machine with glibc should have them.)
You could read lines with fgets(3) and discover the split locations using strchr(3).
You could read lines with fgets(3) and use strtok(3) to tokenize strings.
You can use scanf(3) to perform input and scanning in one go; it seems from the questions here that scanf(3) is difficult to use correctly.
You could use character-at-a-time parsing approaches: read characters using getc(3), inspect it, do something with it, iterate until no more characters.

Resources