HTTP 1

引数に指定したURLの情報とソースを表示するプログラム.
適切なエラー処理がところどころしていませんので, 引数を指定する際は注意してください.

 /* http.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 80

int main(int argc, char **argv)
{
    int sock;
    int http_val  = 0;
    int https_val = 0;

    socklen_t len = 0;
    ssize_t byte;

    char *tmp;
    char *ch;

    char send_buff[256];
    char buff[512];

    struct hostent *host_name;
    struct servent *service;
    struct sockaddr_in addr;

    if(argc != 2) {
        fprintf(stderr, "Usage: %s [URL]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    tmp = (char *)malloc(sizeof(char) * 256);

    http_val  = strcmp(argv[1], "http://");
    https_val = strcmp(argv[1], "https://");

    if(http_val > https_val) {
        sscanf(argv[1], "http://%s", tmp);
    }
    else if(https_val > http_val) {
        sscanf(argv[1], "https://%s", tmp);
    }
    else if(https_val && https_val)
        strcpy(tmp, argv[1]);

    if((ch = strchr(tmp, '/')) != NULL) {
        *ch = '\0';
    }

    printf("tmp = %s\n", tmp);

    if((host_name = gethostbyname(tmp)) == NULL) {
        perror("gethostbyname(3)");
        exit(EXIT_FAILURE);
    }

    printf("h_name     = %s\n", host_name->h_name);
    printf("h_addrtype = %d\n", host_name->h_addrtype);
    printf("h_length   = %d\n", host_name->h_length);

    if((service = getservbyname("http", "tcp")) == NULL) {
        perror("getservbyname(3)");
        exit(EXIT_FAILURE);
    }

    printf("s_name  = %s\n", service->s_name);
    printf("s_port  = %d\n", service->s_port);
    printf("s_proto = %s\n", service->s_proto);

    bcopy(host_name->h_addr, &addr.sin_addr, host_name->h_length);

    addr.sin_family = AF_INET;
    addr.sin_port = service->s_port;

    if((sock = socket(AF_INET, SOCK_STREAM, 0)) == EOF) {
        perror("socket(2)");
        exit(EXIT_FAILURE);
    }

    len = sizeof(addr);

    if(connect(sock, (struct sockaddr *)&addr, len) == EOF) {
        perror("connect(2)");
        exit(EXIT_FAILURE);
    }

    sprintf(send_buff, "GET: %s HTTP/1.0\r\n", tmp);
    printf("send_buff = %s", send_buff);
    write(sock, send_buff, strlen(send_buff));

    sprintf(send_buff, "HOST: %s:%d\r\n", tmp, PORT);
    printf("send_buff = %s", send_buff);
    write(sock, send_buff, strlen(send_buff));

    sprintf(send_buff, "Reference: %s\r\n", argv[1]);
    printf("send_buff = %s\n", send_buff);
    write(sock, send_buff, strlen(send_buff));

    sprintf(send_buff, "\r\n");
    write(sock, send_buff, strlen(send_buff));

    printf("\n ~~~ Get Message %s Server ~~~ \n\n", tmp);

    free(tmp);

    while(1) {
        if((byte = read(sock, buff, 512)) == EOF) {
            perror("read(2)");
            exit(EXIT_FAILURE);
        }
        if(byte == 0)
            break;
        if(write(1, buff, byte) == EOF)  {
            perror("write(2)");
            exit(EXIT_FAILURE);
        }
    }

    close(sock);

    return 0;
}

実行例:

$ ./http https://www.google.co.jp
tmp = google.co.jp
h_name = google.co.jp
h_addrtype = 2
h_length = 4
s_name = http
s_port = 20480
s_proto = tcp
send_buff = GET: google.co.jp HTTP/1.0
send_buff = HOST: google.co.jp:80
send_buff = Reference: https://google.co.jp/index.html


~~~ Get Message google.co.jp Server ~~~

HTTP/1.0 405 Method Not Allowed
Content-Type: text/html; charset=UTF-8
Content-Length: 959
Date: Fri, 15 Mar 2013 05:45:50 GMT
Server: GFE/2.0

<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 405 (Method Not Allowed)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}
</style>
<a href=//www.google.com/><img src=//www.google.com/images/errors/logo_sm.gif alt=Google></a>
<p><b>405.</b> <ins>That’s an error.</ins>
<p>The request method <code>GET:</code> is inappropriate for the URL <code>/</code>. <ins>That’s all we know.</ins>