Popen and EVFILT_WRITE question

Mel fbsd.hackers at rachie.is-a-geek.net
Sun Mar 30 03:36:26 PDT 2008


Hi,

from reading the manpage on EVFILT_WRITE I thought it would be an easy to use 
interface to detect when a program wants input.
So far, that doesn't seem to be the case. Ultimately what I want to do is pipe 
all the popen(3)'d output to a logfile and act on any input it wants.

Could anyone explain to me why I'm never getting the EVFILT_WRITE event in 
below testcode?
(It doesn't matter if I open the pipe with w+ or r+).

test.c:
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sysexits.h>
#include <err.h>
#include <stdio.h>

int main(int argc, char **argv)
{
	FILE *proc;
	int kq;
	struct kevent changes[2], events[2];

	proc = popen("./test.sh", "w+");
	if( -1 == (kq = kqueue()) )
		err(EX_OSERR, "Cannot get a kqueue");

	EV_SET(&changes[0], fileno(proc), EVFILT_WRITE, EV_ADD|EV_ENABLE, 0,
			0, 0);
	EV_SET(&changes[1], fileno(proc), EVFILT_READ, EV_ADD|EV_ENABLE, 0,
			0, 0);

	for( ;; )
	{
		int nev, i;

		if( -1 == (nev = kevent(kq, changes, 2, events, 2, NULL)) )
			err(EX_OSERR, "kevent");

		for( i = 0; i < nev; i++ )
		{
			char *buf;

			if( events[i].filter == EVFILT_READ )
			{
				if( events[i].flags & EV_ERROR )
				{
					warn("Event error");
					goto END;
				}
				if( events[i].flags & EV_EOF )
					goto END;
				buf = malloc(events[i].data);
				(void)fread(buf, sizeof(char), events[i].data, proc);
				(void)fwrite(buf, sizeof(char), events[i].data, stdout);
				free(buf);
			}
			else if( events[i].filter == EVFILT_WRITE )
			{
				if( events[i].flags & EV_ERROR )
				{
					warn("Event error");
					goto END;
				}
				if( events[i].flags & EV_EOF )
					goto END;
				fprintf(proc, "yes\n");
			}
		}
	}

END:
	close(kq);
	pclose(proc);
	return 0;
}

test.sh:
#!/bin/sh

i=0
while(test $i -lt 3); do
	echo sleeping
	sleep 1;
	i=$((i+1));
done

echo "Do you wanna write? "; read ANSWER
echo $ANSWER


-- 
Mel


More information about the freebsd-hackers mailing list