Question

I ultimately want a solution to this problem but in true one-step-forward-two-steps-back fashion which is programming, I have been reduced to figuring out why I can't even write a character to a named pipe then get that very same character back. Here is a simple MWE script I have, and the accompanying output I am, regretfully, getting:

MWE:

#include <stdio.h>
#include <fcntl.h>
#define PIPE_PATH "testpipe"

int main( int argc, char *argv[] ) {
   int fd;
   FILE *fp;
   char c;
   int result;
   int contingency;

   //Initialize it for debugging purposes
   c = 0;
   contingency = 0;

   if ( atoi ( argv [ 1 ] ) == 1 )
   {
      printf ("Writer [%s]\n", argv[1]);

      mkfifo ( PIPE_PATH, 0666 );

      fd = open ( PIPE_PATH, O_WRONLY );
      c = getchar();
      printf ( "[%d] [%s]\n", c, &c );

      if ( ( result = write ( fd, &c, 1 ) ) == -1)
      {
         fprintf ( stderr, "error writing to pipe\n" );
         return -1;
      }

      close(fd);
   }
   else if ( atoi ( argv [ 1 ] ) == 2 )
   {
      printf ( "Reader [%s]\n", argv[1] );

      fp = fopen( PIPE_PATH, "r" );
      while ( contingency < 3 && ( c = getc ( fp ) ) != EOF )
      { //contingency set to 3 to avoid infinite loop
         c = getc ( fp );
         putchar ( c );
         printf ( "[%d]\n", c ); //don't print c as a string or the shell will go nuts

         printf ( "\n" );
         contingency++;
      }
      fclose ( fp );

      unlink( PIPE_PATH );
   }

   return 0;
}

Output:

Writer [1]
q
[113] [q]
....
Reader [2]
�[255]
�[255]
�[255]

For some reason I am getting a question symbol stuck in hexagon, but which in vim looks like a y (gamma?) with an umlat over it. Since the ASCII code associated with this character is 255, I am assuming that the pipe is not working as expected and returning the highest value possible. Could somebody please tell me what is going on as I have literally spent the last 6 hours of my life accomplishing nothing?

Was it helpful?

Solution

First error

A big problem here...

char c = getc(fp);

See that? That's a big problem. Why? Let's look at the definition of getc()...

int getc(FILE *stream);

Yes, it returns int not char, and that is Important with a capital I and a bold font. The getc() function (or macro) signals EOF with the EOF, which is usually -1, and therefore becomes 0xff when stored in a char.

Always use int with getc().

int c = getc(fp);
if (c == EOF) {
    ...
}

Second error

Well, why are we getting EOF? Because getc() is called twice instead of once...

while ((c = getc(fp)) != EOF) {
    c = getc(fp); // <-- should not be there
    ...
}

Third error

This code is also wrong:

char c = ...;
printf("[%d] [%s]\n", c, &c);

Yes, &c has type char * but that does not mean you can print it out with %s. The %s specifier is strictly for NUL-terminated strings. Either use %c, or continue using %s and NUL-terminate the string you pass it.

char c = ...;
printf("[%d] [%c]\n", c, c);

Or...

char c = ...;
printf("[%d] [%s]\n", c, (char[]){c, '\0'});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top