Im programming a shell. This is a small piece of it that handles redirects. I only included the snippet that is causing the error. This portion of the program is supposed to take a command/argument line and execute the line accordingly. The wc < junk > junk2 is an example of a command line input and for some reason when i execute the line its producing that error junk: >: open: No such file or directory. The rest of the program functions fine but its breaking here.
: wc < junk > junk2
junk: >: open: No such file or directory 1 4 31 junk2 1 4 31 total
I briefly had it working as intended but for some reason I must have lost a piece of the puzzle because it’s broken once again.
Ive looked at my array values and they are as expected. For some clarification I’m using a copy of the arguments array so the original is unchanged by setting the argument copy value to NULL. Im setting the argument copy value to null so the loop doesn’t repeatedly use a redirection.
If you have any advise or see the problem that I apparently can’t it would be appreciated.
while (arguments[i] != NULL) { if ((strcmp(argumentsCopy[i], "<") == 0)) { if ((access(argumentsCopy[i + 1], R_OK) == -1)) { printf("Cannot open %s for inputn", argumentsCopy[i + 1]); fflush(stdout); redirect = 1; } else { int fd = open(argumentsCopy[i + 1], O_RDONLY); dup2(fd, STDIN_FILENO); close(fd); argumentsCopy[i] = NULL; redirect = 1; execvp(command, &arguments[i + 1]); } } if ((strcmp(argumentsCopy[i], ">") == 0)) { int fd = open(argumentsCopy[ i + 1], O_RDWR); dup2(fd, STDOUT_FILENO); close(fd); argumentsCopy[i] = NULL; redirect = 1; // avoid repeat use of redirection symbol in arguments array execvp(command, &arguments[i + 1]); } i++; } if (redirect == 0) { execvp(command, execArgs); //execArgs is entire command w/ arguments } exit 0; //default if error occurred.
Advertisement
Answer
First, note that you’re not correctly using the execvp
function. Once a call to execvp
(or any call in the exec
family) succeeds, the execution of the current program terminates and is replaced by the program you are exec
ing. Thus, control flow should never proceed past an execvp
call unless that call failed. Therefore, you cannot call execvp
until you are sure both the stdin
and stdout
file descriptors have been properly redirected (in the case that you have both input and output redirection). From your code sample, it appears you call execvp
once either one is detected, which means your shell can only redirect input or output, not both.
However, that is not the source of the error you’re receiving. Consider the input wc < junk > junk2
. Based on the information you provided, the command and arguments array will be populated as follows:
command = "wc" arguments[0] = ">" arguments[1] = "junk" arguments[2] = "<" arguments[3] = "junk2" arguments[4] = NULL
When i = 0
, the first if-statement will be taken, opening the file descriptor and performing execvp
with the parameters command
and &arguments[i+1]
. These correspond to the file to be executed and the argv
array passed to that function’s main method respectively. In this case, the command is wc
and the args are { "junk", "<", "junk2", NULL }
(as this is the value of the null terminated array beginning at &arguments[i+1]
). On Unix systems, it is conventional for the first argument (argv[0]
) to be the name of the current program. Thus the actual command line arguments begin at argv[1]
(see Program Arguments for documentation). From wc
‘s perspective, the command line arguments it should process are { "<", "junk2", NULL }
after it processes what it believes to be its program name, argv[0]
, or junk
.
wc
takes as arguments the list of files it will process. In this case, it believes that list to be <
and junk2
, as "<"
is an operator recognized by bash and other shells, not the executing program. Thus, wc
(which believes its name is junk
because of argv[0]
) attempts to open <
as an input file and fails, printing the message:
junk: >: open: No such file or directory