其实环境还是没装好来着,先跟着作业做一下。。。
第一个作业: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:
$ lsThe parser already builds an
execcmd
for you, so the only code you have to write is for the ’ ’ case inruncmd
. You might find it useful to look at the manual page for exec; type “man 3 exec”, and read aboutexecv
. 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.