Merge branch 'mob'
[eleutheria.git] / kqueue / kqclient.c
blob2c316495a0a21475c90e87c5fc962742972194eb
1 /* compile with:
2 gcc kqclient.c -o kqclient -Wall -W -Wextra -ansi -pedantic */
4 #include <netinet/in.h>
5 #include <sys/event.h>
6 #include <sys/socket.h>
7 #include <sys/time.h>
8 #include <netdb.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
14 #define BUFSIZE 1024
16 /* function prototypes */
17 void diep(const char *s);
18 int tcpopen(const char *host, int port);
19 void sendbuftosck(int sckfd, const char *buf, int len);
21 int main(int argc, char *argv[])
23 struct kevent chlist[2]; /* events we want to monitor */
24 struct kevent evlist[2]; /* events that were triggered */
25 char buf[BUFSIZE];
26 int sckfd, kq, nev, i;
28 /* check argument count */
29 if (argc != 3) {
30 fprintf(stderr, "usage: %s host port\n", argv[0]);
31 exit(EXIT_FAILURE);
34 /* open a connection to a host:port pair */
35 sckfd = tcpopen(argv[1], atoi(argv[2]));
37 /* create a new kernel event queue */
38 if ((kq = kqueue()) == -1)
39 diep("kqueue()");
41 /* initialise kevent structures */
42 EV_SET(&chlist[0], sckfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
43 EV_SET(&chlist[1], fileno(stdin), EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
45 /* loop forever */
46 for (;;) {
47 nev = kevent(kq, chlist, 2, evlist, 2, NULL);
49 if (nev < 0)
50 diep("kevent()");
52 else if (nev > 0) {
53 if (evlist[0].flags & EV_EOF) /* read direction of socket has shutdown */
54 exit(EXIT_FAILURE);
56 for (i = 0; i < nev; i++) {
57 if (evlist[i].flags & EV_ERROR) { /* report errors */
58 fprintf(stderr, "EV_ERROR: %s\n", strerror(evlist[i].data));
59 exit(EXIT_FAILURE);
62 if (evlist[i].ident == sckfd) { /* we have data from the host */
63 memset(buf, 0, BUFSIZE);
64 if (read(sckfd, buf, BUFSIZE) < 0)
65 diep("read()");
66 fputs(buf, stdout);
69 else if (evlist[i].ident == fileno(stdin)) { /* we have data from stdin */
70 memset(buf, 0, BUFSIZE);
71 fgets(buf, BUFSIZE, stdin);
72 sendbuftosck(sckfd, buf, strlen(buf));
78 close(kq);
79 return EXIT_SUCCESS;
82 void diep(const char *s)
84 perror(s);
85 exit(EXIT_FAILURE);
88 int tcpopen(const char *host, int port)
90 struct sockaddr_in server;
91 struct hostent *hp;
92 int sckfd;
94 if ((hp = gethostbyname(host)) == NULL)
95 diep("gethostbyname()");
97 if ((sckfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
98 diep("socket()");
100 server.sin_family = AF_INET;
101 server.sin_port = htons(port);
102 server.sin_addr = *((struct in_addr *)hp->h_addr);
103 memset(&(server.sin_zero), 0, 8);
105 if (connect(sckfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) < 0)
106 diep("connect()");
108 return sckfd;
111 void sendbuftosck(int sckfd, const char *buf, int len)
113 int bytessent, pos;
115 pos = 0;
116 do {
117 if ((bytessent = send(sckfd, buf + pos, len - pos, 0)) < 0)
118 diep("send()");
119 pos += bytessent;
120 } while (bytessent > 0);