Cryptos90
Cryptos90

Reputation: 3

Client reads empty line

My Client.c ask for user input and writes it to the FIFO of the oracle.c called ask.me. While my oracle.c is waiting to read something. If the client writes something,the oracle reads it and writes an answer in the fifo of the client called answer.(pid of the client). The client waits and the reads the answer and puts it out.

everything works fine, til the client has to read and put the answer out. Because the client always puts out a empty line and i dont know if the oracle doesnt write anything or the client cant read it.

please help

ORACLE.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>

#define FIFO "/tmp/ask.me"



int isVokal(const char* buf, int i){

    if (buf[i] == '?' && ((buf[i-1] == 'a') || (buf[i-1] == 'e') ||(buf[i-1] == 'i') || (buf[i-1] == 'o') || (buf[i-1] == 'u')))
        return 1;
    else
        return 0;
}

char *adress(const char *buf){

    char tmp[500];
    char adress[500] = "/tmp/answer.";
    int i = 0;
    while(buf[i] != ':'){

        tmp[i] = buf[i];
            i++;
    }

    strcat(adress, tmp);
    puts(adress);
    return adress;
}


int answer(char * buf){
    int i = 0;


    int fd = open(adress(buf), O_WRONLY | O_NONBLOCK );
    char *answer = malloc(PIPE_BUF);

    do{
        i++;
        if(buf[i] == '\0'){
            --i;
            if(buf[i] != '?'){

                sprintf(answer, "%s","Dies ist keine Frage.\n");
                write(fd,answer, PIPE_BUF);
                i++;
            }else if(isVokal(buf,i)){

                sprintf(answer, "%s","Yes!\n");
                write(fd,answer, PIPE_BUF);
                i++;
            }else{

                sprintf(answer, "%s","No!\n");
                write(fd,answer, PIPE_BUF);
                i++;
            }
        }

    }while ( buf[i] != '\0');
    free(answer);
    close (fd);
    return 0;
}

void oracle() {

    int i = 1;
    char *buf;
    buf = malloc(PIPE_BUF);

    if ((mkfifo(FIFO, 0666)) == -1)
        perror(" oracle mkfifo:");


    int fd = open(FIFO, O_RDONLY );
    if(fd == -1)
        perror(" oracle open():");


    while (i) {

    printf("waiting for input\n");
        int n = read(fd, buf, PIPE_BUF);

        if (n == -1) {
            perror(" oracle read():");
            exit(EXIT_FAILURE);
        }else{

            i=answer(buf);
        }
        sleep(2);
    }
    free(buf);
    close(fd);
}


int main(){

    oracle();
    return 0;
}

CLIENT.c

#include <fcntl.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>

#define FIFO "/tmp/ask.me"


void question(){
    id_t pid = getpid();
    int fd2,fd;
    char *quest = malloc(PIPE_BUF);
    char *answer = malloc(PIPE_BUF);
    char *buf= malloc(PIPE_BUF);
    char *myID= malloc(PIPE_BUF);
    int n = 0;

    char adress[500] = "/tmp/answer.";
    sprintf(myID, "%d", pid);
    strcat (adress, myID);


    if (mkfifo(adress, 0666) == -1){
        if(errno == EEXIST)
            perror(" oracle mkfifo:");
        else{
            perror(" oracle mkfifo:");
            exit(EXIT_FAILURE);
        }
    }
    fd = open(FIFO, O_WRONLY );
    if(fd == -1){
        perror("client fd open():");
        exit(EXIT_FAILURE);
    }
    while(n==0){
        printf("Bitte Frage stellen\n");
        n=scanf("%s", buf);
    }
    sprintf(quest, "%d :", pid);
    strcat(quest, buf);

    write(fd,quest,PIPE_BUF);
    close(fd);
    sleep(5);
    fd2 = open(adress, O_RDONLY|O_NONBLOCK);
    if(fd2 == -1){
        perror("client fd2 open():");
        exit(EXIT_FAILURE);
    }

    while(1) {
        n=read(fd2, answer, PIPE_BUF);
        if (n == -1) {
            perror(" client read():");
            break;
        } else{
            puts(answer);
            break;
        }
        sleep(2);

    }
    free(quest);
    free(answer);
    free(buf);
    free(myID);

    close(fd2);
    unlink(adress);
}

int main(){

    question();
    return 0;

}

Upvotes: 0

Views: 58

Answers (1)

Lots of problems here:

  1. return adress; returns a pointer that immediately becomes dangling, so using it is Undefined Behavior.
  2. You're passing an extra space before the : in CLIENT.c, so ORACLE tries to open the wrong filename.
  3. You forgot to null-terminate the filename that ORACLE is trying to open.
  4. Opening a FIFO with O_NONBLOCK only works if you're opening it for reading. It will fail with ENXIO if you try to open it with O_WRONLY and there's no reader yet.
  5. Reading from a file opened with O_NONBLOCK will fail with EWOULDBLOCK if there's no data to read yet.

Fix all of those things and your client program will be able to print Dies ist keine Frage.

By the way, your sleep(2); in CLIENT.c will never run, and you're usually reading and writing a bunch of uninitialized garbage after the data you intend to transfer.

Upvotes: 0

Related Questions