164 lines
3.2 KiB
C
164 lines
3.2 KiB
C
#include "headers.h"
|
|
|
|
|
|
enum
|
|
{
|
|
/* display a status bar */
|
|
B,
|
|
/* put the file somewhere other than the current directory */
|
|
O,
|
|
/* silence all output -- the default */
|
|
/* note that if -q is passed explicitly, it will irrevocably override -v and -b */
|
|
Q,
|
|
/* increase the verbosity level. higher levels imply you want the content lower levels would provide */
|
|
/* all verbose output is sent to stderr for ease of capture */
|
|
/* 0: no informational, statistical or debug output */
|
|
/* 1: informational output (Sending request FOO to host BAR, Received response header BAZ, etc) */
|
|
/* 2: statistical. informational+size of header and body in bytes, round-trip time, etc */
|
|
/* 3+: debug. statistical+all internal state changes */
|
|
V
|
|
};
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int i, sockd, recvlen, recv_header;
|
|
char recvbuf[BUFSIZ] = {0};
|
|
char param[4] = {0};
|
|
char *outpath, *sendbufp, *offsetp;
|
|
FILE *filed;
|
|
uri uristruct;
|
|
|
|
outpath = sendbufp = offsetp = 0;
|
|
i = sockd = recvlen = recv_header = 0;
|
|
filed = 0;
|
|
|
|
|
|
if(argc < 2)
|
|
{
|
|
fprintf(stderr, "%s: need args\n", argv[0]);
|
|
goto err;
|
|
}
|
|
|
|
for(i = 0; (i = getopt(argc, argv, "bo:qv")) != -1; i = 0)
|
|
{
|
|
switch(i)
|
|
{
|
|
case 'b':
|
|
param[B] = 1;
|
|
break;
|
|
case 'o':
|
|
if(!param[Q])
|
|
{
|
|
param[O] = 1;
|
|
}
|
|
outpath = optarg;
|
|
break;
|
|
case 'q':
|
|
param[Q] = 1;
|
|
param[B] = 0;
|
|
param[V] = 0;
|
|
break;
|
|
case 'v':
|
|
/* we handle v differently because we want to support different levels of verbosity */
|
|
if(!param[Q])
|
|
{
|
|
param[V]++;
|
|
}
|
|
break;
|
|
default:
|
|
errno = ERRUSAGE;
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
|
|
if(uri_parse(argv[optind], &uristruct))
|
|
{
|
|
fprintf(stderr, "%s: invalid URI.\n", argv[0]);
|
|
goto err;
|
|
}
|
|
if(!strlen(uristruct.path))
|
|
{
|
|
uristruct.path = "/";
|
|
}
|
|
|
|
if(!outpath && !param[O])
|
|
{
|
|
if(strlen(uristruct.path) == 0 || !strcmp(uristruct.path, "/"))
|
|
{
|
|
outpath = "default";
|
|
}
|
|
else
|
|
{
|
|
outpath = (1 + strrchr(uristruct.path, '/'));
|
|
}
|
|
}
|
|
|
|
sendbufp = reqgen(&uristruct);
|
|
|
|
if(!(filed = fopen(outpath, "w")))
|
|
{
|
|
printf("filed err\n");
|
|
goto err;
|
|
}
|
|
|
|
if( !(sockd = dial(uristruct.fqdn, uristruct.proto)))
|
|
{
|
|
printf("%s: couldn't connect to host %s.\n", argv[0], uristruct.fqdn);
|
|
goto err;
|
|
}
|
|
|
|
if(!send(sockd, sendbufp, strlen(sendbufp), 0))
|
|
{
|
|
printf("send err\n");
|
|
goto err;
|
|
}
|
|
|
|
printf("%s\n", sendbufp);
|
|
|
|
for(recv_header = 0, recvlen =1; sockd; memset(recvbuf, 0, BUFSIZ))
|
|
{
|
|
recvlen = recv(sockd, recvbuf, BUFSIZ, 0);
|
|
switch(recvlen)
|
|
{
|
|
case -1:
|
|
goto err;
|
|
|
|
case 0:
|
|
close(sockd);
|
|
sockd = 0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if(!recv_header)
|
|
{
|
|
offsetp = (strstr(recvbuf, "\r\n\r\n") + 4);
|
|
i = (int) (offsetp - recvbuf);
|
|
|
|
recv_header = 1;
|
|
}
|
|
else
|
|
{
|
|
offsetp = recvbuf;
|
|
i = 0;
|
|
}
|
|
|
|
if(param[V] >= 2)
|
|
{
|
|
printf("%s: received %d bytes...\n", argv[0], recvlen);
|
|
}
|
|
|
|
fwrite(offsetp, sizeof(char), recvlen-i, filed);
|
|
}
|
|
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
err:
|
|
exit(EXIT_FAILURE);
|
|
}
|