user1945613
user1945613

Reputation:

Can't solve Segmentation fault (core dumped) in c

we are writing a program that has to mimic the Linux shell. It is consisted of some parts. Every part does what the previous part did, plus something extra.

This is where we are stuck.. We compile myShell 2 without errors. But when we are typing any command we get the segmentation fault. We're sorry for writing almost all out code here(myShell 1 not included), we just wanted to make sure you have everything you need to tell us where we are wrong.

functions.h

#ifndef FUNCTIONS_H
#define FUNCTIONS_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define max 260

extern int argCounter(char *argLine,char *delim);
extern void myExec(char *argLine,int howMany,char *delim);
extern char **argArray(char* argLine,int howMany,char *args[],char *delim);
void myExecRedir(char **tokens,char* argLine, int howMany);
#endif

functions.c

#include "functions.h"


int argCounter(char *argLine,char *delim)
{
    char *temp;
    memcpy(temp,argLine,strlen(argLine));
    char *pointer = strtok(temp, delim);
    int counter = 0;
    while (pointer != NULL)
    {
        counter++;
        pointer = strtok(NULL, delim);
    }                               
    return counter; 
}

void myExec(char *argLine,int howMany,char *delim)
{
    char temp[max];
    memset(temp,0,max);
    char *args[howMany];
    argLine[strlen(argLine)-1] = '\0';
    //argArray breaks the argLine and returns an array that contains each argument
    argArray(argLine,howMany,args,delim);
    execvp(args[0],args); 
    perror("ERROR: wrong command!");
}


char **argArray(char *argLine,int howMany,char *args[],char *delim)
{                               
    args[howMany] = NULL;
    char *pointer = strtok(argLine, delim);
    int counter = 0;
    while (pointer != NULL)
    {
        args[counter]=pointer;
        counter++;
        pointer = strtok(NULL, delim);
    }                               
    return args;    
}

void myExecRedir(char **tokens,char* argLine, int howMany)
{
    char *delim3="<";
    char *delim4=">";
    int howManyIn= argCounter(argLine,delim3);
    int howManyOut= argCounter(argLine,delim4);
    if(howManyOut= howManyIn)
    {
        int fdin = open(tokens[1],O_RDWR);
        int fdout = open(tokens[2],O_RDWR);
        if(dup2(fdin,fdout) >= 0)
        {
            tokens[1]=NULL;
            tokens[2]=NULL;
            execvp(tokens[0],tokens);
        }
        else
        {
            printf("ERROR in dup2\n");
        }
    }
    else if(howManyIn== 0) //means we only have > redirection
    {
        int fdout = open(tokens[1],O_RDWR);
        if(dup2(2,fdout) >= 0)
        {
            tokens[2]=NULL;
            execvp(tokens[0],tokens);
        }
        else
        {
            printf("ERROR in dup2\n");
        }
    }
    else                //means we only have  redirection
    {
        int fdin = open(tokens[1],O_RDWR);
        if(dup2(fdin,1) >= 0)
        {
            tokens[2]=NULL;
            execvp(tokens[0],tokens);
        }
        else
        {
            printf("ERROR in dup2\n");
        }
    }
}

myShell2.c

#include "functions.h"

int main()
{
    printf("myshell2>");
    pid_t pid,waitPid;
    //WE TRIED WITHOU ALLOCATING MEMORY AS WELL
    char *argLine = (char *)malloc(max);
    char **args = (char **)malloc(max);
    char **args2 =( char **)malloc(max);
    char **temp = (char **)malloc(max);
    char *delim="><";
    char *delim2=" ";
    int i,howMany,howMany2,status;
    while(fgets(argLine,max,stdin) != NULL)
        {
            howMany= argCounter(argLine,delim);//howMany redirections
            args=argArray(argLine,howMany,args,delim);

            if (howMany == 1)//means we are at myShell 1
            {
                howMany2= argCounter(argLine,delim2);
                if(howMany2 ==1)//checking if the command has any parameters (like ls -l)
                {
                    printf("myshell2>");
                    pid = fork();
                    if (pid < 0)    
                    {
                        perror("ERROR: Fork failed.\n");
                        return -1;
                    }
                    else if(pid == 0)
                    {
                        myExec(args[0],howMany2,delim2);

                        perror("ERROR: Child should never arrive here.\n");
                    }
                    else
                    {
                        waitPid = wait(&status);
                        if (waitPid == -1) 
                        {
                            perror("ERROR: Waitpid failed.\n");
                            return -1;
                        }
                    }
                }
                else
                {
                    printf("ERROR: Wrong number of Arguments!\n");//can't run on myshell 2
                    return(0);
                }
            }
            //means we have redirection (< or >)
            for (i=0; i<howMany; i++)
            {
                argArray(args[i],2,args2,delim2);//args2 contains the tokens without spaces(delim2)
                temp[i] = args2[0];
                howMany2 = argCounter(args[i],delim2);
                if(howMany2 > 1)        // eg. ls -l should not run here
                {
                    printf("ERROR: Wrong number of Arguments!\n");//myShell3 should be running this
                    return(0);
                }
            }
            printf("myshell2>");
            pid = fork();

            if (pid < 0)    
            {
                perror("ERROR: Fork failed.\n");
                return -1;
            }                   
            else if(pid == 0)
            {               
                myExecRedir(temp,argLine,howMany);
                perror("ERROR: Child should never arrive here.\n");
            }
            else
            {
                waitPid = wait(&status);
                if (waitPid == -1) 
                {
                    perror("ERROR: Waitpid failed.\n");
                    return -1;
                }
            }               
        }
}

Thank you in advance.

Upvotes: 0

Views: 824

Answers (1)

David Ranieri
David Ranieri

Reputation: 41017

char *temp;
memcpy(temp,argLine,strlen(argLine));
char *pointer = strtok(temp, delim);
...

is wrong, you need to reserve space with malloc:

size_t len = strlen(argline);
char *temp = malloc(len + 1);
if (temp == NULL) return 0;
memcpy(temp, argLine, len);
/* NUL-terminate the string */
temp[len] = '\0';
char *pointer = strtok(temp, delim);
...
free(temp);

or you can use the non-standard function (but available on many implementations) strdup:

char *temp = strdup(argline);
if (temp == NULL) return 0;
char *pointer = strtok(temp, delim);
...
free(temp);

char **args = (char **)malloc(max);

is also wrong, if you need to reserve space for n pointers to char use:

char **args = malloc(sizeof(*args) * n); /* don't cast malloc */

or

char **args = malloc(sizeof(char *) * n);

Upvotes: 2

Related Questions