Reputation: 919
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;
}
Upvotes: 1
Views: 1991
Reputation: 382
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.
Upvotes: 2
Reputation: 754490
If you try ls |
in an ordinary shell, it will prompt you for the rest of the pipeline (another command) before trying to launch anything. A pipe with no command to read the output is nonsense.
This idiom (repeated several times in the code) is broken:
srcPtr++;
while (*srcPtr == ' ' || *srcPtr == '\t' || *srcPtr == '\0')
srcPtr++;
You can't afford to skip over the null '\0'
at the end of the string! You immediately fall into 'undefined behaviour'. You need to review the loop logic, perhaps to:
srcPtr++;
while (*srcPtr == ' ' || *srcPtr == '\t')
srcPtr++;
if (*srcPtr == '\0')
...no more data in string...
Upvotes: 2