Linux小程序: 手写自己的shell

注意: 本文章只是为了理解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;
}

相关推荐

  1. Linux程序自己shell

    2024-03-29 00:46:04       21 阅读
  2. Linuxshell

    2024-03-29 00:46:04       18 阅读
  3. 微信程序canvas签字

    2024-03-29 00:46:04       30 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-29 00:46:04       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-29 00:46:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-29 00:46:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-29 00:46:04       18 阅读

热门阅读

  1. js的数组

    2024-03-29 00:46:04       21 阅读
  2. webpack为什么要使用loader,如何手写loader

    2024-03-29 00:46:04       18 阅读
  3. webpack快速基础

    2024-03-29 00:46:04       18 阅读
  4. Linux双向链表相关API的使用及事例Demo

    2024-03-29 00:46:04       17 阅读
  5. 添加了ssh keys还是无法git push

    2024-03-29 00:46:04       21 阅读
  6. 数据库底层原理

    2024-03-29 00:46:04       17 阅读
  7. mysql null值相减还是null

    2024-03-29 00:46:04       17 阅读
  8. 电机转速&转矩计算公式

    2024-03-29 00:46:04       29 阅读
  9. Go语言教程和案例

    2024-03-29 00:46:04       16 阅读