quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

tool_main.c (8168B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 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.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  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 #include "tool_setup.h"
     25 
     26 #ifdef _WIN32
     27 #include <tchar.h>
     28 #endif
     29 
     30 #ifndef UNDER_CE
     31 #include <signal.h>
     32 #endif
     33 
     34 #ifdef HAVE_FCNTL_H
     35 #include <fcntl.h>
     36 #endif
     37 
     38 #include "tool_cfgable.h"
     39 #include "tool_doswin.h"
     40 #include "tool_msgs.h"
     41 #include "tool_operate.h"
     42 #include "tool_vms.h"
     43 #include "tool_main.h"
     44 #include "tool_libinfo.h"
     45 #include "tool_stderr.h"
     46 
     47 /*
     48  * This is low-level hard-hacking memory leak tracking and similar. Using
     49  * the library level code from this client-side is ugly, but we do this
     50  * anyway for convenience.
     51  */
     52 #include "memdebug.h" /* keep this as LAST include */
     53 
     54 #ifdef __VMS
     55 /*
     56  * vms_show is a global variable, used in main() as parameter for
     57  * function vms_special_exit() to allow proper curl tool exiting.
     58  * Its value may be set in other tool_*.c source files thanks to
     59  * forward declaration present in tool_vms.h
     60  */
     61 int vms_show = 0;
     62 #endif
     63 
     64 #if defined(__AMIGA__)
     65 #if defined(__GNUC__)
     66 #define CURL_USED __attribute__((used))
     67 #else
     68 #define CURL_USED
     69 #endif
     70 static const char CURL_USED min_stack[] = "$STACK:16384";
     71 #endif
     72 
     73 #ifdef __MINGW32__
     74 /*
     75  * There seems to be no way to escape "*" in command-line arguments with MinGW
     76  * when command-line argument globbing is enabled under the MSYS shell, so turn
     77  * it off.
     78  */
     79 extern int _CRT_glob;
     80 int _CRT_glob = 0;
     81 #endif /* __MINGW32__ */
     82 
     83 /* if we build a static library for unit tests, there is no main() function */
     84 #ifndef UNITTESTS
     85 
     86 #if defined(HAVE_PIPE) && defined(HAVE_FCNTL)
     87 /*
     88  * Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
     89  * open before starting to run. Otherwise, the first three network
     90  * sockets opened by curl could be used for input sources, downloaded data
     91  * or error logs as they will effectively be stdin, stdout and/or stderr.
     92  *
     93  * fcntl's F_GETFD instruction returns -1 if the file descriptor is closed,
     94  * otherwise it returns "the file descriptor flags (which typically can only
     95  * be FD_CLOEXEC, which is not set here).
     96  */
     97 static int main_checkfds(void)
     98 {
     99   int fd[2];
    100   while((fcntl(STDIN_FILENO, F_GETFD) == -1) ||
    101         (fcntl(STDOUT_FILENO, F_GETFD) == -1) ||
    102         (fcntl(STDERR_FILENO, F_GETFD) == -1))
    103     if(pipe(fd))
    104       return 1;
    105   return 0;
    106 }
    107 #else
    108 #define main_checkfds() 0
    109 #endif
    110 
    111 #ifdef CURLDEBUG
    112 static void memory_tracking_init(void)
    113 {
    114   char *env;
    115   /* if CURL_MEMDEBUG is set, this starts memory tracking message logging */
    116   env = curl_getenv("CURL_MEMDEBUG");
    117   if(env) {
    118     /* use the value as filename */
    119     char fname[512];
    120     if(strlen(env) >= sizeof(fname))
    121       env[sizeof(fname)-1] = '\0';
    122     strcpy(fname, env);
    123     curl_free(env);
    124     curl_dbg_memdebug(fname);
    125     /* this weird stuff here is to make curl_free() get called before
    126        curl_dbg_memdebug() as otherwise memory tracking will log a free()
    127        without an alloc! */
    128   }
    129   /* if CURL_MEMLIMIT is set, this enables fail-on-alloc-number-N feature */
    130   env = curl_getenv("CURL_MEMLIMIT");
    131   if(env) {
    132     curl_off_t num;
    133     const char *p = env;
    134     if(!curlx_str_number(&p, &num, LONG_MAX))
    135       curl_dbg_memlimit((long)num);
    136     curl_free(env);
    137   }
    138 }
    139 #else
    140 #  define memory_tracking_init() tool_nop_stmt
    141 #endif
    142 
    143 /*
    144  * This is the main global constructor for the app. Call this before
    145  * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
    146  * used, or havoc may be the result.
    147  */
    148 static CURLcode main_init(struct GlobalConfig *global)
    149 {
    150   CURLcode result = CURLE_OK;
    151 
    152 #ifdef __DJGPP__
    153   /* stop stat() wasting time */
    154   _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
    155 #endif
    156 
    157   /* Initialise the global config */
    158   global->showerror = FALSE;          /* show errors when silent */
    159   global->styled_output = TRUE;       /* enable detection */
    160   global->parallel_max = PARALLEL_DEFAULT;
    161 
    162   /* Allocate the initial operate config */
    163   global->first = global->last = config_alloc(global);
    164   if(global->first) {
    165     /* Perform the libcurl initialization */
    166     result = curl_global_init(CURL_GLOBAL_DEFAULT);
    167     if(!result) {
    168       /* Get information about libcurl */
    169       result = get_libcurl_info();
    170 
    171       if(result) {
    172         errorf(global, "error retrieving curl library information");
    173         free(global->first);
    174       }
    175     }
    176     else {
    177       errorf(global, "error initializing curl library");
    178       free(global->first);
    179     }
    180   }
    181   else {
    182     errorf(global, "error initializing curl");
    183     result = CURLE_FAILED_INIT;
    184   }
    185 
    186   return result;
    187 }
    188 
    189 static void free_globalconfig(struct GlobalConfig *global)
    190 {
    191   tool_safefree(global->trace_dump);
    192 
    193   if(global->trace_fopened && global->trace_stream)
    194     fclose(global->trace_stream);
    195   global->trace_stream = NULL;
    196 
    197   tool_safefree(global->libcurl);
    198 }
    199 
    200 /*
    201  * This is the main global destructor for the app. Call this after _all_
    202  * libcurl usage is done.
    203  */
    204 static void main_free(struct GlobalConfig *global)
    205 {
    206   /* Cleanup the easy handle */
    207   /* Main cleanup */
    208   curl_global_cleanup();
    209   free_globalconfig(global);
    210 
    211   /* Free the OperationConfig structures */
    212   config_free(global->last);
    213   global->first = NULL;
    214   global->last = NULL;
    215 }
    216 
    217 /*
    218 ** curl tool main function.
    219 */
    220 #if defined(_UNICODE) && !defined(UNDER_CE)
    221 #if defined(__GNUC__) || defined(__clang__)
    222 /* GCC does not know about wmain() */
    223 #pragma GCC diagnostic push
    224 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
    225 #pragma GCC diagnostic ignored "-Wmissing-declarations"
    226 #endif
    227 int wmain(int argc, wchar_t *argv[])
    228 #else
    229 int main(int argc, char *argv[])
    230 #endif
    231 {
    232   CURLcode result = CURLE_OK;
    233   struct GlobalConfig global;
    234   memset(&global, 0, sizeof(global));
    235 
    236   tool_init_stderr();
    237 
    238 #if defined(_WIN32) && !defined(UNDER_CE)
    239   /* Undocumented diagnostic option to list the full paths of all loaded
    240      modules. This is purposely pre-init. */
    241   if(argc == 2 && !_tcscmp(argv[1], _T("--dump-module-paths"))) {
    242     struct curl_slist *item, *head = GetLoadedModulePaths();
    243     for(item = head; item; item = item->next)
    244       printf("%s\n", item->data);
    245     curl_slist_free_all(head);
    246     return head ? 0 : 1;
    247   }
    248 #endif
    249 #ifdef _WIN32
    250   /* win32_init must be called before other init routines. */
    251   result = win32_init();
    252   if(result) {
    253     errorf(&global, "(%d) Windows-specific init failed", result);
    254     return (int)result;
    255   }
    256 #endif
    257 
    258   if(main_checkfds()) {
    259     errorf(&global, "out of file descriptors");
    260     return CURLE_FAILED_INIT;
    261   }
    262 
    263 #if defined(HAVE_SIGNAL) && defined(SIGPIPE)
    264   (void)signal(SIGPIPE, SIG_IGN);
    265 #endif
    266 
    267   /* Initialize memory tracking */
    268   memory_tracking_init();
    269 
    270   /* Initialize the curl library - do not call any libcurl functions before
    271      this point */
    272   result = main_init(&global);
    273   if(!result) {
    274     /* Start our curl operation */
    275     result = operate(&global, argc, argv);
    276 
    277     /* Perform the main cleanup */
    278     main_free(&global);
    279   }
    280 
    281 #ifdef _WIN32
    282   /* Flush buffers of all streams opened in write or update mode */
    283   fflush(NULL);
    284 #endif
    285 
    286 #ifdef __VMS
    287   vms_special_exit(result, vms_show);
    288 #else
    289   return (int)result;
    290 #endif
    291 }
    292 
    293 #if defined(_UNICODE) && !defined(UNDER_CE)
    294 #if defined(__GNUC__) || defined(__clang__)
    295 #pragma GCC diagnostic pop
    296 #endif
    297 #endif
    298 
    299 #endif /* ndef UNITTESTS */