Linux shell内部命令实现 模拟终端(仅内部命令)

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<string.h>
#include <unistd.h>
#include<glob.h>
#define DEMLIMS " \t\n"

struct cmd_st
{
        glob_t globres;
};

//打印命令行提示
static void prompt(void)
{
        printf("mysh-$ ");
}

//解析拆分linebuf并存到glob_t中
static void parse(char*linebuf,struct cmd_st* cmd)
{
        char* str;
        glob_t globres;
        int i=0;
        while(1)
        {
                //将输入信息按照空格回车tab分割
                str=strsep(&linebuf,DEMLIMS);
                if(str==NULL)
                {
                        break;
                }
                //命令中存在空格连串的 例如 ls      -l
                if(str[0]=='\0')
                {
                        continue;
                }
                //将解析到的命令追加到globres中 仅第一次不追加(原因gl_pathc和gl_pathv一开始为随机值) *优先级高于|
                glob(str,GLOB_NOCHECK|GLOB_APPEND*i,NULL,&(cmd->globres));
                i=1;
        }


}

int main(int argc,char** agv)
{
        pid_t pid;
        char* linebuf=NULL;
        size_t linebuf_size=0;
        struct cmd_st cmd;
        while(1)
        {
                //打印命令提示行
                prompt();
                //获取外部输入 返回值小于0,则函数出现错误
                if(getline(&linebuf,&linebuf_size,stdin)<0)
                        break;
                //解析外部输入
                parse(linebuf,&cmd);

                if(0)  //外部命令
                {

                }
                else   //内部命令
                {

                        pid=fork();
                        if(pid<0)
                        {
                                perror("fork()");
                                exit(1);
                        }
                        if(pid==0)//子进程
                        {
                                //输入的命令名找到其命令,跳转命令
                                execvp(cmd.globres.gl_pathv[0],cmd.globres.gl_pathv);

                                perror("execvp()");
                                exit(1);
                        }
                        else  //回收子进程
                        {
                                wait(NULL);
                        }
                }
        }
        exit(0);

}
~

结果展示:

book@100ask:~/tmpfile/process_basic$ make mysh
cc     mysh.c   -o mysh
book@100ask:~/tmpfile/process_basic$ ./mysh
mysh-$ ls
execl_date    few    fork0    fork1    fork2    forkwait0    mysh
execl_date.c  few.c  fork0.c  fork1.c  fork2.c  forkwait0.c  mysh.c
mysh-$ date
Sun Oct 27 04:10:57 EDT 2024
mysh-$ ps axf
   PID TTY      STAT   TIME COMMAND
     2 ?        S      0:00 [kthreadd]
     3 ?        I<     0:00  \_ [rcu_gp]
     4 ?        I<     0:00  \_ [rcu_par_gp]
     6 ?        I<     0:00  \_ [kworker/0:0H-kb]
     8 ?        I<     0:00  \_ [mm_percpu_wq]
     9 ?        S      0:00  \_ [ksoftirqd/0]
    10 ?        I      0:18  \_ [rcu_sched]
    11 ?        S      0:00  \_ [migration/0]

外部命令不可实现:

mysh-$ cd
execvp(): No such file or directory

扩展,将该函数应用到用户作为其shell:

步骤1:登录root
book@100ask:~/tmpfile/process_basic$ su -
Password:
root@100ask:~#

步骤2:将mysh复制到指定目录下
root@100ask:~# cp /home/book/tmpfile/process_basic/mysh /usr/local/bin/mysh

步骤3:创建要运用这个的用户,设置密码
root@100ask:~# useradd john
root@100ask:~# passwd john
Enter new UNIX password:

步骤4:进入passwd文件  修改用户john最后的路径为mysh的路径
root@100ask:~# vim /etc/passwd
修改文件
john:x:1002:1002::/home/john:/usr/local/bin/mysh

步骤5:更改登录用户,可见mysh替代了shell但仅可使用shell内部命令
root@100ask:~# su - john
No directory, logging in with HOME=/
mysh-$ ls
bin    dev   initrd.img      lib32   lost+found  opt   run   srv  usr      vmlinuz.old
boot   etc   initrd.img.old  lib64   media       proc  sbin  sys  var
cdrom  home  lib             libx32  mnt         root  snap  tmp  vmlinuz
mysh-$ date
Sun Oct 27 04:21:46 EDT 2024
mysh-$

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值