Coherent4.2.10/conf/echo/src/polltest.c

Compare this file to the similar file:
Show the results in this format:

/*
 * Test out STREAMS polling; open several streams and pipes, then fork. The
 * child will write to a random channel, the parent has to pick it up.
 */

#include <common/tricks.h>
#include <sys/compat.h>
#include <stdio.h>
#include <unistd.h>
#include <poll.h>
#include <fcntl.h>
#include <stdarg.h>
#include <time.h>
#include <signal.h>

/*
 * The server will wait a second.
 */

#define	TEST_SERVER	1000


/*
 * Here we record all the file descriptors.
 */

#define	TEST_MAX	20

struct pollfd	fds [TEST_MAX];
int		max_fd;


/*
 * Add a file descriptor.
 */

#if	USE_PROTO
int add_fd (int fd)
#else
int
add_fd (fd)
int		fd;
#endif
{
	if (max_fd >= ARRAY_LENGTH (fds)) {
		printf ("add_fd: trying to set up too many files.\n");
		return -1;
	}

	fds [max_fd].events = POLLIN;
	fds [max_fd ++].fd = fd;
	return 0;
}


/*
 * Create an echo stream.
 */

#if	USE_PROTO
int create_echo (void)
#else
int
create_echo ()
#endif
{
	int		fd;

	if ((fd = open ("/dev/echo", O_RDWR)) == -1) {

		perror ("Couldn't open /dev/echo");
		return -1;
	}

	return add_fd (fd);
}


/*
 * Create a pipe pair.
 */

#if	USE_PROTO
int create_pipe (void)
#else
int
create_pipe ()
#endif
{
	int		pipes [2];

	if (pipe (pipes) < 0) {
		perror ("could not create pipes");
		return -1;
	}

	return add_fd (pipes [0]) >= 0 && add_fd (pipes [1]) >= 0 ? 0 : -1;
}


/*
 * Statically set up the I/O buffers for the client and server; since each
 * will get a separate copy, this saves some stuffing around.
 */

char		control_information [256];
char		data_information [256];

#if	0
struct strbuf	ctlbuf = {
	sizeof (control_information), 0, control_information
};
struct strbuf	databuf = {
	sizeof (data_information), 0, data_information
};
#endif


/*
 * Client/server output routine.
 */

#if	USE_PROTO
void report (CONST char * fmt, ...)
#else
void
report (fmt)
CONST char    *	fmt;
#endif
{
	va_list		args;
	struct tm     *	tm;
	time_t		now;

	(void) time (& now);
	tm = localtime (& now);

	va_start (args, fmt);
	(void) fprintf (stderr, "%5d %02d:%02d:%02d: ", getpid (),
			tm->tm_hour, tm->tm_min, tm->tm_sec);
	(void) vfprintf (stderr, fmt, args);
	va_end (args);
}


/*
 * Server half: input sink.
 */

#if	USE_PROTO
void run_server (void)
#else
void
run_server ()
#endif
{
	for (;;) {
		int		i;

		report ("server: waiting\n");

		if ((i = poll (fds, max_fd, TEST_SERVER)) == 0) {
			report ("server: no events\n");
			continue;
		}

		report ("server: got %d events\n", i);

		for (i = 0 ; i < max_fd ; i ++) {
			int		flags;
			int		retval;

			if (fds [i].revents == 0)
				continue;
			report ("server: event on channel %d\n", i);

			/*
			 * Flush the data. For now, pipes are filesystem
			 * objects so we must use read ().
			 */

			fcntl (fds [i].fd, F_SETFL,
			       fcntl (fds [i].fd, F_GETFL) | O_NONBLOCK);

			while (read (fds [i].fd, data_information,
				     sizeof (data_information)) != -1)
				/* DO NOTHING */ ;

			fcntl (fds [i].fd, F_SETFL,
			       fcntl (fds [i].fd, F_GETFL) & ~ O_NONBLOCK);
		}
	}
}


/*
 * Signal-catching function for the client; we use this as a backup to ensure
 * that poll () really is waiting for the right amount of time.
 */

#if	USE_PROTO
void catch_alarm (int sig)
#else
void
catch_alarm (sig)
int		sig;
#endif
{
	signal (SIGALRM, catch_alarm);
	report ("Caught alarm signal!\n");
}


/*
 * Client half: periodically generate output.
 */

#if	USE_PROTO
void run_client (void)
#else
void
run_client ()
#endif
{
	signal (SIGALRM, catch_alarm);

	for (;;) {
		int		i;
		int		written;

		/*
		 * Delay a random amount, between 0.5 and 1.5 seconds.
		 */

		alarm (2);
		i = rand () % 1000 + 500;
		report ("client: waiting %d msec\n", i);

		if (poll (fds, 0, i) != 0)
			continue;

		/*
		 * Generate some output, and send it someplace.
		 */

		i = rand () % max_fd;
		report ("client: writing to channel %d\n", i);

		strcpy (data_information, ctime ());
		written = write (fds [i].fd, data_information,
				 strlen (data_information));

		if (written < 0)
			report ("client: error writing to channel %d\n", i);
	}
}


/*
 * Main program; create a channels and fork into client and server.
 */

#if	USE_PROTO
int main (int argc, char * argv [])
#else
int
main (argc, argv)
int		argc;
char	      *	argv [];
#endif
{
	int		i;

	srand (clock ());

	create_echo ();
	create_echo ();
	while (max_fd < TEST_MAX - 1)
		create_pipe ();

	if (fork ())
		run_server ();
	else
		run_client ();

	return 0;
}