Reputation: 540
I've been trying to pick up C for a homework assignment that says to create a C shell. One requirement is that all the commands should be executed from a child process. The problem seems to be that my child process dies way too early, and I never get to the part of the code that actually executes the command. My code:
parseCommand.h
char *parseCommand(char str[]) {
char * token;
//get size of the input array. divide memory amount allocated to array by the size of the 1st element (which should be representative of other elements)
size_t n = sizeof(str) / sizeof(str[0]);
char *args = malloc(n);
printf("Splitting string \"%s\" into tokens:\n", str);
token = strtok(str, " \n");
int i = 0;
while (token != NULL) {
printf(":: %s\n", token);
args[i++] = token;
token = strtok(NULL, " \n");
}
printf("after while loop");
args[i]=(char *) 0;
return args;
}
main.c
//I probably don't need all these
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
//Custom Libraries
#include "parseCommand.h"
char *parseCommand(char str[]);
int main() {
char path[10] = "/bin/";//path to bash scripts
int should_run = 1;
while (should_run) {
printf("yazan_shell>> ");
fflush(stdout); //force the prompt to the output immediately
char *cmdStr = (char *)malloc(40); //allocate space for array
fgets(&cmdStr, 40, stdin); //save user input to cmdStr
pid_t pid = fork(); //create
if (pid == 0) {
printf("==> Child received: %s command. Executing...\n", &cmdStr);
char *cmd = parseCommand(&cmdStr);//split user input by space
printf("cmd: %s", &cmd);
execvp(strcat(path, cmd[0]), cmd);//excecute the input cmd
} else {
int returnStatus;
waitpid(pid, &returnStatus, 0); //parent waits for child process
printf("==> Parent is silent!! PID: %d\n", pid);
should_run = 0;
}
free(cmdStr); //deallocate cmdStr
}
}
Output 1
yazan_shell>> ls -l
==> Child received: ls -l
command. Executing...
Splitting string "ls -l
" into tokens:
:: ls
:: -l
==> Parent is silent!! PID: 5500
RUN FINISHED; Segmentation fault; core dumped; real time: 3s; user: 0ms; system: 0ms
I just started learning C a couple days ago, but I google'd segmentation errors in C and it seems that I am either dereferencing a non-initialized pointer or trying to access freed memory. So I tried commenting out the
free(cmdStr);
line and the output then looks like:
yazan_shell>> ls -l
==> Child received: ls -l
command. Executing...
Splitting string "ls -l
" into tokens:
:: ls
:: -l
==> Parent is silent!! PID: 5601
RUN FINISHED; exit value 33; real time: 1s; user: 0ms; system: 0ms
I also tried moving the print statement in the while loop in parseCommand.h but the output seems to not change either. I've asked a couple of C++ professors who were available, but none of them were able to pinpoint the error(s). Is anyone here able to give me some pointers (hehe) about my mistake?
Thank you very much in advance!
Upvotes: 0
Views: 542
Reputation: 16607
There are several problems -
1. In main
-
char *cmdStr = (char *)malloc(40); // don't cast it
fgets(&cmdStr, 40, stdin); // don't pass address of cmdStr it is already a char *
Just this is fine -
char *cmdStr =malloc(40);
fgets(cmdStr, 40, stdin);
2. also here-
char *cmd = parseCommand(&cmdStr);//split user input by space
printf("cmd: %s", &cmd); //cmd is already a char * don't pass its address
write like this -
printf("cmd: %s", cmd);
3. In your function char *parseCommand(char str[])
when you calculate number of elements -
size_t n = sizeof(str) / sizeof(str[0]);
this wont work as expected . So calculate n
in main
and then pass it to your function
Upvotes: 1