fflush(stdin) is undefined behavior (i.e., the C standard does not define what it does).
It is defined in Windows to empty stdin, but in *nix it does nothing.
Emptying stdin doesn't seem to be needed in your code anyway.
Your cmd is printed twice since you print it right after the fork so it's printed by both copies of the program.
A simplistic version (breaks "words" on whitespace only, so no knowledge of escapes (quotes, etc.)) :
Code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>
void vsh_cmd_exec(char **cmd) {
int ret = fork();
if (ret == -1)
perror("fork");
else if (ret == 0) {
execvp(*cmd, cmd);
perror("exec");
exit(EXIT_FAILURE);
}
else
wait(NULL);
}
void vsh_loop(void) {
while (1) {
char cmd[1024], *cmdp[64];
printf("[vsh]$ ");
if (fgets(cmd, sizeof cmd, stdin) == NULL)
break;
unsigned i = 0;
for (char *c = cmd; i < sizeof cmdp / sizeof *cmdp - 1; ++i) {
while (isspace(*c)) ++c;
if (!*c) break;
cmdp[i] = c;
while (*c && !isspace(*c)) ++c;
if (!*c) break;
*c++ = 0;
}
cmdp[i] = NULL;
if (*cmdp)
vsh_cmd_exec(cmdp);
}
}
int main() {
vsh_loop();
putchar('\n');
return 0;
}