0

I have this two programs in C and I need to find a string value that I pass from the first one to the second and if the string value is in users.txt file, return value 1 or 0 (if the file does not contain the string value).

/*client.c*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

struct message {
        int result;
        char *text;
};

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

        char fifo_name_client[] = "fifo-client";
        char fifo_name_server[] = "fifo-server";

        struct message send, result;

        int fd_client = open(fifo_name_client, O_WRONLY);
        int fd_server = open(fifo_name_server, O_RDONLY);

        send.text = argv[1];
        //printf("Sended: %s, send.text);
        write(fd_client, &send, sizeof(send));
        read(fd_server, &result, sizeof(result));

        if(result.result = 1) printf("User found\n");
        else printf("User not found\n");

        close(fd_client); close(fd_server);

}
/*server.c*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

struct message {
        int result;
        char *text;
};

int main(){

        int fork_result, pid_child, pid_finished, status, child_exit_code;

        char fifo_name_client[] = "fifo-client";
        char fifo_name_server[] = "fifo-server";
        char *user;

        if(access(fifo_name_client, F_OK) != 0){
                if(mknod(fifo_name_client, S_IFIFO | 0666, 0) == -1){
                        perror("mknod");
                        return EXIT_FAILURE;
                }
        }
        if(access(fifo_name_server, F_OK) != 0){
                if(mknod(fifo_name_server, S_IFIFO | 0666, 0) == -1){
                        perror("mknod");
                        return EXIT_FAILURE;
                }
        }

        while(1){

                FILE *fifo_client, *fifo_server;

                fifo_client = fopen(fifo_name_client, "r");
                if(fifo_client == NULL) return EXIT_FAILURE;

                fifo_server = fopen(fifo_name_server, "w");
                if(fifo_server == NULL) return EXIT_FAILURE;

                if(setvbuf(fifo_server, NULL, _IONBF, 0) != 0){ 
                        printf("Error preventing buffering\n");
                }

                struct message send, result;
                fread(&send, sizeof(send), 1, fifo_client);

                user = send.text;
                //printf("Received: %s\n", user); /*Segmentation fault*/
                //printf("Received: %d\n", user);

                fork_result = fork();
                switch(fork_result){
                case -1:
                        printf("Cant create\n");
                        break;
                case 0:
                        execlp("grep", "grep", user, "users.txt", NULL);
                        break;
                default:
                        pid_child = fork_result;
                        pid_finised = wait(&status);
                        if(pid_finished != pid_child) printf("Not equals\n");
                        else {
                                if(WIFEXITED(status)){
                                        child_exit_code = WEXITSTATUS(status);
                                        if(chil_exit_code == 0) result.result = 1;
                                        else result.result = 0;

                                        fwrite(&result, sizeof(result, 1, fifo_server);
                                }
                        }
                        break;
                }
                close(fifo_client); close(fifo_server);
        }
}

My problem here, is that when printf what I receive from the ´client.c´ it appears as a integer value and not the initial string value I give to it in the beggining.

On the other hand, when I do execlp("grep",....) instead of use ´user´ value, I write it as "user1" (is in the file) and "user2" (is not in the file) and the value that comes back to ´client.c´ is correct.

If anyone knows why I get a integer value instead of the initial string I'd be really grateful.

Thank you, and sorry for my bad english

EDIT

I made it work and now the two programs look this way:

/*client.c*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

#define MAX_BUF 1024

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

        char fifo_name_client[] = "fifo-client";
        char fifo_name_server[] = "fifo-server";
    char *user; 
    char result[MAX_BUF];

        int fd_client = open(fifo_name_client, O_WRONLY);
        int fd_server = open(fifo_name_server, O_RDONLY);

    user = argv[1];

        //printf("Sended: %s\n", user);
        write(fd_client, user, sizeof(user));
        read(fd_server, result, MAX_BUF);

        if(strcmp(result,"1") == 0) printf("User found\n");
        else printf("User not found\n");

        close(fd_client); close(fd_server);

}
/*server.c*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

#define MAX_BUF 1024

int main(){

        int fork_result, pid_child, pid_finished, status, child_exit_code;

        char fifo_name_client[] = "fifo-client";
        char fifo_name_server[] = "fifo-server";

    char *result;

        if(access(fifo_name_client, F_OK) != 0){
                if(mknod(fifo_name_client, S_IFIFO | 0666, 0) == -1){
                        perror("mknod");
                        return EXIT_FAILURE;
                }
        }
        if(access(fifo_name_server, F_OK) != 0){
                if(mknod(fifo_name_server, S_IFIFO | 0666, 0) == -1){
                        perror("mknod");
                        return EXIT_FAILURE;
                }
        }

        while(1){

        char user[MAX_BUF];
                int fd_client = open(fifo_name_client, O_RDONLY);
            int fd_server = open(fifo_name_server, O_WRONLY);

                read(fd_client, user, MAX_BUF);

                //printf("Received: %s\n", user);

                fork_result = fork();
                switch(fork_result){
                case -1:
                        printf("Cant create\n");
                        break;
                case 0:
                        execlp("grep", "grep", user, "users.txt", NULL);
                        break;
                default:
                        pid_child = fork_result;
                        pid_finished = wait(&status);
                        if(pid_finished != pid_child) printf("Not equals\n");
                        else {
                                if(WIFEXITED(status)){
                                        child_exit_code = WEXITSTATUS(status);
                                        if(child_exit_code == 0) result = "1";
                                        else result = "0";
                                        write(fd_server, result, sizeof(result));
                                }
                        }
                        break;
                }
                close(fd_client); close(fd_server);
        }
}

My problem now is that everytime I execute server.c and then client.c for some reason, execlp("grep", "grep", user, "users.txt", NULL); it executes twice and then server.c program stops because of "broke pipe error", and I don´t know how to solve that. Does someone know why is that and how to solve it? Thank you in advance

  • 1
    please compile your code using `-Wextra -Wall -Werror` flags and fix all the issues. – MarcoLucidi May 22 '22 at 16:15
  • 1
    also the "integer value" you get i think it's just the pointer (in the client program) of your string and will of course be invalid in the server program (segfault): `write(fd_client, &send, sizeof(send));` writes the struct contents and `send.text` is a pointer, so it writes the pointer to the string (it's address), not the string characters. – MarcoLucidi May 22 '22 at 16:42
  • I made it work but another problem appeared. Please look the edited part. Thank you for the response. – I'm really bad at coding May 22 '22 at 17:10
  • The new code can hardly be said to be "working". `sizeof(user)` is the size of a `char *`. If the length of the string is exactly the same as the size of a char pointer then you may get some reasonable results, but it the string is longer it will be truncated, and if it is shorter then your program is accessing invalid data and exhibiting undefined behavior. You seem to have some confusion about what a `char *` actually is. – William Pursell May 22 '22 at 17:25
  • [This answer](https://stackoverflow.com/a/5925935/147356) provides some explanation of the problem to which @WilliamPursell is referring. – larsks May 22 '22 at 18:44
  • Okay. Then should I replace sizeof with strlen?? If not, how can I get get the size of the string if I can't use neither? I tried with MAX_BUF, but I couldn't get the correct answers in any program – I'm really bad at coding May 22 '22 at 19:29

1 Answers1

0

Now it works the way I wanted it to work. Here's the solution if anyone wanted to know:

/*client.c*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

#define MAX_BUF 1024

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

        char fifo_name_client[] = "fifo-client";
        char fifo_name_server[] = "fifo-server";
        char *user; 
        char result[MAX_BUF];

        user = argv[1];

        //printf("Sended: %s\n", user);
        int fd_client = open(fifo_name_client, O_WRONLY);
        write(fd_client, user, sizeof(user));
        close(fd_client);

        int fd_server = open(fifo_name_server, O_RDONLY);
        read(fd_server, result, MAX_BUF);
        close(fd_server);

        if(strcmp(result,"1") == 0) printf("User found\n");
        else printf("User not found\n");

}
/*server.c*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

#define MAX_BUF 1024

int main(){

        int fork_result, pid_child, pid_finished, status, child_exit_code;

        char fifo_name_client[] = "fifo-client";
        char fifo_name_server[] = "fifo-server";

        char *result;

        if(access(fifo_name_client, F_OK) != 0){
                if(mknod(fifo_name_client, S_IFIFO | 0666, 0) == -1){
                        perror("mknod");
                        return EXIT_FAILURE;
                }
        }
        if(access(fifo_name_server, F_OK) != 0){
                if(mknod(fifo_name_server, S_IFIFO | 0666, 0) == -1){
                        perror("mknod");
                        return EXIT_FAILURE;
                }
        }

        while(1){

                char user[MAX_BUF];

                int fd_client = open(fifo_name_client, O_RDONLY);
                read(fd_client, user, MAX_BUF);
                close(fd_client);

                //printf("Received: %s\n", user);

                fork_result = fork();
                switch(fork_result){
                case -1:
                        printf("Cant create\n");
                        break;
                case 0:
                        execlp("grep", "grep", user, "users.txt", NULL);
                        break;
                default:
                        pid_child = fork_result;
                        pid_finished = wait(&status);
                        if(pid_finished != pid_child) printf("Not equals\n");
                        else {
                                if(WIFEXITED(status)){
                                        child_exit_code = WEXITSTATUS(status);
                                        if(child_exit_code == 0) result = "1";
                                        else result = "0";

                                        int fd_server = open(fifo_name_server, O_WRONLY);
                                        write(fd_server, result, sizeof(result));
                                        close(fd_server);
                                }
                        }
                        break;
                }
        }
}