⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wget.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* vi: set sw=4 ts=4: *//* * wget - retrieve a file using HTTP or FTP * * Chip Rosenthal Covad Communications <chip@laserlink.net> * */#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <unistd.h>#include <ctype.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <sys/ioctl.h>#include <sys/time.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#ifndef _GNU_SOURCE#define _GNU_SOURCE#endif#include <getopt.h>#include "busybox.h"/* Stupid libc5 doesn't define this... */#ifndef timersub#define	timersub(a, b, result)						      \  do {									      \    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;			      \    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;			      \    if ((result)->tv_usec < 0) {					      \      --(result)->tv_sec;						      \      (result)->tv_usec += 1000000;					      \    }									      \  } while (0)#endif	struct host_info {	char *host;	int port;	char *path;	int is_ftp;	char *user;};static void parse_url(char *url, struct host_info *h);static FILE *open_socket(char *host, int port);static char *gethdr(char *buf, size_t bufsiz, FILE *fp, int *istrunc);static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf);/* Globals (can be accessed from signal handlers */static off_t filesize = 0;		/* content-length of the file */static int chunked = 0;			/* chunked transfer encoding */#ifdef CONFIG_FEATURE_WGET_STATUSBARstatic void progressmeter(int flag);static char *curfile;			/* Name of current file being transferred. */static struct timeval start;	/* Time a transfer started. */static volatile unsigned long statbytes = 0; /* Number of bytes transferred so far. *//* For progressmeter() -- number of seconds before xfer considered "stalled" */static const int STALLTIME = 5;#endif		static void close_and_delete_outfile(FILE* output, char *fname_out, int do_continue){	if (output != stdout && do_continue==0) {		fclose(output);		unlink(fname_out);	}}/* Read NMEMB elements of SIZE bytes into PTR from STREAM.  Returns the * number of elements read, and a short count if an eof or non-interrupt * error is encountered.  */static size_t safe_fread(void *ptr, size_t size, size_t nmemb, FILE *stream){	size_t ret = 0;	do {		clearerr(stream);		ret += fread((char *)ptr + (ret * size), size, nmemb - ret, stream);	} while (ret < nmemb && ferror(stream) && errno == EINTR);	return ret;}/* Write NMEMB elements of SIZE bytes from PTR to STREAM.  Returns the * number of elements written, and a short count if an eof or non-interrupt * error is encountered.  */static size_t safe_fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream){	size_t ret = 0;	do {		clearerr(stream);		ret += fwrite((char *)ptr + (ret * size), size, nmemb - ret, stream);	} while (ret < nmemb && ferror(stream) && errno == EINTR);	return ret;}/* Read a line or SIZE - 1 bytes into S, whichever is less, from STREAM. * Returns S, or NULL if an eof or non-interrupt error is encountered.  */static char *safe_fgets(char *s, int size, FILE *stream){	char *ret;	do {		clearerr(stream);		ret = fgets(s, size, stream);	} while (ret == NULL && ferror(stream) && errno == EINTR);	return ret;}#define close_delete_and_die(s...) { \	close_and_delete_outfile(output, fname_out, do_continue); \	error_msg_and_die(s); }#ifdef CONFIG_FEATURE_WGET_AUTHENTICATION/* *  Base64-encode character string *  oops... isn't something similar in uuencode.c? *  It would be better to use already existing code */char *base64enc(char *p, char *buf, int len) {        char al[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"                    "0123456789+/";		char *s = buf;        while(*p) {				if (s >= buf+len-4)					error_msg_and_die("buffer overflow");                *(s++) = al[(*p >> 2) & 0x3F];                *(s++) = al[((*p << 4) & 0x30) | ((*(p+1) >> 4) & 0x0F)];                *s = *(s+1) = '=';                *(s+2) = 0;                if (! *(++p)) break;                *(s++) = al[((*p << 2) & 0x3C) | ((*(p+1) >> 6) & 0x03)];                if (! *(++p)) break;                *(s++) = al[*(p++) & 0x3F];        }		return buf;}#endifint wget_main(int argc, char **argv){	int n, try=5, status;	int port;	char *proxy = 0;	char *dir_prefix=NULL;	char *s, buf[512];	struct stat sbuf;	char extra_headers[1024];	char *extra_headers_ptr = extra_headers;	int extra_headers_left = sizeof(extra_headers);	int which_long_opt = 0, option_index = -1;	struct host_info server, target;	FILE *sfp = NULL;			/* socket to web/ftp server			*/	FILE *dfp = NULL;			/* socket to ftp server (data)		*/	char *fname_out = NULL;		/* where to direct output (-O)		*/	int do_continue = 0;		/* continue a prev transfer (-c)	*/	long beg_range = 0L;		/*   range at which continue begins	*/	int got_clen = 0;			/* got content-length: from server	*/	FILE *output;				/* socket to web server				*/	int quiet_flag = FALSE;		/* Be verry, verry quiet...			*/	int noproxy = 0;            /* Use proxies if env vars are set  */#define LONG_HEADER	1	struct option long_options[] = {		{ "continue",		0, NULL, 'c' },		{ "quiet",		0, NULL, 'q' },		{ "output-document",	1, NULL, 'O' },		{ "header",		1, &which_long_opt, LONG_HEADER },		{ "proxy",		1, NULL, 'Y' },		{ 0,			0, 0, 0 }	};	/*	 * Crack command line.	 */	while ((n = getopt_long(argc, argv, "cqO:P:Y:", long_options, &option_index)) != EOF) {		switch (n) {		case 'c':			++do_continue;			break;		case 'P':			dir_prefix = optarg;			break;		case 'q':			quiet_flag = TRUE;			break;		case 'O':			/* can't set fname_out to NULL if outputting to stdout, because			 * this gets interpreted as the auto-gen output filename			 * case below  - tausq@debian.org			 */			fname_out = optarg;			break;		case 'Y':			if (strcmp(optarg, "off") == 0)				noproxy=1;				break;		case 0:			switch (which_long_opt) {				case LONG_HEADER: {					int arglen = strlen(optarg);					if(extra_headers_left - arglen - 2 <= 0)						error_msg_and_die("extra_headers buffer too small(need %i)", extra_headers_left - arglen);					strcpy(extra_headers_ptr, optarg);					extra_headers_ptr += arglen;					extra_headers_left -= ( arglen + 2 );					*extra_headers_ptr++ = '\r';					*extra_headers_ptr++ = '\n';					*(extra_headers_ptr + 1) = 0;					break;				}			}			break;		default:			show_usage();		}	}	if (argc - optind != 1)			show_usage();	parse_url(argv[optind], &target);	server.host = target.host;	server.port = target.port;	/*	 * Use the proxy if necessary.	 */	if (!noproxy) {		proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy");		if (proxy)			parse_url(xstrdup(proxy), &server);	}		/* Guess an output filename */	if (!fname_out) {		fname_out = #ifdef CONFIG_FEATURE_WGET_STATUSBAR			curfile = #endif			get_last_path_component(target.path);		if (fname_out==NULL || strlen(fname_out)<1) {			fname_out = #ifdef CONFIG_FEATURE_WGET_STATUSBAR				curfile = #endif				"index.html";		}		if (dir_prefix != NULL)			fname_out = concat_path_file(dir_prefix, fname_out);#ifdef CONFIG_FEATURE_WGET_STATUSBAR	} else {		curfile = get_last_path_component(fname_out);#endif	}	if (do_continue && !fname_out)		error_msg_and_die("cannot specify continue (-c) without a filename (-O)");	/*	 * Open the output file stream.	 */	if (strcmp(fname_out, "-") == 0) {		output = stdout;		quiet_flag = TRUE;	} else {		output = xfopen(fname_out, (do_continue ? "a" : "w"));	}	/*	 * Determine where to start transfer.	 */	if (do_continue) {		if (fstat(fileno(output), &sbuf) < 0)			perror_msg_and_die("fstat()");		if (sbuf.st_size > 0)			beg_range = sbuf.st_size;		else			do_continue = 0;	}	if (proxy || !target.is_ftp) {		/*		 *  HTTP session		 */		do {			if (! --try)				close_delete_and_die("too many redirections");			/*			 * Open socket to http server			 */			if (sfp) fclose(sfp);			sfp = open_socket(server.host, server.port);						/*			 * Send HTTP request.			 */			if (proxy) {				fprintf(sfp, "GET %stp://%s:%d/%s HTTP/1.1\r\n",					target.is_ftp ? "f" : "ht", target.host,					target.port, target.path);			} else {				fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);			}			fprintf(sfp, "Host: %s\r\nUser-Agent: Wget\r\n", target.host);#ifdef CONFIG_FEATURE_WGET_AUTHENTICATION			if (target.user) {				fprintf(sfp, "Authorization: Basic %s\r\n",					base64enc(target.user, buf, sizeof(buf)));			}			if (proxy && server.user) {				fprintf(sfp, "Proxy-Authorization: Basic %s\r\n",					base64enc(server.user, buf, sizeof(buf)));			}#endif			if (do_continue)				fprintf(sfp, "Range: bytes=%ld-\r\n", beg_range);			if(extra_headers_left < sizeof(extra_headers))				fputs(extra_headers,sfp);			fprintf(sfp,"Connection: close\r\n\r\n");			/*		 	* Retrieve HTTP response line and check for "200" status code.		 	*/read_response:		if (fgets(buf, sizeof(buf), sfp) == NULL)				close_delete_and_die("no response from server");							for (s = buf ; *s != '\0' && !isspace(*s) ; ++s)			;			for ( ; isspace(*s) ; ++s)			;			switch (status = atoi(s)) {				case 0:				case 100:					while (gethdr(buf, sizeof(buf), sfp, &n) != NULL);					goto read_response;				case 200:					if (do_continue && output != stdout)						output = freopen(fname_out, "w", output);					do_continue = 0;					break;				case 300:	/* redirection */				case 301:				case 302:				case 303:					break;				case 206:					if (do_continue)						break;					/*FALLTHRU*/				default:					chomp(buf);					close_delete_and_die("server returned error %d: %s", atoi(s), buf);			}					/*			 * Retrieve HTTP headers.			 */			while ((s = gethdr(buf, sizeof(buf), sfp, &n)) != NULL) {				if (strcasecmp(buf, "content-length") == 0) {					filesize = atol(s);					got_clen = 1;					continue;				}				if (strcasecmp(buf, "transfer-encoding") == 0) {					if (strcasecmp(s, "chunked") == 0) {						chunked = got_clen = 1;					} else {					close_delete_and_die("server wants to do %s transfer encoding", s);					}				}				if (strcasecmp(buf, "location") == 0) {					if (s[0] == '/')						target.path = xstrdup(s+1);					else {						parse_url(xstrdup(s), &target);						if (!proxy) {							server.host = target.host;							server.port = target.port;						}					}				}			}		} while(status >= 300);				dfp = sfp;	}	else	{		/*		 *  FTP session		 */		if (! target.user)			target.user = xstrdup("anonymous:busybox@");		sfp = open_socket(server.host, server.port);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -