与EXC_BAD_ACCESS的minishell malloc错误

时间:2017-12-07 06:10:23

标签: c shell unix

您好我最近在学习unix系统编程 我正在尝试在c中创建一个minishell,但是当我运行我的代码时 我总是得到:

  

EXC_BAD_ACCESS(code = EXC_I386_GPFLT

这里真的不知道什么是错的。在网上搜索他们说malloc出了问题,但是我没有看到什么是错的 有人可以帮我解决这个问题吗?

#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include "minishell.h"

char promptString[] = "mysh>";

struct command_t command;
int enviromentlength;
int commandlength;
char *pathv[MAX_PATHS];
//to display the prompt in the front of every line
void printPrompt()
{
    printf("%s", promptString);
}

//get the user's command
void readCommand(char *buffer)
{
    gets(buffer);
}

//get the environment variable and store in a pathEnvVar
int parsePath( char* dirs[] )
{
    char* pathEnvVar;
    char* thePath;
    int i;

    for(i = 0; i < MAX_ARGS; i++)
    {
        dirs[i] = NULL;
    }
        i = 0;
    //use system call to get the environment variable
    pathEnvVar = (char*) getenv("PATH");

//printf("%s\n", pathEnvVar);
thePath = (char*) malloc(strlen(pathEnvVar) + 1);
strcpy(thePath, pathEnvVar);

//splict the variable and store in the pathv
char *temp = strtok(thePath, ":");
dirs[i] = temp;
while(temp != NULL)
{
    i++;
    temp = strtok(NULL, ":");
    if(temp == NULL)
    {
        break;
    }
    else
    {
        dirs[i] = temp;
    }
}
    dirs[i+1] = NULL;
    return i;
}

//get the user's command and parameters
int parseCommand(char * commandline)
{

int i = 0;

char* temp;
temp = strtok(commandline, " ");
while(temp != NULL)
{
    command.argv[i] = temp;
    i++;
    temp = strtok(NULL, " ");
}
command.argv[i] = NULL;
return i;
}

//input the user's command to
//fix the absolute path of the command
char* lookupPath(char* dir[], char* command[])
{
char* result = NULL;

int i;
//printf("%c\n", *command.argv[0]);

//if the command is already an absolute path
if(*command[0] == '/')
{
    result = command[0];
    //printf("test\n");
    if( access(result, X_OK) == 0)
    {
        return result;
    }
    else
    {
        fprintf(stderr, "%s: command not found\n", result);
        return NULL;
    }
}

//if the command is not an absolute path
else
{
    for(i = 0; i < enviromentlength; i++)
    {

        char *temp = (char *) malloc (30);
        strcpy(temp, dir[i]);
        strcat(temp, "/");

        strcat(temp, command[0]);
        result = temp;

        if( access(result, X_OK) == 0)
        {
            return result;
        }

    }

    fprintf(stderr, "%s: command not found\n", result);
    return NULL;

}


}

//to change the directory and
//display the absolute path of the current directory
void do_cd(char* dir[])
{
char currentdirectory[MAX_PATHS];

if(dir[1] == NULL || (strcmp(dir[1], ".") == 0))
{
    printf("director does not change\n");
    //printf("The current directory is:%s", currentdirectory);
}
    else
    {
        if(chdir(dir[1]) < 0)
        {
            printf("change director error\n");
        }
        else
        {
            printf("change director success\n");
        }

    }
    getcwd(currentdirectory, MAX_PATHS);
    printf("The current directory is:%s\n", currentdirectory);
}


//redirection the result to file
void redirection(char* command, char* commandcontent[], int position,         pid_t thisChPID)
{
    char* content[commandlength - 1];
    char* filename = (char *) malloc(MAX_PATH_LEN);
    FILE* fid;
    int i = 0;
    int stat;
    strcpy(filename, commandcontent[position + 1]);
    //printf("%s\n", commandcontent[position + 1]);
    for(i = 0; i < position; i++)
    {
        content[i] = commandcontent[i];
        //printf("content: %s\n", content[i]);
    }
    content[i + 1] = NULL;
    for(i = 0; i< position + 1; i++)
    {
        printf("%s\n", content[i]);
    }
        printf("%s\n", command);
    if((thisChPID=fork()) < 0)
    {
        fprintf(stderr, "fork failed\n");
}
else if(thisChPID == 0)
{

    fid = open(filename, O_WRONLY || O_CREAT);
    close(1);
    dup(fid);
    close(fid);
    execve(command, content, pathv);


}
else
{
    wait(&stat);

}


}


//use pipe to run the program
void piperun(char* command, char* commandcontent[], int position, pid_t thisChPID)
{
printf("%s\n%d\n", command, position);
char* firstcommand[position+1];

char* secondcommand[commandlength-position];
char* result = (char *) malloc(MAX_PATH_LEN);
pid_t child;

//the pipe name
int pipeID[2];
int j;

for(j = 0; j< position; j++)
{
    firstcommand[j] = commandcontent[j];
    printf("%s\n", firstcommand[j]);
}
firstcommand[j] = NULL;
printf("length: %d\n", commandlength-position);
for(j = 0; j < (commandlength-position); j++)
{
    secondcommand[j] = commandcontent[position + 1 + j];
    printf("second:%s\n",secondcommand[j]);
}

//secondcommand[j+1] = NULL;
result = lookupPath(pathv, secondcommand);
//printf("%s\n", secondcommand[0]);
printf("%s\n", result);

//create pipe "pipeID"
if(pipe(pipeID)==-1)
{
    printf("Fail to creat pipe.\n");

}
if((thisChPID=fork())==-1)
{
    printf("Fail to creat child process.\n");

}

if(thisChPID==0)
{
    printf("in the child\n");
    close(1);
    dup(pipeID[1]);
    close(pipeID[0]);
    close(pipeID[1]);
    if(execve(command, firstcommand, pathv)==-1)
    {
        printf("Child process can't exec command %s.\n",firstcommand[0]);

    }

}
else
{
    child = fork();
    if((child=fork())==-1)
    {
        printf("Fail to creat child process.\n");

    }
    if(child==0)
    {
        close(0);
        dup(pipeID[0]);
        close(pipeID[1]);
        close(pipeID[0]);
            if(execve(result, secondcommand, pathv)==-1)
        {
                printf("Child process can't exec command     %s.\n",secondcommand[0]);

        }

        }
        else
        {
            wait(NULL);

        }

    }


}

int main()
{
char commandLine[LINE_LEN];

int child_pid;  //child process id
int stat;    //used by parent wait
pid_t thisChPID;
char *arg[MAX_ARGS];

//the flag of redirection, piping and background running
int redirectionsituation = 0;
int pipesituation = 0;
int background = 0;


char * tempchar;

//Command initialization
int i;
for(i = 0; i < MAX_ARGS; i++ )
{
    command.argv[i] = (char *) malloc(MAX_ARG_LEN);
}

//get all directories from PATH env var
enviromentlength = parsePath(pathv);

//Main loop
while(TRUE)
{
    redirectionsituation = 0;
    pipesituation = 0;
    background = 0;
    //Read the command line
    printPrompt();
    readCommand(commandLine);

    //input nothing
    if(commandLine[0] == '\0')
    {

        continue;
    }

    //quit the shell?
    if((strcmp(commandLine, "exit") == 0) || (strcmp(commandLine, "quit") == 0))
    {
        break;
    }

    //if it is background running
    if(commandLine[strlen(commandLine) - 1] == '&')
    {
        printf("backgrond\n");
        tempchar = strtok (commandLine, "&");
        //strcpy(commandLine, tempchar);
        printf("%s\n", tempchar);
        background = 1;

    }

    //Parse the command line
    commandlength = parseCommand(commandLine);



    //if the command is "cd"
    if(strcmp(command.argv[0], "cd") == 0)
    {
        do_cd(command.argv);
        continue;
    }

    //Get the full path name
    command.name = lookupPath(pathv, command.argv);
    printf("command name %s\n", command.name);


    //report error
    if( command.name == NULL)
    {

        continue;  //non-fatal
    }

    //if redirection is required
    for(i = 0; i < commandlength; i++)
    {
        if(strcmp(command.argv[i], ">") == 0)
        {
            redirectionsituation = 1;
            break;
        }

    }
    if(redirectionsituation == 1)
    {
        redirection(command.name, command.argv, i, thisChPID);
        continue;
    }

    //if pipe is required
    for(i = 0; i < commandlength; i++)
    {
        if(strcmp(command.argv[i], "|") == 0)
        {
            pipesituation = 1;
            break;
        }

    }
    if(pipesituation == 1)
    {    //run pipe
        piperun(command.name, command.argv, i, thisChPID);

        continue;
    }


    //normal running
    if((thisChPID=fork()) < 0)
    {
        fprintf(stderr, "fork failed\n");
    }
        else if(thisChPID == 0)
        {
            //printf("run again\n");
            execve(command.name, command.argv, pathv);

        }
        else
        {
            //do not put the process in the background, wait until the     child process terminates
            if(background == 0)
            {
            wait(&stat);
            }

        }
    }
    return 0;
}

1 个答案:

答案 0 :(得分:-1)

在调试器中运行它,看看你在哪里取消引用null。