This article is part <2> of the article "writing a Shell" series. In the previous article, we have completed the first step of our shell: the shell prompt. In this article, we begin to enable our Shell to start reading commands, and to do simple participle, separating commands from parameters.
Read command 0x00 use of ReadLine Library
The library we use to implement the Read command is readline
that we can use the fgets()
method to achieve the goal, but if we use the fgets()
shell when we enter the wrong command cannot be revoked by SPACEBAR, because fgets()
it is read by character.
0x01 Install ReadLine Library
sudo apt-get install libreadline-dev
0x02 using the ReadLine library
If we use the library in our program, we need to link to the code when we compile it.libreadline
Cases:
gcc -o test test.o -I /usr/include -lreadline
Processing command 0x00 Implementation ideas
For a command
cmd para1 para2 […… paraN]
We want it to be identified as:
Command: cmd
Parameter 0: cmd
Parameter 1: para1
Parameter 2: para2
......
Parameter n:paraN
In fact, the idea is very simple:
We need a command
pointer to store the command, an array to store the command.
It takes two pointers to move along our entire instruction to get every command or parameter.
At the outset:
Two pointers *start
, *end
all pointing to the beginning of an instruction
If *start
, *end
pointing to a space, automatically moves backwards
Define a counter count
, and the *end
pointer starts to move backwards until it touches a space or line break or terminator
If count
0, indicates that the command is currently being processed, a temporary pointer is set, *p
*end
*start
and it is moved along, assigned to *command
and parameter[0]
, count
+ 2.
If the *end
line break or Terminator is stopped, it is assigned, *end
*start
and then *end
continues to move backwards as described above until a space is encountered, which is assigned *start
parameters[count-1]
, count
+ 1.
Repeat until the *end
Terminator \0
or line break is encountered\n
0X01 Implementation Code
#include "lshell.h"#include <readline/readline.h>#include <readline/history.h>intRead_command (Char**command,Char**parameters,Char*prompt) { Free(buffer); Buffer = ReadLine (prompt);if(Feof (stdin)) {printf("\ n");Exit(0); }if(buffer[0] ==' + ') {return-1; }intCount =0;Char*start, *end;intisfinished =0; Start = end = buffer; while(isfinished = =0) { while(*start = ="'&& *end = ="') || (*start = =' \ t '&& *end = =' \ t ')) {start++; end++; }if(*end = =' + '|| *end = =' \ n ') {if(Count = =0) {return-1; } Break; } while(*end! =' + '&& *end! =' \ n '&& *end! ="') {end++; }if(Count = =0){Char*p = end; *command = start; while(P! = Start && *p! ='/') {p--; }if(*p = ='/') {p++; } parameters[0] = p; Count + =2;#ifdef DEBUG printf("\ncommand:%s\n", *command);#endif //DEBUG }Else if(Count <= Max_args) {parameters[count-1] = start; count++; }Else{ Break; }if(*end =' + '|| *end = =' \ n ') {*end =' + '; isfinished =1; }Else{*end =' + '; end++; start = end; }} parameters[count-1] = NULL;#ifdef DEBUG printf("Input analysis:\n");printf("command:[%s]\ncommand:[%s]\nparameters:\n", *command,parameters[0]);intI for(i=0; i<count-1; i++)printf("[%s]\n], Parameters[i]);#endif returnCount;}
Full code See:https://github.com/luoyhang003/linux_kernel_expriment/tree/master/exp2
This article's copyright belongs to the author Luo voyage All, uses Attribution-noncommercial 3.0 License. Any person may reproduce, share, but not be used without permission for commercial purposes; reprint please specify the source. Thanks for cooperating!
Part 2: Enable the Shell to read commands