1 | /* |
2 | * From: @(#)rpc_sample.c 1.1 90/08/30 |
3 | * |
4 | * Copyright (c) 2010, Oracle America, Inc. |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are |
7 | * met: |
8 | * |
9 | * * Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * * Redistributions in binary form must reproduce the above |
12 | * copyright notice, this list of conditions and the following |
13 | * disclaimer in the documentation and/or other materials |
14 | * provided with the distribution. |
15 | * * Neither the name of the "Oracle America, Inc." nor the names of its |
16 | * contributors may be used to endorse or promote products derived |
17 | * from this software without specific prior written permission. |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
22 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
23 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
24 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
26 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | */ |
32 | |
33 | /* |
34 | * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler |
35 | */ |
36 | |
37 | #include <stdio.h> |
38 | #include <string.h> |
39 | #include "rpc_parse.h" |
40 | #include "rpc_util.h" |
41 | #include "proto.h" |
42 | |
43 | |
44 | static const char RQSTP[] = "rqstp" ; |
45 | |
46 | static void write_sample_client (const char *program_name, version_list * vp); |
47 | static void write_sample_server (definition * def); |
48 | static void return_type (proc_list * plist); |
49 | |
50 | |
51 | void |
52 | write_sample_svc (definition * def) |
53 | { |
54 | |
55 | if (def->def_kind != DEF_PROGRAM) |
56 | return; |
57 | write_sample_server (def); |
58 | } |
59 | |
60 | |
61 | int |
62 | write_sample_clnt (definition * def) |
63 | { |
64 | version_list *vp; |
65 | int count = 0; |
66 | |
67 | if (def->def_kind != DEF_PROGRAM) |
68 | return 0; |
69 | /* generate sample code for each version */ |
70 | for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) |
71 | { |
72 | write_sample_client (def->def_name, vp); |
73 | ++count; |
74 | } |
75 | return count; |
76 | } |
77 | |
78 | |
79 | static void |
80 | write_sample_client (const char *program_name, version_list * vp) |
81 | { |
82 | proc_list *proc; |
83 | int i; |
84 | decl_list *l; |
85 | |
86 | f_print (fout, "\n\nvoid\n" ); |
87 | pvname (program_name, vp->vers_num); |
88 | if (Cflag) |
89 | f_print (fout, "(char *host)\n{\n" ); |
90 | else |
91 | f_print (fout, "(host)\nchar *host;\n{\n" ); |
92 | f_print (fout, "\tCLIENT *clnt;\n" ); |
93 | |
94 | i = 0; |
95 | for (proc = vp->procs; proc != NULL; proc = proc->next) |
96 | { |
97 | f_print (fout, "\t" ); |
98 | ++i; |
99 | if (mtflag) |
100 | { |
101 | f_print (fout, "enum clnt_stat retval_%d;\n\t" , i); |
102 | ptype (proc->res_prefix, proc->res_type, 1); |
103 | if (!streq (proc->res_type, "void" )) |
104 | f_print (fout, "result_%d;\n" , i); |
105 | else |
106 | fprintf (fout, "*result_%d;\n" , i); |
107 | } |
108 | else |
109 | { |
110 | ptype (proc->res_prefix, proc->res_type, 1); |
111 | f_print (fout, " *result_%d;\n" , i); |
112 | } |
113 | /* print out declarations for arguments */ |
114 | if (proc->arg_num < 2 && !newstyle) |
115 | { |
116 | f_print (fout, "\t" ); |
117 | if (!streq (proc->args.decls->decl.type, "void" )) |
118 | { |
119 | ptype (proc->args.decls->decl.prefix, |
120 | proc->args.decls->decl.type, 1); |
121 | f_print (fout, " " ); |
122 | } |
123 | else |
124 | f_print (fout, "char *" ); /* cannot have "void" type */ |
125 | pvname (proc->proc_name, vp->vers_num); |
126 | f_print (fout, "_arg;\n" ); |
127 | } |
128 | else if (!streq (proc->args.decls->decl.type, "void" )) |
129 | { |
130 | for (l = proc->args.decls; l != NULL; l = l->next) |
131 | { |
132 | f_print (fout, "\t" ); |
133 | ptype (l->decl.prefix, l->decl.type, 1); |
134 | if (strcmp (l->decl.type, "string" ) == 1) |
135 | f_print (fout, " " ); |
136 | pvname (proc->proc_name, vp->vers_num); |
137 | f_print (fout, "_%s;\n" , l->decl.name); |
138 | } |
139 | } |
140 | } |
141 | |
142 | /* generate creation of client handle */ |
143 | f_print(fout, "\n#ifndef\tDEBUG\n" ); |
144 | f_print (fout, "\tclnt = clnt_create (host, %s, %s, \"%s\");\n" , |
145 | program_name, vp->vers_name, tirpcflag ? "netpath" : "udp" ); |
146 | f_print (fout, "\tif (clnt == NULL) {\n" ); |
147 | f_print (fout, "\t\tclnt_pcreateerror (host);\n" ); |
148 | f_print (fout, "\t\texit (1);\n\t}\n" ); |
149 | f_print(fout, "#endif\t/* DEBUG */\n\n" ); |
150 | |
151 | /* generate calls to procedures */ |
152 | i = 0; |
153 | for (proc = vp->procs; proc != NULL; proc = proc->next) |
154 | { |
155 | if (mtflag) |
156 | f_print(fout, "\tretval_%d = " ,++i); |
157 | else |
158 | f_print (fout, "\tresult_%d = " , ++i); |
159 | pvname (proc->proc_name, vp->vers_num); |
160 | if (proc->arg_num < 2 && !newstyle) |
161 | { |
162 | f_print (fout, "(" ); |
163 | if (streq (proc->args.decls->decl.type, "void" ))/* cast to void* */ |
164 | f_print (fout, "(void*)" ); |
165 | f_print (fout, "&" ); |
166 | pvname (proc->proc_name, vp->vers_num); |
167 | if (mtflag) |
168 | f_print(fout, "_arg, &result_%d, clnt);\n" , i); |
169 | else |
170 | f_print (fout, "_arg, clnt);\n" ); |
171 | } |
172 | else if (streq (proc->args.decls->decl.type, "void" )) |
173 | { |
174 | if (mtflag) |
175 | f_print (fout, "(&result_%d, clnt);\n" , i); |
176 | else |
177 | f_print (fout, "(clnt);\n" ); |
178 | } |
179 | else |
180 | { |
181 | f_print (fout, "(" ); |
182 | for (l = proc->args.decls; l != NULL; l = l->next) |
183 | { |
184 | pvname (proc->proc_name, vp->vers_num); |
185 | f_print (fout, "_%s, " , l->decl.name); |
186 | } |
187 | if (mtflag) |
188 | f_print(fout, "&result_%d, " , i); |
189 | f_print (fout, "clnt);\n" ); |
190 | } |
191 | if (mtflag) |
192 | { |
193 | f_print(fout, "\tif (retval_%d != RPC_SUCCESS) {\n" , i); |
194 | } |
195 | else |
196 | { |
197 | f_print(fout, "\tif (result_%d == (" , i); |
198 | ptype(proc->res_prefix, proc->res_type, 1); |
199 | f_print(fout, "*) NULL) {\n" ); |
200 | } |
201 | f_print(fout, "\t\tclnt_perror (clnt, \"call failed\");\n" ); |
202 | f_print(fout, "\t}\n" ); |
203 | } |
204 | |
205 | f_print (fout, "#ifndef\tDEBUG\n" ); |
206 | f_print (fout, "\tclnt_destroy (clnt);\n" ); |
207 | f_print (fout, "#endif\t /* DEBUG */\n" ); |
208 | f_print (fout, "}\n" ); |
209 | } |
210 | |
211 | static void |
212 | write_sample_server (definition * def) |
213 | { |
214 | version_list *vp; |
215 | proc_list *proc; |
216 | |
217 | for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) |
218 | { |
219 | for (proc = vp->procs; proc != NULL; proc = proc->next) |
220 | { |
221 | f_print (fout, "\n" ); |
222 | if (!mtflag) |
223 | { |
224 | return_type (proc); |
225 | f_print (fout, "*\n" ); |
226 | } |
227 | else |
228 | f_print (fout, "bool_t\n" ); |
229 | if (Cflag || mtflag) |
230 | pvname_svc (proc->proc_name, vp->vers_num); |
231 | else |
232 | pvname(proc->proc_name, vp->vers_num); |
233 | printarglist(proc, "result" , RQSTP, "struct svc_req *" ); |
234 | f_print(fout, "{\n" ); |
235 | if (!mtflag) |
236 | { |
237 | f_print(fout, "\tstatic " ); |
238 | if(!streq(proc->res_type, "void" )) |
239 | return_type(proc); |
240 | else |
241 | f_print(fout, "char *" ); |
242 | /* cannot have void type */ |
243 | /* f_print(fout, " result;\n", proc->res_type); */ |
244 | f_print(fout, " result;\n" ); |
245 | } |
246 | else |
247 | f_print(fout, "\tbool_t retval;\n" ); |
248 | fprintf (fout, "\n\t/*\n\t * insert server code here\n\t */\n\n" ); |
249 | |
250 | if (!mtflag) |
251 | { |
252 | if (!streq(proc->res_type, "void" )) |
253 | f_print(fout, "\treturn &result;\n}\n" ); |
254 | else /* cast back to void * */ |
255 | f_print(fout, "\treturn (void *) &result;\n}\n" ); |
256 | } |
257 | else |
258 | f_print(fout, "\treturn retval;\n}\n" ); |
259 | } |
260 | |
261 | /* put in sample freeing routine */ |
262 | if (mtflag) |
263 | { |
264 | f_print(fout, "\nint\n" ); |
265 | pvname(def->def_name, vp->vers_num); |
266 | if (Cflag) |
267 | f_print(fout,"_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)\n" ); |
268 | else |
269 | { |
270 | f_print(fout,"_freeresult (transp, xdr_result, result)\n" ); |
271 | f_print(fout,"\tSVCXPRT *transp;\n" ); |
272 | f_print(fout,"\txdrproc_t xdr_result;\n" ); |
273 | f_print(fout,"\tcaddr_t result;\n" ); |
274 | } |
275 | f_print(fout, "{\n" ); |
276 | f_print(fout, "\txdr_free (xdr_result, result);\n" ); |
277 | f_print(fout, |
278 | "\n\t/*\n\t * Insert additional freeing code here, if needed\n\t */\n" ); |
279 | f_print(fout, "\n\treturn 1;\n}\n" ); |
280 | } |
281 | } |
282 | } |
283 | |
284 | |
285 | |
286 | static void |
287 | return_type (proc_list * plist) |
288 | { |
289 | ptype (plist->res_prefix, plist->res_type, 1); |
290 | } |
291 | |
292 | void |
293 | add_sample_msg (void) |
294 | { |
295 | f_print (fout, "/*\n" ); |
296 | f_print (fout, " * This is sample code generated by rpcgen.\n" ); |
297 | f_print (fout, " * These are only templates and you can use them\n" ); |
298 | f_print (fout, " * as a guideline for developing your own functions.\n" ); |
299 | f_print (fout, " */\n\n" ); |
300 | } |
301 | |
302 | void |
303 | write_sample_clnt_main (void) |
304 | { |
305 | list *l; |
306 | definition *def; |
307 | version_list *vp; |
308 | |
309 | f_print (fout, "\n\n" ); |
310 | if (Cflag) |
311 | f_print (fout, "int\nmain (int argc, char *argv[])\n{\n" ); |
312 | else |
313 | f_print (fout, "int\nmain (argc, argv)\nint argc;\nchar *argv[];\n{\n" ); |
314 | |
315 | f_print (fout, "\tchar *host;" ); |
316 | f_print (fout, "\n\n\tif (argc < 2) {" ); |
317 | f_print (fout, "\n\t\tprintf (\"usage: %%s server_host\\n\", argv[0]);\n" ); |
318 | f_print (fout, "\t\texit (1);\n\t}" ); |
319 | f_print (fout, "\n\thost = argv[1];\n" ); |
320 | |
321 | for (l = defined; l != NULL; l = l->next) |
322 | { |
323 | def = l->val; |
324 | if (def->def_kind != DEF_PROGRAM) |
325 | { |
326 | continue; |
327 | } |
328 | for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) |
329 | { |
330 | f_print (fout, "\t" ); |
331 | pvname (def->def_name, vp->vers_num); |
332 | f_print (fout, " (host);\n" ); |
333 | } |
334 | } |
335 | f_print (fout, "exit (0);\n}\n" ); |
336 | } |
337 | |