tool: Moved --trace and --verbose to the global config
[platform/upstream/curl.git] / src / tool_main.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2014, 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 http://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 #define ENABLE_CURLX_PRINTF
31 /* use our own printf() functions */
32 #include "curlx.h"
33
34 #include "tool_cfgable.h"
35 #include "tool_convert.h"
36 #include "tool_msgs.h"
37 #include "tool_operate.h"
38 #include "tool_panykey.h"
39 #include "tool_vms.h"
40 #include "tool_main.h"
41 #include "tool_libinfo.h"
42
43 /*
44  * This is low-level hard-hacking memory leak tracking and similar. Using
45  * the library level code from this client-side is ugly, but we do this
46  * anyway for convenience.
47  */
48 #include "memdebug.h" /* keep this as LAST include */
49
50 #ifdef __VMS
51 /*
52  * vms_show is a global variable, used in main() as parameter for
53  * function vms_special_exit() to allow proper curl tool exiting.
54  * Its value may be set in other tool_*.c source files thanks to
55  * forward declaration present in tool_vms.h
56  */
57 int vms_show = 0;
58 #endif
59
60 /* if we build a static library for unit tests, there is no main() function */
61 #ifndef UNITTESTS
62
63 /*
64  * Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
65  * open before starting to run.  Otherwise, the first three network
66  * sockets opened by curl could be used for input sources, downloaded data
67  * or error logs as they will effectively be stdin, stdout and/or stderr.
68  */
69 static void main_checkfds(void)
70 {
71 #ifdef HAVE_PIPE
72   int fd[2] = { STDIN_FILENO, STDIN_FILENO };
73   while(fd[0] == STDIN_FILENO ||
74         fd[0] == STDOUT_FILENO ||
75         fd[0] == STDERR_FILENO ||
76         fd[1] == STDIN_FILENO ||
77         fd[1] == STDOUT_FILENO ||
78         fd[1] == STDERR_FILENO)
79     if(pipe(fd) < 0)
80       return;   /* Out of handles. This isn't really a big problem now, but
81                    will be when we try to create a socket later. */
82   close(fd[0]);
83   close(fd[1]);
84 #endif
85 }
86
87 #ifdef CURLDEBUG
88 static void memory_tracking_init(void)
89 {
90   char *env;
91   /* if CURL_MEMDEBUG is set, this starts memory tracking message logging */
92   env = curlx_getenv("CURL_MEMDEBUG");
93   if(env) {
94     /* use the value as file name */
95     char fname[CURL_MT_LOGFNAME_BUFSIZE];
96     if(strlen(env) >= CURL_MT_LOGFNAME_BUFSIZE)
97       env[CURL_MT_LOGFNAME_BUFSIZE-1] = '\0';
98     strcpy(fname, env);
99     curl_free(env);
100     curl_memdebug(fname);
101     /* this weird stuff here is to make curl_free() get called
102        before curl_memdebug() as otherwise memory tracking will
103        log a free() without an alloc! */
104   }
105   /* if CURL_MEMLIMIT is set, this enables fail-on-alloc-number-N feature */
106   env = curlx_getenv("CURL_MEMLIMIT");
107   if(env) {
108     char *endptr;
109     long num = strtol(env, &endptr, 10);
110     if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
111       curl_memlimit(num);
112     curl_free(env);
113   }
114 }
115 #else
116 #  define memory_tracking_init() Curl_nop_stmt
117 #endif
118
119 /*
120  * This is the main global constructor for the app. Call this before
121  * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
122  * used, or havoc may be the result.
123  */
124 static CURLcode main_init(struct GlobalConfig *config)
125 {
126   CURLcode result = CURLE_OK;
127
128 #if defined(__DJGPP__) || defined(__GO32__)
129   /* stop stat() wasting time */
130   _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
131 #endif
132
133   /* Initialise the global config */
134   config->showerror = -1;             /* Will show errors */
135
136   /* Allocate the initial operate config */
137   config->first = config->last = malloc(sizeof(struct OperationConfig));
138   if(config->first) {
139     /* Perform the libcurl initialization */
140     result = curl_global_init(CURL_GLOBAL_DEFAULT);
141     if(!result) {
142       /* Get information about libcurl */
143       result = get_libcurl_info();
144
145       if(!result) {
146         /* Get a curl handle to use for all forthcoming curl transfers */
147         config->easy = curl_easy_init();
148         if(config->easy) {
149           /* Initialise the config */
150           config_init(config->first);
151           config->first->easy = config->easy;
152           config->first->global = config;
153         }
154         else {
155           helpf(stderr, "error initializing curl easy handle\n");
156           result = CURLE_FAILED_INIT;
157         }
158       }
159       else
160         helpf(stderr, "error retrieving curl library information\n");
161     }
162     else
163       helpf(stderr, "error initializing curl library\n");
164   }
165   else {
166     helpf(stderr, "error initializing curl\n");
167     result = CURLE_FAILED_INIT;
168   }
169
170   return result;
171 }
172
173 static void free_config_fields(struct GlobalConfig *config)
174 {
175   Curl_safefree(config->trace_dump);
176
177   if(config->trace_fopened && config->trace_stream)
178     fclose(config->trace_stream);
179   config->trace_stream = NULL;
180 }
181
182 /*
183  * This is the main global destructor for the app. Call this after
184  * _all_ libcurl usage is done.
185  */
186 static void main_free(struct GlobalConfig *config)
187 {
188   /* Cleanup the easy handle */
189   curl_easy_cleanup(config->easy);
190   config->easy = NULL;
191
192   /* Main cleanup */
193   curl_global_cleanup();
194   convert_cleanup();
195   metalink_cleanup();
196   free_config_fields(config);
197
198   /* Free the config structures */
199   config_free(config->last);
200   config->first = NULL;
201   config->last = NULL;
202 }
203
204 /*
205 ** curl tool main function.
206 */
207 int main(int argc, char *argv[])
208 {
209   CURLcode result = CURLE_OK;
210   struct GlobalConfig global;
211   memset(&global, 0, sizeof(global));
212
213   main_checkfds();
214
215 #if defined(HAVE_SIGNAL) && defined(SIGPIPE)
216   (void)signal(SIGPIPE, SIG_IGN);
217 #endif
218
219   /* Initialize memory tracking */
220   memory_tracking_init();
221
222   /* Initialize the curl library - do not call any libcurl functions before
223      this point */
224   result = main_init(&global);
225   if(!result) {
226     /* Start our curl operation */
227     result = operate(&global, argc, argv);
228
229 #ifdef __SYMBIAN32__
230     if(global.showerror)
231       tool_pressanykey();
232 #endif
233
234     /* Perform the main cleanup */
235     main_free(&global);
236   }
237
238 #ifdef __NOVELL_LIBC__
239   if(getenv("_IN_NETWARE_BASH_") == NULL)
240     tool_pressanykey();
241 #endif
242
243 #ifdef __VMS
244   vms_special_exit(res, vms_show);
245 #else
246   return (int)result;
247 #endif
248 }
249
250 #endif /* ndef UNITTESTS */