milestone2 :

Phase 1 •

According to the specifications in Section 3.2, you shall implement the basic shell before or on Apr. 1, 2015, when every one of you need to give us a demonstration on the OS shell.

• Your program must be thoroughly tested.

You should make sure that you have test the cases both for successful and for unsuccessful operations.

Phase 2 •

According to the specifications in Section 3.3, you shall implement the redirection and the pipe of the shell before or on Apr. 22, 2015 when every one of you need to give us a demonstration on the OS shell program.

• Your program must be thoroughly tested.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#define BUFFER_SIZE 256
#define ARR_SIZE  128
#define HISTORY_SIZE 20
#define CMDNUMBER 128
void ioRedirection( char *argArray[]) {
	int argumentCount=0;
	while(argArray[argumentCount]) argumentCount++;
	//Check if there is io redirection
	for (int i = 1; i < argumentCount; i++) {
		if (strcmp(argArray[i], "<") == 0) {
			if (i + 1 == argumentCount) {
				fprintf(stderr, "Missing argument for <");
				exit(-1);
			}
			if (freopen(argArray[i + 1], "r", stdin) == NULL) {
				fprintf(stderr, "can not open %s\n", argArray[i + 1]);
				exit(-1);
			} else {
				argumentCount -= 2;
				for (int j = i; j < argumentCount; j++)
					argArray[j] = argArray[j + 2];
				argArray[argumentCount] = NULL;
				argArray[argumentCount + 1] = NULL;
				continue;
			}
		}
		if (strcmp(argArray[i], ">") == 0) {
			if (i + 1 == argumentCount) {
				fprintf(stderr, "Missing argument for >");
				exit(-1);
			}
			if (freopen(argArray[i + 1], "w+", stdout) == NULL) {
				fprintf(stderr, "can not open %s\n", argArray[i + 1]);
				exit(-1);
			} else {
				argumentCount -= 2;
				for (int j = i; j < argumentCount; j++)
					argArray[j] = argArray[j + 2];
				argArray[argumentCount + 1] = NULL;
				argArray[argumentCount] = NULL;
				continue;
			}
		}
		if (strcmp(argArray[i], ">>") == 0) {
			if (i + 1 == argumentCount) {
				fprintf(stderr, "Missing argument for >>");
				exit(-1);
			}
			if (freopen(argArray[i + 1], "a+", stdout) == NULL) {
				fprintf(stderr, "can not open %s\n", argArray[i + 1]);
				exit(-1);
			} else {
				argumentCount -= 2;
				for (int j = i; j < argumentCount; j++)
					argArray[j] = argArray[j + 2];
				argArray[argumentCount + 1] = NULL;
				argArray[argumentCount] = NULL;
				continue;
			}
		}
	}
}
int ismultiCmd(char *args[]){
	int i=0;
	while(args[i]){
	if(strcmp(args[i],"|")==0) return 1;
	i++;
	}
	return 0;
}
int mutifork(char *args[])
{
	int pipefd[CMDNUMBER][2];
	pid_t pid[CMDNUMBER];
	int i, j;
	int count;
	int status;
	char **arg_child[CMDNUMBER];
	char **p;
	char ***q;


	/* parse and split args to child arg */
	count = 0;
	p = args; q = arg_child;
	while(*p != NULL && p != NULL){
		*q++ = p;
		count++;
		while(*p != NULL && strcmp(*p, "|") != 0){
			p++;
		}
						
		if(*p != NULL){
			*p++ = NULL;
		}	
	}
	*q = NULL;	
	/* fork count child process */
	for(i = 0; i < count; i++){
		/* init pipe file descriptor */
		if(pipe(pipefd[i]) < 0){ /* FIXME: excess one */
			perror("pipe");
			return -1;
		}
		
		/* fork child i */
		if((pid[i] = fork()) < 0){
			fprintf(stderr, "%s:%d: fork() failed: %s\n", __FILE__,
				__LINE__, strerror(errno));
			return -1;
		}else if(pid[i] == 0){
			/* child i */
			
			//int dup2(int oldfd, int newfd);
			if(i == 0){ /* the first child */
				close(pipefd[i][0]); /* close curr process read */

				if(dup2(pipefd[i][1], STDOUT_FILENO) < 0){
					perror("dup2 failed");
					return -1;
				}
			}else if(i == count - 1){ /* the last child */
				for(j = 0; j < i - 1; j++){ /* close unuse pipefd */
					close(pipefd[j][1]);
					close(pipefd[j][0]);
				}
				close(pipefd[j][1]); /* close prev process end of write */
				close(pipefd[i][0]); /* close curr process end of read */

				if(dup2(pipefd[j][0], STDIN_FILENO) < 0){
					perror("dup2 failed");
					return -1;
				}
			}else{
				for(j = 0; j < i - 1; j++){ /* close unuse pipefd */
					close(pipefd[j][1]);
					close(pipefd[j][0]);
				}
				close(pipefd[j][1]); /* close prev process end of write */
				close(pipefd[i][0]); /* close curr process end of read */

				if(dup2(pipefd[j][0], STDIN_FILENO) < 0){
					perror("dup2 failed");
					return -1;
				}
				if(dup2(pipefd[i][1], STDOUT_FILENO) < 0){
					perror("dup2 failed");
					return -1;
				}
			}
			//int execvp(const char *file, char *const argv[]);
			if(execvp(arg_child[i][0], arg_child[i]) < 0){
				if (errno == ENOENT){	
					printf("%s: command not found\n",arg_child[i][0]);
				}else{
					printf("%s: unknown error\n",arg_child[i][0]);
				}
				exit(1);
			}
			
			exit(0);
		
			/* child process exit */
		}
	}

	/* parent process */

	for(i = 0; i < count; i++){
		/* close all pipe file descriptor */
		close(pipefd[i][0]);
		close(pipefd[i][1]);	
	}


	for(i = 0; i < count; i++){
		//pid_t waitpid(pid_t pid, int *status, int options);
		waitpid(pid[i], &status, 0);
		if(status != 0){
			return status;
		}
	}

	return status;
	
}
void parse_args(char *buffer, char** args, 
                size_t args_size, size_t *nargs)
{
    char *buf_args[args_size]; /* You need C99 */
    char **cp;
    char *wbuf;
    size_t i, j;
    
    wbuf=buffer;
    buf_args[0]=buffer; 
    args[0] =buffer;
    
    for(cp=buf_args; (*cp=strsep(&wbuf, " \n\t")) != NULL ;){
		
        if ((*cp != '\0') && (++cp >= &buf_args[args_size]))
            break;
    }
    
    for (j=i=0; buf_args[i]!=NULL; i++){
        if(strlen(buf_args[i])>0){
			//if()
			args[j++]=buf_args[i];
			
		}
    }
    
    *nargs=j;
    args[j]=NULL;
}
int shell_cd(char *args[])  
{  
    char buf[BUFFER_SIZE + 1];  
	if(args[1]==NULL){
		fprintf(stderr,"There is no argument for cd command!\n");
		return -1;
		}
    memset(buf, 0, BUFFER_SIZE + 1);  
      
    if(args[1][0] != '/' && args[1][0] != '.'){  
        //char *getcwd(char *buf, size_t size);  
        if(getcwd(buf, BUFFER_SIZE) == NULL){  
            fprintf(stderr, "%s:%d: getcwd failed: %s\n", __FILE__,   
                __LINE__, strerror(errno));  
            return -1;  
        }  
        strncat(buf, "/", BUFFER_SIZE - strlen(buf));  
    }  
	
    //char *strncat(char *dest, const char *src, size_t n);  
    strncat(buf, args[1], BUFFER_SIZE - strlen(buf));  
    
    //int chdir(const char *path);  
    if(chdir(buf) == -1){  
        fprintf(stderr, "%s:%s\n",strerror(errno),buf); 
    }  
  
    return 0;  
}
char *shell_prompt(char *promptbuf)  
{  
    char tmpbuf[BUFFER_SIZE + 1];  
  
    //void *memset(void *s, int c, size_t n);  
    memset(promptbuf, 0, BUFFER_SIZE + 1);  
    memset(tmpbuf, 0, sizeof(tmpbuf));  
  
    //char *getcwd(char *buf, size_t size);  
    if(getcwd(tmpbuf, sizeof(tmpbuf) - 1) == NULL){  
        fprintf(stderr, "%s:%d: getcwd failed: %s\n",   
            __FILE__, __LINE__, strerror(errno));  
        exit(1);  
    }  
      
    //int snprintf(char *str, size_t size, const char *format, ...);  
    snprintf(promptbuf, BUFFER_SIZE, "[OSshell:%s]$", tmpbuf);  
  
    return promptbuf;  
}  
void shell_history(char (*history)[BUFFER_SIZE],size_t index){
	size_t j=0;
	index-=1;
	while(history[index][0]!='\0'&&j<HISTORY_SIZE){
//		printf("%d %s\n",j,history[index]);
		index--;
		j++;
		if(index<0) index=HISTORY_SIZE-1;
	}
	for(;j>=1;j--){
		index++;
		index%=HISTORY_SIZE;
		printf("%d %s",index+1,history[index]);
	}
}
int main(int argc, char *argv[], char *envp[]){
    char buffer[BUFFER_SIZE];
	char history[HISTORY_SIZE][BUFFER_SIZE];
	size_t historyIndex;
    char *args[ARR_SIZE];
	char str_prompt[BUFFER_SIZE + 1];
    int ret_status;
    size_t nargs;
    pid_t pid;
	memset(buffer,0,BUFFER_SIZE);
	memset(history,0,BUFFER_SIZE*HISTORY_SIZE);
    historyIndex=0;
    while(1){
        printf("%s",shell_prompt(str_prompt));
        fgets(buffer, BUFFER_SIZE, stdin);
		strcpy(history[historyIndex],buffer);
        parse_args(buffer, args, ARR_SIZE, &nargs); 
        if (nargs==0) continue;
		if(!strcmp(args[0], "history" )) {
			shell_history(history,historyIndex);  
			continue;
		}
		if(args[0][0]=='!'){
			int his;
			if(args[0][1]=='!'){
				his=historyIndex-1;
			}else{
				sscanf(&args[0][1],"%d",&his);
				if(his>HISTORY_SIZE|| his<1){
					fprintf(stderr,"history out of bound!\n");
					continue;
				}
				his=his-1;
			}
			parse_args(history[his], args, ARR_SIZE, &nargs); 
		}else{
			historyIndex++;
			historyIndex%=HISTORY_SIZE;
		}
        if (!strcmp(args[0], "exit" )) exit(0); 
		if (!strcmp(args[0], "cd" )) {
			shell_cd(args);  
			continue;
		}
		if(ismultiCmd(args)==1){
//			printf("Multi\n");
			mutifork(args);
		}else{
			pid = fork();
			if (pid){
	//            printf("Waiting for child (%d)\n", pid);
				pid = wait(&ret_status);
	 //           printf("Child (%d) finished\n", pid);
			} else {
				ioRedirection(args);
				if( execvp(args[0], args)) {
	//                puts(strerror(errno));
					printf("Commands not found!\n");
					exit(127);
				}
			}
		}
    }    
    return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据