Linux小程序: 手写自己的shell

news/2024/7/20 2:42:33 标签: linux, 小程序, 运维

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


http://www.niftyadmin.cn/n/5457265.html

相关文章

Ubuntu下使用vscode进行C/C++开发:进阶篇

在vscode上进行C/C++开发的进阶需求: 1) 编写及调试源码时,可进行断点调试、可跨文件及文件夹进行函数调用。 2) 可生成库及自动提取对应的头文件和库文件。 3) 可基于当前工程资源一键点击验证所提取的库文件的正确性。 4) 可结合find_package实现方便的调用。 对于第一…

HackTheBox-Machines--Legacy

文章目录 1 端口扫描2 测试思路3 445端口漏洞测试4 flag Legacy 测试过程 1 端口扫描 nmap -sC -sV 10.129.227.1812 测试思路 目标开启了135、139、445端口&#xff0c;445 SMB服务存在很多可利用漏洞&#xff0c;所以测试点先从445端口开始。而且在Nmap扫描结果中&#xff0c…

软考 系统架构设计师系列知识点之云原生架构设计理论与实践(8)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之云原生架构设计理论与实践&#xff08;7&#xff09; 所属章节&#xff1a; 第14章. 云原生架构设计理论与实践 第2节 云原生架构内涵 14.2 云原生架构内涵 关于云原生的定义有众多版本&#xff0c;对于云原生架构的…

OpenHarmony实战开发-Web组件的使用

介绍 本篇Codelab使用ArkTS语言实现一个简单的免登录过程&#xff0c;向大家介绍基本的cookie管理操作。主要包含以下功能&#xff1a; 获取指定url对应的cookie的值。设置cookie。清除所有cookie。免登录访问账户中心。 原理说明 本应用旨在说明Web组件中cookie的管理操作。…

Ubuntu通过分用户进行多版本jdk配置

前言&#xff1a;本文内容为实操记录&#xff0c;仅供参考&#xff01; linux安装jdk参考&#xff1a;http://t.csdnimg.cn/TeECj 出发点&#xff1a;最新的项目需要用jdk17来编译&#xff0c;就把服务器的jdk版本升级到了17&#xff0c;但是有一些软件例如nexus还需要jdk1.8进…

Poetry是一个现代的Python包管理工具

Poetry是一个现代的Python包管理工具&#xff0c;它旨在简化包的声明、管理和发布过程。Poetry解决了Python项目中的一些常见问题&#xff0c;如依赖管理、包版本控制以及项目的打包和发布。它被设计为一站式的解决方案&#xff0c;提供了一系列的特性来处理Python包的生命周期…

学习vue3第十二节(组件的使用与类型)

1、组件的作用用途 目的&#xff1a; 提高代码的复用度&#xff0c;和便于维护&#xff0c;通过封装将复杂的功能代码拆分为更小的模块&#xff0c;方便管理&#xff0c; 当我们需要实现相同的功能时&#xff0c;我们只需要复用已经封装好的组件&#xff0c;而不需要重新编写相…

2024年数字IC秋招-海康威视-数字逻辑设计工程师-笔试题

文章目录 前言一、多选题1、下面属于AXI定义的传输通道的是2、在SystemVerilog语言中&#xff0c;如果想要约束随机变量x在a和b之间&#xff0c;以下代码中正确的是?3、UVM的通信接口类型包括哪些?4、常见的代码覆盖率收集包括哪些?5、关于linux和windows操作系统的使用&…