Системная функция ничего не выводит - PullRequest
0 голосов
/ 17 января 2019

Я возился с каналами и связью родитель-потомок, только теперь я использовал вызов функции system, чтобы передать что-то от потомка к родителю. Проблема в том, что в моем примере system на самом деле ничего не выводит.

Родитель читает входные данные и отправляет их дочернему элементу, чтобы проверить, содержит ли строка «отсортированные буквы». Символы должны быть в лексикографическом порядке. Я использовал system, чтобы объединить echo и grep и отправить результат обратно в канал. Я был в состоянии сузить это до конца чтения трубы родителя; это блокирует. Я предполагаю, что это потому, что в канале нет ничего для чтения, и конец записи не закрыт. Я понимаю, что это будет причиной проблемы, для того, чтобы это имело смысл, system не должен был бы ничего выводить.

  /*
$ ./grep
AeIoU
Yes.
blah
No.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <ctype.h>


#define     STRING_SIZE 128

static void     fatalError(char* message);          
int     checkIfAlpha(char   *string, int length);   //f-ja koja proverava da li se string sastroji samo od slova

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

    pid_t   pid;
    char    input[STRING_SIZE];     //cuvamo input string ovde
    char    command[100 + STRING_SIZE];
    int     pipeToParent[2], pipeToChild[2];
    int     n;
    char    tmp[50];
    int     count;


    if (pipe(pipeToParent) < 0)
        fatalError("pipe error");

    if (pipe(pipeToChild) < 0)
        fatalError("pipe error");

    if ((pid = fork()) < 0)
        fatalError("fork error");
    else if (pid == 0) {
            //child
        if (close(pipeToChild[1]) < 0)
            fatalError("close error");

        if (close(pipeToParent[0]) < 0)
            fatalError("close error");

        if (dup2(pipeToParent[1], STDOUT_FILENO) < 0)
            fatalError("dup2 error");

        while (1) {

        if ((count = read(pipeToChild[0], tmp, 50)) < 0)
            fatalError("read error");
        fprintf(stderr, "2\n");
        if (count == 0)
            break;
        sprintf(command, "echo '%s' | grep -i ^a*b*c*d*e*f*g*h*i*j*k*l*m*n*o*p*q*r*s*t*u*v*w*x*y*z*$", tmp);

        if (system(command) < 0) 
            fatalError("system error");

        fprintf(stderr, "3\n"); 

        }

        exit(EXIT_SUCCESS);


    }

    //parent

    if (close(pipeToParent[1]) < 0)
        fatalError("close rror");


    if (close(pipeToChild[0]) < 0)
        fatalError("close error");

    while(fgets(input, STRING_SIZE, stdin) != NULL) {

        input[strlen(input)-1] = '\0';


            if (checkIfAlpha(input, strlen(input)) == -1) {
                fprintf(stderr, "Samo slova\n");
                continue;
            }
            if (write(pipeToChild[1], input, strlen(input)) != strlen(input))
                fatalError("write error");
            printf("1\n");

            if ((n = read(pipeToParent[0], input, STRING_SIZE)) < 0)
                fatalError("fatal error");
            printf("4\n");

            if (n == 0)
                printf("No\n");
            else if (n > 0)
                printf("Yes\n");

    }

    exit(EXIT_SUCCESS);

}


static void     fatalError(char *message) {
    perror(message);
    exit(EXIT_FAILURE);
}

int     checkIfAlpha(char   *string , int   length) {

    int c = 1;

    for (int i = 0; i < length; i++)
        if (!isalpha(string[i])) {
            c = -1;
            break;
        }

    return c;
}

EDIT: Я бы опубликовал результаты, если бы думал, что они будут настолько значительными, но во что бы то ни стало.

Вот вывод (с правым входом):

./grep 
abcde
1
2
3

Вот GDB:

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe058) at grep.c:23
23  {
(gdb) next
34      if (pipe(pipeToParent) < 0)
(gdb) 
37      if (pipe(pipeToChild) < 0)
(gdb) 
40      if ((pid = fork()) < 0)
(gdb) 
42      else if (pid == 0) {
(gdb) 
76      if (close(pipeToParent[1]) < 0)
(gdb) 
80      if (close(pipeToChild[0]) < 0)
(gdb) 
83      while(fgets(input, STRING_SIZE, stdin) != NULL) {
(gdb) 

85          input[strlen(input)-1] = '\0';
(gdb) 
88              if (checkIfAlpha(input, strlen(input)) == -1) {
(gdb) 
92              if (write(pipeToChild[1], input, strlen(input)) != strlen(input))
(gdb) 
94              printf("1\n");
(gdb) 
1
96              if ((n = read(pipeToParent[0], input, STRING_SIZE)) < 0)
(gdb) 

1 Ответ

0 голосов
/ 17 января 2019

read не записывает завершающий нулевой символ. После if ((count = read(pipeToChild[0], tmp, 50)) < 0) программа передает tmp, не записывая в него нулевую символику, в sprintf.

Это приводит к тому, что команде echo передаются дополнительные данные мусора из tmp сверх того, что было прочитано из канала, что, в свою очередь, заставляет grep не найти подходящую строку.

Одним из исправлений было бы изменить read на read(pipeToChild[0], tmp, sizeof tmp - 1) и вставить tmp[count] = 0;.

...