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