📄 docd.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 + -