The kqueue interface includes the following two functions and macro:
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
int kqueue(void);
int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout) ;
void EV_SET(struct kevent *kev, uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, void *udata);
The kevent structure is defined by including the <sys/event.h> header.
struct kevent {
uintptr_t ident; /* identifier (e.g., file descriptor) */
short filter; /* filter type (e.g., EVFILT_READ) */
u_short flags; /* action flags (e.g., EV_ADD) */
u_int fflags; /* filter-specific flags */
intptr_t data; /* filter-specific data */
void *udata; /* opaque user data */
};
#include "unp.h"
void str_client(int sockfd)
{
int kq,i,n,nev,stdineof=0, isfile;
char buf[MAXLINE];
struct kevent kev[2];
struct timespec ts;
struct stat st;
isfile=((fstat(fileno(fp),&st)==0)&&(st.st_mode&S_IFMT)==S_IFREG);
EV_SET(&kev[0], fileno(fp),EVFILE_READ, EV_ADD, 0, 0, NULL);
EV_SET(&kev[1], sockfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
kq=Kqueue();
ts.tv_sec=ts.tv_nsec=0;
Kevent(kq, kev, 2, NULL, 0, &ts);
for( ; ;)
{
nev=Kevent(kq, NUll, 0, kev, 2, NULL);
for(i=0;i<nev;i++)
{
if(kev[i].ident==sockfd)
{
if((n=Read(sockfd, buf, MAXLINE))==0)
{
if(stdineof==1)
return;
else
err_quit("str_cli: server terminated prematurely");
}
Write(fileno(stdout), buf, n);
}
if(kev[i].ident==fileno(fp))
{
if(n>0)
Writen(sockfd, buf, n);
if(n==0||(isfile&&n==kev[i].data))
{
stdineof=1;
Shutdown(sockfd, SHUT_WR);
kev[i].flags=EV_DELETE;
Kevent(kq, &kev[i], 1, NULL, 0, &ts);
continue;
}
}
}
}
}
str_cli function using kqueue.