I'm trying to make simple shell, but with a specific condition, I have to use the following structure:
typedef struct cmd_struct{
char cmd[80];
char args[10][80];
int nargs;
} cmd_type;
Inside cmd I will save de main command and arguments in args.
Then I read from a file, different commands, and save them into and array of cmd_type. My program or fake shell, ask for a number and should take it from this array.
My function that executes the command looks like:
void execCmd(cmd_type* cmds_arg, int idxCmd){
pid_t pid;
printf("Father: my pid is %d\n", getpid());
char* buff;
pid = fork();
if (pid == 0) {
printf("Child process: My pid is %d\n", getpid());
printf("-------------- Child doing exec: %s\n", cmds_arg[idxCmd].cmd);
execvp(cmds_arg[idxCmd].cmd,&cmds_arg[idxCmd].args);
_exit(2);
_exit(1);
}
printf("Father: Gonna wait for Child\n");
int status;
wait(&status);
printf("-------------- Father: Child finished\n");
// WIFEXITED, WEXITSTATUS Macro of the gnu lib POSIX standard to recover end status
if ( WIFEXITED(status) ) {
const int es = WEXITSTATUS(status);
printf("Father: Child Complete with exit status %d\n", es);
if(es == 1) printf("Father: Child didn't execute any command\n");
else if(es == 2) printf("Father: Child command was not found\n");
}
}
As you can see, when I'm calling the execvp() system call, I'm doing it wrong. First argument I think that it is right, second one it's totally wrong.
First of all, I have a conversion problem right there, and the second problem is that the array should contain "main command", "arg1", "arg2" ... and mine only has the arguments. Am I wrong?
Is there a way to add the "main command" using services like sscanf ()? And the most important part, do I have any chance to make it work this way?
In the same spirit of the answer from @pts, you can copy the parameters for execvp() in a dynamically allocated table:
void execCmd(cmd_type* cmds_arg, int idxCmd){
pid_t pid;
printf("Father: my pid is %d\n", getpid());
char* buff;
pid = fork();
if (pid == 0) {
int i;
char **args = (char **)malloc((1 + cmds_arg[idxCmd].nargs + 1) * sizeof(char *));
args[0] = cmds_arg[idxCmd].cmd;
for (i = 1; i < (cmds_arg[idxCmd].nargs + 1); i ++) {
args[i] = cmds_arg[idxCmd].args[i - 1];
}
args[i] = NULL;
printf("Child process: My pid is %d\n", getpid());
printf("-------------- Child doing exec: %s\n", cmds_arg[idxCmd].cmd);
execvp(cmds_arg[idxCmd].cmd, args);
_exit(2);
}
printf("Father: Gonna wait for Child\n");
int status;
wait(&status);
printf("-------------- Father: Child finished\n");
// WIFEXITED, WEXITSTATUS Macro of the gnu lib POSIX standard to recover end status
if ( WIFEXITED(status) ) {
const int es = WEXITSTATUS(status);
printf("Father: Child Complete with exit status %d\n", es);
if(es == 1) printf("Father: Child didn't execute any command\n");
else if(es == 2) printf("Father: Child command was not found\n");
}
}