linuxc 实现my_shell

问题
1.cd命令的实现(cd ,cd ~,cd -,cd path)

由于cd命令是shell 内建的命令,是不能调用系统的命令实现cd,所以就得手写

所用函数:

char * getcwd(char * buf, size_t size); //取得当前工作目录
buf 为所取得的路径,   size为所取的大小
int chdir(const char * path); //改变当前目录
path 为要切换的路径

因为要实现 cd -,所以要将每次的路径保存下来,(这里用cd_pathnametemp)保存

                getcwd(cd_pathname,100);
                if((argcount == 1)  || strcmp(arg[1],"~") == 0)  
                {
      
                        strcpy(cd_pathnametemp,cd_pathname);
                        my_chdir();   //更改家目录
                }   
                else if(strcmp(arg[1],"-") == 0)
                {
      
                //      strcpy(cd_pathnametemp,cd_pathname);
                        chdir(cd_pathnametemp);
                        strcpy(cd_pathnametemp,cd_pathname);
                }   
                else
                {
      
                        strcpy(cd_pathnametemp,cd_pathname);
                        chdir(arg[1]);    //更改当前工作目录
                }   
                
2.ls输出加颜色

因为ls 本身是不输出颜色的,而我们的shell 中能输出颜色是因为 用了别名

 alias ls='ls --color=auto'

所以在处理 ls 的时候,给它加上 - -color=auto参数就ok

3.屏蔽ctrl + c

一个优秀的程序是不会轻易的挂掉,所以不屏蔽ctrl + c 的话,用户一个ctrl + c 就会让程序挂掉,那样会有多尴尬.
而屏蔽ctrl + c也不难

 signal(SIGINT, SIG_IGN);

SIGINT :当用户按下了<ctrl + c >时,用户终端向正在运行中的由该终端启动的程序发出此信号,默认为终止进程.而进程终止后,程序自然也就被终止了
SIG_IGN : 忽略该信号

4.命令自动补全

了解了之后,发现readline 这个库是真的强大,有许多特别好用,方便的函数,下面的history也是这个库里的函数

自动补全这个功能需要用Readline 库 ,没有的话需要安装

			sudo apt-get install libreadline6-dev 

因为readline 是动态链接库 所以 ,编译的时候 需要加上 -lreadline
要加头文件

#include<readline/readline.h>

        char * str = readline(" ");
5.通过上下查找历史命令

头文件

#include<readline/history.h>

同样,编译的时候需要加上 -lreadline

        add_history(str);

每次将所读取的命令加到 add_history()中就ok了.

对readline还不是很熟悉的可以做个小测试熟悉一下

6.将my_shell 设置环境变量,使程序可以像bash,zsh这种shell一样运行;

这个问题就将my_shell 的可执行程序 加在 /bin 下就搞定了.

以上就是这次shell 的主要问题.
其他问题
    1. 支持输入输出重定向(< > >>)
    2. 支持管道(|)
    3. 支持后台运行程序(&)
看源码就可以搞定,我就不再赘述.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<dirent.h>
#include<pwd.h>
#include<readline/readline.h>
#include<readline/history.h>


#define normal  0 //一般命令
#define out_redirect  1  //输出重定向
#define in_redirect 2 //输入重定向
#define have_pipe   3  //命令中有管道
#define add_out_redirect 4
#define add_in_redirect 5
#define CLOSE "\001\033[0m\002"                 // 关闭所有属性
char cd_pathnametemp[PATH_MAX] = "/home/tt";    //默认家目录
char cd_pathname[PATH_MAX];


void print_prompt();   //打印提示符  
void get_input(char *);   //得到输入的命令
void explain_input(char *,int *,char a[ ][256]);  //对输入命令进行解析
void do_cmd(int ,char a[ ][256]);  //执行命令
int find_command(char *);    //查找命令中的可执行程序
void my_dir();//cd 到家目录
int main(int argc,char **argv)
{
   
	 signal(SIGINT, SIG_IGN);
	int i;
	int argcount = 0; //记录 命令的个数
	char arglist[100][256];   //存储命令
	char **arg = NULL;
	char *buf = NULL;

	buf = (char *)malloc(256);
	if(buf == NULL)
	{
   
		perror("malloc failed\n");
		exit(-1);
	}


	while(1)
	{
   
		memset(buf,0,sizeof((buf)));
		print_prompt();   //输出命令提示符
		get_input(buf);   //获取输入
		//若输入的命令为 exit 或 logout 则退出本程序
		if(strcmp("exit\n",buf) == 0 || strcmp("logout\n",buf) == 0)  break;
		if(strcmp(buf,"\n") == 0) continue;
		//清空 arglist 
		for(i = 0;i < 100;i++)    arglist[i][0] = '\0';
		argcount = 0;//命令个数 清0


		explain_input(buf,&
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值