#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <sys/stat.h>#include <sys/types.h>/*A lot of excess headers because I'm supposed to add more functions, but that's for later*/int main(void){ char buffer[128]; int fifofd; char fifoname[] = "chatfifo"; int ret; ret = mkfifo(fifoname, S_IRUSR | S_IWUSR); if(ret<0){ printf("'chatfifo' already exists.\nThis is the FIFO reader.\n"); fifofd = open(fifoname, O_RDONLY | O_NONBLOCK); do { read(fifofd, buffer, sizeof(buffer)); printf("Message retrieved> %s", buffer); } while (strcmp(buffer,"exit\n")!=0); close(fifofd); unlink(fifoname); } else{ printf("'chatfifo' created.\nThis is the FIFO writer.\n"); fifofd = open(fifoname, O_WRONLY | O_NONBLOCK); printf("Type in 'exit' to quit:\n"); do { printf("Enter message to send> "); fgets(buffer, sizeof(buffer), stdin); write(fifofd, buffer, strlen(buffer)+1 ); } while (strcmp(buffer,"exit\n")!=0); close(fifofd); } return 0;}
q3k@luna ~ $ ./pwn'chatfifo' created.This is the FIFO writer.Type in 'exit' to quit:Enter message to send> ffdsEnter message to send> I like turtles.Enter message to send>
q3k@luna ~ $ ./pwn'chatfifo' already exists.This is the FIFO reader.Message retrieved> ffdsMessage retrieved> I like turtles.
I disabled both O_NONBLOCKs and for some reason the program just stops at open(). The printf() that followed it didn't come out. D:
Another option, if you want to keep the asynchronous (=non-blocking) reading on the reader, you can refrain from printing data to the client unless read() returns > 0, which would mean some bytes were actually read, This way, the reader can still run on a loop, and do some other processing in the meantime (printing the time, blinking a cursor, whatever). However, this can be more CPU intensive, as a infinite loop like this (=a polled loop) is very CPU intensive.A good compromise between the two (something asynchronous, but not so CPU intensive) is to use the select() syscall (or some OS equivalent, kpoll on Linux, something on Windows I forgot - they are usually even fatser than select(), which is standarized). This syscall allows you to specify a bunch of file descriptors (be it open files, fifos, or even network sockets), and will block until one or more of these descriptors can be read from or written to. Here's the fun part: you can also specify for how long it will block! This allows you to write code that will block, for example, for 0.1 seconds (waiting for the fifo to have somedata), and then return. If it returned the file descriptor, it means some data was available on it - then you can read() it. If it returns 0, it means the block time has expired, and no data was read from the fifo. After you either handle or not the descriptor, you can do whatever more processing you want, and then loop back to the select() call.Of course, all of this is unnecessary if you can live with having a blocked loop :P.
I'm compiling through BBS, and my university's computers are running CentOS 5 (HAHAHAHA SO OLD).
[root@parallelogram ~]# uname -aLinux parallelogram.global7hosting.com 2.6.18-238.19.1.el5 #1 SMP Fri Jul 15 07:31:24 EDT 2011 x86_64 x86_64 x86_64 GNU/Linux[root@parallelogram ~]# cat /etc/issue | head - n 1CentOS release 5.6 (Final)