在父进程和子进程之间发送Receive Char *

时间:2015-10-20 03:12:36

标签: c pipe fork

我试图获取父进程中的字符串并将其传递给子进程,然后发送回一个字符串,根据passTest()方法声明其强度。它似乎正确地将字符串发送给子进程,但然后它表示在完成对子进程中接收的字符串的评估之前它在父进程上的读取条件失败。父母应该等孩子写,因为这不应该吗?

len = read(fd[P1_READ], val, tend);

非常感谢任何帮助

#include <stdio.h>
#include <stdlib.h>    
#include <unistd.h>
#include <string.h>

//  Parent: reads from P1_READ, writes on P1_WRITE
//  Child:  reads from P2_READ, writes on P2_WRITE
#define P1_READ     0
#define P2_WRITE    1
#define P2_READ     2
#define P1_WRITE    3
#define NUM_PIPES   2
#define false       0 //Used for testing password strength

//Prototypes for other functions
char * passTest(char * password);
char * getPass(char * password);


int main(int argc, char *argv[])
{
    int fd[2*NUM_PIPES];
    int len, i;
    char * val = malloc(100);
    pid_t pid;
    int tend;

    // create all the descriptor pairs we need
    for (i=0; i<NUM_PIPES; ++i)
    {
        if (pipe(fd+(i*2)) < 0)
        {
            perror("Piping Failed");
            exit(EXIT_FAILURE);
        }
    }
    //FORK ERROR
    if ((pid = fork()) < 0)
    {
       perror("Fork Error");
        return EXIT_FAILURE;
    }

    //child process
    if (pid == 0)
    {
        // Child. CLOSE UNNEEDED FD
        close(fd[P1_READ]);
        close(fd[P1_WRITE]);

        // used for output
        pid = getpid();

        // wait until parent sends a value
        len = read(fd[P2_READ], val, tend);
        if (len < 0)
        {
            perror("Child: Failed to read data from pipe\n");
            exit(EXIT_FAILURE);
        }
        else if (len == 0)//In case nothing in pipe
        {
            fprintf(stderr, "Child: Read EOF from pipe\n");
        }
        else
        {
            // report what was recieved
            printf("Child(%d): Received >%s<\n", pid, val);
            val = passTest(val); //CHECK PASSWORD
            tend = strlen(val);
            printf("Child(%d): Sending >%s< back\n", pid, val);
            if (write(fd[P2_WRITE], val, tend) < 0)
            {
                perror("Child: Failed to write response value");
                exit(EXIT_FAILURE);
            }
        }
        // finished. close remaining descriptors.
        close(fd[P2_READ]);
        close(fd[P2_WRITE]);

        return EXIT_SUCCESS;
        //END CHILD PROCESS
    }else{
    //PARENT PROCESS
    // Close unused FD
        close(fd[P2_READ]);
        close(fd[P2_WRITE]);

    // used for output
        pid = getpid();

    // send password to child
        val = getPass(val);
        strtok(val, "\n"); 
        tend = strlen(val);
        printf("Parent(%d): Sending %s to child\n", pid, val);
        if (write(fd[P1_WRITE], val, tend) != tend)
        {
        perror("Parent: Failed to send value to child ");
        exit(EXIT_FAILURE);
    }

// now wait for a response
    len = read(fd[P1_READ], val, tend);
    if (len < 0)
    {
        perror("Parent: failed to read value from pipe\n");
        exit(EXIT_FAILURE);
    }
    else if (len == 0)
    {
    // not an error, but certainly unexpected
        fprintf(stderr, "Parent(%d): Read EOF from pipe\n", pid);
    }
    else
    {
    // report what we received
        printf("Parent(%d): Received %s\n", pid, val);
    }

// close descriptors
    close(fd[P1_READ]);
    close(fd[P1_WRITE]);

// wait for child termination
    wait(NULL);
    return EXIT_SUCCESS;
}
}//END MAIN


char * getPass(char * password){
    printf("Please enter the password: ");
    fgets(password, 50, stdin);
    return password;
}

char * passTest(char * password){
    printf("INSIDE passTest %s\n",password);
    char * passStrength = "";
    int   i=0;
    int  found_lower = false, found_upper = false, found_number =false;

    while(password[i] != '\0' || !(found_lower && found_upper&&        found_number)) {
        found_lower = found_lower || (password[i] >= 'a' && password[i] <= 'z');
        found_upper = found_upper || (password[i] >= 'A' && password[i] <= 'Z');
        found_number = found_number ||(password[i] >= '0' && password[i] <= '9');
        i++;
    }
    if(found_lower && found_upper&& found_number){
        strcpy(passStrength, "strong");
    }else{
        strcpy(passStrength, "weak");
    }
    if(strlen(password)<8){
        strcpy(passStrength, "short");
    }
    printf("passStrength >%s<\n",passStrength);
    return passStrength;
}

1 个答案:

答案 0 :(得分:2)

我注意到的问题:

问题1

变量tend未初始化。

我会改变

int tend;

int tend = 100; // Or anything else that makes sense in your application.

问题2

你有

char * passStrength = "";

然后继续使用

strcpy(passStrength, "strong");

肯定会导致未定义的行为。确保passStrength中有足够的内存来保存要分配给它的值。

然后你使用:

return passStrength;

仅当passStrength使用的内存超出函数调用时才会有效。你必须使用:

static char passStrength[100];  // Make it large enough.

char * passStrength = malloc(100);

问题3

在对write的所有调用中,您发送的字符串没有终止空字符,例如:

  tend = strlen(val);
  printf("Parent(%d): Sending %s to child\n", pid, val);
  if (write(fd[P1_WRITE], val, tend) != tend)

当您读取管道另一端的数据时,字符串将以空值终止。使用这些字符串就像它们是空终止字符串一样导致未定义的行为。您可以通过以下方式解决此问题:

  1. 再发一个字符。

    if (write(fd[P1_WRITE], val, tend+1) != tend+1)
    

  2. 读取数据后添加空字符。

    len = read(fd[P1_READ], val, tend);
    val[len] = '\0';
    
  3. 问题4

    while语句passTest未设置正确。因此,该函数访问超出有效范围的内存。这会导致未定义的行为。

    将其更改为:

    while( password[i] != '\0' && ( false == found_lower ||
                                    false == found_upper ||
                                    false == found_number ) ) {
    

    我发现以下内容更容易理解:

    while( password[i] != '\0' ) {
       if ( found_lower && found_upper && found_number ) {
          break;
       }
       found_lower = found_lower || (password[i] >= 'a' && password[i] <= 'z');
       found_upper = found_upper || (password[i] >= 'A' && password[i] <= 'Z');
       found_number = found_number ||(password[i] >= '0' && password[i] <= '9');
       i++;
    }