用C语言实现myshell

C语言实现一个简单的交互式Shell:

1.实现加载普通命令。

难点:通过分析参数字符串,然后利用函数fork()和execvp()来实现。


2.实现重定向的功能。

难点:通过函数dup2()实现


3.实现管道。

难点:学会利用管道实现进程间通信


下面是代码实现:


/*************************************************************************
  > File Name: myshell.c
  > Author: lucifer
  > Mail: [email protected] 
  > Created Time: 2014年11月10日 星期一 18时43分14秒
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

void sys_err(const char *str)
{
	perror(str);
	exit(-1);
}

void analyse_input(char *s,char *argv[])
{
	int i = 0;
	argv[i] = strtok(s," ");
	while(argv[i])
	{
		i++;
		argv[i] = strtok(NULL," ");
	}
	argv[i] = NULL;

}

int main(void)
{
	char s[256]={0};
	char *argv[10],*argv1[10];
	pid_t pid;
	int status,i;
	int isredirect = 0;
	int ispipe = 0;
	int fd;
	int pfd[2];

	while(1)
	{
		printf("myshell#");
		fgets(s,256,stdin);
		if(s[0] == '\n')
		{
			continue;
		}
		if(s[strlen(s) - 1] == '\n')
		{
			s[strlen(s) - 1] ='\0';
		}
		if(strcmp(s,"exit") == 0)
		{
			break;
		}
		for(i = 0;i < strlen(s);i++)
		{
			if(s[i] == '<' || s[i] == '>')
			{
				isredirect = 1;
				break;
			}
			if(s[i] == '|')
			{
				ispipe = 1;
				break;
			}
		}

		if(isredirect)
		{
			if(s[i] == '>')
			{
				char *p1 = strtok(s,">");
				char *p2 = strtok(NULL,">");
				char *p3 = strtok(p2," ");
				analyse_input(p1,argv);
				if((pid = fork()) < 0)
				{
					sys_err("fork error");
				}
				else if(pid == 0)
				{
					if((fd = open(p3,O_WRONLY | O_TRUNC)) < 0)
					{
						sys_err("open failed");
					}
					dup2(fd,STDOUT_FILENO);
					close(fd);
					execvp(argv[0],argv);
					sys_err("excvp error");
				}

				else
				{
					memset(s,0,256);
					isredirect=0;//important
					waitpid(pid,&status,0);
					continue;
				}
			}
			else
			{
				char *p1 = strtok(s,"<");
				char *p2 = strtok(NULL,"<");
				char *p3 = strtok(p2," ");

				analyse_input(p1,argv);
				if((pid = fork()) < 0)
				{
					sys_err("fork error");
				}
				else if(pid == 0)
				{
					if((fd = open(p3,O_RDONLY)) < 0)
					{
						sys_err("open failed");
					}
					dup2(fd,STDIN_FILENO);
					close(fd);
					execvp(argv[0],argv);
					sys_err("execvp error");
				}
				else
				{
					memset(s,0,256);
					isredirect = 0;
					waitpid(pid,&status,0);
					continue;
				}
			}
		}

		else if(ispipe)
		{
			char *p1 = strtok(s,"|");
			char *p2 = strtok(NULL,"|");
			analyse_input(p1,argv);
			analyse_input(p2,argv1);
			if((pid = fork()) < 0)
			{
				sys_err("fork error");
			}
			else if(pid == 0)
			{
				if(pipe(pfd) < 0)
				{
					sys_err("pipe error");
				}
				pid = fork();
				switch(pid)
				{
					case -1 :
						sys_err("fork error");
					case 0 :
						close(pfd[0]);
						dup2(pfd[1],STDOUT_FILENO);
						close(pfd[1]);
						execvp(argv[0],argv);
						sys_err("execvp error");
						exit(-1);
					default:	
						close(pfd[1]);
						dup2(pfd[0],STDIN_FILENO);
						close(pfd[0]);
						execvp(argv1[0],argv1);
						sys_err("execvp error");
						exit(-1);
				}
			}
			else 
			{
				memset(s,0,256);
				waitpid(pid,&status,0);
				ispipe = 0;
				continue;
			}
		}
		else
		{
			analyse_input(s,argv);
			if((pid = fork()) < 0)
			{
				sys_err("fork error");
			}
			else if(pid == 0)
			{
				execvp(argv[0],argv);
				sys_err("execvp error");
			}
			else
			{
				waitpid(pid,&status,0);
			}
		}
	}
	return 0;
}



你可能感兴趣的:(多进程,进程间通信,Linux编程,实现简单的shell)