Redirecting execvp path - c

I'm trying to write a simple code which execute a program from subfolders from a input file and print thr result into a output file.
My problem is that when i execute the program it keeps failing on me. since the execvp command is trying to look for an exe named "a.out" on the wrong location. in (desktop rather than searching the correct path address).
here's the code. please help me out :)
pid_t runner;
char enter[] = "/home/demo/Desktop/OS/Ex1/Ex12/code/input.txt"; // input file
char path[] = "/home/demo/Desktop/OS/Ex1/Ex12/Ex1/ronen/"; correct path
char *r [] = {"./a.out", NULL};
int savedFD = dup(0);
int sever2Fd=dup(1);
int fdin = open(enter,O_RDONLY);
int fdout = open ("output.txt", O_CREAT | O_RDWR, 0466);
dup2(fdin, 0);
dup2(fdout, 1);
if ((runner = fork()) < 0) {perror("could not make fork");}
else if (runner == 0) {
if (execvp(r[0],r) < 0 ) {printf("Failed!\n");}
} else if (runner != 0) {
waitpid(runner,0,0);
dup2(savedFD, 0);
dup2(sever2Fd, 1);
printf("done\n");
}
close(fdin);close(fdout);

The answer was simple.
"chdir(wanted path)"
int dirchange = chdir(argv[1]);

Related

simulating '<' operator in a c programme

I am recreating a complete shell. For that I must simulate <. To do this, I have to use the function dup2().
I made this but it didn't work and I donc't understand why :
void simple_redirection_left(char *buffer, int index, global *glob)
{
char *file_name = &buffer[index + 1];
int fd = 0;
file_name = clean_file_name(file_name);
if (file_name[0] == '\0') {
my_putstr(1, "Missing name for redirect.\n");
return;
}
if ((fd = open(file_name, O_RDONLY)) == -1) {
printf("Error: file not found.\n");
return;
}
dup2(fd, STDIN_FILENO);
}
I first execute the binary on the left of the < in a fork() and then call the function above.
Did someone know why it didn't work ?
Thanks in advance for your answers.

Making a queue in c

I'm having trouble trying to create a queue. My program runs certain commands but they can only run if some requirements are completed. I created child processes to run those commands and when one command ends the information is updated and some other command can run or not. Do you have any suggestion?
This is what I´m trying to do:
char * queque[1024];
int main (int argc, char *argv[]){
int start = canstart(); //returns 1 if can start and 0 if not
char *input[1024];
strcat(input, "teste.mp3");
char *output[1024];
strcat(output, "output.mp3");
char *executable = {./bin/aurrasd-filters/aurrasd-tempo-double,NULL};
if(start==1){
if(!fork()){
int input_f;
if ((input_f = open(input, O_RDONLY)) < 0) {
perror("Error opening input file")
return -1;
}
dup2(input_f, 0);
close(input_f);
int output_f;
if ((output_f = open(output, O_CREAT | O_TRUNC | O_WRONLY)) < 0) {
perror("Error creating output file");
return -1;
}
dup2(output_f, 1);
close(output_f);
execvp(*executable, executable);
_exit(0);
}
}else{strcat(queque,argv[1]);
}

C: execlp() and >

I want to run execlp() from C file and write the result to some output file.
I use the line:
buff = "./cgi-bin/smth";
execlp(buff, buff, "> /cgi-bin/tmp", NULL);
where smth is a compiled c script.
But smth prints to stdout, and no file appears.
What happens, and how to put script result to an output file?
You have to handle it yourself with dup2 if using execlp. You can look at how I handle file out with execvp in comparison. I pass a flag for out redirection and then I handle it:
if (structpipeline->option[0] == 1) { /* output redirection */
int length = structpipeline[i].size;
char *filename = structpipeline->data[length - 1];
for (int k = length - 2; k < length; k++)
structpipeline->data[k] = '\0';
fd[1] = open(filename, O_WRONLY | O_CREAT, 0666);
dup2(fd[1], STDOUT_FILENO);
close(fd[1]);
} /* TODO: input redirection */
execvp(structpipeline[i].data[0], structpipeline[i].data);
See also this question
Redirecting exec output to a buffer or file

Redirecting input and output in a shell

Hi I've been programming a shell in c and I got stuck while trying to redirect. While redirecting the stdout in my program works the stdin doesn't.
void redirect(node_t* node){
// mode 0: >$%d mode 1: < mode 2: > mode 3: >>
int input = 0;
if(node->redirect.mode == 2){
input = 1; // >
} else{
input = 0; // <
}
int pid = 0;
int *status = 0;
char * filename = node->redirect.target; // filename
int fd;
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
if((pid = fork()) == 0){
dup2(fd, input); // STDIN OR STDOUT
close(fd);
node_t* node2 = node->redirect.child;
execvp(node2->command.program, node2->command.argv); // execute program
printf("failed to execvp\n");
exit(1);
} else {
wait(status);
}
}
I'm new to the fork() but my question is what am I doing wrong here that redirecting stdout works but stdin it writes nothing to the given file.
As mentioned in the comments, you need to use different open options depending on whether you're opening the file for input or output redirection. You can put this into your if.
int flags;
if(node->redirect.mode == 2){
input = 1; // >
flags = O_WRONLY | O_CREAT | O_TRUNC;
} else{
input = 0; // <
flags = O_RDONLY;
}
int pid = 0;
int *status = 0;
char * filename = node->redirect.target; // filename
int fd;
fd = open(filename, flags, 0666);
Also, you need to specify the permission modes for the case where the output file is created. It's OK to specify this argument all the time, it will be ignored when O_CREAT isn't in the flags.

Implementation of Redirection in User-Created Shell is not working properly

I am trying to create a shell similar to bash, with redirection and pipes.
In my main(), I call a parser and then call the function below. The problem I am running into is the fact that when I run my shell, it outputs to the terminal correctly, but it does not output to the file correctly when using the >, 1>, or 2>.
For instance, if I call:
pwd > foo5.txt
I end up receiving:
>
foo5.txt
In the text file I write too as opposed to the stdout (for ">"/"1>") or stderr (for "2>") which I am trying to achieve.
This is my code to fork and create the child process:
pid_t create_process(char *part, int const pipes[][2], int pipenum)
{
pid_t pid; // Initialize variables/pointers/arrays.
char *args[64];
int argc=0, n;
char *arg=strtok(part, " \t");
//char const **filename = args;
while(arg != NULL)
{
args[argc++]=arg;
arg=strtok(NULL, " \t");
}
args[argc++]=NULL;
pid = fork(); // Create Fork.
if(pid == 0)
{
int m;
if(pipes[pipenum][STDIN_FILENO] >= 0)
dup2(pipes[pipenum][STDIN_FILENO], STDIN_FILENO); // FD 0.
if(pipes[pipenum][STDOUT_FILENO] >= 0)
dup2(pipes[pipenum][STDOUT_FILENO], STDOUT_FILENO); // FD 1.
// Close all pipes.
for(m=0; m<64; m++)
{
if(pipes[m][STDIN_FILENO] >= 0)
close(pipes[m][STDIN_FILENO]);
if(pipes[m][STDOUT_FILENO] >= 0)
close(pipes[m][STDOUT_FILENO]);
}
char *filename;
char *newargs[64];
newargs[63] = NULL;
int i = 0;
int j = 0;
for(i = 0; i<64; i++)
{
if (args[i] == ">")
{
i++;
if (args[i] != NULL)
{
filename = args[i];
int redir = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
dup2(redir, 1);
close(redir);
}
}
else if (args[i] == "2>")
{
i++;
if (args[i] != NULL)
{
filename = args[i];
int redir = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
dup2(redir, 2);
close(redir);
}
}
else if (args[i] == "2>")
{
i++;
if (args[i] != NULL)
{
filename = args[i];
int redir = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
dup2(redir, 2);
close(redir);
}
}
else if (args[i] == 0)
{
break;
}
else
{
newargs[j] = args[i];
j++;
cout<<"The arg is: " << newargs[j] <<endl;
}
}
execvp(newargs[0], newargs);
fprintf(stderr, "Command not found.\n");
exit(255);
}
else if(pid < 0)
{ // Error checking.
fprintf(stderr, "Fork Failed\n");
}
return(pid);
}
UPDATE: Now my code will not recognize the commands, and the arguments being printed (for error checking) appear as such:
ls > foo5.txt
The arg is: fprintf
The arg is:
The arg is: ▒
Command not found.
I see a few problems here:
First, you have the for loop where you scan the command arguments for redirection syntax (if (strcmp(args[i],">")==0) and so on) - but if the condition is true (meaning you found a redirection character) you're always opening args[2], not args[i+1].
Second (and this is why the redirection syntax gets passed on to the command you're running as command arguments) - once you detect redirection syntax, you don't remove the redirection operator or the target filename from the list of arguments that you pass to execvp().
For instance, if args[] = {"echo", "a", ">", "logfile", 0}, your code detects a request to send the output to a new file called "logfile" and redirects the FDs correctly, but it still passes those three arguments ["a", ">", "logfile"] to the command.
Third - in your loop, you're calling execvp() at the end of each conditional statement - meaning that you don't get to the end of argument processing before you launch the new process. You need to process all the command arguments for shell syntax and then exec the command.
To fix the various problems with arg handling, probably the most effective solution is to build a new argument list as you're processing the raw ones provided by the user. For instance (using a==b as a string equality test for brevity)
if (args[i] == ">")
{
i++; //skip the arg
if (args[i]) { // check we haven't hit the end of the arg list
filename = args[i];
// then open the file, dup it to stdout or whatever, etc...
}
else if (args[i] == "<") // repeat for other redirection syntax...
else { // Finally, handle the case where we didn't identify any shell syntax:
newargs[j] = args[i]; // Copy the arg to the new list, since it isn't "special"
j++; // Size of newargs[] has been increased
}
Note that this still doesn't handle things like no whitespace around the ">" character: "echo foo>file" will just print "foo>file"... Syntax processing gets a little more complicated in that case, as you've got to account for quoting rules and escape characters to process the arguments correctly.

Resources