C でのパイプの実装に問題があります。次のプログラムを実行して「ls | more」と入力すると、エラー セグメンテーション フォールト コア ダンプが返されます。これはプログラムです:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <readline/readline.h>
#include <readline/history.h>
void execute(char **, int, char **);
void handle_signal(int);
int parse(char *, char **, char **, int *);
void chop(char *);
#define INPUT_STRING_SIZE 513
#define NORMAL 00
#define OUTPUT_REDIRECTION 11
#define INPUT_REDIRECTION 22
#define PIPELINE 33
#define BACKGROUND 44
#define OUTPUT_APP 55
int main(int argc, char *argv[])
{
int i, mode = NORMAL, cmdArgc;
size_t len = INPUT_STRING_SIZE;
char *cpt, *inputString, *cmdArgv[INPUT_STRING_SIZE], *supplement = NULL;
inputString = (char*)malloc(sizeof(char)*INPUT_STRING_SIZE+200);
char curDir[100];
char *temp;
while(1)
{
mode = NORMAL;
getcwd(curDir, 100);
inputString = readline("$ ");
if(strcmp(inputString, "exit\n") == 0)
exit(0);
cmdArgc = parse(inputString, cmdArgv, &supplement, &mode);
if(strcmp(*cmdArgv, "cd") == 0)
{
chdir(cmdArgv[1]);
}
else
execute(cmdArgv, mode, &supplement);
}
return 0;
}
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)
{
switch(*srcPtr)
{
case '&':
*modePtr = BACKGROUND;
break;
case '|':
*modePtr = PIPELINE;
*cmdArgv = '\0';
srcPtr++;
while(*srcPtr == ' ' || *srcPtr == '\t')
srcPtr++;
*supplementPtr = srcPtr;
//chop(*supplementPtr);
terminate = 1;
break;
}
srcPtr++;
}
while((*srcPtr == ' ' || *srcPtr == '\t' || *srcPtr == '\n') && terminate == 0)
{
*srcPtr = '\0';
srcPtr++;
}
cmdArgv++;
}
/*srcPtr++;
*srcPtr = '\0';
destPtr--;*/
*cmdArgv = '\0';
return cmdArgc;
}
void chop(char *srcPtr)
{
while(*srcPtr != ' ' && *srcPtr != '\t' && *srcPtr != '\n')
{
srcPtr++;
}
*srcPtr = '\0';
}
void execute(char **cmdArgv, int mode, char **supplementPtr)
{
pid_t pid, pid2;
FILE *fp;
int mode2 = NORMAL, cmdArgc, status1, status2;
char *cmdArgv2[INPUT_STRING_SIZE], *supplement2 = NULL;
int myPipe[2];
if(mode == PIPELINE)
{
if(pipe(myPipe)) //create pipe
{
fprintf(stderr, "Pipe failed!");
exit(-1);
}
parse(*supplementPtr, cmdArgv2, &supplement2, &mode2);
}
pid = fork();
if( pid < 0)
{
printf("Error occured");
exit(-1);
}
else if(pid == 0)
{
switch(mode)
{
case PIPELINE:
close(myPipe[0]); //close input of pipe
dup2(myPipe[1], fileno(stdout));
close(myPipe[1]);
break;
}
execvp(*cmdArgv, cmdArgv);
}
else
{
if(mode == BACKGROUND)
;
else if(mode == PIPELINE)
{
waitpid(pid, &status1, 0); //wait for process 1 to finish
pid2 = fork();
if(pid2 < 0)
{
printf("error in forking");
exit(-1);
}
else if(pid2 == 0)
{
close(myPipe[1]); //close output to pipe
dup2(myPipe[0], fileno(stdin));
close(myPipe[0]);
execvp(*cmdArgv2, cmdArgv2);
}
else
{
;//wait(NULL);
//waitpid(pid, &status1, 0);
//waitpid(pid2, &status2, 0);
close(myPipe[0]);
close(myPipe[1]);
}
}
else
waitpid(pid, &status1, 0);
//wait(NULL);
}
}
ls、cat、sort などの標準コマンドは正常に動作します。