1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2015, 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 #ifndef CURL_DISABLE_LIBCURL_OPTION
25 
26 #define ENABLE_CURLX_PRINTF
27 /* use our own printf() functions */
28 #include "curlx.h"
29 
30 #include "tool_cfgable.h"
31 #include "tool_easysrc.h"
32 #include "tool_msgs.h"
33 
34 #include "memdebug.h" /* keep this as LAST include */
35 
36 /* global variable definitions, for easy-interface source code generation */
37 
38 struct curl_slist *easysrc_decl = NULL; /* Variable declarations */
39 struct curl_slist *easysrc_data = NULL; /* Build slists, forms etc. */
40 struct curl_slist *easysrc_code = NULL; /* Setopt calls */
41 struct curl_slist *easysrc_toohard = NULL; /* Unconvertible setopt */
42 struct curl_slist *easysrc_clean = NULL;  /* Clean up allocated data */
43 int easysrc_form_count = 0;
44 int easysrc_slist_count = 0;
45 
46 static const char *const srchead[]={
47   "/********* Sample code generated by the curl command line tool **********",
48   " * All curl_easy_setopt() options are documented at:",
49   " * http://curl.haxx.se/libcurl/c/curl_easy_setopt.html",
50   " ************************************************************************/",
51   "#include <curl/curl.h>",
52   "",
53   "int main(int argc, char *argv[])",
54   "{",
55   "  CURLcode ret;",
56   "  CURL *hnd;",
57   NULL
58 };
59 /* easysrc_decl declarations come here */
60 /* easysrc_data initialisations come here */
61 /* easysrc_code statements come here */
62 static const char *const srchard[]={
63   "/* Here is a list of options the curl code used that cannot get generated",
64   "   as source easily. You may select to either not use them or implement",
65   "   them yourself.",
66   "",
67   NULL
68 };
69 static const char *const srcend[]={
70   "",
71   "  return (int)ret;",
72   "}",
73   "/**** End of sample code ****/",
74   NULL
75 };
76 
77 /* Clean up all source code if we run out of memory */
easysrc_free(void)78 static void easysrc_free(void)
79 {
80   curl_slist_free_all(easysrc_decl);
81   easysrc_decl = NULL;
82   curl_slist_free_all(easysrc_data);
83   easysrc_data = NULL;
84   curl_slist_free_all(easysrc_code);
85   easysrc_code = NULL;
86   curl_slist_free_all(easysrc_toohard);
87   easysrc_toohard = NULL;
88   curl_slist_free_all(easysrc_clean);
89   easysrc_clean = NULL;
90 }
91 
92 /* Add a source line to the main code or remarks */
easysrc_add(struct curl_slist ** plist,const char * line)93 CURLcode easysrc_add(struct curl_slist **plist, const char *line)
94 {
95   CURLcode ret = CURLE_OK;
96   struct curl_slist *list =
97     curl_slist_append(*plist, line);
98   if(!list) {
99     easysrc_free();
100     ret = CURLE_OUT_OF_MEMORY;
101   }
102   else
103     *plist = list;
104   return ret;
105 }
106 
easysrc_addf(struct curl_slist ** plist,const char * fmt,...)107 CURLcode easysrc_addf(struct curl_slist **plist, const char *fmt, ...)
108 {
109   CURLcode ret;
110   char *bufp;
111   va_list ap;
112   va_start(ap, fmt);
113   bufp = curlx_mvaprintf(fmt, ap);
114   va_end(ap);
115   if(! bufp) {
116     ret = CURLE_OUT_OF_MEMORY;
117   }
118   else {
119     ret = easysrc_add(plist, bufp);
120     curl_free(bufp);
121   }
122   return ret;
123 }
124 
125 #define CHKRET(v) do {CURLcode ret = (v); if(ret) return ret;} WHILE_FALSE
126 
easysrc_init(void)127 CURLcode easysrc_init(void)
128 {
129   CHKRET(easysrc_add(&easysrc_code,
130                      "hnd = curl_easy_init();"));
131   return CURLE_OK;
132 }
133 
easysrc_perform(void)134 CURLcode easysrc_perform(void)
135 {
136   /* Note any setopt calls which we could not convert */
137   if(easysrc_toohard) {
138     int i;
139     struct curl_slist *ptr;
140     const char *c;
141     CHKRET(easysrc_add(&easysrc_code, ""));
142     /* Preamble comment */
143     for(i=0; ((c = srchard[i]) != NULL); i++)
144       CHKRET(easysrc_add(&easysrc_code, c));
145     /* Each unconverted option */
146     for(ptr=easysrc_toohard; ptr; ptr = ptr->next)
147       CHKRET(easysrc_add(&easysrc_code, ptr->data));
148     CHKRET(easysrc_add(&easysrc_code, ""));
149     CHKRET(easysrc_add(&easysrc_code, "*/"));
150 
151     curl_slist_free_all(easysrc_toohard);
152     easysrc_toohard = NULL;
153   }
154 
155   CHKRET(easysrc_add(&easysrc_code, ""));
156   CHKRET(easysrc_add(&easysrc_code, "ret = curl_easy_perform(hnd);"));
157   CHKRET(easysrc_add(&easysrc_code, ""));
158 
159   return CURLE_OK;
160 }
161 
easysrc_cleanup(void)162 CURLcode easysrc_cleanup(void)
163 {
164   CHKRET(easysrc_add(&easysrc_code, "curl_easy_cleanup(hnd);"));
165   CHKRET(easysrc_add(&easysrc_code, "hnd = NULL;"));
166 
167   return CURLE_OK;
168 }
169 
dumpeasysrc(struct GlobalConfig * config)170 void dumpeasysrc(struct GlobalConfig *config)
171 {
172   struct curl_slist *ptr;
173   char *o = config->libcurl;
174 
175   if(o) {
176     FILE *out;
177     bool fopened = FALSE;
178     if(strcmp(o, "-")) {
179       out = fopen(o, FOPEN_WRITETEXT);
180       fopened = TRUE;
181     }
182     else
183       out = stdout;
184     if(!out)
185       warnf(config, "Failed to open %s to write libcurl code!\n", o);
186     else {
187       int i;
188       const char *c;
189 
190       for(i=0; ((c = srchead[i]) != NULL); i++)
191         fprintf(out, "%s\n", c);
192 
193       /* Declare variables used for complex setopt values */
194       for(ptr=easysrc_decl; ptr; ptr = ptr->next)
195         fprintf(out, "  %s\n", ptr->data);
196 
197       /* Set up complex values for setopt calls */
198       if(easysrc_data) {
199         fprintf(out, "\n");
200 
201         for(ptr=easysrc_data; ptr; ptr = ptr->next)
202           fprintf(out, "  %s\n", ptr->data);
203       }
204 
205       fprintf(out, "\n");
206       for(ptr=easysrc_code; ptr; ptr = ptr->next) {
207         if(ptr->data[0]) {
208           fprintf(out, "  %s\n", ptr->data);
209         }
210         else {
211           fprintf(out, "\n");
212         }
213       }
214 
215       for(ptr=easysrc_clean; ptr; ptr = ptr->next)
216         fprintf(out, "  %s\n", ptr->data);
217 
218       for(i=0; ((c = srcend[i]) != NULL); i++)
219         fprintf(out, "%s\n", c);
220 
221       if(fopened)
222         fclose(out);
223     }
224   }
225 
226   easysrc_free();
227 }
228 
229 #endif /* CURL_DISABLE_LIBCURL_OPTION */
230