execve error: no such file or directory - c

I'm trying to write a program to execute and schedule a list of processes. My code for main.c is below. When run, I receive an error from perror saying there is no such file or directory. I'm guessing this is because the files/programs in my files.txt are not binary executables but I'm not sure how to fix this. files.txt contains the list of programs I want to run. They have all been converted to binary executables already. programs is an array containing the four programs that have been read by the readPrograms function
int main(int argc, char ** argv) {
pid_t pid[50];
pid_t wpid;
int i, j;
int status = 0;
char *newenvp[] = {NULL};
char *newargv[] = {"./files.txt", NULL};
printf("Before forking in the parent\n");
int numProgs = readPrograms();
for (i=0; i<numProgs; i++) {
pid[i] = fork();
if (pid[i] < 0) {
perror("fork error");
exit(EXIT_FAILURE);
}
else if (pid[i] == 0) {
printf("Child process running\n");
execve(programs[i], newargv, newenvp);
perror("execve error");
exit(EXIT_FAILURE);
}
}
for (i=0; i<numProgs; i++) {
wait(&status);
}
return 0;
}
char* programs[50];
int readPrograms();
files.txt below
./first
./second
./third
./fourth
(I did "cc first.c -o first" for all of these files respectively)

I suspect the bug is in the code you're not showing, readPrograms. Most likely you're reading the lines of the text file with fgets and each string has a newline on the end of it, whereas your filenames don't have newlines in them.

Related

Program hangs when opening a named pipe for writing in c - use of wait

This is the main in test1.c:
int main(int argc, char *argv[])
{
int fd1,i, *foo;
pid_t childpid;
mkfifo("myfifo1", 0777);
foo = malloc(10*sizeof(int));
childpid=fork();
if (childpid== -1){
perror("Failed to fork\n");
exit(1);
}
if (childpid==0) {
execlp(argv[1],argv[1],(char *) NULL);
perror("exec failure ");
exit(1);
}
else {
wait(NULL);
fd1 = open("myfifo1", O_RDONLY, 0);
for (i=0; i<10; i++) {
read(fd1, &foo[i], sizeof(int));
}
for (i=0; i<10; i++) {
printf("%d\n", foo[i]);
}
}
close(fd1);
}
and this is the main in test2.c:
int main(int argc, char *argv[])
{
int fd1, i, *foo;
fd1 = open("myfifo1", O_WRONLY);
if (fd1==-1) printf("error\n");
foo = malloc(10*sizeof(int));
for (i=0; i<10; i++) {
write(fd1, &i, sizeof(int));
}
printf("\n");
close(fd1);
}
When I run ./test1 ./test2 the program hangs. I assume that this happens because in test2.c only one end of the pipe opens and the program waits for the other one to do so. However, this never happens because of:
wait(NULL)
And indeed if I remove this command the program works fine. However, I thought that wait is always useful and it is prevents us from creating zombie processes. Am I wrong at all these? Is there any way to keep the wait command and make the program work?
Thanks in advance!

redirect stdout from process to stdin from antother in C [duplicate]

I am trying to implement pipe in C. eg - $ ls | wc | wc
I have written the following code -
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
void run_cmd(char *cmd, int* fd_in, int* fd_out)
{
int c = fork();
if (c==0)
{
if (fd_in != NULL)
{
close(fd_in[1]);
dup2(fd_in[0], 0);
}
if (fd_out != NULL)
{
close(fd_out[0]);
dup2(fd_out[1],1);
}
execlp(cmd, cmd, NULL);
}
}
int main(int argc, char **argv)
{
int fd_1[2], fd_2[2], i;
pipe(fd_1);
pipe(fd_2);
run_cmd(argv[1], NULL, fd_1);
for( i=2; i<argc-1; i++)
{
if (i%2 == 0)
run_cmd(argv[i], fd_1, fd_2);
else
run_cmd(argv[i], fd_2, fd_1);
}
if (i%2 == 0)
run_cmd(argv[i], fd_1, NULL);
else
run_cmd(argv[i], fd_2, NULL);
}
This works fine with two arguments, eg - $./a.out ls wc
But when I try with more than two arguments it does not work.
Would anyone please tell me what's wrong with my code, or any other way to do this?
This does virtually no error checking, but why so complicated?
int main (int argc, char ** argv) {
int i;
for( i=1; i<argc-1; i++)
{
int pd[2];
pipe(pd);
if (!fork()) {
dup2(pd[1], 1); // remap output back to parent
execlp(argv[i], argv[i], NULL);
perror("exec");
abort();
}
// remap output from previous child to input
dup2(pd[0], 0);
close(pd[1]);
}
execlp(argv[i], argv[i], NULL);
perror("exec");
abort();
}
If your are still interested in why your source didn't work (Sergey's solution is better anyway):
The problem is not closing the write side of fd_1 in the parent process. Thus both argv[1] and parent have been writers to that pipe and that caused the confusion. Please don't ask for more details (esp. why the prob doesn't occur if you use only one pipe) but your original source will run with tree processes if you just add a close( fd_1[1] ); after the first call of run_cmd()

Process controller running files in random order

I'm trying to execute and schedule my own list of processes read from a file. The files are running in a random order and I'm just curious as to why this is happening. I have simple print statements in the first, second, etc files that tell which is running, and they always print in different (seemingly random) orders. It isn't messing up my functionality thus far, I'm just curious why this is.
main.c below
int main(int argc, char ** argv) {
pid_t pid[50];
pid_t wpid;
int i, j;
int status = 0;
char *newenvp[] = {NULL};
char *newargv[] = {"./files.txt", NULL};
printf("Before forking in the parent\n");
int numProgs = readPrograms();
for (i=0; i<numProgs; i++) {
pid[i] = fork();
if (pid[i] < 0) {
perror("fork error");
exit(EXIT_FAILURE);
}
else if (pid[i] == 0) {
printf("Child process running\n");
execve(programs[i], newargv, newenvp);
perror("execve error");
exit(EXIT_FAILURE);
}
}
for (i=0; i<numProgs; i++) {
wait(&status);
}
return 0;
}
char* programs[50];
int readPrograms();
readPrograms.c below
int readPrograms() {
int i=0;
char line[50];
int numProgs = -1;
FILE *file;
file = fopen("files.txt", "r");
while(fgets(line, sizeof(line), file)!=NULL) {
line[strlen(line)-1] = '\0';
programs[i]=strdup(line);
i++;
numProgs++;
}
fclose(file);
return numProgs;
}
files.txt below
./first
./second
./third
./fourth
When calling fork, your system creates the new process (copy itself,call exec,overlay itself).
Then your fork is ready, both the parent and the child process are marked ready and the running order of the processes is chosen by your system-scheduler.
So depending on your scheduler either your parent or your child is now run.

Executing Multiple Pipes in a Loop

I am so close to figuring out a program I have been writing for linux shell written in C. I have been wanting to get this working for a while now, and I decided to pick it up again and have been tinkering with it for the past few weeks.
For the following code, keep in mind that the array called arrayOfCommands is dynamically filled. My code fills the arrayOfCommands with the current command being run. For the sake of my example, we will be running the command ls -l | wc and arrayOfCommands is filled with the following, depending on which time through the loop it is:
//Pass #1
arrayOfCommands[]= ("ls", "-l", NULL)
//Pass #2
arrayOfCommands[]= ("wc", NULL)
Here is what I have so far:
//PIPING
int do_command(char **args, int pipes) {
// pipes is the number of pipes in the command
// (In our example, one)
// The number of commands is one more than the
// number of pipes (In our example, two)
const int commands = pipes + 1; //Ex: 2
int i = 0;
// Set up the pipes
int pipefds[2*pipes];
for(i = 0; i < pipes; i++){
if(pipe(pipefds + i*2) < 0) {
perror("Couldn't Pipe");
exit(EXIT_FAILURE);
}
}
// Variables
int pid;
int status;
char *str_ptr;
int j = 0;
for (i = 0; i < commands; ++i) {
// A magic function that updates arrayOfCommands with
// the current command goes here. It doesn't make
// sense in the context of the code, so just believe me! :)
// Ex: The contents will be "ls -l" or "wc" depending on
// which time through the loop we are
pid = fork();
if(pid == 0) {
//if not last command
if(i < commands){
if(dup2(pipefds[j + 1], 1) < 0){
perror("dup2");
exit(EXIT_FAILURE);
}
}
//if not first command&& j!= 2*pipes
if(j != 0 ){
if(dup2(pipefds[j-2], 0) < 0){
perror("dup2");
exit(EXIT_FAILURE);
}
}
for(i = 0; i < 2*pipes; i++){
close(pipefds[i]);
}
// Should any of the below inputs be *arrayOfCommands or
// **arrayOfCommands or &arrayOfCommands?
// I'm REALLY bad with pointers
if( execvp(arrayOfCommands, arrayOfCommands) < 0 ){
perror(arrayOfCommands);
exit(EXIT_FAILURE);
}
}
else if(pid < 0){
perror("error");
exit(EXIT_FAILURE);
}
j+=2;
}
for(i = 0; i < 2 * pipes; i++){
close(pipefds[i]);
}
for(i = 0; i < pipes + 1; i++){
}
wait(&status);
}
When I run this, I get a couple of errors:
dup2: Bad file descriptor
ls: |: No such file or directory
ls: wc: No such file or directory
Could someone help me figure out the following two things:
Why am I getting these errors?
In the execvp function, what kinds if pointers am I looking for? arrayOfCommands was initialized as a char *arrayOfArgs[]
First thing:
//if not last command
if(i < commands)
should be
if(i < commands -1)
since igoes from 0 to commands -1
that should solve dup2: Bad file descriptor
ls: |: No such file or directory
ls: wc: No such file or directory
are caused by malformed arrayOfCommands. It has to be initialized by
char * arrayOfCommands[] = {"ls", "-l", NULL};
and
char * arrayOfCommands[] = {"wc", NULL};
respectively and invoked via execvp(arrayOfCommands[0], arrayOfCommands)
essentially arrayOfCommands has to be of the same format that your argument vector (typically argv) of an int main(int argc, char** argv).

Read pipe from another .c with use of exec, c programm

i have a problem reading from a pipe that was created from another .c via execl! I have tried it with a lot of different approaches but i still can't find the solution. I'd appreciate it if you could help me!
Here is the first code :
...some other code before for loop...
for (counter=0; counter<arithmos; counter++)
{
if (pipe(pinakas[counter]) == -1)
{
perror("pipe");
exit(1);
}
sem_wait(&sima);
strcpy(buffer,queueHead(q));
write(fd[WRITE], buffer, strlen(buffer));
queueRemove(&q);
nodes--;
sem_post(&sima);
pid = fork();
if (pid < 0)
{
perror("fork error");
exit(1);
}
if (pid == 0)
{
execl("./paidi","paidi", (char*)pinakas[counter], (char*)NULL);
exit(1);
}
if (pid > 0)
{
printf ("I am the parent with pid %d\n", getpid());
wait(NULL);
}
}
And here is what my child does...
includes etc etc...
int main(int argc, char **argv)
{
//char fd[2];
int *fd = (int*) argv[1];
int nbytes;
char buffer[256];
char *command;
int i;
for (i=0; i<256; i++)
{
buffer[i] = '\0';
}
printf("test2 %d\n",fd[READ]);
//close(fd[WRITE]);
printf("test3\n");
read(fd[READ], buffer, 256);
printf("test4\n");
close(fd[READ]);
printf("test5\n");
printf("Received url : %s", buffer );
printf("test6\n");
//sprintf(command,"wget %zd", url);
//system(command);
printf("I am a child with pid %d\n", getpid());
return 0;
}
Seems like i am doing something wrong with execl. I am trying to pass pointer as argument and i have a pipe : bad address error. I also tried it with string but nothing... Any ideas?
execve(2) creates a brand-new memory space for loaded executable, you cannot pass pointers from previous program, they don't make any sense in that new memory space.
The tried and true approach here is to replace child's standard input (file descriptor 0) with read-end of the pipe(2) after the fork(2) but before the execve(2) using dup2(2).

Resources