Hi guys, i'm working on trying to pass commands from the console from one program to another program by using pipes() and the execve() system calls.

I'm pretty much stuck right now, because I can't seem to determine what i'm doing wrong.

Here are my code listings

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define BUFLEN 100
#define MESSAGE "shit"

int main(int argc, char *argv[])
{
	extern int errno; 
	char buffer[BUFLEN];
	char result[BUFLEN+1];
	char *param[3];
	float *fnum;
	int toServer[2];
	int fromServer[2];
	int pid;
	int err;
	char input[BUFLEN];
	
	/*scanf("%s,%s\n",mpg, input);//fix this to call mpg function*/
	
	/* Create a pipe */
	err=pipe(toServer); /*For reading*/
	err=pipe(fromServer); /*For writing*/
	if(err==-1)
	{
		printf("Error on pipe creation: %d\n",errno);
		exit(1);
	}
	
	pid=fork();
	if(pid==0)
	{
		/* Child process */
		close(fromServer[1]); /*Close output*/
		err=read(fromServer[0], buffer, BUFLEN);/*store from fromServer[0] into buffer*/
		if(err==-1)
		{
			printf("Error on read from pipe: %d\n", errno);
				exit(2);
		}
		sscanf(buffer, "%f", &fnum);//convert buffer to float
		printf("response: Average MPG = %f\n", fnum);/*print from sprintf*/
		exit(0);
	}
	else if (pid>0)  
	{
		/* Parent process */
		close(toServer[0]);/*Close input*/
		err=write(toServer[1],result,strlen(result)+1);/*write char[] to fd[1]*/
		if(err==-1)
		{
			printf("Error on write to pipe: %d\n", errno);
			exit(3);
		}
		sprintf(result, "%f", *fnum);
		param[0]=result;
		err = execve ("./server.c", param,0);
		if (err == -1)
		printf ("error on execve: %d\n", errno);
				exit(0);
	}
	else
		exit(4);
}

That is the first program that handles taking in the input from the console. This next one is the program that processes the command that is passed through the pipe.

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

typedef struct 
{
	char id[8];
	int odometer;
	float gallons;
}Records;

int main(int argc, char *argv[])
{
	FILE *finput;
	int i, n;
	//extern int errno; 
	//char buffer[BUFLEN];
	//char result[100];
	Records r[20];

	finput = fopen("proj3.txt", "r");

	for (i = 0; i < 13; i++ ) 
	{
		fscanf(finput, "%s %d %f", &r[i].id, &r[i].odometer, &r[i].gallons);
		if (feof(finput)) 
		{
			printf("end-of-file detected on file proj3.txt\n");
			exit (1);
		}
		printf("element = %d, id = %s,odometer = %d, gallons = %f\n", i, r[i].id, r[i].odometer, r[i].gallons);
	}
	
	/*parameters passed to Server program via execve call, take in arguments as console,
	and calculate them using the mpg<id> function that calculates the avg 
	use fromServer[], toServer[] to pass response back to Interface program to print
	create text file that stores in all the values listed in the project 3 description
    just numbers.
	use fprintf(), fscanf() to read and write from files
	must use fopen() and fclose() to handle open and close of files
	*/
}

Also, the text file which contains the inputs :

987654 201200 4.000000
red 89114 0.000000
red 89712 13.500000
red 90229 15.300000
987654 201001 0.000000
987654 201111 5.200000
987654 201612 25.299999
red 89300 7.100000
green 16 0.000000
green 216 20.000000
green 518 61.000000
green 879 50.000000

Both codes are incomplete at the moment because I am still trying to figure out how to fix it part by part.

My question is, what am I doing wrong? How do I take in input from the console and pass it through the pipes to invoke a function in the "server.c" program. I understand that you can only pass strings, hence my sscanf() and sprintf() functions. Also am I utilizing execve() the right way?

I understand that the community does not generally solve people's homework for them, and yes this is a project for a class, but I am not asking for an actual program, I just need some help in figuring out where i'm going wrong and what it is I should look at.

It'd be great if someone could guide me in the right direction.

Thank you

err = execve ("./server.c", param, 0); You are trying to run the C file! You have to run the executable.

Hey, thanks for the reply, I have changed a bit of my code but now I'm getting an errno error: 14 when it tries to call the execve() system call. I have changed it to execute the executable function, my makefile has already compiled the server program, i've been trying to figure out what my problem is by altering the code and testing it part by part by i'm still at a complete loss.

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define STD_INPUT 0
#define STD_OUTPUT 1
#define BUFLEN 100
#define MESSAGE "shit"

int main(int argc, char *argv[])
{
	extern int errno; 
	char buffer[BUFLEN];
	char result[BUFLEN];
	char *param[2];
	float fnum=15.05;
	int toServer[2];
	int fromServer[2];
	int pid;
	int err;
	char input[BUFLEN];
	//int input;
	/*scanf("%s,%s\n",mpg, input);//fix this to call mpg function*/
	//printf("Please enter your input\n");
	//scanf("%d",input);
	/* Create a pipe */
	err=pipe(&toServer[1]); /*For reading*/
	err=pipe(&fromServer[0]); /*For writing*/
	if(err==-1)
	{
		printf("Error on pipe creation: %d\n",errno);
		exit(1);
	}
	
	pid=fork();
	if(pid==0)
	{
		/* Child process */
		close(fromServer[1]); /*Close output*/
		close(STD_OUTPUT);
		dup(fromServer[0]);
		err=read(fromServer[0], buffer, BUFLEN);/*store from fromServer[0] into buffer*/
		if(err==-1)
		{
			printf("Error on read from pipe: %d\n", errno);
				exit(2);
		}
		sscanf(buffer, "%f", fnum);//convert buffer to float
		printf("response: Average MPG = %f\n", fnum);/*print from sprintf*/
		exit(0);
	}
	
	else if (pid>0)  
	{
		/* Parent process *
		close(toServer[0]);/*Close input*/
		close(STD_INPUT);
		dup(toServer[1]);
		sprintf(result,"%d",12345);
		
		err=write(toServer[1],result,strlen(result)+1);/*write char[] to fd[1]*/
		if(err==-1)
		{
			printf("Error on write to pipe: %d\n", errno);
			exit(3);
		}
		param[0]=result;
		err = execve ("./server",param,NULL);
		if (err == -1)
		printf ("error on execve: %d\n", errno);
				exit(0);
	}
	else
		exit(4);
	
}
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BUFLEN 100

typedef struct 
{
	char id[8];
	int odometer;
	float gallons;
}Records;

int main(int argc, char *argv[])
{
	extern int errno; 
	int err;
	int fromInterface=atoi(argv[1]);
	int toInterface=atoi(argv[2]);
	int i, n;
	char buffer[BUFLEN];
	FILE *finput;

	Records r[20];
	
	err = read(fromInterface,buffer,BUFLEN);
	printf ("String read from interface = %s\n", buffer);
		
	if(err == -1)
	{
		printf("server read errno=%d\n", errno);
		exit(7);
	}

	/*finput = fopen("proj3.txt", "r");
	
	for (i = 0; i < 13; i++ ) 
	{
		fscanf(finput, "%s %d %f", &r[i].id, &r[i].odometer, &r[i].gallons);
		if (feof(finput)) 
		{
			printf("end-of-file detected on file proj3.txt\n");
			exit (1);
		}
		printf("element = %d, id = %s,odometer = %d, gallons = %f\n", i, r[i].id, r[i].odometer, r[i].gallons);
	}
	

	

	/*parameters passed to Server program via execve call, take in arguments as console,
	and calculate them using the mpg<id> function that calculates the avg 
	use fromServer[], toServer[] to pass response back to Interface program to print
	create text file that stores in all the values listed in the project 3 description
    just numbers.
	*/
}

Sadly I haven't used unix in many years, so hopefully a real unix person will come along to help you. A couple of points, though.

You should pass the base pointer of the 2-element int array to pipe. Also, try cleaning up your error handling, something like this, although I haven't included any cleanup like closing fd's.

void die(const char *msg)
{
    perror(msg);
    exit(1);
}
...
    if (pipe(toServer) == -1) die("pipe to");
    if (pipe(fromServer) == -1) die("pipe from");
    if ((pid = fork()) == -1) die("fork");
    // use same err-handling method elsewhere too

You need to remember when to pass the value and when the address to the scanf functions:

// You need to add an ampersand here since fnum is a float.
    sscanf(buffer, "%f", &fnum);
...
// And remove one here, since id is a string.
    fscanf(finput, "%s %d %f",
           &r[i].id, &r[i].odometer, &r[i].gallons);

Try not closing STD_OUTPUT and STD_INPUT for now; I don't see why that's necessary in this particular case (although maybe it is). And presumably you should be saving and using the file descriptors returned from dup:

if ((fd = dup(fromServer[0])) == -1) die("dup fromServer");

I'm already overstepping my knowledge so I'll stop there.

> param[0]=result;
And what of param[1], is that NULL (it should be)

> printf ("error on execve: %d\n", errno);
Use perror(), and it will give you a wordy description, and not just "error 14".

This article has been dead for over six months. Start a new discussion instead.