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_sample.c, Sample client-server code outputter
40 * for the RPC protocol compiler
41 */
42
43 #include <stdio.h>
44 #include <string.h>
45 #include "rpc_parse.h"
46 #include "rpc_util.h"
47
48
49 static char RQSTP[] = "rqstp";
50
51 extern void printarglist(proc_list *, char *, char *, char *);
52
53 static void write_sample_client(char *, version_list *);
54 static void write_sample_server(definition *);
55 static void return_type(proc_list *);
56
57 void
write_sample_svc(definition * def)58 write_sample_svc(definition *def)
59 {
60 if (def->def_kind != DEF_PROGRAM)
61 return;
62 write_sample_server(def);
63 }
64
65 int
write_sample_clnt(definition * def)66 write_sample_clnt(definition *def)
67 {
68 version_list *vp;
69 int count = 0;
70
71 if (def->def_kind != DEF_PROGRAM)
72 return (0);
73 /* generate sample code for each version */
74 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
75 write_sample_client(def->def_name, vp);
76 ++count;
77 }
78 return (count);
79 }
80
81 static void
write_sample_client(char * program_name,version_list * vp)82 write_sample_client(char *program_name, version_list *vp)
83 {
84 proc_list *proc;
85 int i;
86 decl_list *l;
87
88 f_print(fout, "\n\nvoid\n");
89 pvname(program_name, vp->vers_num);
90 if (Cflag)
91 f_print(fout, "(char *host)\n{\n");
92 else
93 f_print(fout, "(host)\n\tchar *host;\n{\n");
94 f_print(fout, "\tCLIENT *clnt;\n");
95
96 i = 0;
97 for (proc = vp->procs; proc != NULL; proc = proc->next) {
98 f_print(fout, "\t");
99 if (mtflag) {
100 f_print(fout, "enum clnt_stat retval_%d;\n", ++i);
101 if (!streq(proc->res_type, "oneway")) {
102 f_print(fout, "\t");
103 if (!streq(proc->res_type, "void"))
104 ptype(proc->res_prefix,
105 proc->res_type, 1);
106 else
107 f_print(fout, "void *");
108 f_print(fout, "result_%d;\n", i);
109 }
110 } else {
111 ptype(proc->res_prefix, proc->res_type, 1);
112 f_print(fout, " *result_%d;\n", ++i);
113 }
114 /* print out declarations for arguments */
115 if (proc->arg_num < 2 && !newstyle) {
116 f_print(fout, "\t");
117 if (!streq(proc->args.decls->decl.type, "void"))
118 ptype(proc->args.decls->decl.prefix,
119 proc->args.decls->decl.type, 1);
120 else
121 /* cannot have "void" type */
122 f_print(fout, "char * ");
123 f_print(fout, " ");
124 pvname(proc->proc_name, vp->vers_num);
125 f_print(fout, "_arg;\n");
126 } else if (!streq(proc->args.decls->decl.type, "void")) {
127 for (l = proc->args.decls; l != NULL; l = l->next) {
128 f_print(fout, "\t");
129 ptype(l->decl.prefix, l->decl.type, 1);
130 if (strcmp(l->decl.type, "string") == 1)
131 f_print(fout, " ");
132 pvname(proc->proc_name, vp->vers_num);
133 f_print(fout, "_%s;\n", l->decl.name);
134 }
135 }
136 }
137
138 /* generate creation of client handle */
139 f_print(fout, "\n#ifndef\tDEBUG\n");
140 f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n",
141 program_name, vp->vers_name, tirpcflag? "netpath" : "udp");
142 f_print(fout, "\tif (clnt == (CLIENT *) NULL) {\n");
143 f_print(fout, "\t\tclnt_pcreateerror(host);\n");
144 f_print(fout, "\t\texit(1);\n\t}\n");
145 f_print(fout, "#endif\t/* DEBUG */\n\n");
146
147 /* generate calls to procedures */
148 i = 0;
149 for (proc = vp->procs; proc != NULL; proc = proc->next) {
150 if (mtflag)
151 f_print(fout, "\tretval_%d = ", ++i);
152 else
153 f_print(fout, "\tresult_%d = ", ++i);
154 pvname(proc->proc_name, vp->vers_num);
155 if (proc->arg_num < 2 && !newstyle) {
156 f_print(fout, "(");
157 if (streq(proc->args.decls->decl.type, "void"))
158 /* cast to void * */
159 f_print(fout, "(void *)");
160 f_print(fout, "&");
161 pvname(proc->proc_name, vp->vers_num);
162 if (mtflag) {
163 if (streq(proc->res_type, "oneway"))
164 f_print(fout, "_arg, clnt);\n");
165 else
166 f_print(fout,
167 "_arg, &result_%d, clnt);\n", i);
168 } else
169 f_print(fout, "_arg, clnt);\n");
170
171 } else if (streq(proc->args.decls->decl.type, "void")) {
172 if (mtflag) {
173 if (streq(proc->res_type, "oneway"))
174 f_print(fout, "(clnt);\n");
175 else
176 f_print(fout,
177 "(&result_%d, clnt);\n", i);
178 } else
179 f_print(fout, "(clnt);\n");
180 } else {
181 f_print(fout, "(");
182 for (l = proc->args.decls; l != NULL; l = l->next) {
183 pvname(proc->proc_name, vp->vers_num);
184 f_print(fout, "_%s, ", l->decl.name);
185 }
186 if (mtflag) {
187 if (!streq(proc->res_type, "oneway"))
188 f_print(fout, "&result_%d, ", i);
189 }
190
191 f_print(fout, "clnt);\n");
192 }
193 if (mtflag) {
194 f_print(fout, "\tif (retval_%d != RPC_SUCCESS) {\n", i);
195 } else {
196 f_print(fout, "\tif (result_%d == (", i);
197 ptype(proc->res_prefix, proc->res_type, 1);
198 f_print(fout, "*) NULL) {\n");
199 }
200 f_print(fout, "\t\tclnt_perror(clnt, \"call failed\");\n");
201 f_print(fout, "\t}\n");
202 }
203
204 f_print(fout, "#ifndef\tDEBUG\n");
205 f_print(fout, "\tclnt_destroy(clnt);\n");
206 f_print(fout, "#endif\t /* DEBUG */\n");
207 f_print(fout, "}\n");
208 }
209
210 static void
write_sample_server(definition * def)211 write_sample_server(definition *def)
212 {
213 version_list *vp;
214 proc_list *proc;
215
216 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
217 for (proc = vp->procs; proc != NULL; proc = proc->next) {
218 f_print(fout, "\n");
219 if (!mtflag) {
220 return_type(proc);
221 f_print(fout, "*\n");
222 } else {
223 f_print(fout, "bool_t\n");
224 }
225 if (Cflag || mtflag)
226 pvname_svc(proc->proc_name, vp->vers_num);
227 else
228 pvname(proc->proc_name, vp->vers_num);
229 printarglist(proc, "result", RQSTP, "struct svc_req *");
230
231 f_print(fout, "{\n");
232
233 if (!mtflag) {
234 f_print(fout, "\tstatic ");
235 if ((!streq(proc->res_type, "void")) &&
236 (!streq(proc->res_type, "oneway")))
237 return_type(proc);
238 else
239 f_print(fout, "char *");
240 /* cannot have void type */
241 f_print(fout, " result;\n");
242 }
243
244 f_print(fout, "\n\t/*\n\t * insert server code "
245 "here\n\t */\n\n");
246
247 if (!mtflag)
248 if (!streq(proc->res_type, "void"))
249 f_print(fout,
250 "\treturn (&result);\n}\n");
251 else /* cast back to void * */
252 f_print(fout, "\treturn((void *) "
253 "&result);\n}\n");
254 else
255 f_print(fout, "\treturn (retval);\n}\n");
256 }
257 /* put in sample freeing routine */
258 if (mtflag) {
259 f_print(fout, "\nint\n");
260 pvname(def->def_name, vp->vers_num);
261 if (Cflag)
262 f_print(fout, "_freeresult(SVCXPRT *transp,"
263 " xdrproc_t xdr_result,"
264 " caddr_t result)\n");
265 else {
266 f_print(fout, "_freeresult(transp, xdr_result,"
267 " result)\n");
268 f_print(fout, "\tSVCXPRT *transp;\n");
269 f_print(fout, "\txdrproc_t xdr_result;\n");
270 f_print(fout, "\tcaddr_t result;\n");
271 }
272 f_print(fout, "{\n"
273 "\t(void) xdr_free(xdr_result, result);\n"
274 "\n\t/*\n\t * Insert additional freeing"
275 " code here, if needed\n\t */\n"
276 "\n\n\treturn (TRUE);\n}\n");
277 }
278 }
279 }
280
281 static void
return_type(proc_list * plist)282 return_type(proc_list *plist)
283 {
284 ptype(plist->res_prefix, plist->res_type, 1);
285 }
286
287 void
add_sample_msg(void)288 add_sample_msg(void)
289 {
290 f_print(fout, "/*\n");
291 f_print(fout, " * This is sample code generated by rpcgen.\n");
292 f_print(fout, " * These are only templates and you can use them\n");
293 f_print(fout, " * as a guideline for developing your own functions.\n");
294 f_print(fout, " */\n\n");
295 }
296
297 void
write_sample_clnt_main(void)298 write_sample_clnt_main(void)
299 {
300 list *l;
301 definition *def;
302 version_list *vp;
303
304 f_print(fout, "\n\n");
305 if (Cflag)
306 f_print(fout, "int\nmain(int argc, char *argv[])\n{\n");
307 else
308 f_print(fout, "int\nmain(argc, argv)\n\tint argc;\n"
309 "\tchar *argv[];\n{\n");
310
311 f_print(fout, "\tchar *host;");
312 f_print(fout, "\n\n\tif (argc < 2) {");
313 f_print(fout, "\n\t\tprintf(\"usage: %%s server_host\\n\","
314 " argv[0]);\n");
315 f_print(fout, "\t\texit(1);\n\t}");
316 f_print(fout, "\n\thost = argv[1];\n");
317
318 for (l = defined; l != NULL; l = l->next) {
319 def = l->val;
320 if (def->def_kind != DEF_PROGRAM)
321 continue;
322 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
323 f_print(fout, "\t");
324 pvname(def->def_name, vp->vers_num);
325 f_print(fout, "(host);\n");
326 }
327 }
328 f_print(fout, "}\n");
329 }
330