initial load of upstream version 1.06.32
[xmlrpc-c] / examples / xmlrpc_inetd_server.c
1 /* A simple standalone XML-RPC server based on Abyss that processes a
2    single RPC from an existing TCP connection on Standard Input.
3
4    A typical example of where this would be useful is with an Inetd
5    "super server."
6
7    xmlrpc_sample_add_server.c is a server that does the same thing,
8    but you give it a TCP port number and it listens for TCP connecitons
9    and processes RPCs ad infinitum.
10 */
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <signal.h>
15 #ifndef WIN32
16 #include <unistd.h>
17 #endif
18
19 #include <xmlrpc-c/base.h>
20 #include <xmlrpc-c/abyss.h>
21 #include <xmlrpc-c/server.h>
22 #include <xmlrpc-c/server_abyss.h>
23
24 #include "config.h"  /* information about this build environment */
25
26
27 static void
28 setupSignalHandlers(void) {
29
30     /* In UNIX, when you try to write to a socket that has been closed
31        from the other end, your write fails, but you also get a SIGPIPE
32        signal.  That signal will kill you before you even have a chance
33        to see the write fail unless you catch, block, or ignore it.
34        If a client should connect to us and then disconnect before we've
35        sent our response, we see this socket-closed behavior.  We
36        obviously don't want to die just because a client didn't complete
37        an RPC, so we ignore SIGPIPE.
38     */
39     struct sigaction mysigaction;
40     
41     sigemptyset(&mysigaction.sa_mask);
42     mysigaction.sa_flags = 0;
43     mysigaction.sa_handler = SIG_IGN;
44     sigaction(SIGPIPE, &mysigaction, NULL);
45 }
46
47
48
49 static xmlrpc_value *
50 sample_add(xmlrpc_env *   const envP, 
51            xmlrpc_value * const paramArrayP,
52            void *         const userData ATTR_UNUSED) {
53     
54     xmlrpc_int x, y, z;
55
56     /* Parse our argument array. */
57     xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
58     if (envP->fault_occurred)
59         return NULL;
60
61     /* Add our two numbers. */
62     z = x + y;
63
64     /* Return our result. */
65     return xmlrpc_build_value(envP, "i", z);
66 }
67
68
69
70 int 
71 main(int           const argc, 
72      const char ** const argv) {
73
74     TServer abyssServer;
75     xmlrpc_registry * registryP;
76     xmlrpc_env env;
77
78     if (argc-1 != 0) {
79         fprintf(stderr, "There are no arguments.  You must supply a "
80                 "bound socket on which to listen for client connections "
81                 "as Standard Input\n");
82         if (argv) {} /* silence unused parameter warning */
83         exit(1);
84     }
85     xmlrpc_env_init(&env);
86
87     registryP = xmlrpc_registry_new(&env);
88
89     xmlrpc_registry_add_method(
90         &env, registryP, NULL, "sample.add", &sample_add, NULL);
91
92     ServerCreateNoAccept(&abyssServer, "XmlRpcServer", NULL, NULL);
93     
94     xmlrpc_server_abyss_set_handlers(&abyssServer, registryP);
95
96     setupSignalHandlers();
97
98     ServerRunConn(&abyssServer, STDIN_FILENO);
99         /* This reads the HTTP POST request from Standard Input and
100            executes the indicated RPC.
101         */
102
103     ServerFree(&abyssServer);
104
105     return 0;
106 }