I’m trying do to a basic bash with the use of system calls but I’m having some little problems with a pointer array.
To resume my code, I read commands from the stdin with read() to a buffer then I use strsep() to separate the command from the arguments and all the arguments into an array. Then I create a new process with fork() and execute that command with the associated arguments with execvp().
All this goes into a infinite loop until the user types “quit” (not coded yet). The problem is that after the first iteration, I need *pArgs to be empty, for the next command and arguments. And I don’t know how to do it…
Here’s my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
char bBuffer[BUFSIZ], *pArgs[10], *aPtr = NULL, *sPtr;
int aCount;
pid_t pid;
while(1) {
write(1, "\e[1;31mmyBash \e[1;32m# \e[0m", 27);
read(0, bBuffer, BUFSIZ);
sPtr = bBuffer;
aCount = 0;
do {
aPtr = strsep(&sPtr, " ");
pArgs[aCount++] = aPtr;
} while(aPtr);
pArgs[aCount-2][strlen(pArgs[aCount-2])-1] = '\0';
// Debug code to output pArgs content
write(1, "|>", 2);
write(1, pArgs[0], strlen(pArgs[0]));
write(1, "<|", 2);
if(strlen(pArgs[0]) > 1) {
pid = fork();
if(pid == -1) {
perror("fork");
exit(1);
}
if(pid == 0) {
execvp(pArgs[0], pArgs);
exit(0);
}
}
}
return 0;
}
P.S: Sorry but I can’t provide an input and output test case at the moment. Hopefully, this is not that hard to understand and fix that you guys don’t need it. I’ll post it later if it’s needed though…
Just to clear things up:
I know I asked how to clear the array and I got an answer for that. But it seems now obvious to me that my problem wasn’t that, but the garbage that the buffer was collecting as pointed out by litb. It makes more sense to terminate the string with the null character than to clear the array. That’s why I’m marking litb’s answer as right one.
Your problem is that you don’t add a null character after the data read. So the
strsepcalls don’t know where to stop. In C, strings must be terminated by a null character (that’s called the terminating null character).With that in place, i don’t see what array should be cleared now, since
execvpwill read arguments until the first null pointer. Thedoloop, however, adds that null pointer already, which is the null pointer returned by the last invocation ofstrsep.The problem would of course also be solved too by just clearing bBuffer (the data where
*pArgsis pointing to after the first command was scanned). Note that you have to do that also before scanning the first time, since you can’t assume the chars inbBufferarray are initialized to any sensible values.Place that just before the
readinvocation (but in any case, read only maximallyBUFSIZE-1, because the terminating null character must have space too!).But as I’ve shown above, you don’t need this memset call. Just add the terminating null character manually.