简体   繁体   English

C中的Shell程序具有奇怪的fork行为

[英]Shell program in C has odd fork behaviour

I am writing a C program to emulate a simple shell. 我正在编写一个C程序来模拟一个简单的shell。 This shell will basically evaluate commands like any other shell (ls, cat, etc.), as well as handle pipelining and redirection. 此外壳程序基本上将评估任何其他外壳程序(如ls,cat等)的命令,并处理流水线和重定向。

Currently, I am trying to start out by getting user input, tokenizing it, and executing the command provided (eg executing only "ls" and not "ls -l"). 当前,我试图通过获取用户输入,将其标记化并执行所提供的命令(例如仅执行“ ls”而不执行“ ls -l”)来开始。 However, I am having a lot of difficulty with the forking. 但是,我在分叉方面遇到很多困难。 It seems that every time I fork, something goes wrong and hundreds of identical processes are created, leading to my computer freezing and me having to restart. 似乎每次我分叉时,都会出问题,并且创建了数百个相同的进程,导致我的计算机死机,不得不重新启动。 The code appears to be correct, but I have no idea what is causing this behaviour. 该代码似乎是正确的,但是我不知道是什么导致了这种行为。 Below is the relevant portion of my code (main method and input tokenizer method). 以下是我代码的相关部分(main方法和input tokenizer方法)。

int main() {
    char inputLine[512];    //user input
    char *args[10];         //arguments
    char* pathVar = "/bin/";//path for argument
    char programPath[512];  //pathVar + args[0]
    int n;                  //count variable

    //loop
    while (1) {
        //print prompt, get input
        printf("input> ");
        fgets(inputLine, 512, stdin);
        n = tokenizer(inputLine, args);

        //fork process
        pid_t pid = fork();

        if (pid != 0) {     //if parent
            wait(NULL);
        } else {            //if child
            //format input for execution
            strcpy(programPath, pathVar);
            strcat(programPath, args[0]);

            //execute user command
            int returnVal = execv(programPath, args);
        }
    }

    return 0;
}

int tokenizer(char *input, char *args[]) {
    char *line;             //current line
    int i = 0;              //count variable

    line = input;
    args[i] = strtok(line, " ");
    do {
        i++;
        line = NULL;
        args[i] = strtok(line, " ");
    } while (args[i] != NULL);

    return i;
}

Putting it all together: You need to check fork and execv for failure. 放在一起:您需要检查forkexecv是否失败。 You should exit after an execv failure (and perhaps after a fork failure). 您应该在execv失败后(可能在fork失败后) exit And you need to add \\n to the strtok delimiters (or remove the newline from the input line in some other way). 并且您需要在strtok分隔符中添加\\n (或以其他方式从输入行中删除换行符)。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MAXARGS 10
#define PATH "/bin/"

int main() {
    char inputLine[BUFSIZ];
    char *args[MAXARGS];
    char programPath[BUFSIZ + sizeof(PATH) + 10];

    while (1) {
        printf(":-> ");
        if (fgets(inputLine, BUFSIZ, stdin) == NULL) /* ctrl-D entered */
            break;

        tokenize(inputLine, args);

        pid_t pid = fork();
        if (pid == -1) {
            perror("fork");
            exit(EXIT_FAILURE);
        }

        if (pid != 0) {  /* parent */
            wait(NULL);

        } else {         /* child */
            strcpy(programPath, PATH);
            strcat(programPath, args[0]);

            execv(programPath, args); /* will not return unless it fails */

            perror("execv");
            exit(EXIT_FAILURE);
        }
    }

    return 0;
}

int tokenize(char *input, char *args[]) {
    int i = 0;

    args[0] = strtok(input, " \n");
    for (i = 0; args[i] && i < MAXARGS-1; ++i)
        args[++i] = strtok(NULL, " \n");

    return i;
}

You should check that execv doesn't fail and also be sure to exit() at the end of the child block. 您应该检查execv是否不会失败,并确保在子块末尾退出()

            //execute user command
            int returnVal = execv(programPath, args);

            // check return from execv
            if (returnVal < 0) {
                perror("execv");
                exit(1);
            }

Also, beware using functions like strcpy in this context since they may lead to buffer overflows. 另外,在这种情况下,请提防使用诸如strcpy之类的函数,因为它们可能会导致缓冲区溢出。 If an untrusted attacker type is talking to your shell this type of security issue could let them break out of the "sandbox". 如果一种不受信任的攻击者类型正在与您的外壳进行通信,则这种类型的安全问题可能会让他们脱离“沙盒”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM