简易的自定义Shell实现

1. 程序概述

首先,让我们了解一下这个自定义Shell的主要功能和结构。该Shell具有以下特点:

  1. 基本的命令解析和执行
  2. 内建命令支持(cd、export、echo)
  3. 获取用户名、主机名和当前工作目录显示
  4. 错误代码传递和显示

2. 主要函数解析

2.1 getcommand

int getcommand(char* command)
{
  printf("[%s%s %s]# ",getUsername(),getHostname(),getPWDname());
  char* r = fgets(command,MAXIN,stdin);
  if(r == NULL) return 0;
  command[strlen(command)-1] = '\0';
  return 1; 
}

此函数用于获取用户输入的命令,并将其存储在指定的字符数组中。它显示包含用户名、主机名和当前工作目录的命令提示符。

2.2 commandsplit

void commandsplit(char* in, char* out[])
{
  int argc = 0;
  out[argc++] = strtok(in,SEPARATOR);
  while( out[argc++] = strtok(NULL,SEPARATOR));
 return ; 
}

commandsplit 函数将输入的命令字符串分割成命令和参数的数组,并用 SEPARATOR 定义的分隔符进行切割。

2.3 execute

void execute(char* agrv[])
{
    pid_t id = fork();
    if(id == 0)
    {
     execvp(agrv[0],agrv); 
      exit(1);
    }
    else
    {
      int status = 0;
      pid_t rid = waitpid(id,&status,0);
      if(rid > 0 ) 
      {
          lostcode = WEXITSTATUS(status);
      }
    }
}

execute 函数使用 fork 创建子进程,并在子进程中执行用户输入的命令。父进程等待子进程执行完成,并获取子进程的退出状态。

2.4 builtin

int builtin(char* argc[])
{
    if(strcmp(argc[0],"cd") == 0)
    {
      
      cd(argc);
      return 1;
    }
    else
    {
        printf("%s\n",getenv(e));
        return 1;
    }
    return 0;
}

builtin 函数用于处理内建命令,如 cd、export 和 echo。它通过比较命令字符串来确定是否为内建命令,并调用相应的功能函数执行。

3. 完整程序

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAXIN 100
#define SIZE 100
#define SEPARATOR " "

int lostcode = 0;
char cwd[1024];  
char env[1024];

char* getUsername()
{
  return getenv("USER");
}
char* getHostname()
{
  return getenv("HOSTNAME");
}
char* getPWDname()
{
  return getenv("PWD");
}
int getcommand(char* command)
{
  printf("[%s%s %s]# ",getUsername(),getHostname(),getPWDname());
  char* r = fgets(command,MAXIN,stdin);
  if(r == NULL) return 0;
  command[strlen(command)-1] = '\0';
  return 1; 
}
void commandsplit(char* in,char* out[])
{
  int argc = 0;
  out[argc++] = strtok(in,SEPARATOR);
  while( out[argc++] = strtok(NULL,SEPARATOR));
  return ; 
}
void execute(char* agrv[])
{
    pid_t id = fork();
    if(id == 0)
    {
     execvp(agrv[0],agrv); 
      exit(1);
    }
    else
    {
      int status = 0;
      pid_t rid = waitpid(id,&status,0);
      if(rid > 0 ) 
      {
          lostcode = WEXITSTATUS(status);
      }
    }
}
void cd(char* argc[])
{
  char* path = argc[1];
  chdir(path);
  getcwd(path,1024); 
  sprintf(cwd,"PWD=%s",path);
  putenv(cwd);
}
int builtin(char* argc[])
{
    if(strcmp(argc[0],"cd") == 0)
    {
      cd(argc);
      return 1;
    }
    else if(strcmp(argc[0],"export") == 0)
    {
      if(argc[1] == NULL) return 1;
      strcpy(env,argc[1]);  
        
        putenv(env);
        return 1;
    }
    else if(strcmp(argc[0],"echo") == 0)
    {
      char* e = argc[1]+1;
      if(strcmp(e,"?") == 0)
      {
        printf("%d\n",lostcode);
        return 1;
      }
      else
      {
          printf("%s\n",getenv(e));
          return 1;
      }
    }
    return 0;
}
int main()
{
  while(1)
  {
      char command[MAXIN];
    //获取命令
    if(!getcommand(command)) return 1;
    //字符串分隔
    char* argv[SIZE];
    commandsplit(command,argv);
    //是否是内建命令
    int n = builtin(argv);
    if(n) continue;
    //指令执行
    execute(argv);  
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值