diff options
author | wpaul <wpaul@FreeBSD.org> | 1995-12-13 03:21:09 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1995-12-13 03:21:09 +0000 |
commit | c4bda74e8af091bd88fd1d338b0408ced2967a4d (patch) | |
tree | 7b15f8667f850d441bc04980c58773734aeaad24 /usr.bin/rpcgen | |
parent | e16baf7a5fe7ac1453381d0017ed1dcdeefbc995 (diff) | |
download | FreeBSD-src-c4bda74e8af091bd88fd1d338b0408ced2967a4d.zip FreeBSD-src-c4bda74e8af091bd88fd1d338b0408ced2967a4d.tar.gz |
Import a newer and more functional version of rpcgen.
Obtained from: the Sun TI-RPC 2.3 source distribution
Diffstat (limited to 'usr.bin/rpcgen')
-rw-r--r-- | usr.bin/rpcgen/Makefile | 14 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_clntout.c | 279 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_cout.c | 521 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_hout.c | 319 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_main.c | 1133 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_parse.c | 272 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_parse.h | 64 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_sample.c | 311 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_scan.c | 93 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_scan.h | 42 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_svcout.c | 970 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_tblout.c | 171 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_util.c | 213 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpc_util.h | 134 | ||||
-rw-r--r-- | usr.bin/rpcgen/rpcgen.1 | 684 |
15 files changed, 4591 insertions, 629 deletions
diff --git a/usr.bin/rpcgen/Makefile b/usr.bin/rpcgen/Makefile index fefab49..d0e4c14 100644 --- a/usr.bin/rpcgen/Makefile +++ b/usr.bin/rpcgen/Makefile @@ -1,7 +1,13 @@ -# $Id: Makefile,v 1.1 1993/09/13 23:20:11 jtc Exp $ +SRCS= rpc_main.c rpc_clntout.c rpc_cout.c rpc_hout.c rpc_parse.c \ + rpc_sample.c rpc_scan.c rpc_svcout.c rpc_tblout.c rpc_util.c -PROG= rpcgen -SRCS= rpc_clntout.c rpc_cout.c rpc_hout.c rpc_main.c rpc_parse.c rpc_scan.c \ - rpc_svcout.c rpc_util.c +PROG= rpcgen +MAN1= rpcgen.1 + +# +# This is a kludge to work around the fact that this program +# uses 'inline' as a variable name. +# +CFLAGS+=-Dinline=rpcgen_inline .include <bsd.prog.mk> diff --git a/usr.bin/rpcgen/rpc_clntout.c b/usr.bin/rpcgen/rpc_clntout.c index 73cb97d..9137ce1 100644 --- a/usr.bin/rpcgen/rpc_clntout.c +++ b/usr.bin/rpcgen/rpc_clntout.c @@ -1,4 +1,3 @@ -/* @(#)rpc_clntout.c 2.1 88/08/01 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -27,9 +26,11 @@ * 2550 Garcia Avenue * Mountain View, California 94043 */ + +#ident "@(#)rpc_clntout.c 1.15 94/04/25 SMI" + #ifndef lint -/*static char sccsid[] = "from: @(#)rpc_clntout.c 1.2 87/06/24 (C) 1987 SMI";*/ -static char rcsid[] = "$Id: rpc_clntout.c,v 1.1 1993/09/13 23:20:12 jtc Exp $"; +static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI"; #endif /* @@ -37,13 +38,20 @@ static char rcsid[] = "$Id: rpc_clntout.c,v 1.1 1993/09/13 23:20:12 jtc Exp $"; * Copyright (C) 1987, Sun Microsytsems, Inc. */ #include <stdio.h> -#include <strings.h> +#include <string.h> +#include <rpc/types.h> #include "rpc_parse.h" #include "rpc_util.h" -#define DEFAULT_TIMEOUT 25 /* in seconds */ +extern int pdeclaration __P(( char *, declaration *, int, char * )); +void printarglist __P(( proc_list *, char *, char *, char *)); +static int write_program __P(( definition * )); +static int printbody __P(( proc_list * )); -static int write_program(), printbody(); +static char RESULT[] = "clnt_res"; + + +#define DEFAULT_TIMEOUT 25 /* in seconds */ void @@ -52,9 +60,9 @@ 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", + 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; @@ -64,7 +72,6 @@ write_stubs() } } - static write_program(def) definition *def; @@ -75,21 +82,131 @@ write_program(def) 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); - f_print(fout, "(argp, clnt)\n"); - f_print(fout, "\t"); - ptype(proc->arg_prefix, proc->arg_type, 1); - f_print(fout, "*argp;\n"); - f_print(fout, "\tCLIENT *clnt;\n"); + if (mtflag == 0) { + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*\n"); + pvname(proc->proc_name, vp->vers_num); + printarglist(proc, RESULT, "clnt", "CLIENT *"); + } else { + f_print(fout, "enum clnt_stat \n"); + pvname(proc->proc_name, vp->vers_num); + printarglist(proc, RESULT, "clnt", "CLIENT *"); + + } f_print(fout, "{\n"); printbody(proc); - f_print(fout, "}\n\n"); + + 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, result, addargname, addargtype) + proc_list *proc; + char *result; + 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); + + if (mtflag) {/* Generate result field */ + f_print(fout, "*argp, "); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*%s, %s%s)\n", + result, addargtype, addargname); + } else + f_print(fout, "*argp, %s%s)\n", addargtype, addargname); + } else { + if (!mtflag) + f_print(fout, "(argp, %s)\n", addargname); + else + f_print(fout, "(argp, %s, %s)\n", + result, addargname); + f_print(fout, "\t"); + ptype(proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 1); + f_print(fout, "*argp;\n"); + if (mtflag) { + f_print(fout, "\t"); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*%s;\n", result); + } + } + } else if (streq(proc->args.decls->decl.type, "void")) { + /* newstyle, 0 argument */ + if (mtflag) { + f_print(fout, "("); + + + if (Cflag) { + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*%s, %s%s)\n", + result, addargtype, addargname); + } + else + f_print(fout, "(%s)\n", addargname); + + } else + 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); + if (mtflag) + f_print(fout, "%s, ", result); + + f_print(fout, "%s)\n", addargname); + for (l = proc->args.decls; l != NULL; l = l->next) { + pdeclaration(proc->args.argname, + &l->decl, 1, ";\n"); + } + if (mtflag) { + f_print(fout, "\t"); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*%s;\n", result); + } + + } else { /* C++ style header */ + f_print(fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) { + pdeclaration(proc->args.argname, &l->decl, 0, + ", "); + } + if (mtflag) { + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*%s, ", result); + + } + 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; @@ -105,26 +222,110 @@ static printbody(proc) proc_list *proc; { - f_print(fout, "\tstatic "); - if (streq(proc->res_type, "void")) { - f_print(fout, "char "); - } else { - ptype(proc->res_prefix, proc->res_type, 0); + decl_list *l; + bool_t args2 = (proc->arg_num > 1); + int i; + + /* + * 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, "res;\n"); - f_print(fout, "\n"); - f_print(fout, "\tbzero((char *)%sres, sizeof(res));\n", - ampr(proc->res_type)); - f_print(fout, - "\tif (clnt_call(clnt, %s, xdr_%s, argp, xdr_%s, %sres, TIMEOUT) != RPC_SUCCESS) {\n", - proc->proc_name, stringfix(proc->arg_type), - stringfix(proc->res_type), ampr(proc->res_type)); - f_print(fout, "\t\treturn (NULL);\n"); - f_print(fout, "\t}\n"); - if (streq(proc->res_type, "void")) { - f_print(fout, "\treturn ((void *)%sres);\n", - ampr(proc->res_type)); - } else { - f_print(fout, "\treturn (%sres);\n", ampr(proc->res_type)); + if (!mtflag) { + 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 */ + + if (mtflag) + f_print(fout, "\t return "); + else + f_print(fout, "\t if "); + + f_print(fout, + "(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_void, ", + proc->proc_name); + f_print(fout, + "(caddr_t) NULL,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,", + stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type), + RESULT); + + if (mtflag) + f_print(fout, "\n\t\tTIMEOUT));\n}\n"); + else + f_print(fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n"); + + } 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); + } + if (mtflag) + f_print(fout, "\treturn "); + else + f_print(fout, "\tif "); + f_print(fout, + "(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s", + proc->proc_name,proc->args.argname); + f_print(fout, + ", (caddr_t) &arg,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,", + stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type), + RESULT); + if (mtflag) + f_print(fout, "\n\t\tTIMEOUT));\n"); + else + f_print(fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n"); + } else { /* single argument, new or old style */ + if (!mtflag) + f_print(fout, + "\tif (clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\tTIMEOUT) != 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); + else + + f_print(fout, + "\treturn (clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\tTIMEOUT));\n", + proc->proc_name, + stringfix(proc->args.decls->decl.type), + (newstyle ? "&" : ""), + (newstyle ? proc->args.decls->decl.name : "argp"), + stringfix(proc->res_type), "", + RESULT); + } + if (!mtflag) { + f_print(fout, "\t\treturn (NULL);\n"); + f_print(fout, "\t}\n"); + + if (streq(proc->res_type, "void")) { + f_print(fout, "\treturn ((void *)%s%s);\n", + ampr(proc->res_type), RESULT); + } else { + f_print(fout, "\treturn (%s%s);\n", + ampr(proc->res_type), RESULT); + } } } diff --git a/usr.bin/rpcgen/rpc_cout.c b/usr.bin/rpcgen/rpc_cout.c index 9e2e361..e79ac9d 100644 --- a/usr.bin/rpcgen/rpc_cout.c +++ b/usr.bin/rpcgen/rpc_cout.c @@ -1,4 +1,3 @@ -/* @(#)rpc_cout.c 2.1 88/08/01 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -27,34 +26,55 @@ * 2550 Garcia Avenue * Mountain View, California 94043 */ + +#ident "@(#)rpc_cout.c 1.14 93/07/05 SMI" + #ifndef lint -/*static char sccsid[] = "from: @(#)rpc_cout.c 1.8 87/06/24 (C) 1987 SMI";*/ -static char rcsid[] = "$Id: rpc_cout.c,v 1.1 1993/09/13 23:20:13 jtc Exp $"; +static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI"; #endif /* - * rpc_cout.c, XDR routine outputter for the RPC protocol compiler - * Copyright (C) 1987, Sun Microsystems, Inc. + * rpc_cout.c, XDR routine outputter for the RPC protocol compiler + * Copyright (C) 1987, Sun Microsystems, Inc. */ #include <stdio.h> -#include <strings.h> -#include "rpc_util.h" +#include <string.h> #include "rpc_parse.h" +#include "rpc_util.h" -static int print_header(), print_trailer(), space(), emit_enum(), - emit_union(), emit_struct(), emit_typedef(), print_stat(); - +static int print_header __P(( definition * )); +static int print_trailer __P(( void )); +static int print_stat __P(( int , declaration * )); +static int emit_enum __P(( definition * )); +static int emit_program __P(( definition * )); +static int emit_union __P(( definition * )); +static int emit_struct __P(( definition * )); +static int emit_typedef __P(( definition * )); /* - * Emit the C-routine for the given definition + * Emit the C-routine for the given definition */ void emit(def) definition *def; { - if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) { + 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: @@ -78,6 +98,7 @@ findtype(def, type) definition *def; char *type; { + if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) { return (0); } else { @@ -97,20 +118,55 @@ undefined(type) static -print_header(def) - definition *def; +print_generic_header(procname, pointerp) + char* procname; + int pointerp; { - space(); + f_print(fout, "\n"); f_print(fout, "bool_t\n"); - f_print(fout, "xdr_%s(xdrs, objp)\n", def->def_name); - f_print(fout, "\tXDR *xdrs;\n"); - f_print(fout, "\t%s ", def->def_name); - if (def->def_kind != DEF_TYPEDEF || - !isvectordef(def->def.ty.old_type, def->def.ty.rel)) { - f_print(fout, "*"); + if (Cflag) { + f_print(fout, "xdr_%s(", procname); + f_print(fout, "register XDR *xdrs, "); + f_print(fout, "%s ", procname); + if (pointerp) + f_print(fout, "*"); + f_print(fout, "objp)\n{\n\n"); + } else { + f_print(fout, "xdr_%s(xdrs, objp)\n", procname); + f_print(fout, "\tregister XDR *xdrs;\n"); + f_print(fout, "\t%s ", procname); + if (pointerp) + f_print(fout, "*"); + f_print(fout, "objp;\n{\n\n"); } - f_print(fout, "objp;\n"); - f_print(fout, "{\n"); +} + +static +print_header(def) + definition *def; +{ + + decl_list *dl; + bas_type *ptr; + int i; + + print_generic_header(def->def_name, + def->def_kind != DEF_TYPEDEF || + !isvectordef(def->def.ty.old_type, + def->def.ty.rel)); + /* Now add Inline support */ + + if (inline == 0) + return; + /* May cause lint to complain. but ... */ + f_print(fout, "\tregister long *buf;\n\n"); +} + +static +print_prog_header(plist) + proc_list *plist; +{ + print_generic_header(plist->args.argname, 1); } static @@ -118,7 +174,6 @@ print_trailer() { f_print(fout, "\treturn (TRUE);\n"); f_print(fout, "}\n"); - space(); } @@ -131,7 +186,6 @@ print_ifopen(indent, name) f_print(fout, "if (!xdr_%s(xdrs", name); } - static print_ifarg(arg) char *arg; @@ -139,20 +193,26 @@ print_ifarg(arg) f_print(fout, ", %s", arg); } - static -print_ifsizeof(prefix, type) +print_ifsizeof(indent, prefix, type) + int indent; char *prefix; char *type; { + if (indent) { + f_print(fout, ",\n"); + tabify(fout, indent); + } else { + f_print(fout, ", "); + } if (streq(type, "bool")) { - f_print(fout, ", sizeof(bool_t), xdr_bool"); + f_print(fout, "sizeof (bool_t), (xdrproc_t) xdr_bool"); } else { - f_print(fout, ", sizeof("); + f_print(fout, "sizeof ("); if (undefined(type) && prefix) { f_print(fout, "%s ", prefix); } - f_print(fout, "%s), xdr_%s", type, type); + f_print(fout, "%s), (xdrproc_t) xdr_%s", type, type); } } @@ -160,17 +220,9 @@ static print_ifclose(indent) int indent; { - f_print(fout, ")) {\n"); + f_print(fout, "))\n"); tabify(fout, indent); f_print(fout, "\treturn (FALSE);\n"); - tabify(fout, indent); - f_print(fout, "}\n"); -} - -static -space() -{ - f_print(fout, "\n\n"); } static @@ -190,7 +242,7 @@ print_ifstat(indent, prefix, type, rel, amax, objname, name) print_ifopen(indent, "pointer"); print_ifarg("(char **)"); f_print(fout, "%s", objname); - print_ifsizeof(prefix, type); + print_ifsizeof(0, prefix, type); break; case REL_VECTOR: if (streq(type, "string")) { @@ -208,7 +260,7 @@ print_ifstat(indent, prefix, type, rel, amax, objname, name) } print_ifarg(amax); if (!alt) { - print_ifsizeof(prefix, type); + print_ifsizeof(indent + 1, prefix, type); } break; case REL_ARRAY: @@ -228,16 +280,17 @@ print_ifstat(indent, prefix, type, rel, amax, objname, name) } print_ifarg("(char **)"); if (*objname == '&') { - f_print(fout, "%s.%s_val, (u_int *)%s.%s_len", + 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", + f_print(fout, + "&%s->%s_val, (u_int *) &%s->%s_len", objname, name, objname, name); } } print_ifarg(amax); if (!alt) { - print_ifsizeof(prefix, type); + print_ifsizeof(indent + 1, prefix, type); } break; case REL_ALIAS: @@ -248,7 +301,6 @@ print_ifstat(indent, prefix, type, rel, amax, objname, name) print_ifclose(indent); } - /* ARGSUSED */ static emit_enum(def) @@ -259,6 +311,26 @@ emit_enum(def) print_ifclose(1); } +static +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 emit_union(def) @@ -268,19 +340,29 @@ emit_union(def) case_list *cl; declaration *cs; char *object; + char *vecformat = "objp->%s_u.%s"; char *format = "&objp->%s_u.%s"; - print_stat(&def->def.un.enum_decl); + 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) { - cs = &cl->case_decl; + 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); - s_print(object, format, def->def_name, cs->name); - print_ifstat(2, cs->prefix, cs->type, cs->rel, cs->array_max, - object, cs->name); + 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"); @@ -290,10 +372,17 @@ emit_union(def) if (!streq(dflt->type, "void")) { f_print(fout, "\tdefault:\n"); object = alloc(strlen(def->def_name) + strlen(format) + - strlen(dflt->name) + 1); - s_print(object, format, def->def_name, dflt->name); +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); + dflt->array_max, object, dflt->name); free(object); f_print(fout, "\t\tbreak;\n"); } @@ -301,24 +390,238 @@ emit_union(def) f_print(fout, "\tdefault:\n"); f_print(fout, "\t\treturn (FALSE);\n"); } + f_print(fout, "\t}\n"); } +static void +inline_struct(def, flag) +definition *def; +int flag; +{ + decl_list *dl; + int i, size; + decl_list *cur, *psav; + bas_type *ptr; + char *sizestr, *plus; + char ptemp[256]; + int indent = 1; + + if (flag == PUT) + f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n"); + else + f_print(fout, "\t\treturn (TRUE);\n\t} else if (xdrs->x_op == XDR_DECODE) {\n"); + + 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 code is required to handle arrays */ + if (sizestr == NULL) + plus = ""; + else + plus = " + "; + + if (ptr->length != 1) + s_print(ptemp, "%s%s * %d", + plus, dl->decl.array_max, + ptr->length); + else + s_print(ptemp, "%s%s", plus, + dl->decl.array_max); + + /* now concatenate to sizestr !!!! */ + if (sizestr == NULL) + sizestr = strdup(ptemp); + else{ + sizestr = realloc(sizestr, + strlen(sizestr) + +strlen(ptemp)+1); + if (sizestr == NULL){ + f_print(stderr, + "Fatal error : no memory\n"); + crash(); + }; + sizestr = strcat(sizestr, ptemp); + /* build up length of array */ + } + } + } else { + if (i > 0) + if (sizestr == NULL && size < inline){ + /* + * don't expand into inline code + * if size < inline + */ + while (cur != dl){ + print_stat(indent + 1, &cur->decl); + cur = cur->next; + } + } else { + /* were already looking at a xdr_inlineable structure */ + tabify(fout, indent + 1); + if (sizestr == NULL) + f_print(fout, "buf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);", + size); + else + if (size == 0) + f_print(fout, + "buf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);", + sizestr); + else + f_print(fout, + "buf = XDR_INLINE(xdrs, (%d + (%s)) * BYTES_PER_XDR_UNIT);", + size, sizestr); + + f_print(fout, "\n"); + tabify(fout, indent + 1); + f_print(fout, + "if (buf == NULL) {\n"); + + psav = cur; + while (cur != dl){ + print_stat(indent + 2, &cur->decl); + cur = cur->next; + } + + f_print(fout, "\n\t\t} else {\n"); + + cur = psav; + while (cur != dl){ + emit_inline(indent + 2, &cur->decl, flag); + cur = cur->next; + } + + tabify(fout, indent + 1); + f_print(fout, "}\n"); + } + size = 0; + i = 0; + sizestr = NULL; + print_stat(indent + 1, &dl->decl); + } + } + + if (i > 0) + if (sizestr == NULL && size < inline){ + /* don't expand into inline code if size < inline */ + while (cur != dl){ + print_stat(indent + 1, &cur->decl); + cur = cur->next; + } + } else { + /* were already looking at a xdr_inlineable structure */ + if (sizestr == NULL) + f_print(fout, "\t\tbuf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);", + size); + else + if (size == 0) + f_print(fout, + "\t\tbuf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);", + sizestr); + else + f_print(fout, + "\t\tbuf = XDR_INLINE(xdrs, (%d + (%s)) * BYTES_PER_XDR_UNIT);", + size, sizestr); + + f_print(fout, "\n\t\tif (buf == NULL) {\n"); + psav = cur; + while (cur != NULL){ + print_stat(indent + 2, &cur->decl); + cur = cur->next; + } + f_print(fout, "\t\t} else {\n"); + cur = psav; + while (cur != dl){ + emit_inline(indent + 2, &cur->decl, flag); + cur = cur->next; + } + f_print(fout, "\t\t}\n"); + } +} static emit_struct(def) definition *def; { decl_list *dl; + int i, j, size, flag; + bas_type *ptr; + int can_inline; + + if (inline == 0) { + /* No xdr_inlining at all */ + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat(1, &dl->decl); + return; + } + + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + if (dl->decl.rel == REL_VECTOR){ + f_print(fout, "\tint i;\n"); + break; + } - for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { - print_stat(&dl->decl); + size = 0; + can_inline = 0; + /* + * Make a first pass and see if inling is possible. + */ + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + if ((dl->decl.prefix == NULL) && + ((ptr = find_type(dl->decl.type)) != NULL) && + ((dl->decl.rel == REL_ALIAS)|| + (dl->decl.rel == REL_VECTOR))){ + if (dl->decl.rel == REL_ALIAS) + size += ptr->length; + else { + can_inline = 1; + break; /* can be inlined */ + } + } else { + if (size >= inline){ + can_inline = 1; + break; /* can be inlined */ + } + size = 0; + } + if (size >= inline) + can_inline = 1; + + if (can_inline == 0){ /* can not inline, drop back to old mode */ + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat(1, &dl->decl); + return; } -} + flag = PUT; + for (j = 0; j < 2; j++){ + inline_struct(def, flag); + if (flag == PUT) + flag = GET; + } + + f_print(fout, "\t\treturn (TRUE);\n\t}\n\n"); + + /* now take care of XDR_FREE case */ + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat(1, &dl->decl); +} static emit_typedef(def) @@ -332,12 +635,9 @@ emit_typedef(def) print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name); } - - - - static -print_stat(dec) +print_stat(indent, dec) + int indent; declaration *dec; { char *prefix = dec->prefix; @@ -351,5 +651,102 @@ print_stat(dec) } else { s_print(name, "&objp->%s", dec->name); } - print_ifstat(1, prefix, type, rel, amax, name, dec->name); + print_ifstat(indent, prefix, type, rel, amax, name, dec->name); +} + + +char *upcase (); + +emit_inline(indent, decl, flag) +int indent; +declaration *decl; +int flag; +{ + switch (decl->rel) { + case REL_ALIAS : + emit_single_in_line(indent, decl, flag, REL_ALIAS); + break; + case REL_VECTOR : + tabify(fout, indent); + f_print(fout, "{\n"); + tabify(fout, indent + 1); + f_print(fout, "register %s *genp;\n\n", decl->type); + tabify(fout, indent + 1); + f_print(fout, + "for (i = 0, genp = objp->%s;\n", decl->name); + tabify(fout, indent + 2); + f_print(fout, "i < %s; i++) {\n", decl->array_max); + emit_single_in_line(indent + 2, decl, flag, REL_VECTOR); + tabify(fout, indent + 1); + f_print(fout, "}\n"); + tabify(fout, indent); + f_print(fout, "}\n"); + } +} + +emit_single_in_line(indent, decl, flag, rel) +int indent; +declaration *decl; +int flag; +relation rel; +{ + char *upp_case; + int freed = 0; + + tabify(fout, indent); + if (flag == PUT) + f_print(fout, "IXDR_PUT_"); + else + if (rel == REL_ALIAS) + f_print(fout, "objp->%s = IXDR_GET_", decl->name); + else + f_print(fout, "*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/usr.bin/rpcgen/rpc_hout.c b/usr.bin/rpcgen/rpc_hout.c index 8ccd433..ae73454 100644 --- a/usr.bin/rpcgen/rpc_hout.c +++ b/usr.bin/rpcgen/rpc_hout.c @@ -1,4 +1,3 @@ -/* @(#)rpc_hout.c 2.1 88/08/01 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -27,31 +26,48 @@ * 2550 Garcia Avenue * Mountain View, California 94043 */ + +#ident "@(#)rpc_hout.c 1.16 94/04/25 SMI" + #ifndef lint -/*static char sccsid[] = "from: @(#)rpc_hout.c 1.6 87/07/28 (C) 1987 SMI";*/ -static char rcsid[] = "$Id: rpc_hout.c,v 1.1 1993/09/13 23:20:14 jtc Exp $"; +static char sccsid[] = "@(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI"; #endif -static int pconstdef(), pstructdef(), puniondef(), pdefine(), pprogramdef(), - penumdef(), ptypedef(), pdeclaration(), undefined2(); - /* - * rpc_hout.c, Header file outputter for the RPC protocol compiler - * Copyright (C) 1987, Sun Microsystems, Inc. + * rpc_hout.c, Header file outputter for the RPC protocol compiler + * Copyright (C) 1987, Sun Microsystems, Inc. */ #include <stdio.h> #include <ctype.h> -#include "rpc_util.h" #include "rpc_parse.h" +#include "rpc_util.h" + +void storexdrfuncdecl __P(( char *, int )); +static int pconstdef __P(( definition * )); +static int pstructdef __P(( definition * )); +static int puniondef __P(( definition * )); +static int pprogramdef __P(( definition * )); +static int pstructdef __P(( definition * )); +static int penumdef __P(( definition * )); +static int ptypedef __P(( definition * )); +static int pdefine __P(( char *, char * )); +static int undefined2 __P(( char *, char * )); +static int parglist __P(( proc_list *, char * )); + +static char RESULT[] = "clnt_res"; /* - * Print the C-version of an xdr definition + * 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"); } @@ -76,13 +92,71 @@ print_datadef(def) break; } if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) { - f_print(fout, "bool_t xdr_%s();\n", def->def_name); + storexdrfuncdecl(def->def_name, + def->def_kind != DEF_TYPEDEF || + !isvectordef(def->def.ty.old_type, + def->def.ty.rel)); } - if (def->def_kind != DEF_CONST) { +} + + +void +print_funcdef(def) + definition *def; +{ + switch (def->def_kind) { + case DEF_PROGRAM: f_print(fout, "\n"); + pprogramdef(def); + break; + } +} + +/* store away enough information to allow the XDR functions to be spat + out at the end of the file */ + +void +storexdrfuncdecl(name, pointerp) +char *name; +int pointerp; +{ + xdrfunc * xdrptr; + + xdrptr = (xdrfunc *) malloc(sizeof (struct xdrfunc)); + + xdrptr->name = name; + xdrptr->pointerp = pointerp; + xdrptr->next = NULL; + + if (xdrfunc_tail == NULL){ + xdrfunc_head = xdrptr; + xdrfunc_tail = xdrptr; + } else { + xdrfunc_tail->next = xdrptr; + xdrfunc_tail = xdrptr; } + + } +void +print_xdr_func_def(name, pointerp, i) +char* name; +int pointerp; +int i; +{ + if (i == 2) { + f_print(fout, "extern bool_t xdr_%s();\n", name); + return; + } + else + f_print(fout, "extern bool_t xdr_%s(XDR *, %s%s);\n", name, + name, pointerp ? "*" : ""); + + +} + + static pconstdef(def) definition *def; @@ -90,6 +164,43 @@ pconstdef(def) pdefine(def->def_name, def->def.co); } +/* print out the definitions for the arguments of functions in the + header file +*/ +static +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); + storexdrfuncdecl(name, 1); + f_print(fout, "\n"); + } + } +} + + static pstructdef(def) definition *def; @@ -99,7 +210,7 @@ pstructdef(def) f_print(fout, "struct %s {\n", name); for (l = def->def.st.decls; l != NULL; l = l->next) { - pdeclaration(name, &l->decl, 1); + pdeclaration(name, &l->decl, 1, ";\n"); } f_print(fout, "};\n"); f_print(fout, "typedef struct %s %s;\n", name, name); @@ -122,25 +233,24 @@ puniondef(def) } f_print(fout, "\tunion {\n"); for (l = def->def.un.cases; l != NULL; l = l->next) { - pdeclaration(name, &l->case_decl, 2); + 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); + 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 pdefine(name, num) char *name; char *num; { - f_print(fout, "#define %s %s\n", name, num); + f_print(fout, "#define\t%s %s\n", name, num); } static @@ -148,7 +258,7 @@ puldefine(name, num) char *name; char *num; { - f_print(fout, "#define %s ((u_long)%s)\n", name, num); + f_print(fout, "#define\t%s ((unsigned long)(%s))\n", name, num); } static @@ -172,6 +282,18 @@ define_printed(stop, start) /* NOTREACHED */ } +static +pfreeprocdef(char * name, char *vers, int mode) +{ + f_print(fout, "extern int "); + pvname(name, vers); + if (mode == 1) + f_print(fout,"_freeresult(SVCXPRT *, xdrproc_t, caddr_t);\n"); + else + f_print(fout,"_freeresult();\n"); + + +} static pprogramdef(def) @@ -179,41 +301,141 @@ pprogramdef(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); - for (proc = vers->procs; proc != NULL; proc = proc->next) { - if (!define_printed(proc, def->def.pr.versions)) { - puldefine(proc->proc_name, proc->proc_num); + + /* + * Print out 2 definitions, one for ANSI-C, another for + * old K & R C + */ + + if(!Cflag){ + 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, NULL, 0, 2); + + if (mtflag) { + f_print(fout, "%s", ext); + pprocdef(proc, vers, NULL, 1, 2); + } + } + pfreeprocdef(def->def_name, vers->vers_num, 2); + + } else { + for (i = 1; i < 3; i++){ + if (i == 1){ + f_print(fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); + ext = "extern "; + }else{ + f_print(fout, "\n#else /* K&R 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); + } + pfreeprocdef(def->def_name, vers->vers_num, i); } - pprocdef(proc, vers); + f_print(fout, "#endif /* K&R C */\n"); } } } - -pprocdef(proc, vp) +pprocdef(proc, vp, addargtype, server_p, mode) proc_list *proc; version_list *vp; + char* addargtype; + int server_p; + int mode; { - f_print(fout, "extern "); - if (proc->res_prefix) { - if (streq(proc->res_prefix, "enum")) { - f_print(fout, "enum "); - } else { - f_print(fout, "struct "); + if (mtflag) {/* Print MT style stubs */ + if (server_p) + f_print(fout, "bool_t "); + else + f_print(fout, "enum clnt_stat "); + } else { + 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 1 = ANSI-C, mode 2 = K&R C + */ + if ( mode == 1) + parglist(proc, addargtype); + else + f_print(fout, "();\n"); + + + +} + + + +/* print out argument list of procedure */ +static +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, ", "); } } - if (streq(proc->res_type, "bool")) { - f_print(fout, "bool_t *"); - } else if (streq(proc->res_type, "string")) { - f_print(fout, "char **"); - } else { - f_print(fout, "%s *", fixtype(proc->res_type)); + + if (mtflag) { + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*, "); } - pvname(proc->proc_name, vp->vers_num); - f_print(fout, "();\n"); + + f_print(fout, "%s);\n", addargtype); + } static @@ -239,7 +461,10 @@ penumdef(def) f_print(fout, " = %s + %d", last, count++); } } - f_print(fout, ",\n"); + if (l->next) + f_print(fout, ",\n"); + else + f_print(fout, "\n"); } f_print(fout, "};\n"); f_print(fout, "typedef enum %s %s;\n", name, name); @@ -285,19 +510,18 @@ ptypedef(def) def->def.ty.array_max); break; case REL_ALIAS: - f_print(fout, "%s%s %s", prefix, old, name); + f_print(fout, "%s%s %s", prefix, old, name); break; } f_print(fout, ";\n"); } } - -static -pdeclaration(name, dec, tab) +pdeclaration(name, dec, tab, separator) char *name; declaration *dec; int tab; + char *separator; { char buf[8]; /* enough to hold "struct ", include NUL */ char *prefix; @@ -341,17 +565,16 @@ pdeclaration(name, dec, tab) 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); + 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, ";\n"); + f_print(fout, separator); } - - static undefined2(type, stop) char *type; diff --git a/usr.bin/rpcgen/rpc_main.c b/usr.bin/rpcgen/rpc_main.c index 981c94d..6902530 100644 --- a/usr.bin/rpcgen/rpc_main.c +++ b/usr.bin/rpcgen/rpc_main.c @@ -1,4 +1,3 @@ -/* @(#)rpc_main.c 2.2 88/08/01 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -27,103 +26,243 @@ * 2550 Garcia Avenue * Mountain View, California 94043 */ + + +#ident "@(#)rpc_main.c 1.21 94/04/25 SMI" + #ifndef lint -/*static char sccsid[] = "from: @(#)rpc_main.c 1.7 87/06/24 (C) 1987 SMI";*/ -static char rcsid[] = "$Id: rpc_main.c,v 1.1 1993/09/13 23:20:15 jtc Exp $"; +static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI"; #endif /* - * rpc_main.c, Top level of the RPC protocol compiler. - * Copyright (C) 1987, Sun Microsystems, Inc. + * rpc_main.c, Top level of the RPC protocol compiler. + * Copyright (C) 1987, Sun Microsystems, Inc. */ #include <stdio.h> -#include <strings.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/param.h> #include <sys/file.h> -#include "rpc_util.h" +#include <sys/stat.h> #include "rpc_parse.h" +#include "rpc_util.h" #include "rpc_scan.h" -#define EXTEND 1 /* alias for TRUE */ +extern void write_sample_svc __P(( definition * )); +extern int write_sample_clnt __P(( definition * )); +extern void write_sample_clnt_main __P(( void )); +static int c_output __P(( char *, char *, int, char * )); +static int h_output __P(( char *, char *, int, char * )); +static int l_output __P(( char *, char *, int, char * )); +static int t_output __P(( char *, char *, int, char * )); +static int clnt_output __P(( char *, char *, int, char * )); + +#ifndef __FreeBSD__ +char * rindex(); +#endif + +static int usage __P(( void )); +static int options_usage __P (( void )); +static int do_registers __P(( int, char ** )); +static int parseargs __P(( int, char **, struct commandline * )); +static int svc_output __P(( char *, char *, int, char * )); +static void mkfile_output __P(( struct commandline * )); +static int s_output __P(( int, char **, char *, char *, int, char *, int, int )); + +#define EXTEND 1 /* alias for TRUE */ +#define DONT_EXTEND 0 /* alias for FALSE */ + +#define SVR4_CPP "/usr/ccs/lib/cpp" +#ifdef __FreeBSD__ +#define SUNOS_CPP "/usr/libexec/cpp" +#else +#define SUNOS_CPP "/usr/lib/cpp" +#endif + +static int cppDefined = 0; /* explicit path for C preprocessor */ -struct commandline { - int cflag; - int hflag; - int lflag; - int sflag; - int mflag; - char *infile; - char *outfile; -}; static char *cmdname; -static char CPP[] = "/usr/bin/cpp"; + +static char *svcclosetime = "120"; +static char *CPP = SVR4_CPP; static char CPPFLAGS[] = "-C"; +static char pathbuf[MAXPATHLEN + 1]; static char *allv[] = { "rpcgen", "-s", "udp", "-s", "tcp", }; -static int allc = sizeof(allv)/sizeof(allv[0]); +static int allc = sizeof (allv)/sizeof (allv[0]); +static char *allnv[] = { + "rpcgen", "-s", "netpath", +}; +static int allnc = sizeof (allnv)/sizeof (allnv[0]); + +/* + * machinations for handling expanding argument list + */ +static void addarg(); /* add another argument to the list */ +static void putarg(); /* put argument at specified location */ +static void clear_args(); /* clear argument list */ +static void checkfiles(); /* check if out file already exists */ + + + +#define ARGLISTLEN 20 +#define FIXEDARGS 2 +static char *arglist[ARGLISTLEN]; +static int argcount = FIXEDARGS; + + +int nonfatalerrors; /* errors */ +#ifdef __FreeBSD__ +int inetdflag = 0; /* Support for inetd is now the default */ +#else +int inetdflag; /* Support for inetd is now the default */ +#endif +int pmflag; /* Support for port monitors */ +int logflag; /* Use syslog instead of fprintf for errors */ +int tblflag; /* Support for dispatch table file */ +int mtflag = 0; /* Support for MT */ +#ifdef __FreeBSD__ +#define INLINE 0 +#else +#define INLINE 5 +#endif +/* length at which to start doing an inline */ + +int inline = INLINE; +/* + * Length at which to start doing an inline. INLINE = 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 */ +int CCflag = 0; /* C++ files */ +static int allfiles; /* generate all files */ +#ifdef __FreeBSD__ +int tirpcflag = 0; /* generating code for tirpc, by default */ +#else +int tirpcflag = 1; /* generating code for tirpc, by default */ +#endif +xdrfunc *xdrfunc_head = NULL; /* xdr function list */ +xdrfunc *xdrfunc_tail = NULL; /* xdr function list */ +pid_t childpid; -static int h_output(), c_output(), s_output(), l_output(), do_registers(), - parseargs(); main(argc, argv) int argc; char *argv[]; - { struct commandline cmd; - if (!parseargs(argc, argv, &cmd)) { - f_print(stderr, - "usage: %s infile\n", cmdname); - f_print(stderr, - " %s [-c | -h | -l | -m] [-o outfile] [infile]\n", - cmdname); - f_print(stderr, - " %s [-s udp|tcp]* [-o outfile] [infile]\n", - cmdname); - exit(1); + (void) memset((char *)&cmd, 0, sizeof (struct commandline)); + clear_args(); + if (!parseargs(argc, argv, &cmd)) + usage(); + /* + * Only the client and server side stubs are likely to be customized, + * so in that case only, check if the outfile exists, and if so, + * print an error message and exit. + */ + if (cmd.Ssflag || cmd.Scflag || cmd.makefileflag) { + checkfiles(cmd.infile, cmd.outfile); } + else + checkfiles(cmd.infile, NULL); + if (cmd.cflag) { - c_output(cmd.infile, "-DRPC_XDR", !EXTEND, cmd.outfile); + c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); } else if (cmd.hflag) { - h_output(cmd.infile, "-DRPC_HDR", !EXTEND, cmd.outfile); + h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); } else if (cmd.lflag) { - l_output(cmd.infile, "-DRPC_CLNT", !EXTEND, cmd.outfile); - } else if (cmd.sflag || cmd.mflag) { - s_output(argc, argv, cmd.infile, "-DRPC_SVC", !EXTEND, - cmd.outfile, cmd.mflag); + 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 if (cmd.makefileflag) { + mkfile_output(&cmd); } 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(); - s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND, - "_svc.c", cmd.mflag); + 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"); + reinitialize(); + clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, + "_client.c"); + + } + if (allfiles || (cmd.makefileflag == 1)){ + reinitialize(); + mkfile_output(&cmd); + } + } - exit(0); + exit(nonfatalerrors); + /* NOTREACHED */ } + /* - * add extension to filename + * add extension to filename */ static char * +#ifdef __FreeBSD__ +extendfile(path, ext) + char *path; +#else extendfile(file, ext) char *file; +#endif char *ext; { char *res; char *p; +#ifdef __FreeBSD__ + char *file; + if ((file = rindex(path, '/')) == NULL) + file = path; + else + file++; +#endif res = alloc(strlen(file) + strlen(ext) + 1); if (res == NULL) { abort(); } - p = rindex(file, '.'); + p = strrchr(file, '.'); if (p == NULL) { p = file + strlen(file); } @@ -133,20 +272,22 @@ extendfile(file, ext) } /* - * Open output file with given extension + * Open output file with given extension */ static 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); + f_print(stderr, "%s: %s already exists. No output generated.\n", + cmdname, infile); crash(); } fout = fopen(outfile, "w"); @@ -156,10 +297,50 @@ open_output(infile, outfile) crash(); } record_open(outfile); + +} + +static +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 + * Open input file with given define for C-preprocessor */ static open_input(infile, define) @@ -170,13 +351,20 @@ open_input(infile, define) infilename = (infile == NULL) ? "<stdin>" : infile; (void) pipe(pd); - switch (fork()) { + switch (childpid = fork()) { case 0: + find_cpp(); + putarg(0, CPP); + putarg(1, CPPFLAGS); + addarg(define); + if (infile) + addarg(infile); + addarg((char *)NULL); (void) close(1); (void) dup2(pd[1], 1); (void) close(pd[0]); - execl(CPP, CPP, CPPFLAGS, define, infile, NULL); - perror("execl"); + execv(arglist[0], arglist); + perror("execv"); exit(1); case -1: perror("fork"); @@ -191,9 +379,59 @@ open_input(infile, define) } } -/* - * Compile into an XDR routine output file - */ +/* 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); +} + +static char * +file_name(file, ext) +char *file; +char *ext; +{ + char *temp; + temp = extendfile(file, ext); + + if (access(temp, F_OK) != -1) + return (temp); + else + return ((char *)" "); + +} + + static c_output(infile, define, extend, outfile) char *infile; @@ -206,14 +444,17 @@ c_output(infile, define, extend, outfile) char *outfilename; long tell; - open_input(infile, define); + c_initialize(); + open_input(infile, define); outfilename = extend ? extendfile(infile, outfile) : outfile; open_output(infile, outfilename); - f_print(fout, "#include <rpc/rpc.h>\n"); + 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()) { emit(def); @@ -223,9 +464,54 @@ c_output(infile, define, extend, outfile) } } + +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"; + + +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 h_output(infile, define, extend, outfile) char *infile; @@ -236,24 +522,113 @@ h_output(infile, define, extend, outfile) definition *def; char *outfilename; long tell; + char *guard; + list *l; + xdrfunc *xdrfuncp; + int i; open_input(infile, define); outfilename = extend ? extendfile(infile, outfile) : outfile; open_output(infile, outfilename); + add_warning(); + if (outfilename || infile){ + guard = generate_guard(outfilename ? outfilename: infile); + } else + guard = "STDIN_"; + + f_print(fout, "#ifndef _%s\n#define _%s\n\n", guard, + guard); + + f_print(fout, "#include <rpc/rpc.h>\n"); + + if (mtflag) { + f_print(fout, "#include <synch.h>\n"); + f_print(fout, "#include <thread.h>\n"); + }; + + /* put the C++ support */ + if (Cflag && !CCflag){ + f_print(fout, "\n#ifdef __cplusplus\n"); + f_print(fout, "extern \"C\" {\n"); + f_print(fout, "#endif\n\n"); + } + + /* put in a typedef for quadprecision. Only with Cflag */ + tell = ftell(fout); + + /* print data definitions */ while (def = get_definition()) { 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); + } + /* Now print all xdr func declarations */ + if (xdrfunc_head != NULL){ + + f_print(fout, + "\n/* the xdr functions */\n"); + + if (CCflag){ + f_print(fout, "\n#ifdef __cplusplus\n"); + f_print(fout, "extern \"C\" {\n"); + f_print(fout, "#endif\n"); + } + + if (!Cflag){ + xdrfuncp = xdrfunc_head; + while (xdrfuncp != NULL){ + print_xdr_func_def(xdrfuncp->name, + xdrfuncp->pointerp, 2); + xdrfuncp = xdrfuncp->next; + } + } else { + + for (i = 1; i < 3; i++){ + if (i == 1) + f_print(fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); + + else + f_print(fout, "\n#else /* K&R C */\n"); + + xdrfuncp = xdrfunc_head; + while (xdrfuncp != NULL){ + print_xdr_func_def(xdrfuncp->name, + xdrfuncp->pointerp, i); + xdrfuncp = xdrfuncp->next; + } + } + f_print(fout, "\n#endif /* K&R C */\n"); + } + } + if (extend && tell == ftell(fout)) { (void) unlink(outfilename); + } else if (tblflag) { + f_print(fout, rpcgen_table_dcl); } + + if (Cflag){ + f_print(fout, "\n#ifdef __cplusplus\n"); + f_print(fout, "}\n"); + f_print(fout, "#endif\n"); + } + + f_print(fout, "\n#endif /* !_%s */\n", guard); } /* * Compile into an RPC service */ static -s_output(argc, argv, infile, define, extend, outfile, nomain) +s_output(argc, argv, infile, define, extend, outfile, nomain, netflag) int argc; char *argv[]; char *infile; @@ -261,22 +636,80 @@ s_output(argc, argv, infile, define, extend, outfile, nomain) int extend; char *outfile; int nomain; + int netflag; { char *include; definition *def; - int foundprogram; + int foundprogram = 0; char *outfilename; open_input(infile, define); outfilename = extend ? extendfile(infile, outfile) : outfile; open_output(infile, outfilename); - f_print(fout, "#include <stdio.h>\n"); - f_print(fout, "#include <rpc/rpc.h>\n"); + add_warning(); if (infile && (include = extendfile(infile, ".h"))) { f_print(fout, "#include \"%s\"\n", include); free(include); + } else + f_print(fout, "#include <rpc/rpc.h>\n"); + + f_print(fout, "#include <stdio.h>\n"); + f_print(fout, "#include <stdlib.h> /* getenv, exit */\n"); + if (Cflag) { + f_print (fout, + "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n"); + f_print (fout, "#include <string.h> /* strcmp */\n"); + } + if (strcmp(svcclosetime, "-1") == 0) + indefinitewait = 1; + else if (strcmp(svcclosetime, "0") == 0) + exitnow = 1; + else if (inetdflag || pmflag) { + f_print(fout, "#include <signal.h>\n"); + timerflag = 1; + } + + if (!tirpcflag && inetdflag) + f_print(fout, "#include <sys/ttycom.h> /* TIOCNOTTY */\n"); + if (Cflag && (inetdflag || pmflag)) { + f_print(fout, "#ifdef __cplusplus\n"); + f_print(fout, + "#include <sysent.h> /* getdtablesize, open */\n"); + f_print(fout, "#endif /* __cplusplus */\n"); + if (tirpcflag) + f_print(fout, "#include <unistd.h> /* setsid */\n"); + } + if (tirpcflag) + f_print(fout, "#include <sys/types.h>\n"); + + f_print(fout, "#include <memory.h>\n"); +#ifdef __FreeBSD__ + if (tirpcflag) +#endif + 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 && !nomain) { + f_print(fout, "#include <netconfig.h>\n"); } - foundprogram = 0; + if (tirpcflag) + f_print(fout, "#include <sys/resource.h> /* rlimit */\n"); + if (logflag || inetdflag || pmflag) + f_print(fout, "#include <syslog.h>\n"); + + /* for ANSI-C */ + if (Cflag) + f_print(fout, + "\n#ifndef SIG_PF\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()) { foundprogram |= (def->def_kind == DEF_PROGRAM); } @@ -284,16 +717,20 @@ s_output(argc, argv, infile, define, extend, outfile, nomain) (void) unlink(outfilename); return; } - if (nomain) { - write_programs((char *)NULL); - } else { - write_most(); - do_registers(argc, argv); + write_most(infile, netflag, nomain); + if (!nomain) { + if (!do_registers(argc, argv)) { + if (outfilename) + (void) unlink(outfilename); + usage(); + } write_rest(); - write_programs("static"); } } +/* + * generate client side stubs + */ static l_output(infile, define, extend, outfile) char *infile; @@ -303,18 +740,20 @@ l_output(infile, define, extend, outfile) { char *include; definition *def; - int foundprogram; + int foundprogram = 0; char *outfilename; open_input(infile, define); outfilename = extend ? extendfile(infile, outfile) : outfile; open_output(infile, outfilename); - f_print(fout, "#include <rpc/rpc.h>\n"); + add_warning(); + if (Cflag) + f_print (fout, "#include <memory.h> /* for memset */\n"); if (infile && (include = extendfile(infile, ".h"))) { f_print(fout, "#include \"%s\"\n", include); free(include); - } - foundprogram = 0; + } else + f_print(fout, "#include <rpc/rpc.h>\n"); while (def = get_definition()) { foundprogram |= (def->def_kind == DEF_PROGRAM); } @@ -326,38 +765,329 @@ l_output(infile, define, extend, outfile) } /* - * Perform registrations for service output + * generate the dispatch table + */ +static +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()) { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) { + (void) unlink(outfilename); + return; + } + write_tables(); +} + +/* sample routine for the server template */ +static +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()) { + write_sample_svc(def); + } + if (extend && tell == ftell(fout)) { + (void) unlink(outfilename); + } +} + +/* sample main routine for client */ +static +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()) { + has_program += write_sample_clnt(def); + } + + if (has_program) + write_sample_clnt_main(); + + if (extend && tell == ftell(fout)) { + (void) unlink(outfilename); + } +} + + +static void mkfile_output(cmd) +struct commandline *cmd; +{ + char *mkfilename, *clientname, *clntname, *xdrname, *hdrname; + char *servername, *svcname, *servprogname, *clntprogname; + char *temp; + + svcname = file_name(cmd->infile, "_svc.c"); + clntname = file_name(cmd->infile, "_clnt.c"); + xdrname = file_name(cmd->infile, "_xdr.c"); + hdrname = file_name(cmd->infile, ".h"); + + + if (allfiles){ + servername = extendfile(cmd->infile, "_server.c"); + clientname = extendfile(cmd->infile, "_client.c"); + }else{ + servername = " "; + clientname = " "; + } + servprogname = extendfile(cmd->infile, "_server"); + clntprogname = extendfile(cmd->infile, "_client"); + + if (allfiles){ + mkfilename = alloc(strlen("makefile.") + + strlen(cmd->infile) + 1); + temp = (char *)rindex(cmd->infile, '.'); + strcat(mkfilename, "makefile."); + (void) strncat(mkfilename, cmd->infile, + (temp - cmd->infile)); + } else + mkfilename = cmd->outfile; + + + checkfiles(NULL, mkfilename); + open_output(NULL, mkfilename); + + f_print(fout, "\n# This is a template makefile generated\ + by rpcgen \n"); + + f_print(fout, "\n# Parameters \n\n"); + + f_print(fout, "CLIENT = %s\nSERVER = %s\n\n", + clntprogname, servprogname); + f_print(fout, "SOURCES_CLNT.c = \nSOURCES_CLNT.h = \n"); + f_print(fout, "SOURCES_SVC.c = \nSOURCES_SVC.h = \n"); + f_print(fout, "SOURCES.x = %s\n\n", cmd->infile); + f_print(fout, "TARGETS_SVC.c = %s %s %s \n", + svcname, servername, xdrname); + f_print(fout, "TARGETS_CLNT.c = %s %s %s \n", + clntname, clientname, xdrname); + f_print(fout, "TARGETS = %s %s %s %s %s %s\n\n", + hdrname, xdrname, clntname, + svcname, clientname, servername); + + f_print(fout, "OBJECTS_CLNT = $(SOURCES_CLNT.c:%%.c=%%.o) \ +$(TARGETS_CLNT.c:%%.c=%%.o) "); + + f_print(fout, "\nOBJECTS_SVC = $(SOURCES_SVC.c:%%.c=%%.o) \ +$(TARGETS_SVC.c:%%.c=%%.o) "); + + + f_print(fout, "\n# Compiler flags \n"); + if (mtflag) + f_print(fout, "\nCPPFLAGS += -D_REENTRANT\nCFLAGS += -g \nLDLIBS += -lnsl -lthread\n"); + else +#ifdef __FreeBSD__ + f_print(fout, "\nCFLAGS += -g \nLDLIBS +=\n"); +#else + f_print(fout, "\nCFLAGS += -g \nLDLIBS += -lnsl\n"); +#endif + f_print(fout, "RPCGENFLAGS = \n"); + + f_print(fout, "\n# Targets \n\n"); + + f_print(fout, "all : $(CLIENT) $(SERVER)\n\n"); + f_print(fout, "$(TARGETS) : $(SOURCES.x) \n"); + f_print(fout, "\trpcgen $(RPCGENFLAGS) $(SOURCES.x)\n\n"); + f_print(fout, "$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) \ +$(TARGETS_CLNT.c) \n\n"); + + f_print(fout, "$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) \ +$(TARGETS_SVC.c) \n\n"); + f_print(fout, "$(CLIENT) : $(OBJECTS_CLNT) \n"); +#ifdef __FreeBSD__ + f_print(fout, "\t$(CC) -o $(CLIENT) $(OBJECTS_CLNT) \ +$(LDLIBS) \n\n"); +#else + f_print(fout, "\t$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) \ +$(LDLIBS) \n\n"); +#endif + f_print(fout, "$(SERVER) : $(OBJECTS_SVC) \n"); +#ifdef __FreeBSD__ + f_print(fout, "\t$(CC) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n "); + f_print(fout, "clean:\n\t $(RM) -f core $(TARGETS) $(OBJECTS_CLNT) \ +$(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n"); +#else + f_print(fout, "\t$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n "); + f_print(fout, "clean:\n\t $(RM) core $(TARGETS) $(OBJECTS_CLNT) \ +$(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n"); +#endif +} + + + +/* + * Perform registrations for service output + * Return 0 if failed; 1 otherwise. */ static -do_registers(argc, argv) +int do_registers(argc, argv) int argc; char *argv[]; - { int i; - for (i = 1; i < argc; i++) { - if (streq(argv[i], "-s")) { - write_register(argv[i + 1]); - 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 (outfile) { + if (stat(outfile, &buf) < 0) + return; /* file does not exist */ + else { + f_print(stderr, + "file '%s' already exists and may be overwritten\n", + outfile); + crash(); } } } /* - * Parse command line arguments + * Parse command line arguments */ static parseargs(argc, argv, cmd) int argc; char *argv[]; struct commandline *cmd; - { int i; int j; - char c; - char flag[(1 << 8 * sizeof(char))]; + char c, ch; + char flag[(1 << 8 * sizeof (char))]; int nflags; cmdname = argv[0]; @@ -365,15 +1095,25 @@ parseargs(argc, argv, cmd) if (argc < 2) { return (0); } + allfiles = 0; flag['c'] = 0; flag['h'] = 0; - flag['s'] = 0; - flag['o'] = 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; + flag['M'] = 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]; @@ -381,18 +1121,93 @@ parseargs(argc, argv, cmd) for (j = 1; argv[i][j] != 0; j++) { c = argv[i][j]; switch (c) { + case 'a': + allfiles = 1; + break; case 'c': case 'h': case 'l': case 'm': + case 't': if (flag[c]) { return (0); } flag[c] = 1; break; + case 'S': + /* + * sample flag: Ss or Sc. + * Ss means set flag['S']; + * Sc means set flag['C']; + * Sm means set flag['M']; + */ + ch = argv[i][++j]; /* get next char */ + if (ch == 's') + ch = 'S'; + else if (ch == 'c') + ch = 'C'; + else if (ch == 'm') + ch = 'M'; + else + return (0); + + if (flag[ch]) { + return (0); + } + flag[ch] = 1; + break; + case 'C': /* ANSI C syntax */ + Cflag = 1; + ch = argv[i][j+1]; /* get next char */ + + if (ch != 'C') + break; + CCflag = 1; + break; + case 'b': + /* + * Turn TIRPC flag off for + * generating backward compatible + * code + */ +#ifdef __FreeBSD__ + tirpcflag = 1; +#else + tirpcflag = 0; +#endif + 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 'M': + mtflag = 1; + break; + case 'i' : + if (++i == argc) { + return (0); + } + inline = atoi(argv[i]); + goto nextarg; + case 'n': case 'o': case 's': - if (argv[i][j - 1] != '-' || + if (argv[i][j - 1] != '-' || argv[i][j + 1] != 0) { return (0); } @@ -400,39 +1215,167 @@ parseargs(argc, argv, cmd) if (++i == argc) { return (0); } - if (c == 's') { - if (!streq(argv[i], "udp") && - !streq(argv[i], "tcp")) { - return (0); - } - } else if (c == 'o') { + 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: + nextarg: ; } } + cmd->cflag = flag['c']; cmd->hflag = flag['h']; - cmd->sflag = flag['s']; cmd->lflag = flag['l']; cmd->mflag = flag['m']; - nflags = cmd->cflag + cmd->hflag + cmd->sflag + cmd->lflag + cmd->mflag; + cmd->nflag = flag['n']; + cmd->sflag = flag['s']; + cmd->tflag = flag['t']; + cmd->Ssflag = flag['S']; + cmd->Scflag = flag['C']; + cmd->makefileflag = flag['M']; + + 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 */ +#ifndef __FreeBSD__ + inetdflag = 1; /* inetdflag is TRUE by default */ +#endif + 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 + cmd->makefileflag; + if (nflags == 0) { if (cmd->outfile != NULL || cmd->infile == NULL) { return (0); } - } else if (nflags > 1) { + } else if (cmd->infile == NULL && + (cmd->Ssflag || cmd->Scflag || cmd->makefileflag)) { + f_print(stderr, + "\"infile\" is required for template generation flags.\n"); + return (0); + } if (nflags > 1) { + f_print(stderr, + "Cannot have more than one file generation flag.\n"); return (0); } return (1); } + +static +usage() +{ + f_print(stderr, "usage: %s infile\n", cmdname); + f_print(stderr, + "\t%s [-abCLNTM] [-Dname[=value]] [-i size]\ +[-I [-K seconds]] [-Y path] infile\n", + cmdname); + f_print(stderr, + "\t%s [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm]\ +[-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 +options_usage() +{ + f_print(stderr, "options:\n"); + f_print(stderr, "-a\t\tgenerate all files, including samples\n"); + f_print(stderr, "-b\t\tbackward compatibility mode (generates code\ +for SunOS 4.X)\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.X)\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, "-M\t\tgenerate MT-safe code\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, "-Sm \t\tgenerate makefile template \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\tpath where cpp is found\n"); + exit(1); +} + +#ifndef __FreeBSD__ +char * +rindex(sp, c) + register char *sp, c; +{ + register char *r; + + r = NULL; + do { + if (*sp == c) + r = sp; + } while (*sp++); + return (r); +} +#endif diff --git a/usr.bin/rpcgen/rpc_parse.c b/usr.bin/rpcgen/rpc_parse.c index b780851..fb8eec1 100644 --- a/usr.bin/rpcgen/rpc_parse.c +++ b/usr.bin/rpcgen/rpc_parse.c @@ -1,4 +1,3 @@ -/* @(#)rpc_parse.c 2.1 88/08/01 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -27,23 +26,43 @@ * 2550 Garcia Avenue * Mountain View, California 94043 */ + +#ident "@(#)rpc_parse.c 1.12 93/07/05 SMI" + #ifndef lint -/*static char sccsid[] = "from: @(#)rpc_parse.c 1.4 87/04/28 (C) 1987 SMI";*/ -static char rcsid[] = "$Id: rpc_parse.c,v 1.1 1993/09/13 23:20:16 jtc Exp $"; +static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI"; #endif /* - * rpc_parse.c, Parser for the RPC protocol compiler + * rpc_parse.c, Parser for the RPC protocol compiler * Copyright (C) 1987 Sun Microsystems, Inc. */ #include <stdio.h> -#include "rpc_util.h" +#include <string.h> +#include "rpc/types.h" #include "rpc_scan.h" #include "rpc_parse.h" +#include "rpc_util.h" + +#define ARGNAME "arg" + +extern char *make_argname __P(( char *, char * )); +static int isdefined __P(( definition * )); +static int def_struct __P(( definition * )); +static int def_program __P(( definition * )); +static int def_enum __P(( definition * )); +static int def_const __P(( definition * )); +static int def_union __P(( definition * )); +static int def_typedef __P(( definition * )); +static int get_declaration __P(( declaration *, defkind )); +static int get_prog_declaration __P(( declaration *, defkind, int )); +static int get_type __P(( char **, char **, defkind )); +static int unsigned_dec __P(( char ** )); + +#ifndef __FreeBSD__ +extern char *strdup(); +#endif -static int isdefined(), def_struct(), def_program(), def_enum(), def_const(), - def_union(), def_typedef(), get_declaration(), get_type(), - unsigned_dec(); /* * return the next definition you see */ @@ -76,7 +95,6 @@ get_definition() break; case TOK_EOF: return (NULL); - break; default: error("definition keyword expected"); } @@ -92,7 +110,6 @@ isdefined(defp) STOREVAL(&defined, defp); } - static def_struct(defp) definition *defp; @@ -126,16 +143,21 @@ 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); @@ -144,33 +166,75 @@ def_program(defp) 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); + 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_type(&plist->arg_prefix, &plist->arg_type, DEF_PROGRAM); - if (streq(plist->arg_type, "opaque")) { - error("illegal argument type"); + /* 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); @@ -180,6 +244,7 @@ def_program(defp) *vtailp = NULL; } + static def_enum(defp) definition *defp; @@ -230,8 +295,9 @@ def_union(defp) { token tok; declaration dec; - case_list *cases; + case_list *cases, *tcase; case_list **tailp; + int flag; defp->def_kind = DEF_UNION; scan(TOK_IDENT, &tok); @@ -245,15 +311,40 @@ def_union(defp) scan(TOK_LBRACE, &tok); scan(TOK_CASE, &tok); while (tok.kind == TOK_CASE) { - scan(TOK_IDENT, &tok); + 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; @@ -269,6 +360,62 @@ def_union(defp) } } +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 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 def_typedef(defp) @@ -279,13 +426,13 @@ def_typedef(defp) 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 get_declaration(dec, dkind) declaration *dec; @@ -298,6 +445,8 @@ get_declaration(dec, dkind) 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; @@ -338,6 +487,79 @@ get_declaration(dec, dkind) static +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 = 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 get_type(prefixp, typep, dkind) char **prefixp; char **typep; @@ -369,9 +591,14 @@ get_type(prefixp, typep, dkind) *typep = "long"; (void) peekscan(TOK_INT, &tok); break; + case TOK_HYPER: + *typep = "longlong_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"); + error("voids allowed only inside union and program definitions with one argument"); } *typep = tok.str; break; @@ -382,6 +609,7 @@ get_type(prefixp, typep, dkind) case TOK_FLOAT: case TOK_DOUBLE: case TOK_BOOL: + case TOK_QUAD: *typep = tok.str; break; default: @@ -389,7 +617,6 @@ get_type(prefixp, typep, dkind) } } - static unsigned_dec(typep) char **typep; @@ -412,6 +639,11 @@ unsigned_dec(typep) *typep = "u_long"; (void) peekscan(TOK_INT, &tok); break; + case TOK_HYPER: + get_token(&tok); + *typep = "ulonglong_t"; + (void) peekscan(TOK_INT, &tok); + break; case TOK_INT: get_token(&tok); *typep = "u_int"; diff --git a/usr.bin/rpcgen/rpc_parse.h b/usr.bin/rpcgen/rpc_parse.h index 0a4eb1e..b61db9d 100644 --- a/usr.bin/rpcgen/rpc_parse.h +++ b/usr.bin/rpcgen/rpc_parse.h @@ -25,14 +25,42 @@ * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 - * - * from: @(#)rpc_parse.h 1.3 87/03/09 (C) 1987 SMI - * $Id: rpc_parse.h,v 1.1 1993/09/13 23:20:17 jtc Exp $ */ +#pragma ident "@(#)rpc_parse.h 1.10 94/05/15 SMI" + +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ +/* The copyright notice above does not evidence any */ +/* actual or intended publication of such source code. */ + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +* PROPRIETARY NOTICE (Combined) +* +* This source code is unpublished proprietary information +* constituting, or derived under license from AT&T's UNIX(r) System V. +* In addition, portions of such source code were derived from Berkeley +* 4.3 BSD under license from the Regents of the University of +* California. +* +* +* +* Copyright Notice +* +* Notice of copyright on this source code product does not indicate +* publication. +* +* (c) 1986,1987,1988.1989 Sun Microsystems, Inc +* (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. +* All rights reserved. +*/ + +/* @(#)rpc_parse.h 1.3 90/08/29 (C) 1987 SMI */ /* * rpc_parse.h, Definitions for the RPCL parser - * Copyright (C) 1987, Sun Microsystems, Inc. */ enum defkind { @@ -63,7 +91,6 @@ struct typedef_def { }; typedef struct typedef_def typedef_def; - struct enumval_list { char *name; char *assignment; @@ -76,7 +103,6 @@ struct enum_def { }; typedef struct enum_def enum_def; - struct declaration { char *prefix; char *type; @@ -86,7 +112,6 @@ struct declaration { }; typedef struct declaration declaration; - struct decl_list { declaration decl; struct decl_list *next; @@ -98,9 +123,9 @@ struct struct_def { }; typedef struct struct_def struct_def; - struct case_list { char *case_name; + int contflag; declaration case_decl; struct case_list *next; }; @@ -113,20 +138,24 @@ struct union_def { }; 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; - char *arg_type; - char *arg_prefix; + 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; @@ -155,5 +184,14 @@ struct definition { }; typedef struct definition definition; -/* @(#)rpc_parse.h 2.1 88/08/01 4.0 RPCSRC */ definition *get_definition(); + + +struct bas_type +{ + char *name; + int length; + struct bas_type *next; +}; + +typedef struct bas_type bas_type; diff --git a/usr.bin/rpcgen/rpc_sample.c b/usr.bin/rpcgen/rpc_sample.c new file mode 100644 index 0000000..435bb44 --- /dev/null +++ b/usr.bin/rpcgen/rpc_sample.c @@ -0,0 +1,311 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#pragma ident "@(#)rpc_sample.c 1.9 94/04/25 SMI" + +/* + * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler + * Copyright (C) 1987, Sun Microsystems, Inc. + */ + +#include <stdio.h> +#include <string.h> +#include "rpc_parse.h" +#include "rpc_util.h" + + +static char RQSTP[] = "rqstp"; + +extern void printarglist __P(( proc_list *, char *, char *, char *)); +static int write_sample_client __P(( char *, version_list * )); +static int write_sample_server __P(( definition * )); +static int 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 +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)\n\tchar *host;\n{\n"); + f_print(fout, "\tCLIENT *clnt;\n"); + + i = 0; + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\t"); + if (mtflag) { + f_print(fout, "enum clnt_stat retval_%d;\n\t", ++i); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "result_%d;\n", i); + } else { + 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); + if (strcmp(l->decl.type,"string") == 1) + f_print(fout, " "); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_%s;\n", l->decl.name); + } + } + } + + /* generate creation of client handle */ + f_print(fout, "\n#ifndef\tDEBUG\n"); + f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n", + program_name, vp->vers_name, tirpcflag? "netpath" : "udp"); + f_print(fout, "\tif (clnt == (CLIENT *) NULL) {\n"); + f_print(fout, "\t\tclnt_pcreateerror(host);\n"); + f_print(fout, "\t\texit(1);\n\t}\n"); + f_print(fout, "#endif\t/* DEBUG */\n\n"); + + /* generate calls to procedures */ + i = 0; + for (proc = vp->procs; proc != NULL; proc = proc->next) { + if (mtflag) + f_print(fout, "\tretval_%d = ",++i); + else + 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); + if (mtflag) + f_print(fout, "_arg, &result_%d, clnt);\n", + i); + else + f_print(fout, "_arg, clnt);\n"); + + } else if (streq(proc->args.decls->decl.type, "void")) { + if (mtflag) + f_print(fout, "(&result_%d, clnt);\n", i); + else + 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); + } + if (mtflag) + f_print(fout, "&result_%d, ", i); + + f_print(fout, "clnt);\n"); + } + if (mtflag) { + f_print(fout, "\tif (retval_%d != RPC_SUCCESS) {\n", i); + + } else { + f_print(fout, "\tif (result_%d == (", i); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*) NULL) {\n"); + } + f_print(fout, "\t\tclnt_perror(clnt, \"call failed\");\n"); + f_print(fout, "\t}\n"); + } + + f_print(fout, "#ifndef\tDEBUG\n"); + f_print(fout, "\tclnt_destroy(clnt);\n"); + f_print(fout, "#endif\t /* DEBUG */\n"); + f_print(fout, "}\n"); +} + +static +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 (!mtflag) { + return_type(proc); + f_print(fout, "*\n"); + } else + f_print(fout, "bool_t\n"); + if (Cflag || mtflag) + pvname_svc(proc->proc_name, vp->vers_num); + else + pvname(proc->proc_name, vp->vers_num); + printarglist(proc, "result", RQSTP, "struct svc_req *"); + + f_print(fout, "{\n"); + if (!mtflag) { + f_print(fout, "\tstatic "); + if(!streq(proc->res_type, "void")) + return_type(proc); + else + f_print(fout, "char *"); + /* cannot have void type */ + f_print(fout, " result;\n", proc->res_type); + } + else + f_print(fout, "\tbool_t retval;\n"); + f_print(fout, + "\n\t/*\n\t * insert server code here\n\t */\n\n"); + + if (!mtflag) + 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"); + else + f_print(fout, "\treturn (retval);\n}\n"); + } + /* put in sample freeing routine */ + if (mtflag) { + f_print(fout, "\nint\n"); + pvname(def->def_name, vp->vers_num); + if (Cflag) + f_print(fout,"_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)\n"); + else { + f_print(fout,"_freeresult(transp, xdr_result, result)\n"); + f_print(fout,"\tSVCXPRT *transp;\n"); + f_print(fout,"\txdrproc_t xdr_result;\n"); + f_print(fout,"\tcaddr_t result;\n"); + } + f_print(fout, "{\n"); + f_print(fout, "\t(void) xdr_free(xdr_result, result);\n"); + f_print(fout, + "\n\t/*\n\t * Insert additional freeing code here, if needed\n\t */\n"); + f_print(fout, "\n}\n"); + + + } + } +} + + + +static +return_type(plist) + proc_list *plist; +{ + ptype(plist->res_prefix, plist->res_type, 1); +} + +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)\n\tint argc;\n\tchar *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/usr.bin/rpcgen/rpc_scan.c b/usr.bin/rpcgen/rpc_scan.c index c531bba..e65b799 100644 --- a/usr.bin/rpcgen/rpc_scan.c +++ b/usr.bin/rpcgen/rpc_scan.c @@ -1,4 +1,3 @@ -/* @(#)rpc_scan.c 2.1 88/08/01 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -27,19 +26,24 @@ * 2550 Garcia Avenue * Mountain View, California 94043 */ + +#ident "@(#)rpc_scan.c 1.13 93/07/05 SMI" + #ifndef lint -/*static char sccsid[] = "from: @(#)rpc_scan.c 1.6 87/06/24 (C) 1987 SMI";*/ -static char rcsid[] = "$Id: rpc_scan.c,v 1.1 1993/09/13 23:20:18 jtc Exp $"; +static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI"; #endif /* * rpc_scan.c, Scanner for the RPC protocol compiler * Copyright (C) 1987, Sun Microsystems, Inc. */ + +#include <sys/wait.h> #include <stdio.h> #include <ctype.h> -#include <strings.h> +#include <string.h> #include "rpc_scan.h" +#include "rpc_parse.h" #include "rpc_util.h" #define startcomment(where) (where[0] == '/' && where[1] == '*') @@ -48,8 +52,16 @@ static char rcsid[] = "$Id: rpc_scan.c,v 1.1 1993/09/13 23:20:18 jtc Exp $"; static int pushed = 0; /* is a token pushed */ static token lasttok; /* last token, if pushed */ -static int unget_token(), findstrconst(), findconst(), findkind(), cppline(), - directive(), printdirective(), docppline(); +static int unget_token __P(( token * )); +static int findstrconst __P(( char **, char **)); +static int findchrconst __P(( char **, char **)); +static int findconst __P(( char **, char **)); +static int findkind __P(( char **, token * )); +static int cppline __P(( char * )); +static int directive __P(( char * )); +static int printdirective __P(( char * )); +static int docppline __P(( char *, int *, char ** )); + /* * scan expecting 1 given token */ @@ -65,7 +77,7 @@ scan(expect, tokp) } /* - * scan expecting 2 given tokens + * scan expecting any of the 2 given tokens */ void scan2(expect1, expect2, tokp) @@ -80,7 +92,7 @@ scan2(expect1, expect2, tokp) } /* - * scan expecting 3 given token + * scan expecting any of the 3 given token */ void scan3(expect1, expect2, expect3, tokp) @@ -96,7 +108,6 @@ scan3(expect1, expect2, expect3, tokp) } } - /* * scan expecting a constant, possibly symbolic */ @@ -113,7 +124,6 @@ scan_num(tokp) } } - /* * Peek at the next token */ @@ -125,7 +135,6 @@ peek(tokp) unget_token(tokp); } - /* * Peek at the next token and scan it if it matches what you expect */ @@ -142,8 +151,6 @@ peekscan(expect, tokp) return (0); } - - /* * Get the next token, printing out any directive that are encountered. */ @@ -152,7 +159,9 @@ get_token(tokp) token *tokp; { int commenting; - + int stat = 0; + + if (pushed) { pushed = 0; *tokp = lasttok; @@ -164,6 +173,12 @@ get_token(tokp) 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; } @@ -185,10 +200,12 @@ get_token(tokp) where++; /* eat */ } } else if (commenting) { - where++; - if (endcomment(where)) { - where++; - commenting--; + for (where++; *where; where++) { + if (endcomment(where)) { + where++; + commenting--; + break; + } } } else if (startcomment(where)) { where += 2; @@ -259,6 +276,10 @@ get_token(tokp) tokp->kind = TOK_STRCONST; findstrconst(&where, &tokp->str); break; + case '\'': + tokp->kind = TOK_CHARCONST; + findchrconst(&where, &tokp->str); + break; case '-': case '0': @@ -275,7 +296,6 @@ get_token(tokp) findconst(&where, &tokp->str); break; - default: if (!(isalpha(*where) || *where == '_')) { char buf[100]; @@ -295,8 +315,6 @@ get_token(tokp) } } - - static unget_token(tokp) token *tokp; @@ -305,7 +323,6 @@ unget_token(tokp) pushed = 1; } - static findstrconst(str, val) char **str; @@ -330,6 +347,32 @@ findstrconst(str, val) } static +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 findconst(str, val) char **str; char **val; @@ -355,8 +398,6 @@ findconst(str, val) *str = p; } - - static token symbols[] = { {TOK_CONST, "const"}, {TOK_UNION, "union"}, @@ -374,21 +415,21 @@ static token symbols[] = { {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 findkind(mark, tokp) char **mark; token *tokp; { - int len; token *s; char *str; diff --git a/usr.bin/rpcgen/rpc_scan.h b/usr.bin/rpcgen/rpc_scan.h index fdb7e7b..cf042d0 100644 --- a/usr.bin/rpcgen/rpc_scan.h +++ b/usr.bin/rpcgen/rpc_scan.h @@ -25,15 +25,43 @@ * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 - * - * from: @(#)rpc_scan.h 1.3 87/03/09 (C) 1987 SMI - * from: @(#)rpc_scan.h 2.1 88/08/01 4.0 RPCSRC - * $Id: rpc_scan.h,v 1.1 1993/09/13 23:20:18 jtc Exp $ */ +#pragma ident "@(#)rpc_scan.h 1.11 94/05/15 SMI" + +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ +/* The copyright notice above does not evidence any */ +/* actual or intended publication of such source code. */ + + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +* PROPRIETARY NOTICE (Combined) +* +* This source code is unpublished proprietary information +* constituting, or derived under license from AT&T's UNIX(r) System V. +* In addition, portions of such source code were derived from Berkeley +* 4.3 BSD under license from the Regents of the University of +* California. +* +* +* +* Copyright Notice +* +* Notice of copyright on this source code product does not indicate +* publication. +* +* (c) 1986,1987,1988.1989 Sun Microsystems, Inc +* (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. +* All rights reserved. +*/ + +/* @(#)rpc_scan.h 1.3 90/08/29 (C) 1987 SMI */ /* * rpc_scan.h, Definitions for the RPCL scanner - * Copyright (C) 1987, Sun Microsystems, Inc. */ /* @@ -41,6 +69,7 @@ */ enum tok_kind { TOK_IDENT, + TOK_CHARCONST, TOK_STRCONST, TOK_LPAREN, TOK_RPAREN, @@ -66,9 +95,11 @@ enum tok_kind { TOK_INT, TOK_SHORT, TOK_LONG, + TOK_HYPER, TOK_UNSIGNED, TOK_FLOAT, TOK_DOUBLE, + TOK_QUAD, TOK_OPAQUE, TOK_CHAR, TOK_STRING, @@ -93,7 +124,6 @@ typedef struct token token; /* * routine interface */ -void scanprint(); void scan(); void scan2(); void scan3(); diff --git a/usr.bin/rpcgen/rpc_svcout.c b/usr.bin/rpcgen/rpc_svcout.c index 7f375c5..a7b7d87 100644 --- a/usr.bin/rpcgen/rpc_svcout.c +++ b/usr.bin/rpcgen/rpc_svcout.c @@ -1,4 +1,3 @@ -/* @(#)rpc_svcout.c 2.1 88/08/01 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -27,17 +26,19 @@ * 2550 Garcia Avenue * Mountain View, California 94043 */ + +#ident "@(#)rpc_svcout.c 1.4 90/04/13 SMI" + #ifndef lint -/*static char sccsid[] = "from: @(#)rpc_svcout.c 1.6 87/06/24 (C) 1987 SMI";*/ -static char rcsid[] = "$Id: rpc_svcout.c,v 1.1 1993/09/13 23:20:19 jtc Exp $"; +static char sccsid[] = "@(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI"; #endif /* * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler - * Copyright (C) 1987, Sun Microsytsems, Inc. + * Copyright (C) 1987, Sun Microsystems, Inc. */ #include <stdio.h> -#include <strings.h> +#include <string.h> #include "rpc_parse.h" #include "rpc_util.h" @@ -46,98 +47,244 @@ static char TRANSP[] = "transp"; static char ARG[] = "argument"; static char RESULT[] = "result"; static char ROUTINE[] = "local"; +static char RETVAL[] = "retval"; + +char _errbuf[256]; /* For all messages */ + +void internal_proctype __P(( proc_list * )); +static int write_real_program __P(( definition * )); +static int write_program __P(( definition *, char * )); +static int printerr __P(( char *, char * )); +static int printif __P(( char *, char *, char *, char * )); +static int write_inetmost __P(( char * )); +static int print_return __P(( char * )); +static int print_pmapunset __P(( char * )); +static int print_err_message __P(( char * )); +static int write_timeout_func __P(( void )); +static int write_pm_most __P(( char *, int )); +static int write_rpc_svc_fg __P(( char *, char * )); +static int open_log_file __P(( char *, char * )); + + +static +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)); +} + +void +internal_proctype(plist) + proc_list *plist; +{ + f_print(fout, "static "); + ptype(plist->res_prefix, plist->res_type, 1); + f_print(fout, "*"); +} + -static int write_program(), printerr(), printif(); /* - * write most of the service, that is, everything but the registrations. + * write most of the service, that is, everything but the registrations. */ void -write_most() +write_most(infile, netflag, nomain) + char *infile; /* our name */ + int netflag; + int nomain; { - list *l; - definition *def; - version_list *vp; + 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"); + if (!tirpcflag) { + f_print(fout, "%s int _rpcfdtype;", var_type); + f_print(fout, "\n\t\t /* Whether Stream or \ +Datagram ? */\n"); + } + + if (timerflag) { + f_print(fout, " /* States a server can be in \ +wrt request */\n\n"); + f_print(fout, "#define\t_IDLE 0\n"); + f_print(fout, "#define\t_SERVED 1\n"); + f_print(fout, "#define\t_SERVING 2\n\n"); + f_print(fout, "static int _rpcsvcstate = _IDLE;"); + f_print(fout, "\t /* Set when a request is \ +serviced */\n"); + + if (mtflag) { + f_print(fout, "mutex_t _svcstate_lock;"); + f_print(fout, "\t\t\t/* Mutex lock for variable _rpcsvcstate */\n"); - 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, "\nstatic void "); - pvname(def->def_name, vp->vers_num); - f_print(fout, "();"); } + } + + write_svc_aux(nomain); } - f_print(fout, "\n\n"); - f_print(fout, "main()\n"); + /* write out dispatcher and stubs */ + write_programs(nomain? (char *)NULL : "static"); + + if (nomain) + return; + + f_print(fout, "\nmain()\n"); f_print(fout, "{\n"); - f_print(fout, "\tSVCXPRT *%s;\n", TRANSP); + if (inetdflag) { + write_inetmost(infile); + /* Includes call to write_rpc_svc_fg() */ + } else { + if (tirpcflag) { + if (netflag) { + f_print(fout, + "\tregister SVCXPRT *%s;\n", TRANSP); + f_print(fout, + "\tstruct netconfig *nconf = NULL;\n"); + } + f_print(fout, "\tpid_t pid;\n"); + f_print(fout, "\tint i;\n"); + f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n"); + + if (mtflag & timerflag) + f_print(fout, "\tmutex_init(&_svcstate_lock, USYNC_THREAD, NULL);\n"); + + write_pm_most(infile, netflag); + f_print(fout, "\telse {\n"); + write_rpc_svc_fg(infile, "\t\t"); + f_print(fout, "\t}\n"); + } else { + f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP); + f_print(fout, "\n"); + print_pmapunset("\t"); + } + } + + if (logflag && !inetdflag) { + open_log_file(infile, "\t"); + } +} + +/* + * write a registration for the given transport + */ +void +write_netid_register(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, 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, "\t(void)pmap_unset(%s, %s);\n", def->def_name, vp->vers_name); + 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 + * write a registration for the given transport for TLI */ void -write_register(transp) +write_nettype_register(transp) char *transp; { list *l; definition *def; version_list *vp; - f_print(fout, "\n"); - f_print(fout, "\t%s = svc%s_create(RPC_ANYSOCK", TRANSP, transp); - if (streq(transp, "tcp")) { - f_print(fout, ", 0, 0"); - } - f_print(fout, ");\n"); - f_print(fout, "\tif (%s == NULL) {\n", TRANSP); - f_print(fout, "\t\t(void)fprintf(stderr, \"cannot create %s service.\\n\");\n", transp); - f_print(fout, "\t\texit(1);\n"); - f_print(fout, "\t}\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, - "\tif (!svc_register(%s, %s, %s, ", - TRANSP, def->def_name, vp->vers_name); + f_print(fout, "\tif (!svc_create("); pvname(def->def_name, vp->vers_num); - f_print(fout, ", IPPROTO_%s)) {\n", - streq(transp, "udp") ? "UDP" : "TCP"); - f_print(fout, - "\t\t(void)fprintf(stderr, \"unable to register (%s, %s, %s).\\n\");\n", + 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 + * 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/2);\n"); + f_print(fout, "\t}\n"); + } + } f_print(fout, "\tsvc_run();\n"); - f_print(fout, "\t(void)fprintf(stderr, \"svc_run returned\\n\");\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"); } @@ -148,14 +295,109 @@ write_programs(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 +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"); + if (!mtflag) + internal_proctype(proc); + else + f_print(fout, "int"); + f_print(fout, "\n_"); + pvname(proc->proc_name, vp->vers_num); + if (Cflag) { + f_print(fout, "("); + /* arg name */ + if (proc->arg_num > 1) + f_print(fout, proc->args.argname); + else + ptype(proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + if (mtflag) { + f_print(fout, " *argp, void *%s, struct svc_req *%s)\n", + RESULT, RQSTP); + + + } + else + f_print(fout, " *argp, struct svc_req *%s)\n", + RQSTP); + + } else { + if (mtflag) + f_print(fout, "(argp, %s, %s)\n", RESULT, 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"); + } + if (mtflag) + f_print(fout, "\tvoid *%s;\n", RESULT); + f_print(fout, "\tstruct svc_req *%s;\n", RQSTP); + } + + f_print(fout, "{\n"); + f_print(fout, "\treturn ("); + if (Cflag || mtflag) /* for mtflag, arguments are different */ + pvname_svc(proc->proc_name, vp->vers_num); + else + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "("); + if (proc->arg_num < 2) { /* single argument */ + if (!streq(proc->args.decls->decl.type, "void")) + f_print(fout, "*argp, "); /* non-void */ + } else { + for (l = proc->args.decls; l != NULL; + l = l->next) + f_print(fout, "argp->%s, ", + l->decl.name); + } + if (mtflag) + f_print(fout, "%s, ",RESULT); + f_print(fout, "%s));\n}\n", RQSTP); + } + } +} static write_program(def, storage) @@ -173,74 +415,206 @@ write_program(def, storage) } f_print(fout, "void\n"); pvname(def->def_name, vp->vers_num); - f_print(fout, "(%s, %s)\n", RQSTP, TRANSP); - f_print(fout, " struct svc_req *%s;\n", RQSTP); - f_print(fout, " SVCXPRT *%s;\n", TRANSP); + + if (Cflag) { + f_print(fout, "(struct svc_req *%s, ", RQSTP); + f_print(fout, "register SVCXPRT *%s)\n", TRANSP); + } else { + f_print(fout, "(%s, %s)\n", RQSTP, TRANSP); + f_print(fout, " struct svc_req *%s;\n", RQSTP); + f_print(fout, " register SVCXPRT *%s;\n", TRANSP); + } + f_print(fout, "{\n"); filled = 0; f_print(fout, "\tunion {\n"); for (proc = vp->procs; proc != NULL; proc = proc->next) { - if (streq(proc->arg_type, "void")) { - continue; + 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"); } - filled = 1; - f_print(fout, "\t\t"); - ptype(proc->arg_prefix, proc->arg_type, 0); - 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); - f_print(fout, "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", ARG, RESULT); - f_print(fout, "\tchar *(*%s)();\n", ROUTINE); + + if (mtflag) { + f_print(fout, "\tunion {\n"); + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\t\t"); + ptype(proc->res_prefix, proc->res_type, 0); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_res;\n"); + } + f_print(fout, "\t} %s;\n", RESULT); + f_print(fout, "\tbool_t %s;\n", RETVAL); + + } else + f_print(fout, "\tchar *%s;\n", RESULT); + + if (Cflag) { + f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", + ARG, RESULT); + if (mtflag) + f_print(fout, + "\tbool_t (*%s)(char *, void *, struct svc_req *);\n", + ROUTINE); + else + f_print(fout, + "\tchar *(*%s)(char *, struct svc_req *);\n", + ROUTINE); + } else { + f_print(fout, + "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", + ARG, RESULT); + if (mtflag) + f_print(fout, "\tbool_t (*%s)();\n", ROUTINE); + else + f_print(fout, "\tchar *(*%s)();\n", ROUTINE); + } f_print(fout, "\n"); - f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP); + if (timerflag) { + if (mtflag) + f_print(fout, "\tmutex_lock(&_svcstate_lock);\n"); + + f_print(fout, "\t_rpcsvcstate = _SERVING;\n"); + if (mtflag) + f_print(fout, "\tmutex_unlock(&_svcstate_lock);\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, xdr_void, (char *)NULL);\n", TRANSP); - f_print(fout, "\t\treturn;\n\n"); + f_print(fout, + Cflag + ? "\t\t(void) svc_sendreply(%s,\n\t\t\t\ +(xdrproc_t) xdr_void, (char *)NULL);\n" + : "\t\t(void) svc_sendreply(%s, xdr_void,\n\t\t\t\ +(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); - f_print(fout, "\t\txdr_%s = xdr_%s;\n", ARG, - stringfix(proc->arg_type)); - f_print(fout, "\t\txdr_%s = xdr_%s;\n", RESULT, - stringfix(proc->res_type)); - f_print(fout, "\t\t%s = (char *(*)()) ", ROUTINE); - pvname(proc->proc_name, vp->vers_num); + 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) + if (mtflag) + f_print(fout, + "\t\t%s = (bool_t (*) (char *, void *, struct svc_req *))", + ROUTINE); + else + f_print(fout, + "\t\t%s = (char *(*)(char *, struct svc_req *)) ", + ROUTINE); + else + if (mtflag) + f_print(fout, "\t\t%s = (bool_t (*)()) ", + ROUTINE); + else + + f_print(fout, "\t\t%s = (char *(*)()) ", + ROUTINE); + if (newstyle) { /* new style: calls internal routine */ + f_print(fout, "_"); + } + if ((Cflag || mtflag) && !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); - f_print(fout, "\t\treturn;\n"); + print_return("\t\t"); f_print(fout, "\t}\n"); - f_print(fout, "\tbzero((char *)&%s, sizeof(%s));\n", ARG, ARG); - printif("getargs", TRANSP, "&", ARG); + f_print(fout, + "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", + ARG, ARG); + if (Cflag) + printif("getargs", TRANSP, "(caddr_t) &", ARG); + else + printif("getargs", TRANSP, "&", ARG); printerr("decode", TRANSP); - f_print(fout, "\t\treturn;\n"); + print_return("\t\t"); f_print(fout, "\t}\n"); - f_print(fout, "\t%s = (*%s)(&%s, %s);\n", RESULT, ROUTINE, ARG, - RQSTP); - f_print(fout, - "\tif (%s != NULL && !svc_sendreply(%s, xdr_%s, %s)) {\n", - RESULT, TRANSP, RESULT, RESULT); + if (!mtflag) + 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); + else + if (Cflag) + f_print(fout, "\t%s = (bool_t) (*%s)((char *)&%s, (void *)&%s, %s);\n", + RETVAL, ROUTINE, ARG, RESULT, RQSTP); + else + f_print(fout, "\t%s = (bool_t) (*%s)(&%s, &%s, %s);\n", + RETVAL, ROUTINE, ARG, RESULT, RQSTP); + + + + + if (mtflag) + f_print(fout, + "\tif (%s > 0 && !svc_sendreply(%s, xdr_%s, (char *)&%s)) {\n", + RETVAL, TRANSP, RESULT, RESULT); + else + f_print(fout, + "\tif (%s != NULL && !svc_sendreply(%s, xdr_%s, %s)) {\n", + RESULT, TRANSP, RESULT, RESULT); + printerr("systemerr", TRANSP); f_print(fout, "\t}\n"); - printif("freeargs", TRANSP, "&", ARG); - f_print(fout, "\t\t(void)fprintf(stderr, \"unable to free arguments\\n\");\n"); + if (Cflag) + printif("freeargs", TRANSP, "(caddr_t) &", ARG); + else + printif("freeargs", TRANSP, "&", ARG); + (void) sprintf(_errbuf, "unable to free arguments"); + print_err_message("\t\t"); f_print(fout, "\t\texit(1);\n"); f_print(fout, "\t}\n"); - - f_print(fout, "}\n\n"); + /* print out free routine */ + if (mtflag) { + f_print(fout,"\tif (!"); + pvname(def->def_name, vp->vers_num); + f_print(fout,"_freeresult(%s, xdr_%s, (caddr_t) &%s))\n", + TRANSP, RESULT, RESULT); + (void) sprintf(_errbuf, "unable to free results"); + print_err_message("\t\t"); + f_print(fout, "\n"); + }; + print_return("\t"); + f_print(fout, "}\n"); } } @@ -263,7 +637,6 @@ printif(proc, transp, prefix, arg) proc, transp, arg, prefix, arg); } - nullproc(proc) proc_list *proc; { @@ -274,3 +647,436 @@ nullproc(proc) } return (0); } + +static +write_inetmost(infile) + char *infile; +{ + f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP); + f_print(fout, "\tint sock;\n"); + f_print(fout, "\tint proto;\n"); + f_print(fout, "\tstruct sockaddr_in saddr;\n"); + f_print(fout, "\tint asize = sizeof (saddr);\n"); + f_print(fout, "\n"); + f_print(fout, + "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n"); + f_print(fout, "\t\tint ssize = sizeof (int);\n\n"); + f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n"); + f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\tsock = 0;\n"); + f_print(fout, "\t\t_rpcpmstart = 1;\n"); + f_print(fout, "\t\tproto = 0;\n"); + open_log_file(infile, "\t\t"); + f_print(fout, "\t} else {\n"); + write_rpc_svc_fg(infile, "\t\t"); + f_print(fout, "\t\tsock = RPC_ANYSOCK;\n"); + print_pmapunset("\t\t"); + f_print(fout, "\t}\n"); +} + +static +print_return(space) + char *space; +{ + if (exitnow) + f_print(fout, "%sexit(0);\n", space); + else { + if (timerflag) { + if (mtflag) + f_print(fout, "%smutex_lock(&_svcstate_lock);\n", space); + f_print(fout, "%s_rpcsvcstate = _SERVED;\n", space); + if (mtflag) + f_print(fout, "%smutex_unlock(&_svcstate_lock);\n", space); + } + f_print(fout, "%sreturn;\n", space); + } +} + +static +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 +print_err_message(space) + char *space; +{ + if (logflag) + f_print(fout, "%ssyslog(LOG_ERR, \"%s\");\n", space, _errbuf); + else if (inetdflag || pmflag) + f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf); + else + f_print(fout, "%sfprintf(stderr, \"%s\");\n", space, _errbuf); +} + +/* + * Write the server auxiliary function (_msgout, timeout) + */ +void +write_svc_aux(nomain) + int nomain; +{ + if (!logflag) + write_msg_out(); + if (!nomain) + write_timeout_func(); +} + +/* + * Write the _msgout function + */ + +write_msg_out() +{ + f_print(fout, "\n"); +/* + * Avoid making _msgout() static -- it's useful to have it visible + * in the toplevel RPC server code. + */ + 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, 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, msg);\n"); + f_print(fout, "#endif\n"); + f_print(fout, "}\n"); +} + +/* + * Write the timeout function + */ +static +write_timeout_func() +{ + if (!timerflag) + return; + + f_print(fout, "\n"); + f_print(fout, "static void\n"); + if (!Cflag) { + f_print(fout, "closedown(sig)\n"); + f_print(fout, "\tint sig;\n"); + } else + f_print(fout, "closedown(int sig)\n"); + f_print(fout, "{\n"); + if (mtflag) + f_print(fout, "\tmutex_lock(&_svcstate_lock);\n"); + f_print(fout, "\tif (_rpcsvcstate == _IDLE) {\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"); + + if (mtflag) + f_print(fout, "\t\t\t\tmutex_unlock(&_svcstate_lock);\n"); + + f_print(fout, "\t\t\t\treturn;\n\t\t\t}\n"); + } else { + f_print(fout, "\t\t\tsize = getdtablesize();\n"); + } + f_print(fout, "\t\t}\n"); + f_print(fout, + "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n"); + f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n"); + f_print(fout, "\t\t\t\topenfd++;\n"); + f_print(fout, "\t\tif (openfd <= 1)\n"); + f_print(fout, "\t\t\texit(0);\n"); + f_print(fout, "\t}\n"); + f_print(fout, "\tif (_rpcsvcstate == _SERVED)\n"); + f_print(fout, "\t\t_rpcsvcstate = _IDLE;\n\n"); + if (mtflag) + f_print(fout, "\tmutex_unlock(&_svcstate_lock);\n"); + + f_print(fout, "\t(void) signal(SIGALRM, %s closedown);\n", + Cflag? "(SIG_PF)" : "(void(*)())"); + f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n"); + f_print(fout, "}\n"); + +} + +/* + * Write the most of port monitor support + */ +static +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"); + open_log_file(infile, "\t\t"); + f_print(fout, "\n\t\tif ((netid = \ +getenv(\"NLSPROVIDER\")) == NULL) {\n"); + + if (timerflag) { + f_print(fout, "\t\t/* started from inetd */\n"); + f_print(fout, "\t\t\tpmclose = 1;\n"); + } + f_print(fout, + "\t\t} else {\n"); + f_print(fout, "\t\t\tif ((nconf = getnetconfigent(netid)) == NULL)\n"); + sprintf(_errbuf, "cannot get transport info"); + print_err_message("\t\t\t\t"); + if (timerflag) + f_print(fout, "\n\t\t\tpmclose = \ +(t_getstate(0) != T_DATAXFER);\n"); + 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"); + 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/2);\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}"); +} + +/* + * Support for backgrounding the server if self started. + */ +static +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 +open_log_file(infile, sp) + char *infile; + char *sp; +{ + char *s; + + s = strrchr(infile, '.'); + if (s) + *s = '\0'; + f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile); + if (s) + *s = '.'; +} + + + + +/* + * write a registration for the given transport for Inetd + */ +void +write_inetd_register(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"); + } + 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/usr.bin/rpcgen/rpc_tblout.c b/usr.bin/rpcgen/rpc_tblout.c new file mode 100644 index 0000000..e851ded --- /dev/null +++ b/usr.bin/rpcgen/rpc_tblout.c @@ -0,0 +1,171 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#ident "@(#)rpc_tblout.c 1.11 93/07/05 SMI" + +#ifndef lint +static char sccsid[] = "@(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI"; +#endif + +/* + * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler + * Copyright (C) 1989, Sun Microsystems, Inc. + */ +#include <stdio.h> +#include <string.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[] = "\n\t(char *(*)())0,\n\ + \t(xdrproc_t) xdr_void,\t\t\t0,\n\ + \t(xdrproc_t) xdr_void,\t\t\t0,\n"; + + +static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n"; + +static int write_table __P(( definition * )); +static int 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 +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, null_entry); + } + for (proc = vp->procs; proc != NULL; proc = proc->next) { + current = atoi(proc->proc_num); + if (current != expected++) { + f_print(fout, + "\n/*\n * WARNING: table out of order\n */\n"); + if (warning == 0) { + f_print(stderr, + "WARNING %s table is out of order\n", + progvers); + warning = 1; + nonfatalerrors = 1; + } + expected = current + 1; + } + f_print(fout, "\n\t(char *(*)())RPCGEN_ACTION("); + + /* routine to invoke */ + if( Cflag && !newstyle ) + pvname_svc(proc->proc_name, vp->vers_num); + else { + if( newstyle ) + f_print( fout, "_"); /* calls internal func */ + pvname(proc->proc_name, vp->vers_num); + } + f_print(fout, "),\n"); + + /* argument info */ + if( proc->arg_num > 1 ) + printit((char*) NULL, proc->args.argname ); + else + /* do we have to do something special for newstyle */ + printit( proc->args.decls->decl.prefix, + proc->args.decls->decl.type ); + /* result info */ + printit(proc->res_prefix, proc->res_type); + } + + /* print the table trailer */ + f_print(fout, tbl_end); + f_print(fout, tbl_nproc, progvers, progvers, progvers); + } +} + +static +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/usr.bin/rpcgen/rpc_util.c b/usr.bin/rpcgen/rpc_util.c index 6d5b18e..5d3fa06 100644 --- a/usr.bin/rpcgen/rpc_util.c +++ b/usr.bin/rpcgen/rpc_util.c @@ -1,4 +1,3 @@ -/* @(#)rpc_util.c 2.1 88/08/01 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -27,50 +26,55 @@ * 2550 Garcia Avenue * Mountain View, California 94043 */ + +#ident "@(#)rpc_util.c 1.14 93/07/05 SMI" + #ifndef lint -/*static char sccsid[] = "from: @(#)rpc_util.c 1.5 87/06/24 (C) 1987 SMI";*/ -static char rcsid[] = "$Id: rpc_util.c,v 1.1 1993/09/13 23:20:20 jtc Exp $"; +static char sccsid[] = "@(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI"; #endif /* - * rpc_util.c, Utility routines for the RPC protocol compiler - * Copyright (C) 1987, Sun Microsystems, Inc. + * rpc_util.c, Utility routines for the RPC protocol compiler + * Copyright (C) 1989, Sun Microsystems, Inc. */ #include <stdio.h> +#include <ctype.h> #include "rpc_scan.h" #include "rpc_parse.h" #include "rpc_util.h" +#define ARGEXT "argument" + char curline[MAXLINESIZE]; /* current read line */ -char *where = curline; /* current point in line */ -int linenum = 0; /* current line number */ +char *where = curline; /* current point in line */ +int linenum = 0; /* current line number */ -char *infilename; /* input filename */ +char *infilename; /* input filename */ -#define NFILES 4 -char *outfiles[NFILES]; /* output file names */ +#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 */ +FILE *fout; /* file pointer of current output */ +FILE *fin; /* file pointer of current input */ -list *defined; /* list of defined things */ +list *defined; /* list of defined things */ -static int printwhere(); +static int printwhere __P(( void )); /* - * Reinitialize the world + * Reinitialize the world */ reinitialize() { - bzero(curline, MAXLINESIZE); + memset(curline, 0, MAXLINESIZE); where = curline; linenum = 0; defined = NULL; } /* - * string equality + * string equality */ streq(a, b) char *a; @@ -80,9 +84,9 @@ streq(a, b) } /* - * find a value in a list + * find a value in a list */ -char * +definition * findval(lst, val, cmp) list *lst; char *val; @@ -98,12 +102,12 @@ findval(lst, val, cmp) } /* - * store a value in a list + * store a value in a list */ void storeval(lstp, val) list **lstp; - char *val; + definition *val; { list **l; list *lst; @@ -115,7 +119,6 @@ storeval(lstp, val) *l = lst; } - static findit(def, type) definition *def; @@ -124,7 +127,6 @@ findit(def, type) return (streq(def->def_name, type)); } - static char * fixit(type, orig) char *type; @@ -138,7 +140,11 @@ fixit(type, orig) } switch (def->def.ty.rel) { case REL_VECTOR: - return (def->def.ty.old_type); + if (streq(def->def.ty.old_type, "opaque")) + return ("char"); + else + return (def->def.ty.old_type); + case REL_ALIAS: return (fixit(def->def.ty.old_type, orig)); default: @@ -186,7 +192,6 @@ ptype(prefix, type, follow) } } - static typedefed(def, type) definition *def; @@ -224,8 +229,7 @@ isvectordef(type, rel) } } - -static char * +char * locase(str) char *str; { @@ -240,6 +244,13 @@ locase(str) return (buf); } +void +pvname_svc(pname, vnum) + char *pname; + char *vnum; +{ + f_print(fout, "%s_%s_svc", locase(pname), vnum); +} void pvname(pname, vnum) @@ -249,9 +260,8 @@ pvname(pname, vnum) f_print(fout, "%s_%s", locase(pname), vnum); } - /* - * print a useful (?) error message, and then die + * print a useful (?) error message, and then die */ void error(msg) @@ -265,7 +275,7 @@ error(msg) /* * Something went wrong, unlink any files that we may have created and then - * die. + * die. */ crash() { @@ -277,7 +287,6 @@ crash() exit(1); } - void record_open(file) char *file; @@ -294,7 +303,7 @@ static char expectbuf[100]; static char *toktostr(); /* - * error, token encountered was not the expected one + * error, token encountered was not the expected one */ void expected1(exp1) @@ -306,7 +315,7 @@ expected1(exp1) } /* - * error, token encountered was not one of two expected ones + * error, token encountered was not one of two expected ones */ void expected2(exp1, exp2) @@ -319,7 +328,7 @@ expected2(exp1, exp2) } /* - * error, token encountered was not one of 3 expected ones + * error, token encountered was not one of 3 expected ones */ void expected3(exp1, exp2, exp3) @@ -343,42 +352,41 @@ tabify(f, tab) } - 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, "??????"} + {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 * @@ -391,8 +399,6 @@ toktostr(kind) return (sp->str); } - - static printbuf() { @@ -415,7 +421,6 @@ printbuf() } } - static printwhere() { @@ -437,3 +442,67 @@ printwhere() } (void) fputc('\n', stderr); } + +char * +make_argname(pname, vname) + char *pname; + char *vname; +{ + char *name; + + name = malloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3); + if (!name) { + fprintf(stderr, "failed in malloc"); + exit(1); + } + sprintf(name, "%s_%s_%s", locase(pname), vname, ARGEXT); + return (name); +} + +bas_type *typ_list_h; +bas_type *typ_list_t; + +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/usr.bin/rpcgen/rpc_util.h b/usr.bin/rpcgen/rpc_util.h index dcca92f..259860f 100644 --- a/usr.bin/rpcgen/rpc_util.h +++ b/usr.bin/rpcgen/rpc_util.h @@ -25,34 +25,87 @@ * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 - * - * from: @(#)rpc_util.h 1.6 87/06/24 (C) 1987 SMI - * from: @(#)rpc_util.h 2.1 88/08/01 4.0 RPCSRC - * $Id: rpc_util.h,v 1.1 1993/09/13 23:20:21 jtc Exp $ */ +#pragma ident "@(#)rpc_util.h 1.16 94/05/15 SMI" + +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ +/* The copyright notice above does not evidence any */ +/* actual or intended publication of such source code. */ + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +* PROPRIETARY NOTICE (Combined) +* +* This source code is unpublished proprietary information +* constituting, or derived under license from AT&T's UNIX(r) System V. +* In addition, portions of such source code were derived from Berkeley +* 4.3 BSD under license from the Regents of the University of +* California. +* +* +* +* Copyright Notice +* +* Notice of copyright on this source code product does not indicate +* publication. +* +* (c) 1986,1987,1988.1989 Sun Microsystems, Inc +* (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. +* All rights reserved. +*/ + +/* @(#)rpc_util.h 1.5 90/08/29 (C) 1987 SMI */ /* * rpc_util.h, Useful definitions for the RPC protocol compiler - * Copyright (C) 1987, Sun Microsystems, Inc. */ -extern char *malloc(); +#include <sys/types.h> +#include <stdlib.h> -#define alloc(size) malloc((unsigned)(size)) -#define ALLOC(object) (object *) malloc(sizeof(object)) +#define alloc(size) malloc((unsigned)(size)) +#define ALLOC(object) (object *) malloc(sizeof(object)) -#define s_print (void) sprintf -#define f_print (void) fprintf +#define s_print (void) sprintf +#define f_print (void) fprintf struct list { - char *val; + definition *val; struct list *next; }; typedef struct list list; +struct xdrfunc { + char *name; + int pointerp; + struct xdrfunc *next; +}; +typedef struct xdrfunc xdrfunc; + +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 */ + int makefileflag; /* Generate a template Makefile */ + char *infile; /* input module name */ + char *outfile; /* output module name */ +}; + +#define PUT 1 +#define GET 2 + /* * Global variables */ -#define MAXLINESIZE 1024 +#define MAXLINESIZE 1024 extern char curline[MAXLINESIZE]; extern char *where; extern int linenum; @@ -63,21 +116,53 @@ extern FILE *fin; extern list *defined; + +extern bas_type *typ_list_h; +extern bas_type *typ_list_t; +extern xdrfunc *xdrfunc_head, *xdrfunc_tail; + +/* + * All the option flags + */ +extern int inetdflag; +extern int pmflag; +extern int tblflag; +extern int logflag; +extern int newstyle; +extern int Cflag; /* ANSI-C/C++ flag */ +extern int CCflag; /* C++ flag */ +extern int tirpcflag; /* flag for generating tirpc code */ +extern int inline; /* if this is 0, then do not generate inline code */ +extern int mtflag; + +/* + * 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 */ void storeval(); -#define STOREVAL(list,item) \ - storeval(list,(char *)item) +#define STOREVAL(list,item) \ + storeval(list,item) -char *findval(); +definition *findval(); -#define FINDVAL(list,item,finder) \ - findval(list, (char *) item, finder) +#define FINDVAL(list,item,finder) \ + findval(list, item, finder) char *fixtype(); char *stringfix(); +char *locase(); +void pvname_svc(); void pvname(); void ptype(); int isvectordef(); @@ -88,7 +173,7 @@ void expected2(); void expected3(); void tabify(); void record_open(); - +bas_type *find_type(); /* * rpc_cout routines */ @@ -99,6 +184,8 @@ void emit(); * rpc_hout routines */ void print_datadef(); +void print_funcdef(); +void print_xdr_func_def(); /* * rpc_svcout routines @@ -106,8 +193,17 @@ void print_datadef(); void write_most(); void write_register(); void write_rest(); - +void write_programs(); +void write_svc_aux(); +void write_inetd_register(); +void write_netid_register(); +void write_nettype_register(); /* * rpc_clntout routines */ void write_stubs(); + +/* + * rpc_tblout routines + */ +void write_tables(); diff --git a/usr.bin/rpcgen/rpcgen.1 b/usr.bin/rpcgen/rpcgen.1 index 5fd9274..cb81c98 100644 --- a/usr.bin/rpcgen/rpcgen.1 +++ b/usr.bin/rpcgen/rpcgen.1 @@ -1,156 +1,554 @@ -.\" from: @(#)rpcgen.1 2.2 88/08/02 4.0 RPCSRC -.\" $Id: rpcgen.1,v 1.1 1993/09/13 23:20:21 jtc Exp $ -.\" -.Dd January 18, 1988 -.Dt RPCGEN 1 -.Os -.Sh NAME -.Nm rpcgen -.Nd RPC protocol compiler -.Sh SYNOPSIS -.Nm rpcgen -.Ar infile -.Nm rpcgen -.Fl c Li | -.Fl h Li | -.Fl l Li | -.Fl m -.Op Fl o Ar outfile -.Op Ar infile -.Nm rpcgen -.Fl s Ar transport -.Op Fl o Ar outfile -.Op Ar infile -.Sh DESCRIPTION -.Nm rpcgen -is a tool that generates C code to implement an -.Tn RPC -protocol. The input to -.Nm rpcgen +.\" @(#)rpcgen.1 1.35 93/06/02 SMI +'\"macro stdmacro +.\" Copyright 1985-1993 Sun Microsystems, Inc. +.nr X +.TH rpcgen 1 "28 Mar 1993" +.SH NAME +rpcgen \- an RPC protocol compiler +.SH SYNOPSIS +.BI rpcgen " infile" +.LP +.B rpcgen +[ +.B \-a +] [ +.B \-b +] [ +.B \-C +] [ +.BI \-D name +[ = +.I value +] ] +.if n .ti +5n +[ +.BI \-i " size" +] +[ +.B \-I +[ +.BI \-K " seconds" +] ] +[ +.B \-L +] [ +.B \-M +] +.if n .ti +5n +.if t .ti +5n +[ +.B \-N +] +[ +.B \-T +] [ +.BI \-Y " pathname" +] +.I infile +.LP +.B rpcgen +[ +.B \-c +| +.B \-h +| +.B \-l +| +.B \-m +| +.B \-t +| +.B \-Sc +| +.B \-Ss +| +.B \-Sm +] +.if n .ti +5n +[ +.BI \-o " outfile" +] [ +.I infile +] +.LP +.B rpcgen +[ +.BI \-s " nettype" +] [ +.BI \-o " outfile" +] [ +.I infile +] +.LP +.B rpcgen +[ +.BI \-n " netid" +] [ +.BI \-o " outfile" +] [ +.I infile +] +.\" .SH AVAILABILITY +.\" .LP +.\" SUNWcsu +.SH DESCRIPTION +.IX "rpcgen" "" "\fLrpcgen\fP \(em RPC protocol compiler" +.IX "RPC" "protocol compiler" "" "protocol compiler \(em \fLrpcgen\fP" +.IX "RPC Language" "RPC protocol compiler" "" "RPC protocol compiler \(em \fLrpcgen\fP" +.IX "compilers" "RPC protocol compiler" "" "RPC protocol compiler \(em \fLrpcgen\fP" +.IX "programming tools" "RPC protocol compiler" "" "RPC protocol compiler \(em \fLrpcgen\fP" +.LP +\f3rpcgen\f1 +is a tool that generates C code to implement an RPC protocol. +The input to +\f3rpcgen\f1 is a language similar to C known as -.Tn RPC -Language (Remote Procedure Call Language). Information about the -syntax of -.Tn RPC -Language is available in the -.Rs -.%T "rpcgen Programming Guide" -.Re -.Pp -.Nm rpcgen -is normally used as in the first synopsis where it takes an input file -and generates four output files. If the -.Ar infile +RPC Language (Remote Procedure Call Language). +.LP +\f3rpcgen\f1 +is normally used as in the first synopsis where +it takes an input file and generates three output files. +If the +\f2infile\f1 is named -.Pa proto.x , +\f3proto.x\f1, then -.Nm rpcgen -will generate a header file in -.Pa proto.h , -.Tn XDR -routines in -.Pa proto_xdr.c , +\f3rpcgen\f1 +generates a header in +\f3proto.h\f1, +XDR routines in +\f3proto_xdr.c\f1, server-side stubs in -.Pa proto_svc.c , +\f3proto_svc.c\f1, and client-side stubs in -.Pa proto_clnt.c . -.Pp -The other synopses shown above are used when one does not want to -generate all the output files, but only a particular one. -.\" Their usage is described in the -.\" .Sx USAGE -.\" section below. -.Pp -The C-preprocessor, -.Xr cpp 1 , -is run on all input files before they are actually -interpreted by -.Nm rpcgen , -so all the -.Xr cpp -directives are legal within an -.Nm rpcgen -input file. For each type of output file, -.Nm rpcgen -defines a special -.Xr cpp -symbol for use by the -.Nm rpcgen +\f3proto_clnt.c\f1. +With the +\f3\-T\f1 +option, +it also generates the RPC dispatch table in +\f3proto_tbl.i\f1. +.LP +.B rpcgen +can also generate sample client and server files +that can be customized to suit a particular application. The +\f3\-Sc\f1, +\f3\-Ss\f1 +and +\f3\-Sm\f1 +options generate sample client, server and makefile, respectively. +The +\f3\-a\f1 +option generates all files, including sample files. If the infile +is \f3proto.x\f1, then the client side sample file is written to +\f3proto_client.c\f1, the server side sample file to \f3proto_server.c\f1 +and the sample makefile to \f3makefile.proto\f1. +.LP +The server created can be started both by the port monitors +(for example, \f3inetd\f1 or \f3listen\f1) +or by itself. +When it is started by a port monitor, +it creates servers only for the transport for which +the file descriptor \f30\fP was passed. +The name of the transport must be specified +by setting up the environment variable +\f3PM_TRANSPORT\f1. +When the server generated by +\f3rpcgen\f1 +is executed, +it creates server handles for all the transports +specified in +\f3NETPATH\f1 +environment variable, +or if it is unset, +it creates server handles for all the visible transports from +\f3/etc/netconfig\f1 +file. +Note: +the transports are chosen at run time and not at compile time. +When the server is self-started, +it backgrounds itself by default. +A special define symbol +\f3RPC_SVC_FG\f1 +can be used to run the server process in foreground. +.LP +The second synopsis provides special features which allow +for the creation of more sophisticated RPC servers. +These features include support for user provided +\f3#defines\f1 +and RPC dispatch tables. +The entries in the RPC dispatch table contain: +.RS +.PD 0 +.TP 3 +\(bu +pointers to the service routine corresponding to that procedure, +.TP +\(bu +a pointer to the input and output arguments +.TP +\(bu +the size of these routines +.PD +.RE +A server can use the dispatch table to check authorization +and then to execute the service routine; +a client library may use it to deal with the details of storage +management and XDR data conversion. +.LP +The other three synopses shown above are used when +one does not want to generate all the output files, +but only a particular one. +See the +.SM EXAMPLES +section below for examples of +.B rpcgen +usage. +When +\f3rpcgen\f1 +is executed with the +\f3\-s\f1 +option, +it creates servers for that particular class of transports. +When +executed with the +\f3\-n\f1 +option, +it creates a server for the transport specified by +\f2netid\f1. +If +\f2infile\f1 +is not specified, +\f3rpcgen\f1 +accepts the standard input. +.LP +The C preprocessor, +\f3cc \-E\f1 +is run on the input file before it is actually interpreted by +\f3rpcgen\f1. +For each type of output file, +\f3rpcgen\f1 +defines a special preprocessor symbol for use by the +\f3rpcgen\f1 programmer: -.Pp -.Bl -tag -width RPC_CLNT -compact -.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 +.LP +.PD 0 +.RS +.TP 12 +\f3RPC_HDR\f1 +defined when compiling into headers +.TP +\f3RPC_XDR\f1 +defined when compiling into XDR routines +.TP +\f3RPC_SVC\f1 defined when compiling into server-side stubs -.It Dv RPC_CLNT +.TP +\f3RPC_CLNT\f1 defined when compiling into client-side stubs -.El -.Pp -In addition, -.Nm rpcgen -does a little preprocessing of its own. Any line beginning with -.Sq % -is passed directly into the output file, uninterpreted by -.Nm rpcgen . -.Pp -You can customize some of your -.Tn XDR -routines by leaving those data types undefined. For every data type -that is undefined, -.Nm rpcgen -will assume that there exists a routine with the name -.Tn xdr_ -prepended to the name of the undefined type. -.Sh OPTIONS -.Bl -tag -width indent -.It Fl c +.TP +\f3RPC_TBL\f1 +defined when compiling into RPC dispatch tables +.RE +.PD +.LP +Any line beginning with +``\f3%\f1'' +is passed directly into the output file, +uninterpreted by +\f3rpcgen\f1. +To specify the path name of the C preprocessor use \f3\-Y\f1 flag. +.LP +For every data type referred to in +\f2infile\f1, +\f3rpcgen\f1 +assumes that there exists a +routine with the string +\f3xdr_\f1 +prepended to the name of the data type. +If this routine does not exist in the RPC/XDR +library, it must be provided. +Providing an undefined data type +allows customization of XDR routines. +.br +.ne 10 +.SH OPTIONS +.TP 15 +\f3\-a\f1 +Generate all files, including sample files. +.TP +\f3\-b\f1 +Backward compatibility mode. +Generate transport specific RPC code for older versions +of the operating system. +.IP +Note: in FreeBSD, this compatibility flag is turned on by +default since FreeBSD supports only the older ONC RPC library. +.TP +\f3\-c\f1 +Compile into XDR routines. +.TP +\f3\-C\f1 +Generate header and stub files which can be used with +.SM ANSI C +compilers. Headers generated with this flag can also be +used with C++ programs. +.TP +\f3\-D\f2name\f3[=\f2value\f3]\f1 +Define a symbol +\f2name\f1. +Equivalent to the +\f3#define\f1 +directive in the source. +If no +\f2value\f1 +is given, +\f2value\f1 +is defined as \f31\f1. +This option may be specified more than once. +.TP +\f3\-h\f1 Compile into -.Tn XDR -routines. -.It Fl h -Compile into C data-definitions (a header file). -.It Fl l +\f3C\f1 +data-definitions (a header). +\f3\-T\f1 +option can be used in conjunction to produce a +header which supports RPC dispatch tables. +.TP +\f3\-i \f2size\f1 +Size at which to start generating inline code. +This option is useful for optimization. The default size is 5. +.IP +Note: in order to provide backwards compatibility with the older +.B rpcgen +on the FreeBSD platform, the default is actually 0 (which means +that inline code generation is disabled by default). You must specify +a non-zero value explicitly to override this default. +.TP +\f3\-I\f1 +Compile support for +.BR inetd (1M) +in the server side stubs. +Such servers can be self-started or can be started by \f3inetd\f1. +When the server is self-started, it backgrounds itself by default. +A special define symbol \f3RPC_SVC_FG\f1 can be used to run the +server process in foreground, or the user may simply compile without +the \f3\-I\f1 option. +.br +.ne 5 +.IP +If there are no pending client requests, the +\f3inetd\f1 servers exit after 120 seconds (default). +The default can be changed with the +.B \-K +option. +All the error messages for \f3inetd\f1 servers +are always logged with +.BR syslog (3). +.\" .IP +.\" Note: +.\" this option is supported for backward compatibility only. +.\" By default, +.\" .B rpcgen +.\" generates servers that can be invoked through portmonitors. +.TP +.BI \-K " seconds" +By default, services created using \f3rpcgen\fP and invoked through +port monitors wait \f3120\fP seconds +after servicing a request before exiting. +That interval can be changed using the \f3\-K\fP flag. +To create a server that exits immediately upon servicing a request, +use +.BR "\-K\ 0". +To create a server that never exits, the appropriate argument is +\f3\-K \-1\fP. +.IP +When monitoring for a server, +some portmonitors, like +.BR listen (1M), +.I 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, \f3rpcgen\fP should be used with \f3\-K 0\fP. +.TP +\f3\-l\f1 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 -people who need to write their own -.Fn main -routine to do initialization. -.It Fl o Ar outfile -Specify the name of the output file. If none is specified, standard -output is used ( -.Fl c , -.Fl h , -.Fl l +.TP +.B \-L +When the servers are started in foreground, use +.BR syslog (3) +to log the server errors instead of printing them on the standard +error. +.TP +\f3\-m\f1 +Compile into server-side stubs, +but do not generate a \(lqmain\(rq routine. +This option is useful for doing callback-routines +and for users who need to write their own +\(lqmain\(rq routine to do initialization. +.TP +\f3\-M\f1 +Generate multithread-safe stubs for passing arguments and results between +rpcgen generated code and user written code. This option is useful +for users who want to use threads in their code. However, the +.BR rpc_svc_calls (3N) +functions are not yet MT-safe, which means that rpcgen generated server-side +code will not be MT-safe. +.TP +.B \-N +This option allows procedures to have multiple arguments. +It also uses the style of parameter passing that closely resembles C. +So, when passing an argument to a remote procedure, you do not have to +pass a pointer to the argument, but can pass the argument itself. +This behavior is different from the old style of +.B rpcgen +generated code. +To maintain backward compatibility, +this option is not the default. +.TP +\f3\-n \f2netid\f1 +Compile into server-side stubs for the transport +specified by +\f2netid\f1. +There should be an entry for +\f2netid\f1 +in the +netconfig database. +This option may be specified more than once, +so as to compile a server that serves multiple transports. +.TP +\f3\-o \f2outfile\f1 +Specify the name of the output file. +If none is specified, +standard output is used +(\f3\-c\f1, +\f3\-h\f1, +\f3\-l\f1, +\f3\-m\f1, +\f3\-n\f1, +\f3\-s\f1, +\f3\-Sc\f1, +\f3\-Sm\f1, +\f3\-Ss\f1, and -.Fl s +\f3\-t\f1 modes only). -.It Fl s Ar transport -Compile into server-side stubs, using the the given transport. The -supported transports are -.Tn udp +.TP +\f3\-s \f2nettype\f1 +Compile into server-side stubs for all the +transports belonging to the class +\f2nettype\f1. +The supported classes are +\f3netpath\f1, +\f3visible\f1, +\f3circuit_n\f1, +\f3circuit_v\f1, +\f3datagram_n\f1, +\f3datagram_v\f1, +\f3tcp\f1, +and +\f3udp\f1 +(see +.BR rpc (3N) +for the meanings associated with these classes). +This option may be specified more than once. +Note: +the transports are chosen at run time and not at compile time. +.TP +\f3\-Sc\f1 +Generate sample client code that uses remote procedure calls. +.br +.ne 5 +.TP +\f3\-Sm\f1 +Generate a sample Makefile which can be used for compiling the +application. +.TP +\f3\-Ss\f1 +Generate sample server code that uses remote procedure calls. +.TP +\f3\-t\f1 +Compile into RPC dispatch table. +.TP +\f3\-T\f1 +Generate the code to support RPC dispatch tables. +.IP +The options +\f3\-c\f1, +\f3\-h\f1, +\f3\-l\f1, +\f3\-m\f1, +\f3\-s\f1, +\f3\-Sc\f1, +\f3\-Sm\f1, +\f3\-Ss\f1, +and +\f3\-t\f1 +are used exclusively to generate a particular type of file, +while the options +\f3\-D\f1 +and +\f3\-T\f1 +are global and can be used with the other options. +.TP +\f3\-Y\f2 pathname\f1 +Give the name of the directory where +.B rpcgen +will start looking for the C-preprocessor. +.br +.ne 5 +.SH EXAMPLES +The following example: +.LP +.RS +.B example% rpcgen \-T prot.x +.RE +.LP +generates all the five files: +.BR prot.h , +.BR prot_clnt.c , +.BR prot_svc.c , +.B prot_xdr.c and -.Tn tcp . -This option may be invoked more than once so as to compile a server -that serves multiple transports. -.El -.Sh SEE ALSO -.Xr cpp 1 -.Rs -.%T "rpcgen Programming Guide" -.Re -.Sh BUGS -Nesting is not supported. As a work-around, structures can be -declared at 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. +.BR prot_tbl.i . +.LP +The following example sends the C data-definitions (header) +to the standard output. +.LP +.RS +.B example% rpcgen \-h prot.x +.RE +.LP +To send the test version of the +.BR -DTEST , +server side stubs for +all the transport belonging to the class +.B datagram_n +to standard output, use: +.LP +.RS +.B example% rpcgen \-s datagram_n \-DTEST prot.x +.RE +.LP +To create the server side stubs for the transport indicated +by +\f2netid\f1 +\f3tcp\f1, +use: +.LP +.RS +.B example% rpcgen \-n tcp \-o prot_svc.c prot.x +.RE +.SH "SEE ALSO" +.BR cc (1B), +.BR inetd (1M), +.BR listen (1M), +.BR syslog (3), +.BR rpc (3N), +.\" .BR rpc_svc_calls (3N) +.LP +The +.B rpcgen +chapter in the +.TZ NETP +manual. |