Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Creating a Command Line Interface in Linux

Posted on 2009-04-07
9
Medium Priority
?
705 Views
Last Modified: 2012-06-27
I'm trying to create a simple command line interface on Linux, using the termios API.  Basically, the only features I really want are a simple prompt, line-based input, the ability to edit/delete characters on a line before hitting enter, and a "history" vector which can be accessed by hitting the up arrow key.  A simple call to fgets will not be adequate here, because the user would not be able to use the arrow keys to edit input.  

Unfortunately, there are very few tutorials on the workings of termios, and indeed it seems the termios API is quite in depth and sophisticated.

However, I seem to have a basic understanding of what needs to be done here.  Firstly, I would need to set the terminal to non-canonical mode in order to process each key press individually.  My question is, on non-canonical mode, how do I change the actual on-screen output that the user has typed, if the user decides to edit an input string while typing?

For example, suppose the user types 'abc' and then hits backspace.  In canonical mode, the OS would take care of the backspace and delete the 'c' from the screen.  In non-canonical mode, however, this is not the case.  So how can I replicate backspace functionality in non-canonical mode?  One way that occurred to me would be to simply output a linefeed character, and then reoutput the entire string minus the deleted character, as demonstrated in the code below.  Is this a standard practice, or is there a better way to do this?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
 
int main(int argc, char *argv[])
{
	struct termios orig, now;
	int i, rc;
	setvbuf(stdout, NULL, _IONBF ,0);
 
	tcgetattr(0, &orig);
	now = orig;
	now.c_lflag &= ~(ICANON | ECHO);
	now.c_iflag;
 
	now.c_cc[VMIN] = 1;
	now.c_cc[VTIME] = 2;
 
	tcsetattr(0, TCSANOW, &now);
 
	bool done = 0;
	char buf[256];
 
	char output[256];
	char* current = output;
	
	while (!done) 
	{
		char c = getchar();
		if (c == now.c_cc[VERASE]) {
			// Clear rest of the line
			putchar('\r');
			for (int i = 0; i < (current - output); ++i) putchar(' ');
 
			putchar('\r');
			--current;
			write(0, output, current - output);
		}
		else {
			putchar(c);
			if (current == output + (sizeof(output) - 1)) current = output; // reset buffer; 
			*current++ = c;
		}
	}
 
	tcsetattr(0, TCSANOW, &orig);
	return 0;
}

Open in new window

0
Comment
Question by:chsalvia
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
9 Comments
 
LVL 40

Accepted Solution

by:
mrjoltcola earned 668 total points
ID: 24093668
Rather than using termios directly, I have done this in years past with curses. I think curses will be easier. See also NCURSES

http://en.wikipedia.org/wiki/Curses_(programming_library)

http://www.linux.org/docs/ldp/howto/NCURSES-Programming-HOWTO/intro.html#WHATIS
0
 
LVL 35

Assisted Solution

by:Duncan Roe
Duncan Roe earned 668 total points
ID: 24113023
Yes you need to use ncurses to see function (and arrow) keys. Use it for input only - manage your own output.
0
 
LVL 3

Assisted Solution

by:Greg_Arnold
Greg_Arnold earned 664 total points
ID: 25998701
The easiest way to erase a character is to print a backspace, a space, then another backspace.

Something like this:
putchar('\b');
putchar(' ');
putchar('\b');

Open in new window

0
What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

 
LVL 40

Expert Comment

by:mrjoltcola
ID: 28281762
I see no problem with this question, the answers are valid. I recommend force accept, at least the answers regarding NCURSES to manage non-canonical mode.
0
 
LVL 3

Expert Comment

by:Greg_Arnold
ID: 28288929
I agree with mrjoltcola - there are valid answers.  Mostly his, maybe a little of mine.
0
 
LVL 40

Expert Comment

by:mrjoltcola
ID: 28903127
All these answers are appropriate and useful:
http:#24093668
http:#24113023
http:#25998701

Thanks,
-mjc
0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
The goal of this video is to provide viewers with basic examples to understand and use pointers in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.

722 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question