【问题标题】:issues while writing a shell in c在 c 中编写 shell 时出现问题
【发布时间】:2017-03-25 11:02:16
【问题描述】:

我正在尝试用 c 编写一个 shell 程序。 该程序需要具有由 fork 函数创建的多个进程,并且能够在一个命令中打印多个输出行。 比如linux终端,如果输入是“ls ; ps ; pwd ;”,输出应该是这样的。

$./shell
shell> ls ; ps ; pwd ;
(ls output)
(ps output)
(pwd output) 

它应该能够打开一个文件并显示该文件包含的命令列表和输出。(我猜是批处理模式?)

假设这些命令列表在批处理文件中。

batch
1 ls 
2 ps
3 ls ; pwd ; ps

输出是

$./shell batch
shell> ls
shell> (ls output)
shell> ps
shell> (ps output)
shell> ls ; pwd ; ps
shell> (ls output)
(ps output)
(pwd output)

这是我写的代码

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>

void command(char* myargs[][10], char* buffer);
int tokenizing(char* myargs[][10], char* buffer);

int main(int argc, char* argv[]) {

    int fd;
    char buffer[200];
    char* myargs[10][10];
    char* token;

    if(argc >= 2) {
        if((fd=open(argv[1], O_RDONLY)) == -1)
            printf("cannot open file\n");
        else {
            read(fd, buffer, 200);
            printf("%s\n", buffer);
            token = strtok(buffer, "\n");
            while(token != NULL) {
                printf("%s\n", token);
                command(myargs, token);
                token = strtok(NULL, "\n");
            }
            return 0;
        }
    }



    while(1) {
        printf("prompt> ");
        if(fgets(buffer, 200, stdin) == NULL||
                strcmp(buffer, "quit\n") == 0)
            break;
        command(myargs, buffer);
    }

    return 0;
}

void command(char* myargs[][10], char* buffer) {

    int rc = fork();

    if(rc < 0) {
        fprintf(stderr, "fork failed\n");
    } else if(rc == 0) {

        int n = tokenizing(myargs, buffer);

        for(int i = 0 ; i < n; i++) {

            int rc2 = fork();
            if(rc2 < 0) {
                fprintf(stderr, "for failed\n");
            } else if(rc2 == 0) {
                execvp(myargs[i][0], myargs[i]);
                printf("%s: command not found\n", myargs[i][0]);
                exit(0);
            } else {
                wait(NULL);
            }
        }
        exit(0);
    }
    else {

        wait(NULL);


    }
}

int tokenizing(char* myargs[][10], char* buffer) {

    int i = 0;
    int j = 0;
    int k = 0;

    char* token;
    char* subCommand[10];

    token = strtok(buffer, ";\n");

    while(token != NULL) {
        subCommand[k] = token;
        k++;
        token = strtok(NULL, ";\n");
    }


    for(int i = 0; i < k; i++) {
        token = strtok(subCommand[i], " \n");
        while(token != NULL) {
            myargs[i][j] = token;
            j++;
            token = strtok(NULL, " \n");
        }
        myargs[i][j] = NULL;
        j=0;
    }
}

此代码运行良好,但存在一些问题。当此代码与批处理文件一起运行时,我遇到了一些错误。

当程序执行时,我认为输出应该像上面的图像文件 - 据我所知。

但程序经常会出现一些我什至没有输入的奇怪命令行。这些结果只是交替发生。

此外,如果您看到“ps”列表,您可以看到两个 shell 程序正在运行。

你们能帮我解决这些问题吗?

【问题讨论】:

    标签: c linux shell fork


    【解决方案1】:
    C 中的

    'strings' 需要一个 NUL 终止符。在未安全 NUL 终止的字符数组上调用 printf("%s....") 和 strtok() 等 strng 函数会导致未定义的行为。

    read() 返回一个值。您可以使用它将终结器加载到“缓冲区”中。为了超级安全,您应该尝试只读取 [buffer size -1] 字符以确保始终有足够的空间用于终止符,例如:

    buffer[read(fd, buffer, 199)]='\0';
    

    【讨论】:

    • 为了超级安全,最好先检查read()返回值,看它是否为负,然后再将其用作索引。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 2017-05-18
    相关资源
    最近更新 更多