I had this simple shell like program that works both in interactive and non-interactive mode. I have simplified the code as much as I can to present my question, but it is still a bit long, so sorry for that!
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/**
*main-entry point for gbk
*Return: returns the index of 0 on sucess
*/
int main(void)
{
char *cmd = malloc(1 * sizeof(char)), *cmdargs[2];
size_t cmdlen = 0;
int childid, len;
struct stat cmdinfo;
while (1)
{
printf("#cisfun$ ");
len = getline(&cmd, &cmdlen, stdin);
if (len == -1)
{
free(cmd);
exit(-1);
}
/*replace the ending new line with \0*/
cmd[len - 1] = '\0';
cmdargs[0] = cmd;
cmdargs[1] = NULL;
childid = fork();
if (childid == 0)
{
if (stat(*cmdargs, &cmdinfo) == 0 && cmdinfo.st_mode & S_IXUSR)
execve(cmdargs[0], cmdargs, NULL);
else
printf("%s: command not found\n", *cmdargs);
exit(0);
}
else
wait(NULL);
}
free(cmd);
exit(EXIT_SUCCESS);
}
To summarize what this program does, it will first print the prompt #cisfun$
, waits for an input in interactive mode and takes the piped value in non-interactive mode, creates a child process, the child process checks if the string passed is a valid executable binary, and if it is, it executes it other wise it prints a command not found message and prompts again.
I have got this program to work fine for most of the scenarios in interactive mode, but when I run it in non-interactive mode all sorts of crazy (unexpected) things start to happen.
For example, when I run echo "/bin/ls"|./a.out
, (a.out
is the name of the compiled program)
you would first expect the #cisfun$
message to be printed since that is the first thing performed in the while loop, and then the output of the /bin/ls
command, and finally #cisfun$
prompt, but that isn't what actually happens. Here is what happens,
- It is very weird the
ls
command is run even before the first print message. I, at first, thought there was somethreading
going on and theprintf
was slower than the child process executing the ls command. But I am not sure if that is true as I am a noob. and also things get a bit crazier if I was printing a message with'\n'
at the end rather than just a string. (if I changeprintf("#cisfun$ ");
toprintf("#cisfun$\n");
) the following happens,
It works as it should, so it got me thinking what is the relation between '\n'
, fork
and speed of printf
. Just in short what is the explanation for this.
- The second question I have is, why doesn't my program execute the first command and go to an interactive mode, I don't understand why it terminates after printing the second
#cisfun$
message. By checking the status code (255) after exit I have realized that the effect is the same as pressingctr+D
in the interactive mode, which I believe is exited by thegetline
function. But I dont understand whyEOF
is being inserted in the second prompt.