📄 ush.c
字号:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <string.h>#include <dirent.h>#include <sys/wait.h>#include <sys/types.h>#include <sys/stat.h>#include <pwd.h>#include <grp.h>char* buf=NULL; /* 缓冲区 ,用于存储命令行字符串 */int bufsize= 0; /* 缓冲区大小 */char* arg_list[100]={0}; /* 用数组实现的命令行参数列表,每一个元素代表一个命令行参数,数组最大值为100,即命令行参数不能超过100个 */int idex=0; /* 命令行参数数组索引 */int special_cmd=0; /* 指示命令类型的整形值 : 1,2 为重定向 3为管道*/int token_num=0; /* 命令行参数个数*/static short octarray[9]={ 0400,0200,0100,0040,0020,0010,0004,0002,0001 };/* 文件权限*/static char perms[10] = "rwxrwxrwx"; /* 字符描述的文件权限*//*** 功能: 获取命令行字符串,存储于buf指向的内存区域** 返回值:有字符输入,返回指向命令行字符串的指针;否则返回空值** 作者: 卢佳 20040094*/char* get_cmd(FILE * fin){ int pos = 0; /* 缓冲区索引 */ char ch; /* 输入字符 */ printf("bitsh<<"); /* 输出提示符 */ while((ch=getc(fin))!=EOF){ if(pos+1>=bufsize){ if(bufsize==0) /* 分配初始内存块 */ buf=(char*)malloc(100); else /* 内存不够时,继续扩充*/ buf=(char*)realloc(buf,bufsize+100); bufsize+= BUFSIZ; } /* 到达命令末尾,则跳出循环*/ if(ch=='\n') break; /* 否则,继续添加字符*/ buf[pos++]=ch; } if(ch==EOF&&pos== 0) /* 没有输入,返回NULL*/ return NULL; buf[pos]='\0'; /* 添加文件结束标识 */ bufsize=strlen(buf); }/*** 功能: 对命令行参数进行分析** 返回值:命令行参数列表(token表)** 作者: 卢佳 20040094*/void parse(){ char* token_start=buf; /* 单词初始位置 */ char* token_end=buf; /* 单词结束位置 */ int len; /* 单词长度 */ while(1){ /* 如果出现空格,退格,定位符或管道符号,则说明遇到一个单词 */ if(*token_end==' '||*token_end=='\t'||*token_end=='<'||*token_end=='>'||*token_end=='|') { /* 为标记命令类型的special_cmd赋值 */ if(*token_end=='>'){ special_cmd=1; } else if(*token_end=='<'){ special_cmd=2; } else if(*token_end=='|'){ special_cmd=3; } /* 将分析结果插入arg_list数组*/ len=token_end-token_start+1; arg_list[idex]=(char*)malloc(len); memset(arg_list[idex],'\0',len); strncpy(arg_list[idex],token_start,len-1); idex++; token_start=token_end+1; token_num++; } /* 以下是对最后一个单词的处理*/ else if(*token_end=='\0'){ len=token_end-token_start+1; arg_list[idex]=(char*)malloc(len); memset(arg_list[idex],'\0',len); strncpy(arg_list[idex],token_start,len-1); idex++; token_num++; break; } token_end++; }} /*** 功能: 启动一个进程运行指定程序** 系统调用:execlp()** 作者: 卢佳 20040094*/int execute(char *argv[]){ int pid ; int child_info = -1; if ( argv[0] == NULL ) return 0; if ((pid = fork())==-1) /*创建子进程出现错误*/ perror("fork"); else if(pid==0){ /*子进程执行体*/ signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); execvp(argv[0], argv); perror("cannot execute command\n"); exit(1); } else{ /*父进程执行体*/ if(wait(&child_info)==-1) perror("wait"); } return child_info;} /* ** 功能: 一条命令执行完毕时,释放内存资源 ** 返回值:无 ** 作者: 卢佳 20040094 */ void free_buf(){ int i=0; free(buf); while(arg_list[i]!=NULL){ free(arg_list[i]); i++; } idex=0; bufsize=0; buf=0; token_num=0;}/*** 功能: 处理重定向命令** 系统调用:execlp(),fork(),signal(),wait()** 返回值: 无** 作者: 卢佳 20040094*/void redirectory(char* source,char* destination){ int pid ; int fd; int child_info = -1; if ((pid = fork())==-1) /*创建子进程出现错误*/ perror("fork"); else if(pid==0){ /*子进程执行体*/ signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); close(1); fd = creat(destination,0644); execlp(source,source,NULL); perror("execlp"); exit(1); } else{ /*父进程执行体*/ if(wait(&child_info)==-1) perror("wait"); }}/*** 功能: 处理管道命令** 系统调用:fork(),pipe(),dup2()** 返回值: 无** 作者: 卢佳 20040094*/int pipe_op(char* source,char* destination){ int p[2]; /* 两个文件描述符*/ int status; /* 进程状态*/ switch(fork()){ /* 创建第一个进程*/ case -1: printf("cannot create process!\n"); case 0: break; default: wait(&status); return(status); } if(pipe(p)==-1){ /* 创建管道*/ printf("can not create pipe!\n"); } switch(fork()){ /* 创建第二个进程*/ case -1: printf("cannot create process!\n"); case 0: /* 第二个子进程的标准输出连接到管道的输入*/ dup2(p[1],1); close(p[0]); close(p[1]); execlp(source,source,NULL); /* 执行管道符号‘|’左边的命令*/ printf("cannot execute!\n"); default: /* 第一个子进程的标准输入连接到管道的输出*/ dup2(p[0],0); close(p[0]); close(p[1]); execlp(destination,destination,NULL); /* 执行管道符号‘|’右边的命令*/ printf("cannot execute!\n"); }}/*** 功能: 移动文件到一个新的目录** 系统调用:link(),unlink()** 作者: 卢佳 20040094*/void move(){ if(link(arg_list[1],arg_list[2])==-1){ perror("link failed!\n"); } if(unlink(arg_list[1])==-1){ perror("unlink failed!\n"); } exit(0);} /* ** 功能: 监视指定文件在一分钟内是否被修改,若是则给出警告 ** 系统调用:stat() ** 作者: 卢佳 20040094 */void watch_dog(){ int j; struct stat sb; time_t last_time[11]; if(token_num>11){ fprintf(stderr,"too many files!\n"); exit(1); } for(j=1;j<token_num;j++){ if(stat(arg_list[j],&sb)==-1){ fprintf(stderr,"cannot stat!\n"); exit(1); } last_time[j]=sb.st_mtime; } for(;;){ for(j=1;j<token_num;j++){ if(stat(arg_list[j],&sb)==-1||sb.st_mtime!=last_time[j]){ fprintf(stderr,"look out: %s chaged\n",arg_list[j]); exit(0); } } sleep(60);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -