Dummy commit to test new ssh key
[eleutheria.git] / kqueue / kqclient.c
blobb2c6b5b796fb068aa7b21803c904f216de4896da
1 /*
2 * Compile with:
3 * gcc kqclient.c -o kqclient -Wall -W -Wextra -ansi -pedantic
5 * We will implement a raw tcp client using the kqueue framework.
6 * Whenever the host sends data to the socket, we will print them
7 * in the standard output stream. Similarly, when the user types
8 * something in the standard input stream, we will send it to the
9 * host through the socket.
10 * Basically, we need to monitor the following:
12 * 1. any incoming host data in the socket
13 * 2. any user data in the standard input stream
16 #include <netinet/in.h>
17 #include <sys/event.h>
18 #include <sys/socket.h>
19 #include <sys/time.h>
20 #include <netdb.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
26 #define BUFSIZE 1024
28 /* Function prototypes */
29 void diep(const char *s);
30 int tcpopen(const char *host, int port);
31 void sendbuftosck(int sckfd, const char *buf, int len);
33 int main(int argc, char *argv[])
35 struct kevent chlist[2]; /* events we want to monitor */
36 struct kevent evlist[2]; /* events that were triggered */
37 char buf[BUFSIZE];
38 int sckfd, kq, nev, i;
40 /* Check argument count */
41 if (argc != 3) {
42 fprintf(stderr, "Usage: %s host port\n", argv[0]);
43 exit(EXIT_FAILURE);
46 /* Open a connection to a host:port pair */
47 sckfd = tcpopen(argv[1], atoi(argv[2]));
49 /* Create a new kernel event queue */
50 if ((kq = kqueue()) == -1)
51 diep("kqueue()");
53 /* Initialise kevent structures */
54 EV_SET(&chlist[0], sckfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
55 EV_SET(&chlist[1], fileno(stdin), EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
57 /* Loop forever */
58 for (;;) {
59 nev = kevent(kq, chlist, 2, evlist, 2, NULL);
61 if (nev < 0)
62 diep("kevent()");
64 else if (nev > 0) {
65 if (evlist[0].flags & EV_EOF)
66 /* Read direction of socket has shutdown */
67 exit(EXIT_FAILURE);
69 for (i = 0; i < nev; i++) {
70 if (evlist[i].flags & EV_ERROR) {
71 /* Report errors */
72 fprintf(stderr, "EV_ERROR: %s\n", strerror(evlist[i].data));
73 exit(EXIT_FAILURE);
76 if (evlist[i].ident == sckfd) {
77 /* We have data from the host */
78 memset(buf, 0, BUFSIZE);
79 if (read(sckfd, buf, BUFSIZE) < 0)
80 diep("read()");
81 fputs(buf, stdout);
84 else if (evlist[i].ident == fileno(stdin)) {
85 /* We have data from stdin */
86 memset(buf, 0, BUFSIZE);
87 fgets(buf, BUFSIZE, stdin);
88 sendbuftosck(sckfd, buf, strlen(buf));
94 /* Close kqueue */
95 if (close(kq) == -1)
96 diep("close()");
98 return EXIT_SUCCESS;
101 void diep(const char *s)
103 perror(s);
104 exit(EXIT_FAILURE);
107 int tcpopen(const char *host, int port)
109 struct sockaddr_in server;
110 struct hostent *hp;
111 int sckfd;
113 if ((hp = gethostbyname(host)) == NULL)
114 diep("gethostbyname()");
116 if ((sckfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
117 diep("socket()");
119 server.sin_family = AF_INET;
120 server.sin_port = htons(port);
121 server.sin_addr = *((struct in_addr *)hp->h_addr);
122 memset(&(server.sin_zero), 0, 8);
124 if (connect(sckfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) < 0)
125 diep("connect()");
127 return sckfd;
130 void sendbuftosck(int sckfd, const char *buf, int len)
132 int bytessent, pos;
134 pos = 0;
135 do {
136 if ((bytessent = send(sckfd, buf + pos, len - pos, 0)) < 0)
137 diep("send()");
138 pos += bytessent;
139 } while (bytessent > 0);