summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2012-11-10 11:42:40 +0000
committerPeter Korsgaard <jacmet@sunsite.dk>2012-11-14 22:58:17 +0100
commit18828103cdc8b929b29f5cbc27cd771ab1a26326 (patch)
tree7ac4af38f456d37d2117e41a1590e566b8d3f03c
parent9346b1b979edc6444ca8539aec9e1bac585e001f (diff)
downloadbuildroot-novena-18828103cdc8b929b29f5cbc27cd771ab1a26326.tar.gz
buildroot-novena-18828103cdc8b929b29f5cbc27cd771ab1a26326.zip
libtirpc: add patches to fix a number of issues
libtirpc-0005-rpcent-mark-getrpcbyname-name-argument-as-const-char.patch fixes build failures like http://autobuild.buildroot.org/results/7a3a751fe02c639ca75c575ca7fe20a72372b8d6/build-end.log. libtirpc-0006-rpcent-remove-prototypes-of-reentrant-variants.patch ensures that functions not implemented by libtirpc are not described in a header file. It also allows to remove those prototypes that were not matching the functions available in glibc or uClibc, causing mismatch in prototypes. libtirpc-0007-doc-Makefile.am-fix-out-of-tree-installation.patch is a minor fix. The following patches (8 to 9) allow libtirpc to provide sufficient things to be able to build rpcbind on top of it. All these patches have been submitted upstream on the libtirpc-devel@ mailing list. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Acked-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
-rw-r--r--package/libtirpc/libtirpc-0005-rpcent-mark-getrpcbyname-name-argument-as-const-char.patch43
-rw-r--r--package/libtirpc/libtirpc-0006-rpcent-remove-prototypes-of-reentrant-variants.patch33
-rw-r--r--package/libtirpc/libtirpc-0007-doc-Makefile.am-fix-out-of-tree-installation.patch24
-rw-r--r--package/libtirpc/libtirpc-0008-Add-rpcgen-program-from-nfs-utils-sources.patch6504
-rw-r--r--package/libtirpc/libtirpc-0009-Automatically-generate-XDR-header-files-from-.x-sour.patch999
-rw-r--r--package/libtirpc/libtirpc-0010-Add-more-XDR-files-needed-to-build-rpcbind-on-top-of.patch1649
6 files changed, 9252 insertions, 0 deletions
diff --git a/package/libtirpc/libtirpc-0005-rpcent-mark-getrpcbyname-name-argument-as-const-char.patch b/package/libtirpc/libtirpc-0005-rpcent-mark-getrpcbyname-name-argument-as-const-char.patch
new file mode 100644
index 000000000..b1865aee7
--- /dev/null
+++ b/package/libtirpc/libtirpc-0005-rpcent-mark-getrpcbyname-name-argument-as-const-char.patch
@@ -0,0 +1,43 @@
+From 88147b753b86df7e7505ef8150f1329f7c6951cc Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 9 Nov 2012 19:37:24 +0100
+Subject: [PATCH] rpcent: mark getrpcbyname name argument as const char *
+
+This allows to match the glibc prototype and avoid compiling error
+when building libtirpc against a C library that has RPC support.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ src/getrpcent.c | 2 +-
+ tirpc/rpc/rpcent.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/getrpcent.c b/src/getrpcent.c
+index 645f18f..1b54b6d 100644
+--- a/src/getrpcent.c
++++ b/src/getrpcent.c
+@@ -138,7 +138,7 @@ no_yp:
+
+ struct rpcent *
+ getrpcbyname(name)
+- char *name;
++ const char *name;
+ {
+ struct rpcent *rpc = NULL;
+ char **rp;
+diff --git a/tirpc/rpc/rpcent.h b/tirpc/rpc/rpcent.h
+index 8ce05ed..120801d 100644
+--- a/tirpc/rpc/rpcent.h
++++ b/tirpc/rpc/rpcent.h
+@@ -61,7 +61,7 @@ extern struct rpcent *getrpcbynumber_r(int, struct rpcent *, char *, int);
+ extern struct rpcent *getrpcent_r(struct rpcent *, char *, int);
+
+ /* Old interfaces that return a pointer to a static area; MT-unsafe */
+-extern struct rpcent *getrpcbyname(char *);
++extern struct rpcent *getrpcbyname(const char *);
+ extern struct rpcent *getrpcbynumber(int);
+ extern struct rpcent *getrpcent(void);
+ #endif
+--
+1.7.9.5
+
diff --git a/package/libtirpc/libtirpc-0006-rpcent-remove-prototypes-of-reentrant-variants.patch b/package/libtirpc/libtirpc-0006-rpcent-remove-prototypes-of-reentrant-variants.patch
new file mode 100644
index 000000000..1fdc310ef
--- /dev/null
+++ b/package/libtirpc/libtirpc-0006-rpcent-remove-prototypes-of-reentrant-variants.patch
@@ -0,0 +1,33 @@
+From 8e02780905a3e13405a5a1b9f5b2e77655d5c7fb Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Sat, 10 Nov 2012 00:05:23 +0100
+Subject: [PATCH] rpcent: remove prototypes of reentrant variants
+
+The reentrant variants of getrpcbynumber() and al. are not implemented
+by libtirpc, so there is no point in advertising them in this header
+file.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ tirpc/rpc/rpcent.h | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/tirpc/rpc/rpcent.h b/tirpc/rpc/rpcent.h
+index 120801d..45775ed 100644
+--- a/tirpc/rpc/rpcent.h
++++ b/tirpc/rpc/rpcent.h
+@@ -55,11 +55,6 @@ struct rpcent {
+ int r_number; /* rpc program number */
+ };
+
+-extern struct rpcent *getrpcbyname_r(const char *, struct rpcent *,
+- char *, int);
+-extern struct rpcent *getrpcbynumber_r(int, struct rpcent *, char *, int);
+-extern struct rpcent *getrpcent_r(struct rpcent *, char *, int);
+-
+ /* Old interfaces that return a pointer to a static area; MT-unsafe */
+ extern struct rpcent *getrpcbyname(const char *);
+ extern struct rpcent *getrpcbynumber(int);
+--
+1.7.9.5
+
diff --git a/package/libtirpc/libtirpc-0007-doc-Makefile.am-fix-out-of-tree-installation.patch b/package/libtirpc/libtirpc-0007-doc-Makefile.am-fix-out-of-tree-installation.patch
new file mode 100644
index 000000000..c31992c12
--- /dev/null
+++ b/package/libtirpc/libtirpc-0007-doc-Makefile.am-fix-out-of-tree-installation.patch
@@ -0,0 +1,24 @@
+From 4cf0371c96abf83483835daf50d3fc3bf793bdc4 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Sat, 10 Nov 2012 17:29:12 +0100
+Subject: [PATCH] doc/Makefile.am: fix out-of-tree installation
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ doc/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/doc/Makefile.am b/doc/Makefile.am
+index cc4fa76..bac7c0f 100644
+--- a/doc/Makefile.am
++++ b/doc/Makefile.am
+@@ -1,5 +1,5 @@
+
+ install: install-am
+ $(mkinstalldirs) $(DESTDIR)/etc
+- cp -p ./etc_netconfig $(DESTDIR)/etc/netconfig
++ cp -p $(srcdir)/etc_netconfig $(DESTDIR)/etc/netconfig
+ chmod 0644 $(DESTDIR)/etc/netconfig
+--
+1.7.9.5
+
diff --git a/package/libtirpc/libtirpc-0008-Add-rpcgen-program-from-nfs-utils-sources.patch b/package/libtirpc/libtirpc-0008-Add-rpcgen-program-from-nfs-utils-sources.patch
new file mode 100644
index 000000000..27c60649d
--- /dev/null
+++ b/package/libtirpc/libtirpc-0008-Add-rpcgen-program-from-nfs-utils-sources.patch
@@ -0,0 +1,6504 @@
+From 8a1ee148ea860c20fa4e076839e5681412a11f7e Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Sat, 10 Nov 2012 16:21:01 +0100
+Subject: [PATCH] Add rpcgen program from nfs-utils sources
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ Makefile.am | 2 +-
+ configure.ac | 12 +-
+ rpcgen/Makefile.am | 22 ++
+ rpcgen/rpc_clntout.c | 217 ++++++++++
+ rpcgen/rpc_cout.c | 706 +++++++++++++++++++++++++++++++++
+ rpcgen/rpc_hout.c | 490 +++++++++++++++++++++++
+ rpcgen/rpc_main.c | 1067 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ rpcgen/rpc_output.h | 16 +
+ rpcgen/rpc_parse.c | 609 ++++++++++++++++++++++++++++
+ rpcgen/rpc_parse.h | 166 ++++++++
+ rpcgen/rpc_sample.c | 247 ++++++++++++
+ rpcgen/rpc_scan.c | 474 ++++++++++++++++++++++
+ rpcgen/rpc_scan.h | 103 +++++
+ rpcgen/rpc_svcout.c | 882 +++++++++++++++++++++++++++++++++++++++++
+ rpcgen/rpc_tblout.c | 165 ++++++++
+ rpcgen/rpc_util.c | 479 ++++++++++++++++++++++
+ rpcgen/rpc_util.h | 166 ++++++++
+ rpcgen/rpcgen.1 | 521 ++++++++++++++++++++++++
+ 18 files changed, 6342 insertions(+), 2 deletions(-)
+ create mode 100644 rpcgen/Makefile.am
+ create mode 100644 rpcgen/rpc_clntout.c
+ create mode 100644 rpcgen/rpc_cout.c
+ create mode 100644 rpcgen/rpc_hout.c
+ create mode 100644 rpcgen/rpc_main.c
+ create mode 100644 rpcgen/rpc_output.h
+ create mode 100644 rpcgen/rpc_parse.c
+ create mode 100644 rpcgen/rpc_parse.h
+ create mode 100644 rpcgen/rpc_sample.c
+ create mode 100644 rpcgen/rpc_scan.c
+ create mode 100644 rpcgen/rpc_scan.h
+ create mode 100644 rpcgen/rpc_svcout.c
+ create mode 100644 rpcgen/rpc_tblout.c
+ create mode 100644 rpcgen/rpc_util.c
+ create mode 100644 rpcgen/rpc_util.h
+ create mode 100644 rpcgen/rpcgen.1
+
+diff --git a/Makefile.am b/Makefile.am
+index 1a7596b..afb4e38 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,4 +1,4 @@
+-SUBDIRS = src man doc
++SUBDIRS = src man doc rpcgen
+ ACLOCAL_AMFLAGS = -I m4
+
+ nobase_include_HEADERS = tirpc/netconfig.h \
+diff --git a/configure.ac b/configure.ac
+index 487ec83..7f35b48 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -29,6 +29,16 @@ AC_CHECK_HEADER(netinet/ip6.h,
+
+ AC_CHECK_LIB([pthread], [pthread_create])
+
++AM_CONDITIONAL(CROSS_COMPILING, test $cross_compiling = yes)
+
+-AC_CONFIG_FILES([Makefile src/Makefile man/Makefile doc/Makefile])
++AC_MSG_CHECKING([for a C compiler for build tools])
++if test $cross_compiling = yes; then
++ AC_CHECK_PROGS(CC_FOR_BUILD, gcc cc)
++else
++ CC_FOR_BUILD=$CC
++fi
++AC_MSG_RESULT([$CC_FOR_BUILD])
++AC_SUBST(CC_FOR_BUILD)
++
++AC_CONFIG_FILES([Makefile src/Makefile man/Makefile doc/Makefile rpcgen/Makefile])
+ AC_OUTPUT(libtirpc.pc)
+diff --git a/rpcgen/Makefile.am b/rpcgen/Makefile.am
+new file mode 100644
+index 0000000..2277b6f
+--- /dev/null
++++ b/rpcgen/Makefile.am
+@@ -0,0 +1,22 @@
++COMPILE = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
++ $(CPPFLAGS_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD)
++LINK = $(CC_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) $(AM_LDFLAGS) $(LDFLAGS_FOR_BUILD) -o $@
++
++bin_PROGRAMS = rpcgen
++
++rpcgen_SOURCES = \
++ rpc_clntout.c \
++ rpc_cout.c \
++ rpc_hout.c \
++ rpc_main.c \
++ rpc_parse.c \
++ rpc_sample.c \
++ rpc_scan.c \
++ rpc_svcout.c \
++ rpc_tblout.c \
++ rpc_util.c \
++ rpc_parse.h \
++ rpc_scan.h \
++ rpc_util.h
++
++dist_man1_MANS = rpcgen.1
+diff --git a/rpcgen/rpc_clntout.c b/rpcgen/rpc_clntout.c
+new file mode 100644
+index 0000000..e2f4382
+--- /dev/null
++++ b/rpcgen/rpc_clntout.c
+@@ -0,0 +1,217 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI";
++#endif
++
++/*
++ * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
++ * Copyright (C) 1987, Sun Microsytsems, Inc.
++ */
++#include <stdio.h>
++#include <string.h>
++#include <rpc/types.h>
++#include "rpc_parse.h"
++#include "rpc_util.h"
++#include "rpc_output.h"
++
++/* extern pdeclaration(); */
++/* void printarglist(); */
++
++#define DEFAULT_TIMEOUT 25 /* in seconds */
++static char RESULT[] = "clnt_res";
++
++static void write_program(definition *def);
++static void printbody(proc_list *proc);
++
++
++void
++write_stubs(void)
++{
++ list *l;
++ definition *def;
++
++ f_print(fout,
++ "\n/* Default timeout can be changed using clnt_control() */\n");
++ f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
++ DEFAULT_TIMEOUT);
++ for (l = defined; l != NULL; l = l->next) {
++ def = (definition *) l->val;
++ if (def->def_kind == DEF_PROGRAM) {
++ write_program(def);
++ }
++ }
++}
++
++static void
++write_program(definition *def)
++{
++ version_list *vp;
++ proc_list *proc;
++
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ for (proc = vp->procs; proc != NULL; proc = proc->next) {
++ f_print(fout, "\n");
++ ptype(proc->res_prefix, proc->res_type, 1);
++ f_print(fout, "*\n");
++ pvname(proc->proc_name, vp->vers_num);
++ printarglist(proc, "clnt", "CLIENT *");
++ f_print(fout, "{\n");
++ printbody(proc);
++ f_print(fout, "}\n");
++ }
++ }
++}
++
++/*
++ * Writes out declarations of procedure's argument list.
++ * In either ANSI C style, in one of old rpcgen style (pass by reference),
++ * or new rpcgen style (multiple arguments, pass by value);
++ */
++
++/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
++
++void
++printarglist(proc_list *proc, char *addargname, char *addargtype)
++{
++
++ decl_list *l;
++
++ if (!newstyle) { /* old style: always pass arg by reference */
++ if (Cflag) { /* C++ style heading */
++ f_print(fout, "(");
++ ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
++ f_print(fout, "*argp, %s%s)\n", addargtype, addargname);
++ } else {
++ f_print(fout, "(argp, %s)\n", addargname);
++ f_print(fout, "\t");
++ ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
++ f_print(fout, "*argp;\n");
++ }
++ } else if (streq(proc->args.decls->decl.type, "void")) {
++ /* newstyle, 0 argument */
++ if (Cflag)
++ f_print(fout, "(%s%s)\n", addargtype, addargname);
++ else
++ f_print(fout, "(%s)\n", addargname);
++ } else {
++ /* new style, 1 or multiple arguments */
++ if (!Cflag) {
++ f_print(fout, "(");
++ for (l = proc->args.decls; l != NULL; l = l->next)
++ f_print(fout, "%s, ", l->decl.name);
++ f_print(fout, "%s)\n", addargname);
++ for (l = proc->args.decls; l != NULL; l = l->next) {
++ pdeclaration(proc->args.argname, &l->decl, 1, ";\n");
++ }
++ } else { /* C++ style header */
++ f_print(fout, "(");
++ for (l = proc->args.decls; l != NULL; l = l->next) {
++ pdeclaration(proc->args.argname, &l->decl, 0, ", ");
++ }
++ f_print(fout, " %s%s)\n", addargtype, addargname);
++ }
++ }
++
++ if (!Cflag)
++ f_print(fout, "\t%s%s;\n", addargtype, addargname);
++}
++
++
++
++static char *
++ampr(char *type)
++{
++ if (isvectordef(type, REL_ALIAS)) {
++ return ("");
++ } else {
++ return ("&");
++ }
++}
++
++static void
++printbody(proc_list *proc)
++{
++ decl_list *l;
++ bool_t args2 = (proc->arg_num > 1);
++
++ /* For new style with multiple arguments, need a structure in which
++ * to stuff the arguments. */
++ if (newstyle && args2) {
++ f_print(fout, "\t%s", proc->args.argname);
++ f_print(fout, " arg;\n");
++ }
++ f_print(fout, "\tstatic ");
++ if (streq(proc->res_type, "void")) {
++ f_print(fout, "char ");
++ } else {
++ ptype(proc->res_prefix, proc->res_type, 0);
++ }
++ f_print(fout, "%s;\n", RESULT);
++ f_print(fout, "\n");
++ f_print(fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n",
++ ampr(proc->res_type), RESULT, RESULT);
++ if (newstyle && !args2 && (streq(proc->args.decls->decl.type, "void"))) {
++ /* newstyle, 0 arguments */
++ f_print(fout,
++ "\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_void, (caddr_t) NULL, "
++ "(xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n",
++ proc->proc_name,
++ stringfix(proc->res_type), ampr(proc->res_type), RESULT);
++
++ } else if (newstyle && args2) {
++ /* newstyle, multiple arguments: stuff arguments into structure */
++ for (l = proc->args.decls; l != NULL; l = l->next) {
++ f_print(fout, "\targ.%s = %s;\n",
++ l->decl.name, l->decl.name);
++ }
++ f_print(fout,
++ "\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_%s, (caddr_t) &arg, "
++ "(xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n",
++ proc->proc_name, proc->args.argname,
++ stringfix(proc->res_type), ampr(proc->res_type), RESULT);
++ } else { /* single argument, new or old style */
++ f_print(fout,
++ "\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_%s, "
++ "(caddr_t) %s%s, (xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n",
++ proc->proc_name,
++ stringfix(proc->args.decls->decl.type),
++ (newstyle ? "&" : ""),
++ (newstyle ? proc->args.decls->decl.name : "argp"),
++ stringfix(proc->res_type), ampr(proc->res_type), RESULT);
++ }
++ f_print(fout, "\t\treturn (NULL);\n");
++ f_print(fout, "\t}\n");
++ if (streq(proc->res_type, "void")) {
++ f_print(fout, "\treturn ((void *)%s%s);\n",
++ ampr(proc->res_type), RESULT);
++ } else {
++ f_print(fout, "\treturn (%s%s);\n", ampr(proc->res_type), RESULT);
++ }
++}
+diff --git a/rpcgen/rpc_cout.c b/rpcgen/rpc_cout.c
+new file mode 100644
+index 0000000..a61214f
+--- /dev/null
++++ b/rpcgen/rpc_cout.c
+@@ -0,0 +1,706 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI";
++#endif
++
++/*
++ * rpc_cout.c, XDR routine outputter for the RPC protocol compiler
++ */
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <malloc.h>
++#include <ctype.h>
++#include "rpc_parse.h"
++#include "rpc_util.h"
++
++static int findtype(definition *def, char *type);
++static int undefined(char *type);
++static void print_generic_header(char *procname, int pointerp);
++static void print_header(definition *def);
++static void print_prog_header(proc_list *plist);
++static void print_trailer(void);
++static void print_ifopen(int indent, char *name);
++static void print_ifarg(char *arg);
++static void print_ifsizeof(char *prefix, char *type);
++static void print_ifclose(int indent);
++static void print_ifstat(int indent, char *prefix, char *type, relation rel,
++ char *amax, char *objname, char *name);
++static void emit_enum(definition *def);
++static void emit_program(definition *def);
++static void emit_union(definition *def);
++static void emit_struct(definition *def);
++static void emit_typedef(definition *def);
++static void print_stat(int indent, declaration *dec);
++static void emit_inline(declaration *decl, int flag);
++static void emit_single_in_line(declaration *decl, int flag, relation rel);
++static char * upcase(char *str);
++
++/*
++ * Emit the C-routine for the given definition
++ */
++void
++emit(definition *def)
++{
++ if (def->def_kind == DEF_CONST) {
++ return;
++ }
++ if (def->def_kind == DEF_PROGRAM) {
++ emit_program(def);
++ return;
++ }
++ if (def->def_kind == DEF_TYPEDEF) {
++ /* now we need to handle declarations like
++ * struct typedef foo foo;
++ * since we dont want this to be expanded into 2 calls
++ * to xdr_foo */
++
++ if (strcmp(def->def.ty.old_type, def->def_name) == 0)
++ return;
++ };
++
++ print_header(def);
++ switch (def->def_kind) {
++ case DEF_UNION:
++ emit_union(def);
++ break;
++ case DEF_ENUM:
++ emit_enum(def);
++ break;
++ case DEF_STRUCT:
++ emit_struct(def);
++ break;
++ case DEF_TYPEDEF:
++ emit_typedef(def);
++ break;
++ default:
++ break;
++ }
++ print_trailer();
++}
++
++static int
++findtype(definition *def, char *type)
++{
++
++ if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) {
++ return (0);
++ } else {
++ return (streq(def->def_name, type));
++ }
++}
++
++static int
++undefined(char *type)
++{
++ definition *def;
++
++ def = (definition *) FINDVAL(defined, type, findtype);
++
++ return (def == NULL);
++}
++
++
++static void
++print_generic_header(char *procname, int pointerp)
++{
++ f_print(fout, "\n");
++ f_print(fout, "bool_t\n");
++ if (Cflag) {
++ f_print(fout, "xdr_%s(", procname);
++ f_print(fout, "XDR *xdrs, ");
++ f_print(fout, "%s ", procname);
++ if (pointerp)
++ f_print(fout, "*");
++ f_print(fout, "objp)\n{\n\n");
++ } else {
++ f_print(fout, "xdr_%s(xdrs, objp)\n", procname);
++ f_print(fout, "\tXDR *xdrs;\n");
++ f_print(fout, "\t%s ", procname);
++ if (pointerp)
++ f_print(fout, "*");
++ f_print(fout, "objp;\n{\n\n");
++ }
++}
++
++static void
++print_header(definition *def)
++{
++ print_generic_header(def->def_name,
++ def->def_kind != DEF_TYPEDEF ||
++ !isvectordef(def->def.ty.old_type, def->def.ty.rel));
++
++ /* Now add Inline support */
++
++
++ if (Inline == 0)
++ return;
++}
++
++static void
++print_prog_header(proc_list *plist)
++{
++ print_generic_header(plist->args.argname, 1);
++}
++
++static void
++print_trailer(void)
++{
++ f_print(fout, "\treturn (TRUE);\n");
++ f_print(fout, "}\n");
++}
++
++
++static void
++print_ifopen(int indent, char *name)
++{
++ tabify(fout, indent);
++ f_print(fout, " if (!xdr_%s(xdrs", name);
++}
++
++static void
++print_ifarg(char *arg)
++{
++ f_print(fout, ", %s", arg);
++}
++
++static void
++print_ifsizeof(char *prefix, char *type)
++{
++ if (streq(type, "bool")) {
++ f_print(fout, ", sizeof(bool_t), (xdrproc_t)xdr_bool");
++ } else {
++ f_print(fout, ", sizeof(");
++ if (undefined(type) && prefix) {
++ f_print(fout, "%s ", prefix);
++ }
++ f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type);
++ }
++}
++
++static void
++print_ifclose(int indent)
++{
++ f_print(fout, ")) {\n");
++ tabify(fout, indent);
++ f_print(fout, "\t return (FALSE);\n");
++ tabify(fout, indent);
++ f_print(fout, " }\n");
++}
++
++static void
++print_ifstat(int indent, char *prefix, char *type, relation rel,
++ char *amax, char *objname, char *name)
++{
++ char *alt = NULL;
++
++ switch (rel) {
++ case REL_POINTER:
++ print_ifopen(indent, "pointer");
++ print_ifarg("(char **)");
++ f_print(fout, "%s", objname);
++ print_ifsizeof(prefix, type);
++ break;
++ case REL_VECTOR:
++ if (streq(type, "string")) {
++ alt = "string";
++ } else if (streq(type, "opaque")) {
++ alt = "opaque";
++ }
++ if (alt) {
++ print_ifopen(indent, alt);
++ print_ifarg(objname);
++ } else {
++ print_ifopen(indent, "vector");
++ print_ifarg("(char *)");
++ f_print(fout, "%s", objname);
++ }
++ print_ifarg(amax);
++ if (!alt) {
++ print_ifsizeof(prefix, type);
++ }
++ break;
++ case REL_ARRAY:
++ if (streq(type, "string")) {
++ alt = "string";
++ } else if (streq(type, "opaque")) {
++ alt = "bytes";
++ }
++ if (streq(type, "string")) {
++ print_ifopen(indent, alt);
++ print_ifarg(objname);
++ } else {
++ if (alt) {
++ print_ifopen(indent, alt);
++ } else {
++ print_ifopen(indent, "array");
++ }
++ /* The (void*) avoids a gcc-4.1 warning */
++ print_ifarg("(char **)(void*)");
++ if (*objname == '&') {
++ f_print(fout, "%s.%s_val, (u_int *)%s.%s_len",
++ objname, name, objname, name);
++ } else {
++ f_print(fout, "&%s->%s_val, (u_int *)&%s->%s_len",
++ objname, name, objname, name);
++ }
++ }
++ print_ifarg(amax);
++ if (!alt) {
++ print_ifsizeof(prefix, type);
++ }
++ break;
++ case REL_ALIAS:
++ print_ifopen(indent, type);
++ print_ifarg(objname);
++ break;
++ }
++ print_ifclose(indent);
++}
++
++static void
++emit_enum(definition *def)
++{
++ print_ifopen(1, "enum");
++ print_ifarg("(enum_t *)objp");
++ print_ifclose(1);
++}
++
++static void
++emit_program(definition *def)
++{
++ decl_list *dl;
++ version_list *vlist;
++ proc_list *plist;
++
++ for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next)
++ for (plist = vlist->procs; plist != NULL; plist = plist->next) {
++ if (!newstyle || plist->arg_num < 2)
++ continue;/* old style, or single argument */
++ print_prog_header(plist);
++ for (dl = plist->args.decls; dl != NULL; dl = dl->next)
++ print_stat(1, &dl->decl);
++ print_trailer();
++ }
++}
++
++
++static void
++emit_union(definition *def)
++{
++ declaration *dflt;
++ case_list *cl;
++ declaration *cs;
++ char *object;
++ char *vecformat = "objp->%s_u.%s";
++ char *format = "&objp->%s_u.%s";
++
++ print_stat(1,&def->def.un.enum_decl);
++ f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name);
++ for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
++
++ f_print(fout, "\tcase %s:\n", cl->case_name);
++ if(cl->contflag == 1) /* a continued case statement */
++ continue;
++ cs = &cl->case_decl;
++ if (!streq(cs->type, "void")) {
++ object = alloc(strlen(def->def_name) + strlen(format) +
++ strlen(cs->name) + 1);
++ if (isvectordef (cs->type, cs->rel)) {
++ s_print(object, vecformat, def->def_name,
++ cs->name);
++ } else {
++ s_print(object, format, def->def_name,
++ cs->name);
++ }
++ print_ifstat(2, cs->prefix, cs->type, cs->rel, cs->array_max,
++ object, cs->name);
++ free(object);
++ }
++ f_print(fout, "\t\tbreak;\n");
++ }
++ dflt = def->def.un.default_decl;
++ if (dflt != NULL) {
++ if (!streq(dflt->type, "void")) {
++ f_print(fout, "\tdefault:\n");
++ object = alloc(strlen(def->def_name) + strlen(format) +
++ strlen(dflt->name) + 1);
++ if (isvectordef (dflt->type, dflt->rel)) {
++ s_print(object, vecformat, def->def_name,
++ dflt->name);
++ } else {
++ s_print(object, format, def->def_name,
++ dflt->name);
++ }
++
++ print_ifstat(2, dflt->prefix, dflt->type, dflt->rel,
++ dflt->array_max, object, dflt->name);
++ free(object);
++ f_print(fout, "\t\tbreak;\n");
++ } else {
++ /* Avoid gcc warnings about `value not handled in switch' */
++ f_print(fout, "\tdefault:\n");
++ f_print(fout, "\t\tbreak;\n");
++ }
++ } else {
++ f_print(fout, "\tdefault:\n");
++ f_print(fout, "\t\treturn (FALSE);\n");
++ }
++
++ f_print(fout, "\t}\n");
++}
++
++static void
++emit_struct(definition *def)
++{
++ decl_list *dl;
++ int i, j, size, flag;
++ decl_list *cur = NULL, *psav;
++ bas_type *ptr;
++ char *sizestr, *plus;
++ char ptemp[256];
++ int can_inline;
++ const char *buf_declaration;
++
++
++ if (Inline == 0) {
++ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
++ print_stat(1, &dl->decl);
++ } else {
++ size = 0;
++ can_inline = 0;
++ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
++ if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) {
++
++ if (dl->decl.rel == REL_ALIAS)
++ size += ptr->length;
++ else {
++ can_inline = 1;
++ break; /* can be inlined */
++ };
++ } else {
++ if (size >= Inline) {
++ can_inline = 1;
++ break; /* can be inlined */
++ }
++ size = 0;
++ }
++ if (size > Inline)
++ can_inline = 1;
++
++ if (can_inline == 0) { /* can not inline, drop back to old mode */
++ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
++ print_stat(1, &dl->decl);
++ return;
++ };
++
++
++
++
++ flag = PUT;
++ for (j = 0; j < 2; j++) {
++
++ if (flag == PUT)
++ f_print(fout, "\n\t if (xdrs->x_op == XDR_ENCODE) {\n");
++ else
++ f_print(fout, "\n \t return (TRUE);\n\t} else if (xdrs->x_op == XDR_DECODE) {\n");
++
++
++ i = 0;
++ size = 0;
++ sizestr = NULL;
++ buf_declaration = "int32_t *";
++ for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { /* xxx */
++
++ /* now walk down the list and check for basic types */
++ if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) {
++ if (i == 0)
++ cur = dl;
++ i++;
++
++ if (dl->decl.rel == REL_ALIAS)
++ size += ptr->length;
++ else {
++ /* this is required to handle arrays */
++
++ if (sizestr == NULL)
++ plus = " ";
++ else
++ plus = "+";
++
++ if (ptr->length != 1)
++ s_print(ptemp, " %s %s * %d", plus, dl->decl.array_max, ptr->length);
++ else
++ s_print(ptemp, " %s %s ", plus, dl->decl.array_max);
++
++ /*now concatenate to sizestr !!!! */
++ if (sizestr == NULL)
++ sizestr = strdup(ptemp);
++ else {
++ sizestr = realloc(sizestr, strlen(sizestr) + strlen(ptemp) + 1);
++ if (sizestr == NULL) {
++
++ f_print(stderr, "Fatal error : no memory \n");
++ crash();
++ };
++ sizestr = strcat(sizestr, ptemp); /*build up length of array */
++
++ }
++ }
++
++ } else {
++ if (i > 0)
++ {
++ if (sizestr == NULL && size < Inline) {
++ /* don't expand into inline code if size < inline */
++ while (cur != dl) {
++ print_stat(1, &cur->decl);
++ cur = cur->next;
++ }
++ } else {
++
++
++
++ /* were already looking at a xdr_inlineable structure */
++ if (sizestr == NULL)
++ f_print(fout, "\t %sbuf = XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);",
++ buf_declaration, size);
++ else if (size == 0)
++ f_print(fout,
++ "\t %sbuf = XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);",
++ buf_declaration, sizestr);
++ else
++ f_print(fout,
++ "\t %sbuf = XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);",
++ buf_declaration, size, sizestr);
++ buf_declaration = "";
++
++ f_print(fout, "\n\t if (buf == NULL) {\n");
++
++ psav = cur;
++ while (cur != dl) {
++ print_stat(2, &cur->decl);
++ cur = cur->next;
++ }
++
++ f_print(fout, "\n\t }\n\t else {\n");
++
++ cur = psav;
++ while (cur != dl) {
++ emit_inline(&cur->decl, flag);
++ cur = cur->next;
++ }
++
++ f_print(fout, "\t }\n");
++ }
++ }
++ size = 0;
++ i = 0;
++ sizestr = NULL;
++ print_stat(1, &dl->decl);
++ }
++
++ }
++ if (i > 0)
++ {
++ if (sizestr == NULL && size < Inline) {
++ /* don't expand into inline code if size < inline */
++ while (cur != dl) {
++ print_stat(1, &cur->decl);
++ cur = cur->next;
++ }
++ } else {
++
++ /* were already looking at a xdr_inlineable structure */
++ if (sizestr == NULL)
++ f_print(fout, "\t\t%sbuf = XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);",
++ buf_declaration, size);
++ else if (size == 0)
++ f_print(fout,
++ "\t\t%sbuf = XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);",
++ buf_declaration, sizestr);
++ else
++ f_print(fout,
++ "\t\t%sbuf = XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);",
++ buf_declaration, size, sizestr);
++ buf_declaration = "";
++
++ f_print(fout, "\n\t\tif (buf == NULL) {\n");
++
++ psav = cur;
++ while (cur != NULL) {
++ print_stat(2, &cur->decl);
++ cur = cur->next;
++ }
++ f_print(fout, "\n\t }\n\t else {\n");
++
++ cur = psav;
++ while (cur != dl) {
++ emit_inline(&cur->decl, flag);
++ cur = cur->next;
++ }
++
++ f_print(fout, "\t }\n");
++
++ }
++ }
++ flag = GET;
++ }
++ f_print(fout, "\t return(TRUE);\n\t}\n\n");
++
++ /* now take care of XDR_FREE case */
++
++ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
++ print_stat(1, &dl->decl);
++ }
++}
++
++
++
++
++static void
++emit_typedef(definition *def)
++{
++ char *prefix = def->def.ty.old_prefix;
++ char *type = def->def.ty.old_type;
++ char *amax = def->def.ty.array_max;
++ relation rel = def->def.ty.rel;
++
++
++ print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
++}
++
++static void
++print_stat(int indent, declaration *dec)
++{
++ char *prefix = dec->prefix;
++ char *type = dec->type;
++ char *amax = dec->array_max;
++ relation rel = dec->rel;
++ char name[256];
++
++ if (isvectordef(type, rel)) {
++ s_print(name, "objp->%s", dec->name);
++ } else {
++ s_print(name, "&objp->%s", dec->name);
++ }
++ print_ifstat(indent, prefix, type, rel, amax, name, dec->name);
++}
++
++
++static void
++emit_inline(declaration *decl, int flag)
++{
++
++ /*check whether an array or not */
++
++ switch (decl->rel) {
++ case REL_ALIAS:
++ emit_single_in_line(decl, flag, REL_ALIAS);
++ break;
++ case REL_VECTOR:
++ f_print(fout, "\t\t{ register %s *genp; \n", decl->type);
++ f_print(fout, "\t\t int i;\n");
++ f_print(fout, "\t\t for ( i = 0,genp=objp->%s;\n \t\t\ti < %s; i++){\n\t\t",
++ decl->name, decl->array_max);
++ emit_single_in_line(decl, flag, REL_VECTOR);
++ f_print(fout, "\t\t }\n\t\t };\n");
++ break;
++ default:
++ break;
++ }
++}
++
++static void
++emit_single_in_line(declaration *decl, int flag, relation rel)
++{
++ char *upp_case;
++ int freed=0;
++
++ if(flag == PUT)
++ f_print(fout,"\t\t (void) IXDR_PUT_");
++ else
++ if(rel== REL_ALIAS)
++ f_print(fout,"\t\t objp->%s = IXDR_GET_",decl->name);
++ else
++ f_print(fout,"\t\t *genp++ = IXDR_GET_");
++
++ upp_case=upcase(decl->type);
++
++ /* hack - XX */
++ if(strcmp(upp_case,"INT") == 0)
++ {
++ free(upp_case);
++ freed=1;
++ upp_case="INT32";
++ }
++
++ if(strcmp(upp_case,"U_INT") == 0)
++ {
++ free(upp_case);
++ freed=1;
++ upp_case="U_INT32";
++ }
++
++
++ if(flag == PUT)
++ if(rel== REL_ALIAS)
++ f_print(fout,"%s(buf,objp->%s);\n",upp_case,decl->name);
++ else
++ f_print(fout,"%s(buf,*genp++);\n",upp_case);
++
++ else
++ f_print(fout,"%s(buf);\n",upp_case);
++ if(!freed)
++ free(upp_case);
++
++}
++
++
++static char *
++upcase(char *str)
++{
++ char *ptr, *hptr;
++
++
++ ptr = (char *) malloc(strlen(str)+1);
++ if (ptr == (char *) NULL) {
++ f_print(stderr, "malloc failed \n");
++ exit(1);
++ };
++
++ hptr = ptr;
++ while (*str != '\0')
++ *ptr++ = toupper(*str++);
++
++ *ptr = '\0';
++ return (hptr);
++
++}
+diff --git a/rpcgen/rpc_hout.c b/rpcgen/rpc_hout.c
+new file mode 100644
+index 0000000..ea1cb24
+--- /dev/null
++++ b/rpcgen/rpc_hout.c
+@@ -0,0 +1,490 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++static char sccsid[] = "@(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI";
++#endif
++
++/*
++ * rpc_hout.c, Header file outputter for the RPC protocol compiler
++ */
++#include <stdio.h>
++#include <ctype.h>
++#include "rpc_parse.h"
++#include "rpc_util.h"
++#include "rpc_output.h"
++
++
++static int undefined2(char *type, char *stop);
++static void pxdrfuncdecl(char *name, int pointerp);
++static void pconstdef(definition *def);
++static void pargdef(definition *def);
++static void pstructdef(definition *def);
++static void puniondef(definition *def);
++static void pdefine(char *name, char *num);
++static void puldefine(char *name, char *num);
++static int define_printed(proc_list *stop, version_list *start);
++static void pprogramdef(definition *def);
++static void pprocdef(proc_list *proc, version_list *vp,
++ char *addargtype, int server_p, int mode);
++static void parglist(proc_list *proc, char *addargtype);
++static void penumdef(definition *def);
++static void ptypedef(definition *def);
++
++/*
++ * Print the C-version of an xdr definition
++ */
++void
++print_datadef(definition *def)
++{
++
++ if (def->def_kind == DEF_PROGRAM ) /* handle data only */
++ return;
++
++ if (def->def_kind != DEF_CONST) {
++ f_print(fout, "\n");
++ }
++ switch (def->def_kind) {
++ case DEF_STRUCT:
++ pstructdef(def);
++ break;
++ case DEF_UNION:
++ puniondef(def);
++ break;
++ case DEF_ENUM:
++ penumdef(def);
++ break;
++ case DEF_TYPEDEF:
++ ptypedef(def);
++ break;
++ case DEF_PROGRAM:
++ pprogramdef(def);
++ break;
++ case DEF_CONST:
++ pconstdef(def);
++ break;
++ }
++ if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) {
++ pxdrfuncdecl( def->def_name,
++ def->def_kind != DEF_TYPEDEF ||
++ !isvectordef(def->def.ty.old_type, def->def.ty.rel));
++
++ }
++}
++
++
++void
++print_funcdef(definition *def)
++{
++ switch (def->def_kind) {
++ case DEF_PROGRAM:
++ f_print(fout, "\n");
++ pprogramdef(def);
++ break;
++ default:
++ break;
++ }
++}
++
++static void
++pxdrfuncdecl(char *name, int pointerp)
++{
++ f_print(fout,
++ "#ifdef __cplusplus \n"
++ "extern \"C\" bool_t xdr_%s(XDR *, %s%s);\n"
++ "#elif __STDC__ \n"
++ "extern bool_t xdr_%s(XDR *, %s%s);\n"
++ "#else /* Old Style C */ \n"
++ "bool_t xdr_%s();\n"
++ "#endif /* Old Style C */ \n\n",
++ name, name, pointerp ? "*" : "",
++ name, name, pointerp ? "*" : "",
++ name);
++}
++
++
++static void
++pconstdef(definition *def)
++{
++ pdefine(def->def_name, def->def.co);
++}
++
++/* print out the definitions for the arguments of functions in the
++ header file
++*/
++static void
++pargdef(definition *def)
++{
++ decl_list *l;
++ version_list *vers;
++ char *name;
++ proc_list *plist;
++
++
++ for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
++ for(plist = vers->procs; plist != NULL;
++ plist = plist->next) {
++
++ if (!newstyle || plist->arg_num < 2) {
++ continue; /* old style or single args */
++ }
++ name = plist->args.argname;
++ f_print(fout, "struct %s {\n", name);
++ for (l = plist->args.decls;
++ l != NULL; l = l->next) {
++ pdeclaration(name, &l->decl, 1, ";\n" );
++ }
++ f_print(fout, "};\n");
++ f_print(fout, "typedef struct %s %s;\n", name, name);
++ pxdrfuncdecl(name, 0);
++ f_print( fout, "\n" );
++ }
++ }
++
++}
++
++
++static void
++pstructdef(definition *def)
++{
++ decl_list *l;
++ char *name = def->def_name;
++
++ f_print(fout, "struct %s {\n", name);
++ for (l = def->def.st.decls; l != NULL; l = l->next) {
++ pdeclaration(name, &l->decl, 1, ";\n");
++ }
++ f_print(fout, "};\n");
++ f_print(fout, "typedef struct %s %s;\n", name, name);
++}
++
++static void
++puniondef(definition *def)
++{
++ case_list *l;
++ char *name = def->def_name;
++ declaration *decl;
++
++ f_print(fout, "struct %s {\n", name);
++ decl = &def->def.un.enum_decl;
++ if (streq(decl->type, "bool")) {
++ f_print(fout, "\tbool_t %s;\n", decl->name);
++ } else {
++ f_print(fout, "\t%s %s;\n", decl->type, decl->name);
++ }
++ f_print(fout, "\tunion {\n");
++ for (l = def->def.un.cases; l != NULL; l = l->next) {
++ if (l->contflag == 0)
++ pdeclaration(name, &l->case_decl, 2, ";\n");
++ }
++ decl = def->def.un.default_decl;
++ if (decl && !streq(decl->type, "void")) {
++ pdeclaration(name, decl, 2, ";\n");
++ }
++ f_print(fout, "\t} %s_u;\n", name);
++ f_print(fout, "};\n");
++ f_print(fout, "typedef struct %s %s;\n", name, name);
++}
++
++static void
++pdefine(char *name, char *num)
++{
++ f_print(fout, "#define %s %s\n", name, num);
++}
++
++static void
++puldefine(char *name, char *num)
++{
++ f_print(fout, "#define %s ((u_int32_t)%s)\n", name, num);
++}
++
++static int
++define_printed(proc_list *stop, version_list *start)
++{
++ version_list *vers;
++ proc_list *proc;
++
++ for (vers = start; vers != NULL; vers = vers->next) {
++ for (proc = vers->procs; proc != NULL; proc = proc->next) {
++ if (proc == stop) {
++ return (0);
++ } else if (streq(proc->proc_name, stop->proc_name)) {
++ return (1);
++ }
++ }
++ }
++ abort();
++ /* NOTREACHED */
++}
++
++static void
++pprogramdef(definition *def)
++{
++ version_list *vers;
++ proc_list *proc;
++ int i;
++ char *ext;
++
++ pargdef(def);
++
++ puldefine(def->def_name, def->def.pr.prog_num);
++ for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
++ if (tblflag) {
++ f_print(fout, "extern struct rpcgen_table %s_%s_table[];\n",
++ locase(def->def_name), vers->vers_num);
++ f_print(fout, "extern %s_%s_nproc;\n",
++ locase(def->def_name), vers->vers_num);
++ }
++ puldefine(vers->vers_name, vers->vers_num);
++
++ /*
++ * Print out 3 definitions, one for ANSI-C, another for C++,
++ * a third for old style C
++ */
++
++ for (i = 0; i < 3; i++) {
++ if (i == 0) {
++ f_print(fout, "\n#ifdef __cplusplus\n");
++ ext = "extern \"C\" ";
++ } else if (i == 1) {
++ f_print(fout, "\n#elif __STDC__\n");
++ ext = "extern ";
++ } else {
++ f_print(fout, "\n#else /* Old Style C */ \n");
++ ext = "extern ";
++ }
++
++
++ for (proc = vers->procs; proc != NULL; proc = proc->next) {
++ if (!define_printed(proc, def->def.pr.versions)) {
++ puldefine(proc->proc_name, proc->proc_num);
++ }
++ f_print(fout, "%s", ext);
++ pprocdef(proc, vers, "CLIENT *", 0, i);
++ f_print(fout, "%s", ext);
++ pprocdef(proc, vers, "struct svc_req *", 1, i);
++
++ }
++
++ }
++ f_print(fout, "#endif /* Old Style C */ \n");
++ }
++}
++
++static void
++pprocdef(proc_list *proc, version_list *vp, char *addargtype,
++ int server_p, int mode)
++{
++ ptype(proc->res_prefix, proc->res_type, 1);
++ f_print(fout, "* ");
++ if (server_p)
++ pvname_svc(proc->proc_name, vp->vers_num);
++ else
++ pvname(proc->proc_name, vp->vers_num);
++
++ /*
++ * mode 0 == cplusplus, mode 1 = ANSI-C, mode 2 = old style C
++ */
++ if (mode == 0 || mode == 1)
++ parglist(proc, addargtype);
++ else
++ f_print(fout, "();\n");
++}
++
++
++
++/* print out argument list of procedure */
++static void
++parglist(proc_list *proc, char *addargtype)
++{
++ decl_list *dl;
++
++ f_print(fout, "(");
++
++ if (proc->arg_num < 2 && newstyle &&
++ streq(proc->args.decls->decl.type, "void")) {
++ /* 0 argument in new style: do nothing */
++ } else {
++ for (dl = proc->args.decls; dl != NULL; dl = dl->next) {
++ ptype(dl->decl.prefix, dl->decl.type, 1);
++ if (!newstyle)
++ f_print(fout, "*"); /* old style passes by reference */
++
++ f_print(fout, ", ");
++ }
++ }
++
++ f_print(fout, "%s);\n", addargtype);
++}
++
++static void
++penumdef(definition *def)
++{
++ char *name = def->def_name;
++ enumval_list *l;
++ char *last = NULL;
++ int count = 0;
++
++ f_print(fout, "enum %s {\n", name);
++ for (l = def->def.en.vals; l != NULL; l = l->next) {
++ f_print(fout, "\t%s", l->name);
++ if (l->assignment) {
++ f_print(fout, " = %s", l->assignment);
++ last = l->assignment;
++ count = 1;
++ } else {
++ if (last == NULL) {
++ f_print(fout, " = %d", count++);
++ } else {
++ f_print(fout, " = %s + %d", last, count++);
++ }
++ }
++ f_print(fout, ",\n");
++ }
++ f_print(fout, "};\n");
++ f_print(fout, "typedef enum %s %s;\n", name, name);
++}
++
++static void
++ptypedef(definition *def)
++{
++ char *name = def->def_name;
++ char *old = def->def.ty.old_type;
++ char prefix[8]; /* enough to contain "struct ", including NUL */
++ relation rel = def->def.ty.rel;
++
++
++ if (!streq(name, old)) {
++ if (streq(old, "string")) {
++ old = "char";
++ rel = REL_POINTER;
++ } else if (streq(old, "opaque")) {
++ old = "char";
++ } else if (streq(old, "bool")) {
++ old = "bool_t";
++ }
++ if (undefined2(old, name) && def->def.ty.old_prefix) {
++ s_print(prefix, "%s ", def->def.ty.old_prefix);
++ } else {
++ prefix[0] = 0;
++ }
++ f_print(fout, "typedef ");
++ switch (rel) {
++ case REL_ARRAY:
++ f_print(fout, "struct {\n");
++ f_print(fout, "\tu_int %s_len;\n", name);
++ f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name);
++ f_print(fout, "} %s", name);
++ break;
++ case REL_POINTER:
++ f_print(fout, "%s%s *%s", prefix, old, name);
++ break;
++ case REL_VECTOR:
++ f_print(fout, "%s%s %s[%s]", prefix, old, name,
++ def->def.ty.array_max);
++ break;
++ case REL_ALIAS:
++ f_print(fout, "%s%s %s", prefix, old, name);
++ break;
++ }
++ f_print(fout, ";\n");
++ }
++}
++
++void
++pdeclaration(char *name, declaration *dec, int tab, char *separator)
++{
++ char buf[8]; /* enough to hold "struct ", include NUL */
++ char *prefix;
++ char *type;
++
++ if (streq(dec->type, "void")) {
++ return;
++ }
++ tabify(fout, tab);
++ if (streq(dec->type, name) && !dec->prefix) {
++ f_print(fout, "struct ");
++ }
++ if (streq(dec->type, "string")) {
++ f_print(fout, "char *%s", dec->name);
++ } else {
++ prefix = "";
++ if (streq(dec->type, "bool")) {
++ type = "bool_t";
++ } else if (streq(dec->type, "opaque")) {
++ type = "char";
++ } else {
++ if (dec->prefix) {
++ s_print(buf, "%s ", dec->prefix);
++ prefix = buf;
++ }
++ type = dec->type;
++ }
++ switch (dec->rel) {
++ case REL_ALIAS:
++ f_print(fout, "%s%s %s", prefix, type, dec->name);
++ break;
++ case REL_VECTOR:
++ f_print(fout, "%s%s %s[%s]", prefix, type, dec->name,
++ dec->array_max);
++ break;
++ case REL_POINTER:
++ f_print(fout, "%s%s *%s", prefix, type, dec->name);
++ break;
++ case REL_ARRAY:
++ f_print(fout, "struct {\n");
++ tabify(fout, tab);
++ f_print(fout, "\tu_int %s_len;\n", dec->name);
++ tabify(fout, tab);
++ f_print(fout, "\t%s%s *%s_val;\n", prefix, type, dec->name);
++ tabify(fout, tab);
++ f_print(fout, "} %s", dec->name);
++ break;
++ }
++ }
++ f_print(fout, separator );
++}
++
++static int
++undefined2(char *type, char *stop)
++{
++ list *l;
++ definition *def;
++
++ for (l = defined; l != NULL; l = l->next) {
++ def = (definition *) l->val;
++ if (def->def_kind != DEF_PROGRAM) {
++ if (streq(def->def_name, stop)) {
++ return (1);
++ } else if (streq(def->def_name, type)) {
++ return (0);
++ }
++ }
++ }
++ return (1);
++}
+diff --git a/rpcgen/rpc_main.c b/rpcgen/rpc_main.c
+new file mode 100644
+index 0000000..28aa60c
+--- /dev/null
++++ b/rpcgen/rpc_main.c
+@@ -0,0 +1,1067 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI";
++#endif
++
++/*
++ * rpc_main.c, Top level of the RPC protocol compiler.
++ */
++
++#include <sys/types.h>
++#include <sys/param.h>
++#include <sys/file.h>
++#include <sys/stat.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <ctype.h>
++#include <errno.h>
++#include "rpc_parse.h"
++#include "rpc_util.h"
++#include "rpc_scan.h"
++
++struct commandline {
++ int cflag; /* xdr C routines */
++ int hflag; /* header file */
++ int lflag; /* client side stubs */
++ int mflag; /* server side stubs */
++ int nflag; /* netid flag */
++ int sflag; /* server stubs for the given transport */
++ int tflag; /* dispatch Table file */
++ int Ssflag; /* produce server sample code */
++ int Scflag; /* produce client sample code */
++ char *infile; /* input module name */
++ char *outfile; /* output module name */
++};
++
++static char * extendfile(char *file, char *ext);
++static void open_output(char *infile, char *outfile);
++static void add_warning(void);
++static void clear_args(void);
++static void open_input(char *infile, char *define);
++static int check_nettype(char *name, char **list_to_check);
++static void c_output(char *infile, char *define, int extend, char *outfile);
++static void c_initialize(void);
++static char * generate_guard(char *pathname);
++static void h_output(char *infile, char *define, int extend, char *outfile);
++static void s_output(int argc, char **argv, char *infile,
++ char *define, int extend, char *outfile,
++ int nomain, int netflag);
++static void l_output(char *infile, char *define, int extend, char *outfile);
++static void t_output(char *infile, char *define, int extend, char *outfile);
++static void svc_output(char *, char *, int, char *);
++static void clnt_output(char *, char *, int, char *);
++static int do_registers(int argc, char **argv);
++static void addarg(char *cp);
++static void putarg(int where, char *cp);
++static void checkfiles(char *infile, char *outfile);
++static int parseargs(int argc, char **argv, struct commandline *cmd);
++static void usage(void);
++static void options_usage(void);
++
++/*
++extern void write_sample_svc();
++int write_sample_clnt();
++void write_sample_clnt_main();
++
++static svc_output();
++ */
++
++#define EXTEND 1 /* alias for TRUE */
++#define DONT_EXTEND 0 /* alias for FALSE */
++
++#define SVR4_CPP "/usr/ccs/lib/cpp"
++#define SUNOS_CPP "/lib/cpp"
++static int cppDefined = 0; /* explicit path for C preprocessor */
++
++
++static char *cmdname;
++
++static char *svcclosetime = "120";
++static char *CPP = SVR4_CPP;
++static char CPPFLAGS[] = "-C";
++static char pathbuf[MAXPATHLEN + 1];
++static char *allv[] = {
++ "rpcgen", "-s", "udp", "-s", "tcp",
++};
++static int allc = sizeof(allv)/sizeof(allv[0]);
++static char *allnv[] = {
++ "rpcgen", "-s", "netpath",
++};
++static int allnc = sizeof(allnv)/sizeof(allnv[0]);
++
++/*
++ * machinations for handling expanding argument list
++ */
++#if 0
++static void addarg(); /* add another argument to the list */
++static void putarg(); /* put argument at specified location */
++static void clear_args(); /* clear argument list */
++static void checkfiles(); /* check if out file already exists */
++#endif
++
++
++
++#define ARGLISTLEN 20
++#define FIXEDARGS 2
++
++static char *arglist[ARGLISTLEN];
++static int argcount = FIXEDARGS;
++
++
++int nonfatalerrors; /* errors */
++int inetdflag/* = 1*/; /* Support for inetd */ /* is now the default */
++int pmflag; /* Support for port monitors */
++int logflag; /* Use syslog instead of fprintf for errors */
++int tblflag; /* Support for dispatch table file */
++
++/* length at which to start doing an inline */
++#define INLINE 3
++
++int Inline = INLINE; /* length at which to start doing an inline. 3 = default
++ * if 0, no xdr_inline code */
++
++int indefinitewait; /* If started by port monitors, hang till it wants */
++int exitnow; /* If started by port monitors, exit after the call */
++int timerflag; /* TRUE if !indefinite && !exitnow */
++int newstyle; /* newstyle of passing arguments (by value) */
++int Cflag = 0 ; /* ANSI C syntax */
++static int allfiles; /* generate all files */
++#ifdef linux
++int tirpcflag = 0; /* no tirpc by default */
++#else
++int tirpcflag = 1; /* generating code for tirpc, by default */
++#endif
++
++int
++main(int argc, char **argv)
++{
++ struct commandline cmd;
++
++ (void) memset((char *) &cmd, 0, sizeof(struct commandline));
++ clear_args();
++ if (!parseargs(argc, argv, &cmd))
++ usage();
++
++ if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag ||
++ cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) {
++ checkfiles(cmd.infile, cmd.outfile);
++ } else
++ checkfiles(cmd.infile, NULL);
++
++ if (cmd.cflag) {
++ c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile);
++ } else if (cmd.hflag) {
++ h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile);
++ } else if (cmd.lflag) {
++ l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile);
++ } else if (cmd.sflag || cmd.mflag || (cmd.nflag)) {
++ s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND,
++ cmd.outfile, cmd.mflag, cmd.nflag);
++ } else if (cmd.tflag) {
++ t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile);
++ } else if (cmd.Ssflag) {
++ svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile);
++ } else if (cmd.Scflag) {
++ clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile);
++ } else {
++ /* the rescans are required, since cpp may effect input */
++ c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c");
++ reinitialize();
++ h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h");
++ reinitialize();
++ l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c");
++ reinitialize();
++ if (inetdflag || !tirpcflag)
++ s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND,
++ "_svc.c", cmd.mflag, cmd.nflag);
++ else
++ s_output(allnc, allnv, cmd.infile, "-DRPC_SVC",
++ EXTEND, "_svc.c", cmd.mflag, cmd.nflag);
++ if (tblflag) {
++ reinitialize();
++ t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i");
++ }
++ if (allfiles) {
++ reinitialize();
++ svc_output(cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c");
++ }
++ if (allfiles) {
++ reinitialize();
++ clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c");
++ }
++ }
++ exit(nonfatalerrors);
++ /* NOTREACHED */
++}
++
++/*
++ * add extension to filename
++ */
++static char *
++extendfile(char *file, char *ext)
++{
++ char *res;
++ char *p;
++
++ res = alloc(strlen(file) + strlen(ext) + 1);
++ if (res == NULL) {
++ abort();
++ }
++ p = strrchr(file, '.');
++ if (p == NULL) {
++ p = file + strlen(file);
++ }
++ (void) strcpy(res, file);
++ (void) strcpy(res + (p - file), ext);
++ return (res);
++}
++
++/*
++ * Open output file with given extension
++ */
++static void
++open_output(char *infile, char *outfile)
++{
++
++ if (outfile == NULL) {
++ fout = stdout;
++ return;
++ }
++
++ if (infile != NULL && streq(outfile, infile)) {
++ f_print(stderr, "%s: output would overwrite %s\n", cmdname,
++ infile);
++ crash();
++ }
++ fout = fopen(outfile, "w");
++ if (fout == NULL) {
++ f_print(stderr, "%s: unable to open ", cmdname);
++ perror(outfile);
++ crash();
++ }
++ record_open(outfile);
++
++}
++
++static void
++add_warning(void)
++{
++ f_print(fout, "/*\n");
++ f_print(fout, " * Please do not edit this file.\n");
++ f_print(fout, " * It was generated using rpcgen.\n");
++ f_print(fout, " */\n\n");
++}
++
++/* clear list of arguments */
++static void
++clear_args(void)
++{
++ int i;
++ for( i=FIXEDARGS; i<ARGLISTLEN; i++ )
++ arglist[i] = NULL;
++ argcount = FIXEDARGS;
++}
++
++/*
++ * Open input file with given define for C-preprocessor
++ */
++static void
++open_input(char *infile, char *define)
++{
++ int pd[2];
++
++ infilename = (infile == NULL) ? "<stdin>" : infile;
++ (void) pipe(pd);
++ switch (fork()) {
++ case 0:
++ putarg(0, "cpp");
++ putarg(1, CPPFLAGS);
++ addarg(define);
++ addarg(infile);
++ addarg((char *)NULL);
++ (void) close(1);
++ (void) dup2(pd[1], 1);
++ (void) close(pd[0]);
++ if (cppDefined)
++ execv(CPP, arglist);
++ else {
++ execvp("cpp", arglist);
++ if (errno == ENOENT)
++ execvp(SVR4_CPP, arglist);
++ if (errno == ENOENT)
++ execvp(SUNOS_CPP, arglist);
++ }
++ perror("execv");
++ exit(1);
++ case -1:
++ perror("fork");
++ exit(1);
++ }
++ (void) close(pd[1]);
++ fin = fdopen(pd[0], "r");
++ if (fin == NULL) {
++ f_print(stderr, "%s: ", cmdname);
++ perror(infilename);
++ crash();
++ }
++}
++
++/* valid tirpc nettypes */
++static char* valid_ti_nettypes[] =
++{
++ "netpath",
++ "visible",
++ "circuit_v",
++ "datagram_v",
++ "circuit_n",
++ "datagram_n",
++ "udp",
++ "tcp",
++ "raw",
++ NULL
++};
++
++/* valid inetd nettypes */
++static char* valid_i_nettypes[] =
++{
++ "udp",
++ "tcp",
++ NULL
++};
++
++static int
++check_nettype(char *name, char **list_to_check)
++{
++ int i;
++ for( i = 0; list_to_check[i] != NULL; i++ ) {
++ if( strcmp( name, list_to_check[i] ) == 0 ) {
++ return 1;
++ }
++ }
++ f_print( stderr, "illegal nettype :\'%s\'\n", name );
++ return 0;
++}
++
++/*
++ * Compile into an XDR routine output file
++ */
++
++static void
++c_output(char *infile, char *define, int extend, char *outfile)
++{
++ definition *def;
++ char *include;
++ char *outfilename;
++ long tell;
++
++ c_initialize();
++ open_input(infile, define);
++ outfilename = extend ? extendfile(infile, outfile) : outfile;
++ open_output(infile, outfilename);
++ add_warning();
++ if (infile && (include = extendfile(infile, ".h"))) {
++ f_print(fout, "#include \"%s\"\n", include);
++ free(include);
++ /* .h file already contains rpc/rpc.h */
++ } else
++ f_print(fout, "#include <rpc/rpc.h>\n");
++ tell = ftell(fout);
++ while ((def = get_definition()) != NULL) {
++ emit(def);
++ }
++ if (extend && tell == ftell(fout)) {
++ (void) unlink(outfilename);
++ }
++}
++
++
++static void
++c_initialize(void)
++{
++
++ /* add all the starting basic types */
++
++ add_type(1,"int");
++ add_type(1,"int32_t");
++ add_type(1,"short");
++ add_type(1,"bool");
++
++ add_type(1,"u_int");
++ add_type(1,"u_int32_t");
++ add_type(1,"u_short");
++
++}
++
++char rpcgen_table_dcl[] = "struct rpcgen_table {\n\
++ char *(*proc)();\n\
++ xdrproc_t xdr_arg;\n\
++ unsigned len_arg;\n\
++ xdrproc_t xdr_res;\n\
++ unsigned len_res;\n\
++};\n";
++
++
++static char *
++generate_guard(char *pathname)
++{
++ char* filename, *guard, *tmp;
++
++ filename = strrchr(pathname, '/' ); /* find last component */
++ filename = ((filename == 0) ? pathname : filename+1);
++ guard = strdup(filename);
++ /* convert to upper case */
++ tmp = guard;
++ while (*tmp) {
++ if (islower(*tmp))
++ *tmp = toupper(*tmp);
++ tmp++;
++ }
++
++ guard = extendfile(guard, "_H_RPCGEN");
++ return( guard );
++}
++
++/*
++ * Compile into an XDR header file
++ */
++static void
++h_output(char *infile, char *define, int extend, char *outfile)
++{
++ definition *def;
++ char *outfilename;
++ long tell;
++ char *guard;
++ list *l;
++
++ open_input(infile, define);
++ outfilename = extend ? extendfile(infile, outfile) : outfile;
++ open_output(infile, outfilename);
++ add_warning();
++ guard = generate_guard( outfilename ? outfilename: infile );
++
++ f_print(fout,"#ifndef _%s\n#define _%s\n\n", guard,
++ guard);
++
++ f_print(fout, "#include <rpc/rpc.h>\n\n");
++
++ f_print(fout, "#ifndef IXDR_GET_INT32\n");
++ f_print(fout, "#define IXDR_GET_INT32(buf) IXDR_GET_LONG((buf))\n");
++ f_print(fout, "#endif\n");
++ f_print(fout, "#ifndef IXDR_PUT_INT32\n");
++ f_print(fout, "#define IXDR_PUT_INT32(buf, v) IXDR_PUT_LONG((buf), (v))\n");
++ f_print(fout, "#endif\n");
++ f_print(fout, "#ifndef IXDR_GET_U_INT32\n");
++ f_print(fout, "#define IXDR_GET_U_INT32(buf) IXDR_GET_U_LONG((buf))\n");
++ f_print(fout, "#endif\n");
++ f_print(fout, "#ifndef IXDR_PUT_U_INT32\n");
++ f_print(fout, "#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_U_LONG((buf), (v))\n");
++ f_print(fout, "#endif\n");
++
++ tell = ftell(fout);
++ /* print data definitions */
++ while ((def = get_definition()) != NULL) {
++ print_datadef(def);
++ }
++
++ /* print function declarations.
++ Do this after data definitions because they might be used as
++ arguments for functions */
++ for (l = defined; l != NULL; l = l->next) {
++ print_funcdef(l->val);
++ }
++ if (extend && tell == ftell(fout)) {
++ (void) unlink(outfilename);
++ } else if (tblflag) {
++ f_print(fout, rpcgen_table_dcl);
++ }
++ f_print(fout, "\n#endif /* !_%s */\n", guard);
++}
++
++/*
++ * Compile into an RPC service
++ */
++static void
++s_output(int argc, char **argv, char *infile, char *define, int extend,
++ char *outfile, int nomain, int netflag)
++{
++ char *include;
++ definition *def;
++ int foundprogram = 0;
++ char *outfilename;
++
++ open_input(infile, define);
++ outfilename = extend ? extendfile(infile, outfile) : outfile;
++ open_output(infile, outfilename);
++ add_warning();
++ if (infile && (include = extendfile(infile, ".h"))) {
++ f_print(fout, "#include \"%s\"\n", include);
++ free(include);
++ } else
++ f_print(fout, "#include <rpc/rpc.h>\n");
++
++ f_print(fout, "#include <stdio.h>\n");
++ f_print(fout, "#include <stdlib.h>/* getenv, exit */\n");
++ if (Cflag) {
++ f_print (fout, "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n");
++ f_print (fout, "#include <string.h> /* strcmp */ \n");
++ }
++ if (strcmp(svcclosetime, "-1") == 0)
++ indefinitewait = 1;
++ else if (strcmp(svcclosetime, "0") == 0)
++ exitnow = 1;
++ else if (inetdflag || pmflag) {
++ f_print(fout, "#include <signal.h>\n");
++ timerflag = 1;
++ }
++
++#ifndef linux
++ if( !tirpcflag && inetdflag )
++ f_print(fout, "#include <sys/ttycom.h>/* TIOCNOTTY */\n");
++#else
++ if( !tirpcflag )
++ f_print(fout, "#include <sys/ioctl.h>/* TIOCNOTTY */\n");
++#endif
++ if( Cflag && (inetdflag || pmflag ) ) {
++ f_print(fout, "#ifdef __cplusplus\n");
++ f_print(fout, "#include <sysent.h> /* getdtablesize, open */\n");
++ f_print(fout, "#endif /* __cplusplus */\n");
++
++ if( tirpcflag )
++ f_print(fout, "#include <unistd.h> /* setsid */\n");
++ }
++ if( tirpcflag )
++ f_print(fout, "#include <sys/types.h>\n");
++
++ f_print(fout, "#include <memory.h>\n");
++#ifndef linux
++ f_print(fout, "#include <stropts.h>\n");
++#endif
++ if (inetdflag || !tirpcflag ) {
++ f_print(fout, "#include <sys/socket.h>\n");
++ f_print(fout, "#include <netinet/in.h>\n");
++ }
++
++ if ( (netflag || pmflag) && tirpcflag ) {
++ f_print(fout, "#include <netconfig.h>\n");
++ }
++ if (/*timerflag &&*/ tirpcflag)
++ f_print(fout, "#include <sys/resource.h> /* rlimit */\n");
++ if (logflag || inetdflag || pmflag) {
++#ifdef linux
++ f_print(fout, "#include <syslog.h>\n");
++#else
++ f_print(fout, "#ifdef SYSLOG\n");
++ f_print(fout, "#include <syslog.h>\n");
++ f_print(fout, "#else\n");
++ f_print(fout, "#define LOG_ERR 1\n");
++ f_print(fout, "#define openlog(a, b, c)\n");
++ f_print(fout, "#endif\n");
++#endif
++ }
++
++ /* for ANSI-C */
++ f_print(fout, "\n#ifdef __STDC__\n#define SIG_PF void(*)(int)\n#endif\n");
++
++ f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n");
++ if (timerflag)
++ f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime);
++ while ((def = get_definition()) != NULL) {
++ foundprogram |= (def->def_kind == DEF_PROGRAM);
++ }
++ if (extend && !foundprogram) {
++ (void) unlink(outfilename);
++ return;
++ }
++ write_most(infile, netflag, nomain);
++ if (!nomain) {
++ if( !do_registers(argc, argv) ) {
++ if (outfilename)
++ (void) unlink(outfilename);
++ usage();
++ }
++ write_rest();
++ }
++}
++
++/*
++ * generate client side stubs
++ */
++static void
++l_output(char *infile, char *define, int extend, char *outfile)
++{
++ char *include;
++ definition *def;
++ int foundprogram = 0;
++ char *outfilename;
++
++ open_input(infile, define);
++ outfilename = extend ? extendfile(infile, outfile) : outfile;
++ open_output(infile, outfilename);
++ add_warning();
++ if (Cflag)
++ f_print (fout, "#include <memory.h> /* for memset */\n");
++ if (infile && (include = extendfile(infile, ".h"))) {
++ f_print(fout, "#include \"%s\"\n", include);
++ free(include);
++ } else
++ f_print(fout, "#include <rpc/rpc.h>\n");
++ while ((def = get_definition()) != NULL) {
++ foundprogram |= (def->def_kind == DEF_PROGRAM);
++ }
++ if (extend && !foundprogram) {
++ (void) unlink(outfilename);
++ return;
++ }
++ write_stubs();
++}
++
++/*
++ * generate the dispatch table
++ */
++static void
++t_output(char *infile, char *define, int extend, char *outfile)
++{
++ definition *def;
++ int foundprogram = 0;
++ char *outfilename;
++
++ open_input(infile, define);
++ outfilename = extend ? extendfile(infile, outfile) : outfile;
++ open_output(infile, outfilename);
++ add_warning();
++ while ((def = get_definition()) != NULL) {
++ foundprogram |= (def->def_kind == DEF_PROGRAM);
++ }
++ if (extend && !foundprogram) {
++ (void) unlink(outfilename);
++ return;
++ }
++ write_tables();
++}
++
++/* sample routine for the server template */
++static void
++svc_output(char *infile, char *define, int extend, char *outfile)
++{
++ definition *def;
++ char *include;
++ char *outfilename;
++ long tell;
++
++ open_input(infile, define);
++ outfilename = extend ? extendfile(infile, outfile) : outfile;
++ checkfiles(infile,outfilename); /*check if outfile already exists.
++ if so, print an error message and exit*/
++ open_output(infile, outfilename);
++ add_sample_msg();
++
++ if (infile && (include = extendfile(infile, ".h"))) {
++ f_print(fout, "#include \"%s\"\n", include);
++ free(include);
++ } else
++ f_print(fout, "#include <rpc/rpc.h>\n");
++
++ tell = ftell(fout);
++ while ((def = get_definition()) != NULL) {
++ write_sample_svc(def);
++ }
++ if (extend && tell == ftell(fout)) {
++ (void) unlink(outfilename);
++ }
++}
++
++
++/* sample main routine for client */
++static void
++clnt_output(char *infile, char *define, int extend, char *outfile)
++{
++ definition *def;
++ char *include;
++ char *outfilename;
++ long tell;
++ int has_program = 0;
++
++ open_input(infile, define);
++ outfilename = extend ? extendfile(infile, outfile) : outfile;
++ checkfiles(infile, outfilename); /*check if outfile already exists.
++ if so, print an error message and exit*/
++
++ open_output(infile, outfilename);
++ add_sample_msg();
++ if (infile && (include = extendfile(infile, ".h"))) {
++ f_print(fout, "#include \"%s\"\n", include);
++ free(include);
++ } else
++ f_print(fout, "#include <rpc/rpc.h>\n");
++ tell = ftell(fout);
++ while ((def = get_definition()) != NULL) {
++ has_program += write_sample_clnt(def);
++ }
++
++ if (has_program)
++ write_sample_clnt_main();
++
++ if (extend && tell == ftell(fout)) {
++ (void) unlink(outfilename);
++ }
++}
++
++/*
++ * Perform registrations for service output
++ * Return 0 if failed; 1 otherwise.
++ */
++static int
++do_registers(int argc, char **argv)
++{
++ int i;
++
++ if (inetdflag || !tirpcflag) {
++ for (i = 1; i < argc; i++) {
++ if (streq(argv[i], "-s")) {
++ if (!check_nettype(argv[i + 1], valid_i_nettypes))
++ return 0;
++ write_inetd_register(argv[i + 1]);
++ i++;
++ }
++ }
++ } else {
++ for (i = 1; i < argc; i++)
++ if (streq(argv[i], "-s")) {
++ if (!check_nettype(argv[i + 1], valid_ti_nettypes))
++ return 0;
++ write_nettype_register(argv[i + 1]);
++ i++;
++ } else if (streq(argv[i], "-n")) {
++ write_netid_register(argv[i + 1]);
++ i++;
++ }
++ }
++ return 1;
++}
++
++/*
++ * Add another argument to the arg list
++ */
++static void
++addarg(char *cp)
++{
++ if (argcount >= ARGLISTLEN) {
++ f_print(stderr, "rpcgen: too many defines\n");
++ crash();
++ /*NOTREACHED*/
++ }
++ arglist[argcount++] = cp;
++
++}
++
++static void
++putarg(int where, char *cp)
++{
++ if (where >= ARGLISTLEN) {
++ f_print(stderr, "rpcgen: arglist coding error\n");
++ crash();
++ /*NOTREACHED*/
++ }
++ arglist[where] = cp;
++
++}
++
++/*
++ * if input file is stdin and an output file is specified then complain
++ * if the file already exists. Otherwise the file may get overwritten
++ * If input file does not exist, exit with an error
++ */
++
++static void
++checkfiles(char *infile, char *outfile)
++{
++
++ struct stat buf;
++
++ if(infile) /* infile ! = NULL */
++ if(stat(infile,&buf) < 0)
++ {
++ perror(infile);
++ crash();
++ };
++ if (outfile) {
++ if (stat(outfile, &buf) < 0)
++ return; /* file does not exist */
++ else {
++ f_print(stderr,
++ "file '%s' already exists and may be overwritten\n", outfile);
++ crash();
++ }
++ }
++}
++
++/*
++ * Parse command line arguments
++ */
++static int
++parseargs(int argc, char **argv, struct commandline *cmd)
++{
++ int i;
++ int j;
++ char c;
++ char flag[(1 << 8 * sizeof(char))];
++ int nflags;
++
++ cmdname = argv[0];
++ cmd->infile = cmd->outfile = NULL;
++ if (argc < 2) {
++ return (0);
++ }
++ allfiles = 0;
++ flag['c'] = 0;
++ flag['h'] = 0;
++ flag['l'] = 0;
++ flag['m'] = 0;
++ flag['o'] = 0;
++ flag['s'] = 0;
++ flag['n'] = 0;
++ flag['t'] = 0;
++ flag['S'] = 0;
++ flag['C'] = 0;
++ for (i = 1; i < argc; i++) {
++ if (argv[i][0] != '-') {
++ if (cmd->infile) {
++ f_print( stderr, "Cannot specify more than one input file!\n");
++
++ return (0);
++ }
++ cmd->infile = argv[i];
++ } else {
++ for (j = 1; argv[i][j] != 0; j++) {
++ c = argv[i][j];
++ switch (c) {
++ case 'a':
++ allfiles = 1;
++ break;
++ case 'c':
++ case 'h':
++ case 'l':
++ case 'm':
++ case 't':
++ if (flag[(int) c]) {
++ return (0);
++ }
++ flag[(int) c] = 1;
++ break;
++ case 'S':
++ /* sample flag: Ss or Sc.
++ Ss means set flag['S'];
++ Sc means set flag['C']; */
++ c = argv[i][++j]; /* get next char */
++ if( c == 's' )
++ c = 'S';
++ else if( c == 'c' )
++ c = 'C';
++ else
++ return( 0 );
++
++ if (flag[(int) c]) {
++ return (0);
++ }
++ flag[(int) c] = 1;
++ break;
++ case 'C': /* ANSI C syntax */
++ Cflag = 1;
++ break;
++
++ case 'b': /* turn TIRPC flag off for
++ generating backward compatible
++ */
++ tirpcflag = 0;
++ break;
++
++ case 'I':
++ inetdflag = 1;
++ break;
++ case 'N':
++ newstyle = 1;
++ break;
++ case 'L':
++ logflag = 1;
++ break;
++ case 'K':
++ if (++i == argc) {
++ return (0);
++ }
++ svcclosetime = argv[i];
++ goto nextarg;
++ case 'T':
++ tblflag = 1;
++ break;
++ case 'i' :
++ if (++i == argc) {
++ return (0);
++ }
++ Inline = atoi(argv[i]);
++ goto nextarg;
++ case 'n':
++ case 'o':
++ case 's':
++ if (argv[i][j - 1] != '-' ||
++ argv[i][j + 1] != 0) {
++ return (0);
++ }
++ flag[(int) c] = 1;
++ if (++i == argc) {
++ return (0);
++ }
++ if (c == 's') {
++ if (!streq(argv[i], "udp") &&
++ !streq(argv[i], "tcp")) {
++ return (0);
++ }
++ } else if (c == 'o') {
++ if (cmd->outfile) {
++ return (0);
++ }
++ cmd->outfile = argv[i];
++ }
++ goto nextarg;
++ case 'D':
++ if (argv[i][j - 1] != '-') {
++ return (0);
++ }
++ (void) addarg(argv[i]);
++ goto nextarg;
++ case 'Y':
++ if (++i == argc) {
++ return (0);
++ }
++ (void) strcpy(pathbuf, argv[i]);
++ (void) strcat(pathbuf, "/cpp");
++ CPP = pathbuf;
++ cppDefined = 1;
++ goto nextarg;
++
++
++
++ default:
++ return (0);
++ }
++ }
++ nextarg:
++ ;
++ }
++ }
++
++ cmd->cflag = flag['c'];
++ cmd->hflag = flag['h'];
++ cmd->lflag = flag['l'];
++ cmd->mflag = flag['m'];
++ cmd->nflag = flag['n'];
++ cmd->sflag = flag['s'];
++ cmd->tflag = flag['t'];
++ cmd->Ssflag = flag['S'];
++ cmd->Scflag = flag['C'];
++
++ if( tirpcflag ) {
++ pmflag = inetdflag ? 0 : 1; /* pmflag or inetdflag is always TRUE */
++ if( (inetdflag && cmd->nflag)) { /* netid not allowed with inetdflag */
++ f_print(stderr, "Cannot use netid flag with inetd flag!\n");
++ return (0);
++ }
++ } else { /* 4.1 mode */
++ pmflag = 0; /* set pmflag only in tirpcmode */
++ inetdflag = 1; /* inetdflag is TRUE by default */
++ if( cmd->nflag ) { /* netid needs TIRPC */
++ f_print( stderr, "Cannot use netid flag without TIRPC!\n");
++ return( 0 );
++ }
++ }
++
++ if( newstyle && ( tblflag || cmd->tflag) ) {
++ f_print( stderr, "Cannot use table flags with newstyle!\n");
++ return( 0 );
++ }
++
++ /* check no conflicts with file generation flags */
++ nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag +
++ cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag;
++
++ if (nflags == 0) {
++ if (cmd->outfile != NULL || cmd->infile == NULL) {
++ return (0);
++ }
++ } else if (nflags > 1) {
++ f_print( stderr, "Cannot have more than one file generation flag!\n");
++ return (0);
++ }
++ return (1);
++}
++
++static void
++usage(void)
++{
++ f_print(stderr, "usage: %s infile\n", cmdname);
++ f_print(stderr, "\t%s [-a][-b][-C][-Dname[=value]] -i size [-I [-K seconds]] [-L][-N][-T] infile\n",
++ cmdname);
++ f_print(stderr, "\t%s [-c | -h | -l | -m | -t | -Sc | -Ss] [-o outfile] [infile]\n",
++ cmdname);
++ f_print(stderr, "\t%s [-s nettype]* [-o outfile] [infile]\n", cmdname);
++ f_print(stderr, "\t%s [-n netid]* [-o outfile] [infile]\n", cmdname);
++ options_usage();
++ exit(1);
++}
++
++static void
++options_usage(void)
++{
++ f_print(stderr, "options:\n");
++ f_print(stderr, "-a\t\tgenerate all files, including samples\n");
++ f_print(stderr, "-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n");
++ f_print(stderr, "-c\t\tgenerate XDR routines\n");
++ f_print(stderr, "-C\t\tANSI C mode\n");
++ f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n");
++ f_print(stderr, "-h\t\tgenerate header file\n");
++ f_print(stderr, "-i size\t\tsize at which to start generating inline code\n");
++ f_print(stderr, "-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n");
++ f_print(stderr, "-K seconds\tserver exits after K seconds of inactivity\n");
++ f_print(stderr, "-l\t\tgenerate client side stubs\n");
++ f_print(stderr, "-L\t\tserver errors will be printed to syslog\n");
++ f_print(stderr, "-m\t\tgenerate server side stubs\n");
++ f_print(stderr, "-n netid\tgenerate server code that supports named netid\n");
++ f_print(stderr, "-N\t\tsupports multiple arguments and call-by-value\n");
++ f_print(stderr, "-o outfile\tname of the output file\n");
++ f_print(stderr, "-s nettype\tgenerate server code that supports named nettype\n");
++ f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote procedures\n");
++ f_print(stderr, "-Ss\t\tgenerate sample server code that defines remote procedures\n");
++ f_print(stderr, "-t\t\tgenerate RPC dispatch table\n");
++ f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n");
++ f_print(stderr, "-Y path\t\tdirectory name to find C preprocessor (cpp)\n");
++
++ exit(1);
++}
+diff --git a/rpcgen/rpc_output.h b/rpcgen/rpc_output.h
+new file mode 100644
+index 0000000..eb25a60
+--- /dev/null
++++ b/rpcgen/rpc_output.h
+@@ -0,0 +1,16 @@
++/*
++ * rpc_output.h
++ *
++ * Declarations for output functions
++ *
++ */
++
++#ifndef RPCGEN_NEW_OUTPUT_H
++#define RPCGEN_NEW_OUTPUT_H
++
++void write_msg_out(void);
++int nullproc(proc_list *);
++void printarglist(proc_list *, char *, char *);
++void pdeclaration(char *, declaration *, int, char *);
++
++#endif /* RPCGEN_NEW_OUTPUT_H */
+diff --git a/rpcgen/rpc_parse.c b/rpcgen/rpc_parse.c
+new file mode 100644
+index 0000000..b53a553
+--- /dev/null
++++ b/rpcgen/rpc_parse.c
+@@ -0,0 +1,609 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI";
++#endif
++
++/*
++ * rpc_parse.c, Parser for the RPC protocol compiler
++ * Copyright (C) 1987 Sun Microsystems, Inc.
++ */
++#include <stdio.h>
++#include <string.h>
++#include "rpc/types.h"
++#include "rpc_scan.h"
++#include "rpc_parse.h"
++#include "rpc_util.h"
++
++#define ARGNAME "arg"
++
++/*
++extern char *make_argname();
++extern char *strdup();
++ */
++
++static void isdefined(definition *defp);
++static void def_struct(definition *defp);
++static void def_program(definition *defp);
++static void def_enum(definition *defp);
++static void def_const(definition *defp);
++static void def_union(definition *defp);
++static void check_type_name(char *name, int new_type);
++static void def_typedef(definition *defp);
++static void get_declaration(declaration *dec, defkind dkind);
++static void get_prog_declaration(declaration *dec, defkind dkind, int num);
++static void get_type(char **prefixp, char **typep, defkind dkind);
++static void unsigned_dec(char **typep);
++
++/*
++ * return the next definition you see
++ */
++definition *
++get_definition(void)
++{
++ definition *defp;
++ token tok;
++
++ defp = ALLOC(definition);
++ get_token(&tok);
++ switch (tok.kind) {
++ case TOK_STRUCT:
++ def_struct(defp);
++ break;
++ case TOK_UNION:
++ def_union(defp);
++ break;
++ case TOK_TYPEDEF:
++ def_typedef(defp);
++ break;
++ case TOK_ENUM:
++ def_enum(defp);
++ break;
++ case TOK_PROGRAM:
++ def_program(defp);
++ break;
++ case TOK_CONST:
++ def_const(defp);
++ break;
++ case TOK_EOF:
++ free(defp);
++ return (NULL);
++ default:
++ error("definition keyword expected");
++ }
++ scan(TOK_SEMICOLON, &tok);
++ isdefined(defp);
++ return (defp);
++}
++
++static void
++isdefined(definition *defp)
++{
++ STOREVAL(&defined, defp);
++}
++
++static void
++def_struct(definition *defp)
++{
++ token tok;
++ declaration dec;
++ decl_list *decls;
++ decl_list **tailp;
++
++ defp->def_kind = DEF_STRUCT;
++
++ scan(TOK_IDENT, &tok);
++ defp->def_name = tok.str;
++ scan(TOK_LBRACE, &tok);
++ tailp = &defp->def.st.decls;
++ do {
++ get_declaration(&dec, DEF_STRUCT);
++ decls = ALLOC(decl_list);
++ decls->decl = dec;
++ *tailp = decls;
++ tailp = &decls->next;
++ scan(TOK_SEMICOLON, &tok);
++ peek(&tok);
++ } while (tok.kind != TOK_RBRACE);
++ get_token(&tok);
++ *tailp = NULL;
++}
++
++static void
++def_program(definition *defp)
++{
++ token tok;
++ declaration dec;
++ decl_list *decls;
++ decl_list **tailp;
++ version_list *vlist;
++ version_list **vtailp;
++ proc_list *plist;
++ proc_list **ptailp;
++ int num_args;
++ bool_t isvoid = FALSE; /* whether first argument is void */
++ defp->def_kind = DEF_PROGRAM;
++ scan(TOK_IDENT, &tok);
++ defp->def_name = tok.str;
++ scan(TOK_LBRACE, &tok);
++ vtailp = &defp->def.pr.versions;
++ tailp = &defp->def.st.decls;
++ scan(TOK_VERSION, &tok);
++ do {
++ scan(TOK_IDENT, &tok);
++ vlist = ALLOC(version_list);
++ vlist->vers_name = tok.str;
++ scan(TOK_LBRACE, &tok);
++ ptailp = &vlist->procs;
++ do {
++ /* get result type */
++ plist = ALLOC(proc_list);
++ get_type(&plist->res_prefix, &plist->res_type,
++ DEF_PROGRAM);
++ if (streq(plist->res_type, "opaque")) {
++ error("illegal result type");
++ }
++ scan(TOK_IDENT, &tok);
++ plist->proc_name = tok.str;
++ scan(TOK_LPAREN, &tok);
++ /* get args - first one*/
++ num_args = 1;
++ isvoid = FALSE;
++ /* type of DEF_PROGRAM in the first
++ * get_prog_declaration and DEF_STURCT in the next
++ * allows void as argument if it is the only argument
++ */
++ get_prog_declaration(&dec, DEF_PROGRAM, num_args);
++ if (streq(dec.type, "void"))
++ isvoid = TRUE;
++ decls = ALLOC(decl_list);
++ plist->args.decls = decls;
++ decls->decl = dec;
++ tailp = &decls->next;
++ /* get args */
++ while(peekscan(TOK_COMMA, &tok)) {
++ num_args++;
++ get_prog_declaration(&dec, DEF_STRUCT,
++ num_args);
++ decls = ALLOC(decl_list);
++ decls->decl = dec;
++ *tailp = decls;
++ if (streq(dec.type, "void"))
++ isvoid = TRUE;
++ tailp = &decls->next;
++ }
++ /* multiple arguments are only allowed in newstyle */
++ if( !newstyle && num_args > 1 ) {
++ error("only one argument is allowed" );
++ }
++ if (isvoid && num_args > 1) {
++ error("illegal use of void in program definition");
++ }
++ *tailp = NULL;
++ scan(TOK_RPAREN, &tok);
++ scan(TOK_EQUAL, &tok);
++ scan_num(&tok);
++ scan(TOK_SEMICOLON, &tok);
++ plist->proc_num = tok.str;
++ plist->arg_num = num_args;
++ *ptailp = plist;
++ ptailp = &plist->next;
++ peek(&tok);
++ } while (tok.kind != TOK_RBRACE);
++ *ptailp = NULL;
++ *vtailp = vlist;
++ vtailp = &vlist->next;
++ scan(TOK_RBRACE, &tok);
++ scan(TOK_EQUAL, &tok);
++ scan_num(&tok);
++ vlist->vers_num = tok.str;
++ /* make the argument structure name for each arg*/
++ for(plist = vlist->procs; plist != NULL;
++ plist = plist->next) {
++ plist->args.argname = make_argname(plist->proc_name,
++ vlist->vers_num);
++ /* free the memory ??*/
++ }
++ scan(TOK_SEMICOLON, &tok);
++ scan2(TOK_VERSION, TOK_RBRACE, &tok);
++ } while (tok.kind == TOK_VERSION);
++ scan(TOK_EQUAL, &tok);
++ scan_num(&tok);
++ defp->def.pr.prog_num = tok.str;
++ *vtailp = NULL;
++}
++
++
++static void
++def_enum(definition *defp)
++{
++ token tok;
++ enumval_list *elist;
++ enumval_list **tailp;
++
++ defp->def_kind = DEF_ENUM;
++ scan(TOK_IDENT, &tok);
++ defp->def_name = tok.str;
++ scan(TOK_LBRACE, &tok);
++ tailp = &defp->def.en.vals;
++ do {
++ scan(TOK_IDENT, &tok);
++ elist = ALLOC(enumval_list);
++ elist->name = tok.str;
++ elist->assignment = NULL;
++ scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
++ if (tok.kind == TOK_EQUAL) {
++ scan_num(&tok);
++ elist->assignment = tok.str;
++ scan2(TOK_COMMA, TOK_RBRACE, &tok);
++ }
++ *tailp = elist;
++ tailp = &elist->next;
++ } while (tok.kind != TOK_RBRACE);
++ *tailp = NULL;
++}
++
++static void
++def_const(definition *defp)
++{
++ token tok;
++
++ defp->def_kind = DEF_CONST;
++ scan(TOK_IDENT, &tok);
++ defp->def_name = tok.str;
++ scan(TOK_EQUAL, &tok);
++ scan2(TOK_IDENT, TOK_STRCONST, &tok);
++ defp->def.co = tok.str;
++}
++
++static void
++def_union(definition *defp)
++{
++ token tok;
++ declaration dec;
++ case_list *cases;
++ case_list **tailp;
++
++ defp->def_kind = DEF_UNION;
++ scan(TOK_IDENT, &tok);
++ defp->def_name = tok.str;
++ scan(TOK_SWITCH, &tok);
++ scan(TOK_LPAREN, &tok);
++ get_declaration(&dec, DEF_UNION);
++ defp->def.un.enum_decl = dec;
++ tailp = &defp->def.un.cases;
++ scan(TOK_RPAREN, &tok);
++ scan(TOK_LBRACE, &tok);
++ scan(TOK_CASE, &tok);
++ while (tok.kind == TOK_CASE) {
++ scan2(TOK_IDENT, TOK_CHARCONST, &tok);
++ cases = ALLOC(case_list);
++ cases->case_name = tok.str;
++ scan(TOK_COLON, &tok);
++ /* now peek at next token */
++ if(peekscan(TOK_CASE,&tok))
++ {
++
++ do
++ {
++ scan2(TOK_IDENT, TOK_CHARCONST, &tok);
++ cases->contflag=1; /* continued case statement */
++ *tailp = cases;
++ tailp = &cases->next;
++ cases = ALLOC(case_list);
++ cases->case_name = tok.str;
++ scan(TOK_COLON, &tok);
++
++ }while(peekscan(TOK_CASE,&tok));
++ }
++
++ get_declaration(&dec, DEF_UNION);
++ cases->case_decl = dec;
++ cases->contflag=0; /* no continued case statement */
++ *tailp = cases;
++ tailp = &cases->next;
++ scan(TOK_SEMICOLON, &tok);
++
++ scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
++ }
++ *tailp = NULL;
++ if (tok.kind == TOK_DEFAULT) {
++ scan(TOK_COLON, &tok);
++ get_declaration(&dec, DEF_UNION);
++ defp->def.un.default_decl = ALLOC(declaration);
++ *defp->def.un.default_decl = dec;
++ scan(TOK_SEMICOLON, &tok);
++ scan(TOK_RBRACE, &tok);
++ } else {
++ defp->def.un.default_decl = NULL;
++ }
++}
++
++static char* reserved_words[] =
++{
++ "array",
++ "bytes",
++ "destroy",
++ "free",
++ "getpos",
++ "inline",
++ "pointer",
++ "reference",
++ "setpos",
++ "sizeof",
++ "union",
++ "vector",
++ NULL
++ };
++
++static char* reserved_types[] =
++{
++ "opaque",
++ "string",
++ NULL
++ };
++
++/* check that the given name is not one that would eventually result in
++ xdr routines that would conflict with internal XDR routines. */
++static void
++check_type_name(char *name, int new_type)
++{
++ int i;
++ char tmp[100];
++
++ for( i = 0; reserved_words[i] != NULL; i++ ) {
++ if( strcmp( name, reserved_words[i] ) == 0 ) {
++ sprintf(tmp,
++ "illegal (reserved) name :\'%s\' in type definition", name );
++ error(tmp);
++ }
++ }
++ if( new_type ) {
++ for( i = 0; reserved_types[i] != NULL; i++ ) {
++ if( strcmp( name, reserved_types[i] ) == 0 ) {
++ sprintf(tmp,
++ "illegal (reserved) name :\'%s\' in type definition", name );
++ error(tmp);
++ }
++ }
++ }
++}
++
++static void
++def_typedef(definition *defp)
++{
++ declaration dec;
++
++ defp->def_kind = DEF_TYPEDEF;
++ get_declaration(&dec, DEF_TYPEDEF);
++ defp->def_name = dec.name;
++ check_type_name( dec.name, 1 );
++ defp->def.ty.old_prefix = dec.prefix;
++ defp->def.ty.old_type = dec.type;
++ defp->def.ty.rel = dec.rel;
++ defp->def.ty.array_max = dec.array_max;
++}
++
++static void
++get_declaration(declaration *dec, defkind dkind)
++{
++ token tok;
++
++ get_type(&dec->prefix, &dec->type, dkind);
++ dec->rel = REL_ALIAS;
++ if (streq(dec->type, "void")) {
++ return;
++ }
++
++ check_type_name( dec->type, 0 );
++
++ scan2(TOK_STAR, TOK_IDENT, &tok);
++ if (tok.kind == TOK_STAR) {
++ dec->rel = REL_POINTER;
++ scan(TOK_IDENT, &tok);
++ }
++ dec->name = tok.str;
++ if (peekscan(TOK_LBRACKET, &tok)) {
++ if (dec->rel == REL_POINTER) {
++ error("no array-of-pointer declarations -- use typedef");
++ }
++ dec->rel = REL_VECTOR;
++ scan_num(&tok);
++ dec->array_max = tok.str;
++ scan(TOK_RBRACKET, &tok);
++ } else if (peekscan(TOK_LANGLE, &tok)) {
++ if (dec->rel == REL_POINTER) {
++ error("no array-of-pointer declarations -- use typedef");
++ }
++ dec->rel = REL_ARRAY;
++ if (peekscan(TOK_RANGLE, &tok)) {
++ dec->array_max = "~0"; /* unspecified size, use max */
++ } else {
++ scan_num(&tok);
++ dec->array_max = tok.str;
++ scan(TOK_RANGLE, &tok);
++ }
++ }
++ if (streq(dec->type, "opaque")) {
++ if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
++ error("array declaration expected");
++ }
++ } else if (streq(dec->type, "string")) {
++ if (dec->rel != REL_ARRAY) {
++ error("variable-length array declaration expected");
++ }
++ }
++}
++
++
++static void
++get_prog_declaration(declaration *dec, defkind dkind, int num)
++{
++ token tok;
++ char name[10]; /* argument name */
++
++ if (dkind == DEF_PROGRAM) {
++ peek(&tok);
++ if (tok.kind == TOK_RPAREN) { /* no arguments */
++ dec->rel = REL_ALIAS;
++ dec->type = "void";
++ dec->prefix = NULL;
++ dec->name = NULL;
++ return;
++ }
++ }
++ get_type(&dec->prefix, &dec->type, dkind);
++ dec->rel = REL_ALIAS;
++ if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
++ strcpy(name, tok.str);
++ else
++ sprintf(name, "%s%d", ARGNAME, num); /* default name of argument */
++
++ dec->name = (char *) strdup(name);
++
++ if (streq(dec->type, "void")) {
++ return;
++ }
++
++ if (streq(dec->type, "opaque")) {
++ error("opaque -- illegal argument type");
++ }
++ if (peekscan(TOK_STAR, &tok)) {
++ if (streq(dec->type, "string")) {
++ error("pointer to string not allowed in program arguments\n");
++ }
++ dec->rel = REL_POINTER;
++ if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
++ dec->name = strdup(tok.str);
++ }
++ if (peekscan(TOK_LANGLE, &tok)) {
++ if (!streq(dec->type, "string")) {
++ error("arrays cannot be declared as arguments to procedures -- use typedef");
++ }
++ dec->rel = REL_ARRAY;
++ if (peekscan(TOK_RANGLE, &tok)) {
++ dec->array_max = "~0";/* unspecified size, use max */
++ } else {
++ scan_num(&tok);
++ dec->array_max = tok.str;
++ scan(TOK_RANGLE, &tok);
++ }
++ }
++ if (streq(dec->type, "string")) {
++ if (dec->rel != REL_ARRAY) { /* .x specifies just string as
++ * type of argument
++ * - make it string<>
++ */
++ dec->rel = REL_ARRAY;
++ dec->array_max = "~0";/* unspecified size, use max */
++ }
++ }
++}
++
++
++
++static void
++get_type(char **prefixp, char **typep, defkind dkind)
++{
++ token tok;
++
++ *prefixp = NULL;
++ get_token(&tok);
++ switch (tok.kind) {
++ case TOK_IDENT:
++ *typep = tok.str;
++ break;
++ case TOK_STRUCT:
++ case TOK_ENUM:
++ case TOK_UNION:
++ *prefixp = tok.str;
++ scan(TOK_IDENT, &tok);
++ *typep = tok.str;
++ break;
++ case TOK_UNSIGNED:
++ unsigned_dec(typep);
++ break;
++ case TOK_SHORT:
++ *typep = "short";
++ (void) peekscan(TOK_INT, &tok);
++ break;
++ case TOK_INT32:
++ *typep = "int32_t";
++ (void) peekscan(TOK_INT, &tok);
++ break;
++ case TOK_VOID:
++ if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
++ error("voids allowed only inside union and program definitions with one argument");
++ }
++ *typep = tok.str;
++ break;
++ case TOK_STRING:
++ case TOK_OPAQUE:
++ case TOK_CHAR:
++ case TOK_INT:
++ case TOK_FLOAT:
++ case TOK_DOUBLE:
++ case TOK_BOOL:
++ *typep = tok.str;
++ break;
++ default:
++ error("expected type specifier");
++ }
++}
++
++static void
++unsigned_dec(char **typep)
++{
++ token tok;
++
++ peek(&tok);
++ switch (tok.kind) {
++ case TOK_CHAR:
++ get_token(&tok);
++ *typep = "u_char";
++ break;
++ case TOK_SHORT:
++ get_token(&tok);
++ *typep = "u_short";
++ (void) peekscan(TOK_INT, &tok);
++ break;
++ case TOK_INT32:
++ get_token(&tok);
++ *typep = "u_int32_";
++ (void) peekscan(TOK_INT, &tok);
++ break;
++ case TOK_INT:
++ get_token(&tok);
++ *typep = "u_int";
++ break;
++ default:
++ *typep = "u_int";
++ break;
++ }
++}
+diff --git a/rpcgen/rpc_parse.h b/rpcgen/rpc_parse.h
+new file mode 100644
+index 0000000..2afae10
+--- /dev/null
++++ b/rpcgen/rpc_parse.h
+@@ -0,0 +1,166 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++/* @(#)rpc_parse.h 1.3 90/08/29 (C) 1987 SMI */
++
++/*
++ * rpc_parse.h, Definitions for the RPCL parser
++ */
++
++enum defkind {
++ DEF_CONST,
++ DEF_STRUCT,
++ DEF_UNION,
++ DEF_ENUM,
++ DEF_TYPEDEF,
++ DEF_PROGRAM
++};
++typedef enum defkind defkind;
++
++typedef char *const_def;
++
++enum relation {
++ REL_VECTOR, /* fixed length array */
++ REL_ARRAY, /* variable length array */
++ REL_POINTER, /* pointer */
++ REL_ALIAS, /* simple */
++};
++typedef enum relation relation;
++
++struct typedef_def {
++ char *old_prefix;
++ char *old_type;
++ relation rel;
++ char *array_max;
++};
++typedef struct typedef_def typedef_def;
++
++struct enumval_list {
++ char *name;
++ char *assignment;
++ struct enumval_list *next;
++};
++typedef struct enumval_list enumval_list;
++
++struct enum_def {
++ enumval_list *vals;
++};
++typedef struct enum_def enum_def;
++
++struct declaration {
++ char *prefix;
++ char *type;
++ char *name;
++ relation rel;
++ char *array_max;
++};
++typedef struct declaration declaration;
++
++struct decl_list {
++ declaration decl;
++ struct decl_list *next;
++};
++typedef struct decl_list decl_list;
++
++struct struct_def {
++ decl_list *decls;
++};
++typedef struct struct_def struct_def;
++
++struct case_list {
++ char *case_name;
++ int contflag;
++ declaration case_decl;
++ struct case_list *next;
++};
++typedef struct case_list case_list;
++
++struct union_def {
++ declaration enum_decl;
++ case_list *cases;
++ declaration *default_decl;
++};
++typedef struct union_def union_def;
++
++struct arg_list {
++ char *argname; /* name of struct for arg*/
++ decl_list *decls;
++};
++
++typedef struct arg_list arg_list;
++
++struct proc_list {
++ char *proc_name;
++ char *proc_num;
++ arg_list args;
++ int arg_num;
++ char *res_type;
++ char *res_prefix;
++ struct proc_list *next;
++};
++typedef struct proc_list proc_list;
++
++struct version_list {
++ char *vers_name;
++ char *vers_num;
++ proc_list *procs;
++ struct version_list *next;
++};
++typedef struct version_list version_list;
++
++struct program_def {
++ char *prog_num;
++ version_list *versions;
++};
++typedef struct program_def program_def;
++
++struct definition {
++ char *def_name;
++ defkind def_kind;
++ union {
++ const_def co;
++ struct_def st;
++ union_def un;
++ enum_def en;
++ typedef_def ty;
++ program_def pr;
++ } def;
++};
++typedef struct definition definition;
++
++definition *get_definition();
++
++
++struct bas_type
++{
++ char *name;
++ int length;
++ struct bas_type *next;
++};
++
++typedef struct bas_type bas_type;
+diff --git a/rpcgen/rpc_sample.c b/rpcgen/rpc_sample.c
+new file mode 100644
+index 0000000..2b5c81b
+--- /dev/null
++++ b/rpcgen/rpc_sample.c
+@@ -0,0 +1,247 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++static char sccsid[] = "@(#)rpc_sample.c 1.1 90/08/30 (C) 1987 SMI";
++
++#endif
++
++/*
++ * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler
++ */
++
++#include <stdio.h>
++#include <string.h>
++#include "rpc_parse.h"
++#include "rpc_util.h"
++
++
++static char RQSTP[] = "rqstp";
++
++static void write_sample_client(char *program_name, version_list *vp);
++static void write_sample_server(definition * def);
++static void return_type(proc_list *plist);
++
++void
++write_sample_svc(definition *def)
++{
++ if (def->def_kind != DEF_PROGRAM)
++ return;
++ write_sample_server(def);
++}
++
++
++int
++write_sample_clnt(definition *def)
++{
++ version_list *vp;
++ int count = 0;
++
++ if (def->def_kind != DEF_PROGRAM)
++ return (0);
++ /* generate sample code for each version */
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ write_sample_client(def->def_name, vp);
++ ++count;
++ }
++ return (count);
++}
++
++
++static void
++write_sample_client(char *program_name, version_list *vp)
++{
++ proc_list *proc;
++ int i;
++ decl_list *l;
++
++ f_print(fout, "\n\nvoid\n");
++ pvname(program_name, vp->vers_num);
++ if (Cflag)
++ f_print(fout, "( char* host )\n{\n");
++ else
++ f_print(fout, "(host)\nchar *host;\n{\n");
++ f_print(fout, "\tCLIENT *clnt;\n");
++
++ i = 0;
++ for (proc = vp->procs; proc != NULL; proc = proc->next) {
++ f_print(fout, "\t");
++ ptype(proc->res_prefix, proc->res_type, 1);
++ f_print(fout, " *result_%d;\n", ++i);
++ /* print out declarations for arguments */
++ if (proc->arg_num < 2 && !newstyle) {
++ f_print(fout, "\t");
++ if (!streq(proc->args.decls->decl.type, "void"))
++ ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
++ else
++ f_print(fout, "char* "); /* cannot have "void" type */
++ f_print(fout, " ");
++ pvname(proc->proc_name, vp->vers_num);
++ f_print(fout, "_arg;\n");
++ } else if (!streq(proc->args.decls->decl.type, "void")) {
++ for (l = proc->args.decls; l != NULL; l = l->next) {
++ f_print(fout, "\t");
++ ptype(l->decl.prefix, l->decl.type, 1);
++ f_print(fout, " ");
++ pvname(proc->proc_name, vp->vers_num);
++ f_print(fout, "_%s;\n", l->decl.name);
++ /* pdeclaration(proc->args.argname, &l->decl, 1, ";\n" );*/
++ }
++ }
++ }
++
++ /* generate creation of client handle */
++ f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n",
++ program_name, vp->vers_name, tirpcflag ? "netpath" : "udp");
++ f_print(fout, "\tif (clnt == NULL) {\n");
++ f_print(fout, "\t\tclnt_pcreateerror(host);\n");
++ f_print(fout, "\t\texit(1);\n\t}\n");
++
++ /* generate calls to procedures */
++ i = 0;
++ for (proc = vp->procs; proc != NULL; proc = proc->next) {
++ f_print(fout, "\tresult_%d = ", ++i);
++ pvname(proc->proc_name, vp->vers_num);
++ if (proc->arg_num < 2 && !newstyle) {
++ f_print(fout, "(");
++ if (streq(proc->args.decls->decl.type, "void")) /* cast to void* */
++ f_print(fout, "(void*)");
++ f_print(fout, "&");
++ pvname(proc->proc_name, vp->vers_num);
++ f_print(fout, "_arg, clnt);\n");
++ } else if (streq(proc->args.decls->decl.type, "void")) {
++ f_print(fout, "(clnt);\n");
++ } else {
++ f_print(fout, "(");
++ for (l = proc->args.decls; l != NULL; l = l->next) {
++ pvname(proc->proc_name, vp->vers_num);
++ f_print(fout, "_%s, ", l->decl.name);
++ }
++ f_print(fout, "clnt);\n");
++ }
++ f_print(fout, "\tif (result_%d == NULL) {\n", i);
++ f_print(fout, "\t\tclnt_perror(clnt, \"call failed:\");\n");
++ f_print(fout, "\t}\n");
++ }
++
++ f_print(fout, "\tclnt_destroy( clnt );\n");
++ f_print(fout, "}\n");
++}
++
++static void
++write_sample_server(definition * def)
++{
++ version_list *vp;
++ proc_list *proc;
++
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ for (proc = vp->procs; proc != NULL; proc = proc->next) {
++ f_print(fout, "\n");
++ /* if( Cflag )
++ f_print( fout, "extern \"C\"{\n");
++*/
++ return_type(proc);
++ f_print(fout, "* \n");
++ if (Cflag)
++ pvname_svc(proc->proc_name, vp->vers_num);
++ else
++ pvname(proc->proc_name, vp->vers_num);
++ printarglist(proc, RQSTP, "struct svc_req *");
++
++ f_print(fout, "{\n");
++ f_print(fout, "\n\tstatic ");
++ if (!streq(proc->res_type, "void"))
++ return_type(proc);
++ else
++ f_print(fout, "char*"); /* cannot have void type */
++ /* f_print(fout, " result;\n", proc->res_type); */
++ f_print(fout, " result;\n");
++ f_print(fout,
++ "\n\t/*\n\t * insert server code here\n\t */\n\n");
++ if (!streq(proc->res_type, "void"))
++ f_print(fout, "\treturn(&result);\n}\n");
++ else /* cast back to void * */
++ f_print(fout, "\treturn((void*) &result);\n}\n");
++ /* if( Cflag)
++ f_print( fout, "};\n");
++*/
++
++ }
++ }
++}
++
++
++
++static void
++return_type(proc_list *plist)
++{
++ ptype( plist->res_prefix, plist->res_type, 1 );
++}
++
++void
++add_sample_msg(void)
++{
++ f_print(fout, "/*\n");
++ f_print(fout, " * This is sample code generated by rpcgen.\n");
++ f_print(fout, " * These are only templates and you can use them\n");
++ f_print(fout, " * as a guideline for developing your own functions.\n");
++ f_print(fout, " */\n\n");
++}
++
++void
++write_sample_clnt_main(void)
++{
++ list *l;
++ definition *def;
++ version_list *vp;
++
++ f_print(fout, "\n\n" );
++ if( Cflag )
++ f_print(fout,"main( int argc, char* argv[] )\n{\n" );
++ else
++ f_print(fout, "main(argc, argv)\nint argc;\nchar *argv[];\n{\n" );
++
++ f_print(fout, "\tchar *host;");
++ f_print(fout, "\n\n\tif(argc < 2) {");
++ f_print(fout, "\n\t\tprintf(\"usage: %%s server_host\\n\", argv[0]);\n" );
++ f_print(fout, "\t\texit(1);\n\t}");
++ f_print(fout, "\n\thost = argv[1];\n");
++
++ for (l = defined; l != NULL; l = l->next) {
++ def = l->val;
++ if (def->def_kind != DEF_PROGRAM) {
++ continue;
++ }
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ f_print( fout, "\t" );
++ pvname(def->def_name, vp->vers_num);
++ f_print( fout, "( host );\n" );
++ }
++ }
++ f_print(fout, "}\n");
++}
+diff --git a/rpcgen/rpc_scan.c b/rpcgen/rpc_scan.c
+new file mode 100644
+index 0000000..f58fa9f
+--- /dev/null
++++ b/rpcgen/rpc_scan.c
+@@ -0,0 +1,474 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI";
++#endif
++
++/*
++ * rpc_scan.c, Scanner for the RPC protocol compiler
++ * Copyright (C) 1987, Sun Microsystems, Inc.
++ */
++#include <stdio.h>
++#include <ctype.h>
++#include <string.h>
++#include "rpc_scan.h"
++#include "rpc_parse.h"
++#include "rpc_util.h"
++
++static void unget_token(token *tokp);
++static void findstrconst(char **str, char **val);
++static void findchrconst(char **str, char **val);
++static void findconst(char **str, char **val);
++static void findkind(char **mark, token *tokp);
++static int cppline(char *line);
++static int directive(char *line);
++static void printdirective(char *line);
++static void docppline(char *line, int *lineno, char **fname);
++
++#define startcomment(where) (where[0] == '/' && where[1] == '*')
++#define endcomment(where) (where[-1] == '*' && where[0] == '/')
++
++static int pushed = 0; /* is a token pushed */
++static token lasttok; /* last token, if pushed */
++
++/*
++ * scan expecting 1 given token
++ */
++void
++scan(tok_kind expect, token *tokp)
++{
++ get_token(tokp);
++ if (tokp->kind != expect) {
++ expected1(expect);
++ }
++}
++
++/*
++ * scan expecting any of the 2 given tokens
++ */
++void
++scan2(tok_kind expect1, tok_kind expect2, token *tokp)
++{
++ get_token(tokp);
++ if (tokp->kind != expect1 && tokp->kind != expect2) {
++ expected2(expect1, expect2);
++ }
++}
++
++/*
++ * scan expecting any of the 3 given token
++ */
++void
++scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp)
++{
++ get_token(tokp);
++ if (tokp->kind != expect1 && tokp->kind != expect2
++ && tokp->kind != expect3) {
++ expected3(expect1, expect2, expect3);
++ }
++}
++
++/*
++ * scan expecting a constant, possibly symbolic
++ */
++void
++scan_num(token *tokp)
++{
++ get_token(tokp);
++ switch (tokp->kind) {
++ case TOK_IDENT:
++ break;
++ default:
++ error("constant or identifier expected");
++ }
++}
++
++/*
++ * Peek at the next token
++ */
++void
++peek(token *tokp)
++{
++ get_token(tokp);
++ unget_token(tokp);
++}
++
++/*
++ * Peek at the next token and scan it if it matches what you expect
++ */
++int
++peekscan(tok_kind expect, token *tokp)
++{
++ peek(tokp);
++ if (tokp->kind == expect) {
++ get_token(tokp);
++ return (1);
++ }
++ return (0);
++}
++
++/*
++ * Get the next token, printing out any directive that are encountered.
++ */
++void
++get_token(token *tokp)
++{
++ int commenting;
++
++ if (pushed) {
++ pushed = 0;
++ *tokp = lasttok;
++ return;
++ }
++ commenting = 0;
++ for (;;) {
++ if (*where == 0) {
++ for (;;) {
++ if (!fgets(curline, MAXLINESIZE, fin)) {
++ tokp->kind = TOK_EOF;
++ *where = 0;
++ return;
++ }
++ linenum++;
++ if (commenting) {
++ break;
++ } else if (cppline(curline)) {
++ docppline(curline, &linenum,
++ &infilename);
++ } else if (directive(curline)) {
++ printdirective(curline);
++ } else {
++ break;
++ }
++ }
++ where = curline;
++ } else if (isspace(*where)) {
++ while (isspace(*where)) {
++ where++; /* eat */
++ }
++ } else if (commenting) {
++ for (where++; *where; where++) {
++ if (endcomment(where)) {
++ where++;
++ commenting--;
++ break;
++ }
++ }
++ } else if (startcomment(where)) {
++ where += 2;
++ commenting++;
++ } else {
++ break;
++ }
++ }
++
++ /*
++ * 'where' is not whitespace, comment or directive Must be a token!
++ */
++ switch (*where) {
++ case ':':
++ tokp->kind = TOK_COLON;
++ where++;
++ break;
++ case ';':
++ tokp->kind = TOK_SEMICOLON;
++ where++;
++ break;
++ case ',':
++ tokp->kind = TOK_COMMA;
++ where++;
++ break;
++ case '=':
++ tokp->kind = TOK_EQUAL;
++ where++;
++ break;
++ case '*':
++ tokp->kind = TOK_STAR;
++ where++;
++ break;
++ case '[':
++ tokp->kind = TOK_LBRACKET;
++ where++;
++ break;
++ case ']':
++ tokp->kind = TOK_RBRACKET;
++ where++;
++ break;
++ case '{':
++ tokp->kind = TOK_LBRACE;
++ where++;
++ break;
++ case '}':
++ tokp->kind = TOK_RBRACE;
++ where++;
++ break;
++ case '(':
++ tokp->kind = TOK_LPAREN;
++ where++;
++ break;
++ case ')':
++ tokp->kind = TOK_RPAREN;
++ where++;
++ break;
++ case '<':
++ tokp->kind = TOK_LANGLE;
++ where++;
++ break;
++ case '>':
++ tokp->kind = TOK_RANGLE;
++ where++;
++ break;
++
++ case '"':
++ tokp->kind = TOK_STRCONST;
++ findstrconst(&where, &tokp->str);
++ break;
++ case '\'':
++ tokp->kind = TOK_CHARCONST;
++ findchrconst(&where, &tokp->str);
++ break;
++
++ case '-':
++ case '0':
++ case '1':
++ case '2':
++ case '3':
++ case '4':
++ case '5':
++ case '6':
++ case '7':
++ case '8':
++ case '9':
++ tokp->kind = TOK_IDENT;
++ findconst(&where, &tokp->str);
++ break;
++
++ default:
++ if (!(isalpha(*where) || *where == '_')) {
++ char buf[100];
++ char *p;
++
++ s_print(buf, "illegal character in file: ");
++ p = buf + strlen(buf);
++ if (isprint(*where)) {
++ s_print(p, "%c", *where);
++ } else {
++ s_print(p, "%d", *where);
++ }
++ error(buf);
++ }
++ findkind(&where, tokp);
++ break;
++ }
++}
++
++static void
++unget_token(token *tokp)
++{
++ lasttok = *tokp;
++ pushed = 1;
++}
++
++static void
++findstrconst(char **str, char **val)
++{
++ char *p;
++ int size;
++
++ p = *str;
++ do {
++ *p++;
++ } while (*p && *p != '"');
++ if (*p == 0) {
++ error("unterminated string constant");
++ }
++ p++;
++ size = p - *str;
++ *val = alloc(size + 1);
++ (void) strncpy(*val, *str, size);
++ (*val)[size] = 0;
++ *str = p;
++}
++
++static void
++findchrconst(char **str, char **val)
++{
++ char *p;
++ int size;
++
++ p = *str;
++ do {
++ *p++;
++ } while (*p && *p != '\'');
++ if (*p == 0) {
++ error("unterminated string constant");
++ }
++ p++;
++ size = p - *str;
++ if (size != 3) {
++ error("empty char string");
++ }
++ *val = alloc(size + 1);
++ (void) strncpy(*val, *str, size);
++ (*val)[size] = 0;
++ *str = p;
++}
++
++static void
++findconst(char **str, char **val)
++{
++ char *p;
++ int size;
++
++ p = *str;
++ if (*p == '0' && *(p + 1) == 'x') {
++ p++;
++ do {
++ p++;
++ } while (isxdigit(*p));
++ } else {
++ do {
++ p++;
++ } while (isdigit(*p));
++ }
++ size = p - *str;
++ *val = alloc(size + 1);
++ (void) strncpy(*val, *str, size);
++ (*val)[size] = 0;
++ *str = p;
++}
++
++static token symbols[] = {
++ {TOK_CONST, "const"},
++ {TOK_UNION, "union"},
++ {TOK_SWITCH, "switch"},
++ {TOK_CASE, "case"},
++ {TOK_DEFAULT, "default"},
++ {TOK_STRUCT, "struct"},
++ {TOK_TYPEDEF, "typedef"},
++ {TOK_ENUM, "enum"},
++ {TOK_OPAQUE, "opaque"},
++ {TOK_BOOL, "bool"},
++ {TOK_VOID, "void"},
++ {TOK_CHAR, "char"},
++ {TOK_INT, "int"},
++ {TOK_UNSIGNED, "unsigned"},
++ {TOK_SHORT, "short"},
++ {TOK_INT32, "int32"},
++ {TOK_FLOAT, "float"},
++ {TOK_DOUBLE, "double"},
++ {TOK_STRING, "string"},
++ {TOK_PROGRAM, "program"},
++ {TOK_VERSION, "version"},
++ {TOK_EOF, "??????"},
++};
++
++static void
++findkind(char **mark, token *tokp)
++{
++ int len;
++ token *s;
++ char *str;
++
++ str = *mark;
++ for (s = symbols; s->kind != TOK_EOF; s++) {
++ len = strlen(s->str);
++ if (strncmp(str, s->str, len) == 0) {
++ if (!isalnum(str[len]) && str[len] != '_') {
++ tokp->kind = s->kind;
++ tokp->str = s->str;
++ *mark = str + len;
++ return;
++ }
++ }
++ }
++ tokp->kind = TOK_IDENT;
++ for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
++ tokp->str = alloc(len + 1);
++ (void) strncpy(tokp->str, str, len);
++ tokp->str[len] = 0;
++ *mark = str + len;
++}
++
++static int
++cppline(char *line)
++{
++ return (line == curline && *line == '#');
++}
++
++static int
++directive(char *line)
++{
++ return (line == curline && *line == '%');
++}
++
++static void
++printdirective(char *line)
++{
++ f_print(fout, "%s", line + 1);
++}
++
++static void
++docppline(char *line, int *lineno, char **fname)
++{
++ char *file;
++ int num;
++ char *p;
++
++ line++;
++ while (isspace(*line)) {
++ line++;
++ }
++ num = atoi(line);
++ while (isdigit(*line)) {
++ line++;
++ }
++ while (isspace(*line)) {
++ line++;
++ }
++ if (*line != '"') {
++ error("preprocessor error");
++ }
++ line++;
++ p = file = alloc(strlen(line) + 1);
++ while (*line && *line != '"') {
++ *p++ = *line++;
++ }
++ if (*line == 0) {
++ error("preprocessor error");
++ }
++ *p = 0;
++ if (*file == 0) {
++ *fname = NULL;
++ free(file);
++ } else {
++ *fname = file;
++ }
++ *lineno = num - 1;
++}
+diff --git a/rpcgen/rpc_scan.h b/rpcgen/rpc_scan.h
+new file mode 100644
+index 0000000..16f688c
+--- /dev/null
++++ b/rpcgen/rpc_scan.h
+@@ -0,0 +1,103 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++/* @(#)rpc_scan.h 1.3 90/08/29 (C) 1987 SMI */
++
++/*
++ * rpc_scan.h, Definitions for the RPCL scanner
++ */
++
++/*
++ * kinds of tokens
++ */
++enum tok_kind {
++ TOK_IDENT,
++ TOK_CHARCONST,
++ TOK_STRCONST,
++ TOK_LPAREN,
++ TOK_RPAREN,
++ TOK_LBRACE,
++ TOK_RBRACE,
++ TOK_LBRACKET,
++ TOK_RBRACKET,
++ TOK_LANGLE,
++ TOK_RANGLE,
++ TOK_STAR,
++ TOK_COMMA,
++ TOK_EQUAL,
++ TOK_COLON,
++ TOK_SEMICOLON,
++ TOK_CONST,
++ TOK_STRUCT,
++ TOK_UNION,
++ TOK_SWITCH,
++ TOK_CASE,
++ TOK_DEFAULT,
++ TOK_ENUM,
++ TOK_TYPEDEF,
++ TOK_INT,
++ TOK_SHORT,
++ TOK_INT32,
++ TOK_UNSIGNED,
++ TOK_FLOAT,
++ TOK_DOUBLE,
++ TOK_OPAQUE,
++ TOK_CHAR,
++ TOK_STRING,
++ TOK_BOOL,
++ TOK_VOID,
++ TOK_PROGRAM,
++ TOK_VERSION,
++ TOK_EOF
++};
++typedef enum tok_kind tok_kind;
++
++/*
++ * a token
++ */
++struct token {
++ tok_kind kind;
++ char *str;
++};
++typedef struct token token;
++
++
++/*
++ * routine interface
++ */
++void scan();
++void scan2();
++void scan3();
++void scan_num();
++void peek();
++int peekscan();
++void get_token();
++void expected1(tok_kind);
++void expected2(tok_kind, tok_kind);
++void expected3(tok_kind, tok_kind, tok_kind);
++
+diff --git a/rpcgen/rpc_svcout.c b/rpcgen/rpc_svcout.c
+new file mode 100644
+index 0000000..284a529
+--- /dev/null
++++ b/rpcgen/rpc_svcout.c
+@@ -0,0 +1,882 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++ static char sccsid[] = "@(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI";
++#endif
++
++/*
++ * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
++ */
++#include <stdio.h>
++#include <string.h>
++#include "rpc_parse.h"
++#include "rpc_util.h"
++#include "rpc_output.h"
++
++static void write_real_program(definition *def);
++static void write_program(definition *def, char *storage);
++static void printerr(char *err, char *transp);
++static void printif(char *proc, char *transp, char *prefix, char *arg);
++static void write_inetmost(char *infile);
++static void print_return(char *space);
++static void print_pmapunset(char *space);
++static void print_err_message(char *space);
++static void write_timeout_func(void);
++static void write_pm_most(char *infile, int netflag);
++static void write_rpc_svc_fg(char *infile, char *sp);
++static void open_log_file(char *infile, char *sp);
++
++static char RQSTP[] = "rqstp";
++static char TRANSP[] = "transp";
++static char ARG[] = "argument";
++static char RESULT[] = "result";
++static char ROUTINE[] = "local";
++
++char _errbuf[256]; /* For all messages */
++
++static void
++p_xdrfunc(char *rname, char *typename)
++{
++ if (Cflag)
++ f_print(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n", rname,
++ stringfix(typename));
++ else
++ f_print(fout, "\t\txdr_%s = xdr_%s;\n", rname, stringfix(typename));
++}
++
++void
++internal_proctype(proc_list *plist)
++{
++ f_print(fout, "static ");
++ ptype( plist->res_prefix, plist->res_type, 1 );
++ f_print( fout, "*" );
++}
++
++
++/*
++ * write most of the service, that is, everything but the registrations.
++ */
++void
++write_most(char *infile, int netflag, int nomain)
++{
++ if (inetdflag || pmflag) {
++ char* var_type;
++ var_type = (nomain? "extern" : "static");
++ f_print(fout, "%s int _rpcpmstart;", var_type );
++ f_print(fout, "\t\t/* Started by a port monitor ? */\n");
++ f_print(fout, "%s int _rpcfdtype;", var_type );
++ f_print(fout, "\t\t/* Whether Stream or Datagram ? */\n");
++ if (timerflag) {
++ f_print(fout, "%s int _rpcsvcdirty;", var_type );
++ f_print(fout, "\t/* Still serving ? */\n");
++ }
++ write_svc_aux( nomain );
++ }
++ /* write out dispatcher and stubs */
++ write_programs( nomain? (char *)NULL : "static" );
++
++ if( nomain )
++ return;
++
++ f_print(fout, "\nmain()\n");
++ f_print(fout, "{\n");
++ if (inetdflag) {
++ write_inetmost(infile); /* Includes call to write_rpc_svc_fg() */
++ } else {
++ if( tirpcflag ) {
++ if (netflag) {
++ f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
++ f_print(fout, "\tstruct netconfig *nconf = NULL;\n");
++ }
++ f_print(fout, "\tpid_t pid;\n");
++ f_print(fout, "\tint i;\n");
++ f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n");
++ write_pm_most(infile, netflag);
++ f_print(fout, "\telse {\n");
++ write_rpc_svc_fg(infile, "\t\t");
++ f_print(fout, "\t}\n");
++ } else {
++ f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
++ f_print(fout, "\n");
++ print_pmapunset("\t");
++ }
++ }
++
++ if (logflag && !inetdflag) {
++ open_log_file(infile, "\t");
++ }
++}
++
++/*
++ * write a registration for the given transport
++ */
++void
++write_netid_register(char *transp)
++{
++ list *l;
++ definition *def;
++ version_list *vp;
++ char *sp;
++ char tmpbuf[32];
++
++ sp = "";
++ f_print(fout, "\n");
++ f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp);
++ f_print(fout, "%s\tif (nconf == NULL) {\n", sp);
++ (void) sprintf(_errbuf, "cannot find %s netid.", transp);
++ sprintf(tmpbuf, "%s\t\t", sp);
++ print_err_message(tmpbuf);
++ f_print(fout, "%s\t\texit(1);\n", sp);
++ f_print(fout, "%s\t}\n", sp);
++ f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n",
++ sp, TRANSP);
++ f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
++ (void) sprintf(_errbuf, "cannot create %s service.", transp);
++ print_err_message(tmpbuf);
++ f_print(fout, "%s\t\texit(1);\n", sp);
++ f_print(fout, "%s\t}\n", sp);
++
++ for (l = defined; l != NULL; l = l->next) {
++ def = (definition *) l->val;
++ if (def->def_kind != DEF_PROGRAM) {
++ continue;
++ }
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ f_print(fout,
++ "%s\t(void) rpcb_unset(%s, %s, nconf);\n",
++ sp, def->def_name, vp->vers_name);
++ f_print(fout,
++ "%s\tif (!svc_reg(%s, %s, %s, ",
++ sp, TRANSP, def->def_name, vp->vers_name);
++ pvname(def->def_name, vp->vers_num);
++ f_print(fout, ", nconf)) {\n");
++ (void) sprintf(_errbuf, "unable to register (%s, %s, %s).",
++ def->def_name, vp->vers_name, transp);
++ print_err_message(tmpbuf);
++ f_print(fout, "%s\t\texit(1);\n", sp);
++ f_print(fout, "%s\t}\n", sp);
++ }
++ }
++ f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp);
++}
++
++/*
++ * write a registration for the given transport for TLI
++ */
++void
++write_nettype_register(char *transp)
++{
++ list *l;
++ definition *def;
++ version_list *vp;
++
++ for (l = defined; l != NULL; l = l->next) {
++ def = (definition *) l->val;
++ if (def->def_kind != DEF_PROGRAM) {
++ continue;
++ }
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ f_print(fout, "\tif (!svc_create(");
++ pvname(def->def_name, vp->vers_num);
++ f_print(fout, ", %s, %s, \"%s\")) {\n ",
++ def->def_name, vp->vers_name, transp);
++ (void) sprintf(_errbuf,
++ "unable to create (%s, %s) for %s.",
++ def->def_name, vp->vers_name, transp);
++ print_err_message("\t\t");
++ f_print(fout, "\t\texit(1);\n");
++ f_print(fout, "\t}\n");
++ }
++ }
++}
++
++/*
++ * write the rest of the service
++ */
++void
++write_rest(void)
++{
++ f_print(fout, "\n");
++ if (inetdflag) {
++ f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP);
++ (void) sprintf(_errbuf, "could not create a handle");
++ print_err_message("\t\t");
++ f_print(fout, "\t\texit(1);\n");
++ f_print(fout, "\t}\n");
++ if (timerflag) {
++ f_print(fout, "\tif (_rpcpmstart) {\n");
++ f_print(fout,
++ "\t\t(void) signal(SIGALRM, %s closedown);\n",
++ Cflag? "(SIG_PF)" : "(void(*)())" );
++ f_print(fout, "\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
++ f_print(fout, "\t}\n");
++ }
++ }
++ f_print(fout, "\tsvc_run();\n");
++ (void) sprintf(_errbuf, "svc_run returned");
++ print_err_message("\t");
++ f_print(fout, "\texit(1);\n");
++ f_print(fout, "\t/* NOTREACHED */\n");
++ f_print(fout, "}\n");
++}
++
++void
++write_programs(char *storage)
++{
++ list *l;
++ definition *def;
++
++ /* write out stubs for procedure definitions */
++ for (l = defined; l != NULL; l = l->next) {
++ def = (definition *) l->val;
++ if (def->def_kind == DEF_PROGRAM) {
++ write_real_program(def);
++ }
++ }
++
++ /* write out dispatcher for each program */
++ for (l = defined; l != NULL; l = l->next) {
++ def = (definition *) l->val;
++ if (def->def_kind == DEF_PROGRAM) {
++ write_program(def, storage);
++ }
++ }
++
++
++}
++
++/* write out definition of internal function (e.g. _printmsg_1(...))
++ which calls server's defintion of actual function (e.g. printmsg_1(...)).
++ Unpacks single user argument of printmsg_1 to call-by-value format
++ expected by printmsg_1. */
++static void
++write_real_program(definition *def)
++{
++ version_list *vp;
++ proc_list *proc;
++ decl_list *l;
++
++ if( !newstyle ) return; /* not needed for old style */
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ for (proc = vp->procs; proc != NULL; proc = proc->next) {
++ f_print(fout, "\n");
++ internal_proctype(proc);
++ f_print(fout, "\n_");
++ pvname(proc->proc_name, vp->vers_num);
++ if( Cflag ) {
++ f_print(fout, "(" );
++ /* arg name */
++ if (proc->arg_num > 1)
++ f_print(fout, proc->args.argname);
++ else
++ ptype(proc->args.decls->decl.prefix,
++ proc->args.decls->decl.type, 0);
++ f_print(fout, " *argp, struct svc_req *%s)\n",
++ RQSTP);
++ } else {
++ f_print(fout, "(argp, %s)\n", RQSTP );
++ /* arg name */
++ if (proc->arg_num > 1)
++ f_print(fout, "\t%s *argp;\n", proc->args.argname);
++ else {
++ f_print(fout, "\t");
++ ptype(proc->args.decls->decl.prefix,
++ proc->args.decls->decl.type, 0);
++ f_print(fout, " *argp;\n");
++ }
++ f_print(fout, " struct svc_req *%s;\n", RQSTP);
++ }
++
++ f_print(fout, "{\n");
++ f_print(fout, "\treturn(");
++ if( Cflag )
++ pvname_svc(proc->proc_name, vp->vers_num);
++ else
++ pvname(proc->proc_name, vp->vers_num);
++ f_print(fout, "(");
++ if (proc->arg_num < 2) { /* single argument */
++ if (!streq( proc->args.decls->decl.type, "void"))
++ f_print(fout, "*argp, "); /* non-void */
++ } else {
++ for (l = proc->args.decls; l != NULL; l = l->next)
++ f_print(fout, "argp->%s, ", l->decl.name);
++ }
++ f_print(fout, "%s));\n}\n", RQSTP);
++ }
++ }
++}
++
++static void
++write_program(definition *def, char *storage)
++{
++ version_list *vp;
++ proc_list *proc;
++ int filled;
++
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ f_print(fout, "\n");
++ if (storage != NULL) {
++ f_print(fout, "%s ", storage);
++ }
++ f_print(fout, "void\n");
++ pvname(def->def_name, vp->vers_num);
++
++ if (Cflag) {
++ f_print(fout, "(struct svc_req *%s, ", RQSTP);
++ f_print(fout, "register SVCXPRT *%s)\n", TRANSP);
++ } else {
++ f_print(fout, "(%s, %s)\n", RQSTP, TRANSP);
++ f_print(fout, " struct svc_req *%s;\n", RQSTP);
++ f_print(fout, " register SVCXPRT *%s;\n", TRANSP);
++ }
++
++ f_print(fout, "{\n");
++
++ filled = 0;
++ f_print(fout, "\tunion {\n");
++ for (proc = vp->procs; proc != NULL; proc = proc->next) {
++ if (proc->arg_num < 2) { /* single argument */
++ if (streq(proc->args.decls->decl.type,
++ "void")) {
++ continue;
++ }
++ filled = 1;
++ f_print(fout, "\t\t");
++ ptype(proc->args.decls->decl.prefix,
++ proc->args.decls->decl.type, 0);
++ pvname(proc->proc_name, vp->vers_num);
++ f_print(fout, "_arg;\n");
++
++ }
++ else {
++ filled = 1;
++ f_print(fout, "\t\t%s", proc->args.argname);
++ f_print(fout, " ");
++ pvname(proc->proc_name, vp->vers_num);
++ f_print(fout, "_arg;\n");
++ }
++ }
++ if (!filled) {
++ f_print(fout, "\t\tint fill;\n");
++ }
++ f_print(fout, "\t} %s;\n", ARG);
++ f_print(fout, "\tchar *%s;\n", RESULT);
++
++ if (Cflag) {
++ f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT);
++ f_print(fout,
++ "\tchar *(*%s)(char *, struct svc_req *);\n",
++ ROUTINE);
++ } else {
++ f_print(fout, "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", ARG, RESULT);
++ f_print(fout, "\tchar *(*%s)();\n", ROUTINE);
++ }
++
++ f_print(fout, "\n");
++
++ if (timerflag)
++ f_print(fout, "\t_rpcsvcdirty = 1;\n");
++ f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
++ if (!nullproc(vp->procs)) {
++ f_print(fout, "\tcase NULLPROC:\n");
++ f_print(fout,
++ "\t\t(void) svc_sendreply(%s, (xdrproc_t) xdr_void, (char *)NULL);\n",
++ TRANSP);
++ print_return("\t\t");
++ f_print(fout, "\n");
++ }
++ for (proc = vp->procs; proc != NULL; proc = proc->next) {
++ f_print(fout, "\tcase %s:\n", proc->proc_name);
++ if (proc->arg_num < 2) { /* single argument */
++ p_xdrfunc( ARG, proc->args.decls->decl.type);
++ } else {
++ p_xdrfunc( ARG, proc->args.argname);
++ }
++ p_xdrfunc( RESULT, proc->res_type);
++ if( Cflag )
++ f_print(fout,
++ "\t\t%s = (char *(*)(char *, struct svc_req *)) ",
++ ROUTINE);
++ else
++ f_print(fout, "\t\t%s = (char *(*)()) ", ROUTINE);
++
++ if (newstyle) { /* new style: calls internal routine */
++ f_print(fout,"_");
++ }
++ /* Not sure about the following...
++ * rpc_hout always generates foobar_1_svc for
++ * the service procedure, so why should we use
++ * foobar_1 here?! --okir */
++#if 0
++ if( Cflag && !newstyle )
++ pvname_svc(proc->proc_name, vp->vers_num);
++ else
++ pvname(proc->proc_name, vp->vers_num);
++#else
++ pvname_svc(proc->proc_name, vp->vers_num);
++#endif
++ f_print(fout, ";\n");
++ f_print(fout, "\t\tbreak;\n\n");
++ }
++ f_print(fout, "\tdefault:\n");
++ printerr("noproc", TRANSP);
++ print_return("\t\t");
++ f_print(fout, "\t}\n");
++
++ f_print(fout, "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", ARG, ARG);
++ if (Cflag)
++ printif("getargs", TRANSP, "(caddr_t) &", ARG);
++ else
++ printif("getargs", TRANSP, "&", ARG);
++ printerr("decode", TRANSP);
++ print_return("\t\t");
++ f_print(fout, "\t}\n");
++
++ if (Cflag)
++ f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n",
++ RESULT, ROUTINE, ARG, RQSTP);
++ else
++ f_print(fout, "\t%s = (*%s)(&%s, %s);\n",
++ RESULT, ROUTINE, ARG, RQSTP);
++ f_print(fout,
++ "\tif (%s != NULL && !svc_sendreply(%s, "
++ "(xdrproc_t) xdr_%s, %s)) {\n",
++ RESULT, TRANSP, RESULT, RESULT);
++ printerr("systemerr", TRANSP);
++ f_print(fout, "\t}\n");
++
++ if (Cflag)
++ printif("freeargs", TRANSP, "(caddr_t) &", ARG);
++ else
++ printif("freeargs", TRANSP, "&", ARG);
++ (void) sprintf(_errbuf, "unable to free arguments");
++ print_err_message("\t\t");
++ f_print(fout, "\t\texit(1);\n");
++ f_print(fout, "\t}\n");
++ print_return("\t");
++ f_print(fout, "}\n");
++ }
++}
++
++static void
++printerr(char *err, char *transp)
++{
++ f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
++}
++
++static void
++printif(char *proc, char *transp, char *prefix, char *arg)
++{
++ f_print(fout, "\tif (!svc_%s(%s, (xdrproc_t) xdr_%s, (caddr_t) %s%s)) {\n",
++ proc, transp, arg, prefix, arg);
++}
++
++int
++nullproc(proc_list *proc)
++{
++ for (; proc != NULL; proc = proc->next) {
++ if (streq(proc->proc_num, "0")) {
++ return (1);
++ }
++ }
++ return (0);
++}
++
++static void
++write_inetmost(char *infile)
++{
++ f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
++ f_print(fout, "\tint sock;\n");
++ f_print(fout, "\tint proto;\n");
++ f_print(fout, "\tstruct sockaddr_in saddr;\n");
++ f_print(fout, "\tint asize = sizeof (saddr);\n");
++ f_print(fout, "\n");
++ f_print(fout,
++ "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
++ f_print(fout, "\t\tint ssize = sizeof (int);\n\n");
++ f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n");
++ f_print(fout, "\t\t\texit(1);\n");
++ f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
++ f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n");
++ f_print(fout, "\t\t\texit(1);\n");
++ f_print(fout, "\t\tsock = 0;\n");
++ f_print(fout, "\t\t_rpcpmstart = 1;\n");
++ f_print(fout, "\t\tproto = 0;\n");
++ open_log_file(infile, "\t\t");
++ f_print(fout, "\t} else {\n");
++ write_rpc_svc_fg(infile, "\t\t");
++ f_print(fout, "\t\tsock = RPC_ANYSOCK;\n");
++ print_pmapunset("\t\t");
++ f_print(fout, "\t}\n");
++}
++
++static void
++print_return(char *space)
++{
++ if (exitnow)
++ f_print(fout, "%sexit(0);\n", space);
++ else {
++ if (timerflag)
++ f_print(fout, "%s_rpcsvcdirty = 0;\n", space);
++ f_print(fout, "%sreturn;\n", space);
++ }
++}
++
++static void
++print_pmapunset(char *space)
++{
++ list *l;
++ definition *def;
++ version_list *vp;
++
++ for (l = defined; l != NULL; l = l->next) {
++ def = (definition *) l->val;
++ if (def->def_kind == DEF_PROGRAM) {
++ for (vp = def->def.pr.versions; vp != NULL;
++ vp = vp->next) {
++ f_print(fout, "%s(void) pmap_unset(%s, %s);\n",
++ space, def->def_name, vp->vers_name);
++ }
++ }
++ }
++}
++
++static void
++print_err_message(char *space)
++{
++ if (logflag)
++ f_print(fout, "%ssyslog(LOG_ERR, \"%s\");\n", space, _errbuf);
++ else if (inetdflag || pmflag)
++ f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf);
++ else
++ f_print(fout, "%sfprintf(stderr, \"%s\");\n", space, _errbuf);
++}
++
++/*
++ * Write the server auxiliary function ( _msgout, timeout)
++ */
++void
++write_svc_aux(int nomain)
++{
++ if (!logflag)
++ write_msg_out();
++ if( !nomain )
++ write_timeout_func();
++}
++
++/*
++ * Write the _msgout function
++ */
++void
++write_msg_out(void)
++{
++ f_print(fout, "\n");
++ f_print(fout, "static\n");
++ if( !Cflag ) {
++ f_print(fout, "void _msgout(msg)\n");
++ f_print(fout, "\tchar *msg;\n");
++ } else {
++ f_print(fout, "void _msgout(char* msg)\n");
++ }
++ f_print(fout, "{\n");
++ f_print(fout, "#ifdef RPC_SVC_FG\n");
++ if (inetdflag || pmflag)
++ f_print(fout, "\tif (_rpcpmstart)\n");
++ f_print(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n");
++ f_print(fout, "\telse\n");
++ f_print(fout, "\t\t(void) fprintf(stderr, \"%%s\\n\", msg);\n");
++ f_print(fout, "#else\n");
++ f_print(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n");
++ f_print(fout, "#endif\n");
++ f_print(fout, "}\n");
++}
++
++/*
++ * Write the timeout function
++ */
++static void
++write_timeout_func(void)
++{
++ if (!timerflag)
++ return;
++ f_print(fout, "\n");
++ f_print(fout, "static void\n");
++ f_print(fout, "closedown()\n");
++ f_print(fout, "{\n");
++ f_print(fout, "\tif (_rpcsvcdirty == 0) {\n");
++ f_print(fout, "\t\tstatic int size;\n");
++ f_print(fout, "\t\tint i, openfd;\n");
++ if (tirpcflag && pmflag) {
++ f_print(fout, "\t\tstruct t_info tinfo;\n\n");
++ f_print(fout, "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n");
++ } else {
++ f_print(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n");
++ }
++ f_print(fout, "\t\t\texit(0);\n");
++ f_print(fout, "\t\tif (size == 0) {\n");
++ if( tirpcflag ) {
++ f_print(fout, "\t\t\tstruct rlimit rl;\n\n");
++ f_print(fout, "\t\t\trl.rlim_max = 0;\n");
++ f_print(fout, "\t\t\tgetrlimit(RLIMIT_NOFILE, &rl);\n");
++ f_print(fout, "\t\t\tif ((size = rl.rlim_max) == 0)\n");
++ f_print(fout, "\t\t\t\treturn;\n");
++ } else {
++ f_print(fout, "\t\t\tsize = getdtablesize();\n");
++ }
++ f_print(fout, "\t\t}\n");
++ f_print(fout, "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n");
++ f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
++ f_print(fout, "\t\t\t\topenfd++;\n");
++ f_print(fout, "\t\tif (openfd <= 1)\n");
++ f_print(fout, "\t\t\texit(0);\n");
++ f_print(fout, "\t}\n");
++ f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
++ f_print(fout, "}\n");
++}
++
++/*
++ * Write the most of port monitor support
++ */
++static void
++write_pm_most(char *infile, int netflag)
++{
++ list *l;
++ definition *def;
++ version_list *vp;
++
++ f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n");
++ f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||");
++ f_print(fout, " !strcmp(mname, \"timod\"))) {\n");
++ f_print(fout, "\t\tchar *netid;\n");
++ if (!netflag) { /* Not included by -n option */
++ f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n");
++ f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP);
++ }
++ if( timerflag )
++ f_print(fout, "\t\tint pmclose;\n");
++/* not necessary, defined in /usr/include/stdlib */
++/* f_print(fout, "\t\textern char *getenv();\n");*/
++ f_print(fout, "\n");
++ f_print(fout, "\t\t_rpcpmstart = 1;\n");
++ if (logflag)
++ open_log_file(infile, "\t\t");
++ f_print(fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n");
++ sprintf(_errbuf, "cannot get transport name");
++ print_err_message("\t\t\t");
++ f_print(fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n");
++ sprintf(_errbuf, "cannot get transport info");
++ print_err_message("\t\t\t");
++ f_print(fout, "\t\t}\n");
++ /*
++ * A kludgy support for inetd services. Inetd only works with
++ * sockmod, and RPC works only with timod, hence all this jugglery
++ */
++ f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n");
++ f_print(fout, "\t\t\tif (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, \"timod\")) {\n");
++ sprintf(_errbuf, "could not get the right module");
++ print_err_message("\t\t\t\t");
++ f_print(fout, "\t\t\t\texit(1);\n");
++ f_print(fout, "\t\t\t}\n");
++ f_print(fout, "\t\t}\n");
++ if( timerflag )
++ f_print(fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
++ f_print(fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n",
++ TRANSP);
++ sprintf(_errbuf, "cannot create server handle");
++ print_err_message("\t\t\t");
++ f_print(fout, "\t\t\texit(1);\n");
++ f_print(fout, "\t\t}\n");
++ f_print(fout, "\t\tif (nconf)\n");
++ f_print(fout, "\t\t\tfreenetconfigent(nconf);\n");
++ for (l = defined; l != NULL; l = l->next) {
++ def = (definition *) l->val;
++ if (def->def_kind != DEF_PROGRAM) {
++ continue;
++ }
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ f_print(fout,
++ "\t\tif (!svc_reg(%s, %s, %s, ",
++ TRANSP, def->def_name, vp->vers_name);
++ pvname(def->def_name, vp->vers_num);
++ f_print(fout, ", 0)) {\n");
++ (void) sprintf(_errbuf, "unable to register (%s, %s).",
++ def->def_name, vp->vers_name);
++ print_err_message("\t\t\t");
++ f_print(fout, "\t\t\texit(1);\n");
++ f_print(fout, "\t\t}\n");
++ }
++ }
++ if (timerflag) {
++ f_print(fout, "\t\tif (pmclose) {\n");
++ f_print(fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n",
++ Cflag? "(SIG_PF)" : "(void(*)())" );
++ f_print(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
++ f_print(fout, "\t\t}\n");
++ }
++ f_print(fout, "\t\tsvc_run();\n");
++ f_print(fout, "\t\texit(1);\n");
++ f_print(fout, "\t\t/* NOTREACHED */\n");
++ f_print(fout, "\t}\n");
++}
++
++/*
++ * Support for backgrounding the server if self started.
++ */
++static void
++write_rpc_svc_fg(char *infile, char *sp)
++{
++ f_print(fout, "#ifndef RPC_SVC_FG\n");
++ f_print(fout, "%sint size;\n", sp);
++ if( tirpcflag )
++ f_print(fout, "%sstruct rlimit rl;\n", sp);
++ if (inetdflag)
++ f_print(fout, "%sint pid, i;\n\n", sp);
++ f_print(fout, "%spid = fork();\n", sp);
++ f_print(fout, "%sif (pid < 0) {\n", sp);
++ f_print(fout, "%s\tperror(\"cannot fork\");\n", sp);
++ f_print(fout, "%s\texit(1);\n", sp);
++ f_print(fout, "%s}\n", sp);
++ f_print(fout, "%sif (pid)\n", sp);
++ f_print(fout, "%s\texit(0);\n", sp);
++ /* get number of file descriptors */
++ if( tirpcflag ) {
++ f_print(fout, "%srl.rlim_max = 0;\n", sp);
++ f_print(fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp);
++ f_print(fout, "%sif ((size = rl.rlim_max) == 0)\n", sp);
++ f_print(fout, "%s\texit(1);\n", sp);
++ } else {
++ f_print(fout, "%ssize = getdtablesize();\n", sp);
++ }
++
++ f_print(fout, "%sfor (i = 0; i < size; i++)\n", sp);
++ f_print(fout, "%s\t(void) close(i);\n", sp);
++ /* Redirect stderr and stdout to console */
++ f_print(fout, "%si = open(\"/dev/console\", 2);\n", sp);
++ f_print(fout, "%s(void) dup2(i, 1);\n", sp);
++ f_print(fout, "%s(void) dup2(i, 2);\n", sp);
++ /* This removes control of the controlling terminal */
++ if( tirpcflag )
++ f_print(fout, "%ssetsid();\n", sp);
++ else {
++ f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp);
++ f_print(fout, "%sif (i >= 0) {\n", sp);
++ f_print(fout, "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);;
++ f_print(fout, "%s\t(void) close(i);\n", sp);
++ f_print(fout, "%s}\n", sp);
++ }
++ if (!logflag)
++ open_log_file(infile, sp);
++ f_print(fout, "#endif\n");
++ if (logflag)
++ open_log_file(infile, sp);
++}
++
++static void
++open_log_file(char *infile, char *sp)
++{
++ char *s;
++
++ s = strrchr(infile, '.');
++ if (s)
++ *s = '\0';
++ f_print(fout,"%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile);
++ if (s)
++ *s = '.';
++}
++
++
++
++
++/*
++ * write a registration for the given transport for Inetd
++ */
++void
++write_inetd_register(char *transp)
++{
++ list *l;
++ definition *def;
++ version_list *vp;
++ char *sp;
++ int isudp;
++ char tmpbuf[32];
++
++ if (inetdflag)
++ sp = "\t";
++ else
++ sp = "";
++ if (streq(transp, "udp"))
++ isudp = 1;
++ else
++ isudp = 0;
++ f_print(fout, "\n");
++ if (inetdflag) {
++ f_print(fout, "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n",
++ isudp ? "SOCK_DGRAM" : "SOCK_STREAM");
++ }
++ f_print(fout, "%s\t%s = svc%s_create(%s",
++ sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK");
++ if (!isudp)
++ f_print(fout, ", 0, 0");
++ f_print(fout, ");\n");
++ f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
++ (void) sprintf(_errbuf, "cannot create %s service.", transp);
++ (void) sprintf(tmpbuf, "%s\t\t", sp);
++ print_err_message(tmpbuf);
++ f_print(fout, "%s\t\texit(1);\n", sp);
++ f_print(fout, "%s\t}\n", sp);
++
++ if (inetdflag) {
++ f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp);
++ f_print(fout, "%s\tproto = IPPROTO_%s;\n",
++ sp, isudp ? "UDP": "TCP");
++ }
++ for (l = defined; l != NULL; l = l->next) {
++ def = (definition *) l->val;
++ if (def->def_kind != DEF_PROGRAM) {
++ continue;
++ }
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ f_print(fout, "%s\tif (!svc_register(%s, %s, %s, ",
++ sp, TRANSP, def->def_name, vp->vers_name);
++ pvname(def->def_name, vp->vers_num);
++ if (inetdflag)
++ f_print(fout, ", proto)) {\n");
++ else
++ f_print(fout, ", IPPROTO_%s)) {\n",
++ isudp ? "UDP": "TCP");
++ (void) sprintf(_errbuf, "unable to register (%s, %s, %s).",
++ def->def_name, vp->vers_name, transp);
++ print_err_message(tmpbuf);
++ f_print(fout, "%s\t\texit(1);\n", sp);
++ f_print(fout, "%s\t}\n", sp);
++ }
++ }
++ if (inetdflag)
++ f_print(fout, "\t}\n");
++}
+diff --git a/rpcgen/rpc_tblout.c b/rpcgen/rpc_tblout.c
+new file mode 100644
+index 0000000..ae002f7
+--- /dev/null
++++ b/rpcgen/rpc_tblout.c
+@@ -0,0 +1,165 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++static char sccsid[] = "@(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI";
++#endif
++
++/*
++ * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler
++ */
++#include <stdio.h>
++#include <string.h>
++#include "rpc_parse.h"
++#include "rpc_util.h"
++#include "rpc_output.h"
++
++static void write_table(definition *def);
++static void printit(char *prefix, char *type);
++
++#define TABSIZE 8
++#define TABCOUNT 5
++#define TABSTOP (TABSIZE*TABCOUNT)
++
++static char tabstr[TABCOUNT+1] = "\t\t\t\t\t";
++
++static char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n";
++static char tbl_end[] = "};\n";
++
++static char null_entry[] = "\n\t(char *(*)())0,\n\
++ \t(xdrproc_t) xdr_void,\t\t\t0,\n\
++ \t(xdrproc_t) xdr_void,\t\t\t0,\n";
++
++
++static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n";
++
++void
++write_tables(void)
++{
++ list *l;
++ definition *def;
++
++ f_print(fout, "\n");
++ for (l = defined; l != NULL; l = l->next) {
++ def = (definition *) l->val;
++ if (def->def_kind == DEF_PROGRAM) {
++ write_table(def);
++ }
++ }
++}
++
++static void
++write_table(definition *def)
++{
++ version_list *vp;
++ proc_list *proc;
++ int current;
++ int expected;
++ char progvers[100];
++ int warning;
++
++ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
++ warning = 0;
++ s_print(progvers, "%s_%s",
++ locase(def->def_name), vp->vers_num);
++ /* print the table header */
++ f_print(fout, tbl_hdr, progvers);
++
++ if (nullproc(vp->procs)) {
++ expected = 0;
++ } else {
++ expected = 1;
++ f_print(fout, null_entry);
++ }
++ for (proc = vp->procs; proc != NULL; proc = proc->next) {
++ current = atoi(proc->proc_num);
++ if (current != expected++) {
++ f_print(fout,
++ "\n/*\n * WARNING: table out of order\n */\n");
++ if (warning == 0) {
++ f_print(stderr,
++ "WARNING %s table is out of order\n",
++ progvers);
++ warning = 1;
++ nonfatalerrors = 1;
++ }
++ expected = current + 1;
++ }
++ f_print(fout, "\n\t(char *(*)())RPCGEN_ACTION(");
++
++ /* routine to invoke */
++ if( Cflag && !newstyle )
++ pvname_svc(proc->proc_name, vp->vers_num);
++ else {
++ if( newstyle )
++ f_print( fout, "_"); /* calls internal func */
++ pvname(proc->proc_name, vp->vers_num);
++ }
++ f_print(fout, "),\n");
++
++ /* argument info */
++ if( proc->arg_num > 1 )
++ printit((char*) NULL, proc->args.argname );
++ else
++ /* do we have to do something special for newstyle */
++ printit( proc->args.decls->decl.prefix,
++ proc->args.decls->decl.type );
++ /* result info */
++ printit(proc->res_prefix, proc->res_type);
++ }
++
++ /* print the table trailer */
++ f_print(fout, tbl_end);
++ f_print(fout, tbl_nproc, progvers, progvers, progvers);
++ }
++}
++
++static void
++printit(char *prefix, char *type)
++{
++ int len;
++ int tabs;
++
++
++ len = fprintf(fout, "\txdr_%s,", stringfix(type));
++ /* account for leading tab expansion */
++ len += TABSIZE - 1;
++ /* round up to tabs required */
++ tabs = (TABSTOP - len + TABSIZE - 1)/TABSIZE;
++ f_print(fout, "%s", &tabstr[TABCOUNT-tabs]);
++
++ if (streq(type, "void")) {
++ f_print(fout, "0");
++ } else {
++ f_print(fout, "sizeof ( ");
++ /* XXX: should "follow" be 1 ??? */
++ ptype(prefix, type, 0);
++ f_print(fout, ")");
++ }
++ f_print(fout, ",\n");
++}
+diff --git a/rpcgen/rpc_util.c b/rpcgen/rpc_util.c
+new file mode 100644
+index 0000000..b67be57
+--- /dev/null
++++ b/rpcgen/rpc_util.c
+@@ -0,0 +1,479 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++static char sccsid[] = "@(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI";
++#endif
++
++/*
++ * rpc_util.c, Utility routines for the RPC protocol compiler
++ */
++#include <stdio.h>
++#include <memory.h>
++#include <ctype.h>
++#include <unistd.h>
++#include "rpc_scan.h"
++#include "rpc_parse.h"
++#include "rpc_util.h"
++
++static void printwhere(void);
++
++
++#define ARGEXT "argument"
++
++char curline[MAXLINESIZE]; /* current read line */
++char *where = curline; /* current point in line */
++int linenum = 0; /* current line number */
++
++char *infilename; /* input filename */
++
++#define NFILES 7
++char *outfiles[NFILES]; /* output file names */
++int nfiles;
++
++FILE *fout; /* file pointer of current output */
++FILE *fin; /* file pointer of current input */
++
++list *defined; /* list of defined things */
++
++/*
++ * Reinitialize the world
++ */
++void
++reinitialize(void)
++{
++ memset(curline, 0, MAXLINESIZE);
++ where = curline;
++ linenum = 0;
++ defined = NULL;
++}
++
++/*
++ * string equality
++ */
++int
++streq(char *a, char *b)
++{
++ return (strcmp(a, b) == 0);
++}
++
++/*
++ * find a value in a list
++ */
++definition *
++findval(list *lst, char *val, int (*cmp)(definition *, char *))
++{
++
++ for (; lst != NULL; lst = lst->next) {
++ if ((*cmp) (lst->val, val)) {
++ return (lst->val);
++ }
++ }
++ return (NULL);
++}
++
++/*
++ * store a value in a list
++ */
++void
++storeval(lstp, val)
++ list **lstp;
++ definition *val;
++{
++ list **l;
++ list *lst;
++
++
++ for (l = lstp; *l != NULL; l = (list **) & (*l)->next);
++ lst = ALLOC(list);
++ lst->val = val;
++ lst->next = NULL;
++ *l = lst;
++}
++
++static int
++findit(definition *def, char *type)
++{
++ return (streq(def->def_name, type));
++}
++
++static char *
++fixit(char *type, char *orig)
++{
++ definition *def;
++
++ def = (definition *) FINDVAL(defined, type, findit);
++ if (def == NULL || def->def_kind != DEF_TYPEDEF) {
++ return (orig);
++ }
++ switch (def->def.ty.rel) {
++ case REL_VECTOR:
++ return (def->def.ty.old_type);
++ case REL_ALIAS:
++ return (fixit(def->def.ty.old_type, orig));
++ default:
++ return (orig);
++ }
++}
++
++char *
++fixtype(char *type)
++{
++ return (fixit(type, type));
++}
++
++char *
++stringfix(char *type)
++{
++ if (streq(type, "string")) {
++ return ("wrapstring");
++ } else {
++ return (type);
++ }
++}
++
++void
++ptype(char *prefix, char *type, int follow)
++{
++ if (prefix != NULL) {
++ if (streq(prefix, "enum")) {
++ f_print(fout, "enum ");
++ } else {
++ f_print(fout, "struct ");
++ }
++ }
++ if (streq(type, "bool")) {
++ f_print(fout, "bool_t ");
++ } else if (streq(type, "string")) {
++ f_print(fout, "char *");
++ } else {
++ f_print(fout, "%s ", follow ? fixtype(type) : type);
++ }
++}
++
++static int
++typedefed(definition *def, char *type)
++{
++ if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) {
++ return (0);
++ } else {
++ return (streq(def->def_name, type));
++ }
++}
++
++int
++isvectordef(char *type, relation rel)
++{
++ definition *def;
++
++ for (;;) {
++ switch (rel) {
++ case REL_VECTOR:
++ return (!streq(type, "string"));
++ case REL_ARRAY:
++ return (0);
++ case REL_POINTER:
++ return (0);
++ case REL_ALIAS:
++ def = (definition *) FINDVAL(defined, type, typedefed);
++ if (def == NULL) {
++ return (0);
++ }
++ type = def->def.ty.old_type;
++ rel = def->def.ty.rel;
++ }
++ }
++}
++
++char *
++locase(char *str)
++{
++ char c;
++ static char buf[100];
++ char *p = buf;
++
++ while ((c = *str++) != '\0') {
++ *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
++ }
++ *p = 0;
++ return (buf);
++}
++
++void
++pvname_svc(char *pname, char *vnum)
++{
++ f_print(fout, "%s_%s_svc", locase(pname), vnum);
++}
++
++void
++pvname(char *pname, char *vnum)
++{
++ f_print(fout, "%s_%s", locase(pname), vnum);
++}
++
++/*
++ * print a useful (?) error message, and then die
++ */
++void
++error(char *msg)
++{
++ printwhere();
++ f_print(stderr, "%s, line %d: ", infilename, linenum);
++ f_print(stderr, "%s\n", msg);
++ crash();
++}
++
++/*
++ * Something went wrong, unlink any files that we may have created and then
++ * die.
++ */
++void
++crash(void)
++{
++ int i;
++
++ for (i = 0; i < nfiles; i++) {
++ (void) unlink(outfiles[i]);
++ }
++ exit(1);
++}
++
++void
++record_open(char *file)
++{
++ if (nfiles < NFILES) {
++ outfiles[nfiles++] = file;
++ } else {
++ f_print(stderr, "too many files!\n");
++ crash();
++ }
++}
++
++static char expectbuf[100];
++static char *toktostr();
++
++/*
++ * error, token encountered was not the expected one
++ */
++void
++expected1(exp1)
++ tok_kind exp1;
++{
++ s_print(expectbuf, "expected '%s'",
++ toktostr(exp1));
++ error(expectbuf);
++}
++
++/*
++ * error, token encountered was not one of two expected ones
++ */
++void
++expected2(exp1, exp2)
++ tok_kind exp1, exp2;
++{
++ s_print(expectbuf, "expected '%s' or '%s'",
++ toktostr(exp1),
++ toktostr(exp2));
++ error(expectbuf);
++}
++
++/*
++ * error, token encountered was not one of 3 expected ones
++ */
++void
++expected3(exp1, exp2, exp3)
++ tok_kind exp1, exp2, exp3;
++{
++ s_print(expectbuf, "expected '%s', '%s' or '%s'",
++ toktostr(exp1),
++ toktostr(exp2),
++ toktostr(exp3));
++ error(expectbuf);
++}
++
++void
++tabify(f, tab)
++ FILE *f;
++ int tab;
++{
++ while (tab--) {
++ (void) fputc('\t', f);
++ }
++}
++
++
++static token tokstrings[] = {
++ {TOK_IDENT, "identifier"},
++ {TOK_CONST, "const"},
++ {TOK_RPAREN, ")"},
++ {TOK_LPAREN, "("},
++ {TOK_RBRACE, "}"},
++ {TOK_LBRACE, "{"},
++ {TOK_LBRACKET, "["},
++ {TOK_RBRACKET, "]"},
++ {TOK_STAR, "*"},
++ {TOK_COMMA, ","},
++ {TOK_EQUAL, "="},
++ {TOK_COLON, ":"},
++ {TOK_SEMICOLON, ";"},
++ {TOK_UNION, "union"},
++ {TOK_STRUCT, "struct"},
++ {TOK_SWITCH, "switch"},
++ {TOK_CASE, "case"},
++ {TOK_DEFAULT, "default"},
++ {TOK_ENUM, "enum"},
++ {TOK_TYPEDEF, "typedef"},
++ {TOK_INT, "int"},
++ {TOK_SHORT, "short"},
++ {TOK_INT32, "int32"},
++ {TOK_UNSIGNED, "unsigned"},
++ {TOK_DOUBLE, "double"},
++ {TOK_FLOAT, "float"},
++ {TOK_CHAR, "char"},
++ {TOK_STRING, "string"},
++ {TOK_OPAQUE, "opaque"},
++ {TOK_BOOL, "bool"},
++ {TOK_VOID, "void"},
++ {TOK_PROGRAM, "program"},
++ {TOK_VERSION, "version"},
++ {TOK_EOF, "??????"}
++};
++
++static char *
++toktostr(kind)
++ tok_kind kind;
++{
++ token *sp;
++
++ for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++);
++ return (sp->str);
++}
++
++static void
++printbuf(void)
++{
++ char c;
++ int i;
++ int cnt;
++
++# define TABSIZE 4
++
++ for (i = 0; (c = curline[i]) != '\0'; i++) {
++ if (c == '\t') {
++ cnt = 8 - (i % TABSIZE);
++ c = ' ';
++ } else {
++ cnt = 1;
++ }
++ while (cnt--) {
++ (void) fputc(c, stderr);
++ }
++ }
++}
++
++static void
++printwhere(void)
++{
++ int i;
++ char c;
++ int cnt;
++
++ printbuf();
++ for (i = 0; i < where - curline; i++) {
++ c = curline[i];
++ if (c == '\t') {
++ cnt = 8 - (i % TABSIZE);
++ } else {
++ cnt = 1;
++ }
++ while (cnt--) {
++ (void) fputc('^', stderr);
++ }
++ }
++ (void) fputc('\n', stderr);
++}
++
++char *
++make_argname(char *pname, char *vname)
++{
++ char *name;
++
++ name = malloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3);
++ if (!name) {
++ fprintf(stderr, "failed in malloc");
++ exit(1);
++ }
++ sprintf(name, "%s_%s_%s", locase(pname), vname, ARGEXT);
++ return(name);
++}
++
++bas_type *typ_list_h;
++bas_type *typ_list_t;
++
++void
++add_type(int len, char *type)
++{
++ bas_type *ptr;
++
++
++ if ((ptr = (bas_type *) malloc(sizeof(bas_type))) == (bas_type *) NULL) {
++ fprintf(stderr, "failed in malloc");
++ exit(1);
++ }
++ ptr->name = type;
++ ptr->length = len;
++ ptr->next = NULL;
++ if (typ_list_t == NULL) {
++
++ typ_list_t = ptr;
++ typ_list_h = ptr;
++ } else {
++
++ typ_list_t->next = ptr;
++ typ_list_t = ptr;
++ }
++}
++
++
++bas_type *
++find_type(char *type)
++{
++ bas_type *ptr;
++
++ ptr = typ_list_h;
++
++
++ while (ptr != NULL) {
++ if (strcmp(ptr->name, type) == 0)
++ return (ptr);
++ else
++ ptr = ptr->next;
++ };
++ return (NULL);
++}
++
+diff --git a/rpcgen/rpc_util.h b/rpcgen/rpc_util.h
+new file mode 100644
+index 0000000..fa115be
+--- /dev/null
++++ b/rpcgen/rpc_util.h
+@@ -0,0 +1,166 @@
++/*
++ * Copyright (c) 2009, Sun Microsystems, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of Sun Microsystems, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++/* @(#)rpc_util.h 1.5 90/08/29 (C) 1987 SMI */
++
++/*
++ * rpc_util.h, Useful definitions for the RPC protocol compiler
++ */
++
++#include <stdlib.h>
++
++#define alloc(size) malloc((unsigned)(size))
++#define ALLOC(object) (object *) malloc(sizeof(object))
++
++#define s_print (void) sprintf
++#define f_print (void) fprintf
++
++struct list {
++ definition *val;
++ struct list *next;
++};
++typedef struct list list;
++
++#define PUT 1
++#define GET 2
++
++/*
++ * Global variables
++ */
++#define MAXLINESIZE 1024
++extern char curline[MAXLINESIZE];
++extern char *where;
++extern int linenum;
++
++extern char *infilename;
++extern FILE *fout;
++extern FILE *fin;
++
++extern list *defined;
++
++
++extern bas_type *typ_list_h;
++extern bas_type *typ_list_t;
++
++/*
++ * All the option flags
++ */
++extern int inetdflag;
++extern int pmflag;
++extern int tblflag;
++extern int logflag;
++extern int newstyle;
++extern int Cflag; /* C++ flag */
++extern int tirpcflag; /* flag for generating tirpc code */
++extern int Inline; /* if this is 0, then do not generate inline code */
++
++/*
++ * Other flags related with inetd jumpstart.
++ */
++extern int indefinitewait;
++extern int exitnow;
++extern int timerflag;
++
++extern int nonfatalerrors;
++
++/*
++ * rpc_util routines
++ */
++void storeval();
++
++#define STOREVAL(list,item) \
++ storeval(list,item)
++
++definition *findval();
++
++#define FINDVAL(list,item,finder) \
++ findval(list, item, finder)
++
++
++/*
++ * rpc_cout routines
++ */
++void cprint(void);
++void emit(definition *);
++
++/*
++ * rpc_hout routines
++ */
++void print_datadef(definition *);
++void print_funcdef(definition *);
++
++/*
++ * rpc_svcout routines
++ */
++void write_most(char *, int, int);
++void write_register(void);
++void write_netid_register(char *);
++void write_nettype_register(char *);
++void write_inetd_register(char *);
++void write_rest(void);
++void write_programs(char *);
++void write_svc_aux(int);
++
++/*
++ * rpc_clntout routines
++ */
++void write_stubs(void);
++void printarglist(proc_list *, char *, char *);
++
++/*
++ * rpc_tblout routines
++ */
++void write_tables(void);
++
++/*
++ * rpc_util
++ */
++void pvname_svc(char *, char *);
++void pvname(char *, char *);
++void ptype(char *, char *, int);
++char * make_argname(char *, char *);
++void add_type(int, char *);
++void reinitialize(void);
++void crash(void);
++void error(char *);
++char *fixtype(char *);
++char *stringfix(char *);
++char *locase(char *);
++int isvectordef(char *, relation);
++int streq(char *, char *);
++void tabify(FILE *, int);
++void record_open(char *);
++bas_type *find_type(char *type);
++
++/*
++ * rpc_sample
++ */
++void write_sample_svc(definition *);
++int write_sample_clnt(definition *);
++void write_sample_clnt_main(void);
++void add_sample_msg(void);
+diff --git a/rpcgen/rpcgen.1 b/rpcgen/rpcgen.1
+new file mode 100644
+index 0000000..89df7ed
+--- /dev/null
++++ b/rpcgen/rpcgen.1
+@@ -0,0 +1,521 @@
++.\" @(#)rpcgen.1 1.35 93/06/02 SMI
++.\" $FreeBSD: src/usr.bin/rpcgen/rpcgen.1,v 1.12.2.4 2002/06/21 15:28:50 charnier Exp $
++.\" Copyright 1985-1993 Sun Microsystems, Inc.
++.Dd March 28, 1993
++.Dt RPCGEN 1
++.Os
++.Sh NAME
++.Nm rpcgen
++.Nd an RPC protocol compiler
++.Sh SYNOPSIS
++.Nm
++.Ar infile
++.Nm
++.Op Fl a
++.Op Fl b
++.Op Fl C
++.Oo
++.Fl D Ns Ar name Ns Op Ar =value
++.Oc
++.Op Fl i Ar size
++.Op Fl I Op Fl K Ar seconds
++.Op Fl L
++.Op Fl M
++.Op Fl N
++.Op Fl T
++.Op Fl Y Ar pathname
++.Ar infile
++.Nm
++.Oo
++.Fl c |
++.Fl h |
++.Fl l |
++.Fl m |
++.Fl t |
++.Fl \&Sc |
++.Fl \&Ss |
++.Fl \&Sm
++.Oc
++.Op Fl o Ar outfile
++.Op Ar infile
++.Nm
++.Op Fl s Ar nettype
++.Op Fl o Ar outfile
++.Op Ar infile
++.Nm
++.Op Fl n Ar netid
++.Op Fl o Ar outfile
++.Op Ar infile
++.\" .SH AVAILABILITY
++.\" .LP
++.\" SUNWcsu
++.Sh DESCRIPTION
++The
++.Nm
++utility is a tool that generates C code to implement an
++.Tn RPC
++protocol.
++The input to
++.Nm
++is a language similar to C known as
++.Tn RPC
++Language (Remote Procedure Call Language).
++.Pp
++The
++.Nm
++utility is normally used as in the first synopsis where
++it takes an input file and generates three output files.
++If the
++.Ar infile
++is named
++.Pa proto.x ,
++then
++.Nm
++generates a header in
++.Pa proto.h ,
++XDR routines in
++.Pa proto_xdr.c ,
++server-side stubs in
++.Pa proto_svc.c ,
++and client-side stubs in
++.Pa proto_clnt.c .
++With the
++.Fl T
++option,
++it also generates the
++.Tn RPC
++dispatch table in
++.Pa proto_tbl.i .
++.Pp
++The
++.Nm
++utility can also generate sample client and server files
++that can be customized to suit a particular application.
++The
++.Fl \&Sc ,
++.Fl \&Ss
++and
++.Fl \&Sm
++options generate sample client, server and makefile, respectively.
++The
++.Fl a
++option generates all files, including sample files.
++If the
++.Ar infile
++is
++.Pa proto.x ,
++then the client side sample file is written to
++.Pa proto_client.c ,
++the server side sample file to
++.Pa proto_server.c
++and the sample makefile to
++.Pa makefile.proto .
++.Pp
++The server created can be started both by the port monitors
++(for example,
++.Xr inetd 8 )
++or by itself.
++When it is started by a port monitor,
++it creates servers only for the transport for which
++the file descriptor
++.Em 0
++was passed.
++The name of the transport must be specified
++by setting up the environment variable
++.Ev PM_TRANSPORT .
++When the server generated by
++.Nm
++is executed,
++it creates server handles for all the transports
++specified in
++.Ev NETPATH
++environment variable,
++or if it is unset,
++it creates server handles for all the visible transports from
++.Pa /etc/netconfig
++file.
++Note:
++the transports are chosen at run time and not at compile time.
++When the server is self-started,
++it backgrounds itself by default.
++A special define symbol
++.Em RPC_SVC_FG
++can be used to run the server process in foreground.
++.Pp
++The second synopsis provides special features which allow
++for the creation of more sophisticated
++.Tn RPC
++servers.
++These features include support for user provided
++.Em #defines
++and
++.Tn RPC
++dispatch tables.
++The entries in the
++.Tn RPC
++dispatch table contain:
++.Bl -bullet -offset indent -compact
++.It
++pointers to the service routine corresponding to that procedure,
++.It
++a pointer to the input and output arguments,
++.It
++the size of these routines.
++.El
++A server can use the dispatch table to check authorization
++and then to execute the service routine;
++a client library may use it to deal with the details of storage
++management and XDR data conversion.
++.Pp
++The other three synopses shown above are used when
++one does not want to generate all the output files,
++but only a particular one.
++See the
++.Sx EXAMPLES
++section below for examples of
++.Nm
++usage.
++When
++.Nm
++is executed with the
++.Fl s
++option,
++it creates servers for that particular class of transports.
++When
++executed with the
++.Fl n
++option,
++it creates a server for the transport specified by
++.Ar netid .
++If
++.Ar infile
++is not specified,
++.Nm
++accepts the standard input.
++.Pp
++The C preprocessor,
++.Em cc -E
++is run on the input file before it is actually interpreted by
++.Nm .
++For each type of output file,
++.Nm
++defines a special preprocessor symbol for use by the
++.Nm
++programmer:
++.Bl -tag -width indent
++.It RPC_HDR
++defined when compiling into headers
++.It RPC_XDR
++defined when compiling into XDR routines
++.It RPC_SVC
++defined when compiling into server-side stubs
++.It RPC_CLNT
++defined when compiling into client-side stubs
++.It RPC_TBL
++defined when compiling into RPC dispatch tables
++.El
++.Pp
++Any line beginning with
++.Dq %
++is passed directly into the output file,
++uninterpreted by
++.Nm .
++To specify the path name of the C preprocessor use
++.Fl Y
++flag.
++.Pp
++For every data type referred to in
++.Ar infile ,
++.Nm
++assumes that there exists a
++routine with the string
++.Em xdr_
++prepended to the name of the data type.
++If this routine does not exist in the
++.Tn RPC/XDR
++library, it must be provided.
++Providing an undefined data type
++allows customization of
++.Xr xdr 3
++routines.
++.Sh OPTIONS
++The following options are available:
++.Bl -tag -width indent
++.It Fl a
++Generate all files, including sample files.
++.It Fl b
++Backward compatibility mode.
++Generate transport specific
++.Tn RPC
++code for older versions
++of the operating system.
++.Pp
++Note: in
++.Fx ,
++this compatibility flag is turned on by
++default since
++.Fx
++supports only the older
++.Tn ONC RPC
++library.
++.It Fl c
++Compile into
++.Tn XDR
++routines.
++.It Fl C
++Generate header and stub files which can be used with
++.Tn ANSI
++C compilers. Headers generated with this flag can also be
++used with C++ programs.
++.It Fl D Ns Ar name
++.It Fl D Ns Ar name=value
++.\".It Fl D Ns Ar name Ns Op Ar =value
++Define a symbol
++.Ar name .
++Equivalent to the
++.Em #define
++directive in the source.
++If no
++.Ar value
++is given,
++.Ar value
++is defined as
++.Em 1 .
++This option may be specified more than once.
++.It Fl h
++Compile into C data-definitions (a header).
++.Fl T
++option can be used in conjunction to produce a
++header which supports
++.Tn RPC
++dispatch tables.
++.It Fl i Ar size
++Size at which to start generating inline code.
++This option is useful for optimization.
++The default size is 5.
++.Pp
++Note: in order to provide backwards compatibility with the older
++.Nm
++on the
++.Fx
++platform, the default is actually 0 (which means
++that inline code generation is disabled by default). You must specify
++a non-zero value explicitly to override this default.
++.It Fl I
++Compile support for
++.Xr inetd 8
++in the server side stubs.
++Such servers can be self-started or can be started by
++.Nm inetd .
++When the server is self-started, it backgrounds itself by default.
++A special define symbol
++.Em RPC_SVC_FG
++can be used to run the
++server process in foreground, or the user may simply compile without
++the
++.Fl I
++option.
++.Pp
++If there are no pending client requests, the
++.Nm inetd
++servers exit after 120 seconds (default).
++The default can be changed with the
++.Fl K
++option.
++All the error messages for
++.Nm inetd
++servers
++are always logged with
++.Xr syslog 3 .
++.\" .IP
++.\" Note:
++.\" this option is supported for backward compatibility only.
++.\" By default,
++.\" .B rpcgen
++.\" generates servers that can be invoked through portmonitors.
++.Pp
++.It Fl K Ar seconds
++By default, services created using
++.Nm
++and invoked through
++port monitors wait 120 seconds
++after servicing a request before exiting.
++That interval can be changed using the
++.Fl K
++flag.
++To create a server that exits immediately upon servicing a request,
++use
++.Fl K Ar 0 .
++To create a server that never exits, the appropriate argument is
++.Fl k Ar -1 .
++.Pp
++When monitoring for a server,
++some portmonitors
++.Em always
++spawn a new process in response to a service request.
++If it is known that a server will be used with such a monitor, the
++server should exit immediately on completion.
++For such servers,
++.Nm
++should be used with
++.Fl K Ar 0 .
++.It Fl l
++Compile into client-side stubs.
++.It Fl L
++When the servers are started in foreground, use
++.Xr syslog 3
++to log the server errors instead of printing them on the standard
++error.
++.It Fl m
++Compile into server-side stubs,
++but do not generate a
++.Qq main
++routine.
++This option is useful for doing callback-routines
++and for users who need to write their own
++.Qq main
++routine to do initialization.
++.It Fl M
++Generate multithread-safe stubs for passing arguments and results between
++rpcgen generated code and user written code.
++This option is useful
++for users who want to use threads in their code.
++However, the
++.Xr rpc_svc_calls 3
++functions are not yet MT-safe, which means that rpcgen generated server-side
++code will not be MT-safe.
++.It Fl N
++This option allows procedures to have multiple arguments.
++It also uses the style of parameter passing that closely resembles C.
++So, when passing an argument to a remote procedure, you do not have to
++pass a pointer to the argument, but can pass the argument itself.
++This behavior is different from the old style of
++.Nm
++generated code.
++To maintain backward compatibility,
++this option is not the default.
++.It Fl n Ar netid
++Compile into server-side stubs for the transport
++specified by
++.Ar netid .
++There should be an entry for
++.Ar netid
++in the
++netconfig database.
++This option may be specified more than once,
++so as to compile a server that serves multiple transports.
++.It Fl o Ar outfile
++Specify the name of the output file.
++If none is specified,
++standard output is used
++(
++.Fl c ,
++.Fl h ,
++.Fl l ,
++.Fl m ,
++.Fl n ,
++.Fl s ,
++.Fl \&Sc ,
++.Fl \&Sm ,
++.Fl \&Ss ,
++and
++.Fl t
++modes only).
++.It Fl s Ar nettype
++Compile into server-side stubs for all the
++transports belonging to the class
++.Ar nettype .
++The supported classes are
++.Em netpath ,
++.Em visible ,
++.Em circuit_n ,
++.Em circuit_v ,
++.Em datagram_n ,
++.Em datagram_v ,
++.Em tcp ,
++and
++.Em udp
++(see
++.Xr rpc 3
++for the meanings associated with these classes).
++This option may be specified more than once.
++Note:
++the transports are chosen at run time and not at compile time.
++.It Fl \&Sc
++Generate sample client code that uses remote procedure calls.
++.It Fl \&Sm
++Generate a sample
++.Pa Makefile
++which can be used for compiling the application.
++.It Fl \&Ss
++Generate sample server code that uses remote procedure calls.
++.It Fl t
++Compile into
++.Tn RPC
++dispatch table.
++.It Fl T
++Generate the code to support
++.Tn RPC
++dispatch tables.
++.Pp
++The options
++.Fl c ,
++.Fl h ,
++.Fl l ,
++.Fl m ,
++.Fl s ,
++.Fl \&Sc ,
++.Fl \&Sm ,
++.Fl \&Ss ,
++and
++.Fl t
++are used exclusively to generate a particular type of file,
++while the options
++.Fl D
++and
++.Fl T
++are global and can be used with the other options.
++.It Fl Y Ar pathname
++Give the name of the directory where
++.Nm
++will start looking for the C-preprocessor.
++.El
++.Sh EXAMPLES
++The following example:
++.Dl example% rpcgen -T prot.x
++.Pp
++generates all the five files:
++.Pa prot.h ,
++.Pa prot_clnt.c ,
++.Pa prot_svc.c ,
++.Pa prot_xdr.c
++and
++.Pa prot_tbl.i .
++.Pp
++The following example sends the C data-definitions (header)
++to the standard output.
++.Dl example% rpcgen -h prot.x
++.Pp
++To send the test version of the
++.Fl D Ns Ar TEST ,
++server side stubs for
++all the transport belonging to the class
++.Ar datagram_n
++to standard output, use:
++.Dl example% rpcgen -s datagram_n -DTEST prot.x
++.Pp
++To create the server side stubs for the transport indicated
++by
++.Ar netid
++tcp,
++use:
++.Dl example% rpcgen -n tcp -o prot_svc.c prot.x
++.Sh SEE ALSO
++.Xr cc 1 ,
++.Xr rpc 3 ,
++.Xr syslog 3 ,
++.Xr inetd 8
++.\" .BR rpc_svc_calls (3)
++.Rs
++.%T The rpcgen chapter in the NETP manual
++.Re
+--
+1.7.9.5
+
diff --git a/package/libtirpc/libtirpc-0009-Automatically-generate-XDR-header-files-from-.x-sour.patch b/package/libtirpc/libtirpc-0009-Automatically-generate-XDR-header-files-from-.x-sour.patch
new file mode 100644
index 000000000..787452a6d
--- /dev/null
+++ b/package/libtirpc/libtirpc-0009-Automatically-generate-XDR-header-files-from-.x-sour.patch
@@ -0,0 +1,999 @@
+From 30fac06891c59a7fb784f6faa4e92921a84c73db Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Sat, 10 Nov 2012 17:29:53 +0100
+Subject: [PATCH] Automatically generate XDR header files from .x sources
+ using rpcgen
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ Makefile.am | 23 +-
+ src/Makefile.am | 2 +-
+ tirpc/rpc/rpcb_prot.h | 797 -------------------------------------------------
+ tirpc/rpcsvc/crypt.h | 109 -------
+ 4 files changed, 21 insertions(+), 910 deletions(-)
+ delete mode 100644 tirpc/rpc/rpcb_prot.h
+ delete mode 100644 tirpc/rpcsvc/crypt.h
+
+diff --git a/Makefile.am b/Makefile.am
+index afb4e38..7e63f78 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,9 +1,12 @@
+ SUBDIRS = src man doc rpcgen
+ ACLOCAL_AMFLAGS = -I m4
+
++GENFILES = \
++ tirpc/rpcsvc/crypt.h \
++ tirpc/rpc/rpcb_prot.h
++
+ nobase_include_HEADERS = tirpc/netconfig.h \
+ tirpc/rpcsvc/crypt.x \
+- tirpc/rpcsvc/crypt.h \
+ tirpc/rpc/xdr.h \
+ tirpc/rpc/types.h \
+ tirpc/rpc/svc_soc.h \
+@@ -15,7 +18,6 @@ nobase_include_HEADERS = tirpc/netconfig.h \
+ tirpc/rpc/rpcent.h \
+ tirpc/rpc/rpc_com.h \
+ tirpc/rpc/rpcb_prot.x \
+- tirpc/rpc/rpcb_prot.h \
+ tirpc/rpc/rpcb_clnt.h \
+ tirpc/rpc/raw.h \
+ tirpc/rpc/pmap_rmt.h \
+@@ -32,6 +34,21 @@ nobase_include_HEADERS = tirpc/netconfig.h \
+ tirpc/rpc/auth.h \
+ tirpc/rpc/auth_gss.h \
+ tirpc/rpc/auth_des.h
+-
++
++nobase_nodist_include_HEADERS = $(GENFILES)
++
++BUILT_SOURCES = $(GENFILES)
++
+ pkgconfigdir=$(libdir)/pkgconfig
+ pkgconfig_DATA = libtirpc.pc
++
++$(GENFILES): %.h: %.x $(top_builddir)/rpcgen/rpcgen
++ mkdir -p $(dir $@)
++ $(top_builddir)/rpcgen/rpcgen -h -o $@ $<
++
++$(top_builddir)/rpcgen/rpcgen: force
++ cd rpcgen && $(MAKE)
++
++force:
++
++CLEANFILES = $(GENFILES)
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 6dc259e..bd276cf 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -7,7 +7,7 @@
+
+
+ INCLUDES = -I$(top_srcdir)/tirpc -DPORTMAP -DVERSION="\"$(VERSION)\"" \
+- -D_GNU_SOURCE -Wall -pipe
++ -D_GNU_SOURCE -Wall -pipe -I$(top_builddir)/tirpc
+
+ lib_LTLIBRARIES = libtirpc.la
+
+diff --git a/tirpc/rpc/rpcb_prot.h b/tirpc/rpc/rpcb_prot.h
+deleted file mode 100644
+index 7ae48b8..0000000
+--- a/tirpc/rpc/rpcb_prot.h
++++ /dev/null
+@@ -1,797 +0,0 @@
+-/*
+- * Please do not edit this file.
+- * It was generated using rpcgen.
+- */
+-
+-#ifndef _RPCB_PROT_H_RPCGEN
+-#define _RPCB_PROT_H_RPCGEN
+-
+-#include <rpc/rpc.h>
+-
+-#ifndef IXDR_GET_INT32
+-#define IXDR_GET_INT32(buf) IXDR_GET_LONG((buf))
+-#endif
+-#ifndef IXDR_PUT_INT32
+-#define IXDR_PUT_INT32(buf, v) IXDR_PUT_LONG((buf), (v))
+-#endif
+-#ifndef IXDR_GET_U_INT32
+-#define IXDR_GET_U_INT32(buf) IXDR_GET_U_LONG((buf))
+-#endif
+-#ifndef IXDR_PUT_U_INT32
+-#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_U_LONG((buf), (v))
+-#endif
+-/*
+- * $FreeBSD: src/include/rpc/rpcb_prot.x,v 1.3 2002/03/13 10:29:06 obrien Exp $
+- *
+- * Copyright (c) 2009, Sun Microsystems, Inc.
+- * All rights reserved.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions are met:
+- * - Redistributions of source code must retain the above copyright notice,
+- * this list of conditions and the following disclaimer.
+- * - Redistributions in binary form must reproduce the above copyright notice,
+- * this list of conditions and the following disclaimer in the documentation
+- * and/or other materials provided with the distribution.
+- * - Neither the name of Sun Microsystems, Inc. nor the names of its
+- * contributors may be used to endorse or promote products derived
+- * from this software without specific prior written permission.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+- * POSSIBILITY OF SUCH DAMAGE.
+- */
+-/*
+- * Copyright (c) 1988 by Sun Microsystems, Inc.
+- */
+-/* from rpcb_prot.x */
+-
+-/* #pragma ident "@(#)rpcb_prot.x 1.5 94/04/29 SMI" */
+-
+-#ifndef _KERNEL
+-
+-
+-/*
+- * The following procedures are supported by the protocol in version 3:
+- *
+- * RPCBPROC_NULL() returns ()
+- * takes nothing, returns nothing
+- *
+- * RPCBPROC_SET(rpcb) returns (bool_t)
+- * TRUE is success, FALSE is failure. Registers the tuple
+- * [prog, vers, address, owner, netid].
+- * Finds out owner and netid information on its own.
+- *
+- * RPCBPROC_UNSET(rpcb) returns (bool_t)
+- * TRUE is success, FALSE is failure. Un-registers tuple
+- * [prog, vers, netid]. addresses is ignored.
+- * If netid is NULL, unregister all.
+- *
+- * RPCBPROC_GETADDR(rpcb) returns (string).
+- * 0 is failure. Otherwise returns the universal address where the
+- * triple [prog, vers, netid] is registered. Ignore address and owner.
+- *
+- * RPCBPROC_DUMP() RETURNS (rpcblist_ptr)
+- * used to dump the entire rpcbind maps
+- *
+- * RPCBPROC_CALLIT(rpcb_rmtcallargs)
+- * RETURNS (rpcb_rmtcallres);
+- * Calls the procedure on the remote machine. If it is not registered,
+- * this procedure is quiet; i.e. it does not return error information!!!
+- * This routine only passes null authentication parameters.
+- * It has no interface to xdr routines for RPCBPROC_CALLIT.
+- *
+- * RPCBPROC_GETTIME() returns (int).
+- * Gets the remote machines time
+- *
+- * RPCBPROC_UADDR2TADDR(strint) RETURNS (struct netbuf)
+- * Returns the netbuf address from universal address.
+- *
+- * RPCBPROC_TADDR2UADDR(struct netbuf) RETURNS (string)
+- * Returns the universal address from netbuf address.
+- *
+- * END OF RPCBIND VERSION 3 PROCEDURES
+- */
+-/*
+- * Except for RPCBPROC_CALLIT, the procedures above are carried over to
+- * rpcbind version 4. Those below are added or modified for version 4.
+- * NOTE: RPCBPROC_BCAST HAS THE SAME FUNCTIONALITY AND PROCEDURE NUMBER
+- * AS RPCBPROC_CALLIT.
+- *
+- * RPCBPROC_BCAST(rpcb_rmtcallargs)
+- * RETURNS (rpcb_rmtcallres);
+- * Calls the procedure on the remote machine. If it is not registered,
+- * this procedure IS quiet; i.e. it DOES NOT return error information!!!
+- * This routine should be used for broadcasting and nothing else.
+- *
+- * RPCBPROC_GETVERSADDR(rpcb) returns (string).
+- * 0 is failure. Otherwise returns the universal address where the
+- * triple [prog, vers, netid] is registered. Ignore address and owner.
+- * Same as RPCBPROC_GETADDR except that if the given version number
+- * is not available, the address is not returned.
+- *
+- * RPCBPROC_INDIRECT(rpcb_rmtcallargs)
+- * RETURNS (rpcb_rmtcallres);
+- * Calls the procedure on the remote machine. If it is not registered,
+- * this procedure is NOT quiet; i.e. it DOES return error information!!!
+- * as any normal application would expect.
+- *
+- * RPCBPROC_GETADDRLIST(rpcb) returns (rpcb_entry_list_ptr).
+- * Same as RPCBPROC_GETADDR except that it returns a list of all the
+- * addresses registered for the combination (prog, vers) (for all
+- * transports).
+- *
+- * RPCBPROC_GETSTAT(void) returns (rpcb_stat_byvers)
+- * Returns the statistics about the kind of requests received by rpcbind.
+- */
+-
+-/*
+- * A mapping of (program, version, network ID) to address
+- */
+-
+-struct rpcb {
+- rpcprog_t r_prog;
+- rpcvers_t r_vers;
+- char *r_netid;
+- char *r_addr;
+- char *r_owner;
+-};
+-typedef struct rpcb rpcb;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcb(XDR *, rpcb*);
+-#elif __STDC__
+-extern bool_t xdr_rpcb(XDR *, rpcb*);
+-#else /* Old Style C */
+-bool_t xdr_rpcb();
+-#endif /* Old Style C */
+-
+-
+-typedef rpcb RPCB;
+-
+-
+-/*
+- * A list of mappings
+- *
+- * Below are two definitions for the rpcblist structure. This is done because
+- * xdr_rpcblist() is specified to take a struct rpcblist **, rather than a
+- * struct rpcblist * that rpcgen would produce. One version of the rpcblist
+- * structure (actually called rp__list) is used with rpcgen, and the other is
+- * defined only in the header file for compatibility with the specified
+- * interface.
+- */
+-
+-struct rp__list {
+- rpcb rpcb_map;
+- struct rp__list *rpcb_next;
+-};
+-typedef struct rp__list rp__list;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rp__list(XDR *, rp__list*);
+-#elif __STDC__
+-extern bool_t xdr_rp__list(XDR *, rp__list*);
+-#else /* Old Style C */
+-bool_t xdr_rp__list();
+-#endif /* Old Style C */
+-
+-
+-typedef rp__list *rpcblist_ptr;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcblist_ptr(XDR *, rpcblist_ptr*);
+-#elif __STDC__
+-extern bool_t xdr_rpcblist_ptr(XDR *, rpcblist_ptr*);
+-#else /* Old Style C */
+-bool_t xdr_rpcblist_ptr();
+-#endif /* Old Style C */
+-
+-
+-typedef struct rp__list rpcblist;
+-typedef struct rp__list RPCBLIST;
+-
+-#ifndef __cplusplus
+-struct rpcblist {
+- RPCB rpcb_map;
+- struct rpcblist *rpcb_next;
+-};
+-#endif
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-extern bool_t xdr_rpcblist(XDR *, rpcblist**);
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-
+-/*
+- * Arguments of remote calls
+- */
+-
+-struct rpcb_rmtcallargs {
+- rpcprog_t prog;
+- rpcvers_t vers;
+- rpcproc_t proc;
+- struct {
+- u_int args_len;
+- char *args_val;
+- } args;
+-};
+-typedef struct rpcb_rmtcallargs rpcb_rmtcallargs;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcb_rmtcallargs(XDR *, rpcb_rmtcallargs*);
+-#elif __STDC__
+-extern bool_t xdr_rpcb_rmtcallargs(XDR *, rpcb_rmtcallargs*);
+-#else /* Old Style C */
+-bool_t xdr_rpcb_rmtcallargs();
+-#endif /* Old Style C */
+-
+-
+-/*
+- * Client-side only representation of rpcb_rmtcallargs structure.
+- *
+- * The routine that XDRs the rpcb_rmtcallargs structure must deal with the
+- * opaque arguments in the "args" structure. xdr_rpcb_rmtcallargs() needs to
+- * be passed the XDR routine that knows the args' structure. This routine
+- * doesn't need to go over-the-wire (and it wouldn't make sense anyway) since
+- * the application being called already knows the args structure. So we use a
+- * different "XDR" structure on the client side, r_rpcb_rmtcallargs, which
+- * includes the args' XDR routine.
+- */
+-struct r_rpcb_rmtcallargs {
+- rpcprog_t prog;
+- rpcvers_t vers;
+- rpcproc_t proc;
+- struct {
+- u_int args_len;
+- char *args_val;
+- } args;
+- xdrproc_t xdr_args; /* encodes args */
+-};
+-
+-
+-/*
+- * Results of the remote call
+- */
+-
+-struct rpcb_rmtcallres {
+- char *addr;
+- struct {
+- u_int results_len;
+- char *results_val;
+- } results;
+-};
+-typedef struct rpcb_rmtcallres rpcb_rmtcallres;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcb_rmtcallres(XDR *, rpcb_rmtcallres*);
+-#elif __STDC__
+-extern bool_t xdr_rpcb_rmtcallres(XDR *, rpcb_rmtcallres*);
+-#else /* Old Style C */
+-bool_t xdr_rpcb_rmtcallres();
+-#endif /* Old Style C */
+-
+-
+-/*
+- * Client-side only representation of rpcb_rmtcallres structure.
+- */
+-struct r_rpcb_rmtcallres {
+- char *addr;
+- struct {
+- u_int32_t results_len;
+- char *results_val;
+- } results;
+- xdrproc_t xdr_res; /* decodes results */
+-};
+-
+-/*
+- * rpcb_entry contains a merged address of a service on a particular
+- * transport, plus associated netconfig information. A list of rpcb_entrys
+- * is returned by RPCBPROC_GETADDRLIST. See netconfig.h for values used
+- * in r_nc_* fields.
+- */
+-
+-struct rpcb_entry {
+- char *r_maddr;
+- char *r_nc_netid;
+- u_int r_nc_semantics;
+- char *r_nc_protofmly;
+- char *r_nc_proto;
+-};
+-typedef struct rpcb_entry rpcb_entry;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcb_entry(XDR *, rpcb_entry*);
+-#elif __STDC__
+-extern bool_t xdr_rpcb_entry(XDR *, rpcb_entry*);
+-#else /* Old Style C */
+-bool_t xdr_rpcb_entry();
+-#endif /* Old Style C */
+-
+-
+-/*
+- * A list of addresses supported by a service.
+- */
+-
+-struct rpcb_entry_list {
+- rpcb_entry rpcb_entry_map;
+- struct rpcb_entry_list *rpcb_entry_next;
+-};
+-typedef struct rpcb_entry_list rpcb_entry_list;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcb_entry_list(XDR *, rpcb_entry_list*);
+-#elif __STDC__
+-extern bool_t xdr_rpcb_entry_list(XDR *, rpcb_entry_list*);
+-#else /* Old Style C */
+-bool_t xdr_rpcb_entry_list();
+-#endif /* Old Style C */
+-
+-
+-typedef rpcb_entry_list *rpcb_entry_list_ptr;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcb_entry_list_ptr(XDR *, rpcb_entry_list_ptr*);
+-#elif __STDC__
+-extern bool_t xdr_rpcb_entry_list_ptr(XDR *, rpcb_entry_list_ptr*);
+-#else /* Old Style C */
+-bool_t xdr_rpcb_entry_list_ptr();
+-#endif /* Old Style C */
+-
+-
+-/*
+- * rpcbind statistics
+- */
+-
+-#define rpcb_highproc_2 RPCBPROC_CALLIT
+-#define rpcb_highproc_3 RPCBPROC_TADDR2UADDR
+-#define rpcb_highproc_4 RPCBPROC_GETSTAT
+-#define RPCBSTAT_HIGHPROC 13
+-#define RPCBVERS_STAT 3
+-#define RPCBVERS_4_STAT 2
+-#define RPCBVERS_3_STAT 1
+-#define RPCBVERS_2_STAT 0
+-
+-/* Link list of all the stats about getport and getaddr */
+-
+-struct rpcbs_addrlist {
+- rpcprog_t prog;
+- rpcvers_t vers;
+- int success;
+- int failure;
+- char *netid;
+- struct rpcbs_addrlist *next;
+-};
+-typedef struct rpcbs_addrlist rpcbs_addrlist;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcbs_addrlist(XDR *, rpcbs_addrlist*);
+-#elif __STDC__
+-extern bool_t xdr_rpcbs_addrlist(XDR *, rpcbs_addrlist*);
+-#else /* Old Style C */
+-bool_t xdr_rpcbs_addrlist();
+-#endif /* Old Style C */
+-
+-
+-/* Link list of all the stats about rmtcall */
+-
+-struct rpcbs_rmtcalllist {
+- rpcprog_t prog;
+- rpcvers_t vers;
+- rpcproc_t proc;
+- int success;
+- int failure;
+- int indirect;
+- char *netid;
+- struct rpcbs_rmtcalllist *next;
+-};
+-typedef struct rpcbs_rmtcalllist rpcbs_rmtcalllist;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcbs_rmtcalllist(XDR *, rpcbs_rmtcalllist*);
+-#elif __STDC__
+-extern bool_t xdr_rpcbs_rmtcalllist(XDR *, rpcbs_rmtcalllist*);
+-#else /* Old Style C */
+-bool_t xdr_rpcbs_rmtcalllist();
+-#endif /* Old Style C */
+-
+-
+-typedef int rpcbs_proc[RPCBSTAT_HIGHPROC];
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcbs_proc(XDR *, rpcbs_proc);
+-#elif __STDC__
+-extern bool_t xdr_rpcbs_proc(XDR *, rpcbs_proc);
+-#else /* Old Style C */
+-bool_t xdr_rpcbs_proc();
+-#endif /* Old Style C */
+-
+-
+-typedef rpcbs_addrlist *rpcbs_addrlist_ptr;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcbs_addrlist_ptr(XDR *, rpcbs_addrlist_ptr*);
+-#elif __STDC__
+-extern bool_t xdr_rpcbs_addrlist_ptr(XDR *, rpcbs_addrlist_ptr*);
+-#else /* Old Style C */
+-bool_t xdr_rpcbs_addrlist_ptr();
+-#endif /* Old Style C */
+-
+-
+-typedef rpcbs_rmtcalllist *rpcbs_rmtcalllist_ptr;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcbs_rmtcalllist_ptr(XDR *, rpcbs_rmtcalllist_ptr*);
+-#elif __STDC__
+-extern bool_t xdr_rpcbs_rmtcalllist_ptr(XDR *, rpcbs_rmtcalllist_ptr*);
+-#else /* Old Style C */
+-bool_t xdr_rpcbs_rmtcalllist_ptr();
+-#endif /* Old Style C */
+-
+-
+-struct rpcb_stat {
+- rpcbs_proc info;
+- int setinfo;
+- int unsetinfo;
+- rpcbs_addrlist_ptr addrinfo;
+- rpcbs_rmtcalllist_ptr rmtinfo;
+-};
+-typedef struct rpcb_stat rpcb_stat;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcb_stat(XDR *, rpcb_stat*);
+-#elif __STDC__
+-extern bool_t xdr_rpcb_stat(XDR *, rpcb_stat*);
+-#else /* Old Style C */
+-bool_t xdr_rpcb_stat();
+-#endif /* Old Style C */
+-
+-
+-/*
+- * One rpcb_stat structure is returned for each version of rpcbind
+- * being monitored.
+- */
+-
+-typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT];
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_rpcb_stat_byvers(XDR *, rpcb_stat_byvers);
+-#elif __STDC__
+-extern bool_t xdr_rpcb_stat_byvers(XDR *, rpcb_stat_byvers);
+-#else /* Old Style C */
+-bool_t xdr_rpcb_stat_byvers();
+-#endif /* Old Style C */
+-
+-
+-/*
+- * We don't define netbuf in RPCL, since it would contain structure member
+- * names that would conflict with the definition of struct netbuf in
+- * <tiuser.h>. Instead we merely declare the XDR routine xdr_netbuf() here,
+- * and implement it ourselves in rpc/rpcb_prot.c.
+- */
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_netbuf(XDR *, struct netbuf *);
+-
+-#else /* __STDC__ */
+-extern bool_t xdr_netbuf(XDR *, struct netbuf *);
+-
+-#endif
+-
+-#define RPCBVERS_3 RPCBVERS
+-#define RPCBVERS_4 RPCBVERS4
+-
+-#define _PATH_RPCBINDSOCK "/var/run/rpcbind.sock"
+-
+-#else /* ndef _KERNEL */
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/*
+- * A mapping of (program, version, network ID) to address
+- */
+-struct rpcb {
+- rpcprog_t r_prog; /* program number */
+- rpcvers_t r_vers; /* version number */
+- char *r_netid; /* network id */
+- char *r_addr; /* universal address */
+- char *r_owner; /* owner of the mapping */
+-};
+-typedef struct rpcb RPCB;
+-
+-/*
+- * A list of mappings
+- */
+-struct rpcblist {
+- RPCB rpcb_map;
+- struct rpcblist *rpcb_next;
+-};
+-typedef struct rpcblist RPCBLIST;
+-typedef struct rpcblist *rpcblist_ptr;
+-
+-/*
+- * Remote calls arguments
+- */
+-struct rpcb_rmtcallargs {
+- rpcprog_t prog; /* program number */
+- rpcvers_t vers; /* version number */
+- rpcproc_t proc; /* procedure number */
+- u_int32_t arglen; /* arg len */
+- caddr_t args_ptr; /* argument */
+- xdrproc_t xdr_args; /* XDR routine for argument */
+-};
+-typedef struct rpcb_rmtcallargs rpcb_rmtcallargs;
+-
+-/*
+- * Remote calls results
+- */
+-struct rpcb_rmtcallres {
+- char *addr_ptr; /* remote universal address */
+- u_int32_t resultslen; /* results length */
+- caddr_t results_ptr; /* results */
+- xdrproc_t xdr_results; /* XDR routine for result */
+-};
+-typedef struct rpcb_rmtcallres rpcb_rmtcallres;
+-
+-struct rpcb_entry {
+- char *r_maddr;
+- char *r_nc_netid;
+- unsigned int r_nc_semantics;
+- char *r_nc_protofmly;
+- char *r_nc_proto;
+-};
+-typedef struct rpcb_entry rpcb_entry;
+-
+-/*
+- * A list of addresses supported by a service.
+- */
+-
+-struct rpcb_entry_list {
+- rpcb_entry rpcb_entry_map;
+- struct rpcb_entry_list *rpcb_entry_next;
+-};
+-typedef struct rpcb_entry_list rpcb_entry_list;
+-
+-typedef rpcb_entry_list *rpcb_entry_list_ptr;
+-
+-/*
+- * rpcbind statistics
+- */
+-
+-#define rpcb_highproc_2 RPCBPROC_CALLIT
+-#define rpcb_highproc_3 RPCBPROC_TADDR2UADDR
+-#define rpcb_highproc_4 RPCBPROC_GETSTAT
+-#define RPCBSTAT_HIGHPROC 13
+-#define RPCBVERS_STAT 3
+-#define RPCBVERS_4_STAT 2
+-#define RPCBVERS_3_STAT 1
+-#define RPCBVERS_2_STAT 0
+-
+-/* Link list of all the stats about getport and getaddr */
+-
+-struct rpcbs_addrlist {
+- rpcprog_t prog;
+- rpcvers_t vers;
+- int success;
+- int failure;
+- char *netid;
+- struct rpcbs_addrlist *next;
+-};
+-typedef struct rpcbs_addrlist rpcbs_addrlist;
+-
+-/* Link list of all the stats about rmtcall */
+-
+-struct rpcbs_rmtcalllist {
+- rpcprog_t prog;
+- rpcvers_t vers;
+- rpcproc_t proc;
+- int success;
+- int failure;
+- int indirect;
+- char *netid;
+- struct rpcbs_rmtcalllist *next;
+-};
+-typedef struct rpcbs_rmtcalllist rpcbs_rmtcalllist;
+-
+-typedef int rpcbs_proc[RPCBSTAT_HIGHPROC];
+-
+-typedef rpcbs_addrlist *rpcbs_addrlist_ptr;
+-
+-typedef rpcbs_rmtcalllist *rpcbs_rmtcalllist_ptr;
+-
+-struct rpcb_stat {
+- rpcbs_proc info;
+- int setinfo;
+- int unsetinfo;
+- rpcbs_addrlist_ptr addrinfo;
+- rpcbs_rmtcalllist_ptr rmtinfo;
+-};
+-typedef struct rpcb_stat rpcb_stat;
+-
+-/*
+- * One rpcb_stat structure is returned for each version of rpcbind
+- * being monitored.
+- */
+-
+-typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT];
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* ndef _KERNEL */
+-
+-#define RPCBPROG ((u_int32_t)100000)
+-#define RPCBVERS ((u_int32_t)3)
+-
+-#ifdef __cplusplus
+-#define RPCBPROC_SET ((u_int32_t)1)
+-extern "C" bool_t * rpcbproc_set_3(rpcb *, CLIENT *);
+-extern "C" bool_t * rpcbproc_set_3_svc(rpcb *, struct svc_req *);
+-#define RPCBPROC_UNSET ((u_int32_t)2)
+-extern "C" bool_t * rpcbproc_unset_3(rpcb *, CLIENT *);
+-extern "C" bool_t * rpcbproc_unset_3_svc(rpcb *, struct svc_req *);
+-#define RPCBPROC_GETADDR ((u_int32_t)3)
+-extern "C" char ** rpcbproc_getaddr_3(rpcb *, CLIENT *);
+-extern "C" char ** rpcbproc_getaddr_3_svc(rpcb *, struct svc_req *);
+-#define RPCBPROC_DUMP ((u_int32_t)4)
+-extern "C" rpcblist_ptr * rpcbproc_dump_3(void *, CLIENT *);
+-extern "C" rpcblist_ptr * rpcbproc_dump_3_svc(void *, struct svc_req *);
+-#define RPCBPROC_CALLIT ((u_int32_t)5)
+-extern "C" rpcb_rmtcallres * rpcbproc_callit_3(rpcb_rmtcallargs *, CLIENT *);
+-extern "C" rpcb_rmtcallres * rpcbproc_callit_3_svc(rpcb_rmtcallargs *, struct svc_req *);
+-#define RPCBPROC_GETTIME ((u_int32_t)6)
+-extern "C" u_int * rpcbproc_gettime_3(void *, CLIENT *);
+-extern "C" u_int * rpcbproc_gettime_3_svc(void *, struct svc_req *);
+-#define RPCBPROC_UADDR2TADDR ((u_int32_t)7)
+-extern "C" struct netbuf * rpcbproc_uaddr2taddr_3(char **, CLIENT *);
+-extern "C" struct netbuf * rpcbproc_uaddr2taddr_3_svc(char **, struct svc_req *);
+-#define RPCBPROC_TADDR2UADDR ((u_int32_t)8)
+-extern "C" char ** rpcbproc_taddr2uaddr_3(struct netbuf *, CLIENT *);
+-extern "C" char ** rpcbproc_taddr2uaddr_3_svc(struct netbuf *, struct svc_req *);
+-
+-#elif __STDC__
+-#define RPCBPROC_SET ((u_int32_t)1)
+-extern bool_t * rpcbproc_set_3(rpcb *, CLIENT *);
+-extern bool_t * rpcbproc_set_3_svc(rpcb *, struct svc_req *);
+-#define RPCBPROC_UNSET ((u_int32_t)2)
+-extern bool_t * rpcbproc_unset_3(rpcb *, CLIENT *);
+-extern bool_t * rpcbproc_unset_3_svc(rpcb *, struct svc_req *);
+-#define RPCBPROC_GETADDR ((u_int32_t)3)
+-extern char ** rpcbproc_getaddr_3(rpcb *, CLIENT *);
+-extern char ** rpcbproc_getaddr_3_svc(rpcb *, struct svc_req *);
+-#define RPCBPROC_DUMP ((u_int32_t)4)
+-extern rpcblist_ptr * rpcbproc_dump_3(void *, CLIENT *);
+-extern rpcblist_ptr * rpcbproc_dump_3_svc(void *, struct svc_req *);
+-#define RPCBPROC_CALLIT ((u_int32_t)5)
+-extern rpcb_rmtcallres * rpcbproc_callit_3(rpcb_rmtcallargs *, CLIENT *);
+-extern rpcb_rmtcallres * rpcbproc_callit_3_svc(rpcb_rmtcallargs *, struct svc_req *);
+-#define RPCBPROC_GETTIME ((u_int32_t)6)
+-extern u_int * rpcbproc_gettime_3(void *, CLIENT *);
+-extern u_int * rpcbproc_gettime_3_svc(void *, struct svc_req *);
+-#define RPCBPROC_UADDR2TADDR ((u_int32_t)7)
+-extern struct netbuf * rpcbproc_uaddr2taddr_3(char **, CLIENT *);
+-extern struct netbuf * rpcbproc_uaddr2taddr_3_svc(char **, struct svc_req *);
+-#define RPCBPROC_TADDR2UADDR ((u_int32_t)8)
+-extern char ** rpcbproc_taddr2uaddr_3(struct netbuf *, CLIENT *);
+-extern char ** rpcbproc_taddr2uaddr_3_svc(struct netbuf *, struct svc_req *);
+-
+-#else /* Old Style C */
+-#define RPCBPROC_SET ((u_int32_t)1)
+-extern bool_t * rpcbproc_set_3();
+-extern bool_t * rpcbproc_set_3_svc();
+-#define RPCBPROC_UNSET ((u_int32_t)2)
+-extern bool_t * rpcbproc_unset_3();
+-extern bool_t * rpcbproc_unset_3_svc();
+-#define RPCBPROC_GETADDR ((u_int32_t)3)
+-extern char ** rpcbproc_getaddr_3();
+-extern char ** rpcbproc_getaddr_3_svc();
+-#define RPCBPROC_DUMP ((u_int32_t)4)
+-extern rpcblist_ptr * rpcbproc_dump_3();
+-extern rpcblist_ptr * rpcbproc_dump_3_svc();
+-#define RPCBPROC_CALLIT ((u_int32_t)5)
+-extern rpcb_rmtcallres * rpcbproc_callit_3();
+-extern rpcb_rmtcallres * rpcbproc_callit_3_svc();
+-#define RPCBPROC_GETTIME ((u_int32_t)6)
+-extern u_int * rpcbproc_gettime_3();
+-extern u_int * rpcbproc_gettime_3_svc();
+-#define RPCBPROC_UADDR2TADDR ((u_int32_t)7)
+-extern struct netbuf * rpcbproc_uaddr2taddr_3();
+-extern struct netbuf * rpcbproc_uaddr2taddr_3_svc();
+-#define RPCBPROC_TADDR2UADDR ((u_int32_t)8)
+-extern char ** rpcbproc_taddr2uaddr_3();
+-extern char ** rpcbproc_taddr2uaddr_3_svc();
+-#endif /* Old Style C */
+-#define RPCBVERS4 ((u_int32_t)4)
+-
+-#ifdef __cplusplus
+-extern "C" bool_t * rpcbproc_set_4(rpcb *, CLIENT *);
+-extern "C" bool_t * rpcbproc_set_4_svc(rpcb *, struct svc_req *);
+-extern "C" bool_t * rpcbproc_unset_4(rpcb *, CLIENT *);
+-extern "C" bool_t * rpcbproc_unset_4_svc(rpcb *, struct svc_req *);
+-extern "C" char ** rpcbproc_getaddr_4(rpcb *, CLIENT *);
+-extern "C" char ** rpcbproc_getaddr_4_svc(rpcb *, struct svc_req *);
+-extern "C" rpcblist_ptr * rpcbproc_dump_4(void *, CLIENT *);
+-extern "C" rpcblist_ptr * rpcbproc_dump_4_svc(void *, struct svc_req *);
+-#define RPCBPROC_BCAST ((u_int32_t)RPCBPROC_CALLIT)
+-extern "C" rpcb_rmtcallres * rpcbproc_bcast_4(rpcb_rmtcallargs *, CLIENT *);
+-extern "C" rpcb_rmtcallres * rpcbproc_bcast_4_svc(rpcb_rmtcallargs *, struct svc_req *);
+-extern "C" u_int * rpcbproc_gettime_4(void *, CLIENT *);
+-extern "C" u_int * rpcbproc_gettime_4_svc(void *, struct svc_req *);
+-extern "C" struct netbuf * rpcbproc_uaddr2taddr_4(char **, CLIENT *);
+-extern "C" struct netbuf * rpcbproc_uaddr2taddr_4_svc(char **, struct svc_req *);
+-extern "C" char ** rpcbproc_taddr2uaddr_4(struct netbuf *, CLIENT *);
+-extern "C" char ** rpcbproc_taddr2uaddr_4_svc(struct netbuf *, struct svc_req *);
+-#define RPCBPROC_GETVERSADDR ((u_int32_t)9)
+-extern "C" char ** rpcbproc_getversaddr_4(rpcb *, CLIENT *);
+-extern "C" char ** rpcbproc_getversaddr_4_svc(rpcb *, struct svc_req *);
+-#define RPCBPROC_INDIRECT ((u_int32_t)10)
+-extern "C" rpcb_rmtcallres * rpcbproc_indirect_4(rpcb_rmtcallargs *, CLIENT *);
+-extern "C" rpcb_rmtcallres * rpcbproc_indirect_4_svc(rpcb_rmtcallargs *, struct svc_req *);
+-#define RPCBPROC_GETADDRLIST ((u_int32_t)11)
+-extern "C" rpcb_entry_list_ptr * rpcbproc_getaddrlist_4(rpcb *, CLIENT *);
+-extern "C" rpcb_entry_list_ptr * rpcbproc_getaddrlist_4_svc(rpcb *, struct svc_req *);
+-#define RPCBPROC_GETSTAT ((u_int32_t)12)
+-extern "C" rpcb_stat * rpcbproc_getstat_4(void *, CLIENT *);
+-extern "C" rpcb_stat * rpcbproc_getstat_4_svc(void *, struct svc_req *);
+-
+-#elif __STDC__
+-extern bool_t * rpcbproc_set_4(rpcb *, CLIENT *);
+-extern bool_t * rpcbproc_set_4_svc(rpcb *, struct svc_req *);
+-extern bool_t * rpcbproc_unset_4(rpcb *, CLIENT *);
+-extern bool_t * rpcbproc_unset_4_svc(rpcb *, struct svc_req *);
+-extern char ** rpcbproc_getaddr_4(rpcb *, CLIENT *);
+-extern char ** rpcbproc_getaddr_4_svc(rpcb *, struct svc_req *);
+-extern rpcblist_ptr * rpcbproc_dump_4(void *, CLIENT *);
+-extern rpcblist_ptr * rpcbproc_dump_4_svc(void *, struct svc_req *);
+-#define RPCBPROC_BCAST ((u_int32_t)RPCBPROC_CALLIT)
+-extern rpcb_rmtcallres * rpcbproc_bcast_4(rpcb_rmtcallargs *, CLIENT *);
+-extern rpcb_rmtcallres * rpcbproc_bcast_4_svc(rpcb_rmtcallargs *, struct svc_req *);
+-extern u_int * rpcbproc_gettime_4(void *, CLIENT *);
+-extern u_int * rpcbproc_gettime_4_svc(void *, struct svc_req *);
+-extern struct netbuf * rpcbproc_uaddr2taddr_4(char **, CLIENT *);
+-extern struct netbuf * rpcbproc_uaddr2taddr_4_svc(char **, struct svc_req *);
+-extern char ** rpcbproc_taddr2uaddr_4(struct netbuf *, CLIENT *);
+-extern char ** rpcbproc_taddr2uaddr_4_svc(struct netbuf *, struct svc_req *);
+-#define RPCBPROC_GETVERSADDR ((u_int32_t)9)
+-extern char ** rpcbproc_getversaddr_4(rpcb *, CLIENT *);
+-extern char ** rpcbproc_getversaddr_4_svc(rpcb *, struct svc_req *);
+-#define RPCBPROC_INDIRECT ((u_int32_t)10)
+-extern rpcb_rmtcallres * rpcbproc_indirect_4(rpcb_rmtcallargs *, CLIENT *);
+-extern rpcb_rmtcallres * rpcbproc_indirect_4_svc(rpcb_rmtcallargs *, struct svc_req *);
+-#define RPCBPROC_GETADDRLIST ((u_int32_t)11)
+-extern rpcb_entry_list_ptr * rpcbproc_getaddrlist_4(rpcb *, CLIENT *);
+-extern rpcb_entry_list_ptr * rpcbproc_getaddrlist_4_svc(rpcb *, struct svc_req *);
+-#define RPCBPROC_GETSTAT ((u_int32_t)12)
+-extern rpcb_stat * rpcbproc_getstat_4(void *, CLIENT *);
+-extern rpcb_stat * rpcbproc_getstat_4_svc(void *, struct svc_req *);
+-
+-#else /* Old Style C */
+-extern bool_t * rpcbproc_set_4();
+-extern bool_t * rpcbproc_set_4_svc();
+-extern bool_t * rpcbproc_unset_4();
+-extern bool_t * rpcbproc_unset_4_svc();
+-extern char ** rpcbproc_getaddr_4();
+-extern char ** rpcbproc_getaddr_4_svc();
+-extern rpcblist_ptr * rpcbproc_dump_4();
+-extern rpcblist_ptr * rpcbproc_dump_4_svc();
+-#define RPCBPROC_BCAST ((u_int32_t)RPCBPROC_CALLIT)
+-extern rpcb_rmtcallres * rpcbproc_bcast_4();
+-extern rpcb_rmtcallres * rpcbproc_bcast_4_svc();
+-extern u_int * rpcbproc_gettime_4();
+-extern u_int * rpcbproc_gettime_4_svc();
+-extern struct netbuf * rpcbproc_uaddr2taddr_4();
+-extern struct netbuf * rpcbproc_uaddr2taddr_4_svc();
+-extern char ** rpcbproc_taddr2uaddr_4();
+-extern char ** rpcbproc_taddr2uaddr_4_svc();
+-#define RPCBPROC_GETVERSADDR ((u_int32_t)9)
+-extern char ** rpcbproc_getversaddr_4();
+-extern char ** rpcbproc_getversaddr_4_svc();
+-#define RPCBPROC_INDIRECT ((u_int32_t)10)
+-extern rpcb_rmtcallres * rpcbproc_indirect_4();
+-extern rpcb_rmtcallres * rpcbproc_indirect_4_svc();
+-#define RPCBPROC_GETADDRLIST ((u_int32_t)11)
+-extern rpcb_entry_list_ptr * rpcbproc_getaddrlist_4();
+-extern rpcb_entry_list_ptr * rpcbproc_getaddrlist_4_svc();
+-#define RPCBPROC_GETSTAT ((u_int32_t)12)
+-extern rpcb_stat * rpcbproc_getstat_4();
+-extern rpcb_stat * rpcbproc_getstat_4_svc();
+-#endif /* Old Style C */
+-
+-#endif /* !_RPCB_PROT_H_RPCGEN */
+diff --git a/tirpc/rpcsvc/crypt.h b/tirpc/rpcsvc/crypt.h
+deleted file mode 100644
+index da1f9cc..0000000
+--- a/tirpc/rpcsvc/crypt.h
++++ /dev/null
+@@ -1,109 +0,0 @@
+-/*
+- * Please do not edit this file.
+- * It was generated using rpcgen.
+- */
+-
+-#ifndef _CRYPT_H_RPCGEN
+-#define _CRYPT_H_RPCGEN
+-
+-#include <rpc/rpc.h>
+-
+-#ifndef IXDR_GET_INT32
+-#define IXDR_GET_INT32(buf) IXDR_GET_LONG((buf))
+-#endif
+-#ifndef IXDR_PUT_INT32
+-#define IXDR_PUT_INT32(buf, v) IXDR_PUT_LONG((buf), (v))
+-#endif
+-#ifndef IXDR_GET_U_INT32
+-#define IXDR_GET_U_INT32(buf) IXDR_GET_U_LONG((buf))
+-#endif
+-#ifndef IXDR_PUT_U_INT32
+-#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_U_LONG((buf), (v))
+-#endif
+-
+-enum des_dir {
+- ENCRYPT_DES = 0,
+- DECRYPT_DES = 1,
+-};
+-typedef enum des_dir des_dir;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_des_dir(XDR *, des_dir*);
+-#elif __STDC__
+-extern bool_t xdr_des_dir(XDR *, des_dir*);
+-#else /* Old Style C */
+-bool_t xdr_des_dir();
+-#endif /* Old Style C */
+-
+-
+-enum des_mode {
+- CBC_DES = 0,
+- ECB_DES = 1,
+-};
+-typedef enum des_mode des_mode;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_des_mode(XDR *, des_mode*);
+-#elif __STDC__
+-extern bool_t xdr_des_mode(XDR *, des_mode*);
+-#else /* Old Style C */
+-bool_t xdr_des_mode();
+-#endif /* Old Style C */
+-
+-
+-struct desargs {
+- u_char des_key[8];
+- des_dir des_dir;
+- des_mode des_mode;
+- u_char des_ivec[8];
+- struct {
+- u_int desbuf_len;
+- char *desbuf_val;
+- } desbuf;
+-};
+-typedef struct desargs desargs;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_desargs(XDR *, desargs*);
+-#elif __STDC__
+-extern bool_t xdr_desargs(XDR *, desargs*);
+-#else /* Old Style C */
+-bool_t xdr_desargs();
+-#endif /* Old Style C */
+-
+-
+-struct desresp {
+- struct {
+- u_int desbuf_len;
+- char *desbuf_val;
+- } desbuf;
+- u_char des_ivec[8];
+- int stat;
+-};
+-typedef struct desresp desresp;
+-#ifdef __cplusplus
+-extern "C" bool_t xdr_desresp(XDR *, desresp*);
+-#elif __STDC__
+-extern bool_t xdr_desresp(XDR *, desresp*);
+-#else /* Old Style C */
+-bool_t xdr_desresp();
+-#endif /* Old Style C */
+-
+-
+-#define CRYPT_PROG ((u_int32_t)600100029)
+-#define CRYPT_VERS ((u_int32_t)1)
+-
+-#ifdef __cplusplus
+-#define DES_CRYPT ((u_int32_t)1)
+-extern "C" desresp * des_crypt_1(desargs *, CLIENT *);
+-extern "C" desresp * des_crypt_1_svc(desargs *, struct svc_req *);
+-
+-#elif __STDC__
+-#define DES_CRYPT ((u_int32_t)1)
+-extern desresp * des_crypt_1(desargs *, CLIENT *);
+-extern desresp * des_crypt_1_svc(desargs *, struct svc_req *);
+-
+-#else /* Old Style C */
+-#define DES_CRYPT ((u_int32_t)1)
+-extern desresp * des_crypt_1();
+-extern desresp * des_crypt_1_svc();
+-#endif /* Old Style C */
+-
+-#endif /* !_CRYPT_H_RPCGEN */
+--
+1.7.9.5
+
diff --git a/package/libtirpc/libtirpc-0010-Add-more-XDR-files-needed-to-build-rpcbind-on-top-of.patch b/package/libtirpc/libtirpc-0010-Add-more-XDR-files-needed-to-build-rpcbind-on-top-of.patch
new file mode 100644
index 000000000..360a27f83
--- /dev/null
+++ b/package/libtirpc/libtirpc-0010-Add-more-XDR-files-needed-to-build-rpcbind-on-top-of.patch
@@ -0,0 +1,1649 @@
+From 52aecb645b2e45d120a941f42fdbe193e22c27e1 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Sat, 10 Nov 2012 17:45:03 +0100
+Subject: [PATCH] Add more XDR files needed to build rpcbind on top of
+ libtirpc
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ Makefile.am | 6 +
+ tirpc/rpcsvc/mount.x | 257 ++++++++++
+ tirpc/rpcsvc/nfs_prot.x | 1266 +++++++++++++++++++++++++++++++++++++++++++++++
+ tirpc/rpcsvc/rquota.x | 67 +++
+ 4 files changed, 1596 insertions(+)
+ create mode 100644 tirpc/rpcsvc/mount.x
+ create mode 100644 tirpc/rpcsvc/nfs_prot.x
+ create mode 100644 tirpc/rpcsvc/rquota.x
+
+diff --git a/Makefile.am b/Makefile.am
+index 7e63f78..351c5df 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -3,10 +3,16 @@ ACLOCAL_AMFLAGS = -I m4
+
+ GENFILES = \
+ tirpc/rpcsvc/crypt.h \
++ tirpc/rpcsvc/mount.h \
++ tirpc/rpcsvc/nfs_prot.h \
++ tirpc/rpcsvc/rquota.h \
+ tirpc/rpc/rpcb_prot.h
+
+ nobase_include_HEADERS = tirpc/netconfig.h \
+ tirpc/rpcsvc/crypt.x \
++ tirpc/rpcsvc/mount.x \
++ tirpc/rpcsvc/nfs_prot.x \
++ tirpc/rpcsvc/rquota.x \
+ tirpc/rpc/xdr.h \
+ tirpc/rpc/types.h \
+ tirpc/rpc/svc_soc.h \
+diff --git a/tirpc/rpcsvc/mount.x b/tirpc/rpcsvc/mount.x
+new file mode 100644
+index 0000000..f68a06f
+--- /dev/null
++++ b/tirpc/rpcsvc/mount.x
+@@ -0,0 +1,257 @@
++/*
++ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
++ * unrestricted use provided that this legend is included on all tape
++ * media and as a part of the software program in whole or part. Users
++ * may copy or modify Sun RPC without charge, but are not authorized
++ * to license or distribute it to anyone else except as part of a product or
++ * program developed by the user.
++ *
++ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
++ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
++ *
++ * Sun RPC is provided with no support and without any obligation on the
++ * part of Sun Microsystems, Inc. to assist in its use, correction,
++ * modification or enhancement.
++ *
++ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
++ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
++ * OR ANY PART THEREOF.
++ *
++ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
++ * or profits or other special, indirect and consequential damages, even if
++ * Sun has been advised of the possibility of such damages.
++ *
++ * Sun Microsystems, Inc.
++ * 2550 Garcia Avenue
++ * Mountain View, California 94043
++ */
++
++/*
++ * Protocol description for the mount program
++ */
++
++#ifndef RPC_HDR
++%#ifndef lint
++%/*static char sccsid[] = "from: @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro";*/
++%/*static char sccsid[] = "from: @(#)mount.x 2.1 88/08/01 4.0 RPCSRC";*/
++%static const char rcsid[] =
++% "$FreeBSD: src/include/rpcsvc/mount.x,v 1.6 1999/08/27 23:45:08 peter Exp $";
++%#endif /* not lint */
++#endif
++
++const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
++const MNTNAMLEN = 255; /* maximum bytes in a name argument */
++const FHSIZE = 32; /* size in bytes of a file handle */
++#ifdef WANT_NFS3
++const FHSIZE3 = 64; /* size in bytes of a file handle (v3) */
++#endif
++
++/*
++ * The fhandle is the file handle that the server passes to the client.
++ * All file operations are done using the file handles to refer to a file
++ * or a directory. The file handle can contain whatever information the
++ * server needs to distinguish an individual file.
++ */
++typedef opaque fhandle[FHSIZE];
++#ifdef WANT_NFS3
++typedef opaque fhandle3<FHSIZE3>;
++#endif
++
++/*
++ * If a status of zero is returned, the call completed successfully, and
++ * a file handle for the directory follows. A non-zero status indicates
++ * some sort of error. The status corresponds with UNIX error numbers.
++ */
++union fhstatus switch (unsigned fhs_status) {
++case 0:
++ fhandle fhs_fhandle;
++default:
++ void;
++};
++
++#ifdef WANT_NFS3
++/*
++ * Status codes returned by the version 3 mount call.
++ */
++enum mountstat3 {
++ MNT3_OK = 0, /* no error */
++ MNT3ERR_PERM = 1, /* Not owner */
++ MNT3ERR_NOENT = 2, /* No such file or directory */
++ MNT3ERR_IO = 5, /* I/O error */
++ MNT3ERR_ACCES = 13, /* Permission denied */
++ MNT3ERR_NOTDIR = 20, /* Not a directory */
++ MNT3ERR_INVAL = 22, /* Invalid argument */
++ MNT3ERR_NAMETOOLONG = 63, /* Filename too long */
++ MNT3ERR_NOTSUPP = 10004, /* Operation not supported */
++ MNT3ERR_SERVERFAULT = 10006 /* A failure on the server */
++};
++
++struct mountres3_ok {
++ fhandle3 fhandle;
++ int auth_flavors<>;
++};
++
++union mountres3 switch (mountstat3 fhs_status) {
++case 0:
++ mountres3_ok mountinfo;
++default:
++ void;
++};
++#endif
++
++/*
++ * The type dirpath is the pathname of a directory
++ */
++typedef string dirpath<MNTPATHLEN>;
++
++/*
++ * The type name is used for arbitrary names (hostnames, groupnames)
++ */
++typedef string name<MNTNAMLEN>;
++
++/*
++ * A list of who has what mounted
++ */
++typedef struct mountbody *mountlist;
++struct mountbody {
++ name ml_hostname;
++ dirpath ml_directory;
++ mountlist ml_next;
++};
++
++/*
++ * A list of netgroups
++ */
++typedef struct groupnode *groups;
++struct groupnode {
++ name gr_name;
++ groups gr_next;
++};
++
++/*
++ * A list of what is exported and to whom
++ */
++typedef struct exportnode *exports;
++struct exportnode {
++ dirpath ex_dir;
++ groups ex_groups;
++ exports ex_next;
++};
++
++program MOUNTPROG {
++ /*
++ * Version one of the mount protocol communicates with version two
++ * of the NFS protocol. Version three communicates with
++ * version three of the NFS protocol. The only connecting
++ * point is the fhandle structure, which is the same for both
++ * protocols.
++ */
++ version MOUNTVERS {
++ /*
++ * Does no work. It is made available in all RPC services
++ * to allow server reponse testing and timing
++ */
++ void
++ MOUNTPROC_NULL(void) = 0;
++
++ /*
++ * If fhs_status is 0, then fhs_fhandle contains the
++ * file handle for the directory. This file handle may
++ * be used in the NFS protocol. This procedure also adds
++ * a new entry to the mount list for this client mounting
++ * the directory.
++ * Unix authentication required.
++ */
++ fhstatus
++ MOUNTPROC_MNT(dirpath) = 1;
++
++ /*
++ * Returns the list of remotely mounted filesystems. The
++ * mountlist contains one entry for each hostname and
++ * directory pair.
++ */
++ mountlist
++ MOUNTPROC_DUMP(void) = 2;
++
++ /*
++ * Removes the mount list entry for the directory
++ * Unix authentication required.
++ */
++ void
++ MOUNTPROC_UMNT(dirpath) = 3;
++
++ /*
++ * Removes all of the mount list entries for this client
++ * Unix authentication required.
++ */
++ void
++ MOUNTPROC_UMNTALL(void) = 4;
++
++ /*
++ * Returns a list of all the exported filesystems, and which
++ * machines are allowed to import it.
++ */
++ exports
++ MOUNTPROC_EXPORT(void) = 5;
++
++ /*
++ * Identical to MOUNTPROC_EXPORT above
++ */
++ exports
++ MOUNTPROC_EXPORTALL(void) = 6;
++ } = 1;
++#ifdef WANT_NFS3
++ version MOUNTVERS3 {
++ /*
++ * Does no work. It is made available in all RPC services
++ * to allow server reponse testing and timing
++ */
++ void
++ MOUNTPROC_NULL(void) = 0;
++
++ /*
++ * If mountres3.fhs_status is MNT3_OK, then
++ * mountres3.mountinfo contains the file handle for
++ * the directory and a list of acceptable
++ * authentication flavors. This file handle may only
++ * be used in the NFS version 3 protocol. This
++ * procedure also results in the server adding a new
++ * entry to its mount list recording that this client
++ * has mounted the directory. AUTH_UNIX authentication
++ * or better is required.
++ */
++ mountres3
++ MOUNTPROC_MNT(dirpath) = 1;
++
++ /*
++ * Returns the list of remotely mounted filesystems. The
++ * mountlist contains one entry for each hostname and
++ * directory pair.
++ */
++ mountlist
++ MOUNTPROC_DUMP(void) = 2;
++
++ /*
++ * Removes the mount list entry for the directory
++ * Unix authentication required.
++ */
++ void
++ MOUNTPROC_UMNT(dirpath) = 3;
++
++ /*
++ * Removes all of the mount list entries for this client
++ * Unix authentication required.
++ */
++ void
++ MOUNTPROC_UMNTALL(void) = 4;
++
++ /*
++ * Returns a list of all the exported filesystems, and which
++ * machines are allowed to import it.
++ */
++ exports
++ MOUNTPROC_EXPORT(void) = 5;
++ } = 3;
++#endif
++} = 100005;
+diff --git a/tirpc/rpcsvc/nfs_prot.x b/tirpc/rpcsvc/nfs_prot.x
+new file mode 100644
+index 0000000..01564f8
+--- /dev/null
++++ b/tirpc/rpcsvc/nfs_prot.x
+@@ -0,0 +1,1266 @@
++/*
++ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
++ * unrestricted use provided that this legend is included on all tape
++ * media and as a part of the software program in whole or part. Users
++ * may copy or modify Sun RPC without charge, but are not authorized
++ * to license or distribute it to anyone else except as part of a product or
++ * program developed by the user.
++ *
++ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
++ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
++ *
++ * Sun RPC is provided with no support and without any obligation on the
++ * part of Sun Microsystems, Inc. to assist in its use, correction,
++ * modification or enhancement.
++ *
++ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
++ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
++ * OR ANY PART THEREOF.
++ *
++ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
++ * or profits or other special, indirect and consequential damages, even if
++ * Sun has been advised of the possibility of such damages.
++ *
++ * Sun Microsystems, Inc.
++ * 2550 Garcia Avenue
++ * Mountain View, California 94043
++ */
++
++#ifndef RPC_HDR
++%#ifndef lint
++%/*static char sccsid[] = "from: @(#)nfs_prot.x 1.2 87/10/12 Copyr 1987 Sun Micro";*/
++%/*static char sccsid[] = "from: @(#)nfs_prot.x 2.1 88/08/01 4.0 RPCSRC";*/
++%static const char rcsid[] =
++% "$FreeBSD: src/include/rpcsvc/nfs_prot.x,v 1.7 1999/08/27 23:45:08 peter Exp $";
++%#endif /* not lint */
++#endif
++
++const NFS_PORT = 2049;
++const NFS_MAXDATA = 8192;
++const NFS_MAXPATHLEN = 1024;
++const NFS_MAXNAMLEN = 255;
++const NFS_FHSIZE = 32;
++const NFS_COOKIESIZE = 4;
++const NFS_FIFO_DEV = -1; /* size kludge for named pipes */
++
++/*
++ * File types
++ */
++const NFSMODE_FMT = 0170000; /* type of file */
++const NFSMODE_DIR = 0040000; /* directory */
++const NFSMODE_CHR = 0020000; /* character special */
++const NFSMODE_BLK = 0060000; /* block special */
++const NFSMODE_REG = 0100000; /* regular */
++const NFSMODE_LNK = 0120000; /* symbolic link */
++const NFSMODE_SOCK = 0140000; /* socket */
++const NFSMODE_FIFO = 0010000; /* fifo */
++
++/*
++ * Error status
++ */
++enum nfsstat {
++ NFS_OK= 0, /* no error */
++ NFSERR_PERM=1, /* Not owner */
++ NFSERR_NOENT=2, /* No such file or directory */
++ NFSERR_IO=5, /* I/O error */
++ NFSERR_NXIO=6, /* No such device or address */
++ NFSERR_ACCES=13, /* Permission denied */
++ NFSERR_EXIST=17, /* File exists */
++ NFSERR_NODEV=19, /* No such device */
++ NFSERR_NOTDIR=20, /* Not a directory*/
++ NFSERR_ISDIR=21, /* Is a directory */
++ NFSERR_FBIG=27, /* File too large */
++ NFSERR_NOSPC=28, /* No space left on device */
++ NFSERR_ROFS=30, /* Read-only file system */
++ NFSERR_NAMETOOLONG=63, /* File name too long */
++ NFSERR_NOTEMPTY=66, /* Directory not empty */
++ NFSERR_DQUOT=69, /* Disc quota exceeded */
++ NFSERR_STALE=70, /* Stale NFS file handle */
++ NFSERR_WFLUSH=99 /* write cache flushed */
++};
++
++/*
++ * File types
++ */
++enum ftype {
++ NFNON = 0, /* non-file */
++ NFREG = 1, /* regular file */
++ NFDIR = 2, /* directory */
++ NFBLK = 3, /* block special */
++ NFCHR = 4, /* character special */
++ NFLNK = 5, /* symbolic link */
++ NFSOCK = 6, /* unix domain sockets */
++ NFBAD = 7, /* unused */
++ NFFIFO = 8 /* named pipe */
++};
++
++/*
++ * File access handle
++ */
++struct nfs_fh {
++ opaque data[NFS_FHSIZE];
++};
++
++/*
++ * Timeval
++ */
++struct nfstime {
++ unsigned seconds;
++ unsigned useconds;
++};
++
++
++/*
++ * File attributes
++ */
++struct fattr {
++ ftype type; /* file type */
++ unsigned mode; /* protection mode bits */
++ unsigned nlink; /* # hard links */
++ unsigned uid; /* owner user id */
++ unsigned gid; /* owner group id */
++ unsigned size; /* file size in bytes */
++ unsigned blocksize; /* prefered block size */
++ unsigned rdev; /* special device # */
++ unsigned blocks; /* Kb of disk used by file */
++ unsigned fsid; /* device # */
++ unsigned fileid; /* inode # */
++ nfstime atime; /* time of last access */
++ nfstime mtime; /* time of last modification */
++ nfstime ctime; /* time of last change */
++};
++
++/*
++ * File attributes which can be set
++ */
++struct sattr {
++ unsigned mode; /* protection mode bits */
++ unsigned uid; /* owner user id */
++ unsigned gid; /* owner group id */
++ unsigned size; /* file size in bytes */
++ nfstime atime; /* time of last access */
++ nfstime mtime; /* time of last modification */
++};
++
++
++typedef string filename<NFS_MAXNAMLEN>;
++typedef string nfspath<NFS_MAXPATHLEN>;
++
++/*
++ * Reply status with file attributes
++ */
++union attrstat switch (nfsstat status) {
++case NFS_OK:
++ fattr attributes;
++default:
++ void;
++};
++
++struct sattrargs {
++ nfs_fh file;
++ sattr attributes;
++};
++
++/*
++ * Arguments for directory operations
++ */
++struct diropargs {
++ nfs_fh dir; /* directory file handle */
++ filename name; /* name (up to NFS_MAXNAMLEN bytes) */
++};
++
++struct diropokres {
++ nfs_fh file;
++ fattr attributes;
++};
++
++/*
++ * Results from directory operation
++ */
++union diropres switch (nfsstat status) {
++case NFS_OK:
++ diropokres diropres;
++default:
++ void;
++};
++
++union readlinkres switch (nfsstat status) {
++case NFS_OK:
++ nfspath data;
++default:
++ void;
++};
++
++/*
++ * Arguments to remote read
++ */
++struct readargs {
++ nfs_fh file; /* handle for file */
++ unsigned offset; /* byte offset in file */
++ unsigned count; /* immediate read count */
++ unsigned totalcount; /* total read count (from this offset)*/
++};
++
++/*
++ * Status OK portion of remote read reply
++ */
++struct readokres {
++ fattr attributes; /* attributes, need for pagin*/
++ opaque data<NFS_MAXDATA>;
++};
++
++union readres switch (nfsstat status) {
++case NFS_OK:
++ readokres reply;
++default:
++ void;
++};
++
++/*
++ * Arguments to remote write
++ */
++struct writeargs {
++ nfs_fh file; /* handle for file */
++ unsigned beginoffset; /* beginning byte offset in file */
++ unsigned offset; /* current byte offset in file */
++ unsigned totalcount; /* total write count (to this offset)*/
++ opaque data<NFS_MAXDATA>;
++};
++
++struct createargs {
++ diropargs where;
++ sattr attributes;
++};
++
++struct renameargs {
++ diropargs from;
++ diropargs to;
++};
++
++struct linkargs {
++ nfs_fh from;
++ diropargs to;
++};
++
++struct symlinkargs {
++ diropargs from;
++ nfspath to;
++ sattr attributes;
++};
++
++
++typedef opaque nfscookie[NFS_COOKIESIZE];
++
++/*
++ * Arguments to readdir
++ */
++struct readdirargs {
++ nfs_fh dir; /* directory handle */
++ nfscookie cookie;
++ unsigned count; /* number of directory bytes to read */
++};
++
++struct entry {
++ unsigned fileid;
++ filename name;
++ nfscookie cookie;
++ entry *nextentry;
++};
++
++struct dirlist {
++ entry *entries;
++ bool eof;
++};
++
++union readdirres switch (nfsstat status) {
++case NFS_OK:
++ dirlist reply;
++default:
++ void;
++};
++
++struct statfsokres {
++ unsigned tsize; /* preferred transfer size in bytes */
++ unsigned bsize; /* fundamental file system block size */
++ unsigned blocks; /* total blocks in file system */
++ unsigned bfree; /* free blocks in fs */
++ unsigned bavail; /* free blocks avail to non-superuser */
++};
++
++union statfsres switch (nfsstat status) {
++case NFS_OK:
++ statfsokres reply;
++default:
++ void;
++};
++
++#ifdef WANT_NFS3
++
++/*
++ * NFSv3 constants and types
++ */
++const NFS3_FHSIZE = 64; /* maximum size in bytes of a file handle */
++const NFS3_COOKIEVERFSIZE = 8; /* size of a cookie verifier for READDIR */
++const NFS3_CREATEVERFSIZE = 8; /* size of the verifier used for CREATE */
++const NFS3_WRITEVERFSIZE = 8; /* size of the verifier used for WRITE */
++
++typedef unsigned hyper uint64;
++typedef hyper int64;
++typedef unsigned long uint32;
++typedef long int32;
++typedef string filename3<>;
++typedef string nfspath3<>;
++typedef uint64 fileid3;
++typedef uint64 cookie3;
++typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
++typedef opaque createverf3[NFS3_CREATEVERFSIZE];
++typedef opaque writeverf3[NFS3_WRITEVERFSIZE];
++typedef uint32 uid3;
++typedef uint32 gid3;
++typedef uint64 size3;
++typedef uint64 offset3;
++typedef uint32 mode3;
++typedef uint32 count3;
++
++/*
++ * Error status (v3)
++ */
++enum nfsstat3 {
++ NFS3_OK = 0,
++ NFS3ERR_PERM = 1,
++ NFS3ERR_NOENT = 2,
++ NFS3ERR_IO = 5,
++ NFS3ERR_NXIO = 6,
++ NFS3ERR_ACCES = 13,
++ NFS3ERR_EXIST = 17,
++ NFS3ERR_XDEV = 18,
++ NFS3ERR_NODEV = 19,
++ NFS3ERR_NOTDIR = 20,
++ NFS3ERR_ISDIR = 21,
++ NFS3ERR_INVAL = 22,
++ NFS3ERR_FBIG = 27,
++ NFS3ERR_NOSPC = 28,
++ NFS3ERR_ROFS = 30,
++ NFS3ERR_MLINK = 31,
++ NFS3ERR_NAMETOOLONG = 63,
++ NFS3ERR_NOTEMPTY = 66,
++ NFS3ERR_DQUOT = 69,
++ NFS3ERR_STALE = 70,
++ NFS3ERR_REMOTE = 71,
++ NFS3ERR_BADHANDLE = 10001,
++ NFS3ERR_NOT_SYNC = 10002,
++ NFS3ERR_BAD_COOKIE = 10003,
++ NFS3ERR_NOTSUPP = 10004,
++ NFS3ERR_TOOSMALL = 10005,
++ NFS3ERR_SERVERFAULT = 10006,
++ NFS3ERR_BADTYPE = 10007,
++ NFS3ERR_JUKEBOX = 10008
++};
++
++/*
++ * File types (v3)
++ */
++enum ftype3 {
++ NF3REG = 1, /* regular file */
++ NF3DIR = 2, /* directory */
++ NF3BLK = 3, /* block special */
++ NF3CHR = 4, /* character special */
++ NF3LNK = 5, /* symbolic link */
++ NF3SOCK = 6, /* unix domain sockets */
++ NF3FIFO = 7 /* named pipe */
++};
++
++struct specdata3 {
++ uint32 specdata1;
++ uint32 specdata2;
++};
++
++/*
++ * File access handle (v3)
++ */
++struct nfs_fh3 {
++ opaque data<NFS3_FHSIZE>;
++};
++
++/*
++ * Timeval (v3)
++ */
++struct nfstime3 {
++ uint32 seconds;
++ uint32 nseconds;
++};
++
++
++/*
++ * File attributes (v3)
++ */
++struct fattr3 {
++ ftype3 type; /* file type */
++ mode3 mode; /* protection mode bits */
++ uint32 nlink; /* # hard links */
++ uid3 uid; /* owner user id */
++ gid3 gid; /* owner group id */
++ size3 size; /* file size in bytes */
++ size3 used; /* prefered block size */
++ specdata3 rdev; /* special device # */
++ uint64 fsid; /* device # */
++ fileid3 fileid; /* inode # */
++ nfstime3 atime; /* time of last access */
++ nfstime3 mtime; /* time of last modification */
++ nfstime3 ctime; /* time of last change */
++};
++
++union post_op_attr switch (bool attributes_follow) {
++case TRUE:
++ fattr3 attributes;
++case FALSE:
++ void;
++};
++
++struct wcc_attr {
++ size3 size;
++ nfstime3 mtime;
++ nfstime3 ctime;
++};
++
++union pre_op_attr switch (bool attributes_follow) {
++case TRUE:
++ wcc_attr attributes;
++case FALSE:
++ void;
++};
++
++struct wcc_data {
++ pre_op_attr before;
++ post_op_attr after;
++};
++
++union post_op_fh3 switch (bool handle_follows) {
++case TRUE:
++ nfs_fh3 handle;
++case FALSE:
++ void;
++};
++
++/*
++ * File attributes which can be set (v3)
++ */
++enum time_how {
++ DONT_CHANGE = 0,
++ SET_TO_SERVER_TIME = 1,
++ SET_TO_CLIENT_TIME = 2
++};
++
++union set_mode3 switch (bool set_it) {
++case TRUE:
++ mode3 mode;
++default:
++ void;
++};
++
++union set_uid3 switch (bool set_it) {
++case TRUE:
++ uid3 uid;
++default:
++ void;
++};
++
++union set_gid3 switch (bool set_it) {
++case TRUE:
++ gid3 gid;
++default:
++ void;
++};
++
++union set_size3 switch (bool set_it) {
++case TRUE:
++ size3 size;
++default:
++ void;
++};
++
++union set_atime switch (time_how set_it) {
++case SET_TO_CLIENT_TIME:
++ nfstime3 atime;
++default:
++ void;
++};
++
++union set_mtime switch (time_how set_it) {
++case SET_TO_CLIENT_TIME:
++ nfstime3 mtime;
++default:
++ void;
++};
++
++struct sattr3 {
++ set_mode3 mode;
++ set_uid3 uid;
++ set_gid3 gid;
++ set_size3 size;
++ set_atime atime;
++ set_mtime mtime;
++};
++
++/*
++ * Arguments for directory operations (v3)
++ */
++struct diropargs3 {
++ nfs_fh3 dir; /* directory file handle */
++ filename3 name; /* name (up to NFS_MAXNAMLEN bytes) */
++};
++
++/*
++ * Arguments to getattr (v3).
++ */
++struct GETATTR3args {
++ nfs_fh3 object;
++};
++
++struct GETATTR3resok {
++ fattr3 obj_attributes;
++};
++
++union GETATTR3res switch (nfsstat3 status) {
++case NFS3_OK:
++ GETATTR3resok resok;
++default:
++ void;
++};
++
++/*
++ * Arguments to setattr (v3).
++ */
++union sattrguard3 switch (bool check) {
++case TRUE:
++ nfstime3 obj_ctime;
++case FALSE:
++ void;
++};
++
++struct SETATTR3args {
++ nfs_fh3 object;
++ sattr3 new_attributes;
++ sattrguard3 guard;
++};
++
++struct SETATTR3resok {
++ wcc_data obj_wcc;
++};
++
++struct SETATTR3resfail {
++ wcc_data obj_wcc;
++};
++
++union SETATTR3res switch (nfsstat3 status) {
++case NFS3_OK:
++ SETATTR3resok resok;
++default:
++ SETATTR3resfail resfail;
++};
++
++/*
++ * Arguments to lookup (v3).
++ */
++struct LOOKUP3args {
++ diropargs3 what;
++};
++
++struct LOOKUP3resok {
++ nfs_fh3 object;
++ post_op_attr obj_attributes;
++ post_op_attr dir_attributes;
++};
++
++struct LOOKUP3resfail {
++ post_op_attr dir_attributes;
++};
++
++union LOOKUP3res switch (nfsstat3 status) {
++case NFS3_OK:
++ LOOKUP3resok resok;
++default:
++ LOOKUP3resfail resfail;
++};
++
++/*
++ * Arguments to access (v3).
++ */
++const ACCESS3_READ = 0x0001;
++const ACCESS3_LOOKUP = 0x0002;
++const ACCESS3_MODIFY = 0x0004;
++const ACCESS3_EXTEND = 0x0008;
++const ACCESS3_DELETE = 0x0010;
++const ACCESS3_EXECUTE = 0x0020;
++
++struct ACCESS3args {
++ nfs_fh3 object;
++ uint32 access;
++};
++
++struct ACCESS3resok {
++ post_op_attr obj_attributes;
++ uint32 access;
++};
++
++struct ACCESS3resfail {
++ post_op_attr obj_attributes;
++};
++
++union ACCESS3res switch (nfsstat3 status) {
++case NFS3_OK:
++ ACCESS3resok resok;
++default:
++ ACCESS3resfail resfail;
++};
++
++/*
++ * Arguments to readlink (v3).
++ */
++struct READLINK3args {
++ nfs_fh3 symlink;
++};
++
++struct READLINK3resok {
++ post_op_attr symlink_attributes;
++ nfspath3 data;
++};
++
++struct READLINK3resfail {
++ post_op_attr symlink_attributes;
++};
++
++union READLINK3res switch (nfsstat3 status) {
++case NFS3_OK:
++ READLINK3resok resok;
++default:
++ READLINK3resfail resfail;
++};
++
++/*
++ * Arguments to read (v3).
++ */
++struct READ3args {
++ nfs_fh3 file;
++ offset3 offset;
++ count3 count;
++};
++
++struct READ3resok {
++ post_op_attr file_attributes;
++ count3 count;
++ bool eof;
++ opaque data<>;
++};
++
++struct READ3resfail {
++ post_op_attr file_attributes;
++};
++
++/* XXX: solaris 2.6 uses ``nfsstat'' here */
++union READ3res switch (nfsstat3 status) {
++case NFS3_OK:
++ READ3resok resok;
++default:
++ READ3resfail resfail;
++};
++
++/*
++ * Arguments to write (v3).
++ */
++enum stable_how {
++ UNSTABLE = 0,
++ DATA_SYNC = 1,
++ FILE_SYNC = 2
++};
++
++struct WRITE3args {
++ nfs_fh3 file;
++ offset3 offset;
++ count3 count;
++ stable_how stable;
++ opaque data<>;
++};
++
++struct WRITE3resok {
++ wcc_data file_wcc;
++ count3 count;
++ stable_how committed;
++ writeverf3 verf;
++};
++
++struct WRITE3resfail {
++ wcc_data file_wcc;
++};
++
++union WRITE3res switch (nfsstat3 status) {
++case NFS3_OK:
++ WRITE3resok resok;
++default:
++ WRITE3resfail resfail;
++};
++
++/*
++ * Arguments to create (v3).
++ */
++enum createmode3 {
++ UNCHECKED = 0,
++ GUARDED = 1,
++ EXCLUSIVE = 2
++};
++
++union createhow3 switch (createmode3 mode) {
++case UNCHECKED:
++case GUARDED:
++ sattr3 obj_attributes;
++case EXCLUSIVE:
++ createverf3 verf;
++};
++
++struct CREATE3args {
++ diropargs3 where;
++ createhow3 how;
++};
++
++struct CREATE3resok {
++ post_op_fh3 obj;
++ post_op_attr obj_attributes;
++ wcc_data dir_wcc;
++};
++
++struct CREATE3resfail {
++ wcc_data dir_wcc;
++};
++
++union CREATE3res switch (nfsstat3 status) {
++case NFS3_OK:
++ CREATE3resok resok;
++default:
++ CREATE3resfail resfail;
++};
++
++/*
++ * Arguments to mkdir (v3).
++ */
++struct MKDIR3args {
++ diropargs3 where;
++ sattr3 attributes;
++};
++
++struct MKDIR3resok {
++ post_op_fh3 obj;
++ post_op_attr obj_attributes;
++ wcc_data dir_wcc;
++};
++
++struct MKDIR3resfail {
++ wcc_data dir_wcc;
++};
++
++union MKDIR3res switch (nfsstat3 status) {
++case NFS3_OK:
++ MKDIR3resok resok;
++default:
++ MKDIR3resfail resfail;
++};
++
++/*
++ * Arguments to symlink (v3).
++ */
++struct symlinkdata3 {
++ sattr3 symlink_attributes;
++ nfspath3 symlink_data;
++};
++
++struct SYMLINK3args {
++ diropargs3 where;
++ symlinkdata3 symlink;
++};
++
++struct SYMLINK3resok {
++ post_op_fh3 obj;
++ post_op_attr obj_attributes;
++ wcc_data dir_wcc;
++};
++
++struct SYMLINK3resfail {
++ wcc_data dir_wcc;
++};
++
++union SYMLINK3res switch (nfsstat3 status) {
++case NFS3_OK:
++ SYMLINK3resok resok;
++default:
++ SYMLINK3resfail resfail;
++};
++
++/*
++ * Arguments to mknod (v3).
++ */
++struct devicedata3 {
++ sattr3 dev_attributes;
++ specdata3 spec;
++};
++
++union mknoddata3 switch (ftype3 type) {
++case NF3CHR:
++case NF3BLK:
++ devicedata3 device;
++case NF3SOCK:
++case NF3FIFO:
++ sattr3 pipe_attributes;
++default:
++ void;
++};
++
++struct MKNOD3args {
++ diropargs3 where;
++ mknoddata3 what;
++};
++
++struct MKNOD3resok {
++ post_op_fh3 obj;
++ post_op_attr obj_attributes;
++ wcc_data dir_wcc;
++};
++
++struct MKNOD3resfail {
++ wcc_data dir_wcc;
++};
++
++union MKNOD3res switch (nfsstat3 status) {
++case NFS3_OK:
++ MKNOD3resok resok;
++default:
++ MKNOD3resfail resfail;
++};
++
++/*
++ * Arguments to remove (v3).
++ */
++struct REMOVE3args {
++ diropargs3 object;
++};
++
++struct REMOVE3resok {
++ wcc_data dir_wcc;
++};
++
++struct REMOVE3resfail {
++ wcc_data dir_wcc;
++};
++
++union REMOVE3res switch (nfsstat3 status) {
++case NFS3_OK:
++ REMOVE3resok resok;
++default:
++ REMOVE3resfail resfail;
++};
++
++/*
++ * Arguments to rmdir (v3).
++ */
++struct RMDIR3args {
++ diropargs3 object;
++};
++
++struct RMDIR3resok {
++ wcc_data dir_wcc;
++};
++
++struct RMDIR3resfail {
++ wcc_data dir_wcc;
++};
++
++union RMDIR3res switch (nfsstat3 status) {
++case NFS3_OK:
++ RMDIR3resok resok;
++default:
++ RMDIR3resfail resfail;
++};
++
++/*
++ * Arguments to rename (v3).
++ */
++struct RENAME3args {
++ diropargs3 from;
++ diropargs3 to;
++};
++
++struct RENAME3resok {
++ wcc_data fromdir_wcc;
++ wcc_data todir_wcc;
++};
++
++struct RENAME3resfail {
++ wcc_data fromdir_wcc;
++ wcc_data todir_wcc;
++};
++
++union RENAME3res switch (nfsstat3 status) {
++case NFS3_OK:
++ RENAME3resok resok;
++default:
++ RENAME3resfail resfail;
++};
++
++/*
++ * Arguments to link (v3).
++ */
++struct LINK3args {
++ nfs_fh3 file;
++ diropargs3 link;
++};
++
++struct LINK3resok {
++ post_op_attr file_attributes;
++ wcc_data linkdir_wcc;
++};
++
++struct LINK3resfail {
++ post_op_attr file_attributes;
++ wcc_data linkdir_wcc;
++};
++
++union LINK3res switch (nfsstat3 status) {
++case NFS3_OK:
++ LINK3resok resok;
++default:
++ LINK3resfail resfail;
++};
++
++/*
++ * Arguments to readdir (v3).
++ */
++struct READDIR3args {
++ nfs_fh3 dir;
++ cookie3 cookie;
++ cookieverf3 cookieverf;
++ count3 count;
++};
++
++struct entry3 {
++ fileid3 fileid;
++ filename3 name;
++ cookie3 cookie;
++ entry3 *nextentry;
++};
++
++struct dirlist3 {
++ entry3 *entries;
++ bool eof;
++};
++
++struct READDIR3resok {
++ post_op_attr dir_attributes;
++ cookieverf3 cookieverf;
++ dirlist3 reply;
++};
++
++struct READDIR3resfail {
++ post_op_attr dir_attributes;
++};
++
++union READDIR3res switch (nfsstat3 status) {
++case NFS3_OK:
++ READDIR3resok resok;
++default:
++ READDIR3resfail resfail;
++};
++
++/*
++ * Arguments to readdirplus (v3).
++ */
++struct READDIRPLUS3args {
++ nfs_fh3 dir;
++ cookie3 cookie;
++ cookieverf3 cookieverf;
++ count3 dircount;
++ count3 maxcount;
++};
++
++struct entryplus3 {
++ fileid3 fileid;
++ filename3 name;
++ cookie3 cookie;
++ post_op_attr name_attributes;
++ post_op_fh3 name_handle;
++ entryplus3 *nextentry;
++};
++
++struct dirlistplus3 {
++ entryplus3 *entries;
++ bool eof;
++};
++
++struct READDIRPLUS3resok {
++ post_op_attr dir_attributes;
++ cookieverf3 cookieverf;
++ dirlistplus3 reply;
++};
++
++struct READDIRPLUS3resfail {
++ post_op_attr dir_attributes;
++};
++
++union READDIRPLUS3res switch (nfsstat3 status) {
++case NFS3_OK:
++ READDIRPLUS3resok resok;
++default:
++ READDIRPLUS3resfail resfail;
++};
++
++/*
++ * Arguments to fsstat (v3).
++ */
++struct FSSTAT3args {
++ nfs_fh3 fsroot;
++};
++
++struct FSSTAT3resok {
++ post_op_attr obj_attributes;
++ size3 tbytes;
++ size3 fbytes;
++ size3 abytes;
++ size3 tfiles;
++ size3 ffiles;
++ size3 afiles;
++ uint32 invarsec;
++};
++
++struct FSSTAT3resfail {
++ post_op_attr obj_attributes;
++};
++
++union FSSTAT3res switch (nfsstat3 status) {
++case NFS3_OK:
++ FSSTAT3resok resok;
++default:
++ FSSTAT3resfail resfail;
++};
++
++/*
++ * Arguments to fsinfo (v3).
++ */
++const FSF3_LINK = 0x0001;
++const FSF3_SYMLINK = 0x0002;
++const FSF3_HOMOGENEOUS = 0x0008;
++const FSF3_CANSETTIME = 0x0010;
++
++struct FSINFO3args {
++ nfs_fh3 fsroot;
++};
++
++struct FSINFO3resok {
++ post_op_attr obj_attributes;
++ uint32 rtmax;
++ uint32 rtpref;
++ uint32 rtmult;
++ uint32 wtmax;
++ uint32 wtpref;
++ uint32 wtmult;
++ uint32 dtpref;
++ size3 maxfilesize;
++ nfstime3 time_delta;
++ uint32 properties;
++};
++
++struct FSINFO3resfail {
++ post_op_attr obj_attributes;
++};
++
++union FSINFO3res switch (nfsstat3 status) {
++case NFS3_OK:
++ FSINFO3resok resok;
++default:
++ FSINFO3resfail resfail;
++};
++
++/*
++ * Arguments to pathconf (v3).
++ */
++struct PATHCONF3args {
++ nfs_fh3 object;
++};
++
++struct PATHCONF3resok {
++ post_op_attr obj_attributes;
++ uint32 linkmax;
++ uint32 name_max;
++ bool no_trunc;
++ bool chown_restricted;
++ bool case_insensitive;
++ bool case_preserving;
++};
++
++struct PATHCONF3resfail {
++ post_op_attr obj_attributes;
++};
++
++union PATHCONF3res switch (nfsstat3 status) {
++case NFS3_OK:
++ PATHCONF3resok resok;
++default:
++ PATHCONF3resfail resfail;
++};
++
++/*
++ * Arguments to commit (v3).
++ */
++struct COMMIT3args {
++ nfs_fh3 file;
++ offset3 offset;
++ count3 count;
++};
++
++struct COMMIT3resok {
++ wcc_data file_wcc;
++ writeverf3 verf;
++};
++
++struct COMMIT3resfail {
++ wcc_data file_wcc;
++};
++
++union COMMIT3res switch (nfsstat3 status) {
++case NFS3_OK:
++ COMMIT3resok resok;
++default:
++ COMMIT3resfail resfail;
++};
++
++#endif /* WANT_NFS3 */
++
++/*
++ * Remote file service routines
++ */
++program NFS_PROGRAM {
++ version NFS_VERSION {
++ void
++ NFSPROC_NULL(void) = 0;
++
++ attrstat
++ NFSPROC_GETATTR(nfs_fh) = 1;
++
++ attrstat
++ NFSPROC_SETATTR(sattrargs) = 2;
++
++ void
++ NFSPROC_ROOT(void) = 3;
++
++ diropres
++ NFSPROC_LOOKUP(diropargs) = 4;
++
++ readlinkres
++ NFSPROC_READLINK(nfs_fh) = 5;
++
++ readres
++ NFSPROC_READ(readargs) = 6;
++
++ void
++ NFSPROC_WRITECACHE(void) = 7;
++
++ attrstat
++ NFSPROC_WRITE(writeargs) = 8;
++
++ diropres
++ NFSPROC_CREATE(createargs) = 9;
++
++ nfsstat
++ NFSPROC_REMOVE(diropargs) = 10;
++
++ nfsstat
++ NFSPROC_RENAME(renameargs) = 11;
++
++ nfsstat
++ NFSPROC_LINK(linkargs) = 12;
++
++ nfsstat
++ NFSPROC_SYMLINK(symlinkargs) = 13;
++
++ diropres
++ NFSPROC_MKDIR(createargs) = 14;
++
++ nfsstat
++ NFSPROC_RMDIR(diropargs) = 15;
++
++ readdirres
++ NFSPROC_READDIR(readdirargs) = 16;
++
++ statfsres
++ NFSPROC_STATFS(nfs_fh) = 17;
++ } = 2;
++} = 100003;
++#ifdef WANT_NFS3
++program NFS3_PROGRAM {
++ version NFS_V3 {
++ void
++ NFSPROC3_NULL(void) = 0;
++
++ GETATTR3res
++ NFSPROC3_GETATTR(GETATTR3args) = 1;
++
++ SETATTR3res
++ NFSPROC3_SETATTR(SETATTR3args) = 2;
++
++ LOOKUP3res
++ NFSPROC3_LOOKUP(LOOKUP3args) = 3;
++
++ ACCESS3res
++ NFSPROC3_ACCESS(ACCESS3args) = 4;
++
++ READLINK3res
++ NFSPROC3_READLINK(READLINK3args) = 5;
++
++ READ3res
++ NFSPROC3_READ(READ3args) = 6;
++
++ WRITE3res
++ NFSPROC3_WRITE(WRITE3args) = 7;
++
++ CREATE3res
++ NFSPROC3_CREATE(CREATE3args) = 8;
++
++ MKDIR3res
++ NFSPROC3_MKDIR(MKDIR3args) = 9;
++
++ SYMLINK3res
++ NFSPROC3_SYMLINK(SYMLINK3args) = 10;
++
++ MKNOD3res
++ NFSPROC3_MKNOD(MKNOD3args) = 11;
++
++ REMOVE3res
++ NFSPROC3_REMOVE(REMOVE3args) = 12;
++
++ RMDIR3res
++ NFSPROC3_RMDIR(RMDIR3args) = 13;
++
++ RENAME3res
++ NFSPROC3_RENAME(RENAME3args) = 14;
++
++ LINK3res
++ NFSPROC3_LINK(LINK3args) = 15;
++
++ READDIR3res
++ NFSPROC3_READDIR(READDIR3args) = 16;
++
++ READDIRPLUS3res
++ NFSPROC3_READDIRPLUS(READDIRPLUS3args) = 17;
++
++ FSSTAT3res
++ NFSPROC3_FSSTAT(FSSTAT3args) = 18;
++
++ FSINFO3res
++ NFSPROC3_FSINFO(FSINFO3args) = 19;
++
++ PATHCONF3res
++ NFSPROC3_PATHCONF(PATHCONF3args) = 20;
++
++ COMMIT3res
++ NFSPROC3_COMMIT(COMMIT3args) = 21;
++ } = 3;
++} = 100003;
++#endif
++
+diff --git a/tirpc/rpcsvc/rquota.x b/tirpc/rpcsvc/rquota.x
+new file mode 100644
+index 0000000..72864d1
+--- /dev/null
++++ b/tirpc/rpcsvc/rquota.x
+@@ -0,0 +1,67 @@
++/*
++ * Remote quota protocol
++ * Requires unix authentication
++ */
++
++#ifndef RPC_HDR
++%#ifndef lint
++%/*static char sccsid[] = "from: @(#)rquota.x 1.2 87/09/20 Copyr 1987 Sun Micro";*/
++%/*static char sccsid[] = "from: @(#)rquota.x 2.1 88/08/01 4.0 RPCSRC";*/
++%static const char rcsid[] =
++% "$FreeBSD: src/include/rpcsvc/rquota.x,v 1.6 1999/08/27 23:45:10 peter Exp $";
++%#endif /* not lint */
++#endif
++
++const RQ_PATHLEN = 1024;
++
++struct getquota_args {
++ string gqa_pathp<RQ_PATHLEN>; /* path to filesystem of interest */
++ int gqa_uid; /* inquire about quota for uid */
++};
++
++/*
++ * remote quota structure
++ */
++struct rquota {
++ int rq_bsize; /* block size for block counts */
++ bool rq_active; /* indicates whether quota is active */
++ unsigned int rq_bhardlimit; /* absolute limit on disk blks alloc */
++ unsigned int rq_bsoftlimit; /* preferred limit on disk blks */
++ unsigned int rq_curblocks; /* current block count */
++ unsigned int rq_fhardlimit; /* absolute limit on allocated files */
++ unsigned int rq_fsoftlimit; /* preferred file limit */
++ unsigned int rq_curfiles; /* current # allocated files */
++ unsigned int rq_btimeleft; /* time left for excessive disk use */
++ unsigned int rq_ftimeleft; /* time left for excessive files */
++};
++
++enum gqr_status {
++ Q_OK = 1, /* quota returned */
++ Q_NOQUOTA = 2, /* noquota for uid */
++ Q_EPERM = 3 /* no permission to access quota */
++};
++
++union getquota_rslt switch (gqr_status status) {
++case Q_OK:
++ rquota gqr_rquota; /* valid if status == Q_OK */
++case Q_NOQUOTA:
++ void;
++case Q_EPERM:
++ void;
++};
++
++program RQUOTAPROG {
++ version RQUOTAVERS {
++ /*
++ * Get all quotas
++ */
++ getquota_rslt
++ RQUOTAPROC_GETQUOTA(getquota_args) = 1;
++
++ /*
++ * Get active quotas only
++ */
++ getquota_rslt
++ RQUOTAPROC_GETACTIVEQUOTA(getquota_args) = 2;
++ } = 1;
++} = 100011;
+--
+1.7.9.5
+