Annotation of embedaddon/curl/src/tool_main.c, revision 1.1
1.1 ! misho 1: /***************************************************************************
! 2: * _ _ ____ _
! 3: * Project ___| | | | _ \| |
! 4: * / __| | | | |_) | |
! 5: * | (__| |_| | _ <| |___
! 6: * \___|\___/|_| \_\_____|
! 7: *
! 8: * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
! 9: *
! 10: * This software is licensed as described in the file COPYING, which
! 11: * you should have received as part of this distribution. The terms
! 12: * are also available at https://curl.haxx.se/docs/copyright.html.
! 13: *
! 14: * You may opt to use, copy, modify, merge, publish, distribute and/or sell
! 15: * copies of the Software, and permit persons to whom the Software is
! 16: * furnished to do so, under the terms of the COPYING file.
! 17: *
! 18: * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
! 19: * KIND, either express or implied.
! 20: *
! 21: ***************************************************************************/
! 22: #include "tool_setup.h"
! 23:
! 24: #include <sys/stat.h>
! 25:
! 26: #ifdef HAVE_SIGNAL_H
! 27: #include <signal.h>
! 28: #endif
! 29:
! 30: #ifdef USE_NSS
! 31: #include <nspr.h>
! 32: #include <plarenas.h>
! 33: #endif
! 34:
! 35: #define ENABLE_CURLX_PRINTF
! 36: /* use our own printf() functions */
! 37: #include "curlx.h"
! 38:
! 39: #include "tool_cfgable.h"
! 40: #include "tool_convert.h"
! 41: #include "tool_doswin.h"
! 42: #include "tool_msgs.h"
! 43: #include "tool_operate.h"
! 44: #include "tool_panykey.h"
! 45: #include "tool_vms.h"
! 46: #include "tool_main.h"
! 47: #include "tool_libinfo.h"
! 48:
! 49: /*
! 50: * This is low-level hard-hacking memory leak tracking and similar. Using
! 51: * the library level code from this client-side is ugly, but we do this
! 52: * anyway for convenience.
! 53: */
! 54: #include "memdebug.h" /* keep this as LAST include */
! 55:
! 56: #ifdef __VMS
! 57: /*
! 58: * vms_show is a global variable, used in main() as parameter for
! 59: * function vms_special_exit() to allow proper curl tool exiting.
! 60: * Its value may be set in other tool_*.c source files thanks to
! 61: * forward declaration present in tool_vms.h
! 62: */
! 63: int vms_show = 0;
! 64: #endif
! 65:
! 66: #ifdef __MINGW32__
! 67: /*
! 68: * There seems to be no way to escape "*" in command-line arguments with MinGW
! 69: * when command-line argument globbing is enabled under the MSYS shell, so turn
! 70: * it off.
! 71: */
! 72: int _CRT_glob = 0;
! 73: #endif /* __MINGW32__ */
! 74:
! 75: /* if we build a static library for unit tests, there is no main() function */
! 76: #ifndef UNITTESTS
! 77:
! 78: /*
! 79: * Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
! 80: * open before starting to run. Otherwise, the first three network
! 81: * sockets opened by curl could be used for input sources, downloaded data
! 82: * or error logs as they will effectively be stdin, stdout and/or stderr.
! 83: */
! 84: static void main_checkfds(void)
! 85: {
! 86: #ifdef HAVE_PIPE
! 87: int fd[2] = { STDIN_FILENO, STDIN_FILENO };
! 88: while(fd[0] == STDIN_FILENO ||
! 89: fd[0] == STDOUT_FILENO ||
! 90: fd[0] == STDERR_FILENO ||
! 91: fd[1] == STDIN_FILENO ||
! 92: fd[1] == STDOUT_FILENO ||
! 93: fd[1] == STDERR_FILENO)
! 94: if(pipe(fd) < 0)
! 95: return; /* Out of handles. This isn't really a big problem now, but
! 96: will be when we try to create a socket later. */
! 97: close(fd[0]);
! 98: close(fd[1]);
! 99: #endif
! 100: }
! 101:
! 102: #ifdef CURLDEBUG
! 103: static void memory_tracking_init(void)
! 104: {
! 105: char *env;
! 106: /* if CURL_MEMDEBUG is set, this starts memory tracking message logging */
! 107: env = curlx_getenv("CURL_MEMDEBUG");
! 108: if(env) {
! 109: /* use the value as file name */
! 110: char fname[CURL_MT_LOGFNAME_BUFSIZE];
! 111: if(strlen(env) >= CURL_MT_LOGFNAME_BUFSIZE)
! 112: env[CURL_MT_LOGFNAME_BUFSIZE-1] = '\0';
! 113: strcpy(fname, env);
! 114: curl_free(env);
! 115: curl_dbg_memdebug(fname);
! 116: /* this weird stuff here is to make curl_free() get called before
! 117: curl_gdb_memdebug() as otherwise memory tracking will log a free()
! 118: without an alloc! */
! 119: }
! 120: /* if CURL_MEMLIMIT is set, this enables fail-on-alloc-number-N feature */
! 121: env = curlx_getenv("CURL_MEMLIMIT");
! 122: if(env) {
! 123: char *endptr;
! 124: long num = strtol(env, &endptr, 10);
! 125: if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
! 126: curl_dbg_memlimit(num);
! 127: curl_free(env);
! 128: }
! 129: }
! 130: #else
! 131: # define memory_tracking_init() Curl_nop_stmt
! 132: #endif
! 133:
! 134: /*
! 135: * This is the main global constructor for the app. Call this before
! 136: * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
! 137: * used, or havoc may be the result.
! 138: */
! 139: static CURLcode main_init(struct GlobalConfig *config)
! 140: {
! 141: CURLcode result = CURLE_OK;
! 142:
! 143: #if defined(__DJGPP__) || defined(__GO32__)
! 144: /* stop stat() wasting time */
! 145: _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
! 146: #endif
! 147:
! 148: /* Initialise the global config */
! 149: config->showerror = -1; /* Will show errors */
! 150: config->errors = stderr; /* Default errors to stderr */
! 151: config->styled_output = TRUE; /* enable detection */
! 152: config->parallel_max = PARALLEL_DEFAULT;
! 153:
! 154: /* Allocate the initial operate config */
! 155: config->first = config->last = malloc(sizeof(struct OperationConfig));
! 156: if(config->first) {
! 157: /* Perform the libcurl initialization */
! 158: result = curl_global_init(CURL_GLOBAL_DEFAULT);
! 159: if(!result) {
! 160: /* Get information about libcurl */
! 161: result = get_libcurl_info();
! 162:
! 163: if(!result) {
! 164: /* Initialise the config */
! 165: config_init(config->first);
! 166: config->first->global = config;
! 167: }
! 168: else {
! 169: errorf(config, "error retrieving curl library information\n");
! 170: free(config->first);
! 171: }
! 172: }
! 173: else {
! 174: errorf(config, "error initializing curl library\n");
! 175: free(config->first);
! 176: }
! 177: }
! 178: else {
! 179: errorf(config, "error initializing curl\n");
! 180: result = CURLE_FAILED_INIT;
! 181: }
! 182:
! 183: return result;
! 184: }
! 185:
! 186: static void free_globalconfig(struct GlobalConfig *config)
! 187: {
! 188: Curl_safefree(config->trace_dump);
! 189:
! 190: if(config->errors_fopened && config->errors)
! 191: fclose(config->errors);
! 192: config->errors = NULL;
! 193:
! 194: if(config->trace_fopened && config->trace_stream)
! 195: fclose(config->trace_stream);
! 196: config->trace_stream = NULL;
! 197:
! 198: Curl_safefree(config->libcurl);
! 199: }
! 200:
! 201: /*
! 202: * This is the main global destructor for the app. Call this after
! 203: * _all_ libcurl usage is done.
! 204: */
! 205: static void main_free(struct GlobalConfig *config)
! 206: {
! 207: /* Cleanup the easy handle */
! 208: /* Main cleanup */
! 209: curl_global_cleanup();
! 210: convert_cleanup();
! 211: metalink_cleanup();
! 212: #ifdef USE_NSS
! 213: if(PR_Initialized()) {
! 214: /* prevent valgrind from reporting still reachable mem from NSRP arenas */
! 215: PL_ArenaFinish();
! 216: /* prevent valgrind from reporting possibly lost memory (fd cache, ...) */
! 217: PR_Cleanup();
! 218: }
! 219: #endif
! 220: free_globalconfig(config);
! 221:
! 222: /* Free the config structures */
! 223: config_free(config->last);
! 224: config->first = NULL;
! 225: config->last = NULL;
! 226: }
! 227:
! 228: #ifdef WIN32
! 229: /* TerminalSettings for Windows */
! 230: static struct TerminalSettings {
! 231: HANDLE hStdOut;
! 232: DWORD dwOutputMode;
! 233: } TerminalSettings;
! 234:
! 235: static void configure_terminal(void)
! 236: {
! 237: /*
! 238: * If we're running Windows, enable VT output.
! 239: * Note: VT mode flag can be set on any version of Windows, but VT
! 240: * processing only performed on Win10 >= Creators Update)
! 241: */
! 242:
! 243: /* Define the VT flags in case we're building with an older SDK */
! 244: #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
! 245: #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
! 246: #endif
! 247:
! 248: memset(&TerminalSettings, 0, sizeof(TerminalSettings));
! 249:
! 250: /* Enable VT output */
! 251: TerminalSettings.hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
! 252: if((TerminalSettings.hStdOut != INVALID_HANDLE_VALUE)
! 253: && (GetConsoleMode(TerminalSettings.hStdOut,
! 254: &TerminalSettings.dwOutputMode))) {
! 255: SetConsoleMode(TerminalSettings.hStdOut,
! 256: TerminalSettings.dwOutputMode
! 257: | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
! 258: }
! 259: }
! 260: #else
! 261: #define configure_terminal()
! 262: #endif
! 263:
! 264: static void restore_terminal(void)
! 265: {
! 266: #ifdef WIN32
! 267: /* Restore Console output mode and codepage to whatever they were
! 268: * when Curl started */
! 269: SetConsoleMode(TerminalSettings.hStdOut, TerminalSettings.dwOutputMode);
! 270: #endif
! 271: }
! 272:
! 273: /*
! 274: ** curl tool main function.
! 275: */
! 276: int main(int argc, char *argv[])
! 277: {
! 278: CURLcode result = CURLE_OK;
! 279: struct GlobalConfig global;
! 280: memset(&global, 0, sizeof(global));
! 281:
! 282: #ifdef WIN32
! 283: /* Undocumented diagnostic option to list the full paths of all loaded
! 284: modules. This is purposely pre-init. */
! 285: if(argc == 2 && !strcmp(argv[1], "--dump-module-paths")) {
! 286: struct curl_slist *item, *head = GetLoadedModulePaths();
! 287: for(item = head; item; item = item->next)
! 288: printf("%s\n", item->data);
! 289: curl_slist_free_all(head);
! 290: return head ? 0 : 1;
! 291: }
! 292: /* win32_init must be called before other init routines. */
! 293: result = win32_init();
! 294: if(result) {
! 295: fprintf(stderr, "curl: (%d) Windows-specific init failed.\n", result);
! 296: return result;
! 297: }
! 298: #endif
! 299:
! 300: /* Perform any platform-specific terminal configuration */
! 301: configure_terminal();
! 302:
! 303: main_checkfds();
! 304:
! 305: #if defined(HAVE_SIGNAL) && defined(SIGPIPE)
! 306: (void)signal(SIGPIPE, SIG_IGN);
! 307: #endif
! 308:
! 309: /* Initialize memory tracking */
! 310: memory_tracking_init();
! 311:
! 312: /* Initialize the curl library - do not call any libcurl functions before
! 313: this point */
! 314: result = main_init(&global);
! 315: if(!result) {
! 316: /* Start our curl operation */
! 317: result = operate(&global, argc, argv);
! 318:
! 319: #ifdef __SYMBIAN32__
! 320: if(global.showerror)
! 321: tool_pressanykey();
! 322: #endif
! 323:
! 324: /* Perform the main cleanup */
! 325: main_free(&global);
! 326: }
! 327:
! 328: /* Return the terminal to its original state */
! 329: restore_terminal();
! 330:
! 331: #ifdef __NOVELL_LIBC__
! 332: if(getenv("_IN_NETWARE_BASH_") == NULL)
! 333: tool_pressanykey();
! 334: #endif
! 335:
! 336: #ifdef __VMS
! 337: vms_special_exit(result, vms_show);
! 338: #else
! 339: return (int)result;
! 340: #endif
! 341: }
! 342:
! 343: #endif /* ndef UNITTESTS */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>