[linux]用C语言实现一个Linux中的myshell

10 篇文章 4 订阅
9 篇文章 0 订阅

编写一个C语言程序myshell作为Linux内核的Shell命令行解释程序,实现以下功能:

(1)解析用户提交的命令行;按照环境变量搜索目录系统;执行命令,如果将要在后台运行命令,它将以“&”结尾。

(2)提供ls、mkdir  rmdir、pwd、ps等内部命令。

(3)提供历史查询功能。如用户按下Ctrl+C,信号处理器将输出最近的10个命令列表。

(4)'r\n'重复执行最近的一次命令,如果历史命令列表为空,给出提示

(5)'r x'执行最近一次以字符x开头的命令(逆向搜索),如命令列表中不存在,给出提示

HNUers,学长只能帮你们到这里了,可能会要改一下结尾的符号"&"

#include <stdio.h>   // to include printf
#include <signal.h>  // to include struct sigaction handler
#include <unistd.h>  // to include the system function 'execvp'
#include <stdlib.h>  // to include exit()
#include <sys/types.h>  // to include pid_t
#include <sys/wait.h>   // to include wait()
#include <string.h>  // to include strcpy
#define BUFFERSIZE 50
#define MAXLINE 80
#define true 1
#define false 0

char buffer[BUFFERSIZE];
char historyCommands[10][81];
int currentCommandIndex = -1; // where to storage the current command

void printHis () {
    int i = 0;
    printf("\n");
    for (i = 0 ; i < 10 ; ++i) {
	printf("%d : %s", i, historyCommands[i]);
    }
}

void handle_SIGINTO() {
    write(STDOUT_FILENO, buffer, strlen(buffer));    
    printHis();
} 

void addHistory(char *inputBuffer) {
    //add history into the message queue
    currentCommandIndex = (currentCommandIndex + 1) % 10;
    strcpy(historyCommands[currentCommandIndex], inputBuffer);    
}

char* checkHis (char ch, int type) {
    if (type == 3) {
        int i = 0;
        for (i = currentCommandIndex ; i >= 0 ; --i) {
    	    if (historyCommands[i][0] == ch) {
			return historyCommands[i];
	    }	
	}
		for (i = 9 ; i >= currentCommandIndex ; --i) {
	    	    if (historyCommands[i][0] == ch) {
				return historyCommands[i];
		    }	
		}   
    }
    return NULL;
}

void setup(char inputBuffer[], char *args[],int *background) {
	int i = 0;
	int length = -1;  // storage the length of the command
	length = read(STDIN_FILENO, inputBuffer, MAXLINE);
	inputBuffer[length] = '\0';  // read method don't add '\0' automatically
	if (length == 0) {
		exit(0);		 
	}
	else if (length == -1) { 
		args[0] = NULL;  
		return;  // caught nothing, return
	}
	int currParamStartIndex = -1;  // to storage the current parameters'
	int currPos = 0;  // args[currentPosition]
	int copyFlag = false;  // did not call r or 'r x' 	
	char* pCommand = NULL;
	if (inputBuffer[0] == 'r') {
	    // condition 3 : 'r\n' get the most recent one
            if (inputBuffer[1] == '\n') {
            	if (currentCommandIndex == -1) {
                    printf("No valid commands\n");	
		    		return;
                }	
		else {	
		    strcpy(inputBuffer, historyCommands[currentCommandIndex]); 
		    copyFlag = true;
		}
            }    
            else if (inputBuffer[1] == ' ' && inputBuffer[2] != ' ') {
	         if ((pCommand = checkHis(inputBuffer[2], 3)) == NULL) { 
                    printf("No recent valid commands begin with %c\n", inputBuffer[2]);	
		     		return;
                 }
		 else {
                strcpy(inputBuffer, pCommand);                   
                copyFlag = true; 
        	}
	    } 
	}
	if (!copyFlag) {
	    addHistory(inputBuffer);
	}
	else {
            length = strlen(inputBuffer);
	    addHistory(inputBuffer);
        }
	for (i = 0 ; i < length ; ++i) {
		if (inputBuffer[i] == '&') {
			*background = 1;
			inputBuffer[i] = '\0';
		}
		else if (inputBuffer[i] == ' ' || inputBuffer[i] == '\t') {
			if (currParamStartIndex != -1) {
				args[currPos++] = &inputBuffer[currParamStartIndex];
				inputBuffer[i] = '\0';
				currParamStartIndex = -1;
			}
		}
		else if (inputBuffer[i] == '\n') {  // end of the current command
			if (currParamStartIndex != -1) {
				args[currPos++] = &inputBuffer[currParamStartIndex];
				inputBuffer[i] = '\0';
				args[currPos] = NULL;
				currParamStartIndex = -1;
			}
		}
		else {  // storage the valid phrase of the order
			if (currParamStartIndex == -1) {
				currParamStartIndex = i;
			}
		}
	}
	args[currPos] = NULL;  // command length > MAX_LINE
}

int main() {
        int i = 0;
	for (i = 0 ; i < 10 ; i++) {
	    historyCommands[i][0] = '\0'; // Initailize the command Array
	}		
	// create signal handler
	struct sigaction handler;
	handler.sa_handler = handle_SIGINTO;
	sigaction(SIGINT, &handler, NULL);
        		
	char inputBuffer[MAXLINE+1];  // maximum for 80 characters
	int background = 0; 
	char* args[MAXLINE/2 + 1];
	while (true) {
		background = 0; // default value to call wait(0)
		printf("COMMAND->");
		fflush(stdout);  // print the order to the screen
		setup(inputBuffer, args, &background);
		pid_t pid = fork();
		if (pid == -1) {
			perror("fork");
			exit(1);  // exit the process by accident
		}
		if (pid == 0) {  // child code
			execvp(args[0], args);
			exit(0);  // exit the process simoutaneously
		}
		if (background == 0) {
			wait(0); 
		}
	}
	return 0;
} 

 

 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值