简体   繁体   中英

System-calls with c

Hi I'm trying to make a couple pipes in c for communication between a 'server' and an 'interface'. I'm getting a weird error though that I'm having trouble debugging. I've been looking at this for a while and I'm afraid that I'm looking past it at this point. Any help will be greatly appreciated.

//server file
// include needed libraries
#include <errno.h>     // system error numbers
#include <stdio.h>     // Standard Input and Output Library 
#include <stdlib.h>    // Standard General Utilities Library
#include <string.h>    // strings and arrays
#include <sys/types.h> // needed for pipes to work
#include <sys/wait.h>  // for waitpid
#include <unistd.h>    // sleep

#define BUFLENMES 65
#define BUFLEN2 1024

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

// function prototype for comparing ID values
// using void in order to use built-in sort function
int compareID(const void *, const void *);

/**************** Main function *******************/
int main (int argc, char *argv[]) {

    // initialize values for file reading
    int  iter = 0,
         value = 0,      
         command,
         outputFD;

    // set up based on spaces used for delimtation
    char id[8],
         odometer[6],
         gallons[8],
         err,
         buffer[BUFLEN2+1];

    // get input and output file descriptors for pipes
    err = sscanf (argv[1], "%d", &command);
    if (err == 0) {
       printf("Parameter must be an integer.\n");
       exit(2);
    }

    err = sscanf (argv[2], "%d", &outputFD);
    if (err == 0) {
       printf("Parameter must be an integer.\n");
       exit(2);
    }

    // initialize struct
    gasData     gasRecords[20];

    // open file that contains the gas data
    FILE *iFile;
    iFile = fopen ("./gasData.txt", "r");

    //read file for records
    do {
        value = fscanf (iFile, "%8s", id);
        value = fscanf (iFile, "%6s", odometer);
        value = fscanf (iFile, "%8s", gallons);

        //store values in gasRecords struct
        strcpy(gasRecords[iter].id, id);
        sscanf (odometer, "%d", &gasRecords[iter].odometer);
        sscanf (gallons, "%f", &gasRecords[iter].gallons);

        // move to next record
        iter++;
    } while (value != EOF);

    fclose(iFile);

    // use iter to print records stored into struct
    printf("\nRecords Stored\n");
    for(int i = 0; i < (iter -1) ; i++) {
        printf("element = %d:   ", i);
        printf("id = %s, ", gasRecords[i].id);
        printf("odometer = %d, ", gasRecords[i].odometer);
        printf("gallons = %f\n", gasRecords[i].gallons);
    }
    printf("\n");

    /***************** act as server ****************/
    int  odom[iter-1],
         count;

    float averageMPG;
    // checking commands
    do {
        char subString[8],
             finalMessage[BUFLEN2+1],
             message[BUFLENMES+1],
             temp[20];

        err = read (command, buffer, BUFLEN2);
            if (err == -1 ) {
                printf ("Error on read from pipe [server]: %d\n", errno);
                exit (3);
            }
        buffer[BUFLEN2] = '\0';

        if(strstr(buffer, "list,")) {
            count = 0;

            // get second part of command after the firs 5 chars
            for(int i =0; i < 10; i++) {
                subString[i] = buffer[i + 5];
            }

            // loop through structure for other IDs
            for(int i =0; i < (iter-1); i++) {
                if(!strcmp(gasRecords[i].id, subString)) {
                    odom[i] = gasRecords[i].odometer;
                }
            }

            // sort using compareID below and qsort
            qsort(odom, (iter-1), sizeof(int), compareID);

            while(count < (iter-1)) {

                // for each element in odom, check gasRecords
                for(int i=0; i < (iter-1); i++) {

                    // if both the ID and the odometer match, send back to interface
                    if(!strcmp(gasRecords[i].id, subString) &&
                        odom[count] == gasRecords[i].odometer) {
                        char message2[65],
                             temp2[20];

                        sprintf(temp2, "element %d:  ", i);
                        strcpy(message2, temp2);

                        sprintf(temp2, "id = %s, ", gasRecords[i].id);
                        strcat(message2, temp2);

                        sprintf(temp2, "odometer = %d, ", gasRecords[i].odometer);
                        strcat(message2, temp2);

                        sprintf(temp2, "gallons %f\n", gasRecords[i].gallons);
                        strcat(message2, temp2);
                        strcat(finalMessage, message2);
                    }
                }
                count++;
            }
            strcat(finalMessage, '\0');
            err = write (outputFD, finalMessage, strlen(finalMessage)+1);
            if (err == -1 ) {
                printf ("Error on write to interface: %d\n", errno);
                exit (3);
            }
        }
        else if(strstr(buffer, "mpg,")) {
            averageMPG = 0.0;
            count = 0;

            // get ID into subString
            for(int i = 0; i < 10; i++) {
                subString[i] = buffer[i + 4];
            }

            // search for mpg data for id and add it up
            for(int i = 0; i < (iter-1); i++) {
                if(!strcmp(gasRecords[i].id, subString)) {
                    averageMPG += gasRecords[i].gallons;
                    count++;
                }
            }

            sprintf(temp, "Average MPG = %f\n", (averageMPG/count));
            strcpy(message, temp);
            message[BUFLENMES] = '\0';
            err = write (outputFD, message, strlen(message)+1);
            if (err == -1 ) {
                printf ("Error on write to interface: %d\n", errno);
                exit (3);
            }
        }

        // if exit is entered print "response: Server complete."
        else if(!strcmp(buffer, "exit")) {
            strcpy(message, "Server complete");
            message[BUFLENMES] = '\0';
            err = write (outputFD, message, strlen(message)+1);
            if (err == -1 ) {
                printf ("Error on write to interface: %d\n", errno);
                exit (3);
            }

        }

        // check for invalid command
        else {
            strcpy(message, "Invalid command");
            message[BUFLENMES] = '\0';
            err = write (outputFD, message, strlen(message)+1);
            if (err == -1 ) {
                printf ("Error on write to interface: %d\n", errno);
                exit (3);
            }
        }

    } while(strcmp(buffer, "exit"));
    return 0;
}

/****************** Function *********************/
int compareID(const void *first, const void *second) {
    int f = *((int*)first);
    int s = *((int*)second);

    if (f > s)
        return 1;
    else if (s > f)
        return -1;
    else
        return 0;
}

Here's my interface file

// interface file 

#include <errno.h>     // system error numbers
#include <stdio.h>     // Standard Input and Output Library 
#include <stdlib.h>    // Standard General Utilities Library
#include <string.h>    // strings and arrays
#include <sys/types.h> // needed for pipes to work
#include <sys/wait.h>  // for waitpid
#include <unistd.h>    // sleep

// define buffer length
#define BUFLEN 1024

int main (int argc, char *argv[])
{
    int err,
        i,
        id,
        status,
        pError;

    char buffer[BUFLEN+1],
         command[20],
         tochild[2],
         toparent[2];

    int toChild[2];   // if toChild[1], then writting to child
    int toParent[2];  // if toParent[1], then writting to parent

    // turning tochild into a pipe and checking for an error
    err = pipe(toChild);
    if ( err == -1) {
        printf ("Error on pipe creation: %d\n", errno);
        exit (1);
    }

    err = pipe(toParent);
    if ( err == -1) {
        printf ("Error on pipe creation: %d\n", errno);
        exit (1);
    }
    // create child process
    id = fork ();

    // if id = 0, in child process
    if ( id == 0 ) {

        // set up pipes for passing into server
        close (toChild[1]);
        close (toParent[0]);
        sprintf(tochild, "%d", toChild[0]);
        sprintf(toparent, "%d", toParent[1]);
        tochild[1] = '\0';
        toparent[1] = '\0';

        // exec into server, print records, and wait for instructions
        err = execl("server", "server", tochild, toparent, 0);
        if ( err == -1) {
            printf ("Error on execl: %d\n", errno);
            exit (1);
        }
    }
    // if id > 0, in parent process
    else if ( id > 0 ) {

        close (toChild[0]);
        close (toParent[1]);
        sleep(1);

        do {
            printf("Input command: ");
            scanf("%s", command);
            command[19] = '\0';
            err = write (toChild[1], command, strlen(command)+1);
            if (err == -1 ) {
                printf ("Error on write to pipe: %d\n", errno);
                exit (3);
            }
            // parent reads back reponse from server read toParent[0]
            err = read (toParent[0], buffer, BUFLEN);
            if (err == -1 ) {
                printf ("Error on read from pipe: %d\n", errno);
                exit (3);
            }

            buffer[BUFLEN] = '\0';
            printf ("Response: %s", buffer);
            printf("\n");

        } while(strcmp(command, "exit") != 0);
        pError = waitpid(-1, &status, 0);
        printf("Interface: child process (%d) completed.\n", id);
        printf("Interface: child process exit status = %d.\n", status);
        printf("Interface: Complete.\n");
        exit (0);
    }
    else{
        printf("Error creating forked process");
        exit (4);
    }

}

// compilation and error

csci2>g++ -o server Server.c
csci2>g++ Interface3.c      
csci2>a.out                 

Records Stored
element = 0:    id = red, odometer = 90229, gallons = 13.500000
element = 1:    id = red, odometer = 90345, gallons = 14.500000
element = 2:    id = red, odometer = 90453, gallons = 14.200000
element = 3:    id = green, odometer = 23000, gallons = 32.000000
element = 4:    id = green, odometer = 23300, gallons = 31.500000
element = 5:    id = green, odometer = 23546, gallons = 37.799999
element = 6:    id = , odometer = 120000, gallons = 23.700001
element = 7:    id = , odometer = 120200, gallons = 24.670000
element = 8:    id = , odometer = 120423, gallons = 26.799999
element = 9:    id = 9045, odometer = 67321, gallons = 30.100000
element = 10:   id = 9045, odometer = 67412, gallons = 15.900000
element = 11:   id = 9045, odometer = 67689, gallons = 18.900000

Input command: mpg,red
Response: Average MPG = 14.066667

Input command: mgp,green
Response: Invalid command
Input command: mpg,green
Response: Average MPG = 33.766668

Input command: mpg,9045
Response: Average MPG = 21.633334

Input command: list,red
Response: Average MPG = 21.633334

Input command: list,red
Broken pipe

/* end */ 

its worth noting that the middle id isn't being transferred correctly either. I have a .txt file with this info in it:

red 90229 13.5
red 90345 14.5
red 90453 14.2
green 23000 32.0
green 23300 31.5
green 23546 37.8
1489 120000 23.7
1489 120200 24.67
1489 120423 26.8
9045 67321 30.1
9045 67412 15.9
9045 67689 18.9

I think I know what is wrong, it's this

buffer[BUFLEN] = '\0';

if the recieved message is smaller than that, then you are not nul terminating the string correctly, you should

buffer[err] = '\0';

because read() returns the number of bytes successfuly read.

And of course, the same applies to this buffer[BUFLEN2] = '\\0'; .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM