1 /* Transport some XML to a server and get the response back, as if doing
11 #include "config.h" /* information about this build environment */
12 #include "casprintf.h"
13 #include "mallocvar.h"
14 #include "cmdline_parser.h"
16 #include "xmlrpc-c/base.h"
17 #include "xmlrpc-c/client.h"
19 #define NAME "xmlrpc_transport command line program"
24 const char * username;
25 const char * password;
26 const char * transport;
27 /* Name of XML transport he wants to use. NULL if he has no
35 die_if_fault_occurred (xmlrpc_env * const envP) {
36 if (envP->fault_occurred) {
37 fprintf(stderr, "Error: %s (%d)\n",
38 envP->fault_string, envP->fault_code);
45 static void GNU_PRINTF_ATTR(2,3)
46 setError(xmlrpc_env * const envP, const char format[], ...) {
48 const char * faultString;
50 va_start(args, format);
52 cvasprintf(&faultString, format, args);
55 xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, faultString);
63 processArguments(xmlrpc_env * const envP,
64 cmdlineParser const cp,
65 struct cmdlineInfo * const cmdlineP) {
67 if (cmd_argumentCount(cp) < 1)
68 setError(envP, "Not enough arguments. Need a URL.");
70 cmdlineP->url = cmd_getArgument(cp, 0);
77 parseCommandLine(xmlrpc_env * const envP,
79 const char ** const argv,
80 struct cmdlineInfo * const cmdlineP) {
82 cmdlineParser const cp = cmd_createOptionParser();
86 cmd_defineOption(cp, "transport", OPTTYPE_STRING);
87 cmd_defineOption(cp, "username", OPTTYPE_STRING);
88 cmd_defineOption(cp, "password", OPTTYPE_STRING);
90 cmd_processOptions(cp, argc, argv, &error);
93 setError(envP, "Command syntax error. %s", error);
96 cmdlineP->username = cmd_getOptionValueString(cp, "username");
97 cmdlineP->password = cmd_getOptionValueString(cp, "password");
99 if (cmdlineP->username && !cmdlineP->password)
100 setError(envP, "When you specify -username, you must also "
101 "specify -password.");
103 cmdlineP->transport = cmd_getOptionValueString(cp, "transport");
105 processArguments(envP, cp, cmdlineP);
108 cmd_destroyOptionParser(cp);
114 freeCmdline(struct cmdlineInfo const cmdline) {
116 strfree(cmdline.url);
117 if (cmdline.username)
118 strfree(cmdline.username);
119 if (cmdline.password)
120 strfree(cmdline.password);
121 if (cmdline.transport)
122 strfree(cmdline.transport);
128 computeUrl(const char * const urlArg,
129 const char ** const urlP) {
131 if (strstr(urlArg, "://") != 0) {
132 *urlP = strdup(urlArg);
134 casprintf(urlP, "http://%s/RPC2", urlArg);
141 doCall(xmlrpc_env * const envP,
142 const char * const transport,
143 const xmlrpc_server_info * const serverInfoP,
144 xmlrpc_mem_block * const callXmlP,
145 xmlrpc_mem_block ** const respXmlPP) {
147 struct xmlrpc_clientparms clientparms;
149 clientparms.transport = transport;
151 clientparms.transportparmsP = NULL;
152 clientparms.transportparm_size = 0;
154 xmlrpc_client_init2(envP, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION,
155 &clientparms, XMLRPC_CPSIZE(transportparm_size));
156 if (!envP->fault_occurred) {
157 xmlrpc_client_transport_call(envP, NULL, serverInfoP,
158 callXmlP, respXmlPP);
160 xmlrpc_client_cleanup();
167 createServerInfo(xmlrpc_env * const envP,
168 const char * const serverUrl,
169 const char * const userName,
170 const char * const password,
171 xmlrpc_server_info ** const serverInfoPP) {
173 xmlrpc_server_info * serverInfoP;
175 serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
176 if (!envP->fault_occurred) {
178 xmlrpc_server_info_set_basic_auth(
179 envP, serverInfoP, userName, password);
182 *serverInfoPP = serverInfoP;
188 readFile(xmlrpc_env * const envP,
190 xmlrpc_mem_block ** const fileContentsPP) {
192 xmlrpc_mem_block * fileContentsP;
194 fileContentsP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
196 while (!envP->fault_occurred && !feof(ifP)) {
200 bytesRead = fread(buffer, 1, sizeof(buffer), ifP);
201 XMLRPC_MEMBLOCK_APPEND(char, envP,
202 fileContentsP, buffer, bytesRead);
204 if (envP->fault_occurred)
205 XMLRPC_MEMBLOCK_FREE(char, fileContentsP);
207 *fileContentsPP = fileContentsP;
213 writeFile(xmlrpc_env * const envP,
215 xmlrpc_mem_block * const fileContentsP) {
221 while (!envP->fault_occurred &&
222 totalWritten < XMLRPC_MEMBLOCK_SIZE(char, fileContentsP)) {
225 bytesWritten = fwrite(
226 XMLRPC_MEMBLOCK_CONTENTS(char, fileContentsP) + totalWritten,
228 XMLRPC_MEMBLOCK_SIZE(char, fileContentsP) - totalWritten,
231 if (bytesWritten < 1)
232 xmlrpc_env_set_fault_formatted(
233 envP, XMLRPC_INTERNAL_ERROR,
234 "Error writing output");
236 totalWritten -= bytesWritten;
244 const char ** const argv) {
246 struct cmdlineInfo cmdline;
248 xmlrpc_mem_block * callXmlP;
249 xmlrpc_mem_block * respXmlP;
251 xmlrpc_server_info * serverInfoP;
253 xmlrpc_env_init(&env);
255 parseCommandLine(&env, argc, argv, &cmdline);
256 die_if_fault_occurred(&env);
258 computeUrl(cmdline.url, &url);
260 createServerInfo(&env, url, cmdline.username, cmdline.password,
262 die_if_fault_occurred(&env);
264 fprintf(stderr, "Reading call data from Standard Input...\n");
266 readFile(&env, stdin, &callXmlP);
267 die_if_fault_occurred(&env);
269 fprintf(stderr, "Making call...\n");
271 doCall(&env, cmdline.transport, serverInfoP, callXmlP,
273 die_if_fault_occurred(&env);
275 fprintf(stderr, "Writing response data to Standard Output\n");
276 writeFile(&env, stdout, respXmlP);
277 die_if_fault_occurred(&env);
279 XMLRPC_MEMBLOCK_FREE(char, callXmlP);
280 XMLRPC_MEMBLOCK_FREE(char, respXmlP);
284 freeCmdline(cmdline);
286 xmlrpc_env_clean(&env);