赞
踩
注意: 本文章只是为了理解shell内部的工作原理, 所以并没有完成shell的所有工作, 只是完成了shell里的一小部分工作
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include <sys/types.h> #include <sys/wait.h> #define LEFT "[" #define RIGHT "]" #define END "#" #define SPLIT " " #define LINE_SIZE 1024 #define ARGV_SIZE 32 #define EXIT_CODE 66 #define PWD_SIZE 100 int lastexit = 0; int quit = 0; char pwd[PWD_SIZE]; const char* getusername() { return getenv("USER"); } const char* mygethostname() { return getenv("HOSTNAME"); } void getpwd() { getcwd(pwd, PWD_SIZE); } void display() { getpwd(); printf(LEFT"%s@%s %s"RIGHT""END" ", getusername(), mygethostname(), pwd); } void getinput(char* cline, int size) { char* s = fgets(cline, size, stdin); assert(s != NULL); cline[strlen(cline) - 1] = '\0'; //printf("%s\n", cline); } int split(char* cline, char* argv[]) { int i = 0; //printf("%s", cline); argv[i ++] = strtok(cline, SPLIT); while (argv[i ++] = strtok(NULL, SPLIT)); return i - 1; } void normalExe(char* argv[]) { extern char** environ; pid_t id = fork(); if (id < 0) { perror("fork"); //continue; } else if (id == 0) { // child execvpe(argv[0], argv, environ); exit(EXIT_CODE); } // father int status = 0; pid_t ret = waitpid(id, &status, 0); // if (ret > 0) printf("wait success pid: %d\n", ret); if (ret > 0) lastexit = WEXITSTATUS(status); } int neijian(char* argv[], int argc) { if (argc == 2 && strcmp(argv[0], "cd") == 0) { chdir(argv[1]); getpwd(); return 1; } return 0; } int main() { //int quit = 0; char cline[LINE_SIZE]; char* argv[ARGV_SIZE] = { NULL }; extern char** environ; while (!quit) { display(); getinput(cline, LINE_SIZE); int tt = split(cline, argv); if (tt == 0) continue; //printf("%d\n", tt); /* int i = 0; for (i = 0; argv[i]; ++ i) printf("%s ", argv[i]); printf("\n"); */ // 内建命令执行 //内建命令本质上就是shell内部的一个函数 int n = neijian(argv, tt); //printf("%d\n", n); //普通命令执行 if (!n) normalExe(argv); } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。