操作系统实验报告shell程序.docx
《操作系统实验报告shell程序.docx》由会员分享,可在线阅读,更多相关《操作系统实验报告shell程序.docx(22页珍藏版)》请在冰豆网上搜索。
操作系统实验报告shell程序
操作系统实习报告日期:
实习题目:
shell程序
完成人
姓名:
组号:
学号
实习内容简要描述
本实验要实现一个简单的命令解释器,也就是Linux中的shell程序。
实验程序起名为ysh,要求其设计类似于目前流行的shell解释程序,如bash、csh、tcsh,但不需要具备那么复杂的功能。
ysh程序应当具有如下一些重要的特征:
能够执行外部程序命令,命令可以带参数。
能够执行fg、bg、cd、history、exit等内部命令。
使用管道和输入输出重定向。
支持前后台作业,提供作业控制功能,包括打印作业的清单,改变
当前运行作业的前台/后台状态,以及控制作业的挂起、中止和继续
运行。
除此之外,在这个实验中还须做到:
使用make工具建立工程。
使用调试器gdb来调试程序。
提供清晰、详细的设计文档和解决方案。
主要代码结构
(附注释)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include"ysh.h"
#defineNO_PIPE-1
#defineFD_READ0
#defineFD_WRITE1
intis_founded(char*cmd)
{
intk=0;
while(envpath[k]!
=NULL){strcpy(buf,envpath[k]);
strcat(buf,cmd);
if(access(buf,F_OK)==0){return1;
}k++;
}
return0;
}
voidgetenviron(intn,char*s)
{inti=0,j=0,k=0;
charc;
charbuff[80];
char*p;
while((c=s[i])!
='='){buff[i++]=c;
}buff[i++]='\0';
if(strcmp(buff,"PATH")==0){
while(s[i]!
='\0'){if(s[i]==':
'){
buff[j++]='/';
buff[j]='\0';
p=(char*)malloc(strlen(buff)+1);
strcpy(p,buff);
envpath[k++]=p;
envpath[k]=NULL;
j=0;
i++;
}else{
buff[j]=s[i];
j++;
i++;
}
}
}else
fprintf(stderr,"Nomatch");
}
intgetline(intfd,char*buf)
{inti=0;
charc;
while(read(fd,&c,1)){
buf[i++]=c;
if(c=='\n'){
buf[i-1]='\0';
returni;
}
}returni;
}
voidinit_environ()
{
intfd,n;
charbuf[80];
if((fd=open("ysh_profile",O_RDONLY,660))==-1){
printf("initenvironvariableerror!
\n");
exit
(1);
}
while((n=getline(fd,buf))!
=0){
getenviron(n,buf);
}
envhis.start=0;
envhis.end=0;
head=end=NULL;
}
intpipel(char*input,intlen)
{char*argv[10][30];
char*filename[0];
inti,j,k,is_bg=0;
intli_cmd=0;
intfd[10][1],pipe_in=-1;
intpipe_out=-1,flag=0;
pid_tpid;
for(i=0,j=0,k=0;i<=len;i++){
if((input[i]=='')||(input[i]=='\t')||(input[i]=='\0')||
(input[i]=='|')||(input[i]=='>')||(input[i]=='\n')){
if((input[i]=='|')||(input[i]=='>')){
if(input[i]=='>'){
flag=1;
}
if(j>0){
buf[j++]='\0';
argv[li_cmd][k]=(char*)malloc(sizeof(char)*j);
strcpy(argv[li_cmd][k],buf);
k++;
}
argv[li_cmd][k]=(char*)0;
li_cmd++;
k=0;
j=0;
}
if(j==0){
continue;
}else{
buf[j++]='\0';
if(flag==0){
argv[li_cmd][k]=(char*)malloc(sizeof(char)*j);
strcpy(argv[li_cmd][k],buf);
k++;
}else{
filename[0]=(char*)malloc(sizeof(char)*j);
strcpy(filename[0],buf);
}
}
j=0;
}else{
if((input[i]=='&')&&(input[i]=='\0')){
is_bg=1;
continue;
}
buf[j++]=input[i];
}
}
argv[li_cmd][k++]=NULL;
for(i=0;i<=10;i++){
fd[i][FD_READ]=NO_PIPE;
fd[i][FD_WRITE]=NO_PIPE;
}
for(i=0;iif(pipe(fd[i])==-1){
printf("Cannotopenpipe!
\n");
return0;
}
}
for(i=0;iif(is_founded(argv[i][0])==0){
printf("Cannotfoundcommand!
\n");
break;
}
}
if(i!
=0){
pipe_in=fd[i-1][FD_READ];
}else{
pipe_in=NO_PIPE;
}
if(i!
=li_cmd){
pipe_out=fd[i][FD_WRITE];
}else
{if(flag==1){
if((pipe_out=open(filename[0],O_WRONLY|O_CREAT|O_TRUNC,
S_IRUSR|S_IWUSR))==-1){
printf("Cannotopen%s\n",filename[0]);
return0;
}
}else{
pipe_out=NO_PIPE;
}
}
if((pid=fork())<0){
printf("Forkfailed!
\n");
return0;
}
if(pid==0){
if(pipe_in==NO_PIPE){
close(pipe_in);
}
if(pipe_out==NO_PIPE){
close(pipe_out);
}
if(pipe_out!
=NO_PIPE){
dup2(pipe_out,1);
close(pipe_out);
}
if(pipe_in!
=NO_PIPE){
dup2(pipe_in,0);
close(pipe_in);
}
execv(buf,argv[i]);
}else{
if(is_bg==0){
waitpid(pid,NULL,0);
}
close(pipe_in);
close(pipe_out);
}
return0;
}
voidadd_history(char*inputcmd)
{
envhis.end=(envhis.end+1)%HISNUM;
if(envhis.end==envhis.start){
envhis.start=(envhis.start+1)%HISNUM;
}
strcpy(envhis.his_cmd[envhis.end],inputcmd);
}
voidhistory_cmd()
{
inti,j=0;
if(envhis.start==envhis.end){
return;
}
elseif(envhis.startfor(i=envhis.start+1;i<=envhis.end;i++){
printf("%d\t%s\n",j,envhis.his_cmd[i]);
j++;
}
}else{
for(i=envhis.start+1;iprintf("%d\t%s\n",j,envhis.his_cmd[i]);
j++;
}
for(i=0;i<=envhis.end;i++){
printf("%d\t%s\n",j,envhis.his_cmd[i]);
j++;
}
}
}
voidcd_cmd(char*route)
{
if(route!
=NULL){
if(chdir(route)<0)
printf("cd;%sErrorfileordirectory!
\n",route);
}
}
voidjobs_cmd()
{
structNODE*p;
inti=1;
p=head;
if(head!
=NULL){
do
{
printf("%d%d%s\t%s\n",i,p->pid,p->state,p->cmd);
i++;
p=p->link;
}while(p!
=NULL);
}
else
printf("Nojobs!
\n");
}
voidadd_node(char*input_cmd,intnode_pid)
{
structNODE*p;
p=(structNODE*)malloc(sizeof(structNODE));
p->pid=node_pid;
strcpy(p->state,input_cmd);
strcpy(p->state,"running");
p->link=NULL;
if(head==NULL){
head=p;
end=p;
}else{
end->link=p;
end=p;
}
}
voiddel_node(intsig,siginfo_t*sip)
{
structNODE*q;
structNODE*p;
intid;
if(sig_z==1){
sig_z=0;
gotoout;
}
id=sip->si_pid;
p=q=head;
if(head==NULL)
gotoout;
while(p->pid!
=id&&p->link!
=NULL){
p=p->link;
}
if(p->pid!
=id)
gotoout;
if(p==head)
head=head->link;
else{
while(q->link!
=p){
q=q->link;
}
if(p==end){
end=q;
q->link=NULL;
}else{
q->link=p->link;
}
}
free(p);
out:
return;
}
voidsetflag(){
sig_flag=1;
}
voidctrl_z()
{
structNODE*p;
inti=1;
if(pid1==0){
gotoout;
}
if(head!
=NULL){
p=head;
while((p->pid!
=pid1)&&(p->link!
=NULL)){
p=p->link;
}
if(p->pid==pid1){
strcpy(p->state,"stopped");
}else
{
add_node(input,pid1);
strcpy(end->state,"stopped");
}
}
else
{
add_node(input,pid1);
strcpy(end->state,"stopped");
}
sig_z=1;
kill(pid1,SIGSTOP);
for(p=head;p->pid!
=pid1;p=p->link)
{
i++;
}
printf("[%d]\t%s\t%s\n",i,end->state,end->cmd);
pid1=0;
out:
return;
}
voidbg_cmd(intjob_num)
{
structNODE*p;
inti=0;
p=head;
for(i=1;i{
p=p->link;
}
kill(p->pid,SIGCONT);
strcpy(p->state,"running");
}
voidfg_cmd(intjob_num)
{
structNODE*p;
inti=0;
p=head;
for(i=1;i{
p=p->link;
}
strcpy(p->state,"running");
strcpy(input,p->cmd);
pid1=p->pid;
signal(SIGTSTP,ctrl_z);
kill(p->pid,SIGCONT);
waitpid(p->pid,NULL,0);
}
intmain()
{
init_environ();
while
(1)
{
charc;
char*arg[20];
inti=0,j=0,k=0;
intis_pr=0,is_bg=0;
intinput_len=0,path;
intpid=0,status=0;
structsigactionaction;
action.sa_sigaction=del_node;
sigfillset(&action.sa_mask);
action.sa_flags=SA_SIGINFO;
sigaction(SIGCHLD,&action,NULL);
signal(SIGTSTP,ctrl_z);
path=get_current_dir_name();
printf("ysh@%s",path);
while(((c=getchar())=='')||(c=='\t')||(c==EOF))
{
;
}
if(c=='\n')
{
continue;
}
while(c!
='\n')
{
buf[input_len++]=c;
c=getchar();
}
buf[input_len]='\0';
input=(char*)malloc(sizeof(char)*(input_len+1));
strcpy(input,buf);
for(i=0,j=0,k=0;i<=input_len;i++)
{
if((input[i]=='<')||(input[i]=='>')||(input[i]=='|'))
{
if(input[i]=='|')
{
pipel(input,input_len);
add_history(input);
free(input);
}
else
{
redirect(input,input_len);
add_history(input);
free(input);
}
is_pr=1;
break;
}
}
if(is_pr==1)
{
continue;
}
for(i=0,j=0,k=0;i<=input_len;i++)
{
if((input[i]=='')||(input[i]=='\0'))
{
if(j==0)
{
continue;
}
else
{
buf[j++]='\0';
arg[k]=(char*)malloc(sizeof(char)*j);
strcpy(arg[k++],buf);
j=0;
}
}
else
{
if((input[i]=='&')&&(input[i+1]=='\0'))
{
is_bg=1;
continue;
}
buf[j++]=input[i];
}
}
if(strcmp(arg[0],"exit")==0)
{
add_history(input);
printf("Byebye!
\n");
free(input);
break;
}
if(strcmp(arg[0],"history")==0)
{
add_history(input);
history_cmd();
free(input);
continue;
}
if(strcmp(arg[0],"cd")==0)
{
add_history(input);
for(i=3,j=0;i<=input_len;i++)
{
buf[j++]=input[i];
}
buf[j]='\0';
arg[1]=(char*)malloc(sizeof(char)*j);
strcpy(arg[1],buf);
cd_cmd(arg[1]);
free(input);
continue;
}
if(strcmp(arg[0],"jobs")==0)
{
add_history(input);
jobs_cmd();
free(input);
continue;
}
if(strcmp(arg[0],"bg")==0)
{
add_history(input);
for(i=0;i<=input_len;i++)
{
if(input[i]=='%')
{
break;
}
}
i++;
for(;i<=input_len;i++)
{
buf[j++]=input[i];
}
buf[j]='\0';
arg[1]=(char*)malloc(sizeof(char)*j);
strcpy(arg[1],buf);
bg_cmd(atoi(arg[1]));
free(input);
continue;
}
if(strcmp(arg[0],"fg")==0)
{
add_history(input);
for(i=0;i<=input_len;i++){
if(input[i]=='%'){
break;
}
}
i++;
for(;i<=input_len;i++)
{
buf[j++]=input[i];
}
buf[j]='\0';
arg[1]=(char*)malloc(sizeof(char)*j);
strcpy(arg[1],buf);
fg_cmd(atoi(arg[1]));
free(input);
continue;
}
if(is_pr==0)
{
arg[k]=(char*)malloc(sizeof(char));
arg[k]=NULL;
if(is_founded(arg[0])==0)
{
printf("Thiscommandisnotfouned!
\n");
for(i=0;i<=k;i++)
{
free(arg[i]);