my_shell.c
来源:互联网 发布:软件激活码拿码平台 编辑:程序博客网 时间:2024/05/29 07:12
#include<stdio.h>#include<string.h>#include<pwd.h>#include<stdlib.h>#include<sys/types.h>#include<unistd.h>#include<sys/wait.h>#include<fcntl.h>#include<dirent.h>#include<readline/readline.h>#include<readline/history.h>#include<signal.h>#define PIPE 1#define IN 2#define OUT 4#define OUTAPP 16int get_param(char *,char (*str)[256]);void explain_param(char (*str)[256],int *param,int k);//解释参数int getlenth(int start,char *buf);//获取字符串长度int getstart(int end,char *buf);//获得非空字符串的开始int empty(char *str){ for (int i = 0; i < strlen(str); i++) { if (str[i] != ' ') return 0; } return 1;}int main(){ char *buf; char str[100][256]={0}; int pid; int param=0; int k;//二维数组的一维大小 chdir("/home/cwh"); //阻断SIGINT SIGQUIT SIGSTOP SIGTSTP signal(SIGINT, SIG_IGN);//屏蔽ctrl+c或+z signal(SIGQUIT, SIG_IGN); signal(SIGSTOP, SIG_IGN); signal(SIGTSTP, SIG_IGN); while(1) { param=0; char tip[500]; struct passwd *pwd; memset(str, 0, sizeof(str)); pwd=getpwuid(getuid()); sprintf(tip,"%s:%s$ ",pwd->pw_name,get_current_dir_name()); buf=readline(tip); if(strcmp(buf,"exit")==0)//输入exit退出 break; int isempty = empty(buf); if (isempty) continue; add_history(buf);//记录历史记录,实现上下左右查看 k=get_param(buf,str); explain_param(str,¶m,k); } exit(0);}int getstart(int start,char * buf)//得到非空格下标{ while(buf[start]==' ' && start<=strlen(buf)) start++; return start;}int getlenth(int start,char *buf)//获得非空字符串长度{ int lenth=0; for(int i=start+1;i<strlen(buf);i++) { if(buf[i]!=' ') lenth++; else break; } return lenth;}int get_param(char *buf,char (*str)[256]){ int start=0,end=0,k=0;//方法一,判断函数起点和终点的空格问题 int flag; while(end<strlen(buf)) { start=getstart(start,buf); int lenth=getlenth(start,buf); end=start+lenth+1; strncpy(str[k++],buf+start,lenth+1);//用strncpy可以实现从指定起始位置开始复制 if(strcmp(str[k-1],"")==0) k--; start=end; } return k;} /* char st[5000];//方法二 strcpy(st, buf); char bf[5000], gf[5000]; int i = 0; while (sscanf(st,"%s %[^\n]", bf, gf) == 2)//就是将输入分为两部分v { strcpy(str[i++], bf); strcpy(st, gf); } strcpy(str[i++], st); for (int j = strlen(str[i - 1]) - 1; j >= 0; j--) { if (str[i - 1][j] == ' ') str[i - 1][j] = '\0'; else break; } return k; */void explain_param(char (*str)[256],int *param,int k){ int i; char store[100][256]={0};//存ls参数 char rest[256]; int back=0; int len=k; int flag=0; int m=0; int file=0; char file2[100][256]={0}; for(i=0;i<len;i++) { if(strcmp(str[i],"cd")==0) { flag=1; continue; } if(strcmp(str[i],">")==0)//一定要++i,不然就会重复读取 { (*param)|=OUT; strcpy(rest,str[++i]); continue; } if(strcmp(str[i],">>")==0) { (*param)|=OUTAPP; strcpy(rest,str[++i]); continue; } if(strcmp(str[i],"<")==0) { (*param)|=IN; strcpy(rest,str[++i]); continue; } if(strcmp(str[i],"|")==0) { (*param)|=PIPE; for(int j=i+1;j<len;j++) strcpy(file2[file++],str[j]); break; } if(strcmp(str[i],"&")==0) { back=1; continue; } strcpy(store[m++],str[i]); } char *argv[256]; char *pipe[256]; if((*param)&PIPE)//记录管道符号的后半部分 { for(i=0;i<file;i++) pipe[i]=file2[i]; pipe[i]=(char*)NULL; } for(i=0;i<m;i++) { argv[i]=store[i];//指针数组就可以存char *NULL } argv[i]=(char*)NULL; if(len==0)//只是回车或者其他字符,直接返回 { return; } pid_t pid; if(flag==0||back) pid=fork(); if(back&&pid>0)//有了&而且父进程要结束 { printf("process id %d\n",pid); return ; } if(flag)//如果有cd的情况 { if(len!=1) { if(chdir(store[0])<0) printf("No such file or directory\n"); } else chdir("/home/cwh");//单个cd可以直接切换到主目录 return ; } if(pid==0) { int is_redirect=0; int fd; if((*param)&OUT) fd=open(rest,O_RDWR|O_CREAT|O_TRUNC,0644), is_redirect=1; else if((*param)&OUTAPP) fd=open(rest,O_RDWR|O_CREAT|O_APPEND,0644),is_redirect=1; else if((*param)&IN) fd=open(rest,O_RDONLY),is_redirect=2; if((*param)&PIPE) { fd=open("/tmp/cwhshelltxt",O_RDWR|O_CREAT|O_TRUNC,0644); dup2(fd,1); execvp(store[0],argv); exit(0); } if(is_redirect && fd<0) { perror("open"); exit(-1); } if(is_redirect==1) dup2(fd, STDOUT_FILENO); if(is_redirect==2) dup2(fd,STDIN_FILENO); int err=execvp(store[0], argv); if (err!=0) perror("#error#"); exit(0); } if(pid == -1) { printf("creat process failed!"); return; } if(pid > 0) { waitpid(pid,NULL,0); if((*param&PIPE)) { pid_t pid ; pid=fork(); if(pid==0) { int fd; fd=open("/tmp/cwhshelltxt",O_RDONLY); dup2(fd,0); execvp(pipe[0],pipe); exit(0); } if(pid==-1) { perror("fork"); return; } if(pid>0) { waitpid(pid,NULL,0); remove("/tmp/cwhshelltxt"); return ; } } return; }}
阅读全文
0 0
- my_shell.c
- my_shell
- my_shell 编写
- my_shell的简单实现
- 用realine库完善你的my_shell
- c
- c
- c
- c
- C
- c
- c
- c
- C+
- c
- C
- c
- c
- uva题目笔记——高精度
- ROS学习笔记(三)
- shell--ch5 理解shell
- Eclipse设置选中内容亮化显示
- OpenCV学习之摄像头录制存储视频
- my_shell.c
- 1159: 最大的两个数(指针专题)
- [WUA APIs]Using the Windows Update Agent API
- HDU6033Add More Zero
- SQL Server
- # MySQL编程基础——自定义函数返回值
- SCU 4444 Travel (完全图 最短路 set )
- 我自己搭建的html表单
- hdu图论题目