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