c - 用 C 实现的 UNIX 命令

标签 c linux unix operating-system

对于我的操作系统类(class),我有一项作业是基于之前的作业而完成的。不幸的是,除了我不知道下一个项目需要从哪里开始之外,我之前的项目无法正常工作。我下面的代码假设模仿一个简单的 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 级缩进的东西 - 听说过 arrow code

关于c - 用 C 实现的 UNIX 命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9339472/

相关文章:

linux - UDP 服务器进程无法接受来自内核的数据包

linux - 无法在 Amazon Linux 实例上运行后台进程,但在 MAC OS X 上运行

bash - 如何在 shell 中向下移动一行?

node.js - 使用 Jenkins 时永远无法启动

c - 简单管道程序出现此错误 - 'Program received signal SIGPIPE, Broken pipe'

c - 关闭文件需要什么?

c - 将单指针和双指针传递给c中的函数

java - C和Java之间的线程终止区别

php - 如何通过 php (Linux) 获取系统接口(interface)的 MAC 地址

linux - 如何使用 awk 修改文本字段?