不知道这个对不对,在别人的指点下写的
#define SIZE 100
#define BUFFSIZE 200
#define BUFFERSIZE 1024
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/wait.h>
#include<math.h>
#include<malloc.h>
#include<signal.h>
#include<stdlib.h>
//*************************************** **********************/
typedef struct SH_HISTORY //*用循环链表存储用过的SH_HISTORY命令 */
{
int start;
int end;
char command_his[SIZE][100];
}SH_HISTORY;
typedef struct NODE // /*把作业用链表保存起来*/
{
pid_t pid; //*进程号*/
char cmd[100]; // /*命令字符*/
char state[10]; //*状态*/
struct NODE *next; //*指向下一接点的指针*/
}NODE;
char *envpath[10],buff[BUFFSIZE],*input=NULL;
pid_t pid1=0;
int sig_flag=0,sig_z=0;
SH_HISTORY sh_his;
NODE *head,*end;
//*******************声明程序中用到的函数****************************/
int found_cmd(); //*查找命令函数*/
int getline(); //*读取一行的函数*/
void init_environ(); //*初始化环境变量*/
void history_add(); //*记录history命令的函数*/
void command_history();//*显示history命令的函数*/
void command_cd();//*处理cd命令的函数*/
void command_jobs();//*处理jobs命令的函数*/
void setflag();//*将标志位置1的函数*/
void getenviron();//*初始化查找路径的函数*/
void ctrl_z(); //*处理用户按下ctrl-z是时的函数*/
void command_echo();//*处理echo命令的函数*/
void dele_node();//*向jobs命令的链表中删除节点的函数*/
void add_node();//*向jobs命令的链表中增加节点的函数*/
void print_help(); //*处理help命令的函数*/
void command_mkdir(); //*建立目录的函数*/
void command_rmdir();//*撤销目录的函数*/
void command_environ(); //*处理environ命令的函数*/
//*******************************main************************************/
main()
{
init_environ(); //*初始化环境变量,将查找路径置于envpath[]中*/
while(1)
{
char ch,*argment[20];
int i=0,j=0,k=0,is_pr=0,is_bg=0,input_len=0,pid=0,path,status=0,tmp=0;
// ***************************设置signal信号*************************/
struct sigaction action;
action.sa_sigaction=dele_node;
sigfillset(&action.sa_mask);
action.sa_flags=SA_SIGINFO;
sigaction(SIGCHLD,&action,NULL);
signal(SIGTSTP,ctrl_z);
//********************打印提示符**********************/
path=get_current_dir_name();
printf("<shell@%s> ",path);
//***********获取用户输入***************/
while((ch=getchar())==' '||ch=='\t'||ch==EOF) //*跳过空格等无用信息*/
if(ch=='\n') continue; //*输入为空时结束本次循环,打印提示符*/
while(ch!='\n')
{
buff[input_len++]=ch;
ch=getchar();
}
buff[input_len]='\0'; //*加上串结束符*/
//*分配动态存储空间,将命令从缓冲区复制到input中*/
input=(char *)malloc(sizeof(char)*(input_len+1));
strcpy(input,buff); // *将命令复制到input中*/
// ******************************解析指令**************************/
//***************普通命令****************/
if(is_pr==1) continue;//*如果is_pr==1,则执行普通命令,否则,执行管道命令*/
for(i=0,j=0,k=0;i<input_len+1;i++)
{
if(input==' '||input=='\0') ///* 清除空格和结束符*/
{
if(j==0) //*略去连在一起的多个空格*/
continue;
else
{
buff[j++]='\0';
argment[k]=(char *)malloc(sizeof(char)*j);
strcpy(argment[k++],buff);//*将指令或参数复制到argment中*/
j=0;
}
}
else{ //*如果字符串最后是&,将后台命令标志置1*/
if(input=='&'&&input=='\0')
{
is_bg=1;
continue;
}
buff[j++]=input;
}
}
// ***************************内部命令****************************/
if(strcmp(argment[0],"environ")==0||strcmp(argment[0],"en")==0)
{
history_add(input);
command_environ();
free(input);
continue;
}
if(strcmp(argment[0],"rmdir")==0)
{
history_add(input);
for(i=6,j=0;i<=input_len;i++)
buff[j++]=input;
buff[j]='\0';
argment[1]=(char *)malloc(sizeof(char)*j);
strcpy(argment[1],buff);
command_rmdir(argment[1]);
free(input);
continue;
}
if(strcmp(argment[0],"mkdir")==0)
{
history_add(input);
for(i=6,j=0;i<=input_len;i++)
buff[j++]=input;
buff[j]='\0';
argment[1]=(char *)malloc(sizeof(char)*j);
strcpy(argment[1],buff);
command_mkdir(argment[1]);
free(input);
continue;
}
if(strcmp(argment[0],"help")==0)
{
history_add(input);
print_help();
free(input);
continue;
}
// *********exit,bye,quit,退出*************/
if(strcmp(argment[0],"exit")==0||strcmp(argment[0],"quit")==0||strcmp(argment[0],"bye")==0) {
history_add(input);
printf("bye bye!\n");
free(input);
exit(0);
break;
}
// *************history命令,显示history数组中保存的历史命令************/
if(strcmp(argment[0],"history")==0)
{
history_add(input);
command_history();
free(input);
continue;
}
//*********echo命令, 显示输入过的字符串***************/
if(strcmp(argment[0],"echo")==0){
history_add(input);
for(i=0;i<=input_len;i++)
{
if(input==' ')
break;
}
i++;
for(;i<=input_len;i++)
buff[j++]=input;
buff[j]='\0';
argment[1]=(char *)malloc(sizeof(char)*j);
strcpy(argment[1],buff);
command_echo(argment[1]);
free(input);
continue;
}
/**********************************************/
if(strcmp(argment[0],"cd")==0){
history_add(input);
for(i=3,j=0;i<=input_len;i++)
buff[j++]=input;
buff[j]='\0';
argment[1]=(char *)malloc(sizeof(char)*j);
strcpy(argment[1],buff);
command_cd(argment[1]);
free(input);
continue;
}
/********************************************/
if(strcmp(argment[0],"jobs")==0){
history_add(input);
command_jobs();
free(input);
continue;
}
//*********寻找命令文件**********/
if(is_pr==0)
{
argment[k]=(char *)malloc(sizeof(char));
argment[k]=NULL;
if(found_cmd(argment[0])==0)
{
printf("This is an inavilable command!\n");
for(i=0;i<=k;i++){
free(argment);
continue;
}
}
history_add(input);
//************** 执行命令*****************/
if((pid=fork())==0){ /*子进程*/
while(sig_flag==0)
signal(SIGUSR1,setflag);
sig_flag=0;
execv(buff,argment);
}
else{
pid1=pid;
add_node(input,pid1);
kill(pid,SIGUSR1);
pid1=0;
waitpid(pid,&status,0);
}
for(i=0;i<k;i++)
free(argment);
free(input);
}
}
}
/***********************主程序完成********************/
/*************函数定义*****************/
void init_environ()
{
int fd,n,i;
char buff[80];
if((fd=open("sh_profile",O_RDONLY,660))==-1)
{
printf("init wrong!");
exit(1);
while(n=getline(fd,buff))
getenviron(n,buff);
sh_his.start=0;
sh_his.end=0;
head=end=NULL;
}
//***************查找命令文件的函数********************************/
int found_cmd(char *cmd)
{
int k=0;
while(envpath[k]!=NULL){ //*查找路径已在程序初始化时设定在envpath中*/
strcpy(buff,envpath[k]);
strcat(buff,cmd);
if(access(buff,F_OK)==0) //*文件被找到*/
return 1;
k++;
}
return 0;
}
/********************************************************/
void history_add(char *inputcmd)
{
sh_his.end=(sh_his.end+1)%SIZE; //*end前移一位*/
if(sh_his.end==sh_his.start) //*end和 start同指向同一数组*/
sh_his.start=(sh_his.start+1)%SIZE; //*start前移一位*/
strcpy(sh_his.command_his[sh_his.end],inputcmd);
//*将命令复制到指向end的数组中*/
}
//*************************command-history *************************************/
void command_history()
{
int i,count=0;
if(sh_his.start==sh_his.end) //*循环数组为空*/
return;
else if(sh_his.start<sh_his.end)
{
printf("id command \n");
for(i=sh_his.start+1;i<sh_his.end;i++)
//*显示history命令数组中start+1到end个命令*/
{
printf("%d\t%s\n",count,sh_his.command_his);
count++;
}
}
else {
printf("id command \n");
for(i=sh_his.start+1;i<SIZE;i++)
//*显示history命令数组中start+1到SIZE个命令*/
{
printf("%d\t%s\n",count,sh_his.command_his);
count++;
}
for(i=0;i<sh_his.end;i++) /*显示0~end个命令 */
{
printf("%d\t%s\n",count,sh_his.command_his);
count++;
}
}
}
/************************ *********************************/
void command_cd (char *route)
{
if(route!=NULL)//*路径不为空*/
if(chdir(route)<0) //*系统调用chdir函数,达到改变当前路径的目的*/
printf("%s file error or didn't exist!\n",route);
}
/**************************command-jobs**************************************/
void command_jobs()
{
NODE *p;
int i=1;
p=head;
if(head!=NULL)
{
printf("id pid state command\n");
printf("%d %d %s\t %s \n",i,p->pid,p->state,p->cmd);
i++;
p=p->next;
}
else
printf("no process!\n");
}
/**************************add_node***********************************/
void add_node(char *input_cmd,int node_pid)
{
NODE *p;
p=(NODE *)malloc(sizeof(NODE));
p->pid=node_pid;
strcpy(p->cmd,input_cmd);
strcpy(p->state,"running");
p->next=NULL;
if(head==NULL)
{
head=p;
end=p;
}
else
{
end->next=p;
end=p;
}
}
//************** dele_node *************************/
void dele_node(int sig,siginfo_t *sif)
{
NODE *q,*p;
int id;
if(sig_z==1)
{
sig_z=0;
return;
}
id=sif->si_pid;
p=q=head;
if(head==NULL)
return;
while(p->pid!=id&&p->next!=NULL)
{
p=p->next;
if(p->pid!=id)
return;
if(p==head)
head=head->next;
else
{
while(q->next!=p)
q=q->next;
if(p==end)
{
end=q;
q->next=NULL;
}
else q->next=p->next;
}
free(q);
}
}
/****************setflag*************************/
void setflag()
{
sig_flag=1;
}
/******************getline**************************/
int getline(int fd,char *buf)
{
int i=0;
char c;
while(read(fd,&c,1))
{
buf[i++]=c;
if(c=='\n')
{
buf[i-1]='\n';
return i;
}
}
return i;
}
/***********************getenviron****************************/
void getenviron(int n,char *s)
{
int i=0,count=0,k=0;
char c,buff1[80],*p;
while((c=s)!='=')
buff1[i++]=c;
buff1[i++]='\0';
if(strcmp(buff1,"
ATH")==0)
{
while(s!='\0')
{
if(s==':')
{
buff1[count++]='/';
buff1[count]='\0';
p=(char *)malloc(strlen(buff1)+1);
strcpy(p,buff1);
envpath[k++]=p;
envpath[k]=NULL;
count=0;
i++;
}
else
{
buff1[count]=s;
count++;
i++;
}
}
}
else
fprintf(stderr,"no match\n");
}
/******************ctrl-z***********************************/
void ctrl_z()
{
NODE *p;
int i=1;
if(pid1==0) return;
if(head!=NULL)
{
p=head;
while(p->pid!=pid1&&p->next!=NULL)
p=p->next;
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->next)
i++;
printf("[%d]\t%s\t%s\n",i,end->state,end->cmd);
pid1=0;
}
/*定*/
/*****************echo command**************************/
void command_echo(char *arg){
int i;
if(arg!=NULL){
for(i=0;i<strlen(arg);i++)
printf("%c",arg);
printf("\n");
}
}
/*********************************************************/
void print_help(){
printf(" help -- show the all command\n");
printf(" exit or quit or bye -- exit \n ");
printf(" cd -- show the path\n");
printf(" history -- show the used command\n");
printf(" jobs -- show the running's process\n");
printf(" echo < > show the letter \n");
printf(" mkdir filename -- create a new file!\n");
printf(" rmdir filename -- delete the file!\n");
printf(" en or environ -- show the PATH!\n");
}
/***********************************************************/
void command_mkdir(const char *f){
if(f!=NULL)
if(mkdir(f,660)<0)
printf("can't create file!\n");
}
/**************************************************************/
void command_rmdir(char *fn){
if(fn!=NULL)
if(rmdir(fn)<0)
printf("can't delete the file!\n");
}
/**********************environ**********************************/
void command_environ(){
int fd,read_num,i;
char *buffer;
fd=open("sh_profile",O_RDONLY,00700);
if(fd==-1){
printf("init wrong!");
exit(1);
}
else {
buffer=(char *)malloc(sizeof(char)*BUFFERSIZE);
read_num=read(fd,buffer,BUFFERSIZE);
}
for(i=0;i<BUFFERSIZE;i++)
printf("%c",buffer);
printf("\n");}