summaryrefslogtreecommitdiffstats
path: root/developer_cmds/rpcgen
diff options
context:
space:
mode:
Diffstat (limited to 'developer_cmds/rpcgen')
-rw-r--r--developer_cmds/rpcgen/rpc_clntout.c230
-rw-r--r--developer_cmds/rpcgen/rpc_cout.c741
-rw-r--r--developer_cmds/rpcgen/rpc_hout.c534
-rw-r--r--developer_cmds/rpcgen/rpc_main.c1170
-rw-r--r--developer_cmds/rpcgen/rpc_parse.c643
-rw-r--r--developer_cmds/rpcgen/rpc_parse.h168
-rw-r--r--developer_cmds/rpcgen/rpc_sample.c261
-rw-r--r--developer_cmds/rpcgen/rpc_scan.c521
-rw-r--r--developer_cmds/rpcgen/rpc_scan.h104
-rw-r--r--developer_cmds/rpcgen/rpc_svcout.c980
-rw-r--r--developer_cmds/rpcgen/rpc_tblout.c179
-rw-r--r--developer_cmds/rpcgen/rpc_util.c513
-rw-r--r--developer_cmds/rpcgen/rpc_util.h178
-rw-r--r--developer_cmds/rpcgen/rpcgen.1452
14 files changed, 6674 insertions, 0 deletions
diff --git a/developer_cmds/rpcgen/rpc_clntout.c b/developer_cmds/rpcgen/rpc_clntout.c
new file mode 100644
index 0000000..e0d2263
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_clntout.c
@@ -0,0 +1,230 @@
+/* $NetBSD: rpc_clntout.c,v 1.8 1997/10/18 10:53:37 lukem Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI";
+#else
+__RCSID("$NetBSD: rpc_clntout.c,v 1.8 1997/10/18 10:53:37 lukem Exp $");
+#endif
+#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_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+static void write_program __P((definition *));
+static char *ampr __P((char *));
+static void printbody __P((proc_list *));
+
+#define DEFAULT_TIMEOUT 25 /* in seconds */
+static char RESULT[] = "clnt_res";
+
+
+void
+write_stubs()
+{
+ 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(def)
+ 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, addargname, addargtype)
+ proc_list *proc;
+ char *addargname, *addargtype;
+{
+
+ decl_list *l;
+
+ if (!newstyle) { /* old style: always pass argument 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(type)
+ char *type;
+{
+ if (isvectordef(type, REL_ALIAS)) {
+ return ("");
+ } else {
+ return ("&");
+ }
+}
+
+static void
+printbody(proc)
+ 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, xdr_void", proc->proc_name);
+ f_print(fout,
+ ", NULL, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS) {\n",
+ 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, xdr_%s, &arg, xdr_%s, %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, xdr_%s, %s%s, xdr_%s, %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");
+ 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/developer_cmds/rpcgen/rpc_cout.c b/developer_cmds/rpcgen/rpc_cout.c
new file mode 100644
index 0000000..ca4eb7b
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_cout.c
@@ -0,0 +1,741 @@
+/* $NetBSD: rpc_cout.c,v 1.14 1998/08/25 20:59:40 ross Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI";
+#else
+__RCSID("$NetBSD: rpc_cout.c,v 1.14 1998/08/25 20:59:40 ross Exp $");
+#endif
+#endif
+
+/*
+ * rpc_cout.c, XDR routine outputter for the RPC protocol compiler
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+static int findtype __P((definition *, char *));
+static int undefined __P((char *));
+static void print_generic_header __P((char *, int));
+static void print_header __P((definition *));
+static void print_prog_header __P((proc_list *));
+static void print_trailer __P((void));
+static void print_ifopen __P((int, char *));
+static void print_ifarg __P((char *));
+static void print_ifsizeof __P((char *, char *));
+static void print_ifclose __P((int));
+static void print_ifstat __P((int, char *, char *, relation, char *, char *, char *));
+static void emit_enum __P((definition *));
+static void emit_program __P((definition *));
+static void emit_union __P((definition *));
+static void emit_struct __P((definition *));
+static void emit_typedef __P((definition *));
+static void print_stat __P((int, declaration *));
+
+/*
+ * Emit the C-routine for the given definition
+ */
+void
+emit(def)
+ 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;
+ case DEF_PROGRAM:
+ case DEF_CONST:
+ errx(1, "Internal error %s, %d: Case %d not handled\n",
+ __FILE__, __LINE__, def->def_kind);
+ break;
+ }
+ print_trailer();
+}
+
+static int
+findtype(def, type)
+ 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(type)
+ char *type;
+{
+ definition *def;
+
+ def = (definition *) FINDVAL(defined, type, findtype);
+
+
+ return (def == NULL);
+}
+
+static void
+print_generic_header(procname, pointerp)
+ 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");
+ } 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");
+ }
+}
+
+static void
+print_header(def)
+ definition *def;
+{
+ print_generic_header(def->def_name,
+ def->def_kind != DEF_TYPEDEF ||
+ !isvectordef(def->def.ty.old_type, def->def.ty.rel));
+}
+
+static void
+print_prog_header(plist)
+ proc_list *plist;
+{
+ print_generic_header(plist->args.argname, 1);
+}
+
+static void
+print_trailer()
+{
+ f_print(fout, "\treturn (TRUE);\n");
+ f_print(fout, "}\n");
+}
+
+
+static void
+print_ifopen(indent, name)
+ int indent;
+ char *name;
+{
+ tabify(fout, indent);
+ f_print(fout, "if (!xdr_%s(xdrs", name);
+}
+
+static void
+print_ifarg(arg)
+ char *arg;
+{
+ f_print(fout, ", %s", arg);
+}
+
+static void
+print_ifsizeof(prefix, type)
+ 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(indent)
+ int indent;
+{
+ f_print(fout, "))\n");
+ tabify(fout, indent);
+ f_print(fout, "\treturn (FALSE);\n");
+}
+
+static void
+print_ifstat(indent, prefix, type, rel, amax, objname, name)
+ 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");
+ }
+ print_ifarg("(char **)");
+ 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);
+}
+/* ARGSUSED */
+static void
+emit_enum(def)
+ definition *def;
+{
+ fprintf(fout, "\n");
+ print_ifopen(1, "enum");
+ print_ifarg("(enum_t *)objp");
+ print_ifclose(1);
+}
+
+static void
+emit_program(def)
+ 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(def)
+ definition *def;
+{
+ declaration *dflt;
+ case_list *cl;
+ declaration *cs;
+ char *object;
+ char *vecformat = "objp->%s_u.%s";
+ char *format = "&objp->%s_u.%s";
+
+ f_print(fout, "\n");
+ 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;
+ f_print(fout, "\tdefault:\n");
+ if (dflt != NULL) {
+ if (!streq(dflt->type, "void")) {
+ 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 {
+ f_print(fout, "\t\treturn (FALSE);\n");
+ }
+
+ f_print(fout, "\t}\n");
+}
+
+static void
+emit_struct(def)
+ 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;
+
+
+ if (doinline == 0) {
+ fprintf(fout, "\n");
+ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+ print_stat(1, &dl->decl);
+ return;
+ }
+ 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 >= doinline) {
+ can_inline = 1;
+ break; /* can be inlined */
+ }
+ size = 0;
+ }
+ if (size > doinline)
+ can_inline = 1;
+
+ if (can_inline == 0) { /* can not inline, drop back to old mode */
+ fprintf(fout, "\n");
+ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+ print_stat(1, &dl->decl);
+ return;
+ };
+
+ /* May cause lint to complain. but ... */
+ f_print(fout, "\tint32_t *buf;\n");
+
+ flag = PUT;
+ f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n");
+
+ for (j = 0; j < 2; j++) {
+ i = 0;
+ size = 0;
+ sizestr = NULL;
+ 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 = (char *) 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 < doinline) {
+ /* don't expand into inline
+ * code if size < doinline */
+ while (cur != dl) {
+ print_stat(2, &cur->decl);
+ cur = cur->next;
+ }
+ } else {
+
+
+
+ /* were already looking at a
+ * xdr_inlineable structure */
+ if (sizestr == NULL)
+ f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);\n",
+ size);
+ else
+ if (size == 0)
+ f_print(fout,
+ "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %s * BYTES_PER_XDR_UNIT);\n",
+ sizestr);
+ else
+ f_print(fout,
+ "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, (%d + %s) * BYTES_PER_XDR_UNIT);\n",
+ size, sizestr);
+
+ f_print(fout, "\t\tif (buf == NULL) {\n");
+
+ psav = cur;
+ while (cur != dl) {
+ print_stat(3, &cur->decl);
+ cur = cur->next;
+ }
+
+ f_print(fout, "\t\t} else {\n");
+
+ cur = psav;
+ while (cur != dl) {
+ emit_inline(&cur->decl, flag);
+ cur = cur->next;
+ }
+
+ f_print(fout, "\t\t}\n");
+ }
+ }
+ size = 0;
+ i = 0;
+ sizestr = NULL;
+ print_stat(2, &dl->decl);
+ }
+
+ }
+ if (i > 0) {
+ if (sizestr == NULL && size < doinline) {
+ /* don't expand into inline code if size <
+ * doinline */
+ while (cur != dl) {
+ print_stat(2, &cur->decl);
+ cur = cur->next;
+ }
+ } else {
+
+ /* were already looking at a xdr_inlineable
+ * structure */
+ if (sizestr == NULL)
+ f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);\n",
+ size);
+ else
+ if (size == 0)
+ f_print(fout,
+ "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %s * BYTES_PER_XDR_UNIT);\n",
+ sizestr);
+ else
+ f_print(fout,
+ "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, (%d + %s) * BYTES_PER_XDR_UNIT);\n",
+ size, sizestr);
+
+ f_print(fout, "\t\tif (buf == NULL) {\n");
+
+ psav = cur;
+ while (cur != NULL) {
+ print_stat(3, &cur->decl);
+ cur = cur->next;
+ }
+ f_print(fout, "\t\t} else {\n");
+
+ cur = psav;
+ while (cur != dl) {
+ emit_inline(&cur->decl, flag);
+ cur = cur->next;
+ }
+
+ f_print(fout, "\t\t}\n");
+
+ }
+ }
+ if (flag == PUT) {
+ flag = GET;
+ f_print(fout, "\t} else if (xdrs->x_op == XDR_DECODE) {\n");
+ }
+ }
+
+ f_print(fout, "\t} else {\n");
+
+ /* now take care of XDR_FREE case */
+
+ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+ print_stat(2, &dl->decl);
+
+ f_print(fout, "\t}\n");
+}
+
+static void
+emit_typedef(def)
+ 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;
+
+ fprintf(fout, "\n");
+ print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
+}
+
+static void
+print_stat(indent, dec)
+ declaration *dec;
+ int indent;
+{
+ 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);
+}
+
+
+void
+emit_inline(decl, flag)
+ 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\t{\n");
+ f_print(fout, "\t\t\t\tint i;\n");
+ f_print(fout, "\t\t\t\t%s *genp;\n", decl->type);
+ f_print(fout, "\n");
+ f_print(fout, "\t\t\t\tfor (i = 0, genp = objp->%s;\n",
+ decl->name);
+ f_print(fout, "\t\t\t\t i < %s; i++) {\n\t\t",
+ decl->array_max);
+ emit_single_in_line(decl, flag, REL_VECTOR);
+ f_print(fout, "\t\t\t\t}\n\t\t\t}\n");
+ break;
+ case REL_ARRAY:
+ case REL_POINTER:
+ errx(1, "Internal error %s, %d: Case %d not handled\n",
+ __FILE__, __LINE__, decl->rel);
+ }
+}
+
+void
+emit_single_in_line(decl, flag, rel)
+ declaration *decl;
+ int flag;
+ relation rel;
+{
+ char *upp_case;
+ int freed = 0;
+
+ if (flag == PUT)
+ f_print(fout, "\t\t\tIXDR_PUT_");
+ else
+ if (rel == REL_ALIAS)
+ f_print(fout, "\t\t\tobjp->%s = IXDR_GET_", decl->name);
+ else
+ f_print(fout, "\t\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 = "LONG";
+ }
+ if (strcmp(upp_case, "U_INT") == 0) {
+ free(upp_case);
+ freed = 1;
+ upp_case = "U_LONG";
+ }
+ 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);
+
+}
+
+
+char *
+upcase(str)
+ 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/developer_cmds/rpcgen/rpc_hout.c b/developer_cmds/rpcgen/rpc_hout.c
new file mode 100644
index 0000000..3b8811f
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_hout.c
@@ -0,0 +1,534 @@
+/* $NetBSD: rpc_hout.c,v 1.9 1998/02/11 23:11:17 lukem Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI";
+#else
+__RCSID("$NetBSD: rpc_hout.c,v 1.9 1998/02/11 23:11:17 lukem Exp $");
+#endif
+#endif
+
+/*
+ * rpc_hout.c, Header file outputter for the RPC protocol compiler
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <err.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+static void pconstdef __P((definition *));
+static void pargdef __P((definition *));
+static void pstructdef __P((definition *));
+static void puniondef __P((definition *));
+static void pdefine __P((char *, char *));
+static void puldefine __P((char *, char *));
+static int define_printed __P((proc_list *, version_list *));
+static void pprogramdef __P((definition *));
+static void parglist __P((proc_list *, char *));
+static void penumdef __P((definition *));
+static void ptypedef __P((definition *));
+static int undefined2 __P((char *, char *));
+
+/*
+ * Print the C-version of an xdr definition
+ */
+void
+print_datadef(def)
+ 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(def)
+ definition *def;
+{
+ switch (def->def_kind) {
+ case DEF_PROGRAM:
+ f_print(fout, "\n");
+ pprogramdef(def);
+ break;
+ case DEF_CONST:
+ case DEF_TYPEDEF:
+ case DEF_ENUM:
+ case DEF_UNION:
+ case DEF_STRUCT:
+ break;
+ }
+}
+
+void
+pxdrfuncdecl(name, pointerp)
+ char *name;
+ int pointerp;
+{
+
+ f_print(fout, "#ifdef __cplusplus\n");
+ f_print(fout, "extern \"C\" bool_t xdr_%s(XDR *, %s%s);\n",
+ name,
+ name, pointerp ? ("*") : "");
+ f_print(fout, "#elif __STDC__\n");
+ f_print(fout, "extern bool_t xdr_%s(XDR *, %s%s);\n",
+ name,
+ name, pointerp ? ("*") : "");
+ f_print(fout, "#else /* Old Style C */\n");
+ f_print(fout, "bool_t xdr_%s();\n", name);
+ f_print(fout, "#endif /* Old Style C */\n\n");
+}
+
+
+static void
+pconstdef(def)
+ 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(def)
+ 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(def)
+ 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(def)
+ 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(name, num)
+ char *name;
+ char *num;
+{
+ f_print(fout, "#define %s %s\n", name, num);
+}
+
+static void
+puldefine(name, num)
+ char *name;
+ char *num;
+{
+ f_print(fout, "#define %s ((rpc_uint)%s)\n", name, num);
+}
+
+static int
+define_printed(stop, start)
+ 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);
+ }
+ }
+ }
+ errx(1, "Internal error %s, %d: procedure not found\n",
+ __FILE__, __LINE__);
+ /* NOTREACHED */
+}
+
+static void
+pprogramdef(def)
+ 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");
+ }
+}
+
+void
+pprocdef(proc, vp, addargtype, server_p, mode)
+ 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, addargtype)
+ 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(def)
+ 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(def)
+ 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(name, dec, tab, separator)
+ 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, "%s", separator);
+}
+
+static int
+undefined2(type, stop)
+ 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/developer_cmds/rpcgen/rpc_main.c b/developer_cmds/rpcgen/rpc_main.c
new file mode 100644
index 0000000..a7a15a8
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_main.c
@@ -0,0 +1,1170 @@
+/* $NetBSD: rpc_main.c,v 1.14 1997/10/18 10:53:53 lukem Exp $ */
+
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI";
+#else
+__RCSID("$NetBSD: rpc_main.c,v 1.14 1997/10/18 10:53:53 lukem Exp $");
+#endif
+#endif
+
+/*
+ * rpc_main.c, Top level of the RPC protocol compiler.
+ */
+
+#define RPCGEN_VERSION "199506"/* This program's version (year & month) */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <err.h>
+#include <sys/types.h>
+#ifdef __TURBOC__
+#define MAXPATHLEN 80
+#include <process.h>
+#include <dir.h>
+#else
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#endif
+#include <sys/stat.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+#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 */
+
+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 *cmdname;
+
+static char *svcclosetime = "120";
+static char *CPP = "/usr/bin/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]);
+
+#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 */
+int callerflag; /* Generate svc_caller() function */
+
+#define INLINE 3
+/*length at which to start doing an inline */
+
+int doinline = 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 */
+int tirpcflag = 0; /* generating code for tirpc, by default */
+
+#ifdef __MSDOS__
+static char *dos_cppfile = NULL;
+#endif
+
+int main __P((int, char *[]));
+
+static char *extendfile __P((char *, char *));
+static void open_output __P((char *, char *));
+static void add_warning __P((void));
+static void clear_args __P((void));
+static void find_cpp __P((void));
+static void open_input __P((char *, char *));
+static int check_nettype __P((char *, char *[]));
+static void c_output __P((char *, char *, int, char *));
+static void c_initialize __P((void));
+static char *generate_guard __P((char *));
+static void h_output __P((char *, char *, int, char *));
+static void s_output __P((int, char *[], char *, char *, int, char *, int, int));
+static void l_output __P((char *, char *, int, char *));
+static void t_output __P((char *, char *, int, char *));
+static void svc_output __P((char *, char *, int, char *));
+static void clnt_output __P((char *, char *, int, char *));
+static int do_registers __P((int, char *[]));
+static void addarg __P((char *));
+static void putarg __P((int, char *));
+static void checkfiles __P((char *, char *));
+static int parseargs __P((int, char *[], struct commandline *));
+static void usage __P((void));
+static void options_usage __P((void));
+
+pid_t childpid;
+
+int
+main(argc, argv)
+ 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");
+ }
+ }
+#ifdef __MSDOS__
+ if (dos_cppfile != NULL) {
+ (void) fclose(fin);
+ (void) unlink(dos_cppfile);
+ }
+#endif
+ exit(nonfatalerrors);
+ /* NOTREACHED */
+}
+/*
+ * add extension to filename
+ */
+static char *
+extendfile(path, ext)
+ char *path;
+ char *ext;
+{
+ char *file;
+ char *res;
+ char *p;
+
+ if ((file = strrchr(path, '/')) == NULL)
+ file = path;
+ else
+ file++;
+
+ res = alloc(strlen(file) + strlen(ext) + 1);
+ if (res == NULL) {
+ errx(1, "Out of memory");
+ }
+ 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(infile, outfile)
+ 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()
+{
+ 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()
+{
+ int i;
+ for (i = FIXEDARGS; i < ARGLISTLEN; i++)
+ arglist[i] = NULL;
+ argcount = FIXEDARGS;
+}
+/* make sure that a CPP exists */
+static void
+find_cpp()
+{
+ struct stat buf;
+
+ if (stat(CPP, &buf) < 0) { /* SVR4 or explicit cpp does not exist */
+ if (cppDefined) {
+ fprintf(stderr, "cannot find C preprocessor: %s\n", CPP);
+ crash();
+ } else { /* try the other one */
+ CPP = SUNOS_CPP;
+ if (stat(CPP, &buf) < 0) { /* can't find any cpp */
+ fprintf(stderr, "cannot find any C preprocessor (cpp)\n");
+ crash();
+ }
+ }
+ }
+}
+/*
+ * Open input file with given define for C-preprocessor
+ */
+static void
+open_input(infile, define)
+ char *infile;
+ char *define;
+{
+ int pd[2];
+
+ infilename = (infile == NULL) ? "<stdin>" : infile;
+#ifdef __MSDOS__
+#define DOSCPP "\\prog\\bc31\\bin\\cpp.exe"
+ {
+ int retval;
+ char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE], ext[MAXEXT];
+ char cppfile[MAXPATH];
+ char *cpp;
+
+ if ((cpp = searchpath("cpp.exe")) == NULL
+ && (cpp = getenv("RPCGENCPP")) == NULL)
+ cpp = DOSCPP;
+
+ putarg(0, cpp);
+ putarg(1, "-P-");
+ putarg(2, CPPFLAGS);
+ addarg(define);
+ addarg(infile);
+ addarg(NULL);
+
+ retval = spawnvp(P_WAIT, arglist[0], arglist);
+ if (retval != 0) {
+ fprintf(stderr, "%s: C PreProcessor failed\n", cmdname);
+ crash();
+ }
+ fnsplit(infile, drive, dir, name, ext);
+ fnmerge(cppfile, drive, dir, name, ".i");
+
+ fin = fopen(cppfile, "r");
+ if (fin == NULL) {
+ f_print(stderr, "%s: ", cmdname);
+ perror(cppfile);
+ crash();
+ }
+ dos_cppfile = strdup(cppfile);
+ if (dos_cppfile == NULL) {
+ fprintf(stderr, "%s: out of memory\n", cmdname);
+ crash();
+ }
+ }
+#else
+ (void) pipe(pd);
+ switch (childpid = fork()) {
+ case 0:
+ find_cpp();
+ 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]);
+ execv(arglist[0], arglist);
+ perror("execv");
+ exit(1);
+ case -1:
+ perror("fork");
+ exit(1);
+ }
+ (void) close(pd[1]);
+ fin = fdopen(pd[0], "r");
+#endif
+ 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(name, list_to_check)
+ 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(infile, define, extend, outfile)
+ 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()
+{
+
+ /* add all the starting basic types */
+
+ add_type(1, "int");
+ add_type(1, "long");
+ add_type(1, "short");
+ add_type(1, "bool");
+
+ add_type(1, "u_int");
+ add_type(1, "u_long");
+ 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(pathname)
+ 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(infile, define, extend, outfile)
+ 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, "#define RPCGEN_VERSION\t%s\n\n", RPCGEN_VERSION);
+ f_print(fout, "#include <rpc/rpc.h>\n\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, "%s", rpcgen_table_dcl);
+ }
+ f_print(fout, "\n#endif /* !_%s */\n", guard);
+}
+/*
+ * Compile into an RPC service
+ */
+static void
+s_output(argc, argv, infile, define, extend, outfile, nomain, netflag)
+ 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 <sys/ioctl.h>\n");
+ f_print(fout, "#include <fcntl.h>\n");
+ f_print(fout, "#include <stdio.h>\n");
+ f_print(fout, "#include <stdlib.h>\n");
+ if (Cflag) {
+ f_print(fout, "#include <unistd.h>\n");
+ f_print(fout,
+ "#include <rpc/pmap_clnt.h>\n");
+ f_print(fout, "#include <string.h>\n");
+ }
+ f_print(fout, "#include <netdb.h>\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;
+ }
+ if (!tirpcflag && inetdflag)
+ f_print(fout, "#include <sys/ttycom.h>\n");
+ if (Cflag && (inetdflag || pmflag)) {
+ f_print(fout, "#ifdef __cplusplus\n");
+ f_print(fout, "#include <sysent.h>\n");
+ f_print(fout, "#endif /* __cplusplus */\n");
+ }
+ if (tirpcflag)
+ f_print(fout, "#include <sys/types.h>\n");
+
+ f_print(fout, "#include <memory.h>\n");
+ if (tirpcflag)
+ f_print(fout, "#include <stropts.h>\n");
+
+ 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>\n");
+ if (logflag || inetdflag || pmflag)
+ f_print(fout, "#include <syslog.h>\n");
+
+ /* 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;
+ }
+ if (callerflag) /* EVAS */
+ f_print(fout, "\nstatic SVCXPRT *caller;\n"); /* EVAS */
+ 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(infile, define, extend, outfile)
+ 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>\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(infile, define, extend, outfile)
+ 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(infile, define, extend, outfile)
+ 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(infile, define, extend, outfile)
+ 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(argc, argv)
+ 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(cp)
+ char *cp;
+{
+ if (argcount >= ARGLISTLEN) {
+ f_print(stderr, "rpcgen: too many defines\n");
+ crash();
+ /* NOTREACHED */
+ }
+ arglist[argcount++] = cp;
+
+}
+
+static void
+putarg(where, cp)
+ char *cp;
+ int where;
+{
+ 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(infile, outfile)
+ char *infile;
+ char *outfile;
+{
+
+ struct stat buf;
+
+ if (infile) /* infile ! = NULL */
+ if (stat(infile, &buf) < 0) {
+ perror(infile);
+ crash();
+ };
+#if 0
+ 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();
+ }
+ }
+#endif
+}
+/*
+ * Parse command line arguments
+ */
+static int
+parseargs(argc, argv, cmd)
+ int argc;
+ char *argv[];
+ struct commandline *cmd;
+{
+ int i;
+ int j;
+ int 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':
+ callerflag = 1;
+ break;
+ case 'a':
+ allfiles = 1;
+ break;
+ case 'c':
+ case 'h':
+ case 'l':
+ case 'm':
+ case 't':
+ if (flag[c]) {
+ return (0);
+ }
+ flag[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[c]) {
+ return (0);
+ }
+ flag[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);
+ }
+ doinline = atoi(argv[i]);
+ goto nextarg;
+ case 'n':
+ case 'o':
+ case 's':
+ if (argv[i][j - 1] != '-' ||
+ argv[i][j + 1] != 0) {
+ return (0);
+ }
+ flag[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()
+{
+ f_print(stderr, "usage: %s infile\n", cmdname);
+ f_print(stderr, "\t%s [-a][-b][-C][-Dname[=value]] -i size [-I [-K seconds]] [-A][-L][-M toolkit][-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()
+{
+ f_print(stderr, "options:\n");
+ f_print(stderr, "-A\t\tgenerate svc_caller() function\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/developer_cmds/rpcgen/rpc_parse.c b/developer_cmds/rpcgen/rpc_parse.c
new file mode 100644
index 0000000..db0c1f1
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_parse.c
@@ -0,0 +1,643 @@
+/* $NetBSD: rpc_parse.c,v 1.9 1998/02/11 23:11:18 lukem Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI";
+#else
+__RCSID("$NetBSD: rpc_parse.c,v 1.9 1998/02/11 23:11:18 lukem Exp $");
+#endif
+#endif
+
+/*
+ * rpc_parse.c, Parser for the RPC protocol compiler
+ * Copyright (C) 1987 Sun Microsystems, Inc.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "rpc/types.h"
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+#define ARGNAME "arg"
+
+static void isdefined __P((definition *));
+static void def_struct __P((definition *));
+static void def_program __P((definition *));
+static void def_enum __P((definition *));
+static void def_const __P((definition *));
+static void def_union __P((definition *));
+static void check_type_name __P((char *, int));
+static void def_typedef __P((definition *));
+static void get_declaration __P((declaration *, defkind));
+static void get_prog_declaration __P((declaration *, defkind, int));
+static void get_type __P((char **, char **, defkind));
+static void unsigned_dec __P((char **));
+
+/*
+ * return the next definition you see
+ */
+definition *
+get_definition()
+{
+ 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:
+ return (NULL);
+ default:
+ error("definition keyword expected");
+ }
+ scan(TOK_SEMICOLON, &tok);
+ isdefined(defp);
+ return (defp);
+}
+
+static void
+isdefined(defp)
+ definition *defp;
+{
+ STOREVAL(&defined, defp);
+}
+
+static void
+def_struct(defp)
+ 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(defp)
+ 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(defp)
+ 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(defp)
+ 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(defp)
+ definition *defp;
+{
+ token tok;
+ declaration dec;
+ case_list *cases;
+ case_list **tailp;
+ int flag;
+
+ 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 */
+ flag = 0;
+ 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));
+ } else
+ if (flag) {
+
+ *tailp = cases;
+ tailp = &cases->next;
+ cases = ALLOC(case_list);
+ };
+
+ 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(name, new_type)
+ int new_type;
+ char *name;
+{
+ 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(defp)
+ 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(dec, dkind)
+ 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(dec, dkind, num)
+ declaration *dec;
+ defkind dkind;
+ int num; /* arg number */
+{
+ 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 = (char *) 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(prefixp, typep, dkind)
+ 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_LONG:
+ *typep = "long";
+ (void) peekscan(TOK_INT, &tok);
+ break;
+ case TOK_HYPER:
+ *typep = "int64_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_QUAD:
+ case TOK_BOOL:
+ *typep = tok.str;
+ break;
+ default:
+ error("expected type specifier");
+ }
+}
+
+static void
+unsigned_dec(typep)
+ 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_LONG:
+ get_token(&tok);
+ *typep = "u_long";
+ (void) peekscan(TOK_INT, &tok);
+ break;
+ case TOK_HYPER:
+ get_token(&tok);
+ *typep = "u_int64_t";
+ (void) peekscan(TOK_INT, &tok);
+ break;
+ case TOK_INT:
+ get_token(&tok);
+ *typep = "u_int";
+ break;
+ default:
+ *typep = "u_int";
+ break;
+ }
+}
diff --git a/developer_cmds/rpcgen/rpc_parse.h b/developer_cmds/rpcgen/rpc_parse.h
new file mode 100644
index 0000000..e235bf5
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_parse.h
@@ -0,0 +1,168 @@
+/* $NetBSD: rpc_parse.h,v 1.4 1997/10/11 21:01:42 christos Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+/* @(#)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 __P((void));
+
+struct bas_type
+{
+ char *name;
+ int length;
+ struct bas_type *next;
+};
+
+typedef struct bas_type bas_type;
diff --git a/developer_cmds/rpcgen/rpc_sample.c b/developer_cmds/rpcgen/rpc_sample.c
new file mode 100644
index 0000000..3fee135
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_sample.c
@@ -0,0 +1,261 @@
+/* $NetBSD: rpc_sample.c,v 1.5 1997/10/18 10:54:01 lukem Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rpc_sample.c 1.1 90/08/30 (C) 1987 SMI";
+#else
+__RCSID("$NetBSD: rpc_sample.c,v 1.5 1997/10/18 10:54:01 lukem Exp $");
+#endif
+#endif
+
+/*
+ * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+static char RQSTP[] = "rqstp";
+
+static void write_sample_client __P((char *, version_list *));
+static void write_sample_server __P((definition *));
+static void return_type __P((proc_list *));
+
+void
+write_sample_svc(def)
+ definition *def;
+{
+
+ if (def->def_kind != DEF_PROGRAM)
+ return;
+ write_sample_server(def);
+}
+
+
+int
+write_sample_clnt(def)
+ 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(program_name, vp)
+ 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(def)
+ 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");
+ 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(plist)
+ proc_list *plist;
+{
+ ptype(plist->res_prefix, plist->res_type, 1);
+}
+
+void
+add_sample_msg()
+{
+ 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()
+{
+ 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/developer_cmds/rpcgen/rpc_scan.c b/developer_cmds/rpcgen/rpc_scan.c
new file mode 100644
index 0000000..4130107
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_scan.c
@@ -0,0 +1,521 @@
+/* $NetBSD: rpc_scan.c,v 1.6 1997/10/18 10:54:05 lukem Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI";
+#else
+__RCSID("$NetBSD: rpc_scan.c,v 1.6 1997/10/18 10:54:05 lukem Exp $");
+#endif
+#endif
+
+/*
+ * rpc_scan.c, Scanner for the RPC protocol compiler
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+#define startcomment(where) (where[0] == '/' && where[1] == '*')
+#define endcomment(where) (where[-1] == '*' && where[0] == '/')
+
+static void unget_token __P((token *));
+static void findstrconst __P((char **, char **));
+static void findchrconst __P((char **, char **));
+static void findconst __P((char **, char **));
+static void findkind __P((char **, token *));
+static int cppline __P((char *));
+static int directive __P((char *));
+static void printdirective __P((char *));
+static void docppline __P((char *, int *, char **));
+
+static int pushed = 0; /* is a token pushed */
+static token lasttok; /* last token, if pushed */
+
+/*
+ * scan expecting 1 given token
+ */
+void
+scan(expect, tokp)
+ tok_kind expect;
+ token *tokp;
+{
+ get_token(tokp);
+ if (tokp->kind != expect) {
+ expected1(expect);
+ }
+}
+/*
+ * scan expecting any of the 2 given tokens
+ */
+void
+scan2(expect1, expect2, tokp)
+ 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(expect1, expect2, expect3, tokp)
+ 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(tokp)
+ 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(tokp)
+ token *tokp;
+{
+ get_token(tokp);
+ unget_token(tokp);
+}
+/*
+ * Peek at the next token and scan it if it matches what you expect
+ */
+int
+peekscan(expect, tokp)
+ 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(tokp)
+ token *tokp;
+{
+ int commenting;
+ int stat = 0;
+
+ if (pushed) {
+ pushed = 0;
+ *tokp = lasttok;
+ return;
+ }
+ commenting = 0;
+ for (;;) {
+ if (*where == 0) {
+ for (;;) {
+ if (!fgets(curline, MAXLINESIZE, fin)) {
+ tokp->kind = TOK_EOF;
+ /* now check if cpp returned non NULL value */
+ waitpid(childpid, &stat, WUNTRACED);
+ if (stat > 0) {
+ /* Set return value from rpcgen */
+ nonfatalerrors = stat >> 8;
+ }
+ *where = 0;
+ return;
+ }
+ linenum++;
+ if (commenting) {
+ break;
+ } else
+ /* skip lines beginning with #pragma */
+ if (!strncmp(curline, "#pragma", 7)) *curline = 0;
+ 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(tokp)
+ token *tokp;
+{
+ lasttok = *tokp;
+ pushed = 1;
+}
+
+static void
+findstrconst(str, val)
+ 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(str, val)
+ 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(str, val)
+ 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_LONG, "long"},
+ {TOK_HYPER, "hyper"},
+ {TOK_FLOAT, "float"},
+ {TOK_DOUBLE, "double"},
+ {TOK_QUAD, "quadruple"},
+ {TOK_STRING, "string"},
+ {TOK_PROGRAM, "program"},
+ {TOK_VERSION, "version"},
+ {TOK_EOF, "??????"},
+};
+
+static void
+findkind(mark, tokp)
+ 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(line)
+ char *line;
+{
+ return (line == curline && *line == '#');
+}
+
+static int
+directive(line)
+ char *line;
+{
+ return (line == curline && *line == '%');
+}
+
+static void
+printdirective(line)
+ char *line;
+{
+ f_print(fout, "%s", line + 1);
+}
+
+static void
+docppline(line, lineno, fname)
+ 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;
+ } else {
+ *fname = file;
+ }
+ *lineno = num - 1;
+}
diff --git a/developer_cmds/rpcgen/rpc_scan.h b/developer_cmds/rpcgen/rpc_scan.h
new file mode 100644
index 0000000..e4c57c8
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_scan.h
@@ -0,0 +1,104 @@
+/* $NetBSD: rpc_scan.h,v 1.4 1997/10/11 21:01:50 christos Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+/* @(#)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_LONG,
+ TOK_HYPER,
+ TOK_UNSIGNED,
+ TOK_FLOAT,
+ TOK_DOUBLE,
+ TOK_QUAD,
+ 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 __P((tok_kind, token *));
+void scan2 __P((tok_kind, tok_kind, token *));
+void scan3 __P((tok_kind, tok_kind, tok_kind, token *));
+void scan_num __P((token *));
+void peek __P((token *));
+int peekscan __P((tok_kind, token *));
+void get_token __P((token *));
diff --git a/developer_cmds/rpcgen/rpc_svcout.c b/developer_cmds/rpcgen/rpc_svcout.c
new file mode 100644
index 0000000..cb0ed46
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_svcout.c
@@ -0,0 +1,980 @@
+/* $NetBSD: rpc_svcout.c,v 1.10 1997/10/18 10:54:07 lukem Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI";
+#else
+__RCSID("$NetBSD: rpc_svcout.c,v 1.10 1997/10/18 10:54:07 lukem Exp $");
+#endif
+#endif
+
+/*
+ * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
+ */
+#include <stdio.h>
+#include <string.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+static char RQSTP[] = "rqstp";
+static char TRANSP[] = "transp";
+static char ARG[] = "argument";
+static char RESULT[] = "result";
+static char ROUTINE[] = "local";
+
+static void p_xdrfunc __P((char *, char *));
+static void internal_proctype __P((proc_list *));
+static void write_real_program __P((definition *));
+static void write_program __P((definition *, char *));
+static void printerr __P((char *, char *));
+static void printif __P((char *, char *, char *, char *));
+static void write_inetmost __P((char *));
+static void print_return __P((char *));
+static void print_pmapunset __P((char *));
+static void print_err_message __P((char *));
+static void write_timeout_func __P((void));
+static void write_caller_func __P((void));
+static void write_pm_most __P((char *, int));
+static void write_rpc_svc_fg __P((char *, char *));
+static void open_log_file __P((char *, char *));
+
+char _errbuf[256]; /* For all messages */
+
+static void
+p_xdrfunc(rname, typename)
+ 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));
+}
+
+static void
+internal_proctype(plist)
+ 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(infile, netflag, nomain)
+ char *infile; /* our name */
+ 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, "\n\n");
+ if (Cflag)
+ f_print(fout, "int main( int argc, char* argv[] );\n");
+ f_print(fout, "\nint\n");
+ if (Cflag)
+ f_print(fout, "main( int argc, char* argv[] )\n");
+ else
+ f_print(fout, "main(argc, argv)\nint argc;\nchar *argv[];\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, "\tSVCXPRT *%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, "\tSVCXPRT *%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(transp)
+ 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(transp)
+ 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()
+{
+ 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(storage)
+ 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(def)
+ 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, "%s", 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(");
+ pvname_svc(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(def, storage)
+ definition *def;
+ char *storage;
+{
+ version_list *vp;
+ proc_list *proc;
+ int filled;
+
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ if (Cflag) {
+ f_print(fout, "\n");
+ if (storage != NULL) {
+ f_print(fout, "%s ", storage);
+ }
+ f_print(fout, "void ");
+ pvname(def->def_name, vp->vers_num);
+ f_print(fout, "(struct svc_req *%s, ", RQSTP);
+ f_print(fout, "SVCXPRT *%s);\n", TRANSP);
+ }
+ 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, "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, " 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 (callerflag)
+ f_print(fout, "\tcaller = transp;\n"); /* EVAS */
+ 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, "_");
+ }
+ if (!newstyle)
+ pvname_svc(proc->proc_name, vp->vers_num);
+ else
+ pvname(proc->proc_name, vp->vers_num);
+ 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);
+ printif("getargs", TRANSP, "(caddr_t) &", 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");
+
+ printif("freeargs", TRANSP, "(caddr_t) &", 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(err, transp)
+ char *err;
+ char *transp;
+{
+ f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
+}
+
+static void
+printif(proc, transp, prefix, arg)
+ char *proc;
+ char *transp;
+ char *prefix;
+ char *arg;
+{
+ f_print(fout, "\tif (!svc_%s(%s, xdr_%s, %s%s)) {\n",
+ proc, transp, arg, prefix, arg);
+}
+
+int
+nullproc(proc)
+ proc_list *proc;
+{
+ for (; proc != NULL; proc = proc->next) {
+ if (streq(proc->proc_num, "0")) {
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static void
+write_inetmost(infile)
+ char *infile;
+{
+ f_print(fout, "\tSVCXPRT *%s = NULL;\n", TRANSP);
+ f_print(fout, "\tint sock;\n");
+ f_print(fout, "\tint proto = 0;\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(space)
+ 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(space)
+ 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(space)
+ char *space;
+{
+ if (logflag)
+ f_print(fout, "%ssyslog(LOG_ERR, \"%%s\", \"%s\");\n", space, _errbuf);
+ else
+ if (inetdflag || pmflag)
+ f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf);
+ else
+ f_print(fout, "%sfprintf(stderr, \"%%s\", \"%s\");\n", space, _errbuf);
+}
+/*
+ * Write the server auxiliary function ( _msgout, timeout)
+ */
+void
+write_svc_aux(nomain)
+ int nomain;
+{
+ if (!logflag)
+ write_msg_out();
+ if (!nomain)
+ write_timeout_func();
+ if (callerflag) /* EVAS */
+ write_caller_func(); /* EVAS */
+}
+/*
+ * Write the _msgout function
+ */
+void
+write_msg_out()
+{
+ 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()
+{
+ if (!timerflag)
+ return;
+ if (Cflag) {
+ f_print(fout, "\n");
+ f_print(fout, "static void closedown(void);\n");
+ }
+ 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\textern fd_set svc_fdset;\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 <= (_rpcpmstart?0: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");
+}
+
+static void
+write_caller_func()
+{ /* EVAS */
+#define P(s) f_print(fout, s);
+
+ P("\n");
+ P("char *svc_caller()\n");
+ P("{\n");
+ P(" struct sockaddr_in actual;\n");
+ P(" struct hostent *hp;\n");
+ P(" static struct in_addr prev;\n");
+ P(" static char cname[128];\n\n");
+
+ P(" actual = *svc_getcaller(caller);\n\n");
+
+ P(" if (memcmp((char *)&actual.sin_addr, (char *)&prev,\n");
+ P(" sizeof(struct in_addr)) == 0)\n");
+ P(" return (cname);\n\n");
+
+ P(" prev = actual.sin_addr;\n\n");
+
+ P(" hp = gethostbyaddr((char *) &actual.sin_addr, sizeof(actual.sin_addr), AF_INET);\n");
+ P(" if (hp == NULL) { /* dummy one up */\n");
+ P(" extern char *inet_ntoa();\n");
+ P(" strcpy(cname, inet_ntoa(actual.sin_addr));\n");
+ P(" } else {\n");
+ P(" strcpy(cname, hp->h_name);\n");
+ P(" }\n\n");
+
+ P(" return (cname);\n");
+ P("}\n");
+
+#undef P
+}
+/*
+ * Write the most of port monitor support
+ */
+static void
+write_pm_most(infile, netflag)
+ 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(infile, sp)
+ 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(infile, sp)
+ char *infile;
+ char *sp;
+{
+ char *s, *p;
+
+ s = strrchr(infile, '.');
+ if (s)
+ *s = '\0';
+ p = strrchr(infile, '/');
+ if (p)
+ p++;
+ else
+ p = infile;
+ f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, p);
+ if (s)
+ *s = '.';
+}
+
+/*
+ * write a registration for the given transport for Inetd
+ */
+void
+write_inetd_register(transp)
+ 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");
+ }
+ if (inetdflag && streq(transp, "tcp")) {
+ f_print(fout, "%s\tif (_rpcpmstart)\n", sp);
+
+ f_print(fout, "%s\t\t%s = svc%s_create(%s",
+ sp, TRANSP, "fd", inetdflag ? "sock" : "RPC_ANYSOCK");
+ if (!isudp)
+ f_print(fout, ", 0, 0");
+ f_print(fout, ");\n");
+
+ f_print(fout, "%s\telse\n", sp);
+
+ f_print(fout, "%s\t\t%s = svc%s_create(%s",
+ sp, TRANSP, transp, inetdflag ? "sock" : "RPC_ANYSOCK");
+ if (!isudp)
+ f_print(fout, ", 0, 0");
+ f_print(fout, ");\n");
+
+ } else {
+ 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/developer_cmds/rpcgen/rpc_tblout.c b/developer_cmds/rpcgen/rpc_tblout.c
new file mode 100644
index 0000000..610dcd0
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_tblout.c
@@ -0,0 +1,179 @@
+/* $NetBSD: rpc_tblout.c,v 1.7 1997/10/18 10:54:11 lukem Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI";
+#else
+__RCSID("$NetBSD: rpc_tblout.c,v 1.7 1997/10/18 10:54:11 lukem Exp $");
+#endif
+#endif
+
+/*
+ * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+#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[] = "\t(char *(*)())0,\n\
+ \t(xdrproc_t)xdr_void,\t\t0,\n\
+ \t(xdrproc_t)xdr_void,\t\t0,\n";
+
+static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n";
+
+static void write_table __P((definition *));
+static void printit __P((char *, char *));
+
+void
+write_tables()
+{
+ 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(def)
+ 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, "%s", null_entry);
+ }
+ for (proc = vp->procs; proc != NULL; proc = proc->next) {
+ if (expected != 0)
+ f_print(fout, "\n");
+ current = atoi(proc->proc_num);
+ if (current != expected++) {
+ f_print(fout,
+ "/*\n * WARNING: table out of order\n */\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, "\t(char *(*)())RPCGEN_ACTION(");
+
+ /* routine to invoke */
+ if (!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, "%s", tbl_end);
+ f_print(fout, tbl_nproc, progvers, progvers, progvers);
+ }
+}
+
+static void
+printit(prefix, type)
+ 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/developer_cmds/rpcgen/rpc_util.c b/developer_cmds/rpcgen/rpc_util.c
new file mode 100644
index 0000000..f51114c
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_util.c
@@ -0,0 +1,513 @@
+/* $NetBSD: rpc_util.c,v 1.8 1997/10/18 10:54:14 lukem Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI";
+#else
+__RCSID("$NetBSD: rpc_util.c,v 1.8 1997/10/18 10:54:14 lukem Exp $");
+#endif
+#endif
+
+/*
+ * rpc_util.c, Utility routines for the RPC protocol compiler
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+#define ARGEXT "argument"
+
+static void printwhere __P((void));
+
+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 */
+
+static char *toktostr __P((tok_kind));
+static void printbuf __P((void));
+static void printwhere __P((void));
+static int findit __P((definition *, char *));
+static char *fixit __P((char *, char *));
+static int typedefed __P((definition *, char *));
+
+/*
+ * Reinitialize the world
+ */
+void
+reinitialize()
+{
+ memset(curline, 0, MAXLINESIZE);
+ where = curline;
+ linenum = 0;
+ defined = NULL;
+}
+/*
+ * string equality
+ */
+int
+streq(a, b)
+ char *a;
+ char *b;
+{
+ return (strcmp(a, b) == 0);
+}
+/*
+ * find a value in a list
+ */
+definition *
+findval(lst, val, cmp)
+ list *lst;
+ char *val;
+ int (*cmp) __P((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(def, type)
+ definition *def;
+ char *type;
+{
+ return (streq(def->def_name, type));
+}
+
+static char *
+fixit(type, orig)
+ 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(type)
+ char *type;
+{
+ return (fixit(type, type));
+}
+
+char *
+stringfix(type)
+ char *type;
+{
+ if (streq(type, "string")) {
+ return ("wrapstring");
+ } else {
+ return (type);
+ }
+}
+
+void
+ptype(prefix, type, follow)
+ 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(def, type)
+ 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(type, rel)
+ 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(str)
+ 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(pname, vnum)
+ char *pname;
+ char *vnum;
+{
+ f_print(fout, "%s_%s_svc", locase(pname), vnum);
+}
+
+void
+pvname(pname, vnum)
+ char *pname;
+ char *vnum;
+{
+ f_print(fout, "%s_%s", locase(pname), vnum);
+}
+/*
+ * print a useful (?) error message, and then die
+ */
+void
+error(msg)
+ 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()
+{
+ int i;
+
+ for (i = 0; i < nfiles; i++) {
+ (void) unlink(outfiles[i]);
+ }
+ exit(1);
+}
+
+void
+record_open(file)
+ char *file;
+{
+ if (nfiles < NFILES) {
+ outfiles[nfiles++] = file;
+ } else {
+ f_print(stderr, "too many files!\n");
+ crash();
+ }
+}
+
+static char expectbuf[100];
+
+/*
+ * 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_LONG, "long"},
+ {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()
+{
+ 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()
+{
+ 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(pname, vname)
+ char *pname;
+ char *vname;
+{
+ char *name;
+
+ name = (char *) 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(len, 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(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/developer_cmds/rpcgen/rpc_util.h b/developer_cmds/rpcgen/rpc_util.h
new file mode 100644
index 0000000..33a84b3
--- /dev/null
+++ b/developer_cmds/rpcgen/rpc_util.h
@@ -0,0 +1,178 @@
+/* $NetBSD: rpc_util.h,v 1.4 1997/10/11 21:01:58 christos Exp $ */
+/*
+ * 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 or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * 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
+ */
+
+/* @(#)rpc_util.h 1.5 90/08/29 (C) 1987 SMI */
+
+/*
+ * rpc_util.h, Useful definitions for the RPC protocol compiler
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+
+#define alloc(size) (void *)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 doinline; /* if this is 0, then do not generate inline code */
+extern int callerflag;
+
+/*
+ * Other flags related with inetd jumpstart.
+ */
+extern int indefinitewait;
+extern int exitnow;
+extern int timerflag;
+
+extern int nonfatalerrors;
+
+extern pid_t childpid;
+
+/*
+ * rpc_util routines
+ */
+
+#define STOREVAL(list,item) \
+ storeval(list,item)
+
+#define FINDVAL(list,item,finder) \
+ findval(list, item, finder)
+
+void reinitialize __P((void));
+int streq __P((char *, char *));
+definition *findval __P((list *, char *, int (*)(definition *, char *)));
+void storeval __P((list **, definition *));
+char *fixtype __P((char *));
+char *stringfix __P((char *));
+void ptype __P((char *, char *, int));
+int isvectordef __P((char *, relation));
+char *locase __P((char *));
+void pvname_svc __P((char *, char *));
+void pvname __P((char *, char *));
+void error __P((char *));
+void crash __P((void));
+void record_open __P((char *));
+void expected1 __P((tok_kind));
+void expected2 __P((tok_kind, tok_kind ));
+void expected3 __P((tok_kind, tok_kind, tok_kind));
+void tabify __P((FILE *, int));
+void record_open __P((char *));
+char *make_argname __P((char *, char *));
+void add_type __P((int, char *));
+bas_type *find_type __P((char *));
+/*
+ * rpc_cout routines
+ */
+void emit __P((definition *));
+void emit_inline __P((declaration *, int));
+void emit_single_in_line __P((declaration *, int, relation));
+char *upcase __P((char *));
+
+/*
+ * rpc_hout routines
+ */
+
+void print_datadef __P((definition *));
+void print_funcdef __P((definition *));
+void pxdrfuncdecl __P((char *, int));
+void pprocdef __P((proc_list *, version_list *, char *, int, int));
+void pdeclaration __P((char *, declaration *, int, char *));
+
+/*
+ * rpc_svcout routines
+ */
+void write_most __P((char *, int, int));
+void write_netid_register __P((char *));
+void write_nettype_register __P((char *));
+void write_rest __P((void));
+void write_programs __P((char *));
+int nullproc __P((proc_list *));
+void write_svc_aux __P((int));
+void write_msg_out __P((void));
+void write_inetd_register __P((char *));
+
+/*
+ * rpc_clntout routines
+ */
+void write_stubs __P((void));
+void printarglist __P((proc_list *, char *, char *));
+
+
+/*
+ * rpc_tblout routines
+ */
+void write_tables __P((void));
+
+/*
+ * rpc_sample routines
+ */
+void write_sample_svc __P((definition *));
+int write_sample_clnt __P((definition *));
+void add_sample_msg __P((void));
+void write_sample_clnt_main __P((void));
diff --git a/developer_cmds/rpcgen/rpcgen.1 b/developer_cmds/rpcgen/rpcgen.1
new file mode 100644
index 0000000..a5764a6
--- /dev/null
+++ b/developer_cmds/rpcgen/rpcgen.1
@@ -0,0 +1,452 @@
+.\" $NetBSD: rpcgen.1,v 1.8 1998/04/28 07:19:29 fair Exp $
+.\" from: @(#)rpcgen.new.1 1.1 90/11/09 TIRPC 1.0; from 40.10 of 10/10/89
+.\" Copyright (c) 1988,1990 Sun Microsystems, Inc. - All Rights Reserved.
+.Dd June 11, 1995
+.Dt RPCGEN 1
+.Sh NAME
+.Nm rpcgen
+.Nd Remote Procedure Call (RPC) protocol compiler
+.Sh SYNOPSIS
+.Nm
+.Ar infile
+.Nm
+.Op Fl D Op Ar name=value
+.Op Fl A
+.Op Fl M
+.Op Fl T
+.Op Fl K Ar secs
+.Ar infile
+.Nm
+.Op Fl L
+.Fl c Li |
+.Fl h Li |
+.Fl l Li |
+.Fl m Li |
+.Fl t Li |
+.Fl S\&c Li |
+.Fl S\&s Li |
+.Op Fl o Ar outfile
+.Op Ar infile
+.Nm
+.Fl c Li |
+.Ar nettype
+.Op Fl o Ar outfile
+.Op Ar infile
+.Nm
+.Fl s Li |
+.Ar netid
+.Op Fl o Ar outfile
+.Op Ar infile
+.Sh DESCRIPTION
+.Nm
+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).
+.Nm
+is normally used as in the first synopsis where
+it takes an input file and generates up to four output files.
+If the
+.Ar infile
+is named
+.Pa proto.x ,
+then
+.Nm
+will generate a header file in
+.Pa proto.h ,
+.Tn 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 will also generate the
+.Tn RPC
+dispatch table in
+.Pa proto_tbl.i .
+With the
+.Fl S\&c
+option,
+it will also generate sample code which would illustrate how to use the
+remote procedures on the client side. This code would be created in
+.Pa proto_client.c .
+With the
+.Fl S\&s
+option,
+it will also generate a sample server code which would illustrate how to write
+the remote procedures. This code would be created in
+.Pa proto_server.c .
+.Pp
+The server created can be started both by the port monitors
+(for example,
+.Em inetd
+or
+.Em listen )
+or by itself.
+When it is started by a port monitor,
+it creates servers only for the transport for which
+the file descriptor 0 was passed.
+The name of the transport must be specified
+by setting up the environmental 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.
+.Pp
+.Em 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
+.Dv RPC_SVC_FG
+can be used to run the server process in foreground.
+.P
+The second synopsis provides special features which allow
+for the creation of more sophisticated
+.Tn RPC
+servers.
+These features include support for user provided
+.Li #defines
+and
+.Tn RPC
+dispatch tables.
+The entries in the
+.Tn RPC
+dispatch table contain:
+.Pp
+.Bl -inset -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
+.Pp
+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
+.Tn 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.
+Some examples of their usage is described in the
+EXAMPLE
+section below.
+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
+.Em netid .
+If
+.Ar infile
+is not specified,
+.Nm
+accepts the standard input.
+.Pp
+The C preprocessor,
+.Xr cpp 1
+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 RPC_CLNT
+.It Dv RPC_HDR
+defined when compiling into header files
+.It Dv RPC_XDR
+defined when compiling into
+.Tn XDR
+routines
+.It Dv RPC_SVC
+defined when compiling into server-side stubs
+.It Dv RPC_CLNT
+defined when compiling into client-side stubs
+.It Dv RPC_TBL
+defined when compiling into
+.Tn RPC
+dispatch tables
+.El
+.Pp
+Any line beginning with
+.Sq %
+is passed directly into the output file,
+uninterpreted by
+.Nm .
+.Pp
+For every data type referred to in
+.Ar infile
+.Nm
+assumes that there exists a
+routine with the string
+.Dq 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
+.Tn XDR
+routines.
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl a
+Generate all the files including sample code for client and server side.
+.It Fl b
+This generates code for the
+.Tn "SunOS 4.1"
+style of
+.Tn RPC .
+This is the default.
+.It Fl C
+Generate code in
+.Tn ANSI
+C.
+This option also generates code that could be compiled with the
+C++ compiler.
+.It Fl c
+Compile into
+.Tn XDR
+routines.
+.It Fl D Ar name Ns Op Ar =value
+Define a symbol
+.Dv name .
+Equivalent to the
+.Dv #define
+directive in the source.
+If no
+.Dv value
+is given,
+.Dv value
+is defined as 1.
+This option may be specified more than once.
+.It Fl h
+Compile into C data-definitions (a header file).
+The
+.Fl T
+option can be used in conjunction to produce a
+header file which supports
+.Tn RPC
+dispatch tables.
+.It Fl K Ar secs
+By default, services created using
+.Nm
+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,
+.Dq Fl K No 0
+can be used.
+To create a server that never exits, the appropriate argument is
+.Dq Fl K No -1 .
+.Pp
+When monitoring for a server,
+some port monitors, like the
+.At V.4
+utility
+.Xr listen 1 ,
+.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
+.Dq Fl K No -1 .
+.It Fl L
+Server errors will be sent to syslog instead of stderr.
+.It Fl l
+Compile into client-side stubs.
+.It Fl m
+Compile into server-side stubs,
+but do not generate a
+.Fn main
+routine.
+This option is useful for doing callback-routines
+and for users who need to write their own
+.Fn main
+routine to do initialization.
+.It Fl N
+Use the newstyle of
+.Nm .
+This 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 the argument itself.
+This behaviour is different from the oldstyle
+of
+.Nm
+generated code.
+The newstyle is not the default case because of backward compatibility.
+.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
+.Po
+.Fl c Fl h Fl l
+.Fl m Fl n Fl s
+modes only
+.Pc
+.It Fl S\&c
+Generate sample code to show the use of remote procedure and how to bind
+to the server before calling the client side stubs generated by
+.Nm .
+.It Fl S\&s
+Generate skeleton code for the remote procedures on the server side. You would need
+to fill in the actual code for the remote procedures.
+.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.
+.Em Note:
+.Bx
+currently supports only the
+.Em tcp
+and
+.Em udp
+classes].
+This option may be specified more than once.
+.Em Note:
+the transports are chosen at run time and not at compile time.
+.It Fl T
+Generate the code to support
+.Tn RPC
+dispatch tables.
+.It Fl t
+Compile into
+.Tn RPC
+dispatch table.
+.El
+.Pp
+The options
+.Fl c ,
+.Fl h ,
+.Fl l ,
+.Fl m ,
+.Fl s ,
+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.
+.Sh NOTES
+The
+.Tn RPC
+Language does not support nesting of structures.
+As a work-around,
+structures can be declared at the top-level,
+and their name used inside other structures in
+order to achieve the same effect.
+.Pp
+Name clashes can occur when using program definitions,
+since the apparent scoping does not really apply.
+Most of these can be avoided by giving
+unique names for programs,
+versions,
+procedures and types.
+.Pp
+The server code generated with
+.Fl n
+option refers to the transport indicated by
+.Em netid
+and hence is very site specific.
+.Sh EXAMPLE
+.Pp
+The command
+.Pp
+.Bd -literal -offset indent
+$ rpcgen -T prot.x
+.Ed
+.Pp
+generates 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 file)
+to standard output.
+.Pp
+.Bd -literal -offset indent
+$ rpcgen -h prot.x
+.Ed
+.Pp
+To send the test version of the
+.Dv -DTEST ,
+server side stubs for
+all the transport belonging to the class
+.Em datagram_n
+to standard output, use:
+.Pp
+.Bd -literal -offset indent
+$ rpcgen -s datagram_n -DTEST prot.x
+.Ed
+.Pp
+To create the server side stubs for the transport indicated by
+.Em netid
+.Em tcp ,
+use:
+.Pp
+.Bd -literal -offset indent
+$ rpcgen -n tcp -o prot_svc.c prot.x
+.Ed
+.Sh SEE ALSO
+.Xr cpp 1