Follow MIT的6.828 Lab1 & Homework:shell

其实环境还是没装好来着,先跟着作业做一下。。。

第一个作业:Shell

https://pdos.csail.mit.edu/6.828/2014/homework/xv6-shell.html

implementing several features in a small shell, which we will refer to as the 6.828 shell

要求:

Implement simple commands, such as:
$ ls

The parser already builds an execcmd for you, so the only code you have to write is for the ’ ’ case in runcmd. You might find it useful to look at the manual page for exec; type “man 3 exec”, and read about execv. Print an error message when exec fails.

这里写图片描述

看代码

查询C语言API:
IBN Knowledge Center(好高大上的样子)

main

int
main(void)
{
  static char buf[100];
  int fd, r;

  // Read and run input commands.
  while(getcmd(buf, sizeof(buf)) >= 0){ // 简单的判断用户输入是否为空
    if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){
      // Clumsy but will have to do for now.
      // Chdir has no effect on the parent if run in the child.
      // chdir : 切换到目标工作目录
      buf[strlen(buf)-1] = 0;  // chop \n
      if(chdir(buf+3) < 0) // 切换失败(chdir返回-1)
        fprintf(stderr, "cannot cd %s\n", buf+3);
      continue;
    }
    if(fork1() == 0) // 创建成功(fork1()返回0)
      runcmd(parsecmd(buf));
    wait(&r); //wait() — Wait for a child process to end
  }
  exit(0);
}

parsecmd

struct cmd* parsecmd(char *s)
{ // s: 指向缓冲区的指针
  char *es;
  struct cmd *cmd;

  es = s + strlen(s); // es指向缓冲区最后一个字符
  cmd = parseline(&s, es);  //parseline:将字符串转换为结构体'cmd'
  peek(&s, es, ""); // 
  if(s != es){ 
    fprintf(stderr, "leftovers: %s\n", s);
    exit(-1);
  }
  return cmd;
}

runcmd

void runcmd(struct cmd *cmd)
// Execute cmd.  Never returns.
{
  int p[2], r;
  struct execcmd *ecmd;
  struct pipecmd *pcmd;
  struct redircmd *rcmd;

  if(cmd == 0) // 保护:命令为空返回
    exit(0);

  switch(cmd->type){
  default:
    fprintf(stderr, "unknown runcmd\n");
    exit(-1);

  case ' ':
    ecmd = (struct execcmd*)cmd;
    if(ecmd->argv[0] == 0)
      exit(0);
    fprintf(stderr, "exec not implemented\n");
    // Your code here ...
    break;

  case '>':
  case '<':
    rcmd = (struct redircmd*)cmd;
    fprintf(stderr, "redir not implemented\n");
    // Your code here ...
    runcmd(rcmd->cmd);
    break;

  case '|':
    pcmd = (struct pipecmd*)cmd;
    fprintf(stderr, "pipe not implemented\n");
    // Your code here ...
    break;
  }    
  exit(0);
}

getcmd

int getcmd(char *buf, int nbuf)
{

  if (isatty(fileno(stdin))) // 不知道为什么是stdin,
    fprintf(stdout, "6.828$ "); // 反正结果是不断输出prompt..
  memset(buf, 0, nbuf); // 清空缓存
  fgets(buf, nbuf, stdin); // 得到输入
  if(buf[0] == 0) // EOF
    return -1;
  return 0;
}

用到的API

strrchr() — Find Last Occurrence of Character in String,

Returns a pointer to the last occurrence of c in string.

A built-in function that finds the last occurrence of c (converted to a char) in string. The ending null character is considered part of the string.

fileno()

fileno() — Get the file descriptor from an open stream
Returned value
If successful, fileno() returns the file descriptor number associated with an open HFS stream (that is, one opened with fopen() or freopen()).

isatty() - Test if descriptor represents a terminal

Format

#define _POSIX_SOURCE
#include <unistd.h>

int isatty(int fildes);

Returned value
isatty() returns 1 if the given file descriptor is a terminal, or 0 otherwise.

fgets() — Read a string from a stream

char *fgets(char * __restrict__string, int n, FILE * __restrict__stream);

Reads bytes from a stream pointed to by stream into an array pointed to by string, starting at the position indicated by the file position indicator.
Reading continues until the number of characters read is equal to n-1, or until a newline character (\n), or until the end of the stream, whichever comes first. The fgets() function stores the result in string and adds a NULL character (\0) to the end of the string. The string includes the newline character, if read.
Returned value
If successful, fgets() returns a pointer to the string buffer.
If unsuccessful, fgets() returns NULL to indicate failure.

写代码

看着看着代码发现嵌套好多,而且其实没必要弄懂每个函数在干嘛,因为其实只需要补全

// Execute cmd.  Never returns.
void  runcmd(struct cmd *cmd)
{
...
  case ' ':
    ecmd = (struct execcmd*)cmd;
    if(ecmd->argv[0] == 0)
      exit(0);
    fprintf(stdout, "building...%s\n",ecmd->argv[0]);
    // Your code here ...
    execution(ecmd->argv[0]);
    break;

  case '>':
  case '<':
    rcmd = (struct redircmd*)cmd;
    fprintf(stderr, "redir not implemented\n");
    // Your code here ...
    runcmd(rcmd->cmd);
    break;

  case '|':
    pcmd = (struct pipecmd*)cmd;
    fprintf(stderr, "pipe not implemented\n");
    // Your code here ...
    break;
  }    
  exit(0);
}

编写

void execution(char* exccmd) {

    if (strcmp(exccmd, "ls")==0) {
    // ls : 列出当前目录下所有文件名
     char current_address[100];  
    memset(current_address, 0, 100);  
    getcwd(current_address, 100); //获取当前路径  
    strcat(current_address, "\\*");  
    /*

    还没写完

    */
    }
}

要用到的API

_findfirst

intptr_t _findfirst(  
   const char *filespec,  
   struct _finddata_t *fileinfo   
); 

Parameters
filespec
Target file specification (can include wildcard characters).
fileinfo
File information buffer.
Return Value
If successful, _findfirst returns a unique search handle identifying the file or group of files that match the filespec specification, which can be used in a subsequent call to _findnext or to _findclose. Otherwise, _findfirst returns –1 and sets errno to one of the following values.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值