IO、进程、线程04

练习题:实现伪终端

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <sys/wait.h>  
#include <pwd.h> 
#include <sys/types.h>  
#include <netdb.h> 
#include <unistd.h> 
  
// 读取一行输入,移除末尾的换行符  
char* getLine(char* buf, int size) {  
    fgets(buf, size, stdin);  
    int len = strlen(buf);  
    if (buf[len - 1] == '\n') {  
        buf[len - 1] = 0; // 替换换行符为字符串结束符  
    }  
    return buf; // 返回修改后的字符串  
}  
  
int main(int argc, const char *argv[]) {  
    while (1) { // 死循环,直到程序被外部方式终止  
        int retval = fork(); // 创建子进程  
        if (retval > 0) {  
            wait(0); // 父进程等待子进程结束  
        } else if (retval == 0) { // 子进程分支  
            char* username = getlogin(); // 获取当前登录用户名  
            char hostname[64] = {0};  
            char pwd[128] = {0};  
            gethostname(hostname, 64); // 获取主机名  
            getcwd(pwd, 128); // 获取当前工作目录  
  
            // 打印提示符  
            printf("\033[1;32;10m%s@%s\033[0m:\033[1;34;10m%s\033[0m$ ", username, hostname, pwd);  
            fflush(stdout); // 清空输出缓冲区,确保提示符立即显示  
  
            char* arg[20] = {0}; // 分配命令参数数组  
            char cmd[128] = {0}; // 存储用户输入的命令  
            getLine(cmd, 128); // 读取用户输入的命令  
  
            char* token = NULL; 
            int i = 0;  
            do {  
                if (token == NULL) {  
                    token = strtok(cmd, " "); // 首次调用strtok  
                } else {  
                    token = strtok(NULL, " "); // 后续调用strtok  
                }  
                arg[i++] = token; // 将token添加到参数数组中  
            } while (token != NULL); // 循环直到没有更多token  
  
            // 特殊处理cd命令  
            if (strcmp(arg[0], "cd") == 0) {  
                if (arg[1] != NULL) { // 确保有cd的目标目录  
                    chdir(arg[1]); // 改变工作目录  
                }  
            } else {  
                execvp(arg[0], arg); // 执行用户命令  
                // 如果execvp返回,说明命令未找到或出错  
                perror("execvp failed"); // 打印错误信息  
            }  
            // 注意:这里没有返回语句,因为execvp在成功时不会返回  
            // 如果execvp失败,子进程会执行到这里,但通常我们会希望终止它  
            // 可以通过exit(EXIT_FAILURE)来退出子进程  
            exit(EXIT_FAILURE);  
        } else {  
            // fork失败的情况  
            perror("fork failed");  
            exit(EXIT_FAILURE);  
        }  
    }  
    return 0;
}

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 08:28:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 08:28:04       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 08:28:04       58 阅读
  4. Python语言-面向对象

    2024-07-19 08:28:04       69 阅读

热门阅读

  1. C语言13 位域

    2024-07-19 08:28:04       22 阅读
  2. Linux:使用vim编辑文件为什么会影响目录的mtime

    2024-07-19 08:28:04       17 阅读
  3. 数据结构讲解

    2024-07-19 08:28:04       20 阅读
  4. C++:类的定义和实例化

    2024-07-19 08:28:04       21 阅读
  5. NumPy库学习之logspace函数

    2024-07-19 08:28:04       21 阅读
  6. springMVC前后端请求参数绑定和传递

    2024-07-19 08:28:04       17 阅读
  7. C++中的socket编程常用接口

    2024-07-19 08:28:04       19 阅读
  8. Redis实现打卡功能

    2024-07-19 08:28:04       20 阅读
  9. 探索.NET内存之海:垃圾回收的艺术与实践

    2024-07-19 08:28:04       22 阅读
  10. 【.NET全栈】ASP.NET开发Web应用——Web部件技术

    2024-07-19 08:28:04       18 阅读
  11. 基于Gunicorn、Flask和Docker的高并发部署

    2024-07-19 08:28:04       20 阅读