I'm working on my own little shell program in C. When I run the child process as a background process, I would like to ignore the input from the user coming from the parent process. I am currently trying to pipe it then close stdin for the child, but the input still goes to the child.
else // A process
{
pid_t child_pid;
char lastArgument = args[currArgsIndex-1][0];
if (lastArgument != '&'){ //Normal process
if((child_pid = fork()) == 0) {
execvp(filepath, args);
exit(0);
}
else
{
while(wait(NULL) != child_pid);
}
}
else { // Background
args[currArgsIndex-1] = NULL;
int process_pipe[2];
pipe(process_pipe); // Piping
if((child_pid = fork()) == 0) {
close(process_pipe[0]); // Ignore stdin for child
execvp(filepath, args);
exit(0);
}
}
}
You create a pipe and close the read end, but you never say that the pipe should be stdin.
It sounds like your intention was instead to 1. open the pipe only in the child, 2. close the write
end so that no data can be read, 3. set the read end as stdin:
else { // Background
args[currArgsIndex-1] = NULL;
if((child_pid = fork()) == 0) {
int process_pipe[2];
pipe(process_pipe); // Piping
dup2(process_pipe[0], 0); // Copy read end as stdin
close(process_pipe[0]); // Close FD that is now unused
close(process_pipe[1]); // Close write end so no data can be read
execvp(filepath, args);
perror("execvp failed");
exit(1); // exit with error
}
}
There's no point having a pipe though. You can more easily open /dev/null
for reading and setting that as stdin. Alternatively, simply close stdin
entirely (some programs will complain):
else { // Background
args[currArgsIndex-1] = NULL;
if((child_pid = fork()) == 0) {
close(0); // Close stdin
execvp(filepath, args);
/* error handling */
}
Be aware that real shells allow redirecting to backgrounded processes, in which case none of the above will work:
wc -l < myfile &
Real shells will in fact not close or redirect stdin at all, but will put the command in its own process group that's not controlling the terminal. The process will then receive a SIGTSTP when it tries to read from stdin, and you can then use fg
to bring it to the foreground to start typing data.