get shell

实现nachos的系统调用：
SysWrite:显示提示符与shell版本信息
SysRead: 读取n个字符到缓存buffer
SysExec,SysJoin:执行命令，如不存在则打印错误信息
SysStrncmp:比较两个字符串的前n个字符，判断用户是否输入了exit退出命令

修改日志：

1.syscall.h
add code:
#define SC_Strncmp 43   //define a system call code to tell the kernel
which system call is being asked for

/*
*compare str and buffer to find if buffer is "exit" command
*/
int Strncmp(char *buffer,char* str,int size);

2.ksyscall.h
add code:

#define SHELL "/bin/sh"     //to use waitpid in Linux
//#define EPERAM

#include "sys/types.h"
#include "sys/wait.h"

/*
* Send length of size bytes in id to buffer
*/
int SysWrite(char* buffer,int size,OpenFileId id)
{
return write(id,buffer,(size_t)size);
}

/*
* Send length of size bytes in buffer to file at id
*/
int SysRead(char* buffer, int size, OpenFileId id)
{
return read(id , buffer , (size_t)size);
}
/*
* Creat a child process, and execute the path that SHELL stand for with
"-c".
* It's work like: /bin/sh -c filename
*/
SpaceId SysExec(char* exec_name)
{
pid_t child;
child = vfork();
if(child==0)
{
execl(SHELL,SHELL,"-c",exec_name,NULL);
_exit(EXIT_FAILURE);
}
else if(child<0)
{
return EPERM;
}
return (SpaceId)child;
}
/*
* join a new process and pause current process until receive a signal or
the new
* process stop.
*/
int SysJoin(SpaceId id)
{
return waitpid((pid_t)id,(int*)0,0);
}
/*
*compare str and buffer to find if buffer is "exit" command
*/
int SysStrncmp(char* buffer,char* str, int n)
{
return strncmp(buffer,str,(size_t)n);
}

3.exception.cc

case SC_Write:
DEBUG(dbgSys,"Write from buffer to
consoleOutput"<<kernel->machine->ReadRegister(4)<<kernel->machine->ReadRegister(5)<<kernel->machine->ReadRegister(6)<<"\n");
char wbuffer[60];//the buffer to store information from  userprogram
int size ;
size=(int)kernel->machine->ReadRegister(5);//register 5 save the address
of next process
OpenFileId printOut;
printOut= (OpenFileId)kernel->machine->ReadRegister(6);//The id of the
file that will be write.
int addressOne;
addressOne=(int)kernel->machine->ReadRegister(4);//register 4 save the
address of prev process
int i;
i=0;
do{
kernel->machine->ReadMem(addressOne++,1,(int*)&wbuffer[i++]);
}while(i<size);
int n1;
n1=SysWrite((char*)wbuffer,size,printOut);//write wbuffer to printOut
kernel->machine->WriteRegister(2,n1);
/* Modify return point */
{
/* set previous programm counter (debugging only)*/
kernel->machine->WriteRegister(PrevPCReg,
kernel->machine->ReadRegister(PCReg));
/* set programm counter to next instruction (all Instructions are 4 byte
wide)*/
kernel->machine->WriteRegister(PCReg,
kernel->machine->ReadRegister(PCReg) + 4);
/* set next programm counter for brach execution */
kernel->machine->WriteRegister(NextPCReg,
kernel->machine->ReadRegister(PCReg)+4);
} return;
ASSERTNOTREACHED();
break;

case SC_Read:
DEBUG(dbgSys, "read from buffer" << kernel->machine->ReadRegister(4) <<
kernel->machine->ReadRegister(5)<< kernel->machine->ReadRegister(6) <<
"\n");
int rsize ;
rsize=(int)kernel->machine->ReadRegister(5);//register 5 save the
address of next process
OpenFileId enterIn;
enterIn = (OpenFileId)kernel->machine->ReadRegister(6);//The id of the
file that will be write.
char addressTwo;
addressTwo = (char)kernel->machine->ReadRegister(4);//register 4 save
the address of prev process
int local ;
local= (int)kernel->machine->ReadRegister(4);
int n2 ;
n2= SysRead(&addressTwo,rsize,enterIn);//read from addressTwo to enterIn
kernel->machine->WriteMem(local,1,(int)addressTwo);
kernel->machine->WriteRegister(2,n2);
/* Modify return point */
{
/* set previous programm counter (debugging only)*/
kernel->machine->WriteRegister(PrevPCReg,
kernel->machine->ReadRegister(PCReg));
/* set programm counter to next instruction (all Instructions are 4 byte
wide)*/
kernel->machine->WriteRegister(PCReg,
kernel->machine->ReadRegister(PCReg) + 4);
/* set next programm counter for brach execution */
kernel->machine->WriteRegister(NextPCReg,
kernel->machine->ReadRegister(PCReg)+4);
}
return;
ASSERTNOTREACHED();
break;

case SC_Exec:
DEBUG(dbgSys,"execute a
command"<<kernel->machine->ReadRegister(4)<<"\n");
char ebuffer[60];
int addressThree;
addressThree = kernel->machine->ReadRegister(4);//register 4 save the
address of prev process
int c;
c = 0;
do{
kernel->machine->ReadMem(addressThree++,1,(int*)&ebuffer[c++]);
}while(c<60);
kernel->machine->WriteRegister(2,SysExec(ebuffer));
/* Modify return point */
{
/* set previous programm counter (debugging only)*/
kernel->machine->WriteRegister(PrevPCReg,
kernel->machine->ReadRegister(PCReg));
/* set programm counter to next instruction (all Instructions are 4 byte
wide)*/
kernel->machine->WriteRegister(PCReg,
kernel->machine->ReadRegister(PCReg) + 4);
/* set next programm counter for brach execution */
kernel->machine->WriteRegister(NextPCReg,
kernel->machine->ReadRegister(PCReg)+4);
}
return;
ASSERTNOTREACHED();
break;

case SC_Join:
DEBUG(dbgSys,"jion "<<kernel->machine->ReadRegister(4)<<"\n");

kernel->machine->WriteRegister(2,SysJoin((SpaceId)kernel->machine->ReadRegister(4)));
/* Modify return point */
{
/* set previous programm counter (debugging only)*/
kernel->machine->WriteRegister(PrevPCReg,
kernel->machine->ReadRegister(PCReg));
/* set programm counter to next instruction (all Instructions are 4 byte
wide)*/
kernel->machine->WriteRegister(PCReg,
kernel->machine->ReadRegister(PCReg) + 4);
/* set next programm counter for brach execution */
kernel->machine->WriteRegister(NextPCReg,
kernel->machine->ReadRegister(PCReg)+4);
}
Return;
ASSERTNOTREACHED();
break;
case SC_Strncmp:
DEBUG(dbgSys, "compare two string " << kernel->machine->ReadRegister(4)
<<kernel->machine->ReadRegister(5) << kernel->machine->ReadRegister(6)
<< "\n");
int addressFour;
addressFour = kernel->machine->ReadRegister(4);//register 4 save the
address of prev process
int addressFive;
addressFive = kernel->machine->ReadRegister(5);//register 5 save the
address of next process
char str1buffer[60];
char str2buffer[60];
int d,e;
d= 0;
e=0;
do{
kernel->machine->ReadMem(addressFour++,1,(int*)&str1buffer[d++]);//read
form addressFour to str1buffer
}while(d<60);
--addressFour;
do{
kernel->machine->ReadMem(addressFive++,1,(int*)&str2buffer[e++]);
}while(e<60);
--addressFive;
int n3;
n=SysStrncmp(str1buffer,str2buffer,kernel->machine->ReadRegister(6));
kernel->machine->WriteRegister(2,n3);
/* Modify return point */
{
/* set previous programm counter (debugging only)*/
kernel->machine->WriteRegister(PrevPCReg,
kernel->machine->ReadRegister(PCReg));
/* set programm counter to next instruction (all Instructions are 4 byte
wide)*/
kernel->machine->WriteRegister(PCReg,
kernel->machine->ReadRegister(PCReg) + 4);
/* set next programm counter for brach execution */
kernel->machine->WriteRegister(NextPCReg,
kernel->machine->ReadRegister(PCReg)+4);
}
return;
ASSERTNOTREACHED();
break;

4.shell.c
add code:
Write( "<-My shell ver 1.0->\n", 21, output);

if(Strncmp(buffer,"exit",4)==0)
{
Halt();
}

int Strncmp(char *buffer,char* str,int size)
{
int i;
OpenFileId output=ConsoleOutput;
for(i = 0 ; i<size; i++ )
{
if((buffer[i++])!=(str[i++]))
return 1;
}
return 0;
}
/*
*5.  start.s
*add code:
* .globl Strncmp
*  .ent  Strncmp
*Strncmp: addiu $2,$0,SC_Strncmp
* syscall j  $31
* .end  Strncmp
* .globl Exit
* .ent  Exit
*/