[Ilugc] [TIP] C program to download a file using HTTP#include <stdio.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/socket.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <netdb.h> #define HTTP_GET_

  • From: girishvenkatachalam@xxxxxxxxx (Girish Venkatachalam)
  • Date: Wed, 16 Nov 2011 07:38:30 +0530

Dear boys and girls,

Here we have a cool C program to download from the command line.

It is self contained and does not take care of URL handling and will
fail in some
cases but I bet it will work in nearly all of the cases.

Now the code is here:

$ cat htdl.c
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>

#define HTTP_GET_CMD "GET /%s HTTP 1.1\r\n\r\n"

int
dl(char *url)
{
        int c, ret = -1, fd = -1;
        int bytes, off;
        struct hostent *h;
        struct sockaddr_in s;
        char *p, *p2, host[1024], ip[40], outf[1024];
        char cmd[1024], buf[8192], path[1024];

        c = socket(AF_INET, SOCK_STREAM, 0);
        if(c < 0) {
                perror("socket");
        }

        p = strstr(url, "//");
        p += 2;
        p2 = strchr(p, '/');
        strlcpy(host, p, p2 - p + 1);
        strlcpy(path, p2 + 1, sizeof(path));
        
        printf("Performing DNS Lookup for the host [%s]...\n", host);
        h = gethostbyname(host);
        if(h == NULL) {
                printf("Lookup failed, are you connected to Internet?\n");
                exit(128);
        }
        strlcpy(ip, inet_ntoa(*(struct in_addr *)h->h_addr_list[0]),
           sizeof(ip));
        s.sin_port = htons(80);
        s.sin_family = PF_INET;
        s.sin_addr.s_addr = inet_addr(ip);
        printf("Connecting to %s\n", ip);
        ret = connect(c, (struct sockaddr *)&s, sizeof(s));
        if(ret < 0) {
                perror("connect");
                printf("Could not connect...exiting\n");
                exit(128);
        }
        printf("Connected!\n");

        p = strrchr(p, '/');
        strlcpy(outf, p + 1, sizeof(outf));
        /* Now we are connected, now we can download and write to a file
         * , so let us open the file first
         */
        fd = open(outf, O_WRONLY | O_TRUNC | O_CREAT, 0644);
        if(fd == -1) {
                printf("Could not open downloaded file into current dir,"
                 "check permissions\n");
                perror("open");
                exit(128);
        }
        
        /* Let us send the command to get the file and figure out how
         * the server responds */
        snprintf(cmd, sizeof(cmd), HTTP_GET_CMD, path);
        ret = send(c, cmd, strlen(cmd), 0);
        if(ret < 0) {
                perror("send");
                exit(128);
        }

        printf("Sent command [%s] to get the file using HTTP GET\n", cmd);

        bytes = read(c, buf, sizeof(buf));
        p = strstr(buf, "\r\n\r\n");
        off = (p + 4) - buf;
        write(fd, buf + off, bytes - off);

        while( (bytes = read(c, buf, sizeof(buf))) ) {
                write(fd, buf, bytes);
                printf("Wrote %d bytes to file\n", bytes);
        }
        close(c);
        close(fd);
        printf("Wrote %s to file\n", outf);
        return 0;       

}

int
main(int argc, char **argv)
{
        if(argc < 2) {
                printf("Please give the URL to download!\n");
                exit(128);
        }
        dl(argv[1]);
        return 0;
}


You can look at the code with vim colors:
ftp://tulip.pye.org/htdl.c.html

Or download this from there:
ftp://tulip.pye.org/htdl.c

Once you download it on your Linux box,compile it like this:

$ make htdl

Then it will create an exe by name htdl

$ ./htdl http://ftp.openssl.org/source/openssl-0.9.6.tar.gz

Or you can give any URL that uses HTTP.

It will download the binary file(or even text file) into the current
directory under
 the file name part of the URL(the last part after the final /)

Now do you want me to explain the code?

If you want it I will send a separate mail.

But you have work to do now. Play with it and see how it works.

-Girish

-- 
G3 Tech
Networking appliance company
web: http://g3tech.in ?mail: girish at g3tech.in

Other related posts:

  • » [Ilugc] [TIP] C program to download a file using HTTP#include <stdio.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/socket.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <netdb.h> #define HTTP_GET_ - Girish Venkatachalam