用 C 实现的 UNIX 命令

2024-01-21

对于我的操作系统课程,我有一个作业,该作业是建立在之前作业的基础上的。不幸的是,除了我不知道下一个项目需要从哪里开始之外,我之前的项目无法正常工作。我下面的代码假设模仿一个简单的 UNIX/Linux shell,其中包含一些无法使用 execvp 执行的附加命令:通过 & 运算符进行后台处理,“jobs”shell 命令:列出所有活动子进程的 pid(即不是那些已经终止的进程)、“僵尸”进程的“收获”以及“cd”shell 命令:更改 shell 的工作目录。

我相信,除了“jobs”命令和“cd”命令之外的所有命令都可以工作,但我不确定为什么这两个命令不起作用。

下一个任务是以“mysh$ cmd arg1 arg2 argN > file.out”的形式添加一些 I/O 重定向,我什至不知道从哪里开始......

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
#include <sys/types.h>

int main(int argc, char **argv) {
    char bBuffer[BUFSIZ], *pArgs[10], *aPtr = NULL, *sPtr;
    int jobs[100];
    int jobList = 0;
    int background;
    ssize_t rBytes;
    int aCount;
    pid_t pid;
    int status;
    while(!feof(stdin)) {
        pid = waitpid(-1, &status, WNOHANG);
        if (pid > 0)
        printf("waitpid reaped child pid %d\n", pid);
        write(1, "\e[1;31mmyBash \e[1;32m# \e[0m", 27);
        rBytes = read(0, bBuffer, BUFSIZ-1);
        if(rBytes == -1) {
        perror("read");
        exit(1);
    }

    bBuffer[rBytes-1] = '\0';
    if(!strcasecmp(bBuffer, "exit")){ 
        exit(0);
    }

    sPtr = bBuffer;
    aCount = 0;
    do {
        aPtr = strsep(&sPtr, " ");
        pArgs[aCount++] = aPtr;
    } while(aPtr);
        background = (strcmp(pArgs[aCount-2], "&") == 0);
        if (background)
        pArgs[aCount-2] = NULL;

        if (strlen(pArgs[0]) > 1) {
            pid = fork();
            if (pid == -1) {
                perror("fork");
                exit(1);
            } else if (pid == 0) {
                jobs[jobList] = pid;
                jobList++;

                if(!strcasecmp(pArgs[0], "jobs")){                                         
                    for(int i; i<jobList; i++) {
                        if(kill(jobs[i],0)==0){
                            printf(jobs[i]);    
                        }
                        printf("these are jobs\n");
                        exit(1);
                    }
                    if(!strcasecmp(pArgs[0], "cd")){ 
                        int ret;
                        if (!pArgs[1])
                            strcpy(bBuffer, "pwd");
                        ret = chdir(pArgs[1]);
                        strcpy(bBuffer, "pwd");
                        exit(1);
                    }                                
                    fclose(stdin);
                    fopen("/dev/null", "r");
                    execvp(pArgs[0], pArgs);
                    exit(1);
                } else if (!background) {
                    pid = waitpid(pid, &status, 0);
                    if (pid > 0)
                        printf("waitpid reaped child pid %d\n", pid);
                }
        }
    }
    return 0;
}

首先,您需要解析您的行并检测您是否需要重定向到文件。假设你使用strsep或其他什么,你发现输出将是file.out或输入来自file.in.

此时您想使用重定向输出dup / dup2。例如,重定向STDOUT:

int
do_redirect(int fileno, const char *name)
{
    int newfd;

    switch (fileno) {
    case STDOUT_FILENO:
        newfd = open(name, O_WRONLY | O_CREAT, S_IRUSR | S_IRUSR);
        break;
    }
    if (newfd == -1) {
        perror("open");
        return -1;
    }

    return dup2(fileno, newfd);
}
/* ... */


pid = fork();
do_redirect(STDOUT_FILENO, name);

注意事项:

  • 我没有测试代码 - 它甚至可能无法编译
  • 我没有做太多错误检查 - 你应该(就像我做的那样)open)
  • 你需要实施STDIN_FILENO自行重定向
  • 请注意我如何使用一个单独的函数,你的main实在是太大了
  • 你的代码有类似 7 级缩进的东西 - 听说过箭头代码 http://www.codinghorror.com/blog/2006/01/flattening-arrow-code.html ?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用 C 实现的 UNIX 命令 的相关文章

  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • 通过 Visual Studio 2017 使用远程调试时 Linux 控制台输出在哪里?

    我的Visual Studio 2017 VS2017 成功连接Linux系统 代码如下 include
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐