edid-decode: new package
[buildroot-gz.git] / package / libtirpc / 0003-Add-rpcgen-program-from-nfs-utils-sources.patch
blob1cf861417c9b500b9ed136685eef0343edccdcac
1 From 866b651bcb9f93f47582e5e2e4f1eb3155025298 Mon Sep 17 00:00:00 2001
2 From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
3 Date: Sat, 10 Nov 2012 16:21:01 +0100
4 Subject: [PATCH] Add rpcgen program from nfs-utils sources
6 Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
7 [yann.morin.1998@free.fr: update for 0.3.1]
8 Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
9 ---
10 Makefile.am | 2 +-
11 configure.ac | 14 +-
12 rpcgen/Makefile.am | 22 ++
13 rpcgen/rpc_clntout.c | 217 ++++++++++
14 rpcgen/rpc_cout.c | 706 +++++++++++++++++++++++++++++++++
15 rpcgen/rpc_hout.c | 490 +++++++++++++++++++++++
16 rpcgen/rpc_main.c | 1067 ++++++++++++++++++++++++++++++++++++++++++++++++++
17 rpcgen/rpc_output.h | 16 +
18 rpcgen/rpc_parse.c | 609 ++++++++++++++++++++++++++++
19 rpcgen/rpc_parse.h | 166 ++++++++
20 rpcgen/rpc_sample.c | 247 ++++++++++++
21 rpcgen/rpc_scan.c | 474 ++++++++++++++++++++++
22 rpcgen/rpc_scan.h | 103 +++++
23 rpcgen/rpc_svcout.c | 882 +++++++++++++++++++++++++++++++++++++++++
24 rpcgen/rpc_tblout.c | 165 ++++++++
25 rpcgen/rpc_util.c | 479 ++++++++++++++++++++++
26 rpcgen/rpc_util.h | 166 ++++++++
27 rpcgen/rpcgen.1 | 521 ++++++++++++++++++++++++
28 18 files changed, 6344 insertions(+), 2 deletions(-)
29 create mode 100644 rpcgen/Makefile.am
30 create mode 100644 rpcgen/rpc_clntout.c
31 create mode 100644 rpcgen/rpc_cout.c
32 create mode 100644 rpcgen/rpc_hout.c
33 create mode 100644 rpcgen/rpc_main.c
34 create mode 100644 rpcgen/rpc_output.h
35 create mode 100644 rpcgen/rpc_parse.c
36 create mode 100644 rpcgen/rpc_parse.h
37 create mode 100644 rpcgen/rpc_sample.c
38 create mode 100644 rpcgen/rpc_scan.c
39 create mode 100644 rpcgen/rpc_scan.h
40 create mode 100644 rpcgen/rpc_svcout.c
41 create mode 100644 rpcgen/rpc_tblout.c
42 create mode 100644 rpcgen/rpc_util.c
43 create mode 100644 rpcgen/rpc_util.h
44 create mode 100644 rpcgen/rpcgen.1
46 diff --git a/Makefile.am b/Makefile.am
47 index 466b6dd..8558289 100644
48 --- a/Makefile.am
49 +++ b/Makefile.am
50 @@ -1,4 +1,4 @@
51 -SUBDIRS = src man doc
52 +SUBDIRS = src man doc rpcgen
53 ACLOCAL_AMFLAGS = -I m4
55 noinst_HEADERS = tirpc/reentrant.h \
56 diff --git a/configure.ac b/configure.ac
57 index e3cb8af..0ea2e6e 100644
58 --- a/configure.ac
59 +++ b/configure.ac
60 @@ -58,6 +58,18 @@ AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h locale.h netdb.h netine
61 AC_CHECK_LIB([pthread], [pthread_create])
62 AC_CHECK_FUNCS([getrpcbyname getrpcbynumber setrpcent endrpcent getrpcent])
64 -AC_CONFIG_FILES([Makefile src/Makefile man/Makefile doc/Makefile])
65 +AM_CONDITIONAL(CROSS_COMPILING, test $cross_compiling = yes)
67 +AC_MSG_CHECKING([for a C compiler for build tools])
68 +if test $cross_compiling = yes; then
69 + AC_CHECK_PROGS(CC_FOR_BUILD, gcc cc)
70 +else
71 + CC_FOR_BUILD=$CC
72 +fi
73 +AC_MSG_RESULT([$CC_FOR_BUILD])
74 +AC_SUBST(CC_FOR_BUILD)
76 +AC_CONFIG_FILES([Makefile src/Makefile man/Makefile doc/Makefile rpcgen/Makefile])
78 AC_OUTPUT(libtirpc.pc)
80 diff --git a/rpcgen/Makefile.am b/rpcgen/Makefile.am
81 new file mode 100644
82 index 0000000..2277b6f
83 --- /dev/null
84 +++ b/rpcgen/Makefile.am
85 @@ -0,0 +1,22 @@
86 +COMPILE = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
87 + $(CPPFLAGS_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD)
88 +LINK = $(CC_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) $(AM_LDFLAGS) $(LDFLAGS_FOR_BUILD) -o $@
90 +noinst_PROGRAMS = rpcgen
92 +rpcgen_SOURCES = \
93 + rpc_clntout.c \
94 + rpc_cout.c \
95 + rpc_hout.c \
96 + rpc_main.c \
97 + rpc_parse.c \
98 + rpc_sample.c \
99 + rpc_scan.c \
100 + rpc_svcout.c \
101 + rpc_tblout.c \
102 + rpc_util.c \
103 + rpc_parse.h \
104 + rpc_scan.h \
105 + rpc_util.h
107 +dist_man1_MANS = rpcgen.1
108 diff --git a/rpcgen/rpc_clntout.c b/rpcgen/rpc_clntout.c
109 new file mode 100644
110 index 0000000..e2f4382
111 --- /dev/null
112 +++ b/rpcgen/rpc_clntout.c
113 @@ -0,0 +1,217 @@
115 + * Copyright (c) 2009, Sun Microsystems, Inc.
116 + * All rights reserved.
118 + * Redistribution and use in source and binary forms, with or without
119 + * modification, are permitted provided that the following conditions are met:
120 + * - Redistributions of source code must retain the above copyright notice,
121 + * this list of conditions and the following disclaimer.
122 + * - Redistributions in binary form must reproduce the above copyright notice,
123 + * this list of conditions and the following disclaimer in the documentation
124 + * and/or other materials provided with the distribution.
125 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
126 + * contributors may be used to endorse or promote products derived
127 + * from this software without specific prior written permission.
129 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
130 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
131 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
132 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
133 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
134 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
135 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
136 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
137 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
138 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
139 + * POSSIBILITY OF SUCH DAMAGE.
140 + */
142 +#if 0
143 +static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI";
144 +#endif
147 + * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
148 + * Copyright (C) 1987, Sun Microsytsems, Inc.
149 + */
150 +#include <stdio.h>
151 +#include <string.h>
152 +#include <rpc/types.h>
153 +#include "rpc_parse.h"
154 +#include "rpc_util.h"
155 +#include "rpc_output.h"
157 +/* extern pdeclaration(); */
158 +/* void printarglist(); */
160 +#define DEFAULT_TIMEOUT 25 /* in seconds */
161 +static char RESULT[] = "clnt_res";
163 +static void write_program(definition *def);
164 +static void printbody(proc_list *proc);
167 +void
168 +write_stubs(void)
170 + list *l;
171 + definition *def;
173 + f_print(fout,
174 + "\n/* Default timeout can be changed using clnt_control() */\n");
175 + f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
176 + DEFAULT_TIMEOUT);
177 + for (l = defined; l != NULL; l = l->next) {
178 + def = (definition *) l->val;
179 + if (def->def_kind == DEF_PROGRAM) {
180 + write_program(def);
185 +static void
186 +write_program(definition *def)
188 + version_list *vp;
189 + proc_list *proc;
191 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
192 + for (proc = vp->procs; proc != NULL; proc = proc->next) {
193 + f_print(fout, "\n");
194 + ptype(proc->res_prefix, proc->res_type, 1);
195 + f_print(fout, "*\n");
196 + pvname(proc->proc_name, vp->vers_num);
197 + printarglist(proc, "clnt", "CLIENT *");
198 + f_print(fout, "{\n");
199 + printbody(proc);
200 + f_print(fout, "}\n");
206 + * Writes out declarations of procedure's argument list.
207 + * In either ANSI C style, in one of old rpcgen style (pass by reference),
208 + * or new rpcgen style (multiple arguments, pass by value);
209 + */
211 +/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
213 +void
214 +printarglist(proc_list *proc, char *addargname, char *addargtype)
217 + decl_list *l;
219 + if (!newstyle) { /* old style: always pass arg by reference */
220 + if (Cflag) { /* C++ style heading */
221 + f_print(fout, "(");
222 + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
223 + f_print(fout, "*argp, %s%s)\n", addargtype, addargname);
224 + } else {
225 + f_print(fout, "(argp, %s)\n", addargname);
226 + f_print(fout, "\t");
227 + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
228 + f_print(fout, "*argp;\n");
230 + } else if (streq(proc->args.decls->decl.type, "void")) {
231 + /* newstyle, 0 argument */
232 + if (Cflag)
233 + f_print(fout, "(%s%s)\n", addargtype, addargname);
234 + else
235 + f_print(fout, "(%s)\n", addargname);
236 + } else {
237 + /* new style, 1 or multiple arguments */
238 + if (!Cflag) {
239 + f_print(fout, "(");
240 + for (l = proc->args.decls; l != NULL; l = l->next)
241 + f_print(fout, "%s, ", l->decl.name);
242 + f_print(fout, "%s)\n", addargname);
243 + for (l = proc->args.decls; l != NULL; l = l->next) {
244 + pdeclaration(proc->args.argname, &l->decl, 1, ";\n");
246 + } else { /* C++ style header */
247 + f_print(fout, "(");
248 + for (l = proc->args.decls; l != NULL; l = l->next) {
249 + pdeclaration(proc->args.argname, &l->decl, 0, ", ");
251 + f_print(fout, " %s%s)\n", addargtype, addargname);
255 + if (!Cflag)
256 + f_print(fout, "\t%s%s;\n", addargtype, addargname);
261 +static char *
262 +ampr(char *type)
264 + if (isvectordef(type, REL_ALIAS)) {
265 + return ("");
266 + } else {
267 + return ("&");
271 +static void
272 +printbody(proc_list *proc)
274 + decl_list *l;
275 + bool_t args2 = (proc->arg_num > 1);
277 + /* For new style with multiple arguments, need a structure in which
278 + * to stuff the arguments. */
279 + if (newstyle && args2) {
280 + f_print(fout, "\t%s", proc->args.argname);
281 + f_print(fout, " arg;\n");
283 + f_print(fout, "\tstatic ");
284 + if (streq(proc->res_type, "void")) {
285 + f_print(fout, "char ");
286 + } else {
287 + ptype(proc->res_prefix, proc->res_type, 0);
289 + f_print(fout, "%s;\n", RESULT);
290 + f_print(fout, "\n");
291 + f_print(fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n",
292 + ampr(proc->res_type), RESULT, RESULT);
293 + if (newstyle && !args2 && (streq(proc->args.decls->decl.type, "void"))) {
294 + /* newstyle, 0 arguments */
295 + f_print(fout,
296 + "\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_void, (caddr_t) NULL, "
297 + "(xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n",
298 + proc->proc_name,
299 + stringfix(proc->res_type), ampr(proc->res_type), RESULT);
301 + } else if (newstyle && args2) {
302 + /* newstyle, multiple arguments: stuff arguments into structure */
303 + for (l = proc->args.decls; l != NULL; l = l->next) {
304 + f_print(fout, "\targ.%s = %s;\n",
305 + l->decl.name, l->decl.name);
307 + f_print(fout,
308 + "\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_%s, (caddr_t) &arg, "
309 + "(xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n",
310 + proc->proc_name, proc->args.argname,
311 + stringfix(proc->res_type), ampr(proc->res_type), RESULT);
312 + } else { /* single argument, new or old style */
313 + f_print(fout,
314 + "\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_%s, "
315 + "(caddr_t) %s%s, (xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n",
316 + proc->proc_name,
317 + stringfix(proc->args.decls->decl.type),
318 + (newstyle ? "&" : ""),
319 + (newstyle ? proc->args.decls->decl.name : "argp"),
320 + stringfix(proc->res_type), ampr(proc->res_type), RESULT);
322 + f_print(fout, "\t\treturn (NULL);\n");
323 + f_print(fout, "\t}\n");
324 + if (streq(proc->res_type, "void")) {
325 + f_print(fout, "\treturn ((void *)%s%s);\n",
326 + ampr(proc->res_type), RESULT);
327 + } else {
328 + f_print(fout, "\treturn (%s%s);\n", ampr(proc->res_type), RESULT);
331 diff --git a/rpcgen/rpc_cout.c b/rpcgen/rpc_cout.c
332 new file mode 100644
333 index 0000000..a61214f
334 --- /dev/null
335 +++ b/rpcgen/rpc_cout.c
336 @@ -0,0 +1,706 @@
338 + * Copyright (c) 2009, Sun Microsystems, Inc.
339 + * All rights reserved.
341 + * Redistribution and use in source and binary forms, with or without
342 + * modification, are permitted provided that the following conditions are met:
343 + * - Redistributions of source code must retain the above copyright notice,
344 + * this list of conditions and the following disclaimer.
345 + * - Redistributions in binary form must reproduce the above copyright notice,
346 + * this list of conditions and the following disclaimer in the documentation
347 + * and/or other materials provided with the distribution.
348 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
349 + * contributors may be used to endorse or promote products derived
350 + * from this software without specific prior written permission.
352 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
353 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
354 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
355 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
356 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
357 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
358 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
359 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
360 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
361 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
362 + * POSSIBILITY OF SUCH DAMAGE.
363 + */
365 +#if 0
366 +static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI";
367 +#endif
370 + * rpc_cout.c, XDR routine outputter for the RPC protocol compiler
371 + */
372 +#include <stdio.h>
373 +#include <string.h>
374 +#include <stdlib.h>
375 +#include <malloc.h>
376 +#include <ctype.h>
377 +#include "rpc_parse.h"
378 +#include "rpc_util.h"
380 +static int findtype(definition *def, char *type);
381 +static int undefined(char *type);
382 +static void print_generic_header(char *procname, int pointerp);
383 +static void print_header(definition *def);
384 +static void print_prog_header(proc_list *plist);
385 +static void print_trailer(void);
386 +static void print_ifopen(int indent, char *name);
387 +static void print_ifarg(char *arg);
388 +static void print_ifsizeof(char *prefix, char *type);
389 +static void print_ifclose(int indent);
390 +static void print_ifstat(int indent, char *prefix, char *type, relation rel,
391 + char *amax, char *objname, char *name);
392 +static void emit_enum(definition *def);
393 +static void emit_program(definition *def);
394 +static void emit_union(definition *def);
395 +static void emit_struct(definition *def);
396 +static void emit_typedef(definition *def);
397 +static void print_stat(int indent, declaration *dec);
398 +static void emit_inline(declaration *decl, int flag);
399 +static void emit_single_in_line(declaration *decl, int flag, relation rel);
400 +static char * upcase(char *str);
403 + * Emit the C-routine for the given definition
404 + */
405 +void
406 +emit(definition *def)
408 + if (def->def_kind == DEF_CONST) {
409 + return;
411 + if (def->def_kind == DEF_PROGRAM) {
412 + emit_program(def);
413 + return;
415 + if (def->def_kind == DEF_TYPEDEF) {
416 + /* now we need to handle declarations like
417 + * struct typedef foo foo;
418 + * since we dont want this to be expanded into 2 calls
419 + * to xdr_foo */
421 + if (strcmp(def->def.ty.old_type, def->def_name) == 0)
422 + return;
423 + };
425 + print_header(def);
426 + switch (def->def_kind) {
427 + case DEF_UNION:
428 + emit_union(def);
429 + break;
430 + case DEF_ENUM:
431 + emit_enum(def);
432 + break;
433 + case DEF_STRUCT:
434 + emit_struct(def);
435 + break;
436 + case DEF_TYPEDEF:
437 + emit_typedef(def);
438 + break;
439 + default:
440 + break;
442 + print_trailer();
445 +static int
446 +findtype(definition *def, char *type)
449 + if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) {
450 + return (0);
451 + } else {
452 + return (streq(def->def_name, type));
456 +static int
457 +undefined(char *type)
459 + definition *def;
461 + def = (definition *) FINDVAL(defined, type, findtype);
463 + return (def == NULL);
467 +static void
468 +print_generic_header(char *procname, int pointerp)
470 + f_print(fout, "\n");
471 + f_print(fout, "bool_t\n");
472 + if (Cflag) {
473 + f_print(fout, "xdr_%s(", procname);
474 + f_print(fout, "XDR *xdrs, ");
475 + f_print(fout, "%s ", procname);
476 + if (pointerp)
477 + f_print(fout, "*");
478 + f_print(fout, "objp)\n{\n\n");
479 + } else {
480 + f_print(fout, "xdr_%s(xdrs, objp)\n", procname);
481 + f_print(fout, "\tXDR *xdrs;\n");
482 + f_print(fout, "\t%s ", procname);
483 + if (pointerp)
484 + f_print(fout, "*");
485 + f_print(fout, "objp;\n{\n\n");
489 +static void
490 +print_header(definition *def)
492 + print_generic_header(def->def_name,
493 + def->def_kind != DEF_TYPEDEF ||
494 + !isvectordef(def->def.ty.old_type, def->def.ty.rel));
496 + /* Now add Inline support */
499 + if (Inline == 0)
500 + return;
503 +static void
504 +print_prog_header(proc_list *plist)
506 + print_generic_header(plist->args.argname, 1);
509 +static void
510 +print_trailer(void)
512 + f_print(fout, "\treturn (TRUE);\n");
513 + f_print(fout, "}\n");
517 +static void
518 +print_ifopen(int indent, char *name)
520 + tabify(fout, indent);
521 + f_print(fout, " if (!xdr_%s(xdrs", name);
524 +static void
525 +print_ifarg(char *arg)
527 + f_print(fout, ", %s", arg);
530 +static void
531 +print_ifsizeof(char *prefix, char *type)
533 + if (streq(type, "bool")) {
534 + f_print(fout, ", sizeof(bool_t), (xdrproc_t)xdr_bool");
535 + } else {
536 + f_print(fout, ", sizeof(");
537 + if (undefined(type) && prefix) {
538 + f_print(fout, "%s ", prefix);
540 + f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type);
544 +static void
545 +print_ifclose(int indent)
547 + f_print(fout, ")) {\n");
548 + tabify(fout, indent);
549 + f_print(fout, "\t return (FALSE);\n");
550 + tabify(fout, indent);
551 + f_print(fout, " }\n");
554 +static void
555 +print_ifstat(int indent, char *prefix, char *type, relation rel,
556 + char *amax, char *objname, char *name)
558 + char *alt = NULL;
560 + switch (rel) {
561 + case REL_POINTER:
562 + print_ifopen(indent, "pointer");
563 + print_ifarg("(char **)");
564 + f_print(fout, "%s", objname);
565 + print_ifsizeof(prefix, type);
566 + break;
567 + case REL_VECTOR:
568 + if (streq(type, "string")) {
569 + alt = "string";
570 + } else if (streq(type, "opaque")) {
571 + alt = "opaque";
573 + if (alt) {
574 + print_ifopen(indent, alt);
575 + print_ifarg(objname);
576 + } else {
577 + print_ifopen(indent, "vector");
578 + print_ifarg("(char *)");
579 + f_print(fout, "%s", objname);
581 + print_ifarg(amax);
582 + if (!alt) {
583 + print_ifsizeof(prefix, type);
585 + break;
586 + case REL_ARRAY:
587 + if (streq(type, "string")) {
588 + alt = "string";
589 + } else if (streq(type, "opaque")) {
590 + alt = "bytes";
592 + if (streq(type, "string")) {
593 + print_ifopen(indent, alt);
594 + print_ifarg(objname);
595 + } else {
596 + if (alt) {
597 + print_ifopen(indent, alt);
598 + } else {
599 + print_ifopen(indent, "array");
601 + /* The (void*) avoids a gcc-4.1 warning */
602 + print_ifarg("(char **)(void*)");
603 + if (*objname == '&') {
604 + f_print(fout, "%s.%s_val, (u_int *)%s.%s_len",
605 + objname, name, objname, name);
606 + } else {
607 + f_print(fout, "&%s->%s_val, (u_int *)&%s->%s_len",
608 + objname, name, objname, name);
611 + print_ifarg(amax);
612 + if (!alt) {
613 + print_ifsizeof(prefix, type);
615 + break;
616 + case REL_ALIAS:
617 + print_ifopen(indent, type);
618 + print_ifarg(objname);
619 + break;
621 + print_ifclose(indent);
624 +static void
625 +emit_enum(definition *def)
627 + print_ifopen(1, "enum");
628 + print_ifarg("(enum_t *)objp");
629 + print_ifclose(1);
632 +static void
633 +emit_program(definition *def)
635 + decl_list *dl;
636 + version_list *vlist;
637 + proc_list *plist;
639 + for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next)
640 + for (plist = vlist->procs; plist != NULL; plist = plist->next) {
641 + if (!newstyle || plist->arg_num < 2)
642 + continue;/* old style, or single argument */
643 + print_prog_header(plist);
644 + for (dl = plist->args.decls; dl != NULL; dl = dl->next)
645 + print_stat(1, &dl->decl);
646 + print_trailer();
651 +static void
652 +emit_union(definition *def)
654 + declaration *dflt;
655 + case_list *cl;
656 + declaration *cs;
657 + char *object;
658 + char *vecformat = "objp->%s_u.%s";
659 + char *format = "&objp->%s_u.%s";
661 + print_stat(1,&def->def.un.enum_decl);
662 + f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name);
663 + for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
665 + f_print(fout, "\tcase %s:\n", cl->case_name);
666 + if(cl->contflag == 1) /* a continued case statement */
667 + continue;
668 + cs = &cl->case_decl;
669 + if (!streq(cs->type, "void")) {
670 + object = alloc(strlen(def->def_name) + strlen(format) +
671 + strlen(cs->name) + 1);
672 + if (isvectordef (cs->type, cs->rel)) {
673 + s_print(object, vecformat, def->def_name,
674 + cs->name);
675 + } else {
676 + s_print(object, format, def->def_name,
677 + cs->name);
679 + print_ifstat(2, cs->prefix, cs->type, cs->rel, cs->array_max,
680 + object, cs->name);
681 + free(object);
683 + f_print(fout, "\t\tbreak;\n");
685 + dflt = def->def.un.default_decl;
686 + if (dflt != NULL) {
687 + if (!streq(dflt->type, "void")) {
688 + f_print(fout, "\tdefault:\n");
689 + object = alloc(strlen(def->def_name) + strlen(format) +
690 + strlen(dflt->name) + 1);
691 + if (isvectordef (dflt->type, dflt->rel)) {
692 + s_print(object, vecformat, def->def_name,
693 + dflt->name);
694 + } else {
695 + s_print(object, format, def->def_name,
696 + dflt->name);
699 + print_ifstat(2, dflt->prefix, dflt->type, dflt->rel,
700 + dflt->array_max, object, dflt->name);
701 + free(object);
702 + f_print(fout, "\t\tbreak;\n");
703 + } else {
704 + /* Avoid gcc warnings about `value not handled in switch' */
705 + f_print(fout, "\tdefault:\n");
706 + f_print(fout, "\t\tbreak;\n");
708 + } else {
709 + f_print(fout, "\tdefault:\n");
710 + f_print(fout, "\t\treturn (FALSE);\n");
713 + f_print(fout, "\t}\n");
716 +static void
717 +emit_struct(definition *def)
719 + decl_list *dl;
720 + int i, j, size, flag;
721 + decl_list *cur = NULL, *psav;
722 + bas_type *ptr;
723 + char *sizestr, *plus;
724 + char ptemp[256];
725 + int can_inline;
726 + const char *buf_declaration;
729 + if (Inline == 0) {
730 + for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
731 + print_stat(1, &dl->decl);
732 + } else {
733 + size = 0;
734 + can_inline = 0;
735 + for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
736 + if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) {
738 + if (dl->decl.rel == REL_ALIAS)
739 + size += ptr->length;
740 + else {
741 + can_inline = 1;
742 + break; /* can be inlined */
743 + };
744 + } else {
745 + if (size >= Inline) {
746 + can_inline = 1;
747 + break; /* can be inlined */
749 + size = 0;
751 + if (size > Inline)
752 + can_inline = 1;
754 + if (can_inline == 0) { /* can not inline, drop back to old mode */
755 + for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
756 + print_stat(1, &dl->decl);
757 + return;
758 + };
763 + flag = PUT;
764 + for (j = 0; j < 2; j++) {
766 + if (flag == PUT)
767 + f_print(fout, "\n\t if (xdrs->x_op == XDR_ENCODE) {\n");
768 + else
769 + f_print(fout, "\n \t return (TRUE);\n\t} else if (xdrs->x_op == XDR_DECODE) {\n");
772 + i = 0;
773 + size = 0;
774 + sizestr = NULL;
775 + buf_declaration = "int32_t *";
776 + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { /* xxx */
778 + /* now walk down the list and check for basic types */
779 + if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) {
780 + if (i == 0)
781 + cur = dl;
782 + i++;
784 + if (dl->decl.rel == REL_ALIAS)
785 + size += ptr->length;
786 + else {
787 + /* this is required to handle arrays */
789 + if (sizestr == NULL)
790 + plus = " ";
791 + else
792 + plus = "+";
794 + if (ptr->length != 1)
795 + s_print(ptemp, " %s %s * %d", plus, dl->decl.array_max, ptr->length);
796 + else
797 + s_print(ptemp, " %s %s ", plus, dl->decl.array_max);
799 + /*now concatenate to sizestr !!!! */
800 + if (sizestr == NULL)
801 + sizestr = strdup(ptemp);
802 + else {
803 + sizestr = realloc(sizestr, strlen(sizestr) + strlen(ptemp) + 1);
804 + if (sizestr == NULL) {
806 + f_print(stderr, "Fatal error : no memory \n");
807 + crash();
808 + };
809 + sizestr = strcat(sizestr, ptemp); /*build up length of array */
814 + } else {
815 + if (i > 0)
817 + if (sizestr == NULL && size < Inline) {
818 + /* don't expand into inline code if size < inline */
819 + while (cur != dl) {
820 + print_stat(1, &cur->decl);
821 + cur = cur->next;
823 + } else {
827 + /* were already looking at a xdr_inlineable structure */
828 + if (sizestr == NULL)
829 + f_print(fout, "\t %sbuf = XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);",
830 + buf_declaration, size);
831 + else if (size == 0)
832 + f_print(fout,
833 + "\t %sbuf = XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);",
834 + buf_declaration, sizestr);
835 + else
836 + f_print(fout,
837 + "\t %sbuf = XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);",
838 + buf_declaration, size, sizestr);
839 + buf_declaration = "";
841 + f_print(fout, "\n\t if (buf == NULL) {\n");
843 + psav = cur;
844 + while (cur != dl) {
845 + print_stat(2, &cur->decl);
846 + cur = cur->next;
849 + f_print(fout, "\n\t }\n\t else {\n");
851 + cur = psav;
852 + while (cur != dl) {
853 + emit_inline(&cur->decl, flag);
854 + cur = cur->next;
857 + f_print(fout, "\t }\n");
860 + size = 0;
861 + i = 0;
862 + sizestr = NULL;
863 + print_stat(1, &dl->decl);
867 + if (i > 0)
869 + if (sizestr == NULL && size < Inline) {
870 + /* don't expand into inline code if size < inline */
871 + while (cur != dl) {
872 + print_stat(1, &cur->decl);
873 + cur = cur->next;
875 + } else {
877 + /* were already looking at a xdr_inlineable structure */
878 + if (sizestr == NULL)
879 + f_print(fout, "\t\t%sbuf = XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);",
880 + buf_declaration, size);
881 + else if (size == 0)
882 + f_print(fout,
883 + "\t\t%sbuf = XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);",
884 + buf_declaration, sizestr);
885 + else
886 + f_print(fout,
887 + "\t\t%sbuf = XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);",
888 + buf_declaration, size, sizestr);
889 + buf_declaration = "";
891 + f_print(fout, "\n\t\tif (buf == NULL) {\n");
893 + psav = cur;
894 + while (cur != NULL) {
895 + print_stat(2, &cur->decl);
896 + cur = cur->next;
898 + f_print(fout, "\n\t }\n\t else {\n");
900 + cur = psav;
901 + while (cur != dl) {
902 + emit_inline(&cur->decl, flag);
903 + cur = cur->next;
906 + f_print(fout, "\t }\n");
910 + flag = GET;
912 + f_print(fout, "\t return(TRUE);\n\t}\n\n");
914 + /* now take care of XDR_FREE case */
916 + for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
917 + print_stat(1, &dl->decl);
924 +static void
925 +emit_typedef(definition *def)
927 + char *prefix = def->def.ty.old_prefix;
928 + char *type = def->def.ty.old_type;
929 + char *amax = def->def.ty.array_max;
930 + relation rel = def->def.ty.rel;
933 + print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
936 +static void
937 +print_stat(int indent, declaration *dec)
939 + char *prefix = dec->prefix;
940 + char *type = dec->type;
941 + char *amax = dec->array_max;
942 + relation rel = dec->rel;
943 + char name[256];
945 + if (isvectordef(type, rel)) {
946 + s_print(name, "objp->%s", dec->name);
947 + } else {
948 + s_print(name, "&objp->%s", dec->name);
950 + print_ifstat(indent, prefix, type, rel, amax, name, dec->name);
954 +static void
955 +emit_inline(declaration *decl, int flag)
958 + /*check whether an array or not */
960 + switch (decl->rel) {
961 + case REL_ALIAS:
962 + emit_single_in_line(decl, flag, REL_ALIAS);
963 + break;
964 + case REL_VECTOR:
965 + f_print(fout, "\t\t{ register %s *genp; \n", decl->type);
966 + f_print(fout, "\t\t int i;\n");
967 + f_print(fout, "\t\t for ( i = 0,genp=objp->%s;\n \t\t\ti < %s; i++){\n\t\t",
968 + decl->name, decl->array_max);
969 + emit_single_in_line(decl, flag, REL_VECTOR);
970 + f_print(fout, "\t\t }\n\t\t };\n");
971 + break;
972 + default:
973 + break;
977 +static void
978 +emit_single_in_line(declaration *decl, int flag, relation rel)
980 + char *upp_case;
981 + int freed=0;
983 + if(flag == PUT)
984 + f_print(fout,"\t\t (void) IXDR_PUT_");
985 + else
986 + if(rel== REL_ALIAS)
987 + f_print(fout,"\t\t objp->%s = IXDR_GET_",decl->name);
988 + else
989 + f_print(fout,"\t\t *genp++ = IXDR_GET_");
991 + upp_case=upcase(decl->type);
993 + /* hack - XX */
994 + if(strcmp(upp_case,"INT") == 0)
996 + free(upp_case);
997 + freed=1;
998 + upp_case="INT32";
1001 + if(strcmp(upp_case,"U_INT") == 0)
1003 + free(upp_case);
1004 + freed=1;
1005 + upp_case="U_INT32";
1009 + if(flag == PUT)
1010 + if(rel== REL_ALIAS)
1011 + f_print(fout,"%s(buf,objp->%s);\n",upp_case,decl->name);
1012 + else
1013 + f_print(fout,"%s(buf,*genp++);\n",upp_case);
1015 + else
1016 + f_print(fout,"%s(buf);\n",upp_case);
1017 + if(!freed)
1018 + free(upp_case);
1023 +static char *
1024 +upcase(char *str)
1026 + char *ptr, *hptr;
1029 + ptr = (char *) malloc(strlen(str)+1);
1030 + if (ptr == (char *) NULL) {
1031 + f_print(stderr, "malloc failed \n");
1032 + exit(1);
1033 + };
1035 + hptr = ptr;
1036 + while (*str != '\0')
1037 + *ptr++ = toupper(*str++);
1039 + *ptr = '\0';
1040 + return (hptr);
1043 diff --git a/rpcgen/rpc_hout.c b/rpcgen/rpc_hout.c
1044 new file mode 100644
1045 index 0000000..ea1cb24
1046 --- /dev/null
1047 +++ b/rpcgen/rpc_hout.c
1048 @@ -0,0 +1,490 @@
1050 + * Copyright (c) 2009, Sun Microsystems, Inc.
1051 + * All rights reserved.
1053 + * Redistribution and use in source and binary forms, with or without
1054 + * modification, are permitted provided that the following conditions are met:
1055 + * - Redistributions of source code must retain the above copyright notice,
1056 + * this list of conditions and the following disclaimer.
1057 + * - Redistributions in binary form must reproduce the above copyright notice,
1058 + * this list of conditions and the following disclaimer in the documentation
1059 + * and/or other materials provided with the distribution.
1060 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
1061 + * contributors may be used to endorse or promote products derived
1062 + * from this software without specific prior written permission.
1064 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1065 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1066 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1067 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
1068 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1069 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1070 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1071 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1072 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1073 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1074 + * POSSIBILITY OF SUCH DAMAGE.
1075 + */
1077 +#if 0
1078 +static char sccsid[] = "@(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI";
1079 +#endif
1082 + * rpc_hout.c, Header file outputter for the RPC protocol compiler
1083 + */
1084 +#include <stdio.h>
1085 +#include <ctype.h>
1086 +#include "rpc_parse.h"
1087 +#include "rpc_util.h"
1088 +#include "rpc_output.h"
1091 +static int undefined2(char *type, char *stop);
1092 +static void pxdrfuncdecl(char *name, int pointerp);
1093 +static void pconstdef(definition *def);
1094 +static void pargdef(definition *def);
1095 +static void pstructdef(definition *def);
1096 +static void puniondef(definition *def);
1097 +static void pdefine(char *name, char *num);
1098 +static void puldefine(char *name, char *num);
1099 +static int define_printed(proc_list *stop, version_list *start);
1100 +static void pprogramdef(definition *def);
1101 +static void pprocdef(proc_list *proc, version_list *vp,
1102 + char *addargtype, int server_p, int mode);
1103 +static void parglist(proc_list *proc, char *addargtype);
1104 +static void penumdef(definition *def);
1105 +static void ptypedef(definition *def);
1108 + * Print the C-version of an xdr definition
1109 + */
1110 +void
1111 +print_datadef(definition *def)
1114 + if (def->def_kind == DEF_PROGRAM ) /* handle data only */
1115 + return;
1117 + if (def->def_kind != DEF_CONST) {
1118 + f_print(fout, "\n");
1120 + switch (def->def_kind) {
1121 + case DEF_STRUCT:
1122 + pstructdef(def);
1123 + break;
1124 + case DEF_UNION:
1125 + puniondef(def);
1126 + break;
1127 + case DEF_ENUM:
1128 + penumdef(def);
1129 + break;
1130 + case DEF_TYPEDEF:
1131 + ptypedef(def);
1132 + break;
1133 + case DEF_PROGRAM:
1134 + pprogramdef(def);
1135 + break;
1136 + case DEF_CONST:
1137 + pconstdef(def);
1138 + break;
1140 + if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) {
1141 + pxdrfuncdecl( def->def_name,
1142 + def->def_kind != DEF_TYPEDEF ||
1143 + !isvectordef(def->def.ty.old_type, def->def.ty.rel));
1149 +void
1150 +print_funcdef(definition *def)
1152 + switch (def->def_kind) {
1153 + case DEF_PROGRAM:
1154 + f_print(fout, "\n");
1155 + pprogramdef(def);
1156 + break;
1157 + default:
1158 + break;
1162 +static void
1163 +pxdrfuncdecl(char *name, int pointerp)
1165 + f_print(fout,
1166 + "#ifdef __cplusplus \n"
1167 + "extern \"C\" bool_t xdr_%s(XDR *, %s%s);\n"
1168 + "#elif __STDC__ \n"
1169 + "extern bool_t xdr_%s(XDR *, %s%s);\n"
1170 + "#else /* Old Style C */ \n"
1171 + "bool_t xdr_%s();\n"
1172 + "#endif /* Old Style C */ \n\n",
1173 + name, name, pointerp ? "*" : "",
1174 + name, name, pointerp ? "*" : "",
1175 + name);
1179 +static void
1180 +pconstdef(definition *def)
1182 + pdefine(def->def_name, def->def.co);
1185 +/* print out the definitions for the arguments of functions in the
1186 + header file
1188 +static void
1189 +pargdef(definition *def)
1191 + decl_list *l;
1192 + version_list *vers;
1193 + char *name;
1194 + proc_list *plist;
1197 + for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
1198 + for(plist = vers->procs; plist != NULL;
1199 + plist = plist->next) {
1201 + if (!newstyle || plist->arg_num < 2) {
1202 + continue; /* old style or single args */
1204 + name = plist->args.argname;
1205 + f_print(fout, "struct %s {\n", name);
1206 + for (l = plist->args.decls;
1207 + l != NULL; l = l->next) {
1208 + pdeclaration(name, &l->decl, 1, ";\n" );
1210 + f_print(fout, "};\n");
1211 + f_print(fout, "typedef struct %s %s;\n", name, name);
1212 + pxdrfuncdecl(name, 0);
1213 + f_print( fout, "\n" );
1220 +static void
1221 +pstructdef(definition *def)
1223 + decl_list *l;
1224 + char *name = def->def_name;
1226 + f_print(fout, "struct %s {\n", name);
1227 + for (l = def->def.st.decls; l != NULL; l = l->next) {
1228 + pdeclaration(name, &l->decl, 1, ";\n");
1230 + f_print(fout, "};\n");
1231 + f_print(fout, "typedef struct %s %s;\n", name, name);
1234 +static void
1235 +puniondef(definition *def)
1237 + case_list *l;
1238 + char *name = def->def_name;
1239 + declaration *decl;
1241 + f_print(fout, "struct %s {\n", name);
1242 + decl = &def->def.un.enum_decl;
1243 + if (streq(decl->type, "bool")) {
1244 + f_print(fout, "\tbool_t %s;\n", decl->name);
1245 + } else {
1246 + f_print(fout, "\t%s %s;\n", decl->type, decl->name);
1248 + f_print(fout, "\tunion {\n");
1249 + for (l = def->def.un.cases; l != NULL; l = l->next) {
1250 + if (l->contflag == 0)
1251 + pdeclaration(name, &l->case_decl, 2, ";\n");
1253 + decl = def->def.un.default_decl;
1254 + if (decl && !streq(decl->type, "void")) {
1255 + pdeclaration(name, decl, 2, ";\n");
1257 + f_print(fout, "\t} %s_u;\n", name);
1258 + f_print(fout, "};\n");
1259 + f_print(fout, "typedef struct %s %s;\n", name, name);
1262 +static void
1263 +pdefine(char *name, char *num)
1265 + f_print(fout, "#define %s %s\n", name, num);
1268 +static void
1269 +puldefine(char *name, char *num)
1271 + f_print(fout, "#define %s ((u_int32_t)%s)\n", name, num);
1274 +static int
1275 +define_printed(proc_list *stop, version_list *start)
1277 + version_list *vers;
1278 + proc_list *proc;
1280 + for (vers = start; vers != NULL; vers = vers->next) {
1281 + for (proc = vers->procs; proc != NULL; proc = proc->next) {
1282 + if (proc == stop) {
1283 + return (0);
1284 + } else if (streq(proc->proc_name, stop->proc_name)) {
1285 + return (1);
1289 + abort();
1290 + /* NOTREACHED */
1293 +static void
1294 +pprogramdef(definition *def)
1296 + version_list *vers;
1297 + proc_list *proc;
1298 + int i;
1299 + char *ext;
1301 + pargdef(def);
1303 + puldefine(def->def_name, def->def.pr.prog_num);
1304 + for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
1305 + if (tblflag) {
1306 + f_print(fout, "extern struct rpcgen_table %s_%s_table[];\n",
1307 + locase(def->def_name), vers->vers_num);
1308 + f_print(fout, "extern %s_%s_nproc;\n",
1309 + locase(def->def_name), vers->vers_num);
1311 + puldefine(vers->vers_name, vers->vers_num);
1313 + /*
1314 + * Print out 3 definitions, one for ANSI-C, another for C++,
1315 + * a third for old style C
1316 + */
1318 + for (i = 0; i < 3; i++) {
1319 + if (i == 0) {
1320 + f_print(fout, "\n#ifdef __cplusplus\n");
1321 + ext = "extern \"C\" ";
1322 + } else if (i == 1) {
1323 + f_print(fout, "\n#elif __STDC__\n");
1324 + ext = "extern ";
1325 + } else {
1326 + f_print(fout, "\n#else /* Old Style C */ \n");
1327 + ext = "extern ";
1331 + for (proc = vers->procs; proc != NULL; proc = proc->next) {
1332 + if (!define_printed(proc, def->def.pr.versions)) {
1333 + puldefine(proc->proc_name, proc->proc_num);
1335 + f_print(fout, "%s", ext);
1336 + pprocdef(proc, vers, "CLIENT *", 0, i);
1337 + f_print(fout, "%s", ext);
1338 + pprocdef(proc, vers, "struct svc_req *", 1, i);
1343 + f_print(fout, "#endif /* Old Style C */ \n");
1347 +static void
1348 +pprocdef(proc_list *proc, version_list *vp, char *addargtype,
1349 + int server_p, int mode)
1351 + ptype(proc->res_prefix, proc->res_type, 1);
1352 + f_print(fout, "* ");
1353 + if (server_p)
1354 + pvname_svc(proc->proc_name, vp->vers_num);
1355 + else
1356 + pvname(proc->proc_name, vp->vers_num);
1358 + /*
1359 + * mode 0 == cplusplus, mode 1 = ANSI-C, mode 2 = old style C
1360 + */
1361 + if (mode == 0 || mode == 1)
1362 + parglist(proc, addargtype);
1363 + else
1364 + f_print(fout, "();\n");
1369 +/* print out argument list of procedure */
1370 +static void
1371 +parglist(proc_list *proc, char *addargtype)
1373 + decl_list *dl;
1375 + f_print(fout, "(");
1377 + if (proc->arg_num < 2 && newstyle &&
1378 + streq(proc->args.decls->decl.type, "void")) {
1379 + /* 0 argument in new style: do nothing */
1380 + } else {
1381 + for (dl = proc->args.decls; dl != NULL; dl = dl->next) {
1382 + ptype(dl->decl.prefix, dl->decl.type, 1);
1383 + if (!newstyle)
1384 + f_print(fout, "*"); /* old style passes by reference */
1386 + f_print(fout, ", ");
1390 + f_print(fout, "%s);\n", addargtype);
1393 +static void
1394 +penumdef(definition *def)
1396 + char *name = def->def_name;
1397 + enumval_list *l;
1398 + char *last = NULL;
1399 + int count = 0;
1401 + f_print(fout, "enum %s {\n", name);
1402 + for (l = def->def.en.vals; l != NULL; l = l->next) {
1403 + f_print(fout, "\t%s", l->name);
1404 + if (l->assignment) {
1405 + f_print(fout, " = %s", l->assignment);
1406 + last = l->assignment;
1407 + count = 1;
1408 + } else {
1409 + if (last == NULL) {
1410 + f_print(fout, " = %d", count++);
1411 + } else {
1412 + f_print(fout, " = %s + %d", last, count++);
1415 + f_print(fout, ",\n");
1417 + f_print(fout, "};\n");
1418 + f_print(fout, "typedef enum %s %s;\n", name, name);
1421 +static void
1422 +ptypedef(definition *def)
1424 + char *name = def->def_name;
1425 + char *old = def->def.ty.old_type;
1426 + char prefix[8]; /* enough to contain "struct ", including NUL */
1427 + relation rel = def->def.ty.rel;
1430 + if (!streq(name, old)) {
1431 + if (streq(old, "string")) {
1432 + old = "char";
1433 + rel = REL_POINTER;
1434 + } else if (streq(old, "opaque")) {
1435 + old = "char";
1436 + } else if (streq(old, "bool")) {
1437 + old = "bool_t";
1439 + if (undefined2(old, name) && def->def.ty.old_prefix) {
1440 + s_print(prefix, "%s ", def->def.ty.old_prefix);
1441 + } else {
1442 + prefix[0] = 0;
1444 + f_print(fout, "typedef ");
1445 + switch (rel) {
1446 + case REL_ARRAY:
1447 + f_print(fout, "struct {\n");
1448 + f_print(fout, "\tu_int %s_len;\n", name);
1449 + f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name);
1450 + f_print(fout, "} %s", name);
1451 + break;
1452 + case REL_POINTER:
1453 + f_print(fout, "%s%s *%s", prefix, old, name);
1454 + break;
1455 + case REL_VECTOR:
1456 + f_print(fout, "%s%s %s[%s]", prefix, old, name,
1457 + def->def.ty.array_max);
1458 + break;
1459 + case REL_ALIAS:
1460 + f_print(fout, "%s%s %s", prefix, old, name);
1461 + break;
1463 + f_print(fout, ";\n");
1467 +void
1468 +pdeclaration(char *name, declaration *dec, int tab, char *separator)
1470 + char buf[8]; /* enough to hold "struct ", include NUL */
1471 + char *prefix;
1472 + char *type;
1474 + if (streq(dec->type, "void")) {
1475 + return;
1477 + tabify(fout, tab);
1478 + if (streq(dec->type, name) && !dec->prefix) {
1479 + f_print(fout, "struct ");
1481 + if (streq(dec->type, "string")) {
1482 + f_print(fout, "char *%s", dec->name);
1483 + } else {
1484 + prefix = "";
1485 + if (streq(dec->type, "bool")) {
1486 + type = "bool_t";
1487 + } else if (streq(dec->type, "opaque")) {
1488 + type = "char";
1489 + } else {
1490 + if (dec->prefix) {
1491 + s_print(buf, "%s ", dec->prefix);
1492 + prefix = buf;
1494 + type = dec->type;
1496 + switch (dec->rel) {
1497 + case REL_ALIAS:
1498 + f_print(fout, "%s%s %s", prefix, type, dec->name);
1499 + break;
1500 + case REL_VECTOR:
1501 + f_print(fout, "%s%s %s[%s]", prefix, type, dec->name,
1502 + dec->array_max);
1503 + break;
1504 + case REL_POINTER:
1505 + f_print(fout, "%s%s *%s", prefix, type, dec->name);
1506 + break;
1507 + case REL_ARRAY:
1508 + f_print(fout, "struct {\n");
1509 + tabify(fout, tab);
1510 + f_print(fout, "\tu_int %s_len;\n", dec->name);
1511 + tabify(fout, tab);
1512 + f_print(fout, "\t%s%s *%s_val;\n", prefix, type, dec->name);
1513 + tabify(fout, tab);
1514 + f_print(fout, "} %s", dec->name);
1515 + break;
1518 + f_print(fout, separator );
1521 +static int
1522 +undefined2(char *type, char *stop)
1524 + list *l;
1525 + definition *def;
1527 + for (l = defined; l != NULL; l = l->next) {
1528 + def = (definition *) l->val;
1529 + if (def->def_kind != DEF_PROGRAM) {
1530 + if (streq(def->def_name, stop)) {
1531 + return (1);
1532 + } else if (streq(def->def_name, type)) {
1533 + return (0);
1537 + return (1);
1539 diff --git a/rpcgen/rpc_main.c b/rpcgen/rpc_main.c
1540 new file mode 100644
1541 index 0000000..28aa60c
1542 --- /dev/null
1543 +++ b/rpcgen/rpc_main.c
1544 @@ -0,0 +1,1067 @@
1546 + * Copyright (c) 2009, Sun Microsystems, Inc.
1547 + * All rights reserved.
1549 + * Redistribution and use in source and binary forms, with or without
1550 + * modification, are permitted provided that the following conditions are met:
1551 + * - Redistributions of source code must retain the above copyright notice,
1552 + * this list of conditions and the following disclaimer.
1553 + * - Redistributions in binary form must reproduce the above copyright notice,
1554 + * this list of conditions and the following disclaimer in the documentation
1555 + * and/or other materials provided with the distribution.
1556 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
1557 + * contributors may be used to endorse or promote products derived
1558 + * from this software without specific prior written permission.
1560 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1561 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1562 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1563 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
1564 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1565 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1566 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1567 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1568 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1569 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1570 + * POSSIBILITY OF SUCH DAMAGE.
1571 + */
1573 +#if 0
1574 +static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI";
1575 +#endif
1578 + * rpc_main.c, Top level of the RPC protocol compiler.
1579 + */
1581 +#include <sys/types.h>
1582 +#include <sys/param.h>
1583 +#include <sys/file.h>
1584 +#include <sys/stat.h>
1585 +#include <stdio.h>
1586 +#include <string.h>
1587 +#include <stdlib.h>
1588 +#include <unistd.h>
1589 +#include <ctype.h>
1590 +#include <errno.h>
1591 +#include "rpc_parse.h"
1592 +#include "rpc_util.h"
1593 +#include "rpc_scan.h"
1595 +struct commandline {
1596 + int cflag; /* xdr C routines */
1597 + int hflag; /* header file */
1598 + int lflag; /* client side stubs */
1599 + int mflag; /* server side stubs */
1600 + int nflag; /* netid flag */
1601 + int sflag; /* server stubs for the given transport */
1602 + int tflag; /* dispatch Table file */
1603 + int Ssflag; /* produce server sample code */
1604 + int Scflag; /* produce client sample code */
1605 + char *infile; /* input module name */
1606 + char *outfile; /* output module name */
1609 +static char * extendfile(char *file, char *ext);
1610 +static void open_output(char *infile, char *outfile);
1611 +static void add_warning(void);
1612 +static void clear_args(void);
1613 +static void open_input(char *infile, char *define);
1614 +static int check_nettype(char *name, char **list_to_check);
1615 +static void c_output(char *infile, char *define, int extend, char *outfile);
1616 +static void c_initialize(void);
1617 +static char * generate_guard(char *pathname);
1618 +static void h_output(char *infile, char *define, int extend, char *outfile);
1619 +static void s_output(int argc, char **argv, char *infile,
1620 + char *define, int extend, char *outfile,
1621 + int nomain, int netflag);
1622 +static void l_output(char *infile, char *define, int extend, char *outfile);
1623 +static void t_output(char *infile, char *define, int extend, char *outfile);
1624 +static void svc_output(char *, char *, int, char *);
1625 +static void clnt_output(char *, char *, int, char *);
1626 +static int do_registers(int argc, char **argv);
1627 +static void addarg(char *cp);
1628 +static void putarg(int where, char *cp);
1629 +static void checkfiles(char *infile, char *outfile);
1630 +static int parseargs(int argc, char **argv, struct commandline *cmd);
1631 +static void usage(void);
1632 +static void options_usage(void);
1635 +extern void write_sample_svc();
1636 +int write_sample_clnt();
1637 +void write_sample_clnt_main();
1639 +static svc_output();
1640 + */
1642 +#define EXTEND 1 /* alias for TRUE */
1643 +#define DONT_EXTEND 0 /* alias for FALSE */
1645 +#define SVR4_CPP "/usr/ccs/lib/cpp"
1646 +#define SUNOS_CPP "/lib/cpp"
1647 +static int cppDefined = 0; /* explicit path for C preprocessor */
1650 +static char *cmdname;
1652 +static char *svcclosetime = "120";
1653 +static char *CPP = SVR4_CPP;
1654 +static char CPPFLAGS[] = "-C";
1655 +static char pathbuf[MAXPATHLEN + 1];
1656 +static char *allv[] = {
1657 + "rpcgen", "-s", "udp", "-s", "tcp",
1659 +static int allc = sizeof(allv)/sizeof(allv[0]);
1660 +static char *allnv[] = {
1661 + "rpcgen", "-s", "netpath",
1663 +static int allnc = sizeof(allnv)/sizeof(allnv[0]);
1666 + * machinations for handling expanding argument list
1667 + */
1668 +#if 0
1669 +static void addarg(); /* add another argument to the list */
1670 +static void putarg(); /* put argument at specified location */
1671 +static void clear_args(); /* clear argument list */
1672 +static void checkfiles(); /* check if out file already exists */
1673 +#endif
1677 +#define ARGLISTLEN 20
1678 +#define FIXEDARGS 2
1680 +static char *arglist[ARGLISTLEN];
1681 +static int argcount = FIXEDARGS;
1684 +int nonfatalerrors; /* errors */
1685 +int inetdflag/* = 1*/; /* Support for inetd */ /* is now the default */
1686 +int pmflag; /* Support for port monitors */
1687 +int logflag; /* Use syslog instead of fprintf for errors */
1688 +int tblflag; /* Support for dispatch table file */
1690 +/* length at which to start doing an inline */
1691 +#define INLINE 3
1693 +int Inline = INLINE; /* length at which to start doing an inline. 3 = default
1694 + * if 0, no xdr_inline code */
1696 +int indefinitewait; /* If started by port monitors, hang till it wants */
1697 +int exitnow; /* If started by port monitors, exit after the call */
1698 +int timerflag; /* TRUE if !indefinite && !exitnow */
1699 +int newstyle; /* newstyle of passing arguments (by value) */
1700 +int Cflag = 0 ; /* ANSI C syntax */
1701 +static int allfiles; /* generate all files */
1702 +#ifdef linux
1703 +int tirpcflag = 0; /* no tirpc by default */
1704 +#else
1705 +int tirpcflag = 1; /* generating code for tirpc, by default */
1706 +#endif
1708 +int
1709 +main(int argc, char **argv)
1711 + struct commandline cmd;
1713 + (void) memset((char *) &cmd, 0, sizeof(struct commandline));
1714 + clear_args();
1715 + if (!parseargs(argc, argv, &cmd))
1716 + usage();
1718 + if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag ||
1719 + cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) {
1720 + checkfiles(cmd.infile, cmd.outfile);
1721 + } else
1722 + checkfiles(cmd.infile, NULL);
1724 + if (cmd.cflag) {
1725 + c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile);
1726 + } else if (cmd.hflag) {
1727 + h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile);
1728 + } else if (cmd.lflag) {
1729 + l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile);
1730 + } else if (cmd.sflag || cmd.mflag || (cmd.nflag)) {
1731 + s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND,
1732 + cmd.outfile, cmd.mflag, cmd.nflag);
1733 + } else if (cmd.tflag) {
1734 + t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile);
1735 + } else if (cmd.Ssflag) {
1736 + svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile);
1737 + } else if (cmd.Scflag) {
1738 + clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile);
1739 + } else {
1740 + /* the rescans are required, since cpp may effect input */
1741 + c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c");
1742 + reinitialize();
1743 + h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h");
1744 + reinitialize();
1745 + l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c");
1746 + reinitialize();
1747 + if (inetdflag || !tirpcflag)
1748 + s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND,
1749 + "_svc.c", cmd.mflag, cmd.nflag);
1750 + else
1751 + s_output(allnc, allnv, cmd.infile, "-DRPC_SVC",
1752 + EXTEND, "_svc.c", cmd.mflag, cmd.nflag);
1753 + if (tblflag) {
1754 + reinitialize();
1755 + t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i");
1757 + if (allfiles) {
1758 + reinitialize();
1759 + svc_output(cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c");
1761 + if (allfiles) {
1762 + reinitialize();
1763 + clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c");
1766 + exit(nonfatalerrors);
1767 + /* NOTREACHED */
1771 + * add extension to filename
1772 + */
1773 +static char *
1774 +extendfile(char *file, char *ext)
1776 + char *res;
1777 + char *p;
1779 + res = alloc(strlen(file) + strlen(ext) + 1);
1780 + if (res == NULL) {
1781 + abort();
1783 + p = strrchr(file, '.');
1784 + if (p == NULL) {
1785 + p = file + strlen(file);
1787 + (void) strcpy(res, file);
1788 + (void) strcpy(res + (p - file), ext);
1789 + return (res);
1793 + * Open output file with given extension
1794 + */
1795 +static void
1796 +open_output(char *infile, char *outfile)
1799 + if (outfile == NULL) {
1800 + fout = stdout;
1801 + return;
1804 + if (infile != NULL && streq(outfile, infile)) {
1805 + f_print(stderr, "%s: output would overwrite %s\n", cmdname,
1806 + infile);
1807 + crash();
1809 + fout = fopen(outfile, "w");
1810 + if (fout == NULL) {
1811 + f_print(stderr, "%s: unable to open ", cmdname);
1812 + perror(outfile);
1813 + crash();
1815 + record_open(outfile);
1819 +static void
1820 +add_warning(void)
1822 + f_print(fout, "/*\n");
1823 + f_print(fout, " * Please do not edit this file.\n");
1824 + f_print(fout, " * It was generated using rpcgen.\n");
1825 + f_print(fout, " */\n\n");
1828 +/* clear list of arguments */
1829 +static void
1830 +clear_args(void)
1832 + int i;
1833 + for( i=FIXEDARGS; i<ARGLISTLEN; i++ )
1834 + arglist[i] = NULL;
1835 + argcount = FIXEDARGS;
1839 + * Open input file with given define for C-preprocessor
1840 + */
1841 +static void
1842 +open_input(char *infile, char *define)
1844 + int pd[2];
1846 + infilename = (infile == NULL) ? "<stdin>" : infile;
1847 + (void) pipe(pd);
1848 + switch (fork()) {
1849 + case 0:
1850 + putarg(0, "cpp");
1851 + putarg(1, CPPFLAGS);
1852 + addarg(define);
1853 + addarg(infile);
1854 + addarg((char *)NULL);
1855 + (void) close(1);
1856 + (void) dup2(pd[1], 1);
1857 + (void) close(pd[0]);
1858 + if (cppDefined)
1859 + execv(CPP, arglist);
1860 + else {
1861 + execvp("cpp", arglist);
1862 + if (errno == ENOENT)
1863 + execvp(SVR4_CPP, arglist);
1864 + if (errno == ENOENT)
1865 + execvp(SUNOS_CPP, arglist);
1867 + perror("execv");
1868 + exit(1);
1869 + case -1:
1870 + perror("fork");
1871 + exit(1);
1873 + (void) close(pd[1]);
1874 + fin = fdopen(pd[0], "r");
1875 + if (fin == NULL) {
1876 + f_print(stderr, "%s: ", cmdname);
1877 + perror(infilename);
1878 + crash();
1882 +/* valid tirpc nettypes */
1883 +static char* valid_ti_nettypes[] =
1885 + "netpath",
1886 + "visible",
1887 + "circuit_v",
1888 + "datagram_v",
1889 + "circuit_n",
1890 + "datagram_n",
1891 + "udp",
1892 + "tcp",
1893 + "raw",
1894 + NULL
1897 +/* valid inetd nettypes */
1898 +static char* valid_i_nettypes[] =
1900 + "udp",
1901 + "tcp",
1902 + NULL
1905 +static int
1906 +check_nettype(char *name, char **list_to_check)
1908 + int i;
1909 + for( i = 0; list_to_check[i] != NULL; i++ ) {
1910 + if( strcmp( name, list_to_check[i] ) == 0 ) {
1911 + return 1;
1914 + f_print( stderr, "illegal nettype :\'%s\'\n", name );
1915 + return 0;
1919 + * Compile into an XDR routine output file
1920 + */
1922 +static void
1923 +c_output(char *infile, char *define, int extend, char *outfile)
1925 + definition *def;
1926 + char *include;
1927 + char *outfilename;
1928 + long tell;
1930 + c_initialize();
1931 + open_input(infile, define);
1932 + outfilename = extend ? extendfile(infile, outfile) : outfile;
1933 + open_output(infile, outfilename);
1934 + add_warning();
1935 + if (infile && (include = extendfile(infile, ".h"))) {
1936 + f_print(fout, "#include \"%s\"\n", include);
1937 + free(include);
1938 + /* .h file already contains rpc/rpc.h */
1939 + } else
1940 + f_print(fout, "#include <rpc/rpc.h>\n");
1941 + tell = ftell(fout);
1942 + while ((def = get_definition()) != NULL) {
1943 + emit(def);
1945 + if (extend && tell == ftell(fout)) {
1946 + (void) unlink(outfilename);
1951 +static void
1952 +c_initialize(void)
1955 + /* add all the starting basic types */
1957 + add_type(1,"int");
1958 + add_type(1,"int32_t");
1959 + add_type(1,"short");
1960 + add_type(1,"bool");
1962 + add_type(1,"u_int");
1963 + add_type(1,"u_int32_t");
1964 + add_type(1,"u_short");
1968 +char rpcgen_table_dcl[] = "struct rpcgen_table {\n\
1969 + char *(*proc)();\n\
1970 + xdrproc_t xdr_arg;\n\
1971 + unsigned len_arg;\n\
1972 + xdrproc_t xdr_res;\n\
1973 + unsigned len_res;\n\
1974 +};\n";
1977 +static char *
1978 +generate_guard(char *pathname)
1980 + char* filename, *guard, *tmp;
1982 + filename = strrchr(pathname, '/' ); /* find last component */
1983 + filename = ((filename == 0) ? pathname : filename+1);
1984 + guard = strdup(filename);
1985 + /* convert to upper case */
1986 + tmp = guard;
1987 + while (*tmp) {
1988 + if (islower(*tmp))
1989 + *tmp = toupper(*tmp);
1990 + tmp++;
1993 + guard = extendfile(guard, "_H_RPCGEN");
1994 + return( guard );
1998 + * Compile into an XDR header file
1999 + */
2000 +static void
2001 +h_output(char *infile, char *define, int extend, char *outfile)
2003 + definition *def;
2004 + char *outfilename;
2005 + long tell;
2006 + char *guard;
2007 + list *l;
2009 + open_input(infile, define);
2010 + outfilename = extend ? extendfile(infile, outfile) : outfile;
2011 + open_output(infile, outfilename);
2012 + add_warning();
2013 + guard = generate_guard( outfilename ? outfilename: infile );
2015 + f_print(fout,"#ifndef _%s\n#define _%s\n\n", guard,
2016 + guard);
2018 + f_print(fout, "#include <rpc/rpc.h>\n\n");
2020 + f_print(fout, "#ifndef IXDR_GET_INT32\n");
2021 + f_print(fout, "#define IXDR_GET_INT32(buf) IXDR_GET_LONG((buf))\n");
2022 + f_print(fout, "#endif\n");
2023 + f_print(fout, "#ifndef IXDR_PUT_INT32\n");
2024 + f_print(fout, "#define IXDR_PUT_INT32(buf, v) IXDR_PUT_LONG((buf), (v))\n");
2025 + f_print(fout, "#endif\n");
2026 + f_print(fout, "#ifndef IXDR_GET_U_INT32\n");
2027 + f_print(fout, "#define IXDR_GET_U_INT32(buf) IXDR_GET_U_LONG((buf))\n");
2028 + f_print(fout, "#endif\n");
2029 + f_print(fout, "#ifndef IXDR_PUT_U_INT32\n");
2030 + f_print(fout, "#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_U_LONG((buf), (v))\n");
2031 + f_print(fout, "#endif\n");
2033 + tell = ftell(fout);
2034 + /* print data definitions */
2035 + while ((def = get_definition()) != NULL) {
2036 + print_datadef(def);
2039 + /* print function declarations.
2040 + Do this after data definitions because they might be used as
2041 + arguments for functions */
2042 + for (l = defined; l != NULL; l = l->next) {
2043 + print_funcdef(l->val);
2045 + if (extend && tell == ftell(fout)) {
2046 + (void) unlink(outfilename);
2047 + } else if (tblflag) {
2048 + f_print(fout, rpcgen_table_dcl);
2050 + f_print(fout, "\n#endif /* !_%s */\n", guard);
2054 + * Compile into an RPC service
2055 + */
2056 +static void
2057 +s_output(int argc, char **argv, char *infile, char *define, int extend,
2058 + char *outfile, int nomain, int netflag)
2060 + char *include;
2061 + definition *def;
2062 + int foundprogram = 0;
2063 + char *outfilename;
2065 + open_input(infile, define);
2066 + outfilename = extend ? extendfile(infile, outfile) : outfile;
2067 + open_output(infile, outfilename);
2068 + add_warning();
2069 + if (infile && (include = extendfile(infile, ".h"))) {
2070 + f_print(fout, "#include \"%s\"\n", include);
2071 + free(include);
2072 + } else
2073 + f_print(fout, "#include <rpc/rpc.h>\n");
2075 + f_print(fout, "#include <stdio.h>\n");
2076 + f_print(fout, "#include <stdlib.h>/* getenv, exit */\n");
2077 + if (Cflag) {
2078 + f_print (fout, "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n");
2079 + f_print (fout, "#include <string.h> /* strcmp */ \n");
2081 + if (strcmp(svcclosetime, "-1") == 0)
2082 + indefinitewait = 1;
2083 + else if (strcmp(svcclosetime, "0") == 0)
2084 + exitnow = 1;
2085 + else if (inetdflag || pmflag) {
2086 + f_print(fout, "#include <signal.h>\n");
2087 + timerflag = 1;
2090 +#ifndef linux
2091 + if( !tirpcflag && inetdflag )
2092 + f_print(fout, "#include <sys/ttycom.h>/* TIOCNOTTY */\n");
2093 +#else
2094 + if( !tirpcflag )
2095 + f_print(fout, "#include <sys/ioctl.h>/* TIOCNOTTY */\n");
2096 +#endif
2097 + if( Cflag && (inetdflag || pmflag ) ) {
2098 + f_print(fout, "#ifdef __cplusplus\n");
2099 + f_print(fout, "#include <sysent.h> /* getdtablesize, open */\n");
2100 + f_print(fout, "#endif /* __cplusplus */\n");
2102 + if( tirpcflag )
2103 + f_print(fout, "#include <unistd.h> /* setsid */\n");
2105 + if( tirpcflag )
2106 + f_print(fout, "#include <sys/types.h>\n");
2108 + f_print(fout, "#include <memory.h>\n");
2109 +#ifndef linux
2110 + f_print(fout, "#include <stropts.h>\n");
2111 +#endif
2112 + if (inetdflag || !tirpcflag ) {
2113 + f_print(fout, "#include <sys/socket.h>\n");
2114 + f_print(fout, "#include <netinet/in.h>\n");
2115 + }
2117 + if ( (netflag || pmflag) && tirpcflag ) {
2118 + f_print(fout, "#include <netconfig.h>\n");
2120 + if (/*timerflag &&*/ tirpcflag)
2121 + f_print(fout, "#include <sys/resource.h> /* rlimit */\n");
2122 + if (logflag || inetdflag || pmflag) {
2123 +#ifdef linux
2124 + f_print(fout, "#include <syslog.h>\n");
2125 +#else
2126 + f_print(fout, "#ifdef SYSLOG\n");
2127 + f_print(fout, "#include <syslog.h>\n");
2128 + f_print(fout, "#else\n");
2129 + f_print(fout, "#define LOG_ERR 1\n");
2130 + f_print(fout, "#define openlog(a, b, c)\n");
2131 + f_print(fout, "#endif\n");
2132 +#endif
2135 + /* for ANSI-C */
2136 + f_print(fout, "\n#ifdef __STDC__\n#define SIG_PF void(*)(int)\n#endif\n");
2138 + f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n");
2139 + if (timerflag)
2140 + f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime);
2141 + while ((def = get_definition()) != NULL) {
2142 + foundprogram |= (def->def_kind == DEF_PROGRAM);
2144 + if (extend && !foundprogram) {
2145 + (void) unlink(outfilename);
2146 + return;
2148 + write_most(infile, netflag, nomain);
2149 + if (!nomain) {
2150 + if( !do_registers(argc, argv) ) {
2151 + if (outfilename)
2152 + (void) unlink(outfilename);
2153 + usage();
2155 + write_rest();
2160 + * generate client side stubs
2161 + */
2162 +static void
2163 +l_output(char *infile, char *define, int extend, char *outfile)
2165 + char *include;
2166 + definition *def;
2167 + int foundprogram = 0;
2168 + char *outfilename;
2170 + open_input(infile, define);
2171 + outfilename = extend ? extendfile(infile, outfile) : outfile;
2172 + open_output(infile, outfilename);
2173 + add_warning();
2174 + if (Cflag)
2175 + f_print (fout, "#include <memory.h> /* for memset */\n");
2176 + if (infile && (include = extendfile(infile, ".h"))) {
2177 + f_print(fout, "#include \"%s\"\n", include);
2178 + free(include);
2179 + } else
2180 + f_print(fout, "#include <rpc/rpc.h>\n");
2181 + while ((def = get_definition()) != NULL) {
2182 + foundprogram |= (def->def_kind == DEF_PROGRAM);
2184 + if (extend && !foundprogram) {
2185 + (void) unlink(outfilename);
2186 + return;
2188 + write_stubs();
2192 + * generate the dispatch table
2193 + */
2194 +static void
2195 +t_output(char *infile, char *define, int extend, char *outfile)
2197 + definition *def;
2198 + int foundprogram = 0;
2199 + char *outfilename;
2201 + open_input(infile, define);
2202 + outfilename = extend ? extendfile(infile, outfile) : outfile;
2203 + open_output(infile, outfilename);
2204 + add_warning();
2205 + while ((def = get_definition()) != NULL) {
2206 + foundprogram |= (def->def_kind == DEF_PROGRAM);
2208 + if (extend && !foundprogram) {
2209 + (void) unlink(outfilename);
2210 + return;
2212 + write_tables();
2215 +/* sample routine for the server template */
2216 +static void
2217 +svc_output(char *infile, char *define, int extend, char *outfile)
2219 + definition *def;
2220 + char *include;
2221 + char *outfilename;
2222 + long tell;
2224 + open_input(infile, define);
2225 + outfilename = extend ? extendfile(infile, outfile) : outfile;
2226 + checkfiles(infile,outfilename); /*check if outfile already exists.
2227 + if so, print an error message and exit*/
2228 + open_output(infile, outfilename);
2229 + add_sample_msg();
2231 + if (infile && (include = extendfile(infile, ".h"))) {
2232 + f_print(fout, "#include \"%s\"\n", include);
2233 + free(include);
2234 + } else
2235 + f_print(fout, "#include <rpc/rpc.h>\n");
2237 + tell = ftell(fout);
2238 + while ((def = get_definition()) != NULL) {
2239 + write_sample_svc(def);
2241 + if (extend && tell == ftell(fout)) {
2242 + (void) unlink(outfilename);
2247 +/* sample main routine for client */
2248 +static void
2249 +clnt_output(char *infile, char *define, int extend, char *outfile)
2251 + definition *def;
2252 + char *include;
2253 + char *outfilename;
2254 + long tell;
2255 + int has_program = 0;
2257 + open_input(infile, define);
2258 + outfilename = extend ? extendfile(infile, outfile) : outfile;
2259 + checkfiles(infile, outfilename); /*check if outfile already exists.
2260 + if so, print an error message and exit*/
2262 + open_output(infile, outfilename);
2263 + add_sample_msg();
2264 + if (infile && (include = extendfile(infile, ".h"))) {
2265 + f_print(fout, "#include \"%s\"\n", include);
2266 + free(include);
2267 + } else
2268 + f_print(fout, "#include <rpc/rpc.h>\n");
2269 + tell = ftell(fout);
2270 + while ((def = get_definition()) != NULL) {
2271 + has_program += write_sample_clnt(def);
2274 + if (has_program)
2275 + write_sample_clnt_main();
2277 + if (extend && tell == ftell(fout)) {
2278 + (void) unlink(outfilename);
2283 + * Perform registrations for service output
2284 + * Return 0 if failed; 1 otherwise.
2285 + */
2286 +static int
2287 +do_registers(int argc, char **argv)
2289 + int i;
2291 + if (inetdflag || !tirpcflag) {
2292 + for (i = 1; i < argc; i++) {
2293 + if (streq(argv[i], "-s")) {
2294 + if (!check_nettype(argv[i + 1], valid_i_nettypes))
2295 + return 0;
2296 + write_inetd_register(argv[i + 1]);
2297 + i++;
2300 + } else {
2301 + for (i = 1; i < argc; i++)
2302 + if (streq(argv[i], "-s")) {
2303 + if (!check_nettype(argv[i + 1], valid_ti_nettypes))
2304 + return 0;
2305 + write_nettype_register(argv[i + 1]);
2306 + i++;
2307 + } else if (streq(argv[i], "-n")) {
2308 + write_netid_register(argv[i + 1]);
2309 + i++;
2312 + return 1;
2316 + * Add another argument to the arg list
2317 + */
2318 +static void
2319 +addarg(char *cp)
2321 + if (argcount >= ARGLISTLEN) {
2322 + f_print(stderr, "rpcgen: too many defines\n");
2323 + crash();
2324 + /*NOTREACHED*/
2326 + arglist[argcount++] = cp;
2330 +static void
2331 +putarg(int where, char *cp)
2333 + if (where >= ARGLISTLEN) {
2334 + f_print(stderr, "rpcgen: arglist coding error\n");
2335 + crash();
2336 + /*NOTREACHED*/
2338 + arglist[where] = cp;
2343 + * if input file is stdin and an output file is specified then complain
2344 + * if the file already exists. Otherwise the file may get overwritten
2345 + * If input file does not exist, exit with an error
2346 + */
2348 +static void
2349 +checkfiles(char *infile, char *outfile)
2352 + struct stat buf;
2354 + if(infile) /* infile ! = NULL */
2355 + if(stat(infile,&buf) < 0)
2357 + perror(infile);
2358 + crash();
2359 + };
2360 + if (outfile) {
2361 + if (stat(outfile, &buf) < 0)
2362 + return; /* file does not exist */
2363 + else {
2364 + f_print(stderr,
2365 + "file '%s' already exists and may be overwritten\n", outfile);
2366 + crash();
2372 + * Parse command line arguments
2373 + */
2374 +static int
2375 +parseargs(int argc, char **argv, struct commandline *cmd)
2377 + int i;
2378 + int j;
2379 + char c;
2380 + char flag[(1 << 8 * sizeof(char))];
2381 + int nflags;
2383 + cmdname = argv[0];
2384 + cmd->infile = cmd->outfile = NULL;
2385 + if (argc < 2) {
2386 + return (0);
2388 + allfiles = 0;
2389 + flag['c'] = 0;
2390 + flag['h'] = 0;
2391 + flag['l'] = 0;
2392 + flag['m'] = 0;
2393 + flag['o'] = 0;
2394 + flag['s'] = 0;
2395 + flag['n'] = 0;
2396 + flag['t'] = 0;
2397 + flag['S'] = 0;
2398 + flag['C'] = 0;
2399 + for (i = 1; i < argc; i++) {
2400 + if (argv[i][0] != '-') {
2401 + if (cmd->infile) {
2402 + f_print( stderr, "Cannot specify more than one input file!\n");
2404 + return (0);
2406 + cmd->infile = argv[i];
2407 + } else {
2408 + for (j = 1; argv[i][j] != 0; j++) {
2409 + c = argv[i][j];
2410 + switch (c) {
2411 + case 'a':
2412 + allfiles = 1;
2413 + break;
2414 + case 'c':
2415 + case 'h':
2416 + case 'l':
2417 + case 'm':
2418 + case 't':
2419 + if (flag[(int) c]) {
2420 + return (0);
2422 + flag[(int) c] = 1;
2423 + break;
2424 + case 'S':
2425 + /* sample flag: Ss or Sc.
2426 + Ss means set flag['S'];
2427 + Sc means set flag['C']; */
2428 + c = argv[i][++j]; /* get next char */
2429 + if( c == 's' )
2430 + c = 'S';
2431 + else if( c == 'c' )
2432 + c = 'C';
2433 + else
2434 + return( 0 );
2436 + if (flag[(int) c]) {
2437 + return (0);
2439 + flag[(int) c] = 1;
2440 + break;
2441 + case 'C': /* ANSI C syntax */
2442 + Cflag = 1;
2443 + break;
2445 + case 'b': /* turn TIRPC flag off for
2446 + generating backward compatible
2447 + */
2448 + tirpcflag = 0;
2449 + break;
2451 + case 'I':
2452 + inetdflag = 1;
2453 + break;
2454 + case 'N':
2455 + newstyle = 1;
2456 + break;
2457 + case 'L':
2458 + logflag = 1;
2459 + break;
2460 + case 'K':
2461 + if (++i == argc) {
2462 + return (0);
2464 + svcclosetime = argv[i];
2465 + goto nextarg;
2466 + case 'T':
2467 + tblflag = 1;
2468 + break;
2469 + case 'i' :
2470 + if (++i == argc) {
2471 + return (0);
2473 + Inline = atoi(argv[i]);
2474 + goto nextarg;
2475 + case 'n':
2476 + case 'o':
2477 + case 's':
2478 + if (argv[i][j - 1] != '-' ||
2479 + argv[i][j + 1] != 0) {
2480 + return (0);
2482 + flag[(int) c] = 1;
2483 + if (++i == argc) {
2484 + return (0);
2486 + if (c == 's') {
2487 + if (!streq(argv[i], "udp") &&
2488 + !streq(argv[i], "tcp")) {
2489 + return (0);
2491 + } else if (c == 'o') {
2492 + if (cmd->outfile) {
2493 + return (0);
2495 + cmd->outfile = argv[i];
2497 + goto nextarg;
2498 + case 'D':
2499 + if (argv[i][j - 1] != '-') {
2500 + return (0);
2502 + (void) addarg(argv[i]);
2503 + goto nextarg;
2504 + case 'Y':
2505 + if (++i == argc) {
2506 + return (0);
2508 + (void) strcpy(pathbuf, argv[i]);
2509 + (void) strcat(pathbuf, "/cpp");
2510 + CPP = pathbuf;
2511 + cppDefined = 1;
2512 + goto nextarg;
2516 + default:
2517 + return (0);
2520 + nextarg:
2525 + cmd->cflag = flag['c'];
2526 + cmd->hflag = flag['h'];
2527 + cmd->lflag = flag['l'];
2528 + cmd->mflag = flag['m'];
2529 + cmd->nflag = flag['n'];
2530 + cmd->sflag = flag['s'];
2531 + cmd->tflag = flag['t'];
2532 + cmd->Ssflag = flag['S'];
2533 + cmd->Scflag = flag['C'];
2535 + if( tirpcflag ) {
2536 + pmflag = inetdflag ? 0 : 1; /* pmflag or inetdflag is always TRUE */
2537 + if( (inetdflag && cmd->nflag)) { /* netid not allowed with inetdflag */
2538 + f_print(stderr, "Cannot use netid flag with inetd flag!\n");
2539 + return (0);
2541 + } else { /* 4.1 mode */
2542 + pmflag = 0; /* set pmflag only in tirpcmode */
2543 + inetdflag = 1; /* inetdflag is TRUE by default */
2544 + if( cmd->nflag ) { /* netid needs TIRPC */
2545 + f_print( stderr, "Cannot use netid flag without TIRPC!\n");
2546 + return( 0 );
2550 + if( newstyle && ( tblflag || cmd->tflag) ) {
2551 + f_print( stderr, "Cannot use table flags with newstyle!\n");
2552 + return( 0 );
2555 + /* check no conflicts with file generation flags */
2556 + nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag +
2557 + cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag;
2559 + if (nflags == 0) {
2560 + if (cmd->outfile != NULL || cmd->infile == NULL) {
2561 + return (0);
2563 + } else if (nflags > 1) {
2564 + f_print( stderr, "Cannot have more than one file generation flag!\n");
2565 + return (0);
2567 + return (1);
2570 +static void
2571 +usage(void)
2573 + f_print(stderr, "usage: %s infile\n", cmdname);
2574 + f_print(stderr, "\t%s [-a][-b][-C][-Dname[=value]] -i size [-I [-K seconds]] [-L][-N][-T] infile\n",
2575 + cmdname);
2576 + f_print(stderr, "\t%s [-c | -h | -l | -m | -t | -Sc | -Ss] [-o outfile] [infile]\n",
2577 + cmdname);
2578 + f_print(stderr, "\t%s [-s nettype]* [-o outfile] [infile]\n", cmdname);
2579 + f_print(stderr, "\t%s [-n netid]* [-o outfile] [infile]\n", cmdname);
2580 + options_usage();
2581 + exit(1);
2584 +static void
2585 +options_usage(void)
2587 + f_print(stderr, "options:\n");
2588 + f_print(stderr, "-a\t\tgenerate all files, including samples\n");
2589 + f_print(stderr, "-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n");
2590 + f_print(stderr, "-c\t\tgenerate XDR routines\n");
2591 + f_print(stderr, "-C\t\tANSI C mode\n");
2592 + f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n");
2593 + f_print(stderr, "-h\t\tgenerate header file\n");
2594 + f_print(stderr, "-i size\t\tsize at which to start generating inline code\n");
2595 + f_print(stderr, "-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n");
2596 + f_print(stderr, "-K seconds\tserver exits after K seconds of inactivity\n");
2597 + f_print(stderr, "-l\t\tgenerate client side stubs\n");
2598 + f_print(stderr, "-L\t\tserver errors will be printed to syslog\n");
2599 + f_print(stderr, "-m\t\tgenerate server side stubs\n");
2600 + f_print(stderr, "-n netid\tgenerate server code that supports named netid\n");
2601 + f_print(stderr, "-N\t\tsupports multiple arguments and call-by-value\n");
2602 + f_print(stderr, "-o outfile\tname of the output file\n");
2603 + f_print(stderr, "-s nettype\tgenerate server code that supports named nettype\n");
2604 + f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote procedures\n");
2605 + f_print(stderr, "-Ss\t\tgenerate sample server code that defines remote procedures\n");
2606 + f_print(stderr, "-t\t\tgenerate RPC dispatch table\n");
2607 + f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n");
2608 + f_print(stderr, "-Y path\t\tdirectory name to find C preprocessor (cpp)\n");
2610 + exit(1);
2612 diff --git a/rpcgen/rpc_output.h b/rpcgen/rpc_output.h
2613 new file mode 100644
2614 index 0000000..eb25a60
2615 --- /dev/null
2616 +++ b/rpcgen/rpc_output.h
2617 @@ -0,0 +1,16 @@
2619 + * rpc_output.h
2621 + * Declarations for output functions
2623 + */
2625 +#ifndef RPCGEN_NEW_OUTPUT_H
2626 +#define RPCGEN_NEW_OUTPUT_H
2628 +void write_msg_out(void);
2629 +int nullproc(proc_list *);
2630 +void printarglist(proc_list *, char *, char *);
2631 +void pdeclaration(char *, declaration *, int, char *);
2633 +#endif /* RPCGEN_NEW_OUTPUT_H */
2634 diff --git a/rpcgen/rpc_parse.c b/rpcgen/rpc_parse.c
2635 new file mode 100644
2636 index 0000000..b53a553
2637 --- /dev/null
2638 +++ b/rpcgen/rpc_parse.c
2639 @@ -0,0 +1,609 @@
2641 + * Copyright (c) 2009, Sun Microsystems, Inc.
2642 + * All rights reserved.
2644 + * Redistribution and use in source and binary forms, with or without
2645 + * modification, are permitted provided that the following conditions are met:
2646 + * - Redistributions of source code must retain the above copyright notice,
2647 + * this list of conditions and the following disclaimer.
2648 + * - Redistributions in binary form must reproduce the above copyright notice,
2649 + * this list of conditions and the following disclaimer in the documentation
2650 + * and/or other materials provided with the distribution.
2651 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
2652 + * contributors may be used to endorse or promote products derived
2653 + * from this software without specific prior written permission.
2655 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2656 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2657 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2658 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2659 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2660 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2661 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2662 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2663 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2664 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2665 + * POSSIBILITY OF SUCH DAMAGE.
2666 + */
2668 +#if 0
2669 +static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI";
2670 +#endif
2673 + * rpc_parse.c, Parser for the RPC protocol compiler
2674 + * Copyright (C) 1987 Sun Microsystems, Inc.
2675 + */
2676 +#include <stdio.h>
2677 +#include <string.h>
2678 +#include "rpc/types.h"
2679 +#include "rpc_scan.h"
2680 +#include "rpc_parse.h"
2681 +#include "rpc_util.h"
2683 +#define ARGNAME "arg"
2686 +extern char *make_argname();
2687 +extern char *strdup();
2688 + */
2690 +static void isdefined(definition *defp);
2691 +static void def_struct(definition *defp);
2692 +static void def_program(definition *defp);
2693 +static void def_enum(definition *defp);
2694 +static void def_const(definition *defp);
2695 +static void def_union(definition *defp);
2696 +static void check_type_name(char *name, int new_type);
2697 +static void def_typedef(definition *defp);
2698 +static void get_declaration(declaration *dec, defkind dkind);
2699 +static void get_prog_declaration(declaration *dec, defkind dkind, int num);
2700 +static void get_type(char **prefixp, char **typep, defkind dkind);
2701 +static void unsigned_dec(char **typep);
2704 + * return the next definition you see
2705 + */
2706 +definition *
2707 +get_definition(void)
2709 + definition *defp;
2710 + token tok;
2712 + defp = ALLOC(definition);
2713 + get_token(&tok);
2714 + switch (tok.kind) {
2715 + case TOK_STRUCT:
2716 + def_struct(defp);
2717 + break;
2718 + case TOK_UNION:
2719 + def_union(defp);
2720 + break;
2721 + case TOK_TYPEDEF:
2722 + def_typedef(defp);
2723 + break;
2724 + case TOK_ENUM:
2725 + def_enum(defp);
2726 + break;
2727 + case TOK_PROGRAM:
2728 + def_program(defp);
2729 + break;
2730 + case TOK_CONST:
2731 + def_const(defp);
2732 + break;
2733 + case TOK_EOF:
2734 + free(defp);
2735 + return (NULL);
2736 + default:
2737 + error("definition keyword expected");
2739 + scan(TOK_SEMICOLON, &tok);
2740 + isdefined(defp);
2741 + return (defp);
2744 +static void
2745 +isdefined(definition *defp)
2747 + STOREVAL(&defined, defp);
2750 +static void
2751 +def_struct(definition *defp)
2753 + token tok;
2754 + declaration dec;
2755 + decl_list *decls;
2756 + decl_list **tailp;
2758 + defp->def_kind = DEF_STRUCT;
2760 + scan(TOK_IDENT, &tok);
2761 + defp->def_name = tok.str;
2762 + scan(TOK_LBRACE, &tok);
2763 + tailp = &defp->def.st.decls;
2764 + do {
2765 + get_declaration(&dec, DEF_STRUCT);
2766 + decls = ALLOC(decl_list);
2767 + decls->decl = dec;
2768 + *tailp = decls;
2769 + tailp = &decls->next;
2770 + scan(TOK_SEMICOLON, &tok);
2771 + peek(&tok);
2772 + } while (tok.kind != TOK_RBRACE);
2773 + get_token(&tok);
2774 + *tailp = NULL;
2777 +static void
2778 +def_program(definition *defp)
2780 + token tok;
2781 + declaration dec;
2782 + decl_list *decls;
2783 + decl_list **tailp;
2784 + version_list *vlist;
2785 + version_list **vtailp;
2786 + proc_list *plist;
2787 + proc_list **ptailp;
2788 + int num_args;
2789 + bool_t isvoid = FALSE; /* whether first argument is void */
2790 + defp->def_kind = DEF_PROGRAM;
2791 + scan(TOK_IDENT, &tok);
2792 + defp->def_name = tok.str;
2793 + scan(TOK_LBRACE, &tok);
2794 + vtailp = &defp->def.pr.versions;
2795 + tailp = &defp->def.st.decls;
2796 + scan(TOK_VERSION, &tok);
2797 + do {
2798 + scan(TOK_IDENT, &tok);
2799 + vlist = ALLOC(version_list);
2800 + vlist->vers_name = tok.str;
2801 + scan(TOK_LBRACE, &tok);
2802 + ptailp = &vlist->procs;
2803 + do {
2804 + /* get result type */
2805 + plist = ALLOC(proc_list);
2806 + get_type(&plist->res_prefix, &plist->res_type,
2807 + DEF_PROGRAM);
2808 + if (streq(plist->res_type, "opaque")) {
2809 + error("illegal result type");
2811 + scan(TOK_IDENT, &tok);
2812 + plist->proc_name = tok.str;
2813 + scan(TOK_LPAREN, &tok);
2814 + /* get args - first one*/
2815 + num_args = 1;
2816 + isvoid = FALSE;
2817 + /* type of DEF_PROGRAM in the first
2818 + * get_prog_declaration and DEF_STURCT in the next
2819 + * allows void as argument if it is the only argument
2820 + */
2821 + get_prog_declaration(&dec, DEF_PROGRAM, num_args);
2822 + if (streq(dec.type, "void"))
2823 + isvoid = TRUE;
2824 + decls = ALLOC(decl_list);
2825 + plist->args.decls = decls;
2826 + decls->decl = dec;
2827 + tailp = &decls->next;
2828 + /* get args */
2829 + while(peekscan(TOK_COMMA, &tok)) {
2830 + num_args++;
2831 + get_prog_declaration(&dec, DEF_STRUCT,
2832 + num_args);
2833 + decls = ALLOC(decl_list);
2834 + decls->decl = dec;
2835 + *tailp = decls;
2836 + if (streq(dec.type, "void"))
2837 + isvoid = TRUE;
2838 + tailp = &decls->next;
2840 + /* multiple arguments are only allowed in newstyle */
2841 + if( !newstyle && num_args > 1 ) {
2842 + error("only one argument is allowed" );
2844 + if (isvoid && num_args > 1) {
2845 + error("illegal use of void in program definition");
2847 + *tailp = NULL;
2848 + scan(TOK_RPAREN, &tok);
2849 + scan(TOK_EQUAL, &tok);
2850 + scan_num(&tok);
2851 + scan(TOK_SEMICOLON, &tok);
2852 + plist->proc_num = tok.str;
2853 + plist->arg_num = num_args;
2854 + *ptailp = plist;
2855 + ptailp = &plist->next;
2856 + peek(&tok);
2857 + } while (tok.kind != TOK_RBRACE);
2858 + *ptailp = NULL;
2859 + *vtailp = vlist;
2860 + vtailp = &vlist->next;
2861 + scan(TOK_RBRACE, &tok);
2862 + scan(TOK_EQUAL, &tok);
2863 + scan_num(&tok);
2864 + vlist->vers_num = tok.str;
2865 + /* make the argument structure name for each arg*/
2866 + for(plist = vlist->procs; plist != NULL;
2867 + plist = plist->next) {
2868 + plist->args.argname = make_argname(plist->proc_name,
2869 + vlist->vers_num);
2870 + /* free the memory ??*/
2872 + scan(TOK_SEMICOLON, &tok);
2873 + scan2(TOK_VERSION, TOK_RBRACE, &tok);
2874 + } while (tok.kind == TOK_VERSION);
2875 + scan(TOK_EQUAL, &tok);
2876 + scan_num(&tok);
2877 + defp->def.pr.prog_num = tok.str;
2878 + *vtailp = NULL;
2882 +static void
2883 +def_enum(definition *defp)
2885 + token tok;
2886 + enumval_list *elist;
2887 + enumval_list **tailp;
2889 + defp->def_kind = DEF_ENUM;
2890 + scan(TOK_IDENT, &tok);
2891 + defp->def_name = tok.str;
2892 + scan(TOK_LBRACE, &tok);
2893 + tailp = &defp->def.en.vals;
2894 + do {
2895 + scan(TOK_IDENT, &tok);
2896 + elist = ALLOC(enumval_list);
2897 + elist->name = tok.str;
2898 + elist->assignment = NULL;
2899 + scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
2900 + if (tok.kind == TOK_EQUAL) {
2901 + scan_num(&tok);
2902 + elist->assignment = tok.str;
2903 + scan2(TOK_COMMA, TOK_RBRACE, &tok);
2905 + *tailp = elist;
2906 + tailp = &elist->next;
2907 + } while (tok.kind != TOK_RBRACE);
2908 + *tailp = NULL;
2911 +static void
2912 +def_const(definition *defp)
2914 + token tok;
2916 + defp->def_kind = DEF_CONST;
2917 + scan(TOK_IDENT, &tok);
2918 + defp->def_name = tok.str;
2919 + scan(TOK_EQUAL, &tok);
2920 + scan2(TOK_IDENT, TOK_STRCONST, &tok);
2921 + defp->def.co = tok.str;
2924 +static void
2925 +def_union(definition *defp)
2927 + token tok;
2928 + declaration dec;
2929 + case_list *cases;
2930 + case_list **tailp;
2932 + defp->def_kind = DEF_UNION;
2933 + scan(TOK_IDENT, &tok);
2934 + defp->def_name = tok.str;
2935 + scan(TOK_SWITCH, &tok);
2936 + scan(TOK_LPAREN, &tok);
2937 + get_declaration(&dec, DEF_UNION);
2938 + defp->def.un.enum_decl = dec;
2939 + tailp = &defp->def.un.cases;
2940 + scan(TOK_RPAREN, &tok);
2941 + scan(TOK_LBRACE, &tok);
2942 + scan(TOK_CASE, &tok);
2943 + while (tok.kind == TOK_CASE) {
2944 + scan2(TOK_IDENT, TOK_CHARCONST, &tok);
2945 + cases = ALLOC(case_list);
2946 + cases->case_name = tok.str;
2947 + scan(TOK_COLON, &tok);
2948 + /* now peek at next token */
2949 + if(peekscan(TOK_CASE,&tok))
2952 + do
2954 + scan2(TOK_IDENT, TOK_CHARCONST, &tok);
2955 + cases->contflag=1; /* continued case statement */
2956 + *tailp = cases;
2957 + tailp = &cases->next;
2958 + cases = ALLOC(case_list);
2959 + cases->case_name = tok.str;
2960 + scan(TOK_COLON, &tok);
2962 + }while(peekscan(TOK_CASE,&tok));
2965 + get_declaration(&dec, DEF_UNION);
2966 + cases->case_decl = dec;
2967 + cases->contflag=0; /* no continued case statement */
2968 + *tailp = cases;
2969 + tailp = &cases->next;
2970 + scan(TOK_SEMICOLON, &tok);
2972 + scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
2974 + *tailp = NULL;
2975 + if (tok.kind == TOK_DEFAULT) {
2976 + scan(TOK_COLON, &tok);
2977 + get_declaration(&dec, DEF_UNION);
2978 + defp->def.un.default_decl = ALLOC(declaration);
2979 + *defp->def.un.default_decl = dec;
2980 + scan(TOK_SEMICOLON, &tok);
2981 + scan(TOK_RBRACE, &tok);
2982 + } else {
2983 + defp->def.un.default_decl = NULL;
2987 +static char* reserved_words[] =
2989 + "array",
2990 + "bytes",
2991 + "destroy",
2992 + "free",
2993 + "getpos",
2994 + "inline",
2995 + "pointer",
2996 + "reference",
2997 + "setpos",
2998 + "sizeof",
2999 + "union",
3000 + "vector",
3001 + NULL
3002 + };
3004 +static char* reserved_types[] =
3006 + "opaque",
3007 + "string",
3008 + NULL
3009 + };
3011 +/* check that the given name is not one that would eventually result in
3012 + xdr routines that would conflict with internal XDR routines. */
3013 +static void
3014 +check_type_name(char *name, int new_type)
3016 + int i;
3017 + char tmp[100];
3019 + for( i = 0; reserved_words[i] != NULL; i++ ) {
3020 + if( strcmp( name, reserved_words[i] ) == 0 ) {
3021 + sprintf(tmp,
3022 + "illegal (reserved) name :\'%s\' in type definition", name );
3023 + error(tmp);
3026 + if( new_type ) {
3027 + for( i = 0; reserved_types[i] != NULL; i++ ) {
3028 + if( strcmp( name, reserved_types[i] ) == 0 ) {
3029 + sprintf(tmp,
3030 + "illegal (reserved) name :\'%s\' in type definition", name );
3031 + error(tmp);
3037 +static void
3038 +def_typedef(definition *defp)
3040 + declaration dec;
3042 + defp->def_kind = DEF_TYPEDEF;
3043 + get_declaration(&dec, DEF_TYPEDEF);
3044 + defp->def_name = dec.name;
3045 + check_type_name( dec.name, 1 );
3046 + defp->def.ty.old_prefix = dec.prefix;
3047 + defp->def.ty.old_type = dec.type;
3048 + defp->def.ty.rel = dec.rel;
3049 + defp->def.ty.array_max = dec.array_max;
3052 +static void
3053 +get_declaration(declaration *dec, defkind dkind)
3055 + token tok;
3057 + get_type(&dec->prefix, &dec->type, dkind);
3058 + dec->rel = REL_ALIAS;
3059 + if (streq(dec->type, "void")) {
3060 + return;
3063 + check_type_name( dec->type, 0 );
3065 + scan2(TOK_STAR, TOK_IDENT, &tok);
3066 + if (tok.kind == TOK_STAR) {
3067 + dec->rel = REL_POINTER;
3068 + scan(TOK_IDENT, &tok);
3070 + dec->name = tok.str;
3071 + if (peekscan(TOK_LBRACKET, &tok)) {
3072 + if (dec->rel == REL_POINTER) {
3073 + error("no array-of-pointer declarations -- use typedef");
3075 + dec->rel = REL_VECTOR;
3076 + scan_num(&tok);
3077 + dec->array_max = tok.str;
3078 + scan(TOK_RBRACKET, &tok);
3079 + } else if (peekscan(TOK_LANGLE, &tok)) {
3080 + if (dec->rel == REL_POINTER) {
3081 + error("no array-of-pointer declarations -- use typedef");
3083 + dec->rel = REL_ARRAY;
3084 + if (peekscan(TOK_RANGLE, &tok)) {
3085 + dec->array_max = "~0"; /* unspecified size, use max */
3086 + } else {
3087 + scan_num(&tok);
3088 + dec->array_max = tok.str;
3089 + scan(TOK_RANGLE, &tok);
3092 + if (streq(dec->type, "opaque")) {
3093 + if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
3094 + error("array declaration expected");
3096 + } else if (streq(dec->type, "string")) {
3097 + if (dec->rel != REL_ARRAY) {
3098 + error("variable-length array declaration expected");
3104 +static void
3105 +get_prog_declaration(declaration *dec, defkind dkind, int num)
3107 + token tok;
3108 + char name[10]; /* argument name */
3110 + if (dkind == DEF_PROGRAM) {
3111 + peek(&tok);
3112 + if (tok.kind == TOK_RPAREN) { /* no arguments */
3113 + dec->rel = REL_ALIAS;
3114 + dec->type = "void";
3115 + dec->prefix = NULL;
3116 + dec->name = NULL;
3117 + return;
3120 + get_type(&dec->prefix, &dec->type, dkind);
3121 + dec->rel = REL_ALIAS;
3122 + if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
3123 + strcpy(name, tok.str);
3124 + else
3125 + sprintf(name, "%s%d", ARGNAME, num); /* default name of argument */
3127 + dec->name = (char *) strdup(name);
3129 + if (streq(dec->type, "void")) {
3130 + return;
3133 + if (streq(dec->type, "opaque")) {
3134 + error("opaque -- illegal argument type");
3136 + if (peekscan(TOK_STAR, &tok)) {
3137 + if (streq(dec->type, "string")) {
3138 + error("pointer to string not allowed in program arguments\n");
3140 + dec->rel = REL_POINTER;
3141 + if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
3142 + dec->name = strdup(tok.str);
3144 + if (peekscan(TOK_LANGLE, &tok)) {
3145 + if (!streq(dec->type, "string")) {
3146 + error("arrays cannot be declared as arguments to procedures -- use typedef");
3148 + dec->rel = REL_ARRAY;
3149 + if (peekscan(TOK_RANGLE, &tok)) {
3150 + dec->array_max = "~0";/* unspecified size, use max */
3151 + } else {
3152 + scan_num(&tok);
3153 + dec->array_max = tok.str;
3154 + scan(TOK_RANGLE, &tok);
3157 + if (streq(dec->type, "string")) {
3158 + if (dec->rel != REL_ARRAY) { /* .x specifies just string as
3159 + * type of argument
3160 + * - make it string<>
3161 + */
3162 + dec->rel = REL_ARRAY;
3163 + dec->array_max = "~0";/* unspecified size, use max */
3170 +static void
3171 +get_type(char **prefixp, char **typep, defkind dkind)
3173 + token tok;
3175 + *prefixp = NULL;
3176 + get_token(&tok);
3177 + switch (tok.kind) {
3178 + case TOK_IDENT:
3179 + *typep = tok.str;
3180 + break;
3181 + case TOK_STRUCT:
3182 + case TOK_ENUM:
3183 + case TOK_UNION:
3184 + *prefixp = tok.str;
3185 + scan(TOK_IDENT, &tok);
3186 + *typep = tok.str;
3187 + break;
3188 + case TOK_UNSIGNED:
3189 + unsigned_dec(typep);
3190 + break;
3191 + case TOK_SHORT:
3192 + *typep = "short";
3193 + (void) peekscan(TOK_INT, &tok);
3194 + break;
3195 + case TOK_INT32:
3196 + *typep = "int32_t";
3197 + (void) peekscan(TOK_INT, &tok);
3198 + break;
3199 + case TOK_VOID:
3200 + if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
3201 + error("voids allowed only inside union and program definitions with one argument");
3203 + *typep = tok.str;
3204 + break;
3205 + case TOK_STRING:
3206 + case TOK_OPAQUE:
3207 + case TOK_CHAR:
3208 + case TOK_INT:
3209 + case TOK_FLOAT:
3210 + case TOK_DOUBLE:
3211 + case TOK_BOOL:
3212 + *typep = tok.str;
3213 + break;
3214 + default:
3215 + error("expected type specifier");
3219 +static void
3220 +unsigned_dec(char **typep)
3222 + token tok;
3224 + peek(&tok);
3225 + switch (tok.kind) {
3226 + case TOK_CHAR:
3227 + get_token(&tok);
3228 + *typep = "u_char";
3229 + break;
3230 + case TOK_SHORT:
3231 + get_token(&tok);
3232 + *typep = "u_short";
3233 + (void) peekscan(TOK_INT, &tok);
3234 + break;
3235 + case TOK_INT32:
3236 + get_token(&tok);
3237 + *typep = "u_int32_";
3238 + (void) peekscan(TOK_INT, &tok);
3239 + break;
3240 + case TOK_INT:
3241 + get_token(&tok);
3242 + *typep = "u_int";
3243 + break;
3244 + default:
3245 + *typep = "u_int";
3246 + break;
3249 diff --git a/rpcgen/rpc_parse.h b/rpcgen/rpc_parse.h
3250 new file mode 100644
3251 index 0000000..2afae10
3252 --- /dev/null
3253 +++ b/rpcgen/rpc_parse.h
3254 @@ -0,0 +1,166 @@
3256 + * Copyright (c) 2009, Sun Microsystems, Inc.
3257 + * All rights reserved.
3259 + * Redistribution and use in source and binary forms, with or without
3260 + * modification, are permitted provided that the following conditions are met:
3261 + * - Redistributions of source code must retain the above copyright notice,
3262 + * this list of conditions and the following disclaimer.
3263 + * - Redistributions in binary form must reproduce the above copyright notice,
3264 + * this list of conditions and the following disclaimer in the documentation
3265 + * and/or other materials provided with the distribution.
3266 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
3267 + * contributors may be used to endorse or promote products derived
3268 + * from this software without specific prior written permission.
3270 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3271 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3272 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3273 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
3274 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3275 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3276 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3277 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3278 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3279 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3280 + * POSSIBILITY OF SUCH DAMAGE.
3281 + */
3283 +/* @(#)rpc_parse.h 1.3 90/08/29 (C) 1987 SMI */
3286 + * rpc_parse.h, Definitions for the RPCL parser
3287 + */
3289 +enum defkind {
3290 + DEF_CONST,
3291 + DEF_STRUCT,
3292 + DEF_UNION,
3293 + DEF_ENUM,
3294 + DEF_TYPEDEF,
3295 + DEF_PROGRAM
3297 +typedef enum defkind defkind;
3299 +typedef char *const_def;
3301 +enum relation {
3302 + REL_VECTOR, /* fixed length array */
3303 + REL_ARRAY, /* variable length array */
3304 + REL_POINTER, /* pointer */
3305 + REL_ALIAS, /* simple */
3307 +typedef enum relation relation;
3309 +struct typedef_def {
3310 + char *old_prefix;
3311 + char *old_type;
3312 + relation rel;
3313 + char *array_max;
3315 +typedef struct typedef_def typedef_def;
3317 +struct enumval_list {
3318 + char *name;
3319 + char *assignment;
3320 + struct enumval_list *next;
3322 +typedef struct enumval_list enumval_list;
3324 +struct enum_def {
3325 + enumval_list *vals;
3327 +typedef struct enum_def enum_def;
3329 +struct declaration {
3330 + char *prefix;
3331 + char *type;
3332 + char *name;
3333 + relation rel;
3334 + char *array_max;
3336 +typedef struct declaration declaration;
3338 +struct decl_list {
3339 + declaration decl;
3340 + struct decl_list *next;
3342 +typedef struct decl_list decl_list;
3344 +struct struct_def {
3345 + decl_list *decls;
3347 +typedef struct struct_def struct_def;
3349 +struct case_list {
3350 + char *case_name;
3351 + int contflag;
3352 + declaration case_decl;
3353 + struct case_list *next;
3355 +typedef struct case_list case_list;
3357 +struct union_def {
3358 + declaration enum_decl;
3359 + case_list *cases;
3360 + declaration *default_decl;
3362 +typedef struct union_def union_def;
3364 +struct arg_list {
3365 + char *argname; /* name of struct for arg*/
3366 + decl_list *decls;
3369 +typedef struct arg_list arg_list;
3371 +struct proc_list {
3372 + char *proc_name;
3373 + char *proc_num;
3374 + arg_list args;
3375 + int arg_num;
3376 + char *res_type;
3377 + char *res_prefix;
3378 + struct proc_list *next;
3380 +typedef struct proc_list proc_list;
3382 +struct version_list {
3383 + char *vers_name;
3384 + char *vers_num;
3385 + proc_list *procs;
3386 + struct version_list *next;
3388 +typedef struct version_list version_list;
3390 +struct program_def {
3391 + char *prog_num;
3392 + version_list *versions;
3394 +typedef struct program_def program_def;
3396 +struct definition {
3397 + char *def_name;
3398 + defkind def_kind;
3399 + union {
3400 + const_def co;
3401 + struct_def st;
3402 + union_def un;
3403 + enum_def en;
3404 + typedef_def ty;
3405 + program_def pr;
3406 + } def;
3408 +typedef struct definition definition;
3410 +definition *get_definition();
3413 +struct bas_type
3415 + char *name;
3416 + int length;
3417 + struct bas_type *next;
3420 +typedef struct bas_type bas_type;
3421 diff --git a/rpcgen/rpc_sample.c b/rpcgen/rpc_sample.c
3422 new file mode 100644
3423 index 0000000..2b5c81b
3424 --- /dev/null
3425 +++ b/rpcgen/rpc_sample.c
3426 @@ -0,0 +1,247 @@
3428 + * Copyright (c) 2009, Sun Microsystems, Inc.
3429 + * All rights reserved.
3431 + * Redistribution and use in source and binary forms, with or without
3432 + * modification, are permitted provided that the following conditions are met:
3433 + * - Redistributions of source code must retain the above copyright notice,
3434 + * this list of conditions and the following disclaimer.
3435 + * - Redistributions in binary form must reproduce the above copyright notice,
3436 + * this list of conditions and the following disclaimer in the documentation
3437 + * and/or other materials provided with the distribution.
3438 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
3439 + * contributors may be used to endorse or promote products derived
3440 + * from this software without specific prior written permission.
3442 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3443 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3444 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3445 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
3446 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3447 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3448 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3449 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3450 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3451 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3452 + * POSSIBILITY OF SUCH DAMAGE.
3453 + */
3455 +#if 0
3456 +static char sccsid[] = "@(#)rpc_sample.c 1.1 90/08/30 (C) 1987 SMI";
3458 +#endif
3461 + * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler
3462 + */
3464 +#include <stdio.h>
3465 +#include <string.h>
3466 +#include "rpc_parse.h"
3467 +#include "rpc_util.h"
3470 +static char RQSTP[] = "rqstp";
3472 +static void write_sample_client(char *program_name, version_list *vp);
3473 +static void write_sample_server(definition * def);
3474 +static void return_type(proc_list *plist);
3476 +void
3477 +write_sample_svc(definition *def)
3479 + if (def->def_kind != DEF_PROGRAM)
3480 + return;
3481 + write_sample_server(def);
3485 +int
3486 +write_sample_clnt(definition *def)
3488 + version_list *vp;
3489 + int count = 0;
3491 + if (def->def_kind != DEF_PROGRAM)
3492 + return (0);
3493 + /* generate sample code for each version */
3494 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
3495 + write_sample_client(def->def_name, vp);
3496 + ++count;
3498 + return (count);
3502 +static void
3503 +write_sample_client(char *program_name, version_list *vp)
3505 + proc_list *proc;
3506 + int i;
3507 + decl_list *l;
3509 + f_print(fout, "\n\nvoid\n");
3510 + pvname(program_name, vp->vers_num);
3511 + if (Cflag)
3512 + f_print(fout, "( char* host )\n{\n");
3513 + else
3514 + f_print(fout, "(host)\nchar *host;\n{\n");
3515 + f_print(fout, "\tCLIENT *clnt;\n");
3517 + i = 0;
3518 + for (proc = vp->procs; proc != NULL; proc = proc->next) {
3519 + f_print(fout, "\t");
3520 + ptype(proc->res_prefix, proc->res_type, 1);
3521 + f_print(fout, " *result_%d;\n", ++i);
3522 + /* print out declarations for arguments */
3523 + if (proc->arg_num < 2 && !newstyle) {
3524 + f_print(fout, "\t");
3525 + if (!streq(proc->args.decls->decl.type, "void"))
3526 + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
3527 + else
3528 + f_print(fout, "char* "); /* cannot have "void" type */
3529 + f_print(fout, " ");
3530 + pvname(proc->proc_name, vp->vers_num);
3531 + f_print(fout, "_arg;\n");
3532 + } else if (!streq(proc->args.decls->decl.type, "void")) {
3533 + for (l = proc->args.decls; l != NULL; l = l->next) {
3534 + f_print(fout, "\t");
3535 + ptype(l->decl.prefix, l->decl.type, 1);
3536 + f_print(fout, " ");
3537 + pvname(proc->proc_name, vp->vers_num);
3538 + f_print(fout, "_%s;\n", l->decl.name);
3539 + /* pdeclaration(proc->args.argname, &l->decl, 1, ";\n" );*/
3544 + /* generate creation of client handle */
3545 + f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n",
3546 + program_name, vp->vers_name, tirpcflag ? "netpath" : "udp");
3547 + f_print(fout, "\tif (clnt == NULL) {\n");
3548 + f_print(fout, "\t\tclnt_pcreateerror(host);\n");
3549 + f_print(fout, "\t\texit(1);\n\t}\n");
3551 + /* generate calls to procedures */
3552 + i = 0;
3553 + for (proc = vp->procs; proc != NULL; proc = proc->next) {
3554 + f_print(fout, "\tresult_%d = ", ++i);
3555 + pvname(proc->proc_name, vp->vers_num);
3556 + if (proc->arg_num < 2 && !newstyle) {
3557 + f_print(fout, "(");
3558 + if (streq(proc->args.decls->decl.type, "void")) /* cast to void* */
3559 + f_print(fout, "(void*)");
3560 + f_print(fout, "&");
3561 + pvname(proc->proc_name, vp->vers_num);
3562 + f_print(fout, "_arg, clnt);\n");
3563 + } else if (streq(proc->args.decls->decl.type, "void")) {
3564 + f_print(fout, "(clnt);\n");
3565 + } else {
3566 + f_print(fout, "(");
3567 + for (l = proc->args.decls; l != NULL; l = l->next) {
3568 + pvname(proc->proc_name, vp->vers_num);
3569 + f_print(fout, "_%s, ", l->decl.name);
3571 + f_print(fout, "clnt);\n");
3573 + f_print(fout, "\tif (result_%d == NULL) {\n", i);
3574 + f_print(fout, "\t\tclnt_perror(clnt, \"call failed:\");\n");
3575 + f_print(fout, "\t}\n");
3578 + f_print(fout, "\tclnt_destroy( clnt );\n");
3579 + f_print(fout, "}\n");
3582 +static void
3583 +write_sample_server(definition * def)
3585 + version_list *vp;
3586 + proc_list *proc;
3588 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
3589 + for (proc = vp->procs; proc != NULL; proc = proc->next) {
3590 + f_print(fout, "\n");
3591 + /* if( Cflag )
3592 + f_print( fout, "extern \"C\"{\n");
3594 + return_type(proc);
3595 + f_print(fout, "* \n");
3596 + if (Cflag)
3597 + pvname_svc(proc->proc_name, vp->vers_num);
3598 + else
3599 + pvname(proc->proc_name, vp->vers_num);
3600 + printarglist(proc, RQSTP, "struct svc_req *");
3602 + f_print(fout, "{\n");
3603 + f_print(fout, "\n\tstatic ");
3604 + if (!streq(proc->res_type, "void"))
3605 + return_type(proc);
3606 + else
3607 + f_print(fout, "char*"); /* cannot have void type */
3608 + /* f_print(fout, " result;\n", proc->res_type); */
3609 + f_print(fout, " result;\n");
3610 + f_print(fout,
3611 + "\n\t/*\n\t * insert server code here\n\t */\n\n");
3612 + if (!streq(proc->res_type, "void"))
3613 + f_print(fout, "\treturn(&result);\n}\n");
3614 + else /* cast back to void * */
3615 + f_print(fout, "\treturn((void*) &result);\n}\n");
3616 + /* if( Cflag)
3617 + f_print( fout, "};\n");
3626 +static void
3627 +return_type(proc_list *plist)
3629 + ptype( plist->res_prefix, plist->res_type, 1 );
3632 +void
3633 +add_sample_msg(void)
3635 + f_print(fout, "/*\n");
3636 + f_print(fout, " * This is sample code generated by rpcgen.\n");
3637 + f_print(fout, " * These are only templates and you can use them\n");
3638 + f_print(fout, " * as a guideline for developing your own functions.\n");
3639 + f_print(fout, " */\n\n");
3642 +void
3643 +write_sample_clnt_main(void)
3645 + list *l;
3646 + definition *def;
3647 + version_list *vp;
3649 + f_print(fout, "\n\n" );
3650 + if( Cflag )
3651 + f_print(fout,"main( int argc, char* argv[] )\n{\n" );
3652 + else
3653 + f_print(fout, "main(argc, argv)\nint argc;\nchar *argv[];\n{\n" );
3655 + f_print(fout, "\tchar *host;");
3656 + f_print(fout, "\n\n\tif(argc < 2) {");
3657 + f_print(fout, "\n\t\tprintf(\"usage: %%s server_host\\n\", argv[0]);\n" );
3658 + f_print(fout, "\t\texit(1);\n\t}");
3659 + f_print(fout, "\n\thost = argv[1];\n");
3661 + for (l = defined; l != NULL; l = l->next) {
3662 + def = l->val;
3663 + if (def->def_kind != DEF_PROGRAM) {
3664 + continue;
3666 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
3667 + f_print( fout, "\t" );
3668 + pvname(def->def_name, vp->vers_num);
3669 + f_print( fout, "( host );\n" );
3672 + f_print(fout, "}\n");
3674 diff --git a/rpcgen/rpc_scan.c b/rpcgen/rpc_scan.c
3675 new file mode 100644
3676 index 0000000..f58fa9f
3677 --- /dev/null
3678 +++ b/rpcgen/rpc_scan.c
3679 @@ -0,0 +1,474 @@
3681 + * Copyright (c) 2009, Sun Microsystems, Inc.
3682 + * All rights reserved.
3684 + * Redistribution and use in source and binary forms, with or without
3685 + * modification, are permitted provided that the following conditions are met:
3686 + * - Redistributions of source code must retain the above copyright notice,
3687 + * this list of conditions and the following disclaimer.
3688 + * - Redistributions in binary form must reproduce the above copyright notice,
3689 + * this list of conditions and the following disclaimer in the documentation
3690 + * and/or other materials provided with the distribution.
3691 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
3692 + * contributors may be used to endorse or promote products derived
3693 + * from this software without specific prior written permission.
3695 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3696 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3697 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3698 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
3699 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3700 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3701 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3702 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3703 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3704 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3705 + * POSSIBILITY OF SUCH DAMAGE.
3706 + */
3708 +#if 0
3709 +static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI";
3710 +#endif
3713 + * rpc_scan.c, Scanner for the RPC protocol compiler
3714 + * Copyright (C) 1987, Sun Microsystems, Inc.
3715 + */
3716 +#include <stdio.h>
3717 +#include <ctype.h>
3718 +#include <string.h>
3719 +#include "rpc_scan.h"
3720 +#include "rpc_parse.h"
3721 +#include "rpc_util.h"
3723 +static void unget_token(token *tokp);
3724 +static void findstrconst(char **str, char **val);
3725 +static void findchrconst(char **str, char **val);
3726 +static void findconst(char **str, char **val);
3727 +static void findkind(char **mark, token *tokp);
3728 +static int cppline(char *line);
3729 +static int directive(char *line);
3730 +static void printdirective(char *line);
3731 +static void docppline(char *line, int *lineno, char **fname);
3733 +#define startcomment(where) (where[0] == '/' && where[1] == '*')
3734 +#define endcomment(where) (where[-1] == '*' && where[0] == '/')
3736 +static int pushed = 0; /* is a token pushed */
3737 +static token lasttok; /* last token, if pushed */
3740 + * scan expecting 1 given token
3741 + */
3742 +void
3743 +scan(tok_kind expect, token *tokp)
3745 + get_token(tokp);
3746 + if (tokp->kind != expect) {
3747 + expected1(expect);
3752 + * scan expecting any of the 2 given tokens
3753 + */
3754 +void
3755 +scan2(tok_kind expect1, tok_kind expect2, token *tokp)
3757 + get_token(tokp);
3758 + if (tokp->kind != expect1 && tokp->kind != expect2) {
3759 + expected2(expect1, expect2);
3764 + * scan expecting any of the 3 given token
3765 + */
3766 +void
3767 +scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp)
3769 + get_token(tokp);
3770 + if (tokp->kind != expect1 && tokp->kind != expect2
3771 + && tokp->kind != expect3) {
3772 + expected3(expect1, expect2, expect3);
3777 + * scan expecting a constant, possibly symbolic
3778 + */
3779 +void
3780 +scan_num(token *tokp)
3782 + get_token(tokp);
3783 + switch (tokp->kind) {
3784 + case TOK_IDENT:
3785 + break;
3786 + default:
3787 + error("constant or identifier expected");
3792 + * Peek at the next token
3793 + */
3794 +void
3795 +peek(token *tokp)
3797 + get_token(tokp);
3798 + unget_token(tokp);
3802 + * Peek at the next token and scan it if it matches what you expect
3803 + */
3804 +int
3805 +peekscan(tok_kind expect, token *tokp)
3807 + peek(tokp);
3808 + if (tokp->kind == expect) {
3809 + get_token(tokp);
3810 + return (1);
3812 + return (0);
3816 + * Get the next token, printing out any directive that are encountered.
3817 + */
3818 +void
3819 +get_token(token *tokp)
3821 + int commenting;
3823 + if (pushed) {
3824 + pushed = 0;
3825 + *tokp = lasttok;
3826 + return;
3828 + commenting = 0;
3829 + for (;;) {
3830 + if (*where == 0) {
3831 + for (;;) {
3832 + if (!fgets(curline, MAXLINESIZE, fin)) {
3833 + tokp->kind = TOK_EOF;
3834 + *where = 0;
3835 + return;
3837 + linenum++;
3838 + if (commenting) {
3839 + break;
3840 + } else if (cppline(curline)) {
3841 + docppline(curline, &linenum,
3842 + &infilename);
3843 + } else if (directive(curline)) {
3844 + printdirective(curline);
3845 + } else {
3846 + break;
3849 + where = curline;
3850 + } else if (isspace(*where)) {
3851 + while (isspace(*where)) {
3852 + where++; /* eat */
3854 + } else if (commenting) {
3855 + for (where++; *where; where++) {
3856 + if (endcomment(where)) {
3857 + where++;
3858 + commenting--;
3859 + break;
3862 + } else if (startcomment(where)) {
3863 + where += 2;
3864 + commenting++;
3865 + } else {
3866 + break;
3870 + /*
3871 + * 'where' is not whitespace, comment or directive Must be a token!
3872 + */
3873 + switch (*where) {
3874 + case ':':
3875 + tokp->kind = TOK_COLON;
3876 + where++;
3877 + break;
3878 + case ';':
3879 + tokp->kind = TOK_SEMICOLON;
3880 + where++;
3881 + break;
3882 + case ',':
3883 + tokp->kind = TOK_COMMA;
3884 + where++;
3885 + break;
3886 + case '=':
3887 + tokp->kind = TOK_EQUAL;
3888 + where++;
3889 + break;
3890 + case '*':
3891 + tokp->kind = TOK_STAR;
3892 + where++;
3893 + break;
3894 + case '[':
3895 + tokp->kind = TOK_LBRACKET;
3896 + where++;
3897 + break;
3898 + case ']':
3899 + tokp->kind = TOK_RBRACKET;
3900 + where++;
3901 + break;
3902 + case '{':
3903 + tokp->kind = TOK_LBRACE;
3904 + where++;
3905 + break;
3906 + case '}':
3907 + tokp->kind = TOK_RBRACE;
3908 + where++;
3909 + break;
3910 + case '(':
3911 + tokp->kind = TOK_LPAREN;
3912 + where++;
3913 + break;
3914 + case ')':
3915 + tokp->kind = TOK_RPAREN;
3916 + where++;
3917 + break;
3918 + case '<':
3919 + tokp->kind = TOK_LANGLE;
3920 + where++;
3921 + break;
3922 + case '>':
3923 + tokp->kind = TOK_RANGLE;
3924 + where++;
3925 + break;
3927 + case '"':
3928 + tokp->kind = TOK_STRCONST;
3929 + findstrconst(&where, &tokp->str);
3930 + break;
3931 + case '\'':
3932 + tokp->kind = TOK_CHARCONST;
3933 + findchrconst(&where, &tokp->str);
3934 + break;
3936 + case '-':
3937 + case '0':
3938 + case '1':
3939 + case '2':
3940 + case '3':
3941 + case '4':
3942 + case '5':
3943 + case '6':
3944 + case '7':
3945 + case '8':
3946 + case '9':
3947 + tokp->kind = TOK_IDENT;
3948 + findconst(&where, &tokp->str);
3949 + break;
3951 + default:
3952 + if (!(isalpha(*where) || *where == '_')) {
3953 + char buf[100];
3954 + char *p;
3956 + s_print(buf, "illegal character in file: ");
3957 + p = buf + strlen(buf);
3958 + if (isprint(*where)) {
3959 + s_print(p, "%c", *where);
3960 + } else {
3961 + s_print(p, "%d", *where);
3963 + error(buf);
3965 + findkind(&where, tokp);
3966 + break;
3970 +static void
3971 +unget_token(token *tokp)
3973 + lasttok = *tokp;
3974 + pushed = 1;
3977 +static void
3978 +findstrconst(char **str, char **val)
3980 + char *p;
3981 + int size;
3983 + p = *str;
3984 + do {
3985 + *p++;
3986 + } while (*p && *p != '"');
3987 + if (*p == 0) {
3988 + error("unterminated string constant");
3990 + p++;
3991 + size = p - *str;
3992 + *val = alloc(size + 1);
3993 + (void) strncpy(*val, *str, size);
3994 + (*val)[size] = 0;
3995 + *str = p;
3998 +static void
3999 +findchrconst(char **str, char **val)
4001 + char *p;
4002 + int size;
4004 + p = *str;
4005 + do {
4006 + *p++;
4007 + } while (*p && *p != '\'');
4008 + if (*p == 0) {
4009 + error("unterminated string constant");
4011 + p++;
4012 + size = p - *str;
4013 + if (size != 3) {
4014 + error("empty char string");
4016 + *val = alloc(size + 1);
4017 + (void) strncpy(*val, *str, size);
4018 + (*val)[size] = 0;
4019 + *str = p;
4022 +static void
4023 +findconst(char **str, char **val)
4025 + char *p;
4026 + int size;
4028 + p = *str;
4029 + if (*p == '0' && *(p + 1) == 'x') {
4030 + p++;
4031 + do {
4032 + p++;
4033 + } while (isxdigit(*p));
4034 + } else {
4035 + do {
4036 + p++;
4037 + } while (isdigit(*p));
4039 + size = p - *str;
4040 + *val = alloc(size + 1);
4041 + (void) strncpy(*val, *str, size);
4042 + (*val)[size] = 0;
4043 + *str = p;
4046 +static token symbols[] = {
4047 + {TOK_CONST, "const"},
4048 + {TOK_UNION, "union"},
4049 + {TOK_SWITCH, "switch"},
4050 + {TOK_CASE, "case"},
4051 + {TOK_DEFAULT, "default"},
4052 + {TOK_STRUCT, "struct"},
4053 + {TOK_TYPEDEF, "typedef"},
4054 + {TOK_ENUM, "enum"},
4055 + {TOK_OPAQUE, "opaque"},
4056 + {TOK_BOOL, "bool"},
4057 + {TOK_VOID, "void"},
4058 + {TOK_CHAR, "char"},
4059 + {TOK_INT, "int"},
4060 + {TOK_UNSIGNED, "unsigned"},
4061 + {TOK_SHORT, "short"},
4062 + {TOK_INT32, "int32"},
4063 + {TOK_FLOAT, "float"},
4064 + {TOK_DOUBLE, "double"},
4065 + {TOK_STRING, "string"},
4066 + {TOK_PROGRAM, "program"},
4067 + {TOK_VERSION, "version"},
4068 + {TOK_EOF, "??????"},
4071 +static void
4072 +findkind(char **mark, token *tokp)
4074 + int len;
4075 + token *s;
4076 + char *str;
4078 + str = *mark;
4079 + for (s = symbols; s->kind != TOK_EOF; s++) {
4080 + len = strlen(s->str);
4081 + if (strncmp(str, s->str, len) == 0) {
4082 + if (!isalnum(str[len]) && str[len] != '_') {
4083 + tokp->kind = s->kind;
4084 + tokp->str = s->str;
4085 + *mark = str + len;
4086 + return;
4090 + tokp->kind = TOK_IDENT;
4091 + for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
4092 + tokp->str = alloc(len + 1);
4093 + (void) strncpy(tokp->str, str, len);
4094 + tokp->str[len] = 0;
4095 + *mark = str + len;
4098 +static int
4099 +cppline(char *line)
4101 + return (line == curline && *line == '#');
4104 +static int
4105 +directive(char *line)
4107 + return (line == curline && *line == '%');
4110 +static void
4111 +printdirective(char *line)
4113 + f_print(fout, "%s", line + 1);
4116 +static void
4117 +docppline(char *line, int *lineno, char **fname)
4119 + char *file;
4120 + int num;
4121 + char *p;
4123 + line++;
4124 + while (isspace(*line)) {
4125 + line++;
4127 + num = atoi(line);
4128 + while (isdigit(*line)) {
4129 + line++;
4131 + while (isspace(*line)) {
4132 + line++;
4134 + if (*line != '"') {
4135 + error("preprocessor error");
4137 + line++;
4138 + p = file = alloc(strlen(line) + 1);
4139 + while (*line && *line != '"') {
4140 + *p++ = *line++;
4142 + if (*line == 0) {
4143 + error("preprocessor error");
4145 + *p = 0;
4146 + if (*file == 0) {
4147 + *fname = NULL;
4148 + free(file);
4149 + } else {
4150 + *fname = file;
4152 + *lineno = num - 1;
4154 diff --git a/rpcgen/rpc_scan.h b/rpcgen/rpc_scan.h
4155 new file mode 100644
4156 index 0000000..16f688c
4157 --- /dev/null
4158 +++ b/rpcgen/rpc_scan.h
4159 @@ -0,0 +1,103 @@
4161 + * Copyright (c) 2009, Sun Microsystems, Inc.
4162 + * All rights reserved.
4164 + * Redistribution and use in source and binary forms, with or without
4165 + * modification, are permitted provided that the following conditions are met:
4166 + * - Redistributions of source code must retain the above copyright notice,
4167 + * this list of conditions and the following disclaimer.
4168 + * - Redistributions in binary form must reproduce the above copyright notice,
4169 + * this list of conditions and the following disclaimer in the documentation
4170 + * and/or other materials provided with the distribution.
4171 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
4172 + * contributors may be used to endorse or promote products derived
4173 + * from this software without specific prior written permission.
4175 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4176 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4177 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4178 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
4179 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
4180 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
4181 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
4182 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
4183 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4184 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4185 + * POSSIBILITY OF SUCH DAMAGE.
4186 + */
4188 +/* @(#)rpc_scan.h 1.3 90/08/29 (C) 1987 SMI */
4191 + * rpc_scan.h, Definitions for the RPCL scanner
4192 + */
4195 + * kinds of tokens
4196 + */
4197 +enum tok_kind {
4198 + TOK_IDENT,
4199 + TOK_CHARCONST,
4200 + TOK_STRCONST,
4201 + TOK_LPAREN,
4202 + TOK_RPAREN,
4203 + TOK_LBRACE,
4204 + TOK_RBRACE,
4205 + TOK_LBRACKET,
4206 + TOK_RBRACKET,
4207 + TOK_LANGLE,
4208 + TOK_RANGLE,
4209 + TOK_STAR,
4210 + TOK_COMMA,
4211 + TOK_EQUAL,
4212 + TOK_COLON,
4213 + TOK_SEMICOLON,
4214 + TOK_CONST,
4215 + TOK_STRUCT,
4216 + TOK_UNION,
4217 + TOK_SWITCH,
4218 + TOK_CASE,
4219 + TOK_DEFAULT,
4220 + TOK_ENUM,
4221 + TOK_TYPEDEF,
4222 + TOK_INT,
4223 + TOK_SHORT,
4224 + TOK_INT32,
4225 + TOK_UNSIGNED,
4226 + TOK_FLOAT,
4227 + TOK_DOUBLE,
4228 + TOK_OPAQUE,
4229 + TOK_CHAR,
4230 + TOK_STRING,
4231 + TOK_BOOL,
4232 + TOK_VOID,
4233 + TOK_PROGRAM,
4234 + TOK_VERSION,
4235 + TOK_EOF
4237 +typedef enum tok_kind tok_kind;
4240 + * a token
4241 + */
4242 +struct token {
4243 + tok_kind kind;
4244 + char *str;
4246 +typedef struct token token;
4250 + * routine interface
4251 + */
4252 +void scan();
4253 +void scan2();
4254 +void scan3();
4255 +void scan_num();
4256 +void peek();
4257 +int peekscan();
4258 +void get_token();
4259 +void expected1(tok_kind);
4260 +void expected2(tok_kind, tok_kind);
4261 +void expected3(tok_kind, tok_kind, tok_kind);
4263 diff --git a/rpcgen/rpc_svcout.c b/rpcgen/rpc_svcout.c
4264 new file mode 100644
4265 index 0000000..284a529
4266 --- /dev/null
4267 +++ b/rpcgen/rpc_svcout.c
4268 @@ -0,0 +1,882 @@
4270 + * Copyright (c) 2009, Sun Microsystems, Inc.
4271 + * All rights reserved.
4273 + * Redistribution and use in source and binary forms, with or without
4274 + * modification, are permitted provided that the following conditions are met:
4275 + * - Redistributions of source code must retain the above copyright notice,
4276 + * this list of conditions and the following disclaimer.
4277 + * - Redistributions in binary form must reproduce the above copyright notice,
4278 + * this list of conditions and the following disclaimer in the documentation
4279 + * and/or other materials provided with the distribution.
4280 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
4281 + * contributors may be used to endorse or promote products derived
4282 + * from this software without specific prior written permission.
4284 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4285 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4286 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4287 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
4288 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
4289 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
4290 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
4291 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
4292 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4293 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4294 + * POSSIBILITY OF SUCH DAMAGE.
4295 + */
4297 +#if 0
4298 + static char sccsid[] = "@(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI";
4299 +#endif
4302 + * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
4303 + */
4304 +#include <stdio.h>
4305 +#include <string.h>
4306 +#include "rpc_parse.h"
4307 +#include "rpc_util.h"
4308 +#include "rpc_output.h"
4310 +static void write_real_program(definition *def);
4311 +static void write_program(definition *def, char *storage);
4312 +static void printerr(char *err, char *transp);
4313 +static void printif(char *proc, char *transp, char *prefix, char *arg);
4314 +static void write_inetmost(char *infile);
4315 +static void print_return(char *space);
4316 +static void print_pmapunset(char *space);
4317 +static void print_err_message(char *space);
4318 +static void write_timeout_func(void);
4319 +static void write_pm_most(char *infile, int netflag);
4320 +static void write_rpc_svc_fg(char *infile, char *sp);
4321 +static void open_log_file(char *infile, char *sp);
4323 +static char RQSTP[] = "rqstp";
4324 +static char TRANSP[] = "transp";
4325 +static char ARG[] = "argument";
4326 +static char RESULT[] = "result";
4327 +static char ROUTINE[] = "local";
4329 +char _errbuf[256]; /* For all messages */
4331 +static void
4332 +p_xdrfunc(char *rname, char *typename)
4334 + if (Cflag)
4335 + f_print(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n", rname,
4336 + stringfix(typename));
4337 + else
4338 + f_print(fout, "\t\txdr_%s = xdr_%s;\n", rname, stringfix(typename));
4341 +void
4342 +internal_proctype(proc_list *plist)
4344 + f_print(fout, "static ");
4345 + ptype( plist->res_prefix, plist->res_type, 1 );
4346 + f_print( fout, "*" );
4351 + * write most of the service, that is, everything but the registrations.
4352 + */
4353 +void
4354 +write_most(char *infile, int netflag, int nomain)
4356 + if (inetdflag || pmflag) {
4357 + char* var_type;
4358 + var_type = (nomain? "extern" : "static");
4359 + f_print(fout, "%s int _rpcpmstart;", var_type );
4360 + f_print(fout, "\t\t/* Started by a port monitor ? */\n");
4361 + f_print(fout, "%s int _rpcfdtype;", var_type );
4362 + f_print(fout, "\t\t/* Whether Stream or Datagram ? */\n");
4363 + if (timerflag) {
4364 + f_print(fout, "%s int _rpcsvcdirty;", var_type );
4365 + f_print(fout, "\t/* Still serving ? */\n");
4367 + write_svc_aux( nomain );
4369 + /* write out dispatcher and stubs */
4370 + write_programs( nomain? (char *)NULL : "static" );
4372 + if( nomain )
4373 + return;
4375 + f_print(fout, "\nmain()\n");
4376 + f_print(fout, "{\n");
4377 + if (inetdflag) {
4378 + write_inetmost(infile); /* Includes call to write_rpc_svc_fg() */
4379 + } else {
4380 + if( tirpcflag ) {
4381 + if (netflag) {
4382 + f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
4383 + f_print(fout, "\tstruct netconfig *nconf = NULL;\n");
4385 + f_print(fout, "\tpid_t pid;\n");
4386 + f_print(fout, "\tint i;\n");
4387 + f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n");
4388 + write_pm_most(infile, netflag);
4389 + f_print(fout, "\telse {\n");
4390 + write_rpc_svc_fg(infile, "\t\t");
4391 + f_print(fout, "\t}\n");
4392 + } else {
4393 + f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
4394 + f_print(fout, "\n");
4395 + print_pmapunset("\t");
4399 + if (logflag && !inetdflag) {
4400 + open_log_file(infile, "\t");
4405 + * write a registration for the given transport
4406 + */
4407 +void
4408 +write_netid_register(char *transp)
4410 + list *l;
4411 + definition *def;
4412 + version_list *vp;
4413 + char *sp;
4414 + char tmpbuf[32];
4416 + sp = "";
4417 + f_print(fout, "\n");
4418 + f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp);
4419 + f_print(fout, "%s\tif (nconf == NULL) {\n", sp);
4420 + (void) sprintf(_errbuf, "cannot find %s netid.", transp);
4421 + sprintf(tmpbuf, "%s\t\t", sp);
4422 + print_err_message(tmpbuf);
4423 + f_print(fout, "%s\t\texit(1);\n", sp);
4424 + f_print(fout, "%s\t}\n", sp);
4425 + f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n",
4426 + sp, TRANSP);
4427 + f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
4428 + (void) sprintf(_errbuf, "cannot create %s service.", transp);
4429 + print_err_message(tmpbuf);
4430 + f_print(fout, "%s\t\texit(1);\n", sp);
4431 + f_print(fout, "%s\t}\n", sp);
4433 + for (l = defined; l != NULL; l = l->next) {
4434 + def = (definition *) l->val;
4435 + if (def->def_kind != DEF_PROGRAM) {
4436 + continue;
4438 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
4439 + f_print(fout,
4440 + "%s\t(void) rpcb_unset(%s, %s, nconf);\n",
4441 + sp, def->def_name, vp->vers_name);
4442 + f_print(fout,
4443 + "%s\tif (!svc_reg(%s, %s, %s, ",
4444 + sp, TRANSP, def->def_name, vp->vers_name);
4445 + pvname(def->def_name, vp->vers_num);
4446 + f_print(fout, ", nconf)) {\n");
4447 + (void) sprintf(_errbuf, "unable to register (%s, %s, %s).",
4448 + def->def_name, vp->vers_name, transp);
4449 + print_err_message(tmpbuf);
4450 + f_print(fout, "%s\t\texit(1);\n", sp);
4451 + f_print(fout, "%s\t}\n", sp);
4454 + f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp);
4458 + * write a registration for the given transport for TLI
4459 + */
4460 +void
4461 +write_nettype_register(char *transp)
4463 + list *l;
4464 + definition *def;
4465 + version_list *vp;
4467 + for (l = defined; l != NULL; l = l->next) {
4468 + def = (definition *) l->val;
4469 + if (def->def_kind != DEF_PROGRAM) {
4470 + continue;
4472 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
4473 + f_print(fout, "\tif (!svc_create(");
4474 + pvname(def->def_name, vp->vers_num);
4475 + f_print(fout, ", %s, %s, \"%s\")) {\n ",
4476 + def->def_name, vp->vers_name, transp);
4477 + (void) sprintf(_errbuf,
4478 + "unable to create (%s, %s) for %s.",
4479 + def->def_name, vp->vers_name, transp);
4480 + print_err_message("\t\t");
4481 + f_print(fout, "\t\texit(1);\n");
4482 + f_print(fout, "\t}\n");
4488 + * write the rest of the service
4489 + */
4490 +void
4491 +write_rest(void)
4493 + f_print(fout, "\n");
4494 + if (inetdflag) {
4495 + f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP);
4496 + (void) sprintf(_errbuf, "could not create a handle");
4497 + print_err_message("\t\t");
4498 + f_print(fout, "\t\texit(1);\n");
4499 + f_print(fout, "\t}\n");
4500 + if (timerflag) {
4501 + f_print(fout, "\tif (_rpcpmstart) {\n");
4502 + f_print(fout,
4503 + "\t\t(void) signal(SIGALRM, %s closedown);\n",
4504 + Cflag? "(SIG_PF)" : "(void(*)())" );
4505 + f_print(fout, "\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
4506 + f_print(fout, "\t}\n");
4509 + f_print(fout, "\tsvc_run();\n");
4510 + (void) sprintf(_errbuf, "svc_run returned");
4511 + print_err_message("\t");
4512 + f_print(fout, "\texit(1);\n");
4513 + f_print(fout, "\t/* NOTREACHED */\n");
4514 + f_print(fout, "}\n");
4517 +void
4518 +write_programs(char *storage)
4520 + list *l;
4521 + definition *def;
4523 + /* write out stubs for procedure definitions */
4524 + for (l = defined; l != NULL; l = l->next) {
4525 + def = (definition *) l->val;
4526 + if (def->def_kind == DEF_PROGRAM) {
4527 + write_real_program(def);
4531 + /* write out dispatcher for each program */
4532 + for (l = defined; l != NULL; l = l->next) {
4533 + def = (definition *) l->val;
4534 + if (def->def_kind == DEF_PROGRAM) {
4535 + write_program(def, storage);
4542 +/* write out definition of internal function (e.g. _printmsg_1(...))
4543 + which calls server's defintion of actual function (e.g. printmsg_1(...)).
4544 + Unpacks single user argument of printmsg_1 to call-by-value format
4545 + expected by printmsg_1. */
4546 +static void
4547 +write_real_program(definition *def)
4549 + version_list *vp;
4550 + proc_list *proc;
4551 + decl_list *l;
4553 + if( !newstyle ) return; /* not needed for old style */
4554 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
4555 + for (proc = vp->procs; proc != NULL; proc = proc->next) {
4556 + f_print(fout, "\n");
4557 + internal_proctype(proc);
4558 + f_print(fout, "\n_");
4559 + pvname(proc->proc_name, vp->vers_num);
4560 + if( Cflag ) {
4561 + f_print(fout, "(" );
4562 + /* arg name */
4563 + if (proc->arg_num > 1)
4564 + f_print(fout, proc->args.argname);
4565 + else
4566 + ptype(proc->args.decls->decl.prefix,
4567 + proc->args.decls->decl.type, 0);
4568 + f_print(fout, " *argp, struct svc_req *%s)\n",
4569 + RQSTP);
4570 + } else {
4571 + f_print(fout, "(argp, %s)\n", RQSTP );
4572 + /* arg name */
4573 + if (proc->arg_num > 1)
4574 + f_print(fout, "\t%s *argp;\n", proc->args.argname);
4575 + else {
4576 + f_print(fout, "\t");
4577 + ptype(proc->args.decls->decl.prefix,
4578 + proc->args.decls->decl.type, 0);
4579 + f_print(fout, " *argp;\n");
4581 + f_print(fout, " struct svc_req *%s;\n", RQSTP);
4584 + f_print(fout, "{\n");
4585 + f_print(fout, "\treturn(");
4586 + if( Cflag )
4587 + pvname_svc(proc->proc_name, vp->vers_num);
4588 + else
4589 + pvname(proc->proc_name, vp->vers_num);
4590 + f_print(fout, "(");
4591 + if (proc->arg_num < 2) { /* single argument */
4592 + if (!streq( proc->args.decls->decl.type, "void"))
4593 + f_print(fout, "*argp, "); /* non-void */
4594 + } else {
4595 + for (l = proc->args.decls; l != NULL; l = l->next)
4596 + f_print(fout, "argp->%s, ", l->decl.name);
4598 + f_print(fout, "%s));\n}\n", RQSTP);
4599 + }
4603 +static void
4604 +write_program(definition *def, char *storage)
4606 + version_list *vp;
4607 + proc_list *proc;
4608 + int filled;
4610 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
4611 + f_print(fout, "\n");
4612 + if (storage != NULL) {
4613 + f_print(fout, "%s ", storage);
4615 + f_print(fout, "void\n");
4616 + pvname(def->def_name, vp->vers_num);
4618 + if (Cflag) {
4619 + f_print(fout, "(struct svc_req *%s, ", RQSTP);
4620 + f_print(fout, "register SVCXPRT *%s)\n", TRANSP);
4621 + } else {
4622 + f_print(fout, "(%s, %s)\n", RQSTP, TRANSP);
4623 + f_print(fout, " struct svc_req *%s;\n", RQSTP);
4624 + f_print(fout, " register SVCXPRT *%s;\n", TRANSP);
4627 + f_print(fout, "{\n");
4629 + filled = 0;
4630 + f_print(fout, "\tunion {\n");
4631 + for (proc = vp->procs; proc != NULL; proc = proc->next) {
4632 + if (proc->arg_num < 2) { /* single argument */
4633 + if (streq(proc->args.decls->decl.type,
4634 + "void")) {
4635 + continue;
4637 + filled = 1;
4638 + f_print(fout, "\t\t");
4639 + ptype(proc->args.decls->decl.prefix,
4640 + proc->args.decls->decl.type, 0);
4641 + pvname(proc->proc_name, vp->vers_num);
4642 + f_print(fout, "_arg;\n");
4645 + else {
4646 + filled = 1;
4647 + f_print(fout, "\t\t%s", proc->args.argname);
4648 + f_print(fout, " ");
4649 + pvname(proc->proc_name, vp->vers_num);
4650 + f_print(fout, "_arg;\n");
4653 + if (!filled) {
4654 + f_print(fout, "\t\tint fill;\n");
4656 + f_print(fout, "\t} %s;\n", ARG);
4657 + f_print(fout, "\tchar *%s;\n", RESULT);
4659 + if (Cflag) {
4660 + f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT);
4661 + f_print(fout,
4662 + "\tchar *(*%s)(char *, struct svc_req *);\n",
4663 + ROUTINE);
4664 + } else {
4665 + f_print(fout, "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", ARG, RESULT);
4666 + f_print(fout, "\tchar *(*%s)();\n", ROUTINE);
4669 + f_print(fout, "\n");
4671 + if (timerflag)
4672 + f_print(fout, "\t_rpcsvcdirty = 1;\n");
4673 + f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
4674 + if (!nullproc(vp->procs)) {
4675 + f_print(fout, "\tcase NULLPROC:\n");
4676 + f_print(fout,
4677 + "\t\t(void) svc_sendreply(%s, (xdrproc_t) xdr_void, (char *)NULL);\n",
4678 + TRANSP);
4679 + print_return("\t\t");
4680 + f_print(fout, "\n");
4682 + for (proc = vp->procs; proc != NULL; proc = proc->next) {
4683 + f_print(fout, "\tcase %s:\n", proc->proc_name);
4684 + if (proc->arg_num < 2) { /* single argument */
4685 + p_xdrfunc( ARG, proc->args.decls->decl.type);
4686 + } else {
4687 + p_xdrfunc( ARG, proc->args.argname);
4689 + p_xdrfunc( RESULT, proc->res_type);
4690 + if( Cflag )
4691 + f_print(fout,
4692 + "\t\t%s = (char *(*)(char *, struct svc_req *)) ",
4693 + ROUTINE);
4694 + else
4695 + f_print(fout, "\t\t%s = (char *(*)()) ", ROUTINE);
4697 + if (newstyle) { /* new style: calls internal routine */
4698 + f_print(fout,"_");
4700 + /* Not sure about the following...
4701 + * rpc_hout always generates foobar_1_svc for
4702 + * the service procedure, so why should we use
4703 + * foobar_1 here?! --okir */
4704 +#if 0
4705 + if( Cflag && !newstyle )
4706 + pvname_svc(proc->proc_name, vp->vers_num);
4707 + else
4708 + pvname(proc->proc_name, vp->vers_num);
4709 +#else
4710 + pvname_svc(proc->proc_name, vp->vers_num);
4711 +#endif
4712 + f_print(fout, ";\n");
4713 + f_print(fout, "\t\tbreak;\n\n");
4715 + f_print(fout, "\tdefault:\n");
4716 + printerr("noproc", TRANSP);
4717 + print_return("\t\t");
4718 + f_print(fout, "\t}\n");
4720 + f_print(fout, "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", ARG, ARG);
4721 + if (Cflag)
4722 + printif("getargs", TRANSP, "(caddr_t) &", ARG);
4723 + else
4724 + printif("getargs", TRANSP, "&", ARG);
4725 + printerr("decode", TRANSP);
4726 + print_return("\t\t");
4727 + f_print(fout, "\t}\n");
4729 + if (Cflag)
4730 + f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n",
4731 + RESULT, ROUTINE, ARG, RQSTP);
4732 + else
4733 + f_print(fout, "\t%s = (*%s)(&%s, %s);\n",
4734 + RESULT, ROUTINE, ARG, RQSTP);
4735 + f_print(fout,
4736 + "\tif (%s != NULL && !svc_sendreply(%s, "
4737 + "(xdrproc_t) xdr_%s, %s)) {\n",
4738 + RESULT, TRANSP, RESULT, RESULT);
4739 + printerr("systemerr", TRANSP);
4740 + f_print(fout, "\t}\n");
4742 + if (Cflag)
4743 + printif("freeargs", TRANSP, "(caddr_t) &", ARG);
4744 + else
4745 + printif("freeargs", TRANSP, "&", ARG);
4746 + (void) sprintf(_errbuf, "unable to free arguments");
4747 + print_err_message("\t\t");
4748 + f_print(fout, "\t\texit(1);\n");
4749 + f_print(fout, "\t}\n");
4750 + print_return("\t");
4751 + f_print(fout, "}\n");
4755 +static void
4756 +printerr(char *err, char *transp)
4758 + f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
4761 +static void
4762 +printif(char *proc, char *transp, char *prefix, char *arg)
4764 + f_print(fout, "\tif (!svc_%s(%s, (xdrproc_t) xdr_%s, (caddr_t) %s%s)) {\n",
4765 + proc, transp, arg, prefix, arg);
4768 +int
4769 +nullproc(proc_list *proc)
4771 + for (; proc != NULL; proc = proc->next) {
4772 + if (streq(proc->proc_num, "0")) {
4773 + return (1);
4776 + return (0);
4779 +static void
4780 +write_inetmost(char *infile)
4782 + f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
4783 + f_print(fout, "\tint sock;\n");
4784 + f_print(fout, "\tint proto;\n");
4785 + f_print(fout, "\tstruct sockaddr_in saddr;\n");
4786 + f_print(fout, "\tint asize = sizeof (saddr);\n");
4787 + f_print(fout, "\n");
4788 + f_print(fout,
4789 + "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
4790 + f_print(fout, "\t\tint ssize = sizeof (int);\n\n");
4791 + f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n");
4792 + f_print(fout, "\t\t\texit(1);\n");
4793 + f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
4794 + f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n");
4795 + f_print(fout, "\t\t\texit(1);\n");
4796 + f_print(fout, "\t\tsock = 0;\n");
4797 + f_print(fout, "\t\t_rpcpmstart = 1;\n");
4798 + f_print(fout, "\t\tproto = 0;\n");
4799 + open_log_file(infile, "\t\t");
4800 + f_print(fout, "\t} else {\n");
4801 + write_rpc_svc_fg(infile, "\t\t");
4802 + f_print(fout, "\t\tsock = RPC_ANYSOCK;\n");
4803 + print_pmapunset("\t\t");
4804 + f_print(fout, "\t}\n");
4807 +static void
4808 +print_return(char *space)
4810 + if (exitnow)
4811 + f_print(fout, "%sexit(0);\n", space);
4812 + else {
4813 + if (timerflag)
4814 + f_print(fout, "%s_rpcsvcdirty = 0;\n", space);
4815 + f_print(fout, "%sreturn;\n", space);
4819 +static void
4820 +print_pmapunset(char *space)
4822 + list *l;
4823 + definition *def;
4824 + version_list *vp;
4826 + for (l = defined; l != NULL; l = l->next) {
4827 + def = (definition *) l->val;
4828 + if (def->def_kind == DEF_PROGRAM) {
4829 + for (vp = def->def.pr.versions; vp != NULL;
4830 + vp = vp->next) {
4831 + f_print(fout, "%s(void) pmap_unset(%s, %s);\n",
4832 + space, def->def_name, vp->vers_name);
4838 +static void
4839 +print_err_message(char *space)
4841 + if (logflag)
4842 + f_print(fout, "%ssyslog(LOG_ERR, \"%s\");\n", space, _errbuf);
4843 + else if (inetdflag || pmflag)
4844 + f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf);
4845 + else
4846 + f_print(fout, "%sfprintf(stderr, \"%s\");\n", space, _errbuf);
4850 + * Write the server auxiliary function ( _msgout, timeout)
4851 + */
4852 +void
4853 +write_svc_aux(int nomain)
4855 + if (!logflag)
4856 + write_msg_out();
4857 + if( !nomain )
4858 + write_timeout_func();
4862 + * Write the _msgout function
4863 + */
4864 +void
4865 +write_msg_out(void)
4867 + f_print(fout, "\n");
4868 + f_print(fout, "static\n");
4869 + if( !Cflag ) {
4870 + f_print(fout, "void _msgout(msg)\n");
4871 + f_print(fout, "\tchar *msg;\n");
4872 + } else {
4873 + f_print(fout, "void _msgout(char* msg)\n");
4875 + f_print(fout, "{\n");
4876 + f_print(fout, "#ifdef RPC_SVC_FG\n");
4877 + if (inetdflag || pmflag)
4878 + f_print(fout, "\tif (_rpcpmstart)\n");
4879 + f_print(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n");
4880 + f_print(fout, "\telse\n");
4881 + f_print(fout, "\t\t(void) fprintf(stderr, \"%%s\\n\", msg);\n");
4882 + f_print(fout, "#else\n");
4883 + f_print(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n");
4884 + f_print(fout, "#endif\n");
4885 + f_print(fout, "}\n");
4889 + * Write the timeout function
4890 + */
4891 +static void
4892 +write_timeout_func(void)
4894 + if (!timerflag)
4895 + return;
4896 + f_print(fout, "\n");
4897 + f_print(fout, "static void\n");
4898 + f_print(fout, "closedown()\n");
4899 + f_print(fout, "{\n");
4900 + f_print(fout, "\tif (_rpcsvcdirty == 0) {\n");
4901 + f_print(fout, "\t\tstatic int size;\n");
4902 + f_print(fout, "\t\tint i, openfd;\n");
4903 + if (tirpcflag && pmflag) {
4904 + f_print(fout, "\t\tstruct t_info tinfo;\n\n");
4905 + f_print(fout, "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n");
4906 + } else {
4907 + f_print(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n");
4909 + f_print(fout, "\t\t\texit(0);\n");
4910 + f_print(fout, "\t\tif (size == 0) {\n");
4911 + if( tirpcflag ) {
4912 + f_print(fout, "\t\t\tstruct rlimit rl;\n\n");
4913 + f_print(fout, "\t\t\trl.rlim_max = 0;\n");
4914 + f_print(fout, "\t\t\tgetrlimit(RLIMIT_NOFILE, &rl);\n");
4915 + f_print(fout, "\t\t\tif ((size = rl.rlim_max) == 0)\n");
4916 + f_print(fout, "\t\t\t\treturn;\n");
4917 + } else {
4918 + f_print(fout, "\t\t\tsize = getdtablesize();\n");
4920 + f_print(fout, "\t\t}\n");
4921 + f_print(fout, "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n");
4922 + f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
4923 + f_print(fout, "\t\t\t\topenfd++;\n");
4924 + f_print(fout, "\t\tif (openfd <= 1)\n");
4925 + f_print(fout, "\t\t\texit(0);\n");
4926 + f_print(fout, "\t}\n");
4927 + f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
4928 + f_print(fout, "}\n");
4932 + * Write the most of port monitor support
4933 + */
4934 +static void
4935 +write_pm_most(char *infile, int netflag)
4937 + list *l;
4938 + definition *def;
4939 + version_list *vp;
4941 + f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n");
4942 + f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||");
4943 + f_print(fout, " !strcmp(mname, \"timod\"))) {\n");
4944 + f_print(fout, "\t\tchar *netid;\n");
4945 + if (!netflag) { /* Not included by -n option */
4946 + f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n");
4947 + f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP);
4949 + if( timerflag )
4950 + f_print(fout, "\t\tint pmclose;\n");
4951 +/* not necessary, defined in /usr/include/stdlib */
4952 +/* f_print(fout, "\t\textern char *getenv();\n");*/
4953 + f_print(fout, "\n");
4954 + f_print(fout, "\t\t_rpcpmstart = 1;\n");
4955 + if (logflag)
4956 + open_log_file(infile, "\t\t");
4957 + f_print(fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n");
4958 + sprintf(_errbuf, "cannot get transport name");
4959 + print_err_message("\t\t\t");
4960 + f_print(fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n");
4961 + sprintf(_errbuf, "cannot get transport info");
4962 + print_err_message("\t\t\t");
4963 + f_print(fout, "\t\t}\n");
4964 + /*
4965 + * A kludgy support for inetd services. Inetd only works with
4966 + * sockmod, and RPC works only with timod, hence all this jugglery
4967 + */
4968 + f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n");
4969 + f_print(fout, "\t\t\tif (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, \"timod\")) {\n");
4970 + sprintf(_errbuf, "could not get the right module");
4971 + print_err_message("\t\t\t\t");
4972 + f_print(fout, "\t\t\t\texit(1);\n");
4973 + f_print(fout, "\t\t\t}\n");
4974 + f_print(fout, "\t\t}\n");
4975 + if( timerflag )
4976 + f_print(fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
4977 + f_print(fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n",
4978 + TRANSP);
4979 + sprintf(_errbuf, "cannot create server handle");
4980 + print_err_message("\t\t\t");
4981 + f_print(fout, "\t\t\texit(1);\n");
4982 + f_print(fout, "\t\t}\n");
4983 + f_print(fout, "\t\tif (nconf)\n");
4984 + f_print(fout, "\t\t\tfreenetconfigent(nconf);\n");
4985 + for (l = defined; l != NULL; l = l->next) {
4986 + def = (definition *) l->val;
4987 + if (def->def_kind != DEF_PROGRAM) {
4988 + continue;
4990 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
4991 + f_print(fout,
4992 + "\t\tif (!svc_reg(%s, %s, %s, ",
4993 + TRANSP, def->def_name, vp->vers_name);
4994 + pvname(def->def_name, vp->vers_num);
4995 + f_print(fout, ", 0)) {\n");
4996 + (void) sprintf(_errbuf, "unable to register (%s, %s).",
4997 + def->def_name, vp->vers_name);
4998 + print_err_message("\t\t\t");
4999 + f_print(fout, "\t\t\texit(1);\n");
5000 + f_print(fout, "\t\t}\n");
5003 + if (timerflag) {
5004 + f_print(fout, "\t\tif (pmclose) {\n");
5005 + f_print(fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n",
5006 + Cflag? "(SIG_PF)" : "(void(*)())" );
5007 + f_print(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
5008 + f_print(fout, "\t\t}\n");
5010 + f_print(fout, "\t\tsvc_run();\n");
5011 + f_print(fout, "\t\texit(1);\n");
5012 + f_print(fout, "\t\t/* NOTREACHED */\n");
5013 + f_print(fout, "\t}\n");
5017 + * Support for backgrounding the server if self started.
5018 + */
5019 +static void
5020 +write_rpc_svc_fg(char *infile, char *sp)
5022 + f_print(fout, "#ifndef RPC_SVC_FG\n");
5023 + f_print(fout, "%sint size;\n", sp);
5024 + if( tirpcflag )
5025 + f_print(fout, "%sstruct rlimit rl;\n", sp);
5026 + if (inetdflag)
5027 + f_print(fout, "%sint pid, i;\n\n", sp);
5028 + f_print(fout, "%spid = fork();\n", sp);
5029 + f_print(fout, "%sif (pid < 0) {\n", sp);
5030 + f_print(fout, "%s\tperror(\"cannot fork\");\n", sp);
5031 + f_print(fout, "%s\texit(1);\n", sp);
5032 + f_print(fout, "%s}\n", sp);
5033 + f_print(fout, "%sif (pid)\n", sp);
5034 + f_print(fout, "%s\texit(0);\n", sp);
5035 + /* get number of file descriptors */
5036 + if( tirpcflag ) {
5037 + f_print(fout, "%srl.rlim_max = 0;\n", sp);
5038 + f_print(fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp);
5039 + f_print(fout, "%sif ((size = rl.rlim_max) == 0)\n", sp);
5040 + f_print(fout, "%s\texit(1);\n", sp);
5041 + } else {
5042 + f_print(fout, "%ssize = getdtablesize();\n", sp);
5045 + f_print(fout, "%sfor (i = 0; i < size; i++)\n", sp);
5046 + f_print(fout, "%s\t(void) close(i);\n", sp);
5047 + /* Redirect stderr and stdout to console */
5048 + f_print(fout, "%si = open(\"/dev/console\", 2);\n", sp);
5049 + f_print(fout, "%s(void) dup2(i, 1);\n", sp);
5050 + f_print(fout, "%s(void) dup2(i, 2);\n", sp);
5051 + /* This removes control of the controlling terminal */
5052 + if( tirpcflag )
5053 + f_print(fout, "%ssetsid();\n", sp);
5054 + else {
5055 + f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp);
5056 + f_print(fout, "%sif (i >= 0) {\n", sp);
5057 + f_print(fout, "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);;
5058 + f_print(fout, "%s\t(void) close(i);\n", sp);
5059 + f_print(fout, "%s}\n", sp);
5061 + if (!logflag)
5062 + open_log_file(infile, sp);
5063 + f_print(fout, "#endif\n");
5064 + if (logflag)
5065 + open_log_file(infile, sp);
5068 +static void
5069 +open_log_file(char *infile, char *sp)
5071 + char *s;
5073 + s = strrchr(infile, '.');
5074 + if (s)
5075 + *s = '\0';
5076 + f_print(fout,"%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile);
5077 + if (s)
5078 + *s = '.';
5085 + * write a registration for the given transport for Inetd
5086 + */
5087 +void
5088 +write_inetd_register(char *transp)
5090 + list *l;
5091 + definition *def;
5092 + version_list *vp;
5093 + char *sp;
5094 + int isudp;
5095 + char tmpbuf[32];
5097 + if (inetdflag)
5098 + sp = "\t";
5099 + else
5100 + sp = "";
5101 + if (streq(transp, "udp"))
5102 + isudp = 1;
5103 + else
5104 + isudp = 0;
5105 + f_print(fout, "\n");
5106 + if (inetdflag) {
5107 + f_print(fout, "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n",
5108 + isudp ? "SOCK_DGRAM" : "SOCK_STREAM");
5110 + f_print(fout, "%s\t%s = svc%s_create(%s",
5111 + sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK");
5112 + if (!isudp)
5113 + f_print(fout, ", 0, 0");
5114 + f_print(fout, ");\n");
5115 + f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
5116 + (void) sprintf(_errbuf, "cannot create %s service.", transp);
5117 + (void) sprintf(tmpbuf, "%s\t\t", sp);
5118 + print_err_message(tmpbuf);
5119 + f_print(fout, "%s\t\texit(1);\n", sp);
5120 + f_print(fout, "%s\t}\n", sp);
5122 + if (inetdflag) {
5123 + f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp);
5124 + f_print(fout, "%s\tproto = IPPROTO_%s;\n",
5125 + sp, isudp ? "UDP": "TCP");
5127 + for (l = defined; l != NULL; l = l->next) {
5128 + def = (definition *) l->val;
5129 + if (def->def_kind != DEF_PROGRAM) {
5130 + continue;
5132 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
5133 + f_print(fout, "%s\tif (!svc_register(%s, %s, %s, ",
5134 + sp, TRANSP, def->def_name, vp->vers_name);
5135 + pvname(def->def_name, vp->vers_num);
5136 + if (inetdflag)
5137 + f_print(fout, ", proto)) {\n");
5138 + else
5139 + f_print(fout, ", IPPROTO_%s)) {\n",
5140 + isudp ? "UDP": "TCP");
5141 + (void) sprintf(_errbuf, "unable to register (%s, %s, %s).",
5142 + def->def_name, vp->vers_name, transp);
5143 + print_err_message(tmpbuf);
5144 + f_print(fout, "%s\t\texit(1);\n", sp);
5145 + f_print(fout, "%s\t}\n", sp);
5148 + if (inetdflag)
5149 + f_print(fout, "\t}\n");
5151 diff --git a/rpcgen/rpc_tblout.c b/rpcgen/rpc_tblout.c
5152 new file mode 100644
5153 index 0000000..ae002f7
5154 --- /dev/null
5155 +++ b/rpcgen/rpc_tblout.c
5156 @@ -0,0 +1,165 @@
5158 + * Copyright (c) 2009, Sun Microsystems, Inc.
5159 + * All rights reserved.
5161 + * Redistribution and use in source and binary forms, with or without
5162 + * modification, are permitted provided that the following conditions are met:
5163 + * - Redistributions of source code must retain the above copyright notice,
5164 + * this list of conditions and the following disclaimer.
5165 + * - Redistributions in binary form must reproduce the above copyright notice,
5166 + * this list of conditions and the following disclaimer in the documentation
5167 + * and/or other materials provided with the distribution.
5168 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
5169 + * contributors may be used to endorse or promote products derived
5170 + * from this software without specific prior written permission.
5172 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5173 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5174 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5175 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
5176 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5177 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5178 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
5179 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
5180 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5181 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
5182 + * POSSIBILITY OF SUCH DAMAGE.
5183 + */
5185 +#if 0
5186 +static char sccsid[] = "@(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI";
5187 +#endif
5190 + * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler
5191 + */
5192 +#include <stdio.h>
5193 +#include <string.h>
5194 +#include "rpc_parse.h"
5195 +#include "rpc_util.h"
5196 +#include "rpc_output.h"
5198 +static void write_table(definition *def);
5199 +static void printit(char *prefix, char *type);
5201 +#define TABSIZE 8
5202 +#define TABCOUNT 5
5203 +#define TABSTOP (TABSIZE*TABCOUNT)
5205 +static char tabstr[TABCOUNT+1] = "\t\t\t\t\t";
5207 +static char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n";
5208 +static char tbl_end[] = "};\n";
5210 +static char null_entry[] = "\n\t(char *(*)())0,\n\
5211 + \t(xdrproc_t) xdr_void,\t\t\t0,\n\
5212 + \t(xdrproc_t) xdr_void,\t\t\t0,\n";
5215 +static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n";
5217 +void
5218 +write_tables(void)
5220 + list *l;
5221 + definition *def;
5223 + f_print(fout, "\n");
5224 + for (l = defined; l != NULL; l = l->next) {
5225 + def = (definition *) l->val;
5226 + if (def->def_kind == DEF_PROGRAM) {
5227 + write_table(def);
5232 +static void
5233 +write_table(definition *def)
5235 + version_list *vp;
5236 + proc_list *proc;
5237 + int current;
5238 + int expected;
5239 + char progvers[100];
5240 + int warning;
5242 + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
5243 + warning = 0;
5244 + s_print(progvers, "%s_%s",
5245 + locase(def->def_name), vp->vers_num);
5246 + /* print the table header */
5247 + f_print(fout, tbl_hdr, progvers);
5249 + if (nullproc(vp->procs)) {
5250 + expected = 0;
5251 + } else {
5252 + expected = 1;
5253 + f_print(fout, null_entry);
5255 + for (proc = vp->procs; proc != NULL; proc = proc->next) {
5256 + current = atoi(proc->proc_num);
5257 + if (current != expected++) {
5258 + f_print(fout,
5259 + "\n/*\n * WARNING: table out of order\n */\n");
5260 + if (warning == 0) {
5261 + f_print(stderr,
5262 + "WARNING %s table is out of order\n",
5263 + progvers);
5264 + warning = 1;
5265 + nonfatalerrors = 1;
5267 + expected = current + 1;
5269 + f_print(fout, "\n\t(char *(*)())RPCGEN_ACTION(");
5271 + /* routine to invoke */
5272 + if( Cflag && !newstyle )
5273 + pvname_svc(proc->proc_name, vp->vers_num);
5274 + else {
5275 + if( newstyle )
5276 + f_print( fout, "_"); /* calls internal func */
5277 + pvname(proc->proc_name, vp->vers_num);
5279 + f_print(fout, "),\n");
5281 + /* argument info */
5282 + if( proc->arg_num > 1 )
5283 + printit((char*) NULL, proc->args.argname );
5284 + else
5285 + /* do we have to do something special for newstyle */
5286 + printit( proc->args.decls->decl.prefix,
5287 + proc->args.decls->decl.type );
5288 + /* result info */
5289 + printit(proc->res_prefix, proc->res_type);
5292 + /* print the table trailer */
5293 + f_print(fout, tbl_end);
5294 + f_print(fout, tbl_nproc, progvers, progvers, progvers);
5298 +static void
5299 +printit(char *prefix, char *type)
5301 + int len;
5302 + int tabs;
5305 + len = fprintf(fout, "\txdr_%s,", stringfix(type));
5306 + /* account for leading tab expansion */
5307 + len += TABSIZE - 1;
5308 + /* round up to tabs required */
5309 + tabs = (TABSTOP - len + TABSIZE - 1)/TABSIZE;
5310 + f_print(fout, "%s", &tabstr[TABCOUNT-tabs]);
5312 + if (streq(type, "void")) {
5313 + f_print(fout, "0");
5314 + } else {
5315 + f_print(fout, "sizeof ( ");
5316 + /* XXX: should "follow" be 1 ??? */
5317 + ptype(prefix, type, 0);
5318 + f_print(fout, ")");
5320 + f_print(fout, ",\n");
5322 diff --git a/rpcgen/rpc_util.c b/rpcgen/rpc_util.c
5323 new file mode 100644
5324 index 0000000..b67be57
5325 --- /dev/null
5326 +++ b/rpcgen/rpc_util.c
5327 @@ -0,0 +1,479 @@
5329 + * Copyright (c) 2009, Sun Microsystems, Inc.
5330 + * All rights reserved.
5332 + * Redistribution and use in source and binary forms, with or without
5333 + * modification, are permitted provided that the following conditions are met:
5334 + * - Redistributions of source code must retain the above copyright notice,
5335 + * this list of conditions and the following disclaimer.
5336 + * - Redistributions in binary form must reproduce the above copyright notice,
5337 + * this list of conditions and the following disclaimer in the documentation
5338 + * and/or other materials provided with the distribution.
5339 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
5340 + * contributors may be used to endorse or promote products derived
5341 + * from this software without specific prior written permission.
5343 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5344 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5345 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5346 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
5347 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5348 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5349 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
5350 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
5351 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5352 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
5353 + * POSSIBILITY OF SUCH DAMAGE.
5354 + */
5356 +#if 0
5357 +static char sccsid[] = "@(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI";
5358 +#endif
5361 + * rpc_util.c, Utility routines for the RPC protocol compiler
5362 + */
5363 +#include <stdio.h>
5364 +#include <memory.h>
5365 +#include <ctype.h>
5366 +#include <unistd.h>
5367 +#include "rpc_scan.h"
5368 +#include "rpc_parse.h"
5369 +#include "rpc_util.h"
5371 +static void printwhere(void);
5374 +#define ARGEXT "argument"
5376 +char curline[MAXLINESIZE]; /* current read line */
5377 +char *where = curline; /* current point in line */
5378 +int linenum = 0; /* current line number */
5380 +char *infilename; /* input filename */
5382 +#define NFILES 7
5383 +char *outfiles[NFILES]; /* output file names */
5384 +int nfiles;
5386 +FILE *fout; /* file pointer of current output */
5387 +FILE *fin; /* file pointer of current input */
5389 +list *defined; /* list of defined things */
5392 + * Reinitialize the world
5393 + */
5394 +void
5395 +reinitialize(void)
5397 + memset(curline, 0, MAXLINESIZE);
5398 + where = curline;
5399 + linenum = 0;
5400 + defined = NULL;
5404 + * string equality
5405 + */
5406 +int
5407 +streq(char *a, char *b)
5409 + return (strcmp(a, b) == 0);
5413 + * find a value in a list
5414 + */
5415 +definition *
5416 +findval(list *lst, char *val, int (*cmp)(definition *, char *))
5419 + for (; lst != NULL; lst = lst->next) {
5420 + if ((*cmp) (lst->val, val)) {
5421 + return (lst->val);
5424 + return (NULL);
5428 + * store a value in a list
5429 + */
5430 +void
5431 +storeval(lstp, val)
5432 + list **lstp;
5433 + definition *val;
5435 + list **l;
5436 + list *lst;
5439 + for (l = lstp; *l != NULL; l = (list **) & (*l)->next);
5440 + lst = ALLOC(list);
5441 + lst->val = val;
5442 + lst->next = NULL;
5443 + *l = lst;
5446 +static int
5447 +findit(definition *def, char *type)
5449 + return (streq(def->def_name, type));
5452 +static char *
5453 +fixit(char *type, char *orig)
5455 + definition *def;
5457 + def = (definition *) FINDVAL(defined, type, findit);
5458 + if (def == NULL || def->def_kind != DEF_TYPEDEF) {
5459 + return (orig);
5461 + switch (def->def.ty.rel) {
5462 + case REL_VECTOR:
5463 + return (def->def.ty.old_type);
5464 + case REL_ALIAS:
5465 + return (fixit(def->def.ty.old_type, orig));
5466 + default:
5467 + return (orig);
5471 +char *
5472 +fixtype(char *type)
5474 + return (fixit(type, type));
5477 +char *
5478 +stringfix(char *type)
5480 + if (streq(type, "string")) {
5481 + return ("wrapstring");
5482 + } else {
5483 + return (type);
5487 +void
5488 +ptype(char *prefix, char *type, int follow)
5490 + if (prefix != NULL) {
5491 + if (streq(prefix, "enum")) {
5492 + f_print(fout, "enum ");
5493 + } else {
5494 + f_print(fout, "struct ");
5497 + if (streq(type, "bool")) {
5498 + f_print(fout, "bool_t ");
5499 + } else if (streq(type, "string")) {
5500 + f_print(fout, "char *");
5501 + } else {
5502 + f_print(fout, "%s ", follow ? fixtype(type) : type);
5506 +static int
5507 +typedefed(definition *def, char *type)
5509 + if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) {
5510 + return (0);
5511 + } else {
5512 + return (streq(def->def_name, type));
5516 +int
5517 +isvectordef(char *type, relation rel)
5519 + definition *def;
5521 + for (;;) {
5522 + switch (rel) {
5523 + case REL_VECTOR:
5524 + return (!streq(type, "string"));
5525 + case REL_ARRAY:
5526 + return (0);
5527 + case REL_POINTER:
5528 + return (0);
5529 + case REL_ALIAS:
5530 + def = (definition *) FINDVAL(defined, type, typedefed);
5531 + if (def == NULL) {
5532 + return (0);
5534 + type = def->def.ty.old_type;
5535 + rel = def->def.ty.rel;
5540 +char *
5541 +locase(char *str)
5543 + char c;
5544 + static char buf[100];
5545 + char *p = buf;
5547 + while ((c = *str++) != '\0') {
5548 + *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
5550 + *p = 0;
5551 + return (buf);
5554 +void
5555 +pvname_svc(char *pname, char *vnum)
5557 + f_print(fout, "%s_%s_svc", locase(pname), vnum);
5560 +void
5561 +pvname(char *pname, char *vnum)
5563 + f_print(fout, "%s_%s", locase(pname), vnum);
5567 + * print a useful (?) error message, and then die
5568 + */
5569 +void
5570 +error(char *msg)
5572 + printwhere();
5573 + f_print(stderr, "%s, line %d: ", infilename, linenum);
5574 + f_print(stderr, "%s\n", msg);
5575 + crash();
5579 + * Something went wrong, unlink any files that we may have created and then
5580 + * die.
5581 + */
5582 +void
5583 +crash(void)
5585 + int i;
5587 + for (i = 0; i < nfiles; i++) {
5588 + (void) unlink(outfiles[i]);
5590 + exit(1);
5593 +void
5594 +record_open(char *file)
5596 + if (nfiles < NFILES) {
5597 + outfiles[nfiles++] = file;
5598 + } else {
5599 + f_print(stderr, "too many files!\n");
5600 + crash();
5604 +static char expectbuf[100];
5605 +static char *toktostr();
5608 + * error, token encountered was not the expected one
5609 + */
5610 +void
5611 +expected1(exp1)
5612 + tok_kind exp1;
5614 + s_print(expectbuf, "expected '%s'",
5615 + toktostr(exp1));
5616 + error(expectbuf);
5620 + * error, token encountered was not one of two expected ones
5621 + */
5622 +void
5623 +expected2(exp1, exp2)
5624 + tok_kind exp1, exp2;
5626 + s_print(expectbuf, "expected '%s' or '%s'",
5627 + toktostr(exp1),
5628 + toktostr(exp2));
5629 + error(expectbuf);
5633 + * error, token encountered was not one of 3 expected ones
5634 + */
5635 +void
5636 +expected3(exp1, exp2, exp3)
5637 + tok_kind exp1, exp2, exp3;
5639 + s_print(expectbuf, "expected '%s', '%s' or '%s'",
5640 + toktostr(exp1),
5641 + toktostr(exp2),
5642 + toktostr(exp3));
5643 + error(expectbuf);
5646 +void
5647 +tabify(f, tab)
5648 + FILE *f;
5649 + int tab;
5651 + while (tab--) {
5652 + (void) fputc('\t', f);
5657 +static token tokstrings[] = {
5658 + {TOK_IDENT, "identifier"},
5659 + {TOK_CONST, "const"},
5660 + {TOK_RPAREN, ")"},
5661 + {TOK_LPAREN, "("},
5662 + {TOK_RBRACE, "}"},
5663 + {TOK_LBRACE, "{"},
5664 + {TOK_LBRACKET, "["},
5665 + {TOK_RBRACKET, "]"},
5666 + {TOK_STAR, "*"},
5667 + {TOK_COMMA, ","},
5668 + {TOK_EQUAL, "="},
5669 + {TOK_COLON, ":"},
5670 + {TOK_SEMICOLON, ";"},
5671 + {TOK_UNION, "union"},
5672 + {TOK_STRUCT, "struct"},
5673 + {TOK_SWITCH, "switch"},
5674 + {TOK_CASE, "case"},
5675 + {TOK_DEFAULT, "default"},
5676 + {TOK_ENUM, "enum"},
5677 + {TOK_TYPEDEF, "typedef"},
5678 + {TOK_INT, "int"},
5679 + {TOK_SHORT, "short"},
5680 + {TOK_INT32, "int32"},
5681 + {TOK_UNSIGNED, "unsigned"},
5682 + {TOK_DOUBLE, "double"},
5683 + {TOK_FLOAT, "float"},
5684 + {TOK_CHAR, "char"},
5685 + {TOK_STRING, "string"},
5686 + {TOK_OPAQUE, "opaque"},
5687 + {TOK_BOOL, "bool"},
5688 + {TOK_VOID, "void"},
5689 + {TOK_PROGRAM, "program"},
5690 + {TOK_VERSION, "version"},
5691 + {TOK_EOF, "??????"}
5694 +static char *
5695 +toktostr(kind)
5696 + tok_kind kind;
5698 + token *sp;
5700 + for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++);
5701 + return (sp->str);
5704 +static void
5705 +printbuf(void)
5707 + char c;
5708 + int i;
5709 + int cnt;
5711 +# define TABSIZE 4
5713 + for (i = 0; (c = curline[i]) != '\0'; i++) {
5714 + if (c == '\t') {
5715 + cnt = 8 - (i % TABSIZE);
5716 + c = ' ';
5717 + } else {
5718 + cnt = 1;
5720 + while (cnt--) {
5721 + (void) fputc(c, stderr);
5726 +static void
5727 +printwhere(void)
5729 + int i;
5730 + char c;
5731 + int cnt;
5733 + printbuf();
5734 + for (i = 0; i < where - curline; i++) {
5735 + c = curline[i];
5736 + if (c == '\t') {
5737 + cnt = 8 - (i % TABSIZE);
5738 + } else {
5739 + cnt = 1;
5741 + while (cnt--) {
5742 + (void) fputc('^', stderr);
5745 + (void) fputc('\n', stderr);
5748 +char *
5749 +make_argname(char *pname, char *vname)
5751 + char *name;
5753 + name = malloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3);
5754 + if (!name) {
5755 + fprintf(stderr, "failed in malloc");
5756 + exit(1);
5758 + sprintf(name, "%s_%s_%s", locase(pname), vname, ARGEXT);
5759 + return(name);
5762 +bas_type *typ_list_h;
5763 +bas_type *typ_list_t;
5765 +void
5766 +add_type(int len, char *type)
5768 + bas_type *ptr;
5771 + if ((ptr = (bas_type *) malloc(sizeof(bas_type))) == (bas_type *) NULL) {
5772 + fprintf(stderr, "failed in malloc");
5773 + exit(1);
5775 + ptr->name = type;
5776 + ptr->length = len;
5777 + ptr->next = NULL;
5778 + if (typ_list_t == NULL) {
5780 + typ_list_t = ptr;
5781 + typ_list_h = ptr;
5782 + } else {
5784 + typ_list_t->next = ptr;
5785 + typ_list_t = ptr;
5790 +bas_type *
5791 +find_type(char *type)
5793 + bas_type *ptr;
5795 + ptr = typ_list_h;
5798 + while (ptr != NULL) {
5799 + if (strcmp(ptr->name, type) == 0)
5800 + return (ptr);
5801 + else
5802 + ptr = ptr->next;
5803 + };
5804 + return (NULL);
5807 diff --git a/rpcgen/rpc_util.h b/rpcgen/rpc_util.h
5808 new file mode 100644
5809 index 0000000..fa115be
5810 --- /dev/null
5811 +++ b/rpcgen/rpc_util.h
5812 @@ -0,0 +1,166 @@
5814 + * Copyright (c) 2009, Sun Microsystems, Inc.
5815 + * All rights reserved.
5817 + * Redistribution and use in source and binary forms, with or without
5818 + * modification, are permitted provided that the following conditions are met:
5819 + * - Redistributions of source code must retain the above copyright notice,
5820 + * this list of conditions and the following disclaimer.
5821 + * - Redistributions in binary form must reproduce the above copyright notice,
5822 + * this list of conditions and the following disclaimer in the documentation
5823 + * and/or other materials provided with the distribution.
5824 + * - Neither the name of Sun Microsystems, Inc. nor the names of its
5825 + * contributors may be used to endorse or promote products derived
5826 + * from this software without specific prior written permission.
5828 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5829 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5830 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5831 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
5832 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5833 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5834 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
5835 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
5836 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5837 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
5838 + * POSSIBILITY OF SUCH DAMAGE.
5839 + */
5841 +/* @(#)rpc_util.h 1.5 90/08/29 (C) 1987 SMI */
5844 + * rpc_util.h, Useful definitions for the RPC protocol compiler
5845 + */
5847 +#include <stdlib.h>
5849 +#define alloc(size) malloc((unsigned)(size))
5850 +#define ALLOC(object) (object *) malloc(sizeof(object))
5852 +#define s_print (void) sprintf
5853 +#define f_print (void) fprintf
5855 +struct list {
5856 + definition *val;
5857 + struct list *next;
5859 +typedef struct list list;
5861 +#define PUT 1
5862 +#define GET 2
5865 + * Global variables
5866 + */
5867 +#define MAXLINESIZE 1024
5868 +extern char curline[MAXLINESIZE];
5869 +extern char *where;
5870 +extern int linenum;
5872 +extern char *infilename;
5873 +extern FILE *fout;
5874 +extern FILE *fin;
5876 +extern list *defined;
5879 +extern bas_type *typ_list_h;
5880 +extern bas_type *typ_list_t;
5883 + * All the option flags
5884 + */
5885 +extern int inetdflag;
5886 +extern int pmflag;
5887 +extern int tblflag;
5888 +extern int logflag;
5889 +extern int newstyle;
5890 +extern int Cflag; /* C++ flag */
5891 +extern int tirpcflag; /* flag for generating tirpc code */
5892 +extern int Inline; /* if this is 0, then do not generate inline code */
5895 + * Other flags related with inetd jumpstart.
5896 + */
5897 +extern int indefinitewait;
5898 +extern int exitnow;
5899 +extern int timerflag;
5901 +extern int nonfatalerrors;
5904 + * rpc_util routines
5905 + */
5906 +void storeval();
5908 +#define STOREVAL(list,item) \
5909 + storeval(list,item)
5911 +definition *findval();
5913 +#define FINDVAL(list,item,finder) \
5914 + findval(list, item, finder)
5918 + * rpc_cout routines
5919 + */
5920 +void cprint(void);
5921 +void emit(definition *);
5924 + * rpc_hout routines
5925 + */
5926 +void print_datadef(definition *);
5927 +void print_funcdef(definition *);
5930 + * rpc_svcout routines
5931 + */
5932 +void write_most(char *, int, int);
5933 +void write_register(void);
5934 +void write_netid_register(char *);
5935 +void write_nettype_register(char *);
5936 +void write_inetd_register(char *);
5937 +void write_rest(void);
5938 +void write_programs(char *);
5939 +void write_svc_aux(int);
5942 + * rpc_clntout routines
5943 + */
5944 +void write_stubs(void);
5945 +void printarglist(proc_list *, char *, char *);
5948 + * rpc_tblout routines
5949 + */
5950 +void write_tables(void);
5953 + * rpc_util
5954 + */
5955 +void pvname_svc(char *, char *);
5956 +void pvname(char *, char *);
5957 +void ptype(char *, char *, int);
5958 +char * make_argname(char *, char *);
5959 +void add_type(int, char *);
5960 +void reinitialize(void);
5961 +void crash(void);
5962 +void error(char *);
5963 +char *fixtype(char *);
5964 +char *stringfix(char *);
5965 +char *locase(char *);
5966 +int isvectordef(char *, relation);
5967 +int streq(char *, char *);
5968 +void tabify(FILE *, int);
5969 +void record_open(char *);
5970 +bas_type *find_type(char *type);
5973 + * rpc_sample
5974 + */
5975 +void write_sample_svc(definition *);
5976 +int write_sample_clnt(definition *);
5977 +void write_sample_clnt_main(void);
5978 +void add_sample_msg(void);
5979 diff --git a/rpcgen/rpcgen.1 b/rpcgen/rpcgen.1
5980 new file mode 100644
5981 index 0000000..89df7ed
5982 --- /dev/null
5983 +++ b/rpcgen/rpcgen.1
5984 @@ -0,0 +1,521 @@
5985 +.\" @(#)rpcgen.1 1.35 93/06/02 SMI
5986 +.\" $FreeBSD: src/usr.bin/rpcgen/rpcgen.1,v 1.12.2.4 2002/06/21 15:28:50 charnier Exp $
5987 +.\" Copyright 1985-1993 Sun Microsystems, Inc.
5988 +.Dd March 28, 1993
5989 +.Dt RPCGEN 1
5990 +.Os
5991 +.Sh NAME
5992 +.Nm rpcgen
5993 +.Nd an RPC protocol compiler
5994 +.Sh SYNOPSIS
5995 +.Nm
5996 +.Ar infile
5997 +.Nm
5998 +.Op Fl a
5999 +.Op Fl b
6000 +.Op Fl C
6001 +.Oo
6002 +.Fl D Ns Ar name Ns Op Ar =value
6003 +.Oc
6004 +.Op Fl i Ar size
6005 +.Op Fl I Op Fl K Ar seconds
6006 +.Op Fl L
6007 +.Op Fl M
6008 +.Op Fl N
6009 +.Op Fl T
6010 +.Op Fl Y Ar pathname
6011 +.Ar infile
6012 +.Nm
6013 +.Oo
6014 +.Fl c |
6015 +.Fl h |
6016 +.Fl l |
6017 +.Fl m |
6018 +.Fl t |
6019 +.Fl \&Sc |
6020 +.Fl \&Ss |
6021 +.Fl \&Sm
6022 +.Oc
6023 +.Op Fl o Ar outfile
6024 +.Op Ar infile
6025 +.Nm
6026 +.Op Fl s Ar nettype
6027 +.Op Fl o Ar outfile
6028 +.Op Ar infile
6029 +.Nm
6030 +.Op Fl n Ar netid
6031 +.Op Fl o Ar outfile
6032 +.Op Ar infile
6033 +.\" .SH AVAILABILITY
6034 +.\" .LP
6035 +.\" SUNWcsu
6036 +.Sh DESCRIPTION
6037 +The
6038 +.Nm
6039 +utility is a tool that generates C code to implement an
6040 +.Tn RPC
6041 +protocol.
6042 +The input to
6043 +.Nm
6044 +is a language similar to C known as
6045 +.Tn RPC
6046 +Language (Remote Procedure Call Language).
6047 +.Pp
6048 +The
6049 +.Nm
6050 +utility is normally used as in the first synopsis where
6051 +it takes an input file and generates three output files.
6052 +If the
6053 +.Ar infile
6054 +is named
6055 +.Pa proto.x ,
6056 +then
6057 +.Nm
6058 +generates a header in
6059 +.Pa proto.h ,
6060 +XDR routines in
6061 +.Pa proto_xdr.c ,
6062 +server-side stubs in
6063 +.Pa proto_svc.c ,
6064 +and client-side stubs in
6065 +.Pa proto_clnt.c .
6066 +With the
6067 +.Fl T
6068 +option,
6069 +it also generates the
6070 +.Tn RPC
6071 +dispatch table in
6072 +.Pa proto_tbl.i .
6073 +.Pp
6074 +The
6075 +.Nm
6076 +utility can also generate sample client and server files
6077 +that can be customized to suit a particular application.
6078 +The
6079 +.Fl \&Sc ,
6080 +.Fl \&Ss
6081 +and
6082 +.Fl \&Sm
6083 +options generate sample client, server and makefile, respectively.
6084 +The
6085 +.Fl a
6086 +option generates all files, including sample files.
6087 +If the
6088 +.Ar infile
6090 +.Pa proto.x ,
6091 +then the client side sample file is written to
6092 +.Pa proto_client.c ,
6093 +the server side sample file to
6094 +.Pa proto_server.c
6095 +and the sample makefile to
6096 +.Pa makefile.proto .
6097 +.Pp
6098 +The server created can be started both by the port monitors
6099 +(for example,
6100 +.Xr inetd 8 )
6101 +or by itself.
6102 +When it is started by a port monitor,
6103 +it creates servers only for the transport for which
6104 +the file descriptor
6105 +.Em 0
6106 +was passed.
6107 +The name of the transport must be specified
6108 +by setting up the environment variable
6109 +.Ev PM_TRANSPORT .
6110 +When the server generated by
6111 +.Nm
6112 +is executed,
6113 +it creates server handles for all the transports
6114 +specified in
6115 +.Ev NETPATH
6116 +environment variable,
6117 +or if it is unset,
6118 +it creates server handles for all the visible transports from
6119 +.Pa /etc/netconfig
6120 +file.
6121 +Note:
6122 +the transports are chosen at run time and not at compile time.
6123 +When the server is self-started,
6124 +it backgrounds itself by default.
6125 +A special define symbol
6126 +.Em RPC_SVC_FG
6127 +can be used to run the server process in foreground.
6128 +.Pp
6129 +The second synopsis provides special features which allow
6130 +for the creation of more sophisticated
6131 +.Tn RPC
6132 +servers.
6133 +These features include support for user provided
6134 +.Em #defines
6135 +and
6136 +.Tn RPC
6137 +dispatch tables.
6138 +The entries in the
6139 +.Tn RPC
6140 +dispatch table contain:
6141 +.Bl -bullet -offset indent -compact
6142 +.It
6143 +pointers to the service routine corresponding to that procedure,
6144 +.It
6145 +a pointer to the input and output arguments,
6146 +.It
6147 +the size of these routines.
6148 +.El
6149 +A server can use the dispatch table to check authorization
6150 +and then to execute the service routine;
6151 +a client library may use it to deal with the details of storage
6152 +management and XDR data conversion.
6153 +.Pp
6154 +The other three synopses shown above are used when
6155 +one does not want to generate all the output files,
6156 +but only a particular one.
6157 +See the
6158 +.Sx EXAMPLES
6159 +section below for examples of
6160 +.Nm
6161 +usage.
6162 +When
6163 +.Nm
6164 +is executed with the
6165 +.Fl s
6166 +option,
6167 +it creates servers for that particular class of transports.
6168 +When
6169 +executed with the
6170 +.Fl n
6171 +option,
6172 +it creates a server for the transport specified by
6173 +.Ar netid .
6175 +.Ar infile
6176 +is not specified,
6177 +.Nm
6178 +accepts the standard input.
6179 +.Pp
6180 +The C preprocessor,
6181 +.Em cc -E
6182 +is run on the input file before it is actually interpreted by
6183 +.Nm .
6184 +For each type of output file,
6185 +.Nm
6186 +defines a special preprocessor symbol for use by the
6187 +.Nm
6188 +programmer:
6189 +.Bl -tag -width indent
6190 +.It RPC_HDR
6191 +defined when compiling into headers
6192 +.It RPC_XDR
6193 +defined when compiling into XDR routines
6194 +.It RPC_SVC
6195 +defined when compiling into server-side stubs
6196 +.It RPC_CLNT
6197 +defined when compiling into client-side stubs
6198 +.It RPC_TBL
6199 +defined when compiling into RPC dispatch tables
6200 +.El
6201 +.Pp
6202 +Any line beginning with
6203 +.Dq %
6204 +is passed directly into the output file,
6205 +uninterpreted by
6206 +.Nm .
6207 +To specify the path name of the C preprocessor use
6208 +.Fl Y
6209 +flag.
6210 +.Pp
6211 +For every data type referred to in
6212 +.Ar infile ,
6213 +.Nm
6214 +assumes that there exists a
6215 +routine with the string
6216 +.Em xdr_
6217 +prepended to the name of the data type.
6218 +If this routine does not exist in the
6219 +.Tn RPC/XDR
6220 +library, it must be provided.
6221 +Providing an undefined data type
6222 +allows customization of
6223 +.Xr xdr 3
6224 +routines.
6225 +.Sh OPTIONS
6226 +The following options are available:
6227 +.Bl -tag -width indent
6228 +.It Fl a
6229 +Generate all files, including sample files.
6230 +.It Fl b
6231 +Backward compatibility mode.
6232 +Generate transport specific
6233 +.Tn RPC
6234 +code for older versions
6235 +of the operating system.
6236 +.Pp
6237 +Note: in
6238 +.Fx ,
6239 +this compatibility flag is turned on by
6240 +default since
6241 +.Fx
6242 +supports only the older
6243 +.Tn ONC RPC
6244 +library.
6245 +.It Fl c
6246 +Compile into
6247 +.Tn XDR
6248 +routines.
6249 +.It Fl C
6250 +Generate header and stub files which can be used with
6251 +.Tn ANSI
6252 +C compilers. Headers generated with this flag can also be
6253 +used with C++ programs.
6254 +.It Fl D Ns Ar name
6255 +.It Fl D Ns Ar name=value
6256 +.\".It Fl D Ns Ar name Ns Op Ar =value
6257 +Define a symbol
6258 +.Ar name .
6259 +Equivalent to the
6260 +.Em #define
6261 +directive in the source.
6262 +If no
6263 +.Ar value
6264 +is given,
6265 +.Ar value
6266 +is defined as
6267 +.Em 1 .
6268 +This option may be specified more than once.
6269 +.It Fl h
6270 +Compile into C data-definitions (a header).
6271 +.Fl T
6272 +option can be used in conjunction to produce a
6273 +header which supports
6274 +.Tn RPC
6275 +dispatch tables.
6276 +.It Fl i Ar size
6277 +Size at which to start generating inline code.
6278 +This option is useful for optimization.
6279 +The default size is 5.
6280 +.Pp
6281 +Note: in order to provide backwards compatibility with the older
6282 +.Nm
6283 +on the
6284 +.Fx
6285 +platform, the default is actually 0 (which means
6286 +that inline code generation is disabled by default). You must specify
6287 +a non-zero value explicitly to override this default.
6288 +.It Fl I
6289 +Compile support for
6290 +.Xr inetd 8
6291 +in the server side stubs.
6292 +Such servers can be self-started or can be started by
6293 +.Nm inetd .
6294 +When the server is self-started, it backgrounds itself by default.
6295 +A special define symbol
6296 +.Em RPC_SVC_FG
6297 +can be used to run the
6298 +server process in foreground, or the user may simply compile without
6299 +the
6300 +.Fl I
6301 +option.
6302 +.Pp
6303 +If there are no pending client requests, the
6304 +.Nm inetd
6305 +servers exit after 120 seconds (default).
6306 +The default can be changed with the
6307 +.Fl K
6308 +option.
6309 +All the error messages for
6310 +.Nm inetd
6311 +servers
6312 +are always logged with
6313 +.Xr syslog 3 .
6314 +.\" .IP
6315 +.\" Note:
6316 +.\" this option is supported for backward compatibility only.
6317 +.\" By default,
6318 +.\" .B rpcgen
6319 +.\" generates servers that can be invoked through portmonitors.
6320 +.Pp
6321 +.It Fl K Ar seconds
6322 +By default, services created using
6323 +.Nm
6324 +and invoked through
6325 +port monitors wait 120 seconds
6326 +after servicing a request before exiting.
6327 +That interval can be changed using the
6328 +.Fl K
6329 +flag.
6330 +To create a server that exits immediately upon servicing a request,
6331 +use
6332 +.Fl K Ar 0 .
6333 +To create a server that never exits, the appropriate argument is
6334 +.Fl k Ar -1 .
6335 +.Pp
6336 +When monitoring for a server,
6337 +some portmonitors
6338 +.Em always
6339 +spawn a new process in response to a service request.
6340 +If it is known that a server will be used with such a monitor, the
6341 +server should exit immediately on completion.
6342 +For such servers,
6343 +.Nm
6344 +should be used with
6345 +.Fl K Ar 0 .
6346 +.It Fl l
6347 +Compile into client-side stubs.
6348 +.It Fl L
6349 +When the servers are started in foreground, use
6350 +.Xr syslog 3
6351 +to log the server errors instead of printing them on the standard
6352 +error.
6353 +.It Fl m
6354 +Compile into server-side stubs,
6355 +but do not generate a
6356 +.Qq main
6357 +routine.
6358 +This option is useful for doing callback-routines
6359 +and for users who need to write their own
6360 +.Qq main
6361 +routine to do initialization.
6362 +.It Fl M
6363 +Generate multithread-safe stubs for passing arguments and results between
6364 +rpcgen generated code and user written code.
6365 +This option is useful
6366 +for users who want to use threads in their code.
6367 +However, the
6368 +.Xr rpc_svc_calls 3
6369 +functions are not yet MT-safe, which means that rpcgen generated server-side
6370 +code will not be MT-safe.
6371 +.It Fl N
6372 +This option allows procedures to have multiple arguments.
6373 +It also uses the style of parameter passing that closely resembles C.
6374 +So, when passing an argument to a remote procedure, you do not have to
6375 +pass a pointer to the argument, but can pass the argument itself.
6376 +This behavior is different from the old style of
6377 +.Nm
6378 +generated code.
6379 +To maintain backward compatibility,
6380 +this option is not the default.
6381 +.It Fl n Ar netid
6382 +Compile into server-side stubs for the transport
6383 +specified by
6384 +.Ar netid .
6385 +There should be an entry for
6386 +.Ar netid
6387 +in the
6388 +netconfig database.
6389 +This option may be specified more than once,
6390 +so as to compile a server that serves multiple transports.
6391 +.It Fl o Ar outfile
6392 +Specify the name of the output file.
6393 +If none is specified,
6394 +standard output is used
6396 +.Fl c ,
6397 +.Fl h ,
6398 +.Fl l ,
6399 +.Fl m ,
6400 +.Fl n ,
6401 +.Fl s ,
6402 +.Fl \&Sc ,
6403 +.Fl \&Sm ,
6404 +.Fl \&Ss ,
6405 +and
6406 +.Fl t
6407 +modes only).
6408 +.It Fl s Ar nettype
6409 +Compile into server-side stubs for all the
6410 +transports belonging to the class
6411 +.Ar nettype .
6412 +The supported classes are
6413 +.Em netpath ,
6414 +.Em visible ,
6415 +.Em circuit_n ,
6416 +.Em circuit_v ,
6417 +.Em datagram_n ,
6418 +.Em datagram_v ,
6419 +.Em tcp ,
6420 +and
6421 +.Em udp
6422 +(see
6423 +.Xr rpc 3
6424 +for the meanings associated with these classes).
6425 +This option may be specified more than once.
6426 +Note:
6427 +the transports are chosen at run time and not at compile time.
6428 +.It Fl \&Sc
6429 +Generate sample client code that uses remote procedure calls.
6430 +.It Fl \&Sm
6431 +Generate a sample
6432 +.Pa Makefile
6433 +which can be used for compiling the application.
6434 +.It Fl \&Ss
6435 +Generate sample server code that uses remote procedure calls.
6436 +.It Fl t
6437 +Compile into
6438 +.Tn RPC
6439 +dispatch table.
6440 +.It Fl T
6441 +Generate the code to support
6442 +.Tn RPC
6443 +dispatch tables.
6444 +.Pp
6445 +The options
6446 +.Fl c ,
6447 +.Fl h ,
6448 +.Fl l ,
6449 +.Fl m ,
6450 +.Fl s ,
6451 +.Fl \&Sc ,
6452 +.Fl \&Sm ,
6453 +.Fl \&Ss ,
6454 +and
6455 +.Fl t
6456 +are used exclusively to generate a particular type of file,
6457 +while the options
6458 +.Fl D
6459 +and
6460 +.Fl T
6461 +are global and can be used with the other options.
6462 +.It Fl Y Ar pathname
6463 +Give the name of the directory where
6464 +.Nm
6465 +will start looking for the C-preprocessor.
6466 +.El
6467 +.Sh EXAMPLES
6468 +The following example:
6469 +.Dl example% rpcgen -T prot.x
6470 +.Pp
6471 +generates all the five files:
6472 +.Pa prot.h ,
6473 +.Pa prot_clnt.c ,
6474 +.Pa prot_svc.c ,
6475 +.Pa prot_xdr.c
6476 +and
6477 +.Pa prot_tbl.i .
6478 +.Pp
6479 +The following example sends the C data-definitions (header)
6480 +to the standard output.
6481 +.Dl example% rpcgen -h prot.x
6482 +.Pp
6483 +To send the test version of the
6484 +.Fl D Ns Ar TEST ,
6485 +server side stubs for
6486 +all the transport belonging to the class
6487 +.Ar datagram_n
6488 +to standard output, use:
6489 +.Dl example% rpcgen -s datagram_n -DTEST prot.x
6490 +.Pp
6491 +To create the server side stubs for the transport indicated
6493 +.Ar netid
6494 +tcp,
6495 +use:
6496 +.Dl example% rpcgen -n tcp -o prot_svc.c prot.x
6497 +.Sh SEE ALSO
6498 +.Xr cc 1 ,
6499 +.Xr rpc 3 ,
6500 +.Xr syslog 3 ,
6501 +.Xr inetd 8
6502 +.\" .BR rpc_svc_calls (3)
6503 +.Rs
6504 +.%T The rpcgen chapter in the NETP manual
6505 +.Re
6507 1.9.1