Stream and Pipe in C99

    1. Pipe => pipe[0], pipe[1] 
    2. FILE* stream = fdopen(fd, "x")

    typedef	struct __sFILE {
    ...
    } FILE;

    3. Stream is a struct in c99, it keeps offset pointer, seek pointer position
    4. Stream is like a synchronized queue, consumer and producer
pipe and stream

FILE* in C99 stdio.h


// Wed  9 Aug 10:50:47 2023  
SEE: /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/_stdio.h
SEE: /Users/aaa/myfile/bitbucket/publicfile/c99_stdio.h

typedef	struct __sFILE {
	unsigned char *_p;	/* current position in (some) buffer */
	int	_r;		/* read space left for getc() */
	int	_w;		/* write space left for putc() */
	short	_flags;		/* flags, below; this FILE is free if 0 */
	short	_file;		/* fileno, if Unix descriptor, else -1 */
	struct	__sbuf _bf;	/* the buffer (at least 1 byte, if !NULL) */
	int	_lbfsize;	/* 0 or -_bf._size, for inline putc */

	/* operations */
	void	*_cookie;	/* cookie passed to io functions */
	int	(* _Nullable _close)(void *);
	int	(* _Nullable _read) (void *, char *, int);
	fpos_t	(* _Nullable _seek) (void *, fpos_t, int);
	int	(* _Nullable _write)(void *, const char *, int);

	/* separate buffer for long sequences of ungetc() */
	struct	__sbuf _ub;	/* ungetc buffer */
	struct __sFILEX *_extra; /* additions to FILE to not break ABI */
	int	_ur;		/* saved _r when _r is counting ungetc data */

	/* tricks to meet minimum requirements even when malloc() fails */
	unsigned char _ubuf[3];	/* guarantee an ungetc() buffer */
	unsigned char _nbuf[1];	/* guarantee a getc() buffer */

	/* separate buffer for fgetln() when line crosses buffer boundary */
	struct	__sbuf _lb;	/* buffer for fgetln() */

	/* Unix stdio files get aligned to block boundaries on fseek() */
	int	_blksize;	/* stat.st_blksize (may be != _bf._size) */
	fpos_t	_offset;	/* current lseek offset (see WARNING) */
} FILE;

Create pipe in C

// $b/c99/pipe_sleep.c
// gcc myfile.c -o main
// cpp_compile.sh pipe_sleep.c
//
//                          +-> FILE* stream
//                          |
// Pipe associates with a stream which can be read or written
//                          |
//                          +-> like a buffer
// int mypipe[2];
// pipe(mypipe)
//
//         mypipe[1]           mypipe[0]
//             |                    |
//             v                    v
// write -> stdout [    ] -> read stdin 
//             |                    |
//             v                    v
//         mypipe[1]           mypipe[0]
//             |                    |
//             v                    v
//     write to stream       read from stream
//                |                       |
//                v                       v
//           like a buffer          like a buffer
  
#include 
#include 
#include 
#include 
#include 

// Read char from a pipe
void read_from_pipe(int file){
    FILE *stream;
    int c;
    stream = fdopen(file, "r");
    while((c = fgetc(stream)) != EOF){
        putchar(c);
    }
    fclose(stream);
}

void write_to_pipe(int file){
    FILE *stream;
    int c;
    stream = fdopen(file, "w");
    fprintf(stream, "Hello World\n");
    fprintf(stream, "Good Byte\n");
    fclose(stream);
}


int main () {
    pid_t pid;
    int mypipe[2];
    if(pipe(mypipe)){
        fprintf(stderr, "Pipe failed.\n");
        return EXIT_FAILURE;
    }

    pid = fork();
    if(pid == (pid_t) 0){
        // Child process
        // close the write end 
        close(mypipe[1]);
        read_from_pipe(mypipe[0]);
        return EXIT_SUCCESS;
    }else if(pid < (pid_t)0){
        // fork() failed
        fprintf(stderr, "fork() failed\n");
    }else{
        // This is parent process
        close(mypipe[0]);
        write_to_pipe(mypipe[1]);
        return EXIT_SUCCESS;
    }

   return(0);
}