linux一个简单的myshell

//myshell.c
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include "myshell.h"

#define MAX_BUF 256

void sys_err(char *str, int exitno)
{
    perror(str);
    exit(exitno);
}

void get_cmd(char *buf)
{
    char ch;
    int len = 0;
    while((ch = getchar()) != '\n')
    {
        buf[len++] = ch;
    }
    buf[len++] = '\n';
    buf[len] = '\0';
}

int analysis_cmd(char *buf, char cmd_str[20][256])
{
    char *p = buf;
    char *q = buf;
    int num = 0, count = 0;
    while (1)
    {
        if (p[0] == '\n')
        {
            break;
        }
        if (p[0] == ' ')
        {
            p++;
        }
        else
        {
            q = p;
            num = 0;
            while (p[0] != ' ' && p[0] != '\n')
            {
                p++;
                num++;
            }
            strncpy(cmd_str[count], q, num+1);
            cmd_str[count][num] = '\0';
			count++;
            q = p;
        }
    }
	return count;
}

void get_type(char cmd_str[20][256], cmd *pcmd)
{
	int i = 0;
	for (i = 0; i < pcmd->cmd_num; ++i)
	{
		pcmd->cmd_agr[i] = cmd_str[i];
		if (strcmp(cmd_str[i], "<") == 0)
		{
			pcmd->mylredi[pcmd->lredi_num++] = i;
		}
		else if (strcmp(cmd_str[i], ">") == 0)
		{
			pcmd->myrredi[pcmd->rredi_num++] = i;
		}
		else if(strcmp(cmd_str[i], "|") == 0)
		{
			pcmd->mypipe[pcmd->pipe_num++] = i;
		}
	}
	pcmd->cmd_agr[i] = NULL;
	if (!pcmd->lredi_num && !pcmd->rredi_num && !pcmd->pipe_num)
	{
		pcmd->type = 0;
	}
	else if (pcmd->lredi_num && !pcmd->rredi_num && !pcmd->pipe_num)
 	{
		pcmd->type = 1;	
	}
	else if (pcmd->rredi_num && !pcmd->lredi_num && !pcmd->pipe_num)
	{
		pcmd->type = 2;
	}
	else if (pcmd->pipe_num && !pcmd->lredi_num && !pcmd->rredi_num)
	{
		pcmd->type = 3;
	}
	else if (pcmd->lredi_num && pcmd->pipe_num && !pcmd->rredi_num)
	{
		pcmd->type = 4;
	}
	else if (pcmd->rredi_num && pcmd->pipe_num && !pcmd->lredi_num)
	{
		pcmd->type = 5;
	}
	else 
	{
		pcmd->type = 6;
	}

}

void normal_cmd(cmd *pcmd)
{
	pid_t pid;
	if ((pid = fork()) < 0)
	{
		sys_err("normal_cmd fork", 1);
	}
	if (pid == 0)
	{
		// in child
		if (execvp(pcmd->cmd_agr[0], pcmd->cmd_agr) < 0)
		{
			sys_err("normal_cmd execvp", 1);
		}
		exit(1);
	}
	wait();
}

void lredi_cmd(cmd *pcmd)
{
	pid_t pid;
	if ((pid = fork()) < 0)
	{
		sys_err("lredi_cmd fork", 1);
	}
	if (pid == 0)
	{
		// in child
		int fd;
		char *filename = pcmd->cmd_agr[pcmd->mylredi[0] + 1];
		pcmd->cmd_agr[pcmd->mylredi[0]] = NULL;
		if ((fd = open(filename, O_RDONLY)) < 0)
		{
			sys_err("lredi_cmd open", 1);
		}
		dup2(fd, STDIN_FILENO);
		close(fd);
		if (execvp(pcmd->cmd_agr[0], pcmd->cmd_agr) < 0)
		{
			sys_err("lredi_cmd execvp", 1);
		}
		exit(1);
	}
	wait();
}

void rredi_cmd(cmd *pcmd)
{

	pid_t pid;
	if ((pid = fork()) < 0)
	{
		sys_err("rredi_cmd fork", 1);
	}
	if (pid == 0)
	{
		// in child
		int fd;
		char *filename = pcmd->cmd_agr[pcmd->myrredi[0] + 1];
		pcmd->cmd_agr[pcmd->myrredi[0]] = NULL;
		if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0)
		{
			sys_err("rredi_cmd open", 1);
		}
		dup2(fd, STDOUT_FILENO);
		close(fd);
		if (execvp(pcmd->cmd_agr[0], pcmd->cmd_agr) < 0)
		{
			sys_err("rredi_cmd execvp", 1);
		}
		exit(1);
	}
	wait();
}

void pipe_cmd(cmd *pcmd)
{
	pid_t pid;
	if ((pid = fork()) < 0)
	{
		sys_err("pipe_cmd fork", 1);
	}
	if (pid == 0)
	{
		// in child
		int fd[2], index = pcmd->mypipe[0], j;
		char *temp[10];
		pid_t pid2;
		if (pipe(fd) < 0)
		{
			sys_err("pipe_cmd pipe", 1);
		}
		if ((pid2 = fork()) < 0)
		{
			sys_err("pipe_cmd fork2", 1);
		}
		if (pid2 == 0)
		{
			pcmd->cmd_agr[index] = NULL;
			// close read
			close(fd[0]);
			dup2(fd[1], STDOUT_FILENO);
			close(fd[1]);
			if (execvp(pcmd->cmd_agr[0], pcmd->cmd_agr) < 0)
			{
				sys_err("pipe_r execvp", 1);
			}
		}
		wait();
		for (j = index+1; pcmd->cmd_agr[j] != NULL; ++j)
		{
			temp[j-index-1] = pcmd->cmd_agr[j];
		}
		temp[j-index-1] = pcmd->cmd_agr[j];
		// close write
		close(fd[1]);
		dup2(fd[0], STDIN_FILENO);
		close(fd[0]);
		if (execvp(temp[0], temp) < 0)
		{
			sys_err("pipe_w execvp", 1);
		}
		exit(1);
	}
	wait();
}

void lredi_pipe_cmd(cmd *pcmd)
{
	pid_t pid;
	if ((pid = fork()) < 0)
	{
		sys_err("lredi_pipe_cmd fork", 1);
	}
	if (pid == 0)
	{
		// in child
		int fd[2], index = pcmd->mypipe[0], j, filefd;
		char *temp[10];
		pid_t pid2;
		if (pipe(fd) < 0)
		{
			sys_err("lredi_pipe_cmd pipe", 1);
		}
		if ((pid2 = fork()) < 0)
		{
			sys_err("lredi_pipe_cmd fork2", 1);
		}
		if (pid2 == 0)
		{
			char *filename = pcmd->cmd_agr[pcmd->mylredi[0] + 1];
			pcmd->cmd_agr[pcmd->mylredi[0]] = NULL;
			// open file
			if ((filefd = open(filename, O_RDONLY)) < 0)
			{
				sys_err("lredi_pipe_open", 1);
			}
			// close read
			close(fd[0]);
			dup2(filefd, STDIN_FILENO);
			dup2(fd[1], STDOUT_FILENO);
			close(fd[1]);
			close(filefd);
			if (execvp(pcmd->cmd_agr[0], pcmd->cmd_agr) < 0)
			{
				sys_err("lredi_pipe_r execvp", 1);
			}
		}
		wait();
		for (j = index+1; pcmd->cmd_agr[j] != NULL; ++j)
		{
			temp[j-index-1] = pcmd->cmd_agr[j];
		}
		temp[j-index-1] = pcmd->cmd_agr[j];
		// close write
		close(fd[1]);
		dup2(fd[0], STDIN_FILENO);
		close(fd[0]);
		if (execvp(temp[0], temp) < 0)
		{
			sys_err("lredi_pipe_w execvp", 1);
		}
		exit(1);
	}
	wait();
}
void rredi_pipe_cmd(cmd *pcmd)
{
	pid_t pid;
	if ((pid = fork()) < 0)
	{
		sys_err("rredi_pipe_cmd fork", 1);
	}
	if (pid == 0)
	{
		// in child
		int fd[2], index = pcmd->mypipe[0], j, filefd;
		char *temp[10];
		pid_t pid2;
		if (pipe(fd) < 0)
		{
			sys_err("rredi_pipe_cmd pipe", 1);
		}
		if ((pid2 = fork()) < 0)
		{
			sys_err("rredi_pipe_cmd fork2", 1);
		}
		if (pid2 == 0)
		{
			pcmd->cmd_agr[index] = NULL;
			// close read
			close(fd[0]);
			dup2(fd[1], STDOUT_FILENO);
			close(fd[1]);
			if (execvp(pcmd->cmd_agr[0], pcmd->cmd_agr) < 0)
			{
				sys_err("rredi_pipe_r execvp", 1);
			}
		}
		wait();
		char *filename = pcmd->cmd_agr[pcmd->myrredi[0] + 1];
		pcmd->cmd_agr[pcmd->myrredi[0]] = NULL;
		for (j = index+1; pcmd->cmd_agr[j] != NULL; ++j)
		{
			temp[j-index-1] = pcmd->cmd_agr[j];
		}
		temp[j-index-1] = pcmd->cmd_agr[j];
		if ((filefd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0)
		{
			sys_err("rredi_pipe_cmd open", 1);
		}
		// close write
		close(fd[1]);
		dup2(filefd, STDOUT_FILENO);
		dup2(fd[0], STDIN_FILENO);
		close(fd[0]);
		close(filefd);
		if (execvp(temp[0], temp) < 0)
		{
			sys_err("rredi_pipe_w execvp", 1);
		}
		exit(1);
	}
	wait();
}
void lredi_rredi_pipe_cmd(cmd *pcmd)
{
	pid_t pid;
	if ((pid = fork()) < 0)
	{
		sys_err("lredi_rredi_pipe_cmd fork", 1);
	}
	if (pid == 0)
	{
		// in child
		int fd[2], index = pcmd->mypipe[0], j, filefd;
		char *temp[10];
		pid_t pid2;
		if (pipe(fd) < 0)
		{
			sys_err("lredi_rredi_pipe_cmd pipe", 1);
		}
		if ((pid2 = fork()) < 0)
		{
			sys_err("lredi_rredi_pipe_cmd fork2", 1);
		}
		if (pid2 == 0)
		{
			char *filename = pcmd->cmd_agr[pcmd->mylredi[0] + 1];
			pcmd->cmd_agr[pcmd->mylredi[0]] = NULL;
			// open file
			if ((filefd = open(filename, O_RDONLY)) < 0)
			{
				sys_err("lredi_pipe_open", 1);
			}
			// close read
			close(fd[0]);
			dup2(filefd, STDIN_FILENO);
			dup2(fd[1], STDOUT_FILENO);
			close(fd[1]);
			close(filefd);
			if (execvp(pcmd->cmd_agr[0], pcmd->cmd_agr) < 0)
			{
				sys_err("lredi_rredi_pipe_r execvp", 1);
			}
		}
		wait();
		char *filename = pcmd->cmd_agr[pcmd->myrredi[0] + 1];
		pcmd->cmd_agr[pcmd->myrredi[0]] = NULL;
		for (j = index+1; pcmd->cmd_agr[j] != NULL; ++j)
		{
			temp[j-index-1] = pcmd->cmd_agr[j];
		}
		temp[j-index-1] = pcmd->cmd_agr[j];
		if ((filefd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0)
		{
			sys_err("lredi_rredi_pipe_cmd open", 1);
		}
		// close write
		close(fd[1]);
		dup2(filefd, STDOUT_FILENO);
		dup2(fd[0], STDIN_FILENO);
		close(fd[0]);
		close(filefd);
		if (execvp(temp[0], temp) < 0)
		{
			sys_err("lredi_rredi_pipe_w execvp", 1);
		}
		exit(1);
	}
	wait();
}

void do_cmd(char cmd_str[20][256], cmd *pcmd)
{
	get_type(cmd_str, pcmd);
	switch(pcmd->type)
	{
		case 0:
			normal_cmd(pcmd);
			break;
		case 1:
			lredi_cmd(pcmd);
			break;
		case 2:
			rredi_cmd(pcmd);
			break;
		case 3:
			pipe_cmd(pcmd);
			break;
		case 4:
			lredi_pipe_cmd(pcmd);
			break;
		case 5:
			rredi_pipe_cmd(pcmd);
			break;
		case 6:
			lredi_rredi_pipe_cmd(pcmd);
			break;
	}
}

void init_cmd(cmd *pcmd)
{
	pcmd->cmd_num = 0;
	pcmd->type = 0;
	pcmd->pipe_num = 0;
	pcmd->lredi_num = 0;
	pcmd->rredi_num = 0;
	memset(pcmd->mypipe, 0, 5);
	memset(pcmd->mylredi, 0, 5);
	memset(pcmd->myrredi, 0, 5);
	memset(pcmd->cmd_agr, 0, 10);
}

int main(void)
{
    char buf[256];
    char cmd_str[20][256];
	cmd pcmd;
    while (1)
    {
        printf("mysh$ ");
		init_cmd(&pcmd);
		get_cmd(buf);
		pcmd.cmd_num = analysis_cmd(buf, cmd_str);
		do_cmd(cmd_str, &pcmd);
    }
    return 0;
}
//myshell.h
typedef struct
{
	int cmd_num;	
	int type;		
	int mypipe[5];
	int mylredi[5];	
	int myrredi[5];
	int pipe_num;
	int lredi_num;
	int rredi_num;
	char *cmd_agr[10];
}cmd;

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以为您介绍一下如何实现一个简单Shell程序。 Shell是一种命令行解释器,它能够解释用户输入的命令并执行相应的操作。Shell程序通常由用户输入命令,Shell解释命令并执行相应的操作,然后Shell等待用户下一个命令的输入。 下面是一个简单Shell程序的实现,主要分为以下几个步骤: 1. 读取用户输入 使用C语言中的fgets函数从标准输入读取用户输入的命令。 2. 解析用户输入 将用户输入的命令按照空格分割成多个部分,如命令名和参数等。 3. 执行用户命令 根据用户输入的命令,使用execvp函数执行相应的系统命令,例如ls、cd等。 4. 循环执行 使用while循环不断地读取用户输入并执行相应的操作,直到用户输入exit命令退出程序。 下面是一个简单Shell程序的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <string.h> #define MAX_COMMAND_LENGTH 1024 int main() { char command[MAX_COMMAND_LENGTH]; char* args[MAX_COMMAND_LENGTH/2]; while (1) { printf("myshell> "); fflush(stdout); // 读取用户输入 fgets(command, MAX_COMMAND_LENGTH, stdin); // 去掉换行符 command[strlen(command)-1] = '\0'; // 解析用户输入 char* token = strtok(command, " "); int i = 0; while (token != NULL) { args[i++] = token; token = strtok(NULL, " "); } args[i] = NULL; // 执行用户命令 pid_t pid = fork(); if (pid == -1) { printf("fork failed\n"); } else if (pid == 0) { execvp(args[0], args); exit(0); } else { wait(NULL); } // 处理exit命令 if (strcmp(args[0], "exit") == 0) { break; } } return 0; } ``` 上面的代码中使用了fork函数创建一个新的子进程,并使用execvp函数执行用户命令。在子进程中调用execvp函数后,进程的内存空间将被覆盖为新程序的内存空间。因此,在子进程中调用exit函数退出程序。 在主进程中,使用wait函数等待子进程执行完毕。wait函数将暂停当前进程的执行,直到其子进程结束后恢复执行。 以上就是一个简单Shell程序的实现。当然,实际上Shell程序的实现要比这个复杂得多,因为需要考虑很多其他的因素,例如I/O重定向、管道、变量替换等等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mrack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值