1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28 /*
29 * University Copyright- Copyright (c) 1982, 1986, 1988
30 * The Regents of the University of California
31 * All Rights Reserved
32 *
33 * University Acknowledgment- Portions of this document are derived from
34 * software developed by the University of California, Berkeley, and its
35 * contributors.
36 */
37
38 /*
39 * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
40 */
41 #include <stdio.h>
42 #include <string.h>
43 #include <rpc/types.h>
44 #include "rpc_parse.h"
45 #include "rpc_util.h"
46
47 extern void pdeclaration(char *, declaration *, int, char *);
48 extern void printarglist(proc_list *, char *, char *, char *);
49
50 static void write_program(definition *);
51 static void printbody(proc_list *);
52
53 static char RESULT[] = "clnt_res";
54
55 #define DEFAULT_TIMEOUT 25 /* in seconds */
56
57 void
write_stubs(void)58 write_stubs(void)
59 {
60 list *l;
61 definition *def;
62
63 f_print(fout,
64 "\n/* Default timeout can be changed using clnt_control() */\n");
65 f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
66 DEFAULT_TIMEOUT);
67 for (l = defined; l != NULL; l = l->next) {
68 def = (definition *) l->val;
69 if (def->def_kind == DEF_PROGRAM) {
70 write_program(def);
71 }
72 }
73 }
74
75 static void
write_program(definition * def)76 write_program(definition *def)
77 {
78 version_list *vp;
79 proc_list *proc;
80
81 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
82 for (proc = vp->procs; proc != NULL; proc = proc->next) {
83 f_print(fout, "\n");
84 if (mtflag == 0) {
85 ptype(proc->res_prefix, proc->res_type, 1);
86 f_print(fout, "*\n");
87 pvname(proc->proc_name, vp->vers_num);
88 printarglist(proc, RESULT, "clnt", "CLIENT *");
89 } else {
90 f_print(fout, "enum clnt_stat \n");
91 pvname(proc->proc_name, vp->vers_num);
92 printarglist(proc, RESULT, "clnt", "CLIENT *");
93
94 }
95 f_print(fout, "{\n");
96 printbody(proc);
97
98 f_print(fout, "}\n");
99 }
100 }
101 }
102
103 /*
104 * Writes out declarations of procedure's argument list.
105 * In either ANSI C style, in one of old rpcgen style (pass by reference),
106 * or new rpcgen style (multiple arguments, pass by value);
107 */
108
109 /* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
110
111 void
printarglist(proc_list * proc,char * result,char * addargname,char * addargtype)112 printarglist(proc_list *proc, char *result, char *addargname, char *addargtype)
113 {
114 bool_t oneway = streq(proc->res_type, "oneway");
115 decl_list *l;
116
117 if (!newstyle) {
118 /* old style: always pass argument by reference */
119 if (Cflag) { /* C++ style heading */
120 f_print(fout, "(");
121 ptype(proc->args.decls->decl.prefix,
122 proc->args.decls->decl.type, 1);
123
124 if (mtflag) { /* Generate result field */
125 f_print(fout, "*argp, ");
126 if (!oneway) {
127 ptype(proc->res_prefix,
128 proc->res_type, 1);
129 f_print(fout, "*%s, ", result);
130 }
131 f_print(fout, "%s%s)\n",
132 addargtype, addargname);
133 } else
134 f_print(fout, "*argp, %s%s)\n",
135 addargtype, addargname);
136 } else {
137 if (!mtflag)
138 f_print(fout, "(argp, %s)\n", addargname);
139 else {
140 f_print(fout, "(argp, ");
141 if (!oneway) {
142 f_print(fout, "%s, ",
143 result);
144 }
145 f_print(fout, "%s)\n",
146 addargname);
147 }
148 f_print(fout, "\t");
149 ptype(proc->args.decls->decl.prefix,
150 proc->args.decls->decl.type, 1);
151 f_print(fout, "*argp;\n");
152 if (mtflag && !oneway) {
153 f_print(fout, "\t");
154 ptype(proc->res_prefix, proc->res_type, 1);
155 f_print(fout, "*%s;\n", result);
156 }
157 }
158 } else if (streq(proc->args.decls->decl.type, "void")) {
159 /* newstyle, 0 argument */
160 if (mtflag) {
161 f_print(fout, "(");
162
163 if (Cflag) {
164 if (!oneway) {
165 ptype(proc->res_prefix,
166 proc->res_type, 1);
167 f_print(fout, "*%s, ", result);
168 }
169 f_print(fout, "%s%s)\n",
170 addargtype, addargname);
171 } else
172 f_print(fout, "(%s)\n", addargname);
173
174 } else
175 if (Cflag)
176 f_print(fout, "(%s%s)\n", addargtype, addargname);
177 else
178 f_print(fout, "(%s)\n", addargname);
179 } else {
180 /* new style, 1 or multiple arguments */
181 if (!Cflag) {
182 f_print(fout, "(");
183 for (l = proc->args.decls; l != NULL; l = l->next)
184 f_print(fout, "%s, ", l->decl.name);
185 if (mtflag && !oneway)
186 f_print(fout, "%s, ", result);
187
188 f_print(fout, "%s)\n", addargname);
189 for (l = proc->args.decls; l != NULL; l = l->next) {
190 pdeclaration(proc->args.argname,
191 &l->decl, 1, ";\n");
192 }
193 if (mtflag && !oneway) {
194 f_print(fout, "\t");
195 ptype(proc->res_prefix, proc->res_type, 1);
196 f_print(fout, "*%s;\n", result);
197 }
198
199 } else { /* C++ style header */
200 f_print(fout, "(");
201 for (l = proc->args.decls; l != NULL; l = l->next) {
202 pdeclaration(proc->args.argname, &l->decl, 0,
203 ", ");
204 }
205 if (mtflag && !oneway) {
206 ptype(proc->res_prefix, proc->res_type, 1);
207 f_print(fout, "*%s, ", result);
208
209 }
210 f_print(fout, "%s%s)\n", addargtype, addargname);
211 }
212 }
213
214 if (!Cflag)
215 f_print(fout, "\t%s%s;\n", addargtype, addargname);
216 }
217
218
219
220 static char *
ampr(char * type)221 ampr(char *type)
222 {
223 if (isvectordef(type, REL_ALIAS)) {
224 return ("");
225 } else {
226 return ("&");
227 }
228 }
229
230 static void
printbody(proc_list * proc)231 printbody(proc_list *proc)
232 {
233 decl_list *l;
234 bool_t args2 = (proc->arg_num > 1);
235 bool_t oneway = streq(proc->res_type, "oneway");
236
237 /*
238 * For new style with multiple arguments, need a structure in which
239 * to stuff the arguments.
240 */
241 if (newstyle && args2) {
242 f_print(fout, "\t%s", proc->args.argname);
243 f_print(fout, " arg;\n");
244 }
245 if (!oneway) {
246 if (!mtflag) {
247 f_print(fout, "\tstatic ");
248 if (streq(proc->res_type, "void")) {
249 f_print(fout, "char ");
250 } else {
251 ptype(proc->res_prefix, proc->res_type, 0);
252 }
253 f_print(fout, "%s;\n", RESULT);
254 f_print(fout, "\n");
255 f_print(fout,
256 "\t(void) memset(%s%s, 0, sizeof (%s));\n",
257 ampr(proc->res_type), RESULT, RESULT);
258
259 }
260 if (newstyle && !args2 &&
261 (streq(proc->args.decls->decl.type, "void"))) {
262 /* newstyle, 0 arguments */
263
264 if (mtflag)
265 f_print(fout, "\t return ");
266 else
267 f_print(fout, "\t if ");
268
269 f_print(fout,
270 "(clnt_call(clnt, %s,\n\t\t(xdrproc_t)xdr_void, ",
271 proc->proc_name);
272 f_print(fout,
273 "NULL,\n\t\t(xdrproc_t)xdr_%s, "
274 "(caddr_t)%s%s,",
275 stringfix(proc->res_type),
276 (mtflag)?"":ampr(proc->res_type),
277 RESULT);
278
279 if (mtflag)
280 f_print(fout, "\n\t\tTIMEOUT));\n");
281 else
282 f_print(fout,
283 "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
284
285 } else if (newstyle && args2) {
286 /*
287 * Newstyle, multiple arguments
288 * stuff arguments into structure
289 */
290 for (l = proc->args.decls; l != NULL; l = l->next) {
291 f_print(fout, "\targ.%s = %s;\n",
292 l->decl.name, l->decl.name);
293 }
294 if (mtflag)
295 f_print(fout, "\treturn ");
296 else
297 f_print(fout, "\tif ");
298 f_print(fout,
299 "(clnt_call(clnt, %s,\n\t\t(xdrproc_t)xdr_%s",
300 proc->proc_name, proc->args.argname);
301 f_print(fout,
302 ", (caddr_t)&arg,\n\t\t(xdrproc_t)xdr_%s, "
303 "(caddr_t)%s%s,",
304 stringfix(proc->res_type),
305 (mtflag)?"":ampr(proc->res_type),
306 RESULT);
307 if (mtflag)
308 f_print(fout, "\n\t\tTIMEOUT));\n");
309 else
310 f_print(fout,
311 "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
312 } else { /* single argument, new or old style */
313 if (!mtflag)
314 f_print(fout,
315 "\tif (clnt_call(clnt, "
316 "%s,\n\t\t(xdrproc_t)xdr_%s, "
317 "(caddr_t)%s%s,\n\t\t(xdrproc_t)xdr_%s, "
318 "(caddr_t)%s%s,\n\t\tTIMEOUT) != "
319 "RPC_SUCCESS) {\n",
320 proc->proc_name,
321 stringfix(proc->args.decls->decl.type),
322 (newstyle ? "&" : ""),
323 (newstyle ?
324 proc->args.decls->decl.name :
325 "argp"),
326 stringfix(proc->res_type),
327 ampr(proc->res_type),
328 RESULT);
329 else
330 f_print(fout,
331 "\treturn (clnt_call(clnt, "
332 "%s,\n\t\t(xdrproc_t)xdr_%s, "
333 "(caddr_t)%s%s,\n\t\t(xdrproc_t)xdr_%s, "
334 "(caddr_t)%s%s,\n\t\tTIMEOUT));\n",
335 proc->proc_name,
336 stringfix(proc->args.decls->decl.type),
337 (newstyle ? "&" : ""),
338 (newstyle ?
339 proc->args.decls->decl.name :
340 "argp"),
341 stringfix(proc->res_type), "",
342 RESULT);
343 }
344 if (!mtflag) {
345 f_print(fout, "\t\treturn (NULL);\n");
346 f_print(fout, "\t}\n");
347
348 if (streq(proc->res_type, "void")) {
349 f_print(fout, "\treturn ((void *)%s%s);\n",
350 ampr(proc->res_type), RESULT);
351 } else {
352 f_print(fout, "\treturn (%s%s);\n",
353 ampr(proc->res_type), RESULT);
354 }
355 }
356 } else {
357 /* oneway call */
358 if (!mtflag) {
359 f_print(fout, "\tstatic enum clnt_stat ");
360 f_print(fout, "%s;\n", RESULT);
361 f_print(fout, "\n");
362 f_print(fout,
363 "\t(void) memset(&%s, 0, sizeof (%s));\n",
364 RESULT, RESULT);
365
366 }
367 if (newstyle && !args2 &&
368 (streq(proc->args.decls->decl.type, "void"))) {
369 /* newstyle, 0 arguments */
370
371 if (mtflag)
372 f_print(fout, "\t return (");
373 else
374 f_print(fout, "\t if ((%s = ", RESULT);
375
376 f_print(fout,
377 "clnt_send(clnt, %s,\n\t\t(xdrproc_t)xdr_void, ",
378 proc->proc_name);
379 f_print(fout, "NULL)");
380
381 if (mtflag)
382 f_print(fout, ");\n");
383 else
384 f_print(fout, ") != RPC_SUCCESS) {\n");
385
386 } else if (newstyle && args2) {
387 /*
388 * Newstyle, multiple arguments
389 * stuff arguments into structure
390 */
391 for (l = proc->args.decls; l != NULL; l = l->next) {
392 f_print(fout, "\targ.%s = %s;\n",
393 l->decl.name, l->decl.name);
394 }
395 if (mtflag)
396 f_print(fout, "\treturn (");
397 else
398 f_print(fout, "\tif ((%s =", RESULT);
399 f_print(fout,
400 "clnt_send(clnt, %s,\n\t\t(xdrproc_t)xdr_%s",
401 proc->proc_name, proc->args.argname);
402 f_print(fout,
403 ", (caddr_t)&arg)");
404 if (mtflag)
405 f_print(fout, ");\n");
406 else
407 f_print(fout, ") != RPC_SUCCESS) {\n");
408 } else { /* single argument, new or old style */
409 if (!mtflag)
410 f_print(fout,
411 "\tif ((%s = clnt_send(clnt, "
412 "%s,\n\t\t(xdrproc_t)xdr_%s, "
413 "(caddr_t)%s%s)) != RPC_SUCCESS) {\n",
414 RESULT,
415 proc->proc_name,
416 stringfix(proc->args.decls->decl.type),
417 (newstyle ? "&" : ""),
418 (newstyle ?
419 proc->args.decls->decl.name :
420 "argp"));
421 else
422
423 f_print(fout,
424 "\treturn (clnt_send(clnt, "
425 "%s,\n\t\t(xdrproc_t)xdr_%s, "
426 "(caddr_t)%s%s));\n",
427 proc->proc_name,
428 stringfix(proc->args.decls->decl.type),
429 (newstyle ? "&" : ""),
430 (newstyle ?
431 proc->args.decls->decl.name :
432 "argp"));
433 }
434 if (!mtflag) {
435 f_print(fout, "\t\treturn (NULL);\n");
436 f_print(fout, "\t}\n");
437
438 f_print(fout, "\treturn ((void *)&%s);\n",
439 RESULT);
440 }
441 }
442 }
443