博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用linux下的c语言编程来简单的实现一个shell功能实现!
阅读量:2240 次
发布时间:2019-05-09

本文共 2243 字,大约阅读时间需要 7 分钟。

学习了fork(),exec()函数之后,让我们来简单是实现来实现一个shell

里面用到了一些函数,进行对字符串进行做一下简单的处理!

#include<stdio.h>

#include<errno.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<pwd.h>
#define NUM 1024
#define SIZE 50

int  mystrtok(char *argv[],char *string);

//这个函数做的是对字符串的分割,把命令分割开,用到了字符串的分割函数

int mystrtok(char *argv[],char *string)
{
 int i=0;
 char delim[]=" ";
 char *p;
 argv[0]=strtok(string,delim);//字符串分割函数的使用
 //printf("%s\n",argv[0]);
 while(argv[i]!=NULL)
 {
  argv[++i]=strtok(NULL,delim);
  //printf("%s is %d\n",argv[i],i);
 }
return 0;
}

//获得一个命令提示符的字符串

char *getusername(char buffer[NUM])
{
 uid_t userid;
 char *username;
 char *hostname;
 char *ptr,*p;
 char buf1[1024],buf2[1024];
 char *delim=".";
 int id;
 getwd(buf2);//这段代码说明的是对命令提示的路径获得
 username=getenv("USER");//调用getenv函数,来获得shell命令的提示中的用户名
 strcpy(buffer,username);
 strcat(buffer,"@");
 id=gethostname(buf1,sizeof buf1);//调用此函数来获取shell命令的提示中的主机名
 p=strtok(buf1,delim);//对主机进行截取
 strcat(buffer,p);//字符串的连接函数
 ptr=strrchr(buf2,'/');//字符串的从后往前进行截取的函数,讲多得shell命令提示中的路径
 //比较字符串,判断用户的路径是在"/","~",还是其他当中
 if(strcmp(ptr,"/")==0)
 {
  ptr="/";
 }
 else if(strcmp(ptr,"~")==0)
 {
  ptr="~";
 }
 else
 {
  ptr=strtok(ptr,"/");
  
 }

//把获得的 [用户名@主机名  路径]连接在一起

 strcat(buffer," ");
 strcat(buffer,ptr);
return buffer;
}
int main()
{
 pid_t pid;
 int status;
 char *argv[NUM];
 char buffer[NUM];
 char str[NUM];
 int j=-1;
 char *string=NULL;
 string=getenv("USER");

//当前用户是root用户还是普通用户,通过字符串的比较,如果是root,则返回0;

 if((strcmp(string,"root"))==0)
 {
  j=0;
 }
 while(1){

//通过调用上面自定义的getusername()函数,来得到shell命令中的提示

  printf("[%s]",getusername(buffer));
  //判断是使用root的提示#,还是其他用户的$

if(j==0)

  {
   printf("# ");
  }
  else
  { 

    printf("$ ");
  }

//字符串的输入,要用gets函数或者用fgets函数,因为scanf函数把空格看成字符串的结束

  gets(str);

//调用字符串的分割函数,获得要截取出来的命令和命令参数,例如:ls -a分别放到argv[0],argv[1]中

  status=mystrtok(argv,str);
  if(status!=0)
  {
   printf("fail to getargv!\n");
  }

//通过fork()函数来创建一个父进程和一个子进程

  pid=fork();
  if(-1==pid)
  {
   printf("your fork failed!\n");
  } 
  else if(pid==0)
  { 

//子进程用来对shell命令进程进程解释执行的

   if(argv[1]!=NULL)
   {
    execvp(argv[0],argv);
   }
   else if(argv[1]==NULL)
   {
    execlp(argv[0],argv[0],NULL,NULL);
   }
  }
  else
  {

//父进程用来等待子进程的结束,然后再循环输入shell命令

   if(wait(&status)==-1)
   {
    printf("wait failed!\n");
    exit(1);
   }
  
  }
 }
 return 0;
}

里面用到了很多的系统函数的调用,没有细细的解释说明,留给大家自学啦,哈哈!!

转载地址:http://laqbb.baihongyu.com/

你可能感兴趣的文章
【C++】构造函数、析构函数抛出异常的问题
查看>>
【C++】关于vector<bool>
查看>>
【操作系统】内存碎片产生原因及终极解决办法
查看>>
幂等性验证思想
查看>>
DB理论--数据存储方式
查看>>
PB协议的说明与使用
查看>>
什么是TPS,什么是QPS,区别是什么?
查看>>
git pull遇到错误:error: Your local changes to the following files would be overwritten by merge:
查看>>
arraylist扩容时机java8
查看>>
logback中additivity的理解
查看>>
一篇文章搞懂hash,hashcode,equals,==的用法
查看>>
mysql数据库,悲观锁。for update 的用法。
查看>>
springboot+jta+atomikos多数据源和 springboot+mybatisplus+aop实现数据库读写分离而引发的一些思考
查看>>
java面试中常考的一些面试sql语句
查看>>
一个字节等于多少位?
查看>>
帧框架frameset的用法总结
查看>>
java1.8中创建hashmap的初始化大小设置标准
查看>>
mark一下,service的实现层没有加@service注解。
查看>>
jq对象转换成js对象。已经jq的复合选择器。
查看>>
(一)alin‘s mysql学习笔记----概述
查看>>