i coded a basic shell in C for executing basic commands it\'ll execute commands ls
, ls -al
, ls -al | more
etc.
i want to exec
Before you call execve(2)
in the newly created process to execute the command, you can redirect its standard input or output via the dup2(2) system call:
/* redirect stdout to a file */
dup2(1, some_open_file_descriptor);
Of course, you need to have some error handling.
Don't use pipe when the output is to go to a file.
When you fork the child to run the ls
command, you note the redirection, and open the file; you then use dup2()
(or close()
and dup()
) so that the file descriptor is now standard output for the child; you close the duplicated file descriptor - the one returned by open()
; then you execute ls
as usual; its standard output is now sent to the file.
Note that you do the non-pipe I/O redirection after forking, not before. Pipes have to be set up before forking, but other I/O redirection does not.
This is the result of my testing things out with dup2
The more subtle point is remembering fflush at the right times :) Otherwise, you'll get very surprising results.
Also, prefer fileno
instead of hardcoding 1
(stdout) 2
(stderr).
Redirecting stdin
was left as an exercise for the reader
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
int out = open("cout.log", O_RDWR|O_CREAT|O_APPEND, 0600);
if (-1 == out) { perror("opening cout.log"); return 255; }
int err = open("cerr.log", O_RDWR|O_CREAT|O_APPEND, 0600);
if (-1 == err) { perror("opening cerr.log"); return 255; }
int save_out = dup(fileno(stdout));
int save_err = dup(fileno(stderr));
if (-1 == dup2(out, fileno(stdout))) { perror("cannot redirect stdout"); return 255; }
if (-1 == dup2(err, fileno(stderr))) { perror("cannot redirect stderr"); return 255; }
puts("doing an ls or something now");
fflush(stdout); close(out);
fflush(stderr); close(err);
dup2(save_out, fileno(stdout));
dup2(save_err, fileno(stderr));
close(save_out);
close(save_err);
puts("back to normal output");
return 0;
}