0

My problem is in line read(pipe1[0], path1, pathLength1); where for some reason variable path1 has contains additional characters. For example I enter path "./test.txt" which contains 10 characters, then send it trough pipe, and this read() line of code sets path1 variable to "./test.txt" and then plus some 4 random characters (14 characters total). Can you tell me what am I doing wrong?

I found work around by adding terminate character manually, but I still don't know what's the problem.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <sys/wait.h>
int main(){
    int pipe1[2], pid;
    if(pipe(pipe1) < 0)
    {
        printf("Greska prilikom kreiranja datavoda!\n");
        // exit(-1);
    }
    // Parent process
    if(pid = fork() != 0){
    char path[100], key[100];
    printf("Unesite putanju do fajla koji treba otvoriti \n");
    scanf("%s", path);
    printf("Unesite kljucnu rec koju treba traziti u fajlu\n");
    scanf("%s", key);
    printf("Putanja koju ste uneli je: %s, a kljucna rec: %s\n", path, key);
    close(pipe1[0]);
    int pathLength = strlen(path);
    int keyLength = strlen(key);
    write(pipe1[1], &pathLength, sizeof(pathLength));
    write(pipe1[1], &keyLength, sizeof(keyLength));
    write(pipe1[1], path, pathLength);
    write(pipe1[1], key, keyLength);
    wait(NULL);
    close(pipe1[1]);
    }
    // Child Process
    else
    {
        char path1[100], key1[100];
        int pathLength1, keyLength1;
        close(pipe1[1]);
        read(pipe1[0], &pathLength1, sizeof (pathLength1));
        read(pipe1[0], &keyLength1, sizeof (keyLength1));
        read(pipe1[0], path1, pathLength1);
        read(pipe1[0], key1, keyLength1);
        // For some reason strlen(path1) is 14 ?
        path1[pathLength1] = '\0';
        key1[keyLength1] = '\0';
        printf("Proces dete primio put: %s i kljucnu rec: %s\n", path1, key1);
        FILE *f;
        f = fopen(path1, "r");
        if(f == NULL){
            printf("Greska prilikom otvaranja fajla!");
        }
        int i=0;
        while(!feof(f)){
            i++;
            char tmp[500];
            fgets(tmp, sizeof(tmp), f);
            if(strstr(tmp, key1) != NULL)
                printf("Kljucna rec se nalazi u liniji: %d\n", i);    
        }
        fclose(f);
        close(pipe1[0]);
    }
    return 0;
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • Side note 1: `printf("Proces dete primio put: %s i kljucnu rec: %s\n", &path1, key1)`: `&path1` -> `path1`. Side note 2: https://stackoverflow.com/questions/5431941/why-is-while-feoffile-always-wrong – Jabberwocky Mar 21 '23 at 13:44
  • 2
    you are not checking the return value of read – stark Mar 21 '23 at 13:46
  • I have changed &path1 before, just forgot to change it here. Thank you anyway, but the problem remains. So, how should i check return of read, and what would it change ? I am pretty new to this type of programming ? – Vlada Stefanovic Mar 21 '23 at 13:50
  • @VladaStefanovic yes, the problem remains. _Side notes_ are useful information, but not directly related to your question. – Jabberwocky Mar 21 '23 at 14:14
  • 1
    Re. `"how should i check return of read"`: please refer to the [documentation](https://man7.org/linux/man-pages/man2/read.2.html#RETURN_VALUE). – G.M. Mar 21 '23 at 14:21

2 Answers2

1

You forgot to care about the null terminator of your strings.

On the writer side:

  • you write the 10 characters of "./test.txt"
  • you write the int containing 10.

On the reader side:

  • you read the length (10) into pathLength1,
  • you read 10 (pathlength1) characters into path1. Now path1 is not a null terminated string because path1[10] to path1[99] contain undetermined values.

The easiest would be on the writing side change int pathLength = strlen(path); to int pathLength = strlen(path) + 1;. Then the null terminator will be written into the pipe and will also be read from the pipe on the reader side.

Another method would be to initialize the path1 buffer to zero, e.g with memset(path1, 0, sizeof(path1)) or just putting the null terminator at the right place with path1[pathLength1] = 0.

Same for key and keyLength.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
0

I found the answer. It's just a simple oversight. I should have done this:

int pathLength = strlen(path) + 1;
int keyLength = strlen(key) + 1;

because that + 1 accounts for the '\0' at the end of the string I am writing through pipeline.

Galen
  • 1,307
  • 8
  • 15