Fix connection close.
[wrappi.git] / daemon / wrappid.c
1 /* wrappi
2  * Copyright (C) 2011-2012 Red Hat Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include <config.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <rpc/xdr.h>
25
26 #include "wrappi.h"
27 #include "../lib/proto-xdr.h"
28
29 static void main_loop (void);
30
31 static wrap_h *w;
32
33 int
34 main (int argc, char *argv[])
35 {
36   /* Command line XXX */
37
38   w = wrap_create ();
39   if (!w) {
40     fprintf (stderr, "could not allocate wrappi handle\n");
41     exit (EXIT_FAILURE);
42   }
43
44   wrap_connect (w);
45   if (wrap_error (w))
46     exit (EXIT_FAILURE);
47
48   main_loop ();
49
50   wrap_close (w);
51
52   exit (EXIT_SUCCESS);
53 }
54
55 static void
56 main_loop (void)
57 {
58   XDR xdr;
59   struct wrap_int_message_header hdr;
60   struct wrap_int_message_error err;
61   xdrproc_t args_xdrproc;
62   xdrproc_t ret_xdrproc;
63   void *argsv, *retv;
64
65   for (;;) {
66     /* Receive the request header. */
67     xdrstdio_create (&xdr, stdin, XDR_DECODE);
68     memset (&hdr, 0, sizeof hdr);
69     if (!wrap_int_xdr_message_header (&xdr, &hdr)) {
70       /* No error message here, because this is the expected
71        * exit place when the connection is closed.
72        */
73       xdr_destroy (&xdr);
74       return;
75     }
76
77     if (hdr.magic != WRAP_INT_PROTO_MAGIC) {
78       fprintf (stderr, "error in request: unexpected magic (%x)\n",
79                hdr.magic);
80       xdr_destroy (&xdr);
81       return;
82     }
83     if (hdr.protocol != WRAP_INT_PROTOCOL) {
84       fprintf (stderr, "error in request: unexpected protocol number (%d)\n",
85                hdr.protocol);
86       xdr_destroy (&xdr);
87       return;
88     }
89     if (hdr.type != WRAP_INT_PROTO_TYPE_REQUEST) {
90       fprintf (stderr, "error in request: unexpected type (%d)\n",
91                hdr.type);
92       xdr_destroy (&xdr);
93       return;
94     }
95
96     args_xdrproc = wrap_call_get_args_xdrproc (w, hdr.proc);
97     if (wrap_error (w)) {
98       xdr_destroy (&xdr);
99       return;
100     }
101     ret_xdrproc = wrap_call_get_ret_xdrproc (w, hdr.proc);
102     if (wrap_error (w)) {
103       xdr_destroy (&xdr);
104       return;
105     }
106
107     argsv = calloc (1, wrap_call_get_args_struct_size (w, hdr.proc));
108     if (argsv == NULL) {
109       perror ("malloc");
110       exit (EXIT_FAILURE);
111     }
112     retv = calloc (1, wrap_call_get_ret_struct_size (w, hdr.proc));
113     if (retv == NULL) {
114       perror ("malloc");
115       exit (EXIT_FAILURE);
116     }
117
118     /* Receive the arguments. */
119     if (!args_xdrproc (&xdr, argsv)) {
120       fprintf (stderr, "error receiving request arguments\n");
121       xdr_destroy (&xdr);
122       free (argsv);
123       free (retv);
124       return;
125     }
126
127     xdr_destroy (&xdr);
128
129     /* Call the underlying API. */
130     wrap_call (w, hdr.proc, argsv, retv);
131     free (argsv);
132
133     xdrstdio_create (&xdr, stdout, XDR_ENCODE);
134
135     if (! wrap_error (w)) {
136       /* Send back a normal reply. */
137       hdr.type = WRAP_INT_PROTO_TYPE_REPLY;
138
139       if (!wrap_int_xdr_message_header (&xdr, &hdr)) {
140         fprintf (stderr, "error sending reply header\n");
141         xdr_destroy (&xdr);
142         free (retv);
143         return;
144       }
145
146       if (!ret_xdrproc (&xdr, retv)) {
147         fprintf (stderr, "error sending reply return value\n");
148         xdr_destroy (&xdr);
149         free (retv);
150         return;
151       }
152     }
153     else {
154       /* Send back an error reply. */
155       err.error_message = (char *) wrap_get_error (w);
156       err.error_func = (char *) wrap_get_error_func (w);
157       err.error_errno = (char *) ""; /* XXX set this properly */
158
159       hdr.type = WRAP_INT_PROTO_TYPE_ERROR;
160
161       if (!wrap_int_xdr_message_header (&xdr, &hdr)) {
162         fprintf (stderr, "error sending reply error header\n");
163         xdr_destroy (&xdr);
164         free (retv);
165         return;
166       }
167
168       if (!wrap_int_xdr_message_error (&xdr, &err)) {
169         fprintf (stderr, "error sending reply error struct\n");
170         xdr_destroy (&xdr);
171         free (retv);
172         return;
173       }
174     }
175
176     free (retv);
177     xdr_destroy (&xdr);
178     xdr_free ((xdrproc_t) wrap_int_xdr_message_header, (void *) &hdr);
179   }
180 }