cmdlinelib.c now calls system() rather than doing its own tokenisation
[people/mcb30/gpxe.git] / src / commandline / cmdlinelib.c
1 #include "cmdlinelib.h"
2 #include <gpxe/command.h>
3 #include <gpxe/tables.h>
4 #include <console.h>
5 #include <malloc.h>
6 #include <string.h>
7 #include <stdarg.h>
8
9 static struct command cmd_start[0] __table_start ( commands );
10 static struct command cmd_end[0] __table_end ( commands );
11
12 void cmdl_setgetchar(cmd_line* cmd, cmdl_getchar_t in)
13 {
14         cmd->getchar = in;
15 }
16
17 void cmdl_setputchar(cmd_line* cmd, cmdl_putchar_t in)
18 {
19         cmd->putchar = in;
20 }
21
22 void cmdl_setprintf(cmd_line* cmd, cmdl_printf_t in)
23 {
24         cmd->printf = in;
25 }
26       
27 int cmdl_getexit(cmd_line* cmd)
28 {
29         if(cmdl_check(cmd) && !cmd->exit){
30                 return 0;
31         }else{
32                 return 1;
33         }
34
35 }
36
37 void cmdl_setexit(cmd_line* cmd, int exit)
38 {
39         if(cmdl_check(cmd)){
40                 cmd->exit = exit;
41         }
42 }
43
44 int cmdl_printf(cmd_line* cmd, const char *format, ...)
45 {
46         int ret;
47         char string[CMDL_BUFFER_SIZE];
48         va_list ap;
49
50         va_start(ap, format);
51         ret = vsprintf(string, format, ap);
52         cmdl_addstr(cmd, string);
53         va_end(ap);
54         return ret;
55 }
56
57 void cmdl_addstr(cmd_line* cmd, char* str)
58 {
59         unsigned int i;
60         for(i = 0; i < strlen(str); i++){
61                 cmdl_addchar(cmd, str[i]);
62         }
63 }
64
65 void cmdl_setpropmt(cmd_line* cmd, char prompt[CMDL_PROMPT_SIZE])
66 {
67         if(cmdl_check(cmd) && prompt != NULL){
68                 strncat(cmd->prompt, prompt, CMDL_PROMPT_SIZE);
69         }
70 }
71
72 char *cmdl_getprompt(cmd_line* cmd)
73 {
74         if(cmdl_check(cmd)){
75                 return cmd->prompt;
76         }else{
77                 return "";
78         }
79 }
80
81 char* cmdl_getbuffer(cmd_line* cmd){
82         if(cmdl_check(cmd)){
83                 return cmd->buffer;
84         }else{
85                 return "";
86         }
87 }
88
89 void cmdl_enterloop(cmd_line* cmd)
90 {
91         while(!cmdl_getexit(cmd)){
92                 if(cmd->refresh){
93                         cmd->printf("%s %s", cmd->prompt, cmd->buffer);
94                         cmd->refresh = 0;
95                 }
96 //              cmd->printf("Got %d\n", cmd->getchar());
97                 cmdl_parsechar(cmd, cmd->getchar());
98         }
99 }
100
101 void cmdl_addreplace(cmd_line* cmd, char in)
102 {
103         if(cmd->cursor < CMDL_BUFFER_SIZE - 2){
104                 cmd->buffer[cmd->cursor] = in;
105                 cmd->cursor++;
106                 cmd->putchar((int)in);
107         }
108 }
109
110 void cmdl_addinsert(cmd_line* cmd, char in)
111 {
112         int i;
113         int to;
114         if(cmd->cursor < CMDL_BUFFER_SIZE - 2 && cmd->cursor >= 0){
115                 if(strlen(cmd->buffer) < CMDL_BUFFER_SIZE - 2){
116                         to = strlen(cmd->buffer);
117                 }else{
118                         to = CMDL_BUFFER_SIZE - 2;
119                 }
120                         for(i=to; i > cmd->cursor; i--){
121                                 cmd->buffer[i] = cmd->buffer[i-1];
122                         }
123                         cmd->buffer[cmd->cursor] = in;
124
125                         for(i=cmd->cursor; i < to; i++){
126                                 cmd->putchar(cmd->buffer[i]);
127                         }
128                         
129                         for(i=cmd->cursor; i < to - 1; i++){
130                                 cmd->putchar(CMDLK_BS);
131                         }
132                         cmd->cursor++;
133                         //cmdl_movecursor(cmd, CMDL_RIGHT);
134         }
135 }
136
137 void cmdl_addchar(cmd_line* cmd, char in){
138         if(cmd->insert){
139                 cmdl_addinsert(cmd, in);
140         }else{
141                 cmdl_addreplace(cmd, in);
142         }
143 }
144
145 void cmdl_parsechar(cmd_line* cmd, char in)
146 {
147         if(cmdl_check(cmd)){
148                 if(in >= 32){
149                         cmdl_addchar(cmd, in);
150                 }else{
151                         switch(in){
152                                 case CMDLK_BS:
153                                         if(cmdl_movecursor(cmd, CMDL_LEFT)){
154                                                 cmdl_del(cmd);
155                                         }
156                                         break;
157
158                                 case CMDLK_RETURN:
159                                         cmd->putchar('\n');
160                                         system ( cmd->buffer );
161                                         cmdl_clearbuffer(cmd);
162                                         cmd->refresh = 1;
163                                         break;
164
165                                 case CMDLK_BW:
166                                         cmdl_movecursor(cmd, CMDL_LEFT);
167                                         break;
168
169                                 case CMDLK_FW:
170                                         //cmdl_movecursor(cmd, CMDL_RIGHT);
171                                         break;
172                                 
173                                 case CMDLK_TAB:
174                                         cmdl_tabcomplete(cmd);
175                                         break;
176
177                         }
178                 }
179         }
180 }
181
182 void cmdl_tabcomplete(cmd_line *cmd)
183 {
184         struct command *ccmd;
185         int count=0;
186         char* result[CMDL_MAX_TAB_COMPLETE_RESULT];
187
188         for ( ccmd = cmd_start ; ccmd < cmd_end ; ccmd++ ) {
189                 if(!strncmp(ccmd->name, cmd->buffer, strlen(cmd->buffer))){
190                         if(count <= CMDL_MAX_TAB_COMPLETE_RESULT){
191                                 result[count++] = (char*)(ccmd->name);
192                         }
193                 }
194         }
195         
196
197         if( count == 1 ){
198                 cmdl_addstr(cmd, (char*)(result[0] + strlen(cmd->buffer)));
199                 cmd->tabstate = 0;
200                 cmdl_addchar(cmd, ' ');
201         } else if( count > 1 ) {
202                 int i, i2, minlen=CMDL_BUFFER_SIZE, same=1;
203                 char last;
204
205                 for(i = 0; i < count; i ++) {
206                         if(minlen > (int)strlen( result[i] ) ){
207                                 minlen = strlen(result[i]);
208                         }
209                 
210                 }
211                 if((int)strlen(cmd->buffer) < minlen){
212                         for(i = strlen(cmd->buffer); i < minlen; i++){
213                                 last = result[0][i];
214                                 for(i2 = 1; i2 < count; i2 ++) {
215                                         if(result[i2][i] != last){
216                                                 same = 0;
217                                                 break;
218                                         }
219                                 }
220                                 if(same){
221                                         cmdl_addchar(cmd, last);
222                                 }
223                                 
224                         }
225                 }
226                 cmd->tabstate++;
227         }
228         
229         if(count > 1 && cmd->tabstate > 1){
230                 int i;
231                 cmd->tabstate = 0;
232                 cmd->refresh = 1;
233                 cmd->putchar('\n');
234                 for(i = 0; i < count; i ++){
235                         cmd->printf("%s\t", result[i]);
236                 }
237                 cmd->putchar('\n');
238         }
239
240         
241
242 }
243
244 void cmdl_clearbuffer(cmd_line* cmd)
245 {
246         if(cmdl_check(cmd)){
247                 int i;
248                 cmd->cursor = 0;
249                 for(i=0; i < CMDL_BUFFER_SIZE; i++){
250                         cmd->buffer[i] = 0;
251                 }
252         }
253 }
254
255 int cmdl_movecursor(cmd_line* cmd, int direction)
256 {
257         if(cmdl_check(cmd)){
258                 switch(direction){
259                         case CMDL_LEFT:
260                                 if(cmd->cursor > 0){
261                                         cmd->cursor--;
262                                         cmd->putchar(CMDLK_BS);
263                                 }else{
264                                         return 0;
265                                 }
266                                 break;
267                         case CMDL_RIGHT:
268                                 if(cmd->cursor < CMDL_BUFFER_SIZE - 2){
269                                         cmd->cursor++;
270                                         cmd->putchar(' ');
271                                 }else{
272                                         return 0;
273                                 }
274                                 break;
275                 }
276         }
277         return 1;
278 }
279
280 void cmdl_del(cmd_line* cmd)
281 {
282         if(cmdl_check(cmd) && cmd->cursor < CMDL_BUFFER_SIZE - 2 && cmd->cursor >= 0){
283                 int i;
284                 for(i = cmd->cursor; i < (int)strlen(cmd->buffer); i++){
285                         cmd->buffer[i] = cmd->buffer[i + 1];
286                         if(!cmd->buffer[i]){
287                                 cmd->putchar(' ');
288                         }else{
289                                 cmd->putchar(cmd->buffer[i]);
290                         }
291                 }
292                 for(i = cmd->cursor; i < (int)strlen(cmd->buffer) + 1; i++){
293                         cmd->putchar(CMDLK_BS);
294                 }
295         }
296 }
297
298
299 int cmdl_check(cmd_line* cmd)
300 {
301         if(
302                 cmd != NULL && 
303                 cmd->buffer != NULL &&
304                 cmd->prompt != NULL &&
305                 cmd->cursor >= 0 && 
306                 cmd->cursor < CMDL_BUFFER_SIZE - 1 &&
307                 cmd->buffer[CMDL_BUFFER_SIZE - 1] == 0 &&
308                 cmd->prompt[CMDL_PROMPT_SIZE - 1] == 0
309         ){
310                 return 1;
311         }else{
312                 return 0;
313         }
314 }
315
316 cmd_line* cmdl_create()
317 {
318         cmd_line* this;
319         int i;
320         
321         /* Initiate the command line */
322         
323         this = (cmd_line*)malloc(sizeof(cmd_line));
324         
325         if(this == NULL){
326                 return NULL;
327         }
328         
329
330         /* Allocate output buffer */
331         
332         /*this->output = (char*)malloc(CMDL_OUTPUT_SIZE);
333         if(this->output == NULL){
334                 free(this);
335                 return NULL;
336         }*/
337         
338 /*      for(i = 0; i < CMDL_OUTPUT_SIZE; i++){
339                 this->output[i] = 0;
340         }*/
341
342         /* Allocate command line buffer */
343         
344         this->buffer = (char*)malloc(CMDL_BUFFER_SIZE);
345         if(this->buffer == NULL){
346                 free(this);
347                 return NULL;
348         }
349         
350         for(i = 0; i < CMDL_BUFFER_SIZE; i++){
351                 this->buffer[i] = 0;
352         }
353         
354         /* Allocate prompt buffer */
355         
356         this->prompt = (char*)malloc(CMDL_PROMPT_SIZE);
357         if(this->prompt == NULL){
358                 free(this);
359                 return NULL;
360         }
361         
362         for(i = 0; i < CMDL_PROMPT_SIZE; i++){
363                 this->prompt[i] = 0;
364         }
365         
366         /* Initiate cursor position etc.*/
367         
368         this->cursor = 0;
369         //this->has_output = 0;
370         this->exit = 0;
371         this->refresh = 1;
372         this->tabstate = 0;
373         this->insert = 0;
374
375         /* set callbacks to NULL */
376
377         this->getchar = NULL;
378         this->putchar = NULL;
379         this->printf = NULL;
380
381         /* List the commands */
382
383         struct command *cmd;
384
385         printf ( "Available commands: ");
386         for ( cmd = cmd_start ; cmd < cmd_end ; cmd++ ) {
387                 printf("%s ", cmd->name);
388         }
389         printf("exit\n\n");
390
391         return this;
392 }
393
394 void cmdl_free(cmd_line* cmd)
395 {
396         free(cmd);
397 }
398