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