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.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章