⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tinysh.c

📁 一个简易的Linux下的shell源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * tinysh.c * * Minimal portable shell * * Copyright (C) 2001 Michel Gutierrez <mig@nerim.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "tinysh.h"#ifndef BUFFER_SIZE#define BUFFER_SIZE 256#endif#ifndef HISTORY_DEPTH#define HISTORY_DEPTH 16#endif#ifndef MAX_ARGS#define MAX_ARGS 16#endif#ifndef PROMPT_SIZE#define PROMPT_SIZE 16#endif#ifndef TOPCHAR#define TOPCHAR '/'#endiftypedef unsigned char uchar;/* redefine some useful and maybe missing utilities to avoid conflicts */#define strlen tinysh_strlen#define puts tinysh_puts#define putchar tinysh_char_outstatic void help_fnt(int argc, char **argv);static tinysh_cmd_t help_cmd={   0,"help","display help","<cr>",help_fnt,0,0,0 };static uchar input_buffers[HISTORY_DEPTH][BUFFER_SIZE+1]={0};static uchar trash_buffer[BUFFER_SIZE+1]={0};static int cur_buf_index=0;static uchar context_buffer[BUFFER_SIZE+1]={0};static int cur_context=0;static int cur_index=0;static int echo=1;static char prompt[PROMPT_SIZE+1]="$ ";static tinysh_cmd_t *root_cmd=&help_cmd;static tinysh_cmd_t *cur_cmd_ctx=0;static void *tinysh_arg=0;/* few useful utilities that may be missing */static int strlen(uchar *s){  int i;  for(i=0;*s;s++,i++);  return i;}static void puts(char *s){  while(*s)    putchar(*s++);}/* callback for help function */static void help_fnt(int argc, char **argv){  puts("?            display help on given or available commands\n");  puts("<TAB>        auto-completion\n");  puts("<cr>         execute command line\n");  puts("CTRL-P       recall previous input line\n");  puts("CTRL-N       recall next input line\n");  puts("<any>        treat as input character\n");}/* */enum { NULLMATCH,FULLMATCH,PARTMATCH,UNMATCH,MATCH,AMBIG };/* verify if the non-spaced part of s2 is included at the begining * of s1. * return FULLMATCH if s2 equal to s1, PARTMATCH if s1 starts with s2 * but there are remaining chars in s1, UNMATCH if s1 does not start with * s2 */int strstart(uchar *s1, uchar *s2){  while(*s1 && *s1==*s2) { s1++; s2++; }  if(*s2==' ' || *s2==0)    {      if(*s1==0)        return FULLMATCH; /* full match */      else        return PARTMATCH; /* partial match */     }  else    return UNMATCH;     /* no match */}/* * check commands at given level with input string. * _cmd: point to first command at this level, return matched cmd * _str: point to current unprocessed input, return next unprocessed */static int parse_command(tinysh_cmd_t **_cmd, uchar **_str){  uchar *str=*_str;  tinysh_cmd_t *cmd;  int matched_len=0;  tinysh_cmd_t *matched_cmd=0;  /* first eliminate first blanks */  while(*str==' ') str++;  if(!*str)    {      *_str=str;      return NULLMATCH; /* end of input */    }    /* first pass: count matches */  for(cmd=*_cmd;cmd;cmd=cmd->next)    {      int ret=strstart(cmd->name,str);      if(ret==FULLMATCH)        {          /* found full match */          while(*str && *str!=' ') str++;           while(*str==' ') str++;          *_str=str;          *_cmd=cmd;          return MATCH;        }      else if (ret==PARTMATCH)        {          if(matched_cmd)            {              *_cmd=matched_cmd;              return AMBIG;            }          else            {              matched_cmd=cmd;            }        }      else /* UNMATCH */        {        }    }  if(matched_cmd)    {      while(*str && *str!=' ') str++;       while(*str==' ') str++;      *_cmd=matched_cmd;      *_str=str;      return MATCH;    }  else    return UNMATCH;}/* create a context from current input line */static void do_context(tinysh_cmd_t *cmd, uchar *str){  while(*str)     context_buffer[cur_context++]=*str++;  context_buffer[cur_context]=0;  cur_cmd_ctx=cmd;}/* execute the given command by calling callback with appropriate  * arguments */static void exec_command(tinysh_cmd_t *cmd, uchar *str){  char *argv[MAX_ARGS];  int argc=0;  int i;/* copy command line to preserve it for history */  for(i=0;i<BUFFER_SIZE;i++)    trash_buffer[i]=str[i];  str=trash_buffer;  /* cut into arguments */  argv[argc++]=cmd->name;  while(*str && argc<MAX_ARGS)    {      while(*str==' ') str++;      if(*str==0)        break;      argv[argc++]=str;      while(*str!=' ' && *str) str++;      if(!*str) break;      *str++=0;    }/* call command function if present */  if(cmd->function)    {      tinysh_arg=cmd->arg;      cmd->function(argc,&argv[0]);    }}/* try to execute the current command line */static int exec_command_line(tinysh_cmd_t *cmd, uchar *_str){  uchar *str=_str;  while(1)    {      int ret;      ret=parse_command(&cmd,&str);      if(ret==MATCH) /* found unique match */        {          if(cmd)            {              if(!cmd->child) /* no sub-command, execute */                {                  exec_command(cmd,str);                  return 0;                }              else                {                  if(*str==0) /* no more input, this is a context */                    {                      do_context(cmd,_str);                      return 0;                    }                  else /* process next command word */                    {                      cmd=cmd->child;                    }                }            }           else /* cmd == 0 */            {              return 0;            }        }      else if(ret==AMBIG)        {          puts("ambiguity: ");          puts(str);          putchar('\n');          return 0;        }      else if(ret==UNMATCH) /* UNMATCH */        {          puts("no match: ");          puts(str);          putchar('\n');          return 0;        }      else /* NULLMATCH */        return 0;    }}/* display help for list of commands */static void display_child_help(tinysh_cmd_t *cmd){  tinysh_cmd_t *cm;  int len=0;  putchar('\n');  for(cm=cmd;cm;cm=cm->next)    if(len<strlen(cm->name))      len=strlen(cm->name);  for(cm=cmd;cm;cm=cm->next)    if(cm->help)      {        int i;        puts(cm->name);        for(i=strlen(cm->name);i<len+2;i++)          putchar(' ');        puts(cm->help);        putchar('\n');      }}/* try to display help for current comand line */static int help_command_line(tinysh_cmd_t *cmd, uchar *_str){  uchar *str=_str;  while(1)    {      int ret;      ret=parse_command(&cmd,&str);      if(ret==MATCH && *str==0) /* found unique match or empty line */        {          tinysh_cmd_t *cm;          int len=0;                        if(cmd->child) /* display sub-commands help */            {              display_child_help(cmd->child);              return 0;            }          else  /* no sub-command, show single help */            {              if(*(str-1)!=' ')                putchar(' ');              if(cmd->usage)                puts(cmd->usage);              puts(": ");              if(cmd->help)                puts(cmd->help);              else                puts("no help available");              putchar('\n');            }          return 0;        }      else if(ret==MATCH && *str)        { /* continue processing the line */          cmd=cmd->child;        }      else if(ret==AMBIG)        {          puts("\nambiguity: ");          puts(str);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -