/*
* A Simple HTTP client with C
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <netdb.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/socket.h>
#include <unistd.h>
#ifndef PF_INET
#define PF_INET AF_INET
#endif
static void err (char *msgformat, ...)
{
char msgbuf [4096];
va_list argv;
int len;
va_start (argv, msgformat);
len = vsprintf (msgbuf, msgformat, argv);
va_end (argv);
msgbuf[len] = 0;
fprintf (stderr, msgbuf);
fprintf (stderr, "\n");
exit (-1);
}
static int connect_server (char *host, int port)
{
struct hostent *hp;
struct sockaddr_in remote;
int sock;
sock = socket (PF_INET, SOCK_STREAM, 0);
if (sock == -1) {
err ("Cannot open a new socket [%d]: %s",
errno, strerror (errno));
}
hp = gethostbyname (host);
if (hp == NULL) {
err ("Cannot resolve hostname %s [%d]: %s",
host, errno, strerror (errno));
}
memset (&remote, 0, sizeof (struct sockaddr_in));
remote.sin_family = AF_INET;
remote.sin_port = htons (port);
remote.sin_addr = *((struct in_addr *) hp->h_addr);
if (connect (sock,
(struct sockaddr *) &remote,
sizeof (struct sockaddr)) == -1) {
err ("Cannot connect to %s [%d]: %s",
host, errno, strerror (errno));
}
return sock;
}
static void send_request (int sock)
{
int bytes;
#define REQUEST "GET / HTTP/1.0\r\n\r\n"
bytes = send (sock, REQUEST, sizeof REQUEST, 0);
if (bytes != sizeof REQUEST) {
err ("Couldn't send HTTP Request");
}
}
/*
* Doesn't handle HTTP header seperation
*/
static void read_result (int sock, char **data)
{
char *page = NULL;
char buf[4096];
int size = 0;
int bytes;
do {
memset (buf, 0, sizeof buf);
bytes = recv (sock, buf, sizeof buf, 0);
if (bytes == -1) {
err ("Cannot recieve data [%d]: %s",
errno, strerror (errno));
}
if (bytes == 0) {
break;
}
page = realloc (page, size + bytes);
if (page == NULL) {
err ("Cannot allocate %d bytes", size + bytes);
}
memcpy (page + size, buf, bytes);
size += bytes;
} while (1);
*data = page;
}
static void close_connection (int sock)
{
close (sock);
}
static char *perform_http_request (char *host, int port)
{
char *data;
int sock;
sock = connect_server (host, port);
send_request (sock);
read_result (sock, &data);
close_connection (sock);
return data;
}
int main (int argc, char **argv)
{
char *host;
char *data;
int port = 80;
switch (argc) {
case 3:
port = atoi (argv[2]);
case 2:
host = strdup (argv[1]);
break;
default:
err ("Wrong argument count: "
"You must specify a hostname");
break;
}
data = perform_http_request (host, port);
puts (data);
free (data);
free (host);
return 1;
}