/* webget	ehg@research.bell-labs.com   6 May 1998 */
/* Unix:	cc -o webget webget.c */
/* Windows:	cl -DWIN32 webget.c wsock32.lib */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#ifdef WIN32
#include <winsock.h>
#define Recv(a,b,c) recv(a,b,c,0)
#define Send(a,b,c) send(a,b,c,0)
#define INDEX_HTML "index.htm"

#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <netinet/tcp.h>
u_long inet_addr(char*);
typedef int SOCKET;
#define Recv(a,b,c) read(a,b,c)
#define Send(a,b,c) write(a,b,c)
#define INDEX_HTML "index.html"
#endif

#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif

void Error(char*);
int active_socklib;

void
begin_socklib(void)
{
#ifdef WIN32
	WSADATA w;
	if(WSAStartup(MAKEWORD(2,2),&w))
		Error("couldn't start WinSock");
#endif
	active_socklib = 1;
}

void
end_socklib(void)
{
#ifdef WIN32
	if(active_socklib)
		WSACleanup();
#endif
}

SOCKET
connectTCP(char *host, char *service)
{
	struct hostent *phe;
	struct servent *pse;
	struct sockaddr_in sin;
	SOCKET s;

	memset((void*)&sin,0,sizeof(sin));
	sin.sin_family = AF_INET;
	if( pse = getservbyname(service,"tcp") )
		sin.sin_port = pse->s_port;
	else if( (sin.sin_port = htons((u_short)atoi(service)))==0 )
		Error("unknown service");
	if( phe = gethostbyname(host) )
		memcpy((void*)&sin.sin_addr,(void*)phe->h_addr,phe->h_length);
	else if( (sin.sin_addr.s_addr = inet_addr(host))==INADDR_NONE )
		Error("unknown host");
	if( (s = socket(PF_INET,SOCK_STREAM,0))<0 )
		Error("can't create socket");
	if(connect(s,(struct sockaddr*)&sin,sizeof(sin))<0)
		Error("can't connect");
	return(s);
}

void
main(int argc, char **argv)
{
	char *host, *file, *basename, buf[4096];
	int c, n, local;
	SOCKET s;
	int hdr = 1;	/* in HTTP header */
	int sol = 1;	/* at start of header line */

	if( (argc!=2 && argc!=3) || strncmp(argv[1],"http://",7)!=0)
		Error("usage: webget http://www.foo.com/bar.gz [localname]");
	host = argv[1]+7;
	file = strchr(host,'/');
	if(!file)
		Error("missing / after hostname");
	if(file-host>500)
		Error("hostname implausibly long");
	if(argc == 3){
		basename = argv[2];
	}else{
		basename = strrchr(file,'/')+1;
		if(basename[0]==0)
			basename = INDEX_HTML;
	}
	if((local = open(basename,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666))<0)
		Error("can't open local file for writing");
	begin_socklib();

	sprintf(buf,"%.*s",file-host,host);
	s = connectTCP(buf,"80");
	n = sprintf(buf,"GET %s HTTP/1.0\n\n",file);
	n = strlen(buf);  /* needed on SunOS 4.1.3 */
	if(n!=Send(s,buf,n))
		Error("write error on socket");

	while(Recv(s,buf,1)==1){
		if((c = buf[0])=='\n'){
			if(sol)
				break;  /* last byte of header */
			sol = 1;
		}else if(c!='\r'){
			sol = 0;
		}
	}
	while((n = Recv(s,buf,sizeof(buf)))>0)
		write(local,buf,n);

	end_socklib();
	exit(0);
}

void
Error(char *mess)
{
	fprintf(stderr,"%s\n",mess);
	end_socklib();
	exit(1);
}