Search code examples
cshellpipels

How to handle ls | "pipe" command in C


I have a shell program written in C, and when I try to run the command "ls |" (Just ls and a pipe with nothing after it), my program loops forever. You can ignore the modePtr... What this parser does is take a string of characters from user input, so it is parsing the command "ls |" I'm guessing the issue is with the fact there isn't a "case" that an empty pipe command will fall into, causing an infinite loop? Any suggestions?

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;
}

Solution

  • You may have overcomplicated the problem. If you want a program to read a list items piped to it...

    #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);
    
    }
    

    ... you can then parse the items on each line using strtok(), or if you use "ls -1", each list item is on a unique line anyway.

    Hope this helps.