I am implementing a simple version of a linux shell in c.
I have succesfully written the parser, but I am having some trouble forking out the child process. However, I think the problem is due to arrays, pointers and such, because just started C with this project and am not still very knowledgable with them.
I am getting a segmentation fault and don't know where from. Any help is greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#define MAX_COMMAND_LENGTH 250
#define MAX_ARG_LENGTH 250
typedef enum {false, true} bool;
typedef struct {
char **arg;
char *infile;
char *outfile;
int background;
} Command_Info;
int parse_cmd(char *cmd_line, Command_Info *cmd_info)
{
char *arg;
char *args[MAX_ARG_LENGTH];
int i = 0;
arg = strtok(cmd_line, " ");
while (arg != NULL) {
args[i] = arg;
arg = strtok(NULL, " ");
i++;
}
int num_elems = i;
if (num_elems == 0)
return -1;
cmd_info->infile = NULL;
cmd_info->outfile = NULL;
cmd_info->background = 0;
int iarg = 0;
for (i = 0; i < num_elems-1; i++)
{
if (!strcmp(args[i], "<"))
{
if (args[i+1] != NULL)
cmd_info->infile = args[++i];
开发者_开发技巧 else
return -1;
}
else if (!strcmp(args[i], ">"))
{
if (args[i+1] != NULL)
cmd_info->outfile = args[++i];
else
return -1;
}
else
cmd_info->arg[iarg++] = args[i];
}
if (!strcmp(args[i], "&"))
cmd_info->background = true;
else
cmd_info->arg[iarg++] = args[i];
cmd_info->arg[iarg] = NULL;
return 0;
}
void print_cmd(Command_Info *cmd_info)
{
int i;
for (i = 0; cmd_info->arg[i] != NULL; i++)
printf("arg[%d]=\"%s\"\n", i, cmd_info->arg[i]);
printf("arg[%d]=\"%s\"\n", i, cmd_info->arg[i]);
printf("infile=\"%s\"\n", cmd_info->infile);
printf("outfile=\"%s\"\n", cmd_info->outfile);
printf("background=\"%d\"\n", cmd_info->background);
}
void get_cmd(char* str)
{
fgets(str, MAX_COMMAND_LENGTH, stdin);
str[strlen(str)-1] = '\0'; //apaga o '\n' do fim
}
pid_t exec_simple(Command_Info *cmd_info)
{
pid_t pid = fork();
if (pid < 0)
{
perror("Fork Error");
return -1;
}
if (pid == 0)
{
execvp(cmd_info->arg[0], cmd_info->arg);
perror(cmd_info->arg[0]);
exit(1);
}
return pid;
}
int main(int argc, char* argv[])
{
while (true)
{
char cmd_line[MAX_COMMAND_LENGTH];
Command_Info cmd_info;
printf(">>> ");
get_cmd(cmd_line);
if ( (parse_cmd(cmd_line, &cmd_info) == -1) )
return -1;
parse_cmd(cmd_line, &cmd_info);
if (!strcmp(cmd_info.arg[0], "exit"))
exit(0);
pid_t pid = exec_simple(&cmd_info);
waitpid(pid, NULL, 0);
}
return 0;
}
Thanks.
The problem is with cmd_info->arg
, which is declared as char **arg
and you never allocate memory for it.
So, when you try to access it to save the arguments like this cmd_info->arg[iarg++] = args[i]
, you are dereferencing an uninitialized pointer, causing the segmentation fault.
A solution would be to change the Command_Info
structure to declare arg
like this :
char *arg[MAX_ARG_LENGTH];
精彩评论