diff options
author | Yang Tse <yangsita@gmail.com> | 2011-09-24 17:38:16 +0200 |
---|---|---|
committer | Yang Tse <yangsita@gmail.com> | 2011-09-24 17:40:46 +0200 |
commit | c6702c7d3f53b0eb07e452c732df1b8f5765b287 (patch) | |
tree | a10425f82f68519524437a5751a276b75c25cc09 /src/main.c | |
parent | 8bab6700d9a7f2085c81c069e0ac0792ac0521b2 (diff) | |
download | curl-c6702c7d3f53b0eb07e452c732df1b8f5765b287.tar.gz |
curl tool: reviewed code moved to tool_*.[ch] files
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 622 |
1 files changed, 18 insertions, 604 deletions
diff --git a/src/main.c b/src/main.c index 1c8106626..306df623d 100644 --- a/src/main.c +++ b/src/main.c @@ -102,9 +102,17 @@ #include "tool_mfiles.h" #include "tool_msgs.h" #include "tool_myfunc.h" -#include "tool_progress.h" +#include "tool_cb_prg.h" #include "tool_setopt.h" #include "tool_vms.h" + +#include "tool_cb_rea.h" +#include "tool_cb_wrt.h" +#include "tool_cb_see.h" +#include "tool_cb_skt.h" +#include "tool_cb_hdr.h" +#include "tool_cb_dbg.h" + #ifdef USE_MANUAL # include "hugehelp.h" #endif @@ -230,44 +238,6 @@ char **__crt0_glob_function (char *arg) "If you'd like to turn off curl's verification of the certificate, use\n" \ " the -k (or --insecure) option.\n" -#if defined(WIN32) && !defined(__MINGW64__) - -#ifdef __BORLANDC__ -/* 64-bit lseek-like function unavailable */ -# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence) -#endif - -#ifdef __POCC__ -# if(__POCC__ < 450) -/* 64-bit lseek-like function unavailable */ -# define _lseeki64(hnd,ofs,whence) _lseek(hnd,ofs,whence) -# else -# define _lseeki64(hnd,ofs,whence) _lseek64(hnd,ofs,whence) -# endif -#endif - -#ifndef HAVE_FTRUNCATE -#define HAVE_FTRUNCATE 1 -#endif - -/* - * Truncate a file handle at a 64-bit position 'where'. - */ - -static int ftruncate64(int fd, curl_off_t where) -{ - if(_lseeki64(fd, where, SEEK_SET) < 0) - return -1; - - if(!SetEndOfFile((HANDLE)_get_osfhandle(fd))) - return -1; - - return 0; -} -#define ftruncate(fd,where) ftruncate64(fd,where) - -#endif /* WIN32 */ - /* * This is the main global constructor for the app. Call this before * _any_ libcurl usage. If this fails, *NO* libcurl functions may be @@ -1210,60 +1180,6 @@ static int ftpcccmethod(struct Configurable *config, const char *str) return CURLFTPSSL_CCC_PASSIVE; } - -static int sockoptcallback(void *clientp, curl_socket_t curlfd, - curlsocktype purpose) -{ - struct Configurable *config = (struct Configurable *)clientp; - int onoff = 1; /* this callback is only used if we ask for keepalives on the - connection */ -#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPINTVL) - int keepidle = (int)config->alivetime; -#endif - - switch(purpose) { - case CURLSOCKTYPE_IPCXN: - if(setsockopt(curlfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&onoff, - sizeof(onoff)) < 0) { - /* don't abort operation, just issue a warning */ - SET_SOCKERRNO(0); - warnf(clientp, "Could not set SO_KEEPALIVE!\n"); - return 0; - } - else { - if(config->alivetime) { -#ifdef TCP_KEEPIDLE - if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, - sizeof(keepidle)) < 0) { - /* don't abort operation, just issue a warning */ - SET_SOCKERRNO(0); - warnf(clientp, "Could not set TCP_KEEPIDLE!\n"); - return 0; - } -#endif -#ifdef TCP_KEEPINTVL - if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepidle, - sizeof(keepidle)) < 0) { - /* don't abort operation, just issue a warning */ - SET_SOCKERRNO(0); - warnf(clientp, "Could not set TCP_KEEPINTVL!\n"); - return 0; - } -#endif -#if !defined(TCP_KEEPIDLE) || !defined(TCP_KEEPINTVL) - warnf(clientp, "Keep-alive functionality somewhat crippled due to " - "missing support in your operating system!\n"); -#endif - } - } - break; - default: - break; - } - - return 0; -} - static long delegation(struct Configurable *config, char *str) { @@ -3045,369 +2961,6 @@ static void go_sleep(long ms) #endif } -static size_t my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream) -{ - size_t rc; - struct OutStruct *out=(struct OutStruct *)stream; - struct Configurable *config = out->config; - - /* - * Once that libcurl has called back my_fwrite() the returned value - * is checked against the amount that was intended to be written, if - * it does not match then it fails with CURLE_WRITE_ERROR. So at this - * point returning a value different from sz*nmemb indicates failure. - */ - const size_t err_rc = (sz * nmemb) ? 0 : 1; - - if(!out->stream) { - out->bytes = 0; /* nothing written yet */ - if(!out->filename) { - warnf(config, "Remote filename has no length!\n"); - return err_rc; /* Failure */ - } - - if(config->content_disposition) { - /* don't overwrite existing files */ - FILE* f = fopen(out->filename, "r"); - if(f) { - fclose(f); - warnf(config, "Refusing to overwrite %s: %s\n", out->filename, - strerror(EEXIST)); - return err_rc; /* Failure */ - } - } - - /* open file for writing */ - out->stream=fopen(out->filename, "wb"); - if(!out->stream) { - warnf(config, "Failed to create the file %s: %s\n", out->filename, - strerror(errno)); - return err_rc; /* failure */ - } - } - - rc = fwrite(buffer, sz, nmemb, out->stream); - - if((sz * nmemb) == rc) - /* we added this amount of data to the output */ - out->bytes += (sz * nmemb); - - if(config->readbusy) { - config->readbusy = FALSE; - curl_easy_pause(config->easy, CURLPAUSE_CONT); - } - - if(config->nobuffer) { - /* disable output buffering */ - int res = fflush(out->stream); - if(res) { - /* return a value that isn't the same as sz * nmemb */ - return err_rc; /* failure */ - } - } - - return rc; -} - -#define MAX_SEEK 2147483647 - -/* - * my_seek() is the CURLOPT_SEEKFUNCTION we use - */ -static int my_seek(void *stream, curl_off_t offset, int whence) -{ - struct InStruct *in=(struct InStruct *)stream; - -#if(CURL_SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES) - /* The offset check following here is only interesting if curl_off_t is - larger than off_t and we are not using the WIN32 large file support - macros that provide the support to do 64bit seeks correctly */ - - if(offset > MAX_SEEK) { - /* Some precaution code to work around problems with different data sizes - to allow seeking >32bit even if off_t is 32bit. Should be very rare and - is really valid on weirdo-systems. */ - curl_off_t left = offset; - - if(whence != SEEK_SET) - /* this code path doesn't support other types */ - return 1; - - if(LSEEK_ERROR == lseek(in->fd, 0, SEEK_SET)) - /* couldn't rewind to beginning */ - return 1; - - while(left) { - long step = (left>MAX_SEEK ? MAX_SEEK : (long)left); - if(LSEEK_ERROR == lseek(in->fd, step, SEEK_CUR)) - /* couldn't seek forwards the desired amount */ - return 1; - left -= step; - } - return 0; - } -#endif - if(LSEEK_ERROR == lseek(in->fd, offset, whence)) - /* couldn't rewind, the reason is in errno but errno is just not portable - enough and we don't actually care that much why we failed. We'll let - libcurl know that it may try other means if it wants to. */ - return CURL_SEEKFUNC_CANTSEEK; - - return 0; -} - -static size_t my_fread(void *buffer, size_t sz, size_t nmemb, void *userp) -{ - ssize_t rc; - struct InStruct *in=(struct InStruct *)userp; - - rc = read(in->fd, buffer, sz*nmemb); - if(rc < 0) { - if(errno == EAGAIN) { - errno = 0; - in->config->readbusy = TRUE; - return CURL_READFUNC_PAUSE; - } - /* since size_t is unsigned we can't return negative values fine */ - rc = 0; - } - in->config->readbusy = FALSE; - return (size_t)rc; -} - -static -void dump(const char *timebuf, const char *text, - FILE *stream, const unsigned char *ptr, size_t size, - trace tracetype, curl_infotype infotype) -{ - size_t i; - size_t c; - - unsigned int width=0x10; - - if(tracetype == TRACE_ASCII) - /* without the hex output, we can fit more on screen */ - width = 0x40; - - fprintf(stream, "%s%s, %zd bytes (0x%zx)\n", timebuf, text, size, size); - - for(i=0; i<size; i+= width) { - - fprintf(stream, "%04zx: ", i); - - if(tracetype == TRACE_BIN) { - /* hex not disabled, show it */ - for(c = 0; c < width; c++) - if(i+c < size) - fprintf(stream, "%02x ", ptr[i+c]); - else - fputs(" ", stream); - } - - for(c = 0; (c < width) && (i+c < size); c++) { - /* check for 0D0A; if found, skip past and start a new line of output */ - if((tracetype == TRACE_ASCII) && - (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) { - i+=(c+2-width); - break; - } -#ifdef CURL_DOES_CONVERSIONS - /* repeat the 0D0A check above but use the host encoding for CRLF */ - if((tracetype == TRACE_ASCII) && - (i+c+1 < size) && ptr[i+c]=='\r' && ptr[i+c+1]=='\n') { - i+=(c+2-width); - break; - } - /* convert to host encoding and print this character */ - fprintf(stream, "%c", convert_char(infotype, ptr[i+c])); -#else - (void)infotype; - fprintf(stream, "%c", - (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:UNPRINTABLE_CHAR); -#endif /* CURL_DOES_CONVERSIONS */ - /* check again for 0D0A, to avoid an extra \n if it's at width */ - if((tracetype == TRACE_ASCII) && - (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) { - i+=(c+3-width); - break; - } - } - fputc('\n', stream); /* newline */ - } - fflush(stream); -} - -static -int my_trace(CURL *handle, curl_infotype type, - unsigned char *data, size_t size, - void *userp) -{ - struct Configurable *config = (struct Configurable *)userp; - FILE *output=config->errors; - const char *text; - struct timeval tv; - struct tm *now; - char timebuf[20]; - time_t secs; - static time_t epoch_offset; - static int known_offset; - - (void)handle; /* prevent compiler warning */ - - if(config->tracetime) { - tv = cutil_tvnow(); - if(!known_offset) { - epoch_offset = time(NULL) - tv.tv_sec; - known_offset = 1; - } - secs = epoch_offset + tv.tv_sec; - now = localtime(&secs); /* not thread safe but we don't care */ - snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ", - now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec); - } - else - timebuf[0]=0; - - if(!config->trace_stream) { - /* open for append */ - if(curlx_strequal("-", config->trace_dump)) - config->trace_stream = stdout; - else if(curlx_strequal("%", config->trace_dump)) - /* Ok, this is somewhat hackish but we do it undocumented for now */ - config->trace_stream = config->errors; /* aka stderr */ - else { - config->trace_stream = fopen(config->trace_dump, "w"); - config->trace_fopened = TRUE; - } - } - - if(config->trace_stream) - output = config->trace_stream; - - if(!output) { - warnf(config, "Failed to create/open output"); - return 0; - } - - if(config->tracetype == TRACE_PLAIN) { - /* - * This is the trace look that is similar to what libcurl makes on its - * own. - */ - static const char * const s_infotype[] = { - "*", "<", ">", "{", "}", "{", "}" - }; - size_t i; - size_t st=0; - static bool newl = FALSE; - static bool traced_data = FALSE; - - switch(type) { - case CURLINFO_HEADER_OUT: - for(i=0; i<size-1; i++) { - if(data[i] == '\n') { /* LF */ - if(!newl) { - fprintf(output, "%s%s ", timebuf, s_infotype[type]); - } - (void)fwrite(data+st, i-st+1, 1, output); - st = i+1; - newl = FALSE; - } - } - if(!newl) - fprintf(output, "%s%s ", timebuf, s_infotype[type]); - (void)fwrite(data+st, i-st+1, 1, output); - newl = (size && (data[size-1] != '\n'))?TRUE:FALSE; - traced_data = FALSE; - break; - case CURLINFO_TEXT: - case CURLINFO_HEADER_IN: - if(!newl) - fprintf(output, "%s%s ", timebuf, s_infotype[type]); - (void)fwrite(data, size, 1, output); - newl = (size && (data[size-1] != '\n'))?TRUE:FALSE; - traced_data = FALSE; - break; - case CURLINFO_DATA_OUT: - case CURLINFO_DATA_IN: - case CURLINFO_SSL_DATA_IN: - case CURLINFO_SSL_DATA_OUT: - if(!traced_data) { - /* if the data is output to a tty and we're sending this debug trace - to stderr or stdout, we don't display the alert about the data not - being shown as the data _is_ shown then just not via this - function */ - if(!config->isatty || - ((output != stderr) && (output != stdout))) { - if(!newl) - fprintf(output, "%s%s ", timebuf, s_infotype[type]); - fprintf(output, "[data not shown]\n"); - newl = FALSE; - traced_data = TRUE; - } - } - break; - default: /* nada */ - newl = FALSE; - traced_data = FALSE; - break; - } - - return 0; - } - -#ifdef CURL_DOES_CONVERSIONS - /* Special processing is needed for CURLINFO_HEADER_OUT blocks - * if they contain both headers and data (separated by CRLFCRLF). - * We dump the header text and then switch type to CURLINFO_DATA_OUT. - */ - if((type == CURLINFO_HEADER_OUT) && (size > 4)) { - size_t i; - for(i = 0; i < size - 4; i++) { - if(memcmp(&data[i], "\r\n\r\n", 4) == 0) { - /* dump everything through the CRLFCRLF as a sent header */ - text = "=> Send header"; - dump(timebuf, text, output, data, i+4, config->tracetype, type); - data += i + 3; - size -= i + 4; - type = CURLINFO_DATA_OUT; - data += 1; - break; - } - } - } -#endif /* CURL_DOES_CONVERSIONS */ - - switch (type) { - case CURLINFO_TEXT: - fprintf(output, "%s== Info: %s", timebuf, data); - default: /* in case a new one is introduced to shock us */ - return 0; - - case CURLINFO_HEADER_OUT: - text = "=> Send header"; - break; - case CURLINFO_DATA_OUT: - text = "=> Send data"; - break; - case CURLINFO_HEADER_IN: - text = "<= Recv header"; - break; - case CURLINFO_DATA_IN: - text = "<= Recv data"; - break; - case CURLINFO_SSL_DATA_IN: - text = "<= Recv SSL data"; - break; - case CURLINFO_SSL_DATA_OUT: - text = "=> Send SSL data"; - break; - } - - dump(timebuf, text, output, data, size, config->tracetype, type); - return 0; -} - #define RETRY_SLEEP_DEFAULT 1000L /* ms */ #define RETRY_SLEEP_MAX 600000L /* ms == 10 minutes */ @@ -3505,147 +3058,6 @@ static char *get_url_file_name(const char *url) return fn; } -/* - * Copies a file name part and returns an ALLOCATED data buffer. - */ -static char* -parse_filename(char *ptr, size_t len) -{ - char* copy; - char* p; - char* q; - char stop = 0; - - /* simple implementation of strndup() */ - copy = malloc(len+1); - if(!copy) - return NULL; - memcpy(copy, ptr, len); - copy[len] = 0; - - p = copy; - if(*p == '\'' || *p == '"') { - /* store the starting quote */ - stop = *p; - p++; - } - else - stop = ';'; - - /* if the filename contains a path, only use filename portion */ - q = strrchr(copy, '/'); - if(q) { - p=q+1; - if(!*p) { - Curl_safefree(copy); - return NULL; - } - } - - /* If the filename contains a backslash, only use filename portion. The idea - is that even systems that don't handle backslashes as path separators - probably want the path removed for convenience. */ - q = strrchr(p, '\\'); - if(q) { - p = q+1; - if(!*p) { - Curl_safefree(copy); - return NULL; - } - } - - /* scan for the end letter and stop there */ - q = p; - while(*q) { - if(q[1] && q[0]=='\\') - q++; - else if(q[0] == stop) - break; - q++; - } - *q = 0; - - /* make sure the file name doesn't end in \r or \n */ - q = strchr(p, '\r'); - if(q) - *q = 0; - - q = strchr(p, '\n'); - if(q) - *q = 0; - - if(copy!=p) - memmove(copy, p, strlen(p)+1); - - /* in case we built curl debug enabled, we allow an evironment variable - * named CURL_TESTDIR to prefix the given file name to put it into a - * specific directory - */ -#ifdef CURLDEBUG - { - char *tdir = curlx_getenv("CURL_TESTDIR"); - if(tdir) { - char buffer[512]; /* suitably large */ - snprintf(buffer, sizeof(buffer), "%s/%s", tdir, copy); - Curl_safefree(copy); - copy = strdup(buffer); /* clone the buffer, we don't use the libcurl - aprintf() or similar since we want to use the - same memory code as the "real" parse_filename - function */ - curl_free(tdir); - } - } -#endif - - return copy; -} - -static size_t -header_callback(void *ptr, size_t size, size_t nmemb, void *stream) -{ - struct OutStruct* outs = (struct OutStruct*)stream; - const char* str = (char*)ptr; - const size_t cb = size*nmemb; - const char* end = (char*)ptr + cb; - - if(cb > 20 && checkprefix("Content-disposition:", str)) { - char *p = (char*)str + 20; - - /* look for the 'filename=' parameter - (encoded filenames (*=) are not supported) */ - for(;;) { - char *filename; - size_t len; - - while(*p && (p < end) && !ISALPHA(*p)) - p++; - if(p > end-9) - break; - - if(memcmp(p, "filename=", 9)) { - /* no match, find next parameter */ - while((p < end) && (*p != ';')) - p++; - continue; - } - p+=9; - - /* this expression below typecasts 'cb' only to avoid - warning: signed and unsigned type in conditional expression - */ - len = (ssize_t)cb - (p - str); - filename = parse_filename(p, len); - if(filename) { - outs->filename = filename; - outs->alloc_filename = TRUE; - break; - } - } - } - - return cb; -} - #ifdef CURLDEBUG static void memory_tracking_init(void) { @@ -4322,7 +3734,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) /* where to store */ my_setopt(curl, CURLOPT_WRITEDATA, &outs); /* what call to write */ - my_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); + my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb); /* for uploads */ input.fd = infd; @@ -4331,12 +3743,12 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) /* what call to read */ if((outfile && !curlx_strequal("-", outfile)) || !checkprefix("telnet:", this_url)) - my_setopt(curl, CURLOPT_READFUNCTION, my_fread); + my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb); /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */ my_setopt(curl, CURLOPT_SEEKDATA, &input); - my_setopt(curl, CURLOPT_SEEKFUNCTION, my_seek); + my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb); if(config->recvpersecond) /* tell libcurl to use a smaller sized buffer as it allows us to @@ -4581,7 +3993,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) !config->noprogress && !config->mute) { /* we want the alternative style, then we have to implement it ourselves! */ - my_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress); + my_setopt(curl, CURLOPT_PROGRESSFUNCTION, tool_progress_cb); my_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar); } @@ -4607,7 +4019,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) my_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE); if(config->tracetype != TRACE_NONE) { - my_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb); my_setopt(curl, CURLOPT_DEBUGDATA, config); my_setopt(curl, CURLOPT_VERBOSE, TRUE); } @@ -4702,7 +4114,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) /* curl 7.17.1 */ if(!config->nokeepalive) { - my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockoptcallback); + my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, tool_sockopt_cb); my_setopt(curl, CURLOPT_SOCKOPTDATA, config); } @@ -4727,7 +4139,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) if((urlnode->flags & GETOUT_USEREMOTE) && config->content_disposition) { - my_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback); + my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb); my_setopt(curl, CURLOPT_HEADERDATA, &outs); } else { @@ -5045,6 +4457,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) Curl_safefree(urlnode->infile); urlnode->flags = 0; + /* TODO: Should CURLE_SSL_CACERT be included as critical error ? */ + /* ** Bail out upon critical errors */ |