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_clntout.c, Client-stub outputter for the RPC protocol compiler 42 */ 43 #include <stdio.h> 44 #include <string.h> 45 #include <rpc/types.h> 46 #include "rpc_parse.h" 47 #include "rpc_util.h" 48 49 extern void pdeclaration(char *, declaration *, int, char *); 50 extern void printarglist(proc_list *, char *, char *, char *); 51 52 static void write_program(definition *); 53 static void printbody(proc_list *); 54 55 static char RESULT[] = "clnt_res"; 56 57 #define DEFAULT_TIMEOUT 25 /* in seconds */ 58 59 void 60 write_stubs(void) 61 { 62 list *l; 63 definition *def; 64 65 f_print(fout, 66 "\n/* Default timeout can be changed using clnt_control() */\n"); 67 f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n", 68 DEFAULT_TIMEOUT); 69 for (l = defined; l != NULL; l = l->next) { 70 def = (definition *) l->val; 71 if (def->def_kind == DEF_PROGRAM) { 72 write_program(def); 73 } 74 } 75 } 76 77 static void 78 write_program(definition *def) 79 { 80 version_list *vp; 81 proc_list *proc; 82 83 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 84 for (proc = vp->procs; proc != NULL; proc = proc->next) { 85 f_print(fout, "\n"); 86 if (mtflag == 0) { 87 ptype(proc->res_prefix, proc->res_type, 1); 88 f_print(fout, "*\n"); 89 pvname(proc->proc_name, vp->vers_num); 90 printarglist(proc, RESULT, "clnt", "CLIENT *"); 91 } else { 92 f_print(fout, "enum clnt_stat \n"); 93 pvname(proc->proc_name, vp->vers_num); 94 printarglist(proc, RESULT, "clnt", "CLIENT *"); 95 96 } 97 f_print(fout, "{\n"); 98 printbody(proc); 99 100 f_print(fout, "}\n"); 101 } 102 } 103 } 104 105 /* 106 * Writes out declarations of procedure's argument list. 107 * In either ANSI C style, in one of old rpcgen style (pass by reference), 108 * or new rpcgen style (multiple arguments, pass by value); 109 */ 110 111 /* sample addargname = "clnt"; sample addargtype = "CLIENT * " */ 112 113 void 114 printarglist(proc_list *proc, char *result, char *addargname, char *addargtype) 115 { 116 bool_t oneway = streq(proc->res_type, "oneway"); 117 decl_list *l; 118 119 if (!newstyle) { 120 /* old style: always pass argument by reference */ 121 f_print(fout, "("); 122 ptype(proc->args.decls->decl.prefix, 123 proc->args.decls->decl.type, 1); 124 125 if (mtflag) { /* Generate result field */ 126 f_print(fout, "*argp, "); 127 if (!oneway) { 128 ptype(proc->res_prefix, proc->res_type, 1); 129 f_print(fout, "*%s, ", result); 130 } 131 f_print(fout, "%s%s)\n", addargtype, addargname); 132 } else 133 f_print(fout, "*argp, %s%s)\n", addargtype, addargname); 134 } else if (streq(proc->args.decls->decl.type, "void")) { 135 /* newstyle, 0 argument */ 136 if (mtflag) { 137 f_print(fout, "("); 138 139 if (!oneway) { 140 ptype(proc->res_prefix, proc->res_type, 1); 141 f_print(fout, "*%s, ", result); 142 } 143 f_print(fout, "%s%s)\n", addargtype, addargname); 144 145 } else 146 f_print(fout, "(%s%s)\n", addargtype, addargname); 147 } else { 148 /* new style, 1 or multiple arguments */ 149 f_print(fout, "("); 150 for (l = proc->args.decls; l != NULL; l = l->next) { 151 pdeclaration(proc->args.argname, &l->decl, 0, ", "); 152 } 153 if (mtflag && !oneway) { 154 ptype(proc->res_prefix, proc->res_type, 1); 155 f_print(fout, "*%s, ", result); 156 157 } 158 f_print(fout, "%s%s)\n", addargtype, addargname); 159 } 160 } 161 162 163 164 static char * 165 ampr(char *type) 166 { 167 if (isvectordef(type, REL_ALIAS)) { 168 return (""); 169 } else { 170 return ("&"); 171 } 172 } 173 174 static void 175 printbody(proc_list *proc) 176 { 177 decl_list *l; 178 bool_t args2 = (proc->arg_num > 1); 179 bool_t oneway = streq(proc->res_type, "oneway"); 180 181 /* 182 * For new style with multiple arguments, need a structure in which 183 * to stuff the arguments. 184 */ 185 if (newstyle && args2) { 186 f_print(fout, "\t%s", proc->args.argname); 187 f_print(fout, " arg;\n"); 188 } 189 if (!oneway) { 190 if (!mtflag) { 191 f_print(fout, "\tstatic "); 192 if (streq(proc->res_type, "void")) { 193 f_print(fout, "char "); 194 } else { 195 ptype(proc->res_prefix, proc->res_type, 0); 196 } 197 f_print(fout, "%s;\n", RESULT); 198 f_print(fout, "\n"); 199 f_print(fout, 200 "\t(void) memset(%s%s, 0, sizeof (%s));\n", 201 ampr(proc->res_type), RESULT, RESULT); 202 203 } 204 if (newstyle && !args2 && 205 (streq(proc->args.decls->decl.type, "void"))) { 206 /* newstyle, 0 arguments */ 207 208 if (mtflag) 209 f_print(fout, "\t return "); 210 else 211 f_print(fout, "\t if "); 212 213 f_print(fout, 214 "(clnt_call(clnt, %s,\n\t\t(xdrproc_t)xdr_void, ", 215 proc->proc_name); 216 f_print(fout, 217 "NULL,\n\t\t(xdrproc_t)xdr_%s, " 218 "(caddr_t)%s%s,", 219 stringfix(proc->res_type), 220 (mtflag)?"":ampr(proc->res_type), 221 RESULT); 222 223 if (mtflag) 224 f_print(fout, "\n\t\tTIMEOUT));\n"); 225 else 226 f_print(fout, 227 "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n"); 228 229 } else if (newstyle && args2) { 230 /* 231 * Newstyle, multiple arguments 232 * stuff arguments into structure 233 */ 234 for (l = proc->args.decls; l != NULL; l = l->next) { 235 f_print(fout, "\targ.%s = %s;\n", 236 l->decl.name, l->decl.name); 237 } 238 if (mtflag) 239 f_print(fout, "\treturn "); 240 else 241 f_print(fout, "\tif "); 242 f_print(fout, 243 "(clnt_call(clnt, %s,\n\t\t(xdrproc_t)xdr_%s", 244 proc->proc_name, proc->args.argname); 245 f_print(fout, 246 ", (caddr_t)&arg,\n\t\t(xdrproc_t)xdr_%s, " 247 "(caddr_t)%s%s,", 248 stringfix(proc->res_type), 249 (mtflag)?"":ampr(proc->res_type), 250 RESULT); 251 if (mtflag) 252 f_print(fout, "\n\t\tTIMEOUT));\n"); 253 else 254 f_print(fout, 255 "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n"); 256 } else { /* single argument, new or old style */ 257 if (!mtflag) 258 f_print(fout, 259 "\tif (clnt_call(clnt, " 260 "%s,\n\t\t(xdrproc_t)xdr_%s, " 261 "(caddr_t)%s%s,\n\t\t(xdrproc_t)xdr_%s, " 262 "(caddr_t)%s%s,\n\t\tTIMEOUT) != " 263 "RPC_SUCCESS) {\n", 264 proc->proc_name, 265 stringfix(proc->args.decls->decl.type), 266 (newstyle ? "&" : ""), 267 (newstyle ? 268 proc->args.decls->decl.name : 269 "argp"), 270 stringfix(proc->res_type), 271 ampr(proc->res_type), 272 RESULT); 273 else 274 f_print(fout, 275 "\treturn (clnt_call(clnt, " 276 "%s,\n\t\t(xdrproc_t)xdr_%s, " 277 "(caddr_t)%s%s,\n\t\t(xdrproc_t)xdr_%s, " 278 "(caddr_t)%s%s,\n\t\tTIMEOUT));\n", 279 proc->proc_name, 280 stringfix(proc->args.decls->decl.type), 281 (newstyle ? "&" : ""), 282 (newstyle ? 283 proc->args.decls->decl.name : 284 "argp"), 285 stringfix(proc->res_type), "", 286 RESULT); 287 } 288 if (!mtflag) { 289 f_print(fout, "\t\treturn (NULL);\n"); 290 f_print(fout, "\t}\n"); 291 292 if (streq(proc->res_type, "void")) { 293 f_print(fout, "\treturn ((void *)%s%s);\n", 294 ampr(proc->res_type), RESULT); 295 } else { 296 f_print(fout, "\treturn (%s%s);\n", 297 ampr(proc->res_type), RESULT); 298 } 299 } 300 } else { 301 /* oneway call */ 302 if (!mtflag) { 303 f_print(fout, "\tstatic enum clnt_stat "); 304 f_print(fout, "%s;\n", RESULT); 305 f_print(fout, "\n"); 306 f_print(fout, 307 "\t(void) memset(&%s, 0, sizeof (%s));\n", 308 RESULT, RESULT); 309 310 } 311 if (newstyle && !args2 && 312 (streq(proc->args.decls->decl.type, "void"))) { 313 /* newstyle, 0 arguments */ 314 315 if (mtflag) 316 f_print(fout, "\t return ("); 317 else 318 f_print(fout, "\t if ((%s = ", RESULT); 319 320 f_print(fout, 321 "clnt_send(clnt, %s,\n\t\t(xdrproc_t)xdr_void, ", 322 proc->proc_name); 323 f_print(fout, "NULL)"); 324 325 if (mtflag) 326 f_print(fout, ");\n"); 327 else 328 f_print(fout, ") != RPC_SUCCESS) {\n"); 329 330 } else if (newstyle && args2) { 331 /* 332 * Newstyle, multiple arguments 333 * stuff arguments into structure 334 */ 335 for (l = proc->args.decls; l != NULL; l = l->next) { 336 f_print(fout, "\targ.%s = %s;\n", 337 l->decl.name, l->decl.name); 338 } 339 if (mtflag) 340 f_print(fout, "\treturn ("); 341 else 342 f_print(fout, "\tif ((%s =", RESULT); 343 f_print(fout, 344 "clnt_send(clnt, %s,\n\t\t(xdrproc_t)xdr_%s", 345 proc->proc_name, proc->args.argname); 346 f_print(fout, 347 ", (caddr_t)&arg)"); 348 if (mtflag) 349 f_print(fout, ");\n"); 350 else 351 f_print(fout, ") != RPC_SUCCESS) {\n"); 352 } else { /* single argument, new or old style */ 353 if (!mtflag) 354 f_print(fout, 355 "\tif ((%s = clnt_send(clnt, " 356 "%s,\n\t\t(xdrproc_t)xdr_%s, " 357 "(caddr_t)%s%s)) != RPC_SUCCESS) {\n", 358 RESULT, 359 proc->proc_name, 360 stringfix(proc->args.decls->decl.type), 361 (newstyle ? "&" : ""), 362 (newstyle ? 363 proc->args.decls->decl.name : 364 "argp")); 365 else 366 367 f_print(fout, 368 "\treturn (clnt_send(clnt, " 369 "%s,\n\t\t(xdrproc_t)xdr_%s, " 370 "(caddr_t)%s%s));\n", 371 proc->proc_name, 372 stringfix(proc->args.decls->decl.type), 373 (newstyle ? "&" : ""), 374 (newstyle ? 375 proc->args.decls->decl.name : 376 "argp")); 377 } 378 if (!mtflag) { 379 f_print(fout, "\t\treturn (NULL);\n"); 380 f_print(fout, "\t}\n"); 381 382 f_print(fout, "\treturn ((void *)&%s);\n", 383 RESULT); 384 } 385 } 386 }