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

📄 docd.c

📁 多线程 http资源下载工具 给予linux平台的。还凑合。有bug给我联系
💻 C
字号:
#define __GNU_SOURCE#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <signal.h>#include <locale.h>#include <stdio.h>#include <sys/stat.h>#include <unistd.h>#include <sys/types.h>#include <dlfcn.h>#include <string.h>#include <strings.h>#include <pthread.h>#include "docd.h"static struct proto_handler *list_proto_handlers = NULL;static char *program_name = NULL;/*  begin here.*/int main (int argc, char **argv){  char opt;  char *dir = NULL;    // get program name.  program_name = base_name (argv[0]);  // init locale, signal, handler for protocol.  init ();  //parse options.  opterr = 0;  while (-1 != (opt = getopt (argc, argv, OPTS)))    {      switch (opt)	{	case WORKING_DIR:	  dir = optarg;	  break;	case HELP:	  usage ();	  return 0;	  break;	case '?':	  fprintf (stderr, "%s: Unkonw option: `-%c'\n",program_name, optopt);	  return -1;	  break;	case ':':	  fprintf (stderr, "%s: Missing argument: `-%c'\n", program_name, optopt);	  return -1;	  break;	default:	  fprintf (stderr, "%s: Parse arguments failure.\n", program_name);	  return -1;	}    }  // change working dir to DOWNLOAD_TO.  if (0 != setup_working_dir (dir))    {      fprintf (stderr, "%s: Change directory to `%s' failure.\n", program_name, dir);      return -1;    }  if (optind == argc)    {      fprintf (stderr, "%s: Missing location of resource.\n", program_name);      return -1;    }  else if (optind != argc - 1)    {      fprintf (stderr, "%s: Can't download multi-resource.\n", program_name);      return -1;    }  download_resource (argv[optind]);  hook_exit ();  return 0;}void usage (void){  fprintf (stdout, "%s: multi-thread get network resource tool in linux.\n", program_name);  fprintf (stdout, "Usage: %s -[ch] resource.\n", program_name);  fprintf (stdout, "Options:\n");  fprintf (stdout, "\t-c: working directory.\n");  fprintf (stdout, "\t-h: print help message.\n");  fprintf (stdout, "Bug:\n");  fprintf (stdout, "\treach me to email to `firperfect@gmail.com'.\n");}/*  register protocol handler to list "list_proto_handlers". */int register_proto_handler (const char *proto, const char *lib){  size_t len_proto, len_lib;  struct proto_handler *p;    if ((NULL != proto) && (NULL != lib))    {      len_proto = strlen (proto);      len_lib = strlen (lib);      if ((PROTO_NAME_LEN > len_proto) && (LIB_NAME_LEN > len_lib))	{	  if (NULL != (p = calloc (1, sizeof (struct proto_handler))))	    {	      strncpy ((*p).proto, proto, len_proto);	      strncpy ((*p).lib, lib, len_lib);	      (*p).next = list_proto_handlers;	      list_proto_handlers = p;	    }	  else	    return -1;	}      else	return -1;    }  else    return -1;  return 0;}/*  return the min length of string x and y. */unsigned int min_len (const char *x, const char *y){  size_t len_x;  size_t len_y;    len_x = strlen (x);  len_y = strlen (y);  return (len_x <= len_y)? len_x: len_y;}/*  return the max length of string x and y. */unsigned int max_len (const char *x, const char *y){  size_t len_x;  size_t len_y;    len_x = strlen (x);  len_y = strlen (y);  return (len_x <= len_y)? len_y: len_x;}/*  init handler for signal. */void init_signal (void){  struct sigaction handler;  int flags;    flags = SA_RESTART;  /* signal be ignored.	 */  RESET_SIG_HANDLER (handler, SIGCHLD, SIG_DFL, flags);  RESET_SIG_HANDLER (handler, SIGCONT, SIG_DFL, flags);  RESET_SIG_HANDLER (handler, SIGSTOP, SIG_DFL, flags);  RESET_SIG_HANDLER (handler, SIGTSTP, SIG_DFL, flags);  RESET_SIG_HANDLER (handler, SIGTTIN, SIG_DFL, flags);  RESET_SIG_HANDLER (handler, SIGTTOU, SIG_DFL, flags);  RESET_SIG_HANDLER (handler, SIGWINCH, SIG_DFL, flags);}/*  translate char to lower by c locale.*/char c_tolower (char *const c){  return (C_ISUPPER (*c))? (*c = (*c | 32)): (*c);}/*  translate multi-char to lower by c locale. */size_t c_ntolower (char *const s, size_t n){  size_t i;    i = 0;  do    if ('\0' == c_tolower (s + i))      break;  while (i++ < n);        return i;}/*  translate string to lower by c locale. */size_t c_stolower (char *const s){  size_t len_s;  len_s = strlen (s);  return c_ntolower (s, len_s);}int download_resource (const char *resource){  pthread_t pthread_handler;  size_t url_len;  char default_scheme[] = "http";  char scheme[MAX_LEN_SCHEME];  char *p_scheme_sfix;  char *p;  char *error;  int retval = -1;  void *lib_id;  size_t len;  void *p_handler;    bzero (scheme, sizeof (scheme));  if (NULL == (p_scheme_sfix = strstr (resource, "://")))    strcpy (scheme, default_scheme);  else    {      len = (p_scheme_sfix - resource) / SIZE_CHAR;      if ((0 > len) || (MAX_LEN_SCHEME <= len))	{	  fprintf (stderr, "%s: Invalidable URL.\n", program_name);	  return -1;	}      else	strncpy (scheme, resource, len);    }  c_stolower (scheme);  if (NULL == (lib_id = handler_open (scheme, list_proto_handlers)))    {      fprintf (stderr, "%s: Load handler for `%s' failure.\n", program_name, scheme);      goto __FUNCTION__return_error;    }  dlerror ();  p_handler = dlsym (lib_id, "handler");  if (NULL != (error = dlerror ()))    {      fprintf (stderr, "%s: Load handler for `%s' failure.\n", program_name, scheme);      goto __FUNCTION__return_error;    }    if (0 != pthread_create (&pthread_handler, NULL, p_handler, (void *) resource))    {      fprintf (stderr, "%s: Create thread failure.\n", program_name);      goto __FUNCTION__close_handler;    }    pthread_join (pthread_handler, NULL);  retval = 0; __FUNCTION__close_handler:  handler_close (lib_id); __FUNCTION__return_error:  return retval; }void handler_close (void *lib_id){  dlclose (lib_id);}void *handler_open (const char *proto, struct proto_handler *list){  void *lib_id;  struct proto_handler *p;  p = list;  while (NULL != p)    {      if (0 == strcmp (proto, p->proto))	break;      else	p = p->next;    }  if (NULL == p)    return NULL;  if (NULL == (lib_id = dlopen ((*p).lib, RTLD_LAZY)))    return NULL;    return lib_id;}/*  return base. */char *base_name (const char *path){  char *base;  return (char *)((base = strrchr (path, '/'))? (base + 1): path);}/*  init. */void init (void){  init_locale ();  init_signal ();  init_proto_handlers ();}/*  init locale. */void init_locale (void){  setlocale (LC_ALL, "");}/*  setup working directory. */int setup_working_dir (char *dir){  int retval;    if (NULL == dir)    dir = getenv ("DEFAULT_DOWNLOAD_DIR");  if (NULL != dir)    return chdir_to (dir);      if (NULL != (dir = getcwd (NULL, 0)))    {      retval = access (dir, R_OK | W_OK | X_OK )? -1: 0;      free (dir);      return retval;    } else   return -1;    }/*  change directory to. */int chdir_to (const char *path){  if (0 != access (path, R_OK | W_OK | X_OK | F_OK))    return -1;    if (0 == chdir (path))    return 0;  return -1;}/*  register handler for protocol. */void init_proto_handlers (void){  register_proto_handler ("http", "libdhttp.so");}/*  called when process exit.*/void hook_exit (void){  free_proto_handler ();}/*  free memory for handler registed.. */void free_proto_handler (void){  struct proto_handler *p, *next;    p = list_proto_handlers;  while (NULL != p)    {      next = (*p).next;      free (p);      p = next;    }}/*  return min address. */char *min_addr (const char *x, const char *y){  return (char *)((x > y)? x: y);}

⌨️ 快捷键说明

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