1

I've been stuck on getting piping to work between two programs for the last couple of hours and I'm stuck and not sure if I'm doing something wrong. The idea of my program is that I'm going to use interface.c to open a pipe, and then execute db.c. I want to use two pipes to communicate between the two different programs. Now, with interface.c being the 'parent' and db.c being the 'child', I'm not sure if I'm passing in the parameters to my pipe correctly via the execl command. Everything compiles correctly, but when I try to run the interface program, I'm getting an error stating: 'Bad File Number.' Is it possible that I'm not using pipes correctly? Currently, I'm just trying to get my program to send an integer, value, over the pipe to db.c. Any help would be much appreciated.

Code for interface.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
//PIPES:
//
//Parent: reads from P1_READ, writes on P1_WRITE
//Child:  reads from P2_READ, writes on P2_WRITE
#define P1_READ     0
#define P2_WRITE    1
#define P2_READ     2
#define P1_WRITE    3

// the total number of pipe *pairs* we need
#define NUM_PIPES   2

int main(int argc, char *argv[])
{
    //Create Pipe Array
    int fd[2*NUM_PIPES];

    //For Parameter Passing:
    char param0[20];        //P1_Read
    char param1[20];        //P2_Write
    char param2[20];        //P2_Read
    char param3[20];        //P1_Write

    snprintf(param0, sizeof(param0), "%d" , fd[0]);
    snprintf(param1, sizeof(param1), "%d" , fd[1]);
    snprintf(param2, sizeof(param2), "%d" , fd[2]);
    snprintf(param3, sizeof(param3), "%d" , fd[3]);

    //Variables
    pid_t pid;
    int val = 42;

    //Allocate the PIPES
    for (int i=0; i<NUM_PIPES; ++i)
    {
        if(pipe(fd+(i*2)) < 0)
        {
            perror("Failed to allocate the pipes");
            exit(EXIT_FAILURE);
        }
    }

     //If the fork of the program does not work:
    if ((pid = fork()) < 0)
    {
        perror("Failed to fork process");
        return EXIT_FAILURE;
    }



    if(pid == 0)
    {   //Child Process
        execl("./db", "db", param0, param1, param2, param3, (char *)NULL);
    }
    else
    {   //Parent Process

        //SENDING VALUES HERE
        close(fd[P2_READ]);
        close(fd[P2_WRITE]);
        printf("Interface is sending|%d| to DB\n", val);
        if(write(fd[P1_WRITE],&val, sizeof(val)) != sizeof(val))
        {
            perror("Interfae failed to send value to DB");
            exit(EXIT_FAILURE);
        }
    }

    return 0;
}

This is for db.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
//Typedef-Class-
typedef struct Information
{
    int accountId;
    int checkNumber;
    int date;
    float amount;
} Information;

int main(int argc, char *argv[])
{
//For Input
    //Account Data
    Information acctData[25];
    int dataStorageLooper = 0;      //How many db entries

    //For File Input
    int aVal;
    int bVal;
    int cVal;
    float dVal;

    //Prepare for file input:
    FILE * fp;
    fp = fopen ("accountData.txt", "r");

    //Reads Input
    while(1)
    {
        if (fscanf(fp, "%d %d %d %f", &aVal, &bVal, &cVal, &dVal)!=4)
        {
            break;
        }
        //Puts data into appropriate arrays
        acctData[dataStorageLooper].accountId= aVal;
        acctData[dataStorageLooper].checkNumber= bVal;
        acctData[dataStorageLooper].date= cVal;
        acctData[dataStorageLooper].amount= dVal;
        dataStorageLooper++;
    }

    //Decrement index to point to last item
    dataStorageLooper--;

    //Displays all values
    printf("\nDisplaying AccountData.txt\n");
    for( int i = 0; i < dataStorageLooper; i++)
    {
        printf("Line|%d|: Account|%d|: Check|%d|: Date|%d|: Amount|%.2f|\n",i,acctData[i].accountId,acctData[i].checkNumber,acctData[i].date,acctData[i].amount);
    }
    //Closes File
    fclose(fp);
//End Input

//Parameter Receiving:
    int pipes[4];           //Pipe Array
    int value = 7;
    int test;

    //Build the pipes
    pipes[0] = atoi(argv[1]);       //P1_Read
    pipes[1] = atoi(argv[2]);       //P2_Write
    pipes[2] = atoi(argv[3]);       //P2_Read
    pipes[3] = atoi(argv[4]);       //P1_Write

    //Troubleshooting    
    printf("The number of parameters: %d\n",argc);
    printf("Parameter 1: %s\n", argv[0]);
    printf("I stared correctly\n");

    //Testing
    close(pipes[0]);
    close(pipes[3]);

    //SHOULD RECEIVE VALUE HERE
    test = read(pipes[2], &value, sizeof(value));

        if (test < 0)
        {
            perror("DB: Failed to read data from parent");
            exit(EXIT_FAILURE);
        }
        else if (test == 0)
        {
            //Unexpected
            fprintf(stderr, "DB: Read End-Of-File from pipe");
        }
        else
        {
            //What did the child receive?
            printf("DB: Received Value:(%d)\n", value);
        }
        close(pipes[2]);
        close(pipes[1]);




    return 0;
}
  • I answered a question about `interface.c` and `db.c` a day or two ago — hmmm, yes, there it is [Sending and receiving character array using piping through argv in C](http://stackoverflow.com/questions/39714636/sending-and-receiving-character-array-using-piping-through-argv-in-c/). Different user, but …. Does the answer there help at all? Does it give you someone to talk to? – Jonathan Leffler Oct 03 '16 at 01:27

1 Answers1

0

One of the things you're doing wrong is snprintfing the value of the various elements in fd before you've assigned any value to them. That's undefined behaviour, and the values you're passing as parameters are totally meaningless (at best).

This strikes me as a very odd way to do things, though. Usually you would just dup2 fds 0 and 1 so that the child's stdin and stdout are redirected to the appropriate pipe fds.

rici
  • 234,347
  • 28
  • 237
  • 341
  • I was trying to pass the parameters to access the pipe in db.c. Am I passing them wrong? – Tyler Hietanen Oct 03 '16 at 00:01
  • @sunburst: as i said, when you call `snprintf(param1, sizeof(param1), "%d" , fd[0]);`, `fd[0]` has not yet been assigned a value, so printing that value is undefined behaviour. – rici Oct 03 '16 at 00:26