Jason Reiss / tinyshell

Fork of tinyshell by Murilo Pontes

Committer:
jasonreiss
Date:
Wed Dec 27 23:13:26 2017 +0000
Revision:
3:d027360b1892
Parent:
2:c57737fee604
adjust help description

Who changed what in which revision?

UserRevisionLine numberNew contents of line
murilopontes 0:78b46c0d5246 1 /*
murilopontes 0:78b46c0d5246 2 * tinysh.c
murilopontes 0:78b46c0d5246 3 *
murilopontes 0:78b46c0d5246 4 * Minimal portable shell
murilopontes 0:78b46c0d5246 5 *
murilopontes 0:78b46c0d5246 6 * Copyright (C) 2001 Michel Gutierrez <mig@nerim.net>
murilopontes 0:78b46c0d5246 7 *
murilopontes 0:78b46c0d5246 8 * This library is free software; you can redistribute it and/or
murilopontes 0:78b46c0d5246 9 * modify it under the terms of the GNU Lesser General Public
murilopontes 0:78b46c0d5246 10 * License as published by the Free Software Foundation; either
murilopontes 0:78b46c0d5246 11 * version 2.1 of the License, or (at your option) any later version.
murilopontes 0:78b46c0d5246 12 *
murilopontes 0:78b46c0d5246 13 * This library is distributed in the hope that it will be useful,
murilopontes 0:78b46c0d5246 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
murilopontes 0:78b46c0d5246 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
murilopontes 0:78b46c0d5246 16 * Lesser General Public License for more details.
murilopontes 0:78b46c0d5246 17 *
murilopontes 0:78b46c0d5246 18 * You should have received a copy of the GNU Lesser General Public
murilopontes 0:78b46c0d5246 19 * License along with this library; if not, write to the Free
murilopontes 0:78b46c0d5246 20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
murilopontes 0:78b46c0d5246 21 */
murilopontes 0:78b46c0d5246 22
murilopontes 0:78b46c0d5246 23 #include "tinysh.h"
murilopontes 0:78b46c0d5246 24
murilopontes 0:78b46c0d5246 25 #ifndef BUFFER_SIZE
murilopontes 0:78b46c0d5246 26 #define BUFFER_SIZE 64
murilopontes 0:78b46c0d5246 27 #endif
murilopontes 0:78b46c0d5246 28 #ifndef HISTORY_DEPTH
murilopontes 0:78b46c0d5246 29 #define HISTORY_DEPTH 3
murilopontes 0:78b46c0d5246 30 #endif
murilopontes 0:78b46c0d5246 31 #ifndef MAX_ARGS
murilopontes 0:78b46c0d5246 32 #define MAX_ARGS 4
murilopontes 0:78b46c0d5246 33 #endif
murilopontes 0:78b46c0d5246 34 #ifndef PROMPT_SIZE
murilopontes 0:78b46c0d5246 35 #define PROMPT_SIZE 4
murilopontes 0:78b46c0d5246 36 #endif
murilopontes 0:78b46c0d5246 37 #ifndef TOPCHAR
murilopontes 0:78b46c0d5246 38 #define TOPCHAR '/'
murilopontes 0:78b46c0d5246 39 #endif
murilopontes 0:78b46c0d5246 40
murilopontes 0:78b46c0d5246 41 typedef unsigned char uchar;
murilopontes 0:78b46c0d5246 42 /* redefine some useful and maybe missing utilities to avoid conflicts */
murilopontes 0:78b46c0d5246 43 #define strlen tinysh_strlen
murilopontes 0:78b46c0d5246 44 #define puts tinysh_puts
murilopontes 0:78b46c0d5246 45 #define putchar tinysh_char_out
murilopontes 0:78b46c0d5246 46
murilopontes 0:78b46c0d5246 47 static void help_fnt(int argc, char **argv);
murilopontes 0:78b46c0d5246 48
murilopontes 0:78b46c0d5246 49 static tinysh_cmd_t help_cmd={
jasonreiss 3:d027360b1892 50 0,"help","Display help","<cr>",help_fnt,0,0,0 };
murilopontes 0:78b46c0d5246 51
murilopontes 0:78b46c0d5246 52 static uchar input_buffers[HISTORY_DEPTH][BUFFER_SIZE+1]={0};
murilopontes 0:78b46c0d5246 53 static uchar trash_buffer[BUFFER_SIZE+1]={0};
murilopontes 0:78b46c0d5246 54 static int cur_buf_index=0;
murilopontes 0:78b46c0d5246 55 static uchar context_buffer[BUFFER_SIZE+1]={0};
murilopontes 0:78b46c0d5246 56 static int cur_context=0;
murilopontes 0:78b46c0d5246 57 static int cur_index=0;
murilopontes 0:78b46c0d5246 58 static int echo=1;
murilopontes 0:78b46c0d5246 59 static char prompt[PROMPT_SIZE+1]="$ ";
murilopontes 0:78b46c0d5246 60 static tinysh_cmd_t *root_cmd=&help_cmd;
murilopontes 0:78b46c0d5246 61 static tinysh_cmd_t *cur_cmd_ctx=0;
murilopontes 0:78b46c0d5246 62 static void *tinysh_arg=0;
murilopontes 0:78b46c0d5246 63
murilopontes 0:78b46c0d5246 64 /* few useful utilities that may be missing */
murilopontes 0:78b46c0d5246 65
murilopontes 0:78b46c0d5246 66 static int strlen(uchar *s)
murilopontes 0:78b46c0d5246 67 {
murilopontes 0:78b46c0d5246 68 int i;
murilopontes 0:78b46c0d5246 69 for(i=0;*s;s++,i++);
murilopontes 0:78b46c0d5246 70 return i;
murilopontes 0:78b46c0d5246 71 }
murilopontes 0:78b46c0d5246 72
murilopontes 0:78b46c0d5246 73 static void puts(char *s)
murilopontes 0:78b46c0d5246 74 {
murilopontes 0:78b46c0d5246 75 while(*s)
murilopontes 0:78b46c0d5246 76 putchar(*s++);
murilopontes 0:78b46c0d5246 77 }
murilopontes 0:78b46c0d5246 78
murilopontes 0:78b46c0d5246 79 /* callback for help function
murilopontes 0:78b46c0d5246 80 */
murilopontes 0:78b46c0d5246 81 static void help_fnt(int argc, char **argv)
murilopontes 0:78b46c0d5246 82 {
murilopontes 0:78b46c0d5246 83 puts("? display help on given or available commands\r\n");
murilopontes 0:78b46c0d5246 84 puts("<TAB> auto-completion\r\n");
murilopontes 0:78b46c0d5246 85 puts("<cr> execute command line\r\n");
murilopontes 0:78b46c0d5246 86 puts("CTRL-P recall previous input line\r\n");
murilopontes 0:78b46c0d5246 87 puts("CTRL-N recall next input line\r\n");
murilopontes 0:78b46c0d5246 88 puts("<any> treat as input character\r\n");
murilopontes 0:78b46c0d5246 89 }
murilopontes 0:78b46c0d5246 90
murilopontes 0:78b46c0d5246 91 /*
murilopontes 0:78b46c0d5246 92 */
murilopontes 0:78b46c0d5246 93
murilopontes 0:78b46c0d5246 94 enum { NULLMATCH,FULLMATCH,PARTMATCH,UNMATCH,MATCH,AMBIG };
murilopontes 0:78b46c0d5246 95
murilopontes 0:78b46c0d5246 96 /* verify if the non-spaced part of s2 is included at the begining
murilopontes 0:78b46c0d5246 97 * of s1.
murilopontes 0:78b46c0d5246 98 * return FULLMATCH if s2 equal to s1, PARTMATCH if s1 starts with s2
murilopontes 0:78b46c0d5246 99 * but there are remaining chars in s1, UNMATCH if s1 does not start with
murilopontes 0:78b46c0d5246 100 * s2
murilopontes 0:78b46c0d5246 101 */
murilopontes 0:78b46c0d5246 102 int strstart(uchar *s1, uchar *s2)
murilopontes 0:78b46c0d5246 103 {
murilopontes 0:78b46c0d5246 104 while(*s1 && *s1==*s2) { s1++; s2++; }
murilopontes 0:78b46c0d5246 105
murilopontes 0:78b46c0d5246 106 if(*s2==' ' || *s2==0)
murilopontes 0:78b46c0d5246 107 {
murilopontes 0:78b46c0d5246 108 if(*s1==0)
murilopontes 0:78b46c0d5246 109 return FULLMATCH; /* full match */
murilopontes 0:78b46c0d5246 110 else
murilopontes 0:78b46c0d5246 111 return PARTMATCH; /* partial match */
murilopontes 0:78b46c0d5246 112 }
murilopontes 0:78b46c0d5246 113 else
murilopontes 0:78b46c0d5246 114 return UNMATCH; /* no match */
murilopontes 0:78b46c0d5246 115 }
murilopontes 0:78b46c0d5246 116
murilopontes 0:78b46c0d5246 117 /*
murilopontes 0:78b46c0d5246 118 * check commands at given level with input string.
murilopontes 0:78b46c0d5246 119 * _cmd: point to first command at this level, return matched cmd
murilopontes 0:78b46c0d5246 120 * _str: point to current unprocessed input, return next unprocessed
murilopontes 0:78b46c0d5246 121 */
murilopontes 0:78b46c0d5246 122 static int parse_command(tinysh_cmd_t **_cmd, uchar **_str)
murilopontes 0:78b46c0d5246 123 {
murilopontes 0:78b46c0d5246 124 uchar *str=*_str;
murilopontes 0:78b46c0d5246 125 tinysh_cmd_t *cmd;
murilopontes 0:78b46c0d5246 126 int matched_len=0;
murilopontes 0:78b46c0d5246 127 tinysh_cmd_t *matched_cmd=0;
murilopontes 0:78b46c0d5246 128
murilopontes 0:78b46c0d5246 129 /* first eliminate first blanks */
murilopontes 0:78b46c0d5246 130 while(*str==' ') str++;
murilopontes 0:78b46c0d5246 131 if(!*str)
murilopontes 0:78b46c0d5246 132 {
murilopontes 0:78b46c0d5246 133 *_str=str;
murilopontes 0:78b46c0d5246 134 return NULLMATCH; /* end of input */
murilopontes 0:78b46c0d5246 135 }
murilopontes 0:78b46c0d5246 136
murilopontes 0:78b46c0d5246 137 /* first pass: count matches */
murilopontes 0:78b46c0d5246 138 for(cmd=*_cmd;cmd;cmd=cmd->next)
murilopontes 0:78b46c0d5246 139 {
murilopontes 0:78b46c0d5246 140 int ret=strstart(cmd->name,str);
murilopontes 0:78b46c0d5246 141
murilopontes 0:78b46c0d5246 142 if(ret==FULLMATCH)
murilopontes 0:78b46c0d5246 143 {
murilopontes 0:78b46c0d5246 144 /* found full match */
murilopontes 0:78b46c0d5246 145 while(*str && *str!=' ') str++;
murilopontes 0:78b46c0d5246 146 while(*str==' ') str++;
murilopontes 0:78b46c0d5246 147 *_str=str;
murilopontes 0:78b46c0d5246 148 *_cmd=cmd;
murilopontes 0:78b46c0d5246 149 return MATCH;
murilopontes 0:78b46c0d5246 150 }
murilopontes 0:78b46c0d5246 151 else if (ret==PARTMATCH)
murilopontes 0:78b46c0d5246 152 {
murilopontes 0:78b46c0d5246 153 if(matched_cmd)
murilopontes 0:78b46c0d5246 154 {
murilopontes 0:78b46c0d5246 155 *_cmd=matched_cmd;
murilopontes 0:78b46c0d5246 156 return AMBIG;
murilopontes 0:78b46c0d5246 157 }
murilopontes 0:78b46c0d5246 158 else
murilopontes 0:78b46c0d5246 159 {
murilopontes 0:78b46c0d5246 160 matched_cmd=cmd;
murilopontes 0:78b46c0d5246 161 }
murilopontes 0:78b46c0d5246 162 }
murilopontes 0:78b46c0d5246 163 else /* UNMATCH */
murilopontes 0:78b46c0d5246 164 {
murilopontes 0:78b46c0d5246 165 }
murilopontes 0:78b46c0d5246 166 }
murilopontes 0:78b46c0d5246 167 if(matched_cmd)
murilopontes 0:78b46c0d5246 168 {
murilopontes 0:78b46c0d5246 169 while(*str && *str!=' ') str++;
murilopontes 0:78b46c0d5246 170 while(*str==' ') str++;
murilopontes 0:78b46c0d5246 171 *_cmd=matched_cmd;
murilopontes 0:78b46c0d5246 172 *_str=str;
murilopontes 0:78b46c0d5246 173 return MATCH;
murilopontes 0:78b46c0d5246 174 }
murilopontes 0:78b46c0d5246 175 else
murilopontes 0:78b46c0d5246 176 return UNMATCH;
murilopontes 0:78b46c0d5246 177 }
murilopontes 0:78b46c0d5246 178
murilopontes 0:78b46c0d5246 179 /* create a context from current input line
murilopontes 0:78b46c0d5246 180 */
murilopontes 0:78b46c0d5246 181 static void do_context(tinysh_cmd_t *cmd, uchar *str)
murilopontes 0:78b46c0d5246 182 {
murilopontes 0:78b46c0d5246 183 while(*str)
murilopontes 0:78b46c0d5246 184 context_buffer[cur_context++]=*str++;
murilopontes 0:78b46c0d5246 185 context_buffer[cur_context]=0;
murilopontes 0:78b46c0d5246 186 cur_cmd_ctx=cmd;
murilopontes 0:78b46c0d5246 187 }
murilopontes 0:78b46c0d5246 188
murilopontes 0:78b46c0d5246 189 /* execute the given command by calling callback with appropriate
murilopontes 0:78b46c0d5246 190 * arguments
murilopontes 0:78b46c0d5246 191 */
murilopontes 0:78b46c0d5246 192 static void exec_command(tinysh_cmd_t *cmd, uchar *str)
murilopontes 0:78b46c0d5246 193 {
murilopontes 0:78b46c0d5246 194 char *argv[MAX_ARGS];
murilopontes 0:78b46c0d5246 195 int argc=0;
murilopontes 0:78b46c0d5246 196 int i;
murilopontes 0:78b46c0d5246 197
murilopontes 0:78b46c0d5246 198 /* copy command line to preserve it for history */
murilopontes 0:78b46c0d5246 199 for(i=0;i<BUFFER_SIZE;i++)
murilopontes 0:78b46c0d5246 200 trash_buffer[i]=str[i];
murilopontes 0:78b46c0d5246 201 str=trash_buffer;
murilopontes 0:78b46c0d5246 202
murilopontes 0:78b46c0d5246 203 /* cut into arguments */
murilopontes 0:78b46c0d5246 204 argv[argc++]=cmd->name;
murilopontes 0:78b46c0d5246 205 while(*str && argc<MAX_ARGS)
murilopontes 0:78b46c0d5246 206 {
murilopontes 0:78b46c0d5246 207 while(*str==' ') str++;
murilopontes 0:78b46c0d5246 208 if(*str==0)
murilopontes 0:78b46c0d5246 209 break;
murilopontes 0:78b46c0d5246 210 argv[argc++]=str;
murilopontes 0:78b46c0d5246 211 while(*str!=' ' && *str) str++;
murilopontes 0:78b46c0d5246 212 if(!*str) break;
murilopontes 0:78b46c0d5246 213 *str++=0;
murilopontes 0:78b46c0d5246 214 }
murilopontes 0:78b46c0d5246 215 /* call command function if present */
murilopontes 0:78b46c0d5246 216 if(cmd->function)
murilopontes 0:78b46c0d5246 217 {
murilopontes 0:78b46c0d5246 218 tinysh_arg=cmd->arg;
murilopontes 0:78b46c0d5246 219 cmd->function(argc,&argv[0]);
murilopontes 0:78b46c0d5246 220 }
murilopontes 0:78b46c0d5246 221 }
murilopontes 0:78b46c0d5246 222
murilopontes 0:78b46c0d5246 223 /* try to execute the current command line
murilopontes 0:78b46c0d5246 224 */
murilopontes 0:78b46c0d5246 225 static int exec_command_line(tinysh_cmd_t *cmd, uchar *_str)
murilopontes 0:78b46c0d5246 226 {
murilopontes 0:78b46c0d5246 227 uchar *str=_str;
murilopontes 0:78b46c0d5246 228
murilopontes 0:78b46c0d5246 229 while(1)
murilopontes 0:78b46c0d5246 230 {
murilopontes 0:78b46c0d5246 231 int ret;
murilopontes 0:78b46c0d5246 232 ret=parse_command(&cmd,&str);
murilopontes 0:78b46c0d5246 233 if(ret==MATCH) /* found unique match */
murilopontes 0:78b46c0d5246 234 {
murilopontes 0:78b46c0d5246 235 if(cmd)
murilopontes 0:78b46c0d5246 236 {
murilopontes 0:78b46c0d5246 237 if(!cmd->child) /* no sub-command, execute */
jasonreiss 2:c57737fee604 238 {
murilopontes 0:78b46c0d5246 239 exec_command(cmd,str);
murilopontes 0:78b46c0d5246 240 return 0;
murilopontes 0:78b46c0d5246 241 }
murilopontes 0:78b46c0d5246 242 else
murilopontes 0:78b46c0d5246 243 {
murilopontes 0:78b46c0d5246 244 if(*str==0) /* no more input, this is a context */
murilopontes 0:78b46c0d5246 245 {
murilopontes 0:78b46c0d5246 246 do_context(cmd,_str);
murilopontes 0:78b46c0d5246 247 return 0;
murilopontes 0:78b46c0d5246 248 }
murilopontes 0:78b46c0d5246 249 else /* process next command word */
murilopontes 0:78b46c0d5246 250 {
murilopontes 0:78b46c0d5246 251 cmd=cmd->child;
murilopontes 0:78b46c0d5246 252 }
murilopontes 0:78b46c0d5246 253 }
murilopontes 0:78b46c0d5246 254 }
murilopontes 0:78b46c0d5246 255 else /* cmd == 0 */
murilopontes 0:78b46c0d5246 256 {
murilopontes 0:78b46c0d5246 257 return 0;
murilopontes 0:78b46c0d5246 258 }
murilopontes 0:78b46c0d5246 259 }
murilopontes 0:78b46c0d5246 260 else if(ret==AMBIG)
murilopontes 0:78b46c0d5246 261 {
murilopontes 0:78b46c0d5246 262 puts("ambiguity: ");
murilopontes 0:78b46c0d5246 263 puts(str);
murilopontes 0:78b46c0d5246 264 puts("\r\n");
murilopontes 0:78b46c0d5246 265 return 0;
murilopontes 0:78b46c0d5246 266 }
murilopontes 0:78b46c0d5246 267 else if(ret==UNMATCH) /* UNMATCH */
murilopontes 0:78b46c0d5246 268 {
murilopontes 0:78b46c0d5246 269 puts("no match: ");
murilopontes 0:78b46c0d5246 270 puts(str);
murilopontes 0:78b46c0d5246 271 puts("\r\n");
murilopontes 0:78b46c0d5246 272 return 0;
murilopontes 0:78b46c0d5246 273 }
jasonreiss 2:c57737fee604 274 else { /* NULLMATCH */
jasonreiss 2:c57737fee604 275 puts("\r\n");
murilopontes 0:78b46c0d5246 276 return 0;
jasonreiss 2:c57737fee604 277 }
murilopontes 0:78b46c0d5246 278 }
murilopontes 0:78b46c0d5246 279 }
murilopontes 0:78b46c0d5246 280
murilopontes 0:78b46c0d5246 281 /* display help for list of commands
murilopontes 0:78b46c0d5246 282 */
murilopontes 0:78b46c0d5246 283 static void display_child_help(tinysh_cmd_t *cmd)
murilopontes 0:78b46c0d5246 284 {
murilopontes 0:78b46c0d5246 285 tinysh_cmd_t *cm;
murilopontes 0:78b46c0d5246 286 int len=0;
murilopontes 0:78b46c0d5246 287
murilopontes 0:78b46c0d5246 288 puts("\r\n");
murilopontes 0:78b46c0d5246 289 for(cm=cmd;cm;cm=cm->next)
murilopontes 0:78b46c0d5246 290 if(len<strlen(cm->name))
murilopontes 0:78b46c0d5246 291 len=strlen(cm->name);
murilopontes 0:78b46c0d5246 292 for(cm=cmd;cm;cm=cm->next)
murilopontes 0:78b46c0d5246 293 if(cm->help)
murilopontes 0:78b46c0d5246 294 {
murilopontes 0:78b46c0d5246 295 int i;
murilopontes 0:78b46c0d5246 296 puts(cm->name);
murilopontes 0:78b46c0d5246 297 for(i=strlen(cm->name);i<len+2;i++)
murilopontes 0:78b46c0d5246 298 putchar(' ');
murilopontes 0:78b46c0d5246 299 puts(cm->help);
murilopontes 0:78b46c0d5246 300 puts("\r\n");
murilopontes 0:78b46c0d5246 301 }
murilopontes 0:78b46c0d5246 302 }
murilopontes 0:78b46c0d5246 303
murilopontes 0:78b46c0d5246 304 /* try to display help for current comand line
murilopontes 0:78b46c0d5246 305 */
murilopontes 0:78b46c0d5246 306 static int help_command_line(tinysh_cmd_t *cmd, uchar *_str)
murilopontes 0:78b46c0d5246 307 {
murilopontes 0:78b46c0d5246 308 uchar *str=_str;
murilopontes 0:78b46c0d5246 309
murilopontes 0:78b46c0d5246 310 while(1)
murilopontes 0:78b46c0d5246 311 {
murilopontes 0:78b46c0d5246 312 int ret;
murilopontes 0:78b46c0d5246 313 ret=parse_command(&cmd,&str);
murilopontes 0:78b46c0d5246 314 if(ret==MATCH && *str==0) /* found unique match or empty line */
murilopontes 0:78b46c0d5246 315 {
murilopontes 0:78b46c0d5246 316 tinysh_cmd_t *cm;
murilopontes 0:78b46c0d5246 317 int len=0;
murilopontes 0:78b46c0d5246 318
murilopontes 0:78b46c0d5246 319 if(cmd->child) /* display sub-commands help */
murilopontes 0:78b46c0d5246 320 {
murilopontes 0:78b46c0d5246 321 display_child_help(cmd->child);
murilopontes 0:78b46c0d5246 322 return 0;
murilopontes 0:78b46c0d5246 323 }
murilopontes 0:78b46c0d5246 324 else /* no sub-command, show single help */
murilopontes 0:78b46c0d5246 325 {
murilopontes 0:78b46c0d5246 326 if(*(str-1)!=' ')
murilopontes 0:78b46c0d5246 327 putchar(' ');
murilopontes 0:78b46c0d5246 328 if(cmd->usage)
murilopontes 0:78b46c0d5246 329 puts(cmd->usage);
murilopontes 0:78b46c0d5246 330 puts(": ");
murilopontes 0:78b46c0d5246 331 if(cmd->help)
murilopontes 0:78b46c0d5246 332 puts(cmd->help);
murilopontes 0:78b46c0d5246 333 else
murilopontes 0:78b46c0d5246 334 puts("no help available");
murilopontes 0:78b46c0d5246 335 puts("\r\n");
murilopontes 0:78b46c0d5246 336 }
murilopontes 0:78b46c0d5246 337 return 0;
murilopontes 0:78b46c0d5246 338 }
murilopontes 0:78b46c0d5246 339 else if(ret==MATCH && *str)
murilopontes 0:78b46c0d5246 340 { /* continue processing the line */
murilopontes 0:78b46c0d5246 341 cmd=cmd->child;
murilopontes 0:78b46c0d5246 342 }
murilopontes 0:78b46c0d5246 343 else if(ret==AMBIG)
murilopontes 0:78b46c0d5246 344 {
murilopontes 0:78b46c0d5246 345 puts("\r\nambiguity: ");
murilopontes 0:78b46c0d5246 346 puts(str);
murilopontes 0:78b46c0d5246 347 puts("\r\n");
murilopontes 0:78b46c0d5246 348 return 0;
murilopontes 0:78b46c0d5246 349 }
murilopontes 0:78b46c0d5246 350 else if(ret==UNMATCH)
murilopontes 0:78b46c0d5246 351 {
murilopontes 0:78b46c0d5246 352 puts("\r\nno match: ");
murilopontes 0:78b46c0d5246 353 puts(str);
murilopontes 0:78b46c0d5246 354 puts("\r\n");
murilopontes 0:78b46c0d5246 355 return 0;
murilopontes 0:78b46c0d5246 356 }
murilopontes 0:78b46c0d5246 357 else /* NULLMATCH */
murilopontes 0:78b46c0d5246 358 {
murilopontes 0:78b46c0d5246 359 if(cur_cmd_ctx)
murilopontes 0:78b46c0d5246 360 display_child_help(cur_cmd_ctx->child);
murilopontes 0:78b46c0d5246 361 else
murilopontes 0:78b46c0d5246 362 display_child_help(root_cmd);
murilopontes 0:78b46c0d5246 363 return 0;
murilopontes 0:78b46c0d5246 364 }
murilopontes 0:78b46c0d5246 365 }
murilopontes 0:78b46c0d5246 366 }
murilopontes 0:78b46c0d5246 367
murilopontes 0:78b46c0d5246 368 /* try to complete current command line
murilopontes 0:78b46c0d5246 369 */
murilopontes 0:78b46c0d5246 370 static int complete_command_line(tinysh_cmd_t *cmd, uchar *_str)
murilopontes 0:78b46c0d5246 371 {
murilopontes 0:78b46c0d5246 372 uchar *str=_str;
murilopontes 0:78b46c0d5246 373
murilopontes 0:78b46c0d5246 374 while(1)
murilopontes 0:78b46c0d5246 375 {
murilopontes 0:78b46c0d5246 376 int ret;
murilopontes 0:78b46c0d5246 377 int common_len=BUFFER_SIZE;
murilopontes 0:78b46c0d5246 378 int _str_len;
murilopontes 0:78b46c0d5246 379 int i;
murilopontes 0:78b46c0d5246 380 uchar *__str=str;
murilopontes 0:78b46c0d5246 381
murilopontes 0:78b46c0d5246 382 tinysh_cmd_t *_cmd=cmd;
murilopontes 0:78b46c0d5246 383 ret=parse_command(&cmd,&str);
murilopontes 0:78b46c0d5246 384 for(_str_len=0;__str[_str_len]&&__str[_str_len]!=' ';_str_len++);
murilopontes 0:78b46c0d5246 385 if(ret==MATCH && *str)
murilopontes 0:78b46c0d5246 386 {
murilopontes 0:78b46c0d5246 387 cmd=cmd->child;
murilopontes 0:78b46c0d5246 388 }
murilopontes 0:78b46c0d5246 389 else if(ret==AMBIG || ret==MATCH || ret==NULLMATCH)
murilopontes 0:78b46c0d5246 390 {
murilopontes 0:78b46c0d5246 391 tinysh_cmd_t *cm;
murilopontes 0:78b46c0d5246 392 tinysh_cmd_t *matched_cmd=0;
murilopontes 0:78b46c0d5246 393 int nb_match=0;
murilopontes 0:78b46c0d5246 394
murilopontes 0:78b46c0d5246 395 for(cm=cmd;cm;cm=cm->next)
murilopontes 0:78b46c0d5246 396 {
murilopontes 0:78b46c0d5246 397 int r=strstart(cm->name,__str);
murilopontes 0:78b46c0d5246 398 if(r==FULLMATCH)
murilopontes 0:78b46c0d5246 399 {
murilopontes 0:78b46c0d5246 400 for(i=_str_len;cmd->name[i];i++)
murilopontes 0:78b46c0d5246 401 tinysh_char_in(cmd->name[i]);
murilopontes 0:78b46c0d5246 402 if(*(str-1)!=' ')
murilopontes 0:78b46c0d5246 403 tinysh_char_in(' ');
murilopontes 0:78b46c0d5246 404 if(!cmd->child)
murilopontes 0:78b46c0d5246 405 {
murilopontes 0:78b46c0d5246 406 if(cmd->usage)
murilopontes 0:78b46c0d5246 407 {
murilopontes 0:78b46c0d5246 408 puts(cmd->usage);
murilopontes 0:78b46c0d5246 409 putchar('\n');
murilopontes 0:78b46c0d5246 410 return 1;
murilopontes 0:78b46c0d5246 411 }
murilopontes 0:78b46c0d5246 412 else
murilopontes 0:78b46c0d5246 413 return 0;
murilopontes 0:78b46c0d5246 414 }
murilopontes 0:78b46c0d5246 415 else
murilopontes 0:78b46c0d5246 416 {
murilopontes 0:78b46c0d5246 417 cmd=cmd->child;
murilopontes 0:78b46c0d5246 418 break;
murilopontes 0:78b46c0d5246 419 }
murilopontes 0:78b46c0d5246 420 }
murilopontes 0:78b46c0d5246 421 else if(r==PARTMATCH)
murilopontes 0:78b46c0d5246 422 {
murilopontes 0:78b46c0d5246 423 nb_match++;
murilopontes 0:78b46c0d5246 424 if(!matched_cmd)
murilopontes 0:78b46c0d5246 425 {
murilopontes 0:78b46c0d5246 426 matched_cmd=cm;
murilopontes 0:78b46c0d5246 427 common_len=strlen(cm->name);
murilopontes 0:78b46c0d5246 428 }
murilopontes 0:78b46c0d5246 429 else
murilopontes 0:78b46c0d5246 430 {
murilopontes 0:78b46c0d5246 431 for(i=_str_len;cm->name[i] && i<common_len &&
murilopontes 0:78b46c0d5246 432 cm->name[i]==matched_cmd->name[i];i++);
murilopontes 0:78b46c0d5246 433 if(i<common_len)
murilopontes 0:78b46c0d5246 434 common_len=i;
murilopontes 0:78b46c0d5246 435 }
murilopontes 0:78b46c0d5246 436 }
murilopontes 0:78b46c0d5246 437 }
murilopontes 0:78b46c0d5246 438 if(cm)
murilopontes 0:78b46c0d5246 439 continue;
murilopontes 0:78b46c0d5246 440 if(matched_cmd)
murilopontes 0:78b46c0d5246 441 {
murilopontes 0:78b46c0d5246 442 if(_str_len==common_len)
murilopontes 0:78b46c0d5246 443 {
murilopontes 1:71580bf962fe 444 puts("\r\n");
murilopontes 0:78b46c0d5246 445 for(cm=cmd;cm;cm=cm->next)
murilopontes 0:78b46c0d5246 446 {
murilopontes 0:78b46c0d5246 447 int r=strstart(cm->name,__str);
murilopontes 0:78b46c0d5246 448 if(r==FULLMATCH || r==PARTMATCH)
murilopontes 0:78b46c0d5246 449 {
murilopontes 0:78b46c0d5246 450 puts(cm->name);
murilopontes 1:71580bf962fe 451 puts("\r\n");
murilopontes 0:78b46c0d5246 452 }
murilopontes 0:78b46c0d5246 453 }
murilopontes 0:78b46c0d5246 454 return 1;
murilopontes 0:78b46c0d5246 455 }
murilopontes 0:78b46c0d5246 456 else
murilopontes 0:78b46c0d5246 457 {
murilopontes 0:78b46c0d5246 458 for(i=_str_len;i<common_len;i++)
murilopontes 0:78b46c0d5246 459 tinysh_char_in(matched_cmd->name[i]);
murilopontes 0:78b46c0d5246 460 if(nb_match==1)
murilopontes 0:78b46c0d5246 461 tinysh_char_in(' ');
murilopontes 0:78b46c0d5246 462 }
murilopontes 0:78b46c0d5246 463 }
murilopontes 0:78b46c0d5246 464 return 0;
murilopontes 0:78b46c0d5246 465 }
murilopontes 0:78b46c0d5246 466 else /* UNMATCH */
murilopontes 0:78b46c0d5246 467 {
murilopontes 0:78b46c0d5246 468 return 0;
murilopontes 0:78b46c0d5246 469 }
murilopontes 0:78b46c0d5246 470 }
murilopontes 0:78b46c0d5246 471 }
murilopontes 0:78b46c0d5246 472
murilopontes 0:78b46c0d5246 473 /* start a new line
murilopontes 0:78b46c0d5246 474 */
murilopontes 0:78b46c0d5246 475 static void start_of_line()
murilopontes 0:78b46c0d5246 476 {
murilopontes 0:78b46c0d5246 477 /* display start of new line */
murilopontes 0:78b46c0d5246 478 puts(prompt);
murilopontes 0:78b46c0d5246 479 if(cur_context)
murilopontes 0:78b46c0d5246 480 {
murilopontes 0:78b46c0d5246 481 puts(context_buffer);
murilopontes 0:78b46c0d5246 482 puts("> ");
murilopontes 0:78b46c0d5246 483 }
murilopontes 0:78b46c0d5246 484 cur_index=0;
murilopontes 0:78b46c0d5246 485 }
murilopontes 0:78b46c0d5246 486
murilopontes 0:78b46c0d5246 487 /* character input
murilopontes 0:78b46c0d5246 488 */
murilopontes 0:78b46c0d5246 489 static void _tinysh_char_in(uchar c)
murilopontes 0:78b46c0d5246 490 {
murilopontes 0:78b46c0d5246 491 uchar *line=input_buffers[cur_buf_index];
murilopontes 0:78b46c0d5246 492
murilopontes 0:78b46c0d5246 493 if(c=='\n' || c=='\r') /* validate command */
murilopontes 0:78b46c0d5246 494 {
murilopontes 0:78b46c0d5246 495 tinysh_cmd_t *cmd;
murilopontes 0:78b46c0d5246 496 int context=0;
murilopontes 0:78b46c0d5246 497
murilopontes 0:78b46c0d5246 498 /* first, echo the newline */
murilopontes 0:78b46c0d5246 499 if(echo)
murilopontes 0:78b46c0d5246 500 putchar(c);
murilopontes 0:78b46c0d5246 501
murilopontes 0:78b46c0d5246 502 while(*line && *line==' ') line++;
murilopontes 0:78b46c0d5246 503 if(*line) /* not empty line */
murilopontes 0:78b46c0d5246 504 {
murilopontes 0:78b46c0d5246 505 cmd=cur_cmd_ctx?cur_cmd_ctx->child:root_cmd;
murilopontes 0:78b46c0d5246 506 exec_command_line(cmd,line);
murilopontes 0:78b46c0d5246 507 cur_buf_index=(cur_buf_index+1)%HISTORY_DEPTH;
murilopontes 0:78b46c0d5246 508 cur_index=0;
murilopontes 0:78b46c0d5246 509 input_buffers[cur_buf_index][0]=0;
murilopontes 0:78b46c0d5246 510 }
murilopontes 0:78b46c0d5246 511 start_of_line();
murilopontes 0:78b46c0d5246 512 }
murilopontes 0:78b46c0d5246 513 else if(c==TOPCHAR) /* return to top level */
murilopontes 0:78b46c0d5246 514 {
murilopontes 0:78b46c0d5246 515 if(echo)
murilopontes 0:78b46c0d5246 516 putchar(c);
murilopontes 0:78b46c0d5246 517
murilopontes 0:78b46c0d5246 518 cur_context=0;
murilopontes 0:78b46c0d5246 519 cur_cmd_ctx=0;
murilopontes 0:78b46c0d5246 520 }
murilopontes 0:78b46c0d5246 521 else if(c==8 || c==127) /* backspace */
murilopontes 0:78b46c0d5246 522 {
murilopontes 0:78b46c0d5246 523 if(cur_index>0)
murilopontes 0:78b46c0d5246 524 {
murilopontes 0:78b46c0d5246 525 puts("\b \b");
murilopontes 0:78b46c0d5246 526 cur_index--;
murilopontes 0:78b46c0d5246 527 line[cur_index]=0;
murilopontes 0:78b46c0d5246 528 }
murilopontes 0:78b46c0d5246 529 }
murilopontes 0:78b46c0d5246 530 else if(c==16) /* CTRL-P: back in history */
murilopontes 0:78b46c0d5246 531 {
murilopontes 0:78b46c0d5246 532 int prevline=(cur_buf_index+HISTORY_DEPTH-1)%HISTORY_DEPTH;
murilopontes 0:78b46c0d5246 533
murilopontes 0:78b46c0d5246 534 if(input_buffers[prevline][0])
murilopontes 0:78b46c0d5246 535 {
murilopontes 0:78b46c0d5246 536 line=input_buffers[prevline];
murilopontes 0:78b46c0d5246 537 /* fill the rest of the line with spaces */
murilopontes 0:78b46c0d5246 538 while(cur_index-->strlen(line))
murilopontes 0:78b46c0d5246 539 puts("\b \b");
murilopontes 0:78b46c0d5246 540 putchar('\r');
murilopontes 0:78b46c0d5246 541 start_of_line();
murilopontes 0:78b46c0d5246 542 puts(line);
murilopontes 0:78b46c0d5246 543 cur_index=strlen(line);
murilopontes 0:78b46c0d5246 544 cur_buf_index=prevline;
murilopontes 0:78b46c0d5246 545 }
murilopontes 0:78b46c0d5246 546 }
murilopontes 0:78b46c0d5246 547 else if(c==14) /* CTRL-N: next in history */
murilopontes 0:78b46c0d5246 548 {
murilopontes 0:78b46c0d5246 549 int nextline=(cur_buf_index+1)%HISTORY_DEPTH;
murilopontes 0:78b46c0d5246 550
murilopontes 0:78b46c0d5246 551 if(input_buffers[nextline][0])
murilopontes 0:78b46c0d5246 552 {
murilopontes 0:78b46c0d5246 553 line=input_buffers[nextline];
murilopontes 0:78b46c0d5246 554 /* fill the rest of the line with spaces */
murilopontes 0:78b46c0d5246 555 while(cur_index-->strlen(line))
murilopontes 0:78b46c0d5246 556 puts("\b \b");
murilopontes 0:78b46c0d5246 557 putchar('\r');
murilopontes 0:78b46c0d5246 558 start_of_line();
murilopontes 0:78b46c0d5246 559 puts(line);
murilopontes 0:78b46c0d5246 560 cur_index=strlen(line);
murilopontes 0:78b46c0d5246 561 cur_buf_index=nextline;
murilopontes 0:78b46c0d5246 562 }
murilopontes 0:78b46c0d5246 563 }
murilopontes 0:78b46c0d5246 564 else if(c=='?') /* display help */
murilopontes 0:78b46c0d5246 565 {
murilopontes 0:78b46c0d5246 566 tinysh_cmd_t *cmd;
murilopontes 0:78b46c0d5246 567 cmd=cur_cmd_ctx?cur_cmd_ctx->child:root_cmd;
murilopontes 0:78b46c0d5246 568 help_command_line(cmd,line);
murilopontes 0:78b46c0d5246 569 start_of_line();
murilopontes 0:78b46c0d5246 570 puts(line);
murilopontes 0:78b46c0d5246 571 cur_index=strlen(line);
murilopontes 0:78b46c0d5246 572 }
murilopontes 0:78b46c0d5246 573 else if(c==9 || c=='!') /* TAB: autocompletion */
murilopontes 0:78b46c0d5246 574 {
murilopontes 0:78b46c0d5246 575 tinysh_cmd_t *cmd;
murilopontes 0:78b46c0d5246 576 cmd=cur_cmd_ctx?cur_cmd_ctx->child:root_cmd;
murilopontes 0:78b46c0d5246 577 if(complete_command_line(cmd,line))
murilopontes 0:78b46c0d5246 578 {
murilopontes 0:78b46c0d5246 579 start_of_line();
murilopontes 0:78b46c0d5246 580 puts(line);
murilopontes 0:78b46c0d5246 581 }
murilopontes 0:78b46c0d5246 582 cur_index=strlen(line);
murilopontes 0:78b46c0d5246 583 }
murilopontes 0:78b46c0d5246 584 else /* any input character */
murilopontes 0:78b46c0d5246 585 {
murilopontes 0:78b46c0d5246 586 if(cur_index<BUFFER_SIZE)
murilopontes 0:78b46c0d5246 587 {
murilopontes 0:78b46c0d5246 588 if(echo)
murilopontes 0:78b46c0d5246 589 putchar(c);
murilopontes 0:78b46c0d5246 590 line[cur_index++]=c;
murilopontes 0:78b46c0d5246 591 line[cur_index]=0;
murilopontes 0:78b46c0d5246 592 }
murilopontes 0:78b46c0d5246 593 }
murilopontes 0:78b46c0d5246 594 }
murilopontes 0:78b46c0d5246 595
murilopontes 0:78b46c0d5246 596 /* new character input */
murilopontes 0:78b46c0d5246 597 void tinysh_char_in(uchar c)
murilopontes 0:78b46c0d5246 598 {
murilopontes 0:78b46c0d5246 599 /*
murilopontes 0:78b46c0d5246 600 * filter characters here
murilopontes 0:78b46c0d5246 601 */
murilopontes 0:78b46c0d5246 602 _tinysh_char_in(c);
murilopontes 0:78b46c0d5246 603 }
murilopontes 0:78b46c0d5246 604
murilopontes 0:78b46c0d5246 605 /* add a new command */
murilopontes 0:78b46c0d5246 606 void tinysh_add_command(tinysh_cmd_t *cmd)
murilopontes 0:78b46c0d5246 607 {
murilopontes 0:78b46c0d5246 608 tinysh_cmd_t *cm;
murilopontes 0:78b46c0d5246 609
murilopontes 0:78b46c0d5246 610 if(cmd->parent)
murilopontes 0:78b46c0d5246 611 {
murilopontes 0:78b46c0d5246 612 cm=cmd->parent->child;
murilopontes 0:78b46c0d5246 613 if(!cm)
murilopontes 0:78b46c0d5246 614 {
murilopontes 0:78b46c0d5246 615 cmd->parent->child=cmd;
murilopontes 0:78b46c0d5246 616 }
murilopontes 0:78b46c0d5246 617 else
murilopontes 0:78b46c0d5246 618 {
murilopontes 0:78b46c0d5246 619 while(cm->next) cm=cm->next;
murilopontes 0:78b46c0d5246 620 cm->next=cmd;
murilopontes 0:78b46c0d5246 621 }
murilopontes 0:78b46c0d5246 622 }
murilopontes 0:78b46c0d5246 623 else if(!root_cmd)
murilopontes 0:78b46c0d5246 624 {
murilopontes 0:78b46c0d5246 625 root_cmd=cmd;
murilopontes 0:78b46c0d5246 626 }
murilopontes 0:78b46c0d5246 627 else
murilopontes 0:78b46c0d5246 628 {
murilopontes 0:78b46c0d5246 629 cm=root_cmd;
murilopontes 0:78b46c0d5246 630 while(cm->next) cm=cm->next;
murilopontes 0:78b46c0d5246 631 cm->next=cmd;
murilopontes 0:78b46c0d5246 632 }
murilopontes 0:78b46c0d5246 633 }
murilopontes 0:78b46c0d5246 634
murilopontes 0:78b46c0d5246 635 /* modify shell prompt
murilopontes 0:78b46c0d5246 636 */
murilopontes 0:78b46c0d5246 637 void tinysh_set_prompt(char *str)
murilopontes 0:78b46c0d5246 638 {
murilopontes 0:78b46c0d5246 639 int i;
murilopontes 0:78b46c0d5246 640 for(i=0;str[i] && i<PROMPT_SIZE;i++)
murilopontes 0:78b46c0d5246 641 prompt[i]=str[i];
murilopontes 0:78b46c0d5246 642 prompt[i]=0;
murilopontes 0:78b46c0d5246 643 /* force prompt display by generating empty command */
murilopontes 0:78b46c0d5246 644 tinysh_char_in('\r');
murilopontes 0:78b46c0d5246 645 }
murilopontes 0:78b46c0d5246 646
murilopontes 0:78b46c0d5246 647 /* return current command argument
murilopontes 0:78b46c0d5246 648 */
murilopontes 0:78b46c0d5246 649 void *tinysh_get_arg()
murilopontes 0:78b46c0d5246 650 {
murilopontes 0:78b46c0d5246 651 return tinysh_arg;
murilopontes 0:78b46c0d5246 652 }
murilopontes 0:78b46c0d5246 653
murilopontes 0:78b46c0d5246 654 /* string to decimal/hexadecimal conversion
murilopontes 0:78b46c0d5246 655 */
murilopontes 0:78b46c0d5246 656 unsigned long tinysh_atoxi(char *s)
murilopontes 0:78b46c0d5246 657 {
murilopontes 0:78b46c0d5246 658 int ishex=0;
murilopontes 0:78b46c0d5246 659 unsigned long res=0;
murilopontes 0:78b46c0d5246 660
murilopontes 0:78b46c0d5246 661 if(*s==0) return 0;
murilopontes 0:78b46c0d5246 662
murilopontes 0:78b46c0d5246 663 if(*s=='0' && *(s+1)=='x')
murilopontes 0:78b46c0d5246 664 {
murilopontes 0:78b46c0d5246 665 ishex=1;
murilopontes 0:78b46c0d5246 666 s+=2;
murilopontes 0:78b46c0d5246 667 }
murilopontes 0:78b46c0d5246 668
murilopontes 0:78b46c0d5246 669 while(*s)
murilopontes 0:78b46c0d5246 670 {
murilopontes 0:78b46c0d5246 671 if(ishex)
murilopontes 0:78b46c0d5246 672 res*=16;
murilopontes 0:78b46c0d5246 673 else
murilopontes 0:78b46c0d5246 674 res*=10;
murilopontes 0:78b46c0d5246 675
murilopontes 0:78b46c0d5246 676 if(*s>='0' && *s<='9')
murilopontes 0:78b46c0d5246 677 res+=*s-'0';
murilopontes 0:78b46c0d5246 678 else if(ishex && *s>='a' && *s<='f')
murilopontes 0:78b46c0d5246 679 res+=*s+10-'a';
murilopontes 0:78b46c0d5246 680 else if(ishex && *s>='A' && *s<='F')
murilopontes 0:78b46c0d5246 681 res+=*s+10-'A';
murilopontes 0:78b46c0d5246 682 else
murilopontes 0:78b46c0d5246 683 break;
murilopontes 0:78b46c0d5246 684
murilopontes 0:78b46c0d5246 685 s++;
murilopontes 0:78b46c0d5246 686 }
murilopontes 0:78b46c0d5246 687
murilopontes 0:78b46c0d5246 688 return res;
murilopontes 0:78b46c0d5246 689 }
murilopontes 0:78b46c0d5246 690