1

我有一个用 C 编写的 shell 程序,当我尝试运行命令“ls |”时 (只是 ls 和一个管道,后面什么都没有),我的程序永远循环。您可以忽略 modePtr... 这个解析器所做的是从用户输入中获取一串字符,因此它正在解析命令“ls |” 我猜问题在于没有一个“案例”会导致空管道命令落入,从而导致无限循环?有什么建议么?

int parse(char *inputString, char *cmdArgv[], char **supplementPtr, int *modePtr)
{
int cmdArgc = 0, terminate = 0;
char *srcPtr = inputString;
//printf("parse fun%sends", inputString);
while(*srcPtr != '\0' && terminate == 0)
{
    *cmdArgv = srcPtr;
    cmdArgc++;
    //printf("parse fun2%sends", *cmdArgv);
    while(*srcPtr != ' ' && *srcPtr != '\t' && *srcPtr != '\0' && *srcPtr != '\n' && terminate == 0)
    {
        // Handles redirection/pipes
        switch(*srcPtr)
        {
            // Background mode
            case '&':
                *modePtr = BACKGROUND;
                break;
            // Output mode
            case '>':
                *modePtr = OUTPUT_REDIRECTION;
                *cmdArgv = '\0';
                srcPtr++;
                if(*srcPtr == '>')
                {
                    *modePtr = OUTPUT_APP;
                    srcPtr++;
                }
                while(*srcPtr == ' ' || *srcPtr == '\t' || *srcPtr == '\0')
                    srcPtr++;
                *supplementPtr = srcPtr;
                chop(*supplementPtr);
                terminate = 1;
                break;
            // Input mode
            case '<':
                *modePtr = INPUT_REDIRECTION;
                *cmdArgv = '\0';
                srcPtr++;
                while(*srcPtr == ' ' || *srcPtr == '\t' || *srcPtr == '\0')
                    srcPtr++;
                *supplementPtr = srcPtr;
                chop(*supplementPtr);
                terminate = 1;
                break;
            // Pipe mode
            case '|':
                *modePtr = PIPELINE;
                *cmdArgv = '\0';
                srcPtr++;
                while(*srcPtr == ' ' || *srcPtr == '\t' || *srcPtr == '\0')
                    srcPtr++;
                *supplementPtr = srcPtr;
                //chop(*supplementPtr);
                terminate = 1;
                break;
        }
        srcPtr++;
    }
    // Process commands when these occur
    while((*srcPtr == ' ' || *srcPtr == '\t' || *srcPtr == '\n') && terminate == 0)
    {
        *srcPtr = '\0';
        srcPtr++;
    }
    cmdArgv++;
}
/*srcPtr++;
*srcPtr = '\0';
destPtr--;*/
*cmdArgv = '\0';
return cmdArgc;
}
4

2 回答 2

2

如果您ls |在普通 shell 中尝试,它会在尝试启动任何内容之前提示您输入管道的其余部分(另一个命令)。没有命令读取输出的管道是无稽之谈。

这个成语(在代码中重复了几次)被打破了:

srcPtr++;
while (*srcPtr == ' ' || *srcPtr == '\t' || *srcPtr == '\0')
    srcPtr++;

您不能跳过'\0'字符串末尾的 null !您立即陷入“未定义的行为”。您需要查看循环逻辑,也许是为了:

srcPtr++;
while (*srcPtr == ' ' || *srcPtr == '\t')
    srcPtr++;
if (*srcPtr == '\0')
    ...no more data in string...
于 2013-04-17T14:37:48.233 回答
2

你可能把问题复杂化了。如果您希望程序读取通过管道传输给它的列表项...

#define MAXLINELEN 1000
#include <stdio.h>
#include <stdlib.h>

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

    char line[MAXLINELEN];
    FILE *fpin;

    fpin=stdin;

    while(fgets(line,MAXLINELEN,fpin)!=NULL) printf("%s",line);

}

...然后您可以使用 strtok() 解析每行上的项目,或者如果您使用“ls -1”,则每个列表项无论如何都在唯一的行上。

希望这可以帮助。

于 2013-04-17T17:49:55.940 回答