[Linux]实现minishell

  • 通过进程控制的学习, 来制作一个minishell

Shell基本上是一个命令解释器,类似于DOS下的command。它接收用户命令(如ls等),然后调用相应的应用程序。
— 百度百科

在这里插入图片描述

代码实现

#include <stdio.h>                                                                                  
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <sys/wait.h>
 
int main()
{
     while(1)
     {
         // 1. 等待用户标准输入 
         printf("[username@localhost]$ ");
         fflush(stdout); // 刷新缓冲区, 不换行
         char cmd_buf[1024] = {0};
         fgets(cmd_buf, 1023, stdin); // 从标准输入读取数据
         cmd_buf[strlen(cmd_buf) - 1] = '\0';// cmd_buf最后是一个换行, 把它去掉
        
         // 2. 将输入结果拆分开
         char* argv[32] = {NULL};
         int argc = 0;
         char* ptr = cmd_buf;
         while(*ptr != '\0')
         {
             if (!isspace(*ptr))
             {
                 argv[argc] = ptr;
                 argc++;
                 while(!isspace(*ptr) && *ptr != '\0')
                 {                                                                                   
                     ptr++;
                 }
                 *ptr = '\0';
             }
             ptr++;
        }
         argv[argc] = NULL;
         int i;
         for (i = 0; i < argc; i++)
         {
             printf("argv[%d]=[%s]\n", i, argv[i]);    
         }
         
         // 3. 创建子进程, 在子进程中进行程序替换
         pid_t pid = fork();
         if (pid < 0)
         {
             // shell不能因为一次出错而退出                                                          
             continue;
         }
         else if (pid == 0)
         {
             // 子进程运行程序
            // 使用程序替换
             execvp(argv[0], argv);
             // 若程序替换失败, 因为子进程运行的代码和父进程的一样
             // 替换失败, 则子进程成为了另一个shell
             // 这不是想要的, 一个终端不需要多个shell
             // 因此替换失败, 则子进程直接退出
             exit(0);
         }
         
         // shell程序等待子进程退出
         wait(NULL);
     }
     return 0;                                                                                       
}

运行效果

[test@localhost ~]$ make
gcc minishell.c -o minishell
[test@localhost ~]$ ./minishell 
[username@localhost]$ ls -a
argv[0]=[ls]
argv[1]=[-a]
.	       .bash_profile  ForkTest	minishell    .pki    test     .VimForCpp
..	       .bashrc	      .lesshst	minishell.c  shm     test2    .viminfo
.a.c.swp       .cache	      .LfCache	mkfifo	     signal  test2.c  .vimrc
.bash_history  .config	      .local	.mozilla     .ssh    test.c   .ycm_extra_conf.py
.bash_logout   .cquery	      makefile	PipeTest     .swp    .vim
[username@localhost]$ ls -l
argv[0]=[ls]
argv[1]=[-l]
总用量 52
drwxrwxr-x. 2 test test  100 1月   7 20:18 ForkTest
-rw-rw-r--. 1 test test   97 1月   7 20:52 makefile
-rwxrwxr-x. 1 test test 9064 1月   7 21:33 minishell
-rw-rw-r--. 1 test test 1868 1月   7 21:33 minishell.c
drwxrwxr-x. 2 test test  103 12月 11 16:27 mkfifo
drwxrwxr-x. 2 test test   48 12月 11 15:34 PipeTest
drwxrwxr-x. 3 test test  105 1月   7 12:16 shm
drwxrwxr-x. 2 test test   78 12月 14 21:19 signal
-rwxrwxr-x. 1 test test 8808 12月  1 21:13 test
-rwxrwxr-x. 1 test test 8760 12月  1 21:32 test2
-rw-rw-r--. 1 test test  505 12月  1 21:44 test2.c
-rw-rw-r--. 1 test test  519 12月  1 21:28 test.c
[username@localhost]$ cat test.c
argv[0]=[cat]
argv[1]=[test.c]
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main()
{
    int fd;
    umask(0);
    const char* filename = "/home/test/a.txt";
    fd = open(filename, O_RDWR|O_APPEND, 0664);
    if (fd < 0)
    {
        perror("open error!");
        return -1;
    }
    char string[] = "hello IO!\n"; 
    const char* buf = "good!\n";
    write(fd, string, strlen(buf));
    write(fd, string, strlen(string));
    close(fd);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值