diff options
Diffstat (limited to '')
-rw-r--r-- | tools/rpcgen/Makefile.am | 13 | ||||
-rw-r--r-- | tools/rpcgen/Makefile.in | 850 | ||||
-rw-r--r-- | tools/rpcgen/README | 8 | ||||
-rw-r--r-- | tools/rpcgen/proto.h | 65 | ||||
-rw-r--r-- | tools/rpcgen/rpc_clntout.c | 333 | ||||
-rw-r--r-- | tools/rpcgen/rpc_cout.c | 813 | ||||
-rw-r--r-- | tools/rpcgen/rpc_hout.c | 607 | ||||
-rw-r--r-- | tools/rpcgen/rpc_main.c | 1459 | ||||
-rw-r--r-- | tools/rpcgen/rpc_output.h | 16 | ||||
-rw-r--r-- | tools/rpcgen/rpc_parse.c | 686 | ||||
-rw-r--r-- | tools/rpcgen/rpc_parse.h | 165 | ||||
-rw-r--r-- | tools/rpcgen/rpc_sample.c | 336 | ||||
-rw-r--r-- | tools/rpcgen/rpc_scan.c | 548 | ||||
-rw-r--r-- | tools/rpcgen/rpc_scan.h | 104 | ||||
-rw-r--r-- | tools/rpcgen/rpc_svcout.c | 1093 | ||||
-rw-r--r-- | tools/rpcgen/rpc_tblout.c | 178 | ||||
-rw-r--r-- | tools/rpcgen/rpc_util.c | 525 | ||||
-rw-r--r-- | tools/rpcgen/rpc_util.h | 154 | ||||
-rw-r--r-- | tools/rpcgen/rpcgen.1 | 442 |
19 files changed, 8395 insertions, 0 deletions
diff --git a/tools/rpcgen/Makefile.am b/tools/rpcgen/Makefile.am new file mode 100644 index 0000000..457cd50 --- /dev/null +++ b/tools/rpcgen/Makefile.am @@ -0,0 +1,13 @@ +CLEANFILES = *~ + +bin_PROGRAMS = rpcgen +man_MANS = rpcgen.1 + +EXTRA_DIST=${MANS} + +noinst_HEADERS = proto.h rpc_parse.h rpc_scan.h rpc_util.h + +rpcgen_SOURCES = rpc_clntout.c rpc_cout.c rpc_hout.c rpc_main.c \ + rpc_parse.c rpc_sample.c rpc_scan.c rpc_svcout.c rpc_tblout.c \ + rpc_util.c +rpcgen_LDADD = $(LIBINTL) diff --git a/tools/rpcgen/Makefile.in b/tools/rpcgen/Makefile.in new file mode 100644 index 0000000..85bd78a --- /dev/null +++ b/tools/rpcgen/Makefile.in @@ -0,0 +1,850 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = rpcgen$(EXEEXT) +subdir = tools/rpcgen +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/aclocal/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/aclocal/bsdsignals.m4 \ + $(top_srcdir)/aclocal/getrandom.m4 \ + $(top_srcdir)/aclocal/ipv6.m4 \ + $(top_srcdir)/aclocal/kerberos5.m4 \ + $(top_srcdir)/aclocal/keyutils.m4 \ + $(top_srcdir)/aclocal/libblkid.m4 \ + $(top_srcdir)/aclocal/libcap.m4 \ + $(top_srcdir)/aclocal/libevent.m4 \ + $(top_srcdir)/aclocal/libpthread.m4 \ + $(top_srcdir)/aclocal/libsqlite3.m4 \ + $(top_srcdir)/aclocal/libtirpc.m4 \ + $(top_srcdir)/aclocal/libxml2.m4 \ + $(top_srcdir)/aclocal/nfs-utils.m4 \ + $(top_srcdir)/aclocal/rpcsec_vers.m4 \ + $(top_srcdir)/aclocal/tcp-wrappers.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/support/include/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" +PROGRAMS = $(bin_PROGRAMS) +am_rpcgen_OBJECTS = rpc_clntout.$(OBJEXT) rpc_cout.$(OBJEXT) \ + rpc_hout.$(OBJEXT) rpc_main.$(OBJEXT) rpc_parse.$(OBJEXT) \ + rpc_sample.$(OBJEXT) rpc_scan.$(OBJEXT) rpc_svcout.$(OBJEXT) \ + rpc_tblout.$(OBJEXT) rpc_util.$(OBJEXT) +rpcgen_OBJECTS = $(am_rpcgen_OBJECTS) +rpcgen_DEPENDENCIES = +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/support/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/rpc_clntout.Po \ + ./$(DEPDIR)/rpc_cout.Po ./$(DEPDIR)/rpc_hout.Po \ + ./$(DEPDIR)/rpc_main.Po ./$(DEPDIR)/rpc_parse.Po \ + ./$(DEPDIR)/rpc_sample.Po ./$(DEPDIR)/rpc_scan.Po \ + ./$(DEPDIR)/rpc_svcout.Po ./$(DEPDIR)/rpc_tblout.Po \ + ./$(DEPDIR)/rpc_util.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(rpcgen_SOURCES) +DIST_SOURCES = $(rpcgen_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man_MANS) +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_CFLAGS = @AM_CFLAGS@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CXXFLAGS_FOR_BUILD = @CXXFLAGS_FOR_BUILD@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +GSSD = @GSSD@ +GSSGLUE_CFLAGS = @GSSGLUE_CFLAGS@ +GSSGLUE_LIBS = @GSSGLUE_LIBS@ +GSSKRB_CFLAGS = @GSSKRB_CFLAGS@ +GSSKRB_LIBS = @GSSKRB_LIBS@ +HAVE_GETRANDOM = @HAVE_GETRANDOM@ +HAVE_LIBWRAP = @HAVE_LIBWRAP@ +HAVE_TCP_WRAPPER = @HAVE_TCP_WRAPPER@ +IDMAPD = @IDMAPD@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +K5VERS = @K5VERS@ +KRBCFLAGS = @KRBCFLAGS@ +KRBDIR = @KRBDIR@ +KRBLDFLAGS = @KRBLDFLAGS@ +KRBLIBS = @KRBLIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBBLKID = @LIBBLKID@ +LIBBSD = @LIBBSD@ +LIBCAP = @LIBCAP@ +LIBCRYPT = @LIBCRYPT@ +LIBEVENT = @LIBEVENT@ +LIBKEYUTILS = @LIBKEYUTILS@ +LIBMOUNT = @LIBMOUNT@ +LIBMOUNT_CFLAGS = @LIBMOUNT_CFLAGS@ +LIBMOUNT_LIBS = @LIBMOUNT_LIBS@ +LIBNSL = @LIBNSL@ +LIBOBJS = @LIBOBJS@ +LIBPTHREAD = @LIBPTHREAD@ +LIBS = @LIBS@ +LIBSOCKET = @LIBSOCKET@ +LIBSQLITE = @LIBSQLITE@ +LIBTIRPC = @LIBTIRPC@ +LIBTOOL = @LIBTOOL@ +LIBWRAP = @LIBWRAP@ +LIBXML2 = @LIBXML2@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_PLUGINS = @PATH_PLUGINS@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +RELEASE = @RELEASE@ +RPCGEN_PATH = @RPCGEN_PATH@ +RPCSECGSS_CFLAGS = @RPCSECGSS_CFLAGS@ +RPCSECGSS_LIBS = @RPCSECGSS_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SVCGSSD = @SVCGSSD@ +TIRPC_CFLAGS = @TIRPC_CFLAGS@ +TIRPC_LIBS = @TIRPC_LIBS@ +VERSION = @VERSION@ +XML2_CFLAGS = @XML2_CFLAGS@ +XML2_LIBS = @XML2_LIBS@ +_rpc_pipefsmount = @_rpc_pipefsmount@ +_statedir = @_statedir@ +_sysconfdir = @_sysconfdir@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +enable_gss = @enable_gss@ +enable_ipv6 = @enable_ipv6@ +enable_mountconfig = @enable_mountconfig@ +enable_nfsv4 = @enable_nfsv4@ +enable_nfsv41 = @enable_nfsv41@ +enable_svcgss = @enable_svcgss@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +kprefix = @kprefix@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +mountfile = @mountfile@ +nfsconfig = @nfsconfig@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +rpc_pipefsmount = @rpc_pipefsmount@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +startstatd = @startstatd@ +statdpath = @statdpath@ +statduser = @statduser@ +statedir = @statedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +unitdir = @unitdir@ +CLEANFILES = *~ +man_MANS = rpcgen.1 +EXTRA_DIST = ${MANS} +noinst_HEADERS = proto.h rpc_parse.h rpc_scan.h rpc_util.h +rpcgen_SOURCES = rpc_clntout.c rpc_cout.c rpc_hout.c rpc_main.c \ + rpc_parse.c rpc_sample.c rpc_scan.c rpc_svcout.c rpc_tblout.c \ + rpc_util.c + +rpcgen_LDADD = $(LIBINTL) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tools/rpcgen/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tools/rpcgen/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +rpcgen$(EXEEXT): $(rpcgen_OBJECTS) $(rpcgen_DEPENDENCIES) $(EXTRA_rpcgen_DEPENDENCIES) + @rm -f rpcgen$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rpcgen_OBJECTS) $(rpcgen_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_clntout.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_cout.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_hout.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_parse.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_sample.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_scan.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_svcout.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_tblout.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_util.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/rpc_clntout.Po + -rm -f ./$(DEPDIR)/rpc_cout.Po + -rm -f ./$(DEPDIR)/rpc_hout.Po + -rm -f ./$(DEPDIR)/rpc_main.Po + -rm -f ./$(DEPDIR)/rpc_parse.Po + -rm -f ./$(DEPDIR)/rpc_sample.Po + -rm -f ./$(DEPDIR)/rpc_scan.Po + -rm -f ./$(DEPDIR)/rpc_svcout.Po + -rm -f ./$(DEPDIR)/rpc_tblout.Po + -rm -f ./$(DEPDIR)/rpc_util.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/rpc_clntout.Po + -rm -f ./$(DEPDIR)/rpc_cout.Po + -rm -f ./$(DEPDIR)/rpc_hout.Po + -rm -f ./$(DEPDIR)/rpc_main.Po + -rm -f ./$(DEPDIR)/rpc_parse.Po + -rm -f ./$(DEPDIR)/rpc_sample.Po + -rm -f ./$(DEPDIR)/rpc_scan.Po + -rm -f ./$(DEPDIR)/rpc_svcout.Po + -rm -f ./$(DEPDIR)/rpc_tblout.Po + -rm -f ./$(DEPDIR)/rpc_util.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-man + +uninstall-man: uninstall-man1 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-man1 \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-man uninstall-man1 + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tools/rpcgen/README b/tools/rpcgen/README new file mode 100644 index 0000000..2f6bbf3 --- /dev/null +++ b/tools/rpcgen/README @@ -0,0 +1,8 @@ + + This directory contains the source for rpcgen.new from Sun TIRPC + source distribution. I cleaned it up a little so that it will + compile with gcc (without using -traditional), and modified the + output to avoid those silly warnings you usually get when compiling + an rpcgen-generated C file. + + Olaf Kirch <okir@monad.swb.de> 8 Oct 1996 diff --git a/tools/rpcgen/proto.h b/tools/rpcgen/proto.h new file mode 100644 index 0000000..ea28565 --- /dev/null +++ b/tools/rpcgen/proto.h @@ -0,0 +1,65 @@ +/****** rpc_clntout.c ******/ + +void write_stubs(void); +void printarglist(proc_list *proc, const char *result, + const char *addargname, const char *addargtype); + +/****** rpc_cout.c ******/ + +void emit (definition *def); + +/****** rpc_hout.c ******/ + +void print_datadef(definition *def); +void print_funcdef(definition *def); +void pxdrfuncdecl(const char *name, int pointerp); +void pprocdef(proc_list *proc, version_list *vp, + const char *addargtype, int server_p, int mode); +void pdeclaration(const char *name, declaration *dec, int tab, + const char *separator); +void print_xdr_func_def (char* name, int pointerp, int i); + +/****** rpc_main.c ******/ + /* nil */ + +/****** rpc_parse.c ******/ +definition *get_definition(void); + +/****** rpc_sample.c ******/ +void write_sample_svc(definition *def); +int write_sample_clnt(definition *def); +void add_sample_msg(void); +void write_sample_clnt_main(void); + +/****** rpc_scan.c ******/ + /* see rpc_scan.h */ + +/****** rpc_svcout.c ******/ +int nullproc(const proc_list *proc); +void write_svc_aux(int nomain); +void write_msg_out(void); + +/****** rpc_tblout.c ******/ +void write_tables(void); + +/****** rpc_util.c ******/ +void reinitialize(void); +int streq(const char *a, const char *b); +void error(const char *msg) __attribute__ ((noreturn)); +void crash(void) __attribute__ ((noreturn)); +void tabify(FILE *f, int tab); +char *make_argname(const char *pname, const char *vname); +void add_type(int len, const char *type); + +/* This header is the last one included in all rpc_*.c files, + so we define stuff for cross-rpcgen here to avoid conflicts with + $build's C library and $host's glibc. */ + +#ifdef IS_IN_build + +/* Disable translated messages when built for $build and used in + building glibc. */ +#define _(X) (X) +#define textdomain(X) ((void) 0) + +#endif diff --git a/tools/rpcgen/rpc_clntout.c b/tools/rpcgen/rpc_clntout.c new file mode 100644 index 0000000..9b6a4aa --- /dev/null +++ b/tools/rpcgen/rpc_clntout.c @@ -0,0 +1,333 @@ +/* + * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <stdio.h> +#include <string.h> +// #include <rpc/types.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +#define DEFAULT_TIMEOUT 25 /* in seconds */ +static const char RESULT[] = "clnt_res"; + +static void write_program (definition * def); +static void printbody (proc_list * proc); +static const char *ampr (const char *type); +static void printbody (proc_list * proc); + + +void +write_stubs (void) +{ + list *l; + definition *def; + + fprintf (fout, + "\n/* Default timeout can be changed using clnt_control() */\n"); + fprintf (fout, "static struct timeval TIMEOUT = { %d, 0 };\n", + DEFAULT_TIMEOUT); + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) + { + write_program (def); + } + } +} + +static void +write_program (definition * def) +{ + version_list *vp; + proc_list *proc; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + fprintf (fout, "\n"); + if (mtflag == 0) + { + ptype (proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*\n"); + pvname (proc->proc_name, vp->vers_num); + printarglist (proc, RESULT, "clnt", "CLIENT *"); + } + else + { + fprintf (fout, "enum clnt_stat \n"); + pvname (proc->proc_name, vp->vers_num); + printarglist (proc, RESULT, "clnt", "CLIENT *"); + } + fprintf (fout, "{\n"); + printbody (proc); + fprintf (fout, "}\n"); + } + } +} + +/* Writes out declarations of procedure's argument list. + In either ANSI C style, in one of old rpcgen style (pass by reference), + or new rpcgen style (multiple arguments, pass by value); + */ + +/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */ + +void +printarglist (proc_list * proc, const char *result, + const char *addargname, const char *addargtype) +{ + + decl_list *l; + + if (!newstyle) + { /* old style: always pass argument by reference */ + if (Cflag) + { /* C++ style heading */ + fprintf (fout, "("); + ptype (proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 1); + + if (mtflag) + {/* Generate result field */ + fprintf (fout, "*argp, "); + ptype(proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*%s, %s%s)\n", result, addargtype, addargname); + } + else + fprintf (fout, "*argp, %s%s)\n", addargtype, addargname); + } + else + { + if (!mtflag) + fprintf (fout, "(argp, %s)\n", addargname); + else + fprintf (fout, "(argp, %s, %s)\n", result, addargname); + fprintf (fout, "\t"); + ptype (proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 1); + fprintf (fout, "*argp;\n"); + if (mtflag) + { + fprintf (fout, "\t"); + ptype (proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*%s;\n", result); + } + } + } + else if (streq (proc->args.decls->decl.type, "void")) + { + /* newstyle, 0 argument */ + if (mtflag) + { + fprintf (fout, "("); + if (Cflag) + { + ptype(proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*%s, %s%s)\n", result, addargtype, addargname); + } + else + fprintf (fout, "(%s)\n", addargname); + } + else if (Cflag) + fprintf (fout, "(%s%s)\n", addargtype, addargname); + else + fprintf (fout, "(%s)\n", addargname); + } + else + { + /* new style, 1 or multiple arguments */ + if (!Cflag) + { + fprintf (fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) + fprintf (fout, "%s, ", l->decl.name); + if (mtflag) + fprintf (fout, "%s, ", result); + fprintf (fout, "%s)\n", addargname); + for (l = proc->args.decls; l != NULL; l = l->next) + { + pdeclaration (proc->args.argname, &l->decl, 1, ";\n"); + } + if (mtflag) + { + fprintf (fout, "\t"); + ptype (proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*%s;\n", result); + } + } + else + { /* C++ style header */ + fprintf (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); + fprintf (fout, "*%s, ", result); + } + fprintf (fout, " %s%s)\n", addargtype, addargname); + } + } + + if (!Cflag) + fprintf (fout, "\t%s%s;\n", addargtype, addargname); +} + + +static +const char * +ampr (const char *type) +{ + if (isvectordef (type, REL_ALIAS)) + { + return ""; + } + else + { + return "&"; + } +} + +static void +printbody (proc_list * proc) +{ + decl_list *l; + int 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) + { + fprintf (fout, "\t%s", proc->args.argname); + fprintf (fout, " arg;\n"); + } + if (!mtflag) + { + fprintf (fout, "\tstatic "); + if (streq (proc->res_type, "void")) + { + fprintf (fout, "char "); + } + else + { + ptype (proc->res_prefix, proc->res_type, 0); + } + fprintf (fout, "%s;\n", RESULT); + fprintf (fout, "\n"); + fprintf (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) + fprintf (fout, "\t return "); + else + fprintf (fout, "\t if "); + fprintf (fout, + "(clnt_call (clnt, %s, (xdrproc_t) xdr_void, ", proc->proc_name); + + fprintf (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) + fprintf (fout, "\n\t\tTIMEOUT));\n\n"); + else + fprintf (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) + { + fprintf (fout, "\targ.%s = %s;\n", + l->decl.name, l->decl.name); + } + if (mtflag) + fprintf (fout, "\treturn "); + else + fprintf (fout, "\tif "); + + fprintf (fout, + "(clnt_call (clnt, %s, (xdrproc_t) xdr_%s", proc->proc_name, + proc->args.argname); + fprintf (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) + fprintf (fout, "\n\t\tTIMEOUT));\n"); + else + fprintf (fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n"); + } + else + { /* single argument, new or old style */ + if (!mtflag) + fprintf (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 + fprintf(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) + { + fprintf (fout, "\t\treturn (NULL);\n"); + fprintf (fout, "\t}\n"); + if (streq (proc->res_type, "void")) + { + fprintf (fout, "\treturn ((void *)%s%s);\n", + ampr (proc->res_type), RESULT); + } + else + { + fprintf (fout, "\treturn (%s%s);\n", ampr (proc->res_type), RESULT); + } + } +} diff --git a/tools/rpcgen/rpc_cout.c b/tools/rpcgen/rpc_cout.c new file mode 100644 index 0000000..4627110 --- /dev/null +++ b/tools/rpcgen/rpc_cout.c @@ -0,0 +1,813 @@ +/* + * From: @(#)rpc_cout.c 1.13 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_cout.c, XDR routine outputter for the RPC protocol compiler + */ +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +static void emit_enum (definition * def); +static void emit_program (const definition * def); +static void emit_union (const definition * def); +static void emit_struct (definition * def); +static void emit_typedef (const definition * def); +static void emit_inline (int indent, declaration * decl, int flag); +static void emit_single_in_line (int indent, declaration *decl, int flag, + relation rel); +static int findtype (const definition * def, const char *type); +static int undefined (const char *type); +static void print_generic_header (const char *procname, int pointerp); +static void print_ifopen (int indent, const char *name); +static void print_ifarg (const char *arg); +static void print_ifsizeof (int indent, const char *prefix, const char *type); +static void print_ifclose (int indent); +static void print_ifstat (int indent, const char *prefix, const char *type, + relation rel, const char *amax, + const char *objname, const char *name); +static void print_stat (int indent, const declaration * dec); +static void print_header (const definition * def); +static void print_trailer (void); +static char *upcase (const char *str); + +/* + * Emit the C-routine for the given definition + */ +void +emit (definition * def) +{ + if (def->def_kind == DEF_CONST) + { + return; + } + if (def->def_kind == DEF_PROGRAM) + { + emit_program (def); + return; + } + if (def->def_kind == DEF_TYPEDEF) + { + /* now we need to handle declarations like + struct typedef foo foo; + since we don't want this to be expanded + into 2 calls to xdr_foo */ + + if (strcmp (def->def.ty.old_type, def->def_name) == 0) + return; + }; + + print_header (def); + switch (def->def_kind) + { + case DEF_UNION: + emit_union (def); + break; + case DEF_ENUM: + emit_enum (def); + break; + case DEF_STRUCT: + emit_struct (def); + break; + case DEF_TYPEDEF: + emit_typedef (def); + break; + default: + /* can't happen */ + break; + } + print_trailer (); +} + +static int +findtype (const definition * def, const char *type) +{ + if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) + { + return 0; + } + else + { + return (streq (def->def_name, type)); + } +} + +static int +undefined (const char *type) +{ + definition *def; + def = (definition *) FINDVAL (defined, type, findtype); + return (def == NULL); +} + + +static void +print_generic_header (const char *procname, int pointerp) +{ + f_print (fout, "\n"); + f_print (fout, "bool_t\n"); + if (Cflag) + { + f_print (fout, "xdr_%s (", procname); + f_print (fout, "XDR *xdrs, "); + f_print (fout, "%s ", procname); + if (pointerp) + f_print (fout, "*"); + f_print (fout, "objp)\n{\n"); + } + else + { + f_print (fout, "xdr_%s (xdrs, objp)\n", procname); + f_print (fout, "\tXDR *xdrs;\n"); + f_print (fout, "\t%s ", procname); + if (pointerp) + f_print (fout, "*"); + f_print (fout, "objp;\n{\n"); + } +} + +static void +print_header (const definition * def) +{ + print_generic_header (def->def_name, + def->def_kind != DEF_TYPEDEF || + !isvectordef (def->def.ty.old_type, + def->def.ty.rel)); + + /* Now add Inline support */ + + if (inlineflag == 0) + return; + /*May cause lint to complain. but ... */ + f_print (fout, "\tregister int32_t *buf;\n\n"); +} + +static void +print_prog_header (const proc_list * plist) +{ + print_generic_header (plist->args.argname, 1); +} + +static void +print_trailer (void) +{ + f_print (fout, "\treturn TRUE;\n"); + f_print (fout, "}\n"); +} + + +static void +print_ifopen (int indent, const char *name) +{ + tabify (fout, indent); + f_print (fout, " if (!xdr_%s (xdrs", name); +} + +static void +print_ifarg (const char *arg) +{ + f_print (fout, ", %s", arg); +} + +static void +print_ifsizeof (int indent, const char *prefix, const char *type) +{ + if (indent) + { + fprintf (fout, ",\n"); + tabify (fout, indent); + } + else + fprintf (fout, ", "); + + if (streq (type, "bool")) + fprintf (fout, "sizeof (bool_t), (xdrproc_t) xdr_bool"); + else + { + fprintf (fout, "sizeof ("); + if (undefined (type) && prefix) + { + f_print (fout, "%s ", prefix); + } + fprintf (fout, "%s), (xdrproc_t) xdr_%s", type, type); + } +} + +static void +print_ifclose (int indent) +{ + f_print (fout, "))\n"); + tabify (fout, indent); + f_print (fout, "\t return FALSE;\n"); +} + +static void +print_ifstat (int indent, const char *prefix, const char *type, relation rel, + const char *amax, const char *objname, const char *name) +{ + const char *alt = NULL; + + switch (rel) + { + case REL_POINTER: + print_ifopen (indent, "pointer"); + print_ifarg ("(char **)"); + f_print (fout, "%s", objname); + print_ifsizeof (0, prefix, type); + break; + case REL_VECTOR: + if (streq (type, "string")) + { + alt = "string"; + } + else if (streq (type, "opaque")) + { + alt = "opaque"; + } + if (alt) + { + print_ifopen (indent, alt); + print_ifarg (objname); + } + else + { + print_ifopen (indent, "vector"); + print_ifarg ("(char *)"); + f_print (fout, "%s", objname); + } + print_ifarg (amax); + if (!alt) + { + print_ifsizeof (indent + 1, prefix, type); + } + break; + case REL_ARRAY: + if (streq (type, "string")) + { + alt = "string"; + } + else if (streq (type, "opaque")) + { + alt = "bytes"; + } + if (streq (type, "string")) + { + print_ifopen (indent, alt); + print_ifarg (objname); + } + else + { + if (alt) + { + print_ifopen (indent, alt); + } + else + { + print_ifopen (indent, "array"); + } + print_ifarg ("(char **)"); + if (*objname == '&') + { + f_print (fout, "%s.%s_val, (u_int *) %s.%s_len", + objname, name, objname, name); + } + else + { + f_print (fout, "&%s->%s_val, (u_int *) &%s->%s_len", + objname, name, objname, name); + } + } + print_ifarg (amax); + if (!alt) + { + print_ifsizeof (indent + 1, prefix, type); + } + break; + case REL_ALIAS: + print_ifopen (indent, type); + print_ifarg (objname); + break; + } + print_ifclose (indent); +} + +static void +emit_enum (definition * def) +{ + (void) def; + + print_ifopen (1, "enum"); + print_ifarg ("(enum_t *) objp"); + print_ifclose (1); +} + +static void +emit_program (const 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 (); + } +} + +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +static void +emit_union (const definition * def) +{ + declaration *dflt; + case_list *cl; + declaration *cs; + char *object; + const char *vecformat = "objp->%s_u.%s"; + const char *format = "&objp->%s_u.%s"; + + print_stat (1, &def->def.un.enum_decl); + f_print (fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name); + for (cl = def->def.un.cases; cl != NULL; cl = cl->next) + { + + f_print (fout, "\tcase %s:\n", cl->case_name); + if (cl->contflag == 1) /* a continued case statement */ + continue; + cs = &cl->case_decl; + if (!streq (cs->type, "void")) + { + object = alloc (strlen (def->def_name) + strlen (format) + + strlen (cs->name) + 1); + if (isvectordef (cs->type, cs->rel)) + { + s_print (object, vecformat, def->def_name, + cs->name); + } + else + { + s_print (object, format, def->def_name, + cs->name); + } + print_ifstat (2, cs->prefix, cs->type, cs->rel, cs->array_max, + object, cs->name); + free (object); + } + f_print (fout, "\t\tbreak;\n"); + } + dflt = def->def.un.default_decl; + if (dflt != NULL) + { + if (!streq (dflt->type, "void")) + { + f_print (fout, "\tdefault:\n"); + object = alloc (strlen (def->def_name) + strlen (format) + + strlen (dflt->name) + 1); + if (isvectordef (dflt->type, dflt->rel)) + { + s_print (object, vecformat, def->def_name, + dflt->name); + } + else + { + s_print (object, format, def->def_name, + dflt->name); + } + + print_ifstat (2, dflt->prefix, dflt->type, dflt->rel, + dflt->array_max, object, dflt->name); + free (object); + f_print (fout, "\t\tbreak;\n"); + } + else + { + f_print (fout, "\tdefault:\n"); + f_print (fout, "\t\tbreak;\n"); + } + } + else + { + f_print (fout, "\tdefault:\n"); + f_print (fout, "\t\treturn FALSE;\n"); + } + + f_print (fout, "\t}\n"); +} +#pragma GCC diagnostic warning "-Wformat-nonliteral" + +static void +inline_struct (definition *def, int flag) +{ + decl_list *dl; + int i, size; + decl_list *cur = NULL; + decl_list *psav; + bas_type *ptr; + char *sizestr; + const char *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 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 < inlineflag) + { + /* don't expand into inline code if size < inlineflag */ + 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); + fprintf (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 + 1, &cur->decl, flag); + cur = cur->next; + } + tabify (fout, indent + 1); + f_print (fout, "}\n"); + } + } + size = 0; + i = 0; + free (sizestr); + sizestr = NULL; + print_stat (indent + 1, &dl->decl); + } + } + if (i > 0) + { + if (sizestr == NULL && size < inlineflag) + { + /* don't expand into inline code if size < inlineflag */ + 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"); + } + } +} + +/* this may be const. i haven't traced this one through yet. */ + +static void +emit_struct (definition * def) +{ + decl_list *dl; + int j, size, flag; + bas_type *ptr; + int can_inline; + + + if (inlineflag == 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; + } + + 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 >= inlineflag) + { + can_inline = 1; + break; /* can be inlined */ + } + size = 0; + } + if (size > inlineflag) + 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 return TRUE;\n\t}\n\n"); + + /* now take care of XDR_FREE case */ + + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat (1, &dl->decl); +} + +static void +emit_typedef (const definition * def) +{ + const char *prefix = def->def.ty.old_prefix; + const char *type = def->def.ty.old_type; + const char *amax = def->def.ty.array_max; + relation rel = def->def.ty.rel; + + print_ifstat (1, prefix, type, rel, amax, "objp", def->def_name); +} + +static void +print_stat (int indent, const declaration * dec) +{ + const char *prefix = dec->prefix; + const char *type = dec->type; + const char *amax = dec->array_max; + relation rel = dec->rel; + char name[256]; + + if (isvectordef (type, rel)) + { + s_print (name, "objp->%s", dec->name); + } + else + { + s_print (name, "&objp->%s", dec->name); + } + print_ifstat (indent, prefix, type, rel, amax, name, dec->name); +} + + +static void +emit_inline (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"); + break; + default: + break; + /* ?... do nothing I guess */ + } +} + +static void +emit_single_in_line (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")) + { + free (upp_case); + freed = 1; + /* Casting is safe since the `freed' flag is set. */ + upp_case = (char *) "LONG"; + } + + if (!strcmp (upp_case, "U_INT")) + { + free (upp_case); + freed = 1; + /* Casting is safe since the `freed' flag is set. */ + upp_case = (char *) "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); +} + + +static char * +upcase (const char *str) +{ + char *ptr, *hptr; + ptr = malloc (strlen (str) + 1); + if (ptr == NULL) + { + f_print (stderr, "malloc failed\n"); + exit (1); + } + hptr = ptr; + while (*str != '\0') + *ptr++ = toupper (*str++); + + *ptr = '\0'; + return hptr; +} diff --git a/tools/rpcgen/rpc_hout.c b/tools/rpcgen/rpc_hout.c new file mode 100644 index 0000000..10f793d --- /dev/null +++ b/tools/rpcgen/rpc_hout.c @@ -0,0 +1,607 @@ +/* + * From: @(#)rpc_hout.c 1.12 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_hout.c, Header file outputter for the RPC protocol compiler + */ +#include <stdio.h> +#include <ctype.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +static void pconstdef (definition * def); +static void pargdef (definition * def); +static void pstructdef (definition * def); +static void puniondef (definition * def); +static void pdefine (const char *name, const char *num); +static int define_printed (proc_list * stop, version_list * start); +static void pprogramdef (definition * def); +static void parglist (proc_list * proc, const char *addargtype); +static void penumdef (definition * def); +static void ptypedef (definition * def); +static int undefined2 (const char *type, const char *stop); + +/* store away enough information to allow the XDR functions to be spat + out at the end of the file */ + +static void +storexdrfuncdecl (const char *name, int pointerp) +{ + xdrfunc * xdrptr; + + xdrptr = (xdrfunc *) malloc(sizeof (struct xdrfunc)); + + xdrptr->name = (char *)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; + } +} + +/* + * Print the C-version of an xdr definition + */ +void +print_datadef (definition *def) +{ + + if (def->def_kind == DEF_PROGRAM) /* handle data only */ + return; + + if (def->def_kind != DEF_CONST) + { + f_print (fout, "\n"); + } + switch (def->def_kind) + { + case DEF_STRUCT: + pstructdef (def); + break; + case DEF_UNION: + puniondef (def); + break; + case DEF_ENUM: + penumdef (def); + break; + case DEF_TYPEDEF: + ptypedef (def); + break; + case DEF_PROGRAM: + pprogramdef (def); + break; + case DEF_CONST: + pconstdef (def); + break; + } + if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) + { + storexdrfuncdecl(def->def_name, + def->def_kind != DEF_TYPEDEF || + !isvectordef(def->def.ty.old_type, + def->def.ty.rel)); + } +} + + +void +print_funcdef (definition *def) +{ + switch (def->def_kind) + { + case DEF_PROGRAM: + f_print (fout, "\n"); + pprogramdef (def); + break; + default: + break; + /* ?... shouldn't happen I guess */ + } +} + +void +print_xdr_func_def (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 void +pconstdef (definition *def) +{ + pdefine (def->def_name, def->def.co); +} + +/* print out the definitions for the arguments of functions in the + header file + */ +static void +pargdef (definition * def) +{ + decl_list *l; + version_list *vers; + const 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 void +pstructdef (definition *def) +{ + decl_list *l; + const char *name = def->def_name; + + f_print (fout, "struct %s {\n", name); + for (l = def->def.st.decls; l != NULL; l = l->next) + { + pdeclaration (name, &l->decl, 1, ";\n"); + } + f_print (fout, "};\n"); + f_print (fout, "typedef struct %s %s;\n", name, name); +} + +static void +puniondef (definition *def) +{ + case_list *l; + const char *name = def->def_name; + declaration *decl; + + f_print (fout, "struct %s {\n", name); + decl = &def->def.un.enum_decl; + if (streq (decl->type, "bool")) + { + f_print (fout, "\tbool_t %s;\n", decl->name); + } + else + { + f_print (fout, "\t%s %s;\n", decl->type, decl->name); + } + f_print (fout, "\tunion {\n"); + for (l = def->def.un.cases; l != NULL; l = l->next) + { + if (l->contflag == 0) + pdeclaration (name, &l->case_decl, 2, ";\n"); + } + decl = def->def.un.default_decl; + if (decl && !streq (decl->type, "void")) + { + pdeclaration (name, decl, 2, ";\n"); + } + f_print (fout, "\t} %s_u;\n", name); + f_print (fout, "};\n"); + f_print (fout, "typedef struct %s %s;\n", name, name); +} + +static void +pdefine (const char *name, const char *num) +{ + f_print (fout, "#define %s %s\n", name, num); +} + +static int +define_printed (proc_list *stop, version_list *start) +{ + version_list *vers; + proc_list *proc; + + for (vers = start; vers != NULL; vers = vers->next) + { + for (proc = vers->procs; proc != NULL; proc = proc->next) + { + if (proc == stop) + { + return 0; + } + else if (streq (proc->proc_name, stop->proc_name)) + { + return 1; + } + } + } + abort (); + /* NOTREACHED */ +} + +static void +pfreeprocdef (const char *name, const 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 void +pprogramdef (definition *def) +{ + version_list *vers; + proc_list *proc; + int i; + const char *ext; + + pargdef (def); + + pdefine (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); + } + pdefine (vers->vers_name, vers->vers_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)) + { + pdefine (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)) + { + pdefine(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); + } + f_print (fout, "#endif /* K&R C */\n"); + } + } +} + +void +pprocdef (proc_list * proc, version_list * vp, + const char *addargtype, int server_p, int mode) +{ + 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 void +parglist (proc_list *proc, const 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 (mtflag) + { + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*, "); + } + + f_print (fout, "%s);\n", addargtype); +} + +static void +penumdef (definition *def) +{ + const char *name = def->def_name; + enumval_list *l; + const char *last = NULL; + int count = 0; + + f_print (fout, "enum %s {\n", name); + for (l = def->def.en.vals; l != NULL; l = l->next) + { + f_print (fout, "\t%s", l->name); + if (l->assignment) + { + f_print (fout, " = %s", l->assignment); + last = l->assignment; + count = 1; + } + else + { + if (last == NULL) + { + f_print (fout, " = %d", count++); + } + else + { + f_print (fout, " = %s + %d", last, count++); + } + } + f_print (fout, ",\n"); + } + f_print (fout, "};\n"); + f_print (fout, "typedef enum %s %s;\n", name, name); +} + +static void +ptypedef (definition *def) +{ + const char *name = def->def_name; + const char *old = def->def.ty.old_type; + char prefix[8]; /* enough to contain "struct ", including NUL */ + relation rel = def->def.ty.rel; + + if (!streq (name, old)) + { + if (streq (old, "string")) + { + old = "char"; + rel = REL_POINTER; + } + else if (streq (old, "opaque")) + { + old = "char"; + } + else if (streq (old, "bool")) + { + old = "bool_t"; + } + if (undefined2 (old, name) && def->def.ty.old_prefix) + { + s_print (prefix, "%s ", def->def.ty.old_prefix); + } + else + { + prefix[0] = 0; + } + f_print (fout, "typedef "); + switch (rel) + { + case REL_ARRAY: + f_print (fout, "struct {\n"); + f_print (fout, "\tu_int %s_len;\n", name); + f_print (fout, "\t%s%s *%s_val;\n", prefix, old, name); + f_print (fout, "} %s", name); + break; + case REL_POINTER: + f_print (fout, "%s%s *%s", prefix, old, name); + break; + case REL_VECTOR: + f_print (fout, "%s%s %s[%s]", prefix, old, name, + def->def.ty.array_max); + break; + case REL_ALIAS: + f_print (fout, "%s%s %s", prefix, old, name); + break; + } + f_print (fout, ";\n"); + } +} + +void +pdeclaration (const char *name, declaration * dec, int tab, + const char *separator) +{ + char buf[8]; /* enough to hold "struct ", include NUL */ + const char *prefix; + const char *type; + + if (streq (dec->type, "void")) + { + return; + } + tabify (fout, tab); + if (streq (dec->type, name) && !dec->prefix) + { + f_print (fout, "struct "); + } + if (streq (dec->type, "string")) + { + f_print (fout, "char *%s", dec->name); + } + else + { + prefix = ""; + if (streq (dec->type, "bool")) + { + type = "bool_t"; + } + else if (streq (dec->type, "opaque")) + { + type = "char"; + } + else + { + if (dec->prefix) + { + s_print (buf, "%s ", dec->prefix); + prefix = buf; + } + type = dec->type; + } + switch (dec->rel) + { + case REL_ALIAS: + f_print (fout, "%s%s %s", prefix, type, dec->name); + break; + case REL_VECTOR: + f_print (fout, "%s%s %s[%s]", prefix, type, dec->name, + dec->array_max); + break; + case REL_POINTER: + f_print (fout, "%s%s *%s", prefix, type, dec->name); + break; + case REL_ARRAY: + f_print (fout, "struct {\n"); + tabify (fout, tab); + f_print (fout, "\tu_int %s_len;\n", dec->name); + tabify (fout, tab); + f_print (fout, "\t%s%s *%s_val;\n", prefix, type, dec->name); + tabify (fout, tab); + f_print (fout, "} %s", dec->name); + break; + } + } + f_print (fout, "%s", separator); +} + +static int +undefined2 (const char *type, const char *stop) +{ + list *l; + definition *def; + + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) + { + if (streq (def->def_name, stop)) + { + return 1; + } + else if (streq (def->def_name, type)) + { + return 0; + } + } + } + return 1; +} diff --git a/tools/rpcgen/rpc_main.c b/tools/rpcgen/rpc_main.c new file mode 100644 index 0000000..277adc6 --- /dev/null +++ b/tools/rpcgen/rpc_main.c @@ -0,0 +1,1459 @@ +/* + * From @(#)rpc_main.c 1.30 89/03/30 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_main.c, Top level of the RPC protocol compiler. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <locale.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "rpc_scan.h" +#include "proto.h" +#include "nls.h" + +#ifndef _ +#define _(String) gettext (String) +#endif + +#define EXTEND 1 /* alias for TRUE */ +#define DONT_EXTEND 0 /* alias for FALSE */ + +#ifdef __APPLE__ +# if __DARWIN_ONLY_64_BIT_INO_T +# define stat64 stat +# endif +#endif + +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 */ + const char *infile; /* input module name */ + const char *outfile; /* output module name */ + }; + + +static const char *cmdname; + +static const char *svcclosetime = "120"; +static int cppDefined; /* explicit path for C preprocessor */ +static const char *CPP = "/lib/cpp"; +static const char CPPFLAGS[] = "-C"; +static char *pathbuf; +static int cpp_pid; +static const char *allv[] = +{ + "rpcgen", "-s", "udp", "-s", "tcp" +}; +static int allc = sizeof (allv) / sizeof (allv[0]); +static const char *allnv[] = +{ + "rpcgen", "-s", "netpath", +}; +static int allnc = sizeof (allnv) / sizeof (allnv[0]); + +/* + * machinations for handling expanding argument list + */ +static void addarg (const char *); /* add another argument to the list */ +static void putarg (int, const char *); /* put argument at specified location */ +static void clear_args (void); /* clear argument list */ +static void checkfiles (const char *, const char *); + /* check if out file already exists */ + +static void clear_args (void); +static char *extendfile (const char *file, const char *ext); +static void open_output (const char *infile, const char *outfile); +static void add_warning (void); +static void clear_args (void); +static void find_cpp (void); +static void open_input (const char *infile, const char *define); +static int check_nettype (const char *name, const char *list_to_check[]); +static void c_output (const char *infile, const char *define, + int extend, const char *outfile); +static void h_output (const char *infile, const char *define, + int extend, const char *outfile); +static void s_output (int argc, const char *argv[], const char *infile, + const char *define, int extend, + const char *outfile, int nomain, int netflag); +static void l_output (const char *infile, const char *define, + int extend, const char *outfile); +static void t_output (const char *infile, const char *define, + int extend, const char *outfile); +static void svc_output (const char *infile, const char *define, + int extend, const char *outfile); +static void clnt_output (const char *infile, const char *define, + int extend, const char *outfile); +static void mkfile_output (struct commandline *cmd); +static int do_registers (int argc, const char *argv[]); +static void addarg (const char *cp); +static void putarg (int whereto, const char *cp); +static void checkfiles (const char *infile, const char *outfile); +static int parseargs (int argc, const char *argv[], struct commandline *cmd); +static void usage (FILE *stream, int status) __attribute__ ((noreturn)); +static void options_usage (FILE *stream, int status) __attribute__ ((noreturn)); +static void print_version (void); +static void c_initialize (void); +static char *generate_guard (const char *pathname); + + +#define ARGLISTLEN 20 +#define FIXEDARGS 2 + +static const char *arglist[ARGLISTLEN]; +static int argcount = FIXEDARGS; + + +int nonfatalerrors; /* errors */ +int inetdflag /* = 1 */ ; /* Support for inetd *//* is now the default */ +int pmflag; /* Support for port monitors */ +int logflag; /* Use syslog instead of fprintf for errors */ +int tblflag; /* Support for dispatch table file */ +int mtflag; /* Support for MT */ + +#define INLINE 3 +/*length at which to start doing an inline */ + +int inlineflag = INLINE; /* length at which to start doing an inline. 3 = default + if 0, no xdr_inline code */ + +int indefinitewait; /* If started by port monitors, hang till it wants */ +int exitnow; /* If started by port monitors, exit after the call */ +int timerflag; /* TRUE if !indefinite && !exitnow */ +int newstyle; /* newstyle of passing arguments (by value) */ +int Cflag = 1; /* ANSI C syntax */ +int CCflag; /* C++ files */ +static int allfiles; /* generate all files */ +int tirpcflag; /* generating code for tirpc, default is backward compatibility */ +xdrfunc *xdrfunc_head; /* xdr function list */ +xdrfunc *xdrfunc_tail; /* xdr function list */ + +int +main (int argc, const char *argv[]) +{ + struct commandline cmd; + + setlocale (LC_ALL, ""); + textdomain (PACKAGE); + + (void) memset ((char *) &cmd, 0, sizeof (struct commandline)); + clear_args (); + if (!parseargs (argc, argv, &cmd)) + usage (stderr, 1); + + if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag || + cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) + { + checkfiles (cmd.infile, cmd.outfile); + } + else + checkfiles (cmd.infile, NULL); + + if (cmd.cflag) + c_output (cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); + else if (cmd.hflag) + h_output (cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); + else if (cmd.lflag) + l_output (cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile); + else if (cmd.sflag || cmd.mflag || (cmd.nflag)) + s_output (argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND, + cmd.outfile, cmd.mflag, cmd.nflag); + else if (cmd.tflag) + t_output (cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile); + else if (cmd.Ssflag) + svc_output (cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile); + else if (cmd.Scflag) + clnt_output (cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile); + else 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 (); + 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); + } + } + + return nonfatalerrors; +} + +/* + * add extension to filename + */ +static char * +extendfile (const char *file, const char *ext) +{ + char *res; + const char *p; + + res = alloc (strlen (file) + strlen (ext) + 1); + if (res == NULL) + abort (); + p = strrchr (file, '.'); + if (p == NULL) + p = file + strlen (file); + strcpy (res, file); + strcpy (res + (p - file), ext); + return res; +} + +/* + * Open output file with given extension + */ +static void +open_output (const char *infile, const char *outfile) +{ + if (outfile == NULL) + { + fout = stdout; + return; + } + + if (infile != NULL && streq (outfile, infile)) + { + fprintf (stderr, _("%s: output would overwrite %s\n"), cmdname, + infile); + crash (); + } + fout = fopen (outfile, "w"); + if (fout == NULL) + { + fprintf (stderr, _("%s: unable to open %s: %m\n"), cmdname, outfile); + crash (); + } + record_open (outfile); +} + +/* Close the output file and check for write errors. */ +static void +close_output (const char *outfile) +{ + if (fclose (fout) == EOF) + { + fprintf (stderr, _("%s: while writing output %s: %m"), cmdname, + outfile ?: "<stdout>"); + crash (); + } +} + +static void +add_warning (void) +{ + fprintf (fout, "/*\n"); + fprintf (fout, " * Please do not edit this file.\n"); + fprintf (fout, " * It was generated using rpcgen.\n"); + fprintf (fout, " */\n\n"); +} + +/* clear list of arguments */ +static void +clear_args (void) +{ + int i; + for (i = FIXEDARGS; i < ARGLISTLEN; ++i) + arglist[i] = NULL; + argcount = FIXEDARGS; +} + +/* make sure that a CPP exists */ +static void +find_cpp (void) +{ + struct stat64 buf; + + if (stat64 (CPP, &buf) == 0) + return; + + if (cppDefined) /* user specified cpp but it does not exist */ + { + fprintf (stderr, _ ("cannot find C preprocessor: %s\n"), CPP); + crash (); + } + + /* fall back to system CPP */ + CPP = "cpp"; +} + +/* + * Open input file with given define for C-preprocessor + */ +static void +open_input (const char *infile, const char *define) +{ + int pd[2]; + + infilename = (infile == NULL) ? "<stdin>" : infile; + if (pipe (pd) != 0) + { + perror ("pipe"); + exit (1); + } + cpp_pid = fork (); + switch (cpp_pid) + { + case 0: + find_cpp (); + putarg (0, CPP); + putarg (1, CPPFLAGS); + addarg (define); + if (infile) + addarg (infile); + addarg ((char *) NULL); + close (1); + dup2 (pd[1], 1); + close (pd[0]); + execvp (arglist[0], (char **) arglist); + if (errno == ENOENT) + { + fprintf (stderr, _ ("cannot find C preprocessor: %s\n"), CPP); + exit (1); + } + perror ("execvp"); + exit (1); + case -1: + perror ("fork"); + exit (1); + } + close (pd[1]); + fin = fdopen (pd[0], "r"); + if (fin == NULL) + { + fprintf (stderr, "%s: ", cmdname); + perror (infilename); + crash (); + } +} + +/* Close the connection to the C-preprocessor and check for successfull + termination. */ +static void +close_input (void) +{ + int status; + + fclose (fin); + /* Check the termination status. */ + if (waitpid (cpp_pid, &status, 0) < 0) + { + perror ("waitpid"); + crash (); + } + if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0) + { + if (WIFSIGNALED (status)) + fprintf (stderr, _("%s: C preprocessor failed with signal %d\n"), + cmdname, WTERMSIG (status)); + else + fprintf (stderr, _("%s: C preprocessor failed with exit code %d\n"), + cmdname, WEXITSTATUS (status)); + crash (); + } +} + +/* valid tirpc nettypes */ +static const char *valid_ti_nettypes[] = +{ + "netpath", + "visible", + "circuit_v", + "datagram_v", + "circuit_n", + "datagram_n", + "udp", + "tcp", + "raw", + NULL +}; + +/* valid inetd nettypes */ +static const char *valid_i_nettypes[] = +{ + "udp", + "tcp", + NULL +}; + +static int +check_nettype (const char *name, const 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; + } + } + fprintf (stderr, _ ("illegal nettype: `%s'\n"), name); + return 0; +} + +/* + * Compile into an XDR routine output file + */ + +static void +c_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + definition *def; + char *include; + const char *outfilename; + long tell; + + c_initialize (); + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + add_warning (); + if (infile && (include = extendfile (infile, ".h"))) + { + fprintf (fout, "#include \"%s\"\n", include); + free (include); + /* .h file already contains rpc/rpc.h */ + } + else + fprintf (fout, "#include <rpc/rpc.h>\n"); + tell = ftell (fout); + while ((def = get_definition ()) != NULL) + emit (def); + + if (extend && tell == ftell (fout)) + unlink (outfilename); + close_input (); + close_output (outfilename); +} + +void +c_initialize (void) +{ + + /* add all the starting basic types */ + + add_type (1, "int"); + add_type (1, "long"); + add_type (1, "short"); + add_type (1, "bool"); + + add_type (1, "u_int"); + add_type (1, "u_long"); + add_type (1, "u_short"); + +} + +char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ + char *(*proc)();\n\ + xdrproc_t xdr_arg;\n\ + unsigned len_arg;\n\ + xdrproc_t xdr_res;\n\ + unsigned len_res;\n\ +};\n"; + + +static char * +generate_guard (const char *pathname) +{ + const char *filename; + char *guard, *tmp; + + filename = strrchr (pathname, '/'); /* find last component */ + filename = ((filename == NULL) ? pathname : filename + 1); + guard = extendfile (filename, "_H_RPCGEN"); + /* convert to upper case */ + tmp = guard; + while (*tmp) + { + if (islower (*tmp)) + *tmp = toupper (*tmp); + tmp++; + } + + return guard; +} + +/* + * Compile into an XDR header file + */ + + +static void +h_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + xdrfunc *xdrfuncp; + definition *def; + const char *ifilename; + const char *outfilename; + long tell; + char *guard; + list *l; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + add_warning (); + ifilename = (infile == NULL) ? "STDIN" : infile; + guard = generate_guard (outfilename ? outfilename : ifilename); + + fprintf (fout, "#ifndef _%s\n#define _%s\n\n", guard, + guard); + + fprintf (fout, "#include <rpc/rpc.h>\n\n"); + + if (mtflag) + { + fprintf (fout, "#include <pthread.h>\n"); + } + + /* put the C++ support */ + if (Cflag && !CCflag) + { + fprintf (fout, "\n#ifdef __cplusplus\n"); + fprintf (fout, "extern \"C\" {\n"); + fprintf (fout, "#endif\n\n"); + } + + tell = ftell (fout); + /* print data definitions */ + while ((def = get_definition ()) != NULL) + { + print_datadef (def); + } + + /* print function declarations. + Do this after data definitions because they might be used as + arguments for functions */ + for (l = defined; l != NULL; l = l->next) + { + print_funcdef (l->val); + } + /* Now print all xdr func declarations */ + if (xdrfunc_head != NULL) + { + fprintf (fout, "\n/* the xdr functions */\n"); + if (CCflag) + { + fprintf (fout, "\n#ifdef __cplusplus\n"); + fprintf (fout, "extern \"C\" {\n"); + fprintf (fout, "#endif\n"); + } + if (!Cflag) + { + xdrfuncp = xdrfunc_head; + while (xdrfuncp != NULL) + { + print_xdr_func_def (xdrfuncp->name, + xdrfuncp->pointerp, 2); + xdrfuncp = xdrfuncp->next; + } + } + else + { + int i; + + for (i = 1; i < 3; ++i) + { + if (i == 1) + fprintf (fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); + else + fprintf (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; + } + } + fprintf (fout, "\n#endif /* K&R C */\n"); + } + } + + if (extend && tell == ftell (fout)) + { + unlink (outfilename); + } + else if (tblflag) + { + fprintf (fout, "%s", rpcgen_table_dcl); + } + + if (Cflag) + { + fprintf (fout, "\n#ifdef __cplusplus\n"); + fprintf (fout, "}\n"); + fprintf (fout, "#endif\n"); + } + + fprintf (fout, "\n#endif /* !_%s */\n", guard); + free (guard); + close_input (); + close_output (outfilename); +} + +/* + * Compile into an RPC service + */ +static void +s_output (int argc, const char *argv[], const char *infile, const char *define, + int extend, const char *outfile, int nomain, int netflag) +{ + char *include; + definition *def; + int foundprogram = 0; + const char *outfilename; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + add_warning (); + if (infile && (include = extendfile (infile, ".h"))) + { + fprintf (fout, "#include \"%s\"\n", include); + free (include); + } + else + fprintf (fout, "#include <rpc/rpc.h>\n"); + + fprintf (fout, "#include <stdio.h>\n"); + fprintf (fout, "#include <stdlib.h>\n"); + fprintf (fout, "#include <rpc/pmap_clnt.h>\n"); + if (Cflag) + fprintf (fout, "#include <string.h>\n"); + if (strcmp (svcclosetime, "-1") == 0) + indefinitewait = 1; + else if (strcmp (svcclosetime, "0") == 0) + exitnow = 1; + else if (inetdflag || pmflag) + { + fprintf (fout, "#include <signal.h>\n"); + timerflag = 1; + } + + if (!tirpcflag && inetdflag) + fprintf (fout, "#include <sys/ioctl.h> /* ioctl, TIOCNOTTY */\n"); + if (Cflag && (inetdflag || pmflag)) + { + fprintf (fout, "#include <sys/types.h> /* open */\n"); + fprintf (fout, "#include <sys/stat.h> /* open */\n"); + fprintf (fout, "#include <fcntl.h> /* open */\n"); + fprintf (fout, "#include <unistd.h> /* getdtablesize */\n"); + } + if (tirpcflag && !(Cflag && (inetdflag || pmflag))) + fprintf (fout, "#include <sys/types.h>\n"); + + fprintf (fout, "#include <memory.h>\n"); + if (inetdflag || !tirpcflag) + { + fprintf (fout, "#include <sys/socket.h>\n"); + fprintf (fout, "#include <netinet/in.h>\n"); + } + + if ((netflag || pmflag) && tirpcflag && !nomain) + { + fprintf (fout, "#include <netconfig.h>\n"); + } + if ( /*timerflag && */ tirpcflag) + fprintf (fout, "#include <sys/resource.h> /* rlimit */\n"); + if (logflag || inetdflag || pmflag) + { + fprintf (fout, "#include <syslog.h>\n"); + } + + /* for ANSI-C */ + if (Cflag) + fprintf (fout, "\n#ifndef SIG_PF\n#define SIG_PF void(*)(int)\n#endif\n"); + + if (timerflag) + fprintf (fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime); + while ((def = get_definition ()) != NULL) + { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) + { + unlink (outfilename); + return; + } + write_most (infile, netflag, nomain); + if (!nomain) + { + if (!do_registers (argc, argv)) + { + if (outfilename) + unlink (outfilename); + usage (stderr, 1); + } + write_rest (); + } + close_input (); + close_output (outfilename); +} + +/* + * generate client side stubs + */ +static void +l_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + char *include; + definition *def; + int foundprogram = 0; + const char *outfilename; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + add_warning (); + if (Cflag) + fprintf (fout, "#include <memory.h> /* for memset */\n"); + if (infile && (include = extendfile (infile, ".h"))) + { + fprintf (fout, "#include \"%s\"\n", include); + free (include); + } + else + fprintf (fout, "#include <rpc/rpc.h>\n"); + while ((def = get_definition ()) != NULL) + { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) + { + unlink (outfilename); + return; + } + write_stubs (); + close_input (); + close_output (outfilename); +} + +/* + * generate the dispatch table + */ +static void +t_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + definition *def; + int foundprogram = 0; + const char *outfilename; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + add_warning (); + while ((def = get_definition ()) != NULL) + { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) + { + unlink (outfilename); + return; + } + write_tables (); + close_input (); + close_output (outfilename); +} + +/* sample routine for the server template */ +static void +svc_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + definition *def; + char *include; + const 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"))) + { + fprintf (fout, "#include \"%s\"\n", include); + free (include); + } + else + fprintf (fout, "#include <rpc/rpc.h>\n"); + + tell = ftell (fout); + while ((def = get_definition ()) != NULL) + { + write_sample_svc (def); + } + if (extend && tell == ftell (fout)) + { + unlink (outfilename); + } + close_input (); + close_output (outfilename); +} + + +/* sample main routine for client */ +static void +clnt_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + definition *def; + char *include; + const 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"))) + { + fprintf (fout, "#include \"%s\"\n", include); + free (include); + } + else + fprintf (fout, "#include <rpc/rpc.h>\n"); + tell = ftell (fout); + while ((def = get_definition ()) != NULL) + { + has_program += write_sample_clnt (def); + } + + if (has_program) + write_sample_clnt_main (); + + if (extend && tell == ftell (fout)) + { + unlink (outfilename); + } + close_input (); + close_output (outfilename); +} + +static const char space[] = " "; + +static char * +file_name (const char *file, const char *ext) +{ + char *temp; + temp = extendfile (file, ext); + + if (access (temp, F_OK) != -1) + return (temp); + + free (temp); + return (char *) space; +} + +static void +mkfile_output (struct commandline *cmd) +{ + char *mkfilename; + char *clientname, *clntname, *xdrname, *hdrname; + char *servername, *svcname, *servprogname, *clntprogname; + + 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 = (char *) space; + clientname = (char *) space; + } + servprogname = extendfile (cmd->infile, "_server"); + clntprogname = extendfile (cmd->infile, "_client"); + + if (allfiles) + { + char *cp, *temp; + + mkfilename = alloc (strlen ("Makefile.") + strlen (cmd->infile) + 1); + if (mkfilename == NULL) + abort (); + temp = rindex (cmd->infile, '.'); + cp = stpcpy (mkfilename, "Makefile."); + if (temp != NULL) + *((char *) stpncpy (cp, cmd->infile, temp - cmd->infile)) = '\0'; + else + stpcpy (cp, cmd->infile); + + } + else + mkfilename = (char *) cmd->outfile; + + checkfiles (NULL, mkfilename); + open_output (NULL, mkfilename); + + fprintf (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) + fprintf (fout, "\nCPPFLAGS += -D_REENTRANT\nCFLAGS += -g \nLDLIBS \ ++= -lnsl -lpthread \n "); + else + f_print (fout, "\nCFLAGS += -g \nLDLIBS += -lnsl\n"); + 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"); + f_print (fout, "\t$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) \ +$(LDLIBS) \n\n"); + f_print (fout, "$(SERVER) : $(OBJECTS_SVC) \n"); + 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"); + close_output (mkfilename); + + free (clntprogname); + free (servprogname); + if (servername != space) + free (servername); + if (clientname != space) + free (clientname); + if (mkfilename != (char *) cmd->outfile) + free (mkfilename); + if (svcname != space) + free (svcname); + if (clntname != space) + free (clntname); + if (xdrname != space) + free (xdrname); + if (hdrname != space) + free (hdrname); +} + +/* + * Perform registrations for service output + * Return 0 if failed; 1 otherwise. + */ +static int +do_registers (int argc, const char *argv[]) +{ + int i; + + if (inetdflag || !tirpcflag) + { + for (i = 1; i < argc; i++) + { + if (streq (argv[i], "-s")) + { + if (!check_nettype (argv[i + 1], valid_i_nettypes)) + return 0; + write_inetd_register (argv[i + 1]); + i++; + } + } + } + else + { + for (i = 1; i < argc; i++) + if (streq (argv[i], "-s")) + { + if (!check_nettype (argv[i + 1], valid_ti_nettypes)) + return 0; + write_nettype_register (argv[i + 1]); + i++; + } + else if (streq (argv[i], "-n")) + { + write_netid_register (argv[i + 1]); + i++; + } + } + return 1; +} + +/* + * Add another argument to the arg list + */ +static void +addarg (const char *cp) +{ + if (argcount >= ARGLISTLEN) + { + fprintf (stderr, _("rpcgen: too many defines\n")); + crash (); + /*NOTREACHED */ + } + arglist[argcount++] = cp; +} + +static void +putarg (int whereto, const char *cp) +{ + if (whereto >= ARGLISTLEN) + { + fprintf (stderr, _("rpcgen: arglist coding error\n")); + crash (); + /*NOTREACHED */ + } + arglist[whereto] = 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 (const char *infile, const char *outfile) +{ + struct stat64 buf; + + if (infile) /* infile ! = NULL */ + if (stat64 (infile, &buf) < 0) + { + perror (infile); + crash (); + } + if (outfile) + { + if (stat64 (outfile, &buf) < 0) + return; /* file does not exist */ + else + { + fprintf (stderr, + /* TRANS: the file will not be removed; this is an + TRANS: informative message. */ + _("file `%s' already exists and may be overwritten\n"), + outfile); + crash (); + } + } +} + +/* + * Parse command line arguments + */ +static int +parseargs (int argc, const char *argv[], struct commandline *cmd) +{ + int i; + int j; + int c; + char flag[(1 << 8 * sizeof (char))]; + int nflags; + + cmdname = argv[0]; + cmd->infile = cmd->outfile = NULL; + if (argc < 2) + { + return (0); + } + allfiles = 0; + flag['c'] = 0; + flag['h'] = 0; + flag['l'] = 0; + flag['m'] = 0; + flag['o'] = 0; + flag['s'] = 0; + flag['n'] = 0; + flag['t'] = 0; + flag['S'] = 0; + flag['C'] = 0; + flag['M'] = 0; + + for (i = 1; i < argc; i++) + { + if (argv[i][0] != '-') + { + if (cmd->infile) + { + fprintf (stderr, + _("Cannot specify more than one input file!\n")); + return 0; + } + cmd->infile = argv[i]; + } + else if (strcmp (argv[i], "--help") == 0) + usage (stdout, 0); + else if (strcmp (argv[i], "--version") == 0) + print_version (); + else + { + for (j = 1; argv[i][j] != 0; j++) + { + c = argv[i][j]; + switch (c) + { + case 'a': + allfiles = 1; + break; + case 'c': + case 'h': + case 'l': + case 'm': + case 't': + if (flag[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']; */ + c = argv[i][++j]; /* get next char */ + if (c == 's') + c = 'S'; + else if (c == 'c') + c = 'C'; + else if (c == 'm') + c = 'M'; + else + return 0; + + if (flag[c]) + return 0; + flag[c] = 1; + break; + case 'C': /* ANSI C syntax */ + Cflag = 1; + break; + + case 'k': /* K&R C syntax */ + Cflag = 0; + break; + + case 'b': /* turn TIRPC flag off for + generating backward compatible + */ + tirpcflag = 0; + break; + + case '5': /* turn TIRPC flag on for + generating SysVr4 compatible + */ + tirpcflag = 1; + 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); + } + inlineflag = atoi (argv[i]); + goto nextarg; + case 'n': + case 'o': + case 's': + if (argv[i][j - 1] != '-' || + argv[i][j + 1] != 0) + { + return (0); + } + flag[c] = 1; + if (++i == argc) + { + return (0); + } + if (c == 's') + { + if (!streq (argv[i], "udp") && + !streq (argv[i], "tcp")) + return 0; + } + else if (c == 'o') + { + if (cmd->outfile) + return 0; + cmd->outfile = argv[i]; + } + goto nextarg; + case 'D': + if (argv[i][j - 1] != '-') + return 0; + addarg (argv[i]); + goto nextarg; + case 'Y': + if (++i == argc) + return 0; + { + size_t len = strlen (argv[i]); + pathbuf = malloc (len + 5); + if (pathbuf == NULL) + { + perror (cmdname); + crash (); + } + stpcpy (stpcpy (pathbuf, + argv[i]), + "/cpp"); + CPP = pathbuf; + cppDefined = 1; + goto nextarg; + } + + default: + return 0; + } + } + nextarg: + ; + } + } + + cmd->cflag = flag['c']; + cmd->hflag = flag['h']; + cmd->lflag = flag['l']; + cmd->mflag = flag['m']; + cmd->nflag = flag['n']; + cmd->sflag = flag['s']; + cmd->tflag = flag['t']; + cmd->Ssflag = flag['S']; + cmd->Scflag = flag['C']; + 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 */ + fprintf (stderr, _("Cannot use netid flag with inetd flag!\n")); + return 0; + } + } + else + { /* 4.1 mode */ + pmflag = 0; /* set pmflag only in tirpcmode */ + if (cmd->nflag) + { /* netid needs TIRPC */ + f_print (stderr, _("Cannot use netid flag without TIRPC!\n")); + return (0); + } + } + + if (newstyle && (tblflag || cmd->tflag)) + { + f_print (stderr, _("Cannot use table flags with newstyle!\n")); + return (0); + } + + /* check no conflicts with file generation flags */ + nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag + + cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag; + + if (nflags == 0) + { + if (cmd->outfile != NULL || cmd->infile == NULL) + { + return (0); + } + } + else if (cmd->infile == NULL && + (cmd->Ssflag || cmd->Scflag || cmd->makefileflag)) + { + fprintf (stderr, + _("\"infile\" is required for template generation flags.\n")); + return 0; + } + if (nflags > 1) + { + fprintf (stderr, _("Cannot have more than one file generation flag!\n")); + return 0; + } + return 1; +} + +static void +usage (FILE *stream, int status) +{ + fprintf (stream, _("usage: %s infile\n"), cmdname); + fprintf (stream, _("\t%s [-abkCLNTM][-Dname[=value]] [-i size] \ +[-I [-K seconds]] [-Y path] infile\n"), cmdname); + fprintf (stream, _("\t%s [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm] \ +[-o outfile] [infile]\n"), cmdname); + fprintf (stream, _("\t%s [-s nettype]* [-o outfile] [infile]\n"), cmdname); + fprintf (stream, _("\t%s [-n netid]* [-o outfile] [infile]\n"), cmdname); + options_usage (stream, status); + exit (status); +} + +static void +options_usage (FILE *stream, int status) +{ + f_print (stream, _("options:\n")); + f_print (stream, _("-a\t\tgenerate all files, including samples\n")); + f_print (stream, _("-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n")); + f_print (stream, _("-c\t\tgenerate XDR routines\n")); + f_print (stream, _("-C\t\tANSI C mode\n")); + f_print (stream, _("-Dname[=value]\tdefine a symbol (same as #define)\n")); + f_print (stream, _("-h\t\tgenerate header file\n")); + f_print (stream, _("-i size\t\tsize at which to start generating inline code\n")); + f_print (stream, _("-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n")); + f_print (stream, _("-K seconds\tserver exits after K seconds of inactivity\n")); + f_print (stream, _("-l\t\tgenerate client side stubs\n")); + f_print (stream, _("-L\t\tserver errors will be printed to syslog\n")); + f_print (stream, _("-m\t\tgenerate server side stubs\n")); + f_print (stream, _("-M\t\tgenerate MT-safe code\n")); + f_print (stream, _("-n netid\tgenerate server code that supports named netid\n")); + f_print (stream, _("-N\t\tsupports multiple arguments and call-by-value\n")); + f_print (stream, _("-o outfile\tname of the output file\n")); + f_print (stream, _("-s nettype\tgenerate server code that supports named nettype\n")); + f_print (stream, _("-Sc\t\tgenerate sample client code that uses remote procedures\n")); + f_print (stream, _("-Ss\t\tgenerate sample server code that defines remote procedures\n")); + f_print (stream, _("-Sm \t\tgenerate makefile template \n")); + f_print (stream, _("-t\t\tgenerate RPC dispatch table\n")); + f_print (stream, _("-T\t\tgenerate code to support RPC dispatch tables\n")); + f_print (stream, _("-Y path\t\tdirectory name to find C preprocessor (cpp)\n")); + f_print (stream, _("-5\t\tSysVr4 compatibility mode\n")); + f_print (stream, _("--help\t\tgive this help list\n")); + f_print (stream, _("--version\tprint program version\n")); + + exit (status); +} + +static void +print_version (void) +{ + printf ("rpcgen (%s) %s\n", PACKAGE, VERSION); + exit (0); +} diff --git a/tools/rpcgen/rpc_output.h b/tools/rpcgen/rpc_output.h new file mode 100644 index 0000000..eb25a60 --- /dev/null +++ b/tools/rpcgen/rpc_output.h @@ -0,0 +1,16 @@ +/* + * rpc_output.h + * + * Declarations for output functions + * + */ + +#ifndef RPCGEN_NEW_OUTPUT_H +#define RPCGEN_NEW_OUTPUT_H + +void write_msg_out(void); +int nullproc(proc_list *); +void printarglist(proc_list *, char *, char *); +void pdeclaration(char *, declaration *, int, char *); + +#endif /* RPCGEN_NEW_OUTPUT_H */ diff --git a/tools/rpcgen/rpc_parse.c b/tools/rpcgen/rpc_parse.c new file mode 100644 index 0000000..ee37430 --- /dev/null +++ b/tools/rpcgen/rpc_parse.c @@ -0,0 +1,686 @@ +/* + * From: @(#)rpc_parse.c 1.8 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_parse.c, Parser for the RPC protocol compiler + * Copyright (C) 1987 Sun Microsystems, Inc. + */ +#include <stdio.h> +#include <string.h> +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +#define ARGNAME "arg" + +static void isdefined (definition * defp); +static void def_struct (definition * defp); +static void def_program (definition * defp); +static void def_enum (definition * defp); +static void def_const (definition * defp); +static void def_union (definition * defp); +static void check_type_name (const char *name, int new_type); +static void def_typedef (definition * defp); +static void get_declaration (declaration * dec, defkind dkind); +static void get_prog_declaration (declaration * dec, defkind dkind, int num); +static void get_type (const char **prefixp, const char **typep, defkind dkind); +static void unsigned_dec (const char **typep); + +/* + * return the next definition you see + */ +definition * +get_definition (void) +{ + definition *defp; + token tok; + + defp = ALLOC (definition); + get_token (&tok); + switch (tok.kind) + { + case TOK_STRUCT: + def_struct (defp); + break; + case TOK_UNION: + def_union (defp); + break; + case TOK_TYPEDEF: + def_typedef (defp); + break; + case TOK_ENUM: + def_enum (defp); + break; + case TOK_PROGRAM: + def_program (defp); + break; + case TOK_CONST: + def_const (defp); + break; + case TOK_EOF: + free (defp); + return (NULL); + default: + error ("definition keyword expected"); + } + scan (TOK_SEMICOLON, &tok); + isdefined (defp); + return (defp); +} + +static void +isdefined (definition * defp) +{ + STOREVAL (&defined, defp); +} + +static void +def_struct (definition * defp) +{ + token tok; + declaration dec; + decl_list *decls; + decl_list **tailp; + + defp->def_kind = DEF_STRUCT; + + scan (TOK_IDENT, &tok); + defp->def_name = tok.str; + scan (TOK_LBRACE, &tok); + tailp = &defp->def.st.decls; + do + { + get_declaration (&dec, DEF_STRUCT); + decls = ALLOC (decl_list); + decls->decl = dec; + *tailp = decls; + tailp = &decls->next; + scan (TOK_SEMICOLON, &tok); + peek (&tok); + } + while (tok.kind != TOK_RBRACE); + get_token (&tok); + *tailp = NULL; +} + +static void +def_program (definition * defp) +{ + token tok; + declaration dec; + decl_list *decls; + decl_list **tailp; + version_list *vlist; + version_list **vtailp; + proc_list *plist; + proc_list **ptailp; + int num_args; + int isvoid = 0; /* whether first argument is void */ + defp->def_kind = DEF_PROGRAM; + scan (TOK_IDENT, &tok); + defp->def_name = tok.str; + scan (TOK_LBRACE, &tok); + vtailp = &defp->def.pr.versions; + tailp = &defp->def.st.decls; + scan (TOK_VERSION, &tok); + do + { + scan (TOK_IDENT, &tok); + vlist = ALLOC (version_list); + vlist->vers_name = tok.str; + scan (TOK_LBRACE, &tok); + ptailp = &vlist->procs; + do + { + /* get result type */ + plist = ALLOC (proc_list); + get_type (&plist->res_prefix, &plist->res_type, + DEF_PROGRAM); + if (streq (plist->res_type, "opaque")) + { + error ("illegal result type"); + } + scan (TOK_IDENT, &tok); + plist->proc_name = tok.str; + scan (TOK_LPAREN, &tok); + /* get args - first one */ + num_args = 1; + isvoid = 0; + /* 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 = 1; + 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 = 1; + tailp = &decls->next; + } + /* multiple arguments are only allowed in newstyle */ + if (!newstyle && num_args > 1) + { + error ("only one argument is allowed"); + } + if (isvoid && num_args > 1) + { + error ("illegal use of void in program definition"); + } + *tailp = NULL; + scan (TOK_RPAREN, &tok); + scan (TOK_EQUAL, &tok); + scan_num (&tok); + scan (TOK_SEMICOLON, &tok); + plist->proc_num = tok.str; + plist->arg_num = num_args; + *ptailp = plist; + ptailp = &plist->next; + peek (&tok); + } + while (tok.kind != TOK_RBRACE); + *ptailp = NULL; + *vtailp = vlist; + vtailp = &vlist->next; + scan (TOK_RBRACE, &tok); + scan (TOK_EQUAL, &tok); + scan_num (&tok); + vlist->vers_num = tok.str; + /* make the argument structure name for each arg */ + for (plist = vlist->procs; plist != NULL; + plist = plist->next) + { + plist->args.argname = make_argname (plist->proc_name, + vlist->vers_num); + /* free the memory ?? */ + } + scan (TOK_SEMICOLON, &tok); + scan2 (TOK_VERSION, TOK_RBRACE, &tok); + } + while (tok.kind == TOK_VERSION); + scan (TOK_EQUAL, &tok); + scan_num (&tok); + defp->def.pr.prog_num = tok.str; + *vtailp = NULL; +} + + +static void +def_enum (definition * defp) +{ + token tok; + enumval_list *elist; + enumval_list **tailp; + + defp->def_kind = DEF_ENUM; + scan (TOK_IDENT, &tok); + defp->def_name = tok.str; + scan (TOK_LBRACE, &tok); + tailp = &defp->def.en.vals; + do + { + scan (TOK_IDENT, &tok); + elist = ALLOC (enumval_list); + elist->name = tok.str; + elist->assignment = NULL; + scan3 (TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); + if (tok.kind == TOK_EQUAL) + { + scan_num (&tok); + elist->assignment = tok.str; + scan2 (TOK_COMMA, TOK_RBRACE, &tok); + } + *tailp = elist; + tailp = &elist->next; + } + while (tok.kind != TOK_RBRACE); + *tailp = NULL; +} + +static void +def_const (definition * defp) +{ + token tok; + + defp->def_kind = DEF_CONST; + scan (TOK_IDENT, &tok); + defp->def_name = tok.str; + scan (TOK_EQUAL, &tok); + scan2 (TOK_IDENT, TOK_STRCONST, &tok); + defp->def.co = tok.str; +} + +static void +def_union (definition *defp) +{ + token tok; + declaration dec; + case_list *cases; +/* case_list *tcase; */ + case_list **tailp; +#if 0 + int flag; +#endif + + defp->def_kind = DEF_UNION; + scan (TOK_IDENT, &tok); + defp->def_name = tok.str; + scan (TOK_SWITCH, &tok); + scan (TOK_LPAREN, &tok); + get_declaration (&dec, DEF_UNION); + defp->def.un.enum_decl = dec; + tailp = &defp->def.un.cases; + scan (TOK_RPAREN, &tok); + scan (TOK_LBRACE, &tok); + scan (TOK_CASE, &tok); + while (tok.kind == TOK_CASE) + { + scan2 (TOK_IDENT, TOK_CHARCONST, &tok); + cases = ALLOC (case_list); + cases->case_name = tok.str; + scan (TOK_COLON, &tok); + /* now peek at next token */ +#if 0 + flag = 0; +#endif + 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)); + } +#if 0 + else if (flag) + { + + *tailp = cases; + tailp = &cases->next; + cases = ALLOC (case_list); + }; +#endif + + get_declaration (&dec, DEF_UNION); + cases->case_decl = dec; + cases->contflag = 0; /* no continued case statement */ + *tailp = cases; + tailp = &cases->next; + scan (TOK_SEMICOLON, &tok); + + scan3 (TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); + } + *tailp = NULL; + if (tok.kind == TOK_DEFAULT) + { + scan (TOK_COLON, &tok); + get_declaration (&dec, DEF_UNION); + defp->def.un.default_decl = ALLOC (declaration); + *defp->def.un.default_decl = dec; + scan (TOK_SEMICOLON, &tok); + scan (TOK_RBRACE, &tok); + } + else + { + defp->def.un.default_decl = NULL; + } +} + +static const char *reserved_words[] = +{ + "array", + "bytes", + "destroy", + "free", + "getpos", + "inline", + "pointer", + "reference", + "setpos", + "sizeof", + "union", + "vector", + NULL +}; + +static const char *reserved_types[] = +{ + "opaque", + "string", + NULL +}; + +/* + * check that the given name is not one that would eventually result in + * xdr routines that would conflict with internal XDR routines. + */ +static void +check_type_name (const char *name, int new_type) +{ + int i; + char tmp[100]; + + for (i = 0; reserved_words[i] != NULL; i++) + { + if (strcmp (name, reserved_words[i]) == 0) + { + sprintf (tmp, + "illegal (reserved) name :\'%s\' in type definition", name); + error (tmp); + } + } + if (new_type) + { + for (i = 0; reserved_types[i] != NULL; i++) + { + if (strcmp (name, reserved_types[i]) == 0) + { + sprintf (tmp, + "illegal (reserved) name :\'%s\' in type definition", name); + error (tmp); + } + } + } +} + + + +static void +def_typedef (definition * defp) +{ + declaration dec; + + defp->def_kind = DEF_TYPEDEF; + get_declaration (&dec, DEF_TYPEDEF); + defp->def_name = dec.name; + check_type_name (dec.name, 1); + defp->def.ty.old_prefix = dec.prefix; + defp->def.ty.old_type = dec.type; + defp->def.ty.rel = dec.rel; + defp->def.ty.array_max = dec.array_max; +} + +static void +get_declaration (declaration * dec, defkind dkind) +{ + token tok; + + get_type (&dec->prefix, &dec->type, dkind); + dec->rel = REL_ALIAS; + if (streq (dec->type, "void")) + { + return; + } + + check_type_name (dec->type, 0); + + scan2 (TOK_STAR, TOK_IDENT, &tok); + if (tok.kind == TOK_STAR) + { + dec->rel = REL_POINTER; + scan (TOK_IDENT, &tok); + } + dec->name = tok.str; + if (peekscan (TOK_LBRACKET, &tok)) + { + if (dec->rel == REL_POINTER) + { + error ("no array-of-pointer declarations -- use typedef"); + } + dec->rel = REL_VECTOR; + scan_num (&tok); + dec->array_max = tok.str; + scan (TOK_RBRACKET, &tok); + } + else if (peekscan (TOK_LANGLE, &tok)) + { + if (dec->rel == REL_POINTER) + { + error ("no array-of-pointer declarations -- use typedef"); + } + dec->rel = REL_ARRAY; + if (peekscan (TOK_RANGLE, &tok)) + { + dec->array_max = "~0"; /* unspecified size, use max */ + } + else + { + scan_num (&tok); + dec->array_max = tok.str; + scan (TOK_RANGLE, &tok); + } + } + if (streq (dec->type, "opaque")) + { + if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) + { + error ("array declaration expected"); + } + } + else if (streq (dec->type, "string")) + { + if (dec->rel != REL_ARRAY) + { + error ("variable-length array declaration expected"); + } + } +} + +static void +get_prog_declaration (declaration * dec, defkind dkind, int num /* arg number */ ) +{ + token tok; + char name[MAXLINESIZE]; /* argument name */ + + if (dkind == DEF_PROGRAM) + { + peek (&tok); + if (tok.kind == TOK_RPAREN) + { /* no arguments */ + dec->rel = REL_ALIAS; + dec->type = "void"; + dec->prefix = NULL; + dec->name = NULL; + return; + } + } + get_type (&dec->prefix, &dec->type, dkind); + dec->rel = REL_ALIAS; + if (peekscan (TOK_IDENT, &tok)) /* optional name of argument */ + strcpy (name, tok.str); + else + sprintf (name, "%s%d", ARGNAME, num); /* default name of argument */ + + dec->name = (char *) strdup (name); + + if (streq (dec->type, "void")) + { + return; + } + + if (streq (dec->type, "opaque")) + { + error ("opaque -- illegal argument type"); + } + if (peekscan (TOK_STAR, &tok)) + { + if (streq (dec->type, "string")) + { + error ("pointer to string not allowed in program arguments\n"); + } + dec->rel = REL_POINTER; + if (peekscan (TOK_IDENT, &tok)) /* optional name of argument */ + dec->name = strdup (tok.str); + } + if (peekscan (TOK_LANGLE, &tok)) + { + if (!streq (dec->type, "string")) + { + error ("arrays cannot be declared as arguments to procedures -- use typedef"); + } + dec->rel = REL_ARRAY; + if (peekscan (TOK_RANGLE, &tok)) + { + dec->array_max = "~0"; /* unspecified size, use max */ + } + else + { + scan_num (&tok); + dec->array_max = tok.str; + scan (TOK_RANGLE, &tok); + } + } + if (streq (dec->type, "string")) + { + if (dec->rel != REL_ARRAY) + { /* .x specifies just string as + * type of argument + * - make it string<> + */ + dec->rel = REL_ARRAY; + dec->array_max = "~0"; /* unspecified size, use max */ + } + } +} + +static void +get_type (const char **prefixp, const char **typep, defkind dkind) +{ + token tok; + + *prefixp = NULL; + get_token (&tok); + switch (tok.kind) + { + case TOK_IDENT: + *typep = tok.str; + break; + case TOK_STRUCT: + case TOK_ENUM: + case TOK_UNION: + *prefixp = tok.str; + scan (TOK_IDENT, &tok); + *typep = tok.str; + break; + case TOK_UNSIGNED: + unsigned_dec (typep); + break; + case TOK_SHORT: + *typep = "short"; + (void) peekscan (TOK_INT, &tok); + break; + case TOK_LONG: + *typep = "long"; + (void) peekscan (TOK_INT, &tok); + break; + case TOK_HYPER: + *typep = "quad_t"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_VOID: + if (dkind != DEF_UNION && dkind != DEF_PROGRAM) + { + error ("voids allowed only inside union and program definitions with one argument"); + } + *typep = tok.str; + break; + case TOK_STRING: + case TOK_OPAQUE: + case TOK_CHAR: + case TOK_INT: + case TOK_FLOAT: + case TOK_DOUBLE: + case TOK_BOOL: + *typep = tok.str; + break; + default: + error ("expected type specifier"); + } +} + +static void +unsigned_dec (const char **typep) +{ + token tok; + + peek (&tok); + switch (tok.kind) + { + case TOK_CHAR: + get_token (&tok); + *typep = "u_char"; + break; + case TOK_SHORT: + get_token (&tok); + *typep = "u_short"; + (void) peekscan (TOK_INT, &tok); + break; + case TOK_LONG: + get_token (&tok); + *typep = "u_long"; + (void) peekscan (TOK_INT, &tok); + break; + case TOK_HYPER: + get_token (&tok); + *typep = "u_quad_t"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_INT: + get_token (&tok); + *typep = "u_int"; + break; + default: + *typep = "u_int"; + break; + } +} diff --git a/tools/rpcgen/rpc_parse.h b/tools/rpcgen/rpc_parse.h new file mode 100644 index 0000000..e2e2f1e --- /dev/null +++ b/tools/rpcgen/rpc_parse.h @@ -0,0 +1,165 @@ +/* @(#)rpc_parse.h 1.3 90/08/29 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * rpc_parse.h, Definitions for the RPCL parser + */ + +enum defkind { + DEF_CONST, + DEF_STRUCT, + DEF_UNION, + DEF_ENUM, + DEF_TYPEDEF, + DEF_PROGRAM +}; +typedef enum defkind defkind; + +typedef const char *const_def; + +enum relation { + REL_VECTOR, /* fixed length array */ + REL_ARRAY, /* variable length array */ + REL_POINTER, /* pointer */ + REL_ALIAS /* simple */ +}; +typedef enum relation relation; + +struct typedef_def { + const char *old_prefix; + const char *old_type; + relation rel; + const char *array_max; +}; +typedef struct typedef_def typedef_def; + +struct enumval_list { + const char *name; + const char *assignment; + struct enumval_list *next; +}; +typedef struct enumval_list enumval_list; + +struct enum_def { + enumval_list *vals; +}; +typedef struct enum_def enum_def; + +struct declaration { + const char *prefix; + const char *type; + const char *name; + relation rel; + const char *array_max; +}; +typedef struct declaration declaration; + +struct decl_list { + declaration decl; + struct decl_list *next; +}; +typedef struct decl_list decl_list; + +struct struct_def { + decl_list *decls; +}; +typedef struct struct_def struct_def; + +struct case_list { + const char *case_name; + int contflag; + declaration case_decl; + struct case_list *next; +}; +typedef struct case_list case_list; + +struct union_def { + declaration enum_decl; + case_list *cases; + declaration *default_decl; +}; +typedef struct union_def union_def; + +struct arg_list { + const char *argname; /* name of struct for arg*/ + decl_list *decls; +}; + +typedef struct arg_list arg_list; + +struct proc_list { + const char *proc_name; + const char *proc_num; + arg_list args; + int arg_num; + const char *res_type; + const char *res_prefix; + struct proc_list *next; +}; +typedef struct proc_list proc_list; + +struct version_list { + const char *vers_name; + const char *vers_num; + proc_list *procs; + struct version_list *next; +}; +typedef struct version_list version_list; + +struct program_def { + const char *prog_num; + version_list *versions; +}; +typedef struct program_def program_def; + +struct definition { + const char *def_name; + defkind def_kind; + union { + const_def co; + struct_def st; + union_def un; + enum_def en; + typedef_def ty; + program_def pr; + } def; +}; +typedef struct definition definition; + +definition *get_definition(void); + + +struct bas_type +{ + const char *name; + int length; + struct bas_type *next; +}; + +typedef struct bas_type bas_type; diff --git a/tools/rpcgen/rpc_sample.c b/tools/rpcgen/rpc_sample.c new file mode 100644 index 0000000..e90b58c --- /dev/null +++ b/tools/rpcgen/rpc_sample.c @@ -0,0 +1,336 @@ +/* + * From: @(#)rpc_sample.c 1.1 90/08/30 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler + */ + +#include <stdio.h> +#include <string.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + + +static const char RQSTP[] = "rqstp"; + +static void write_sample_client (const char *program_name, version_list * vp); +static void write_sample_server (definition * def); +static void return_type (proc_list * plist); + + +void +write_sample_svc (definition * def) +{ + + if (def->def_kind != DEF_PROGRAM) + return; + write_sample_server (def); +} + + +int +write_sample_clnt (definition * def) +{ + version_list *vp; + int count = 0; + + if (def->def_kind != DEF_PROGRAM) + return 0; + /* generate sample code for each version */ + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + write_sample_client (def->def_name, vp); + ++count; + } + return count; +} + + +static void +write_sample_client (const char *program_name, version_list * vp) +{ + proc_list *proc; + int i; + decl_list *l; + + f_print (fout, "\n\nvoid\n"); + pvname (program_name, vp->vers_num); + if (Cflag) + f_print (fout, "(char *host)\n{\n"); + else + f_print (fout, "(host)\nchar *host;\n{\n"); + f_print (fout, "\tCLIENT *clnt;\n"); + + i = 0; + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + f_print (fout, "\t"); + ++i; + if (mtflag) + { + f_print (fout, "enum clnt_stat retval_%d;\n\t", i); + ptype (proc->res_prefix, proc->res_type, 1); + if (!streq (proc->res_type, "void")) + f_print (fout, "result_%d;\n", i); + else + fprintf (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); + f_print (fout, " "); + } + else + f_print (fout, "char *"); /* cannot have "void" type */ + 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 == 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 void +write_sample_server (definition * def) +{ + version_list *vp; + proc_list *proc; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + f_print (fout, "\n"); + if (!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); */ + f_print(fout, " result;\n"); + } + else + f_print(fout, "\tbool_t retval;\n"); + fprintf (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, "\txdr_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\treturn 1;\n}\n"); + } + } +} + + + +static void +return_type (proc_list * plist) +{ + ptype (plist->res_prefix, plist->res_type, 1); +} + +void +add_sample_msg (void) +{ + f_print (fout, "/*\n"); + f_print (fout, " * This is sample code generated by rpcgen.\n"); + f_print (fout, " * These are only templates and you can use them\n"); + f_print (fout, " * as a guideline for developing your own functions.\n"); + f_print (fout, " */\n\n"); +} + +void +write_sample_clnt_main (void) +{ + list *l; + definition *def; + version_list *vp; + + f_print (fout, "\n\n"); + if (Cflag) + f_print (fout, "int\nmain (int argc, char *argv[])\n{\n"); + else + f_print (fout, "int\nmain (argc, argv)\nint argc;\nchar *argv[];\n{\n"); + + f_print (fout, "\tchar *host;"); + f_print (fout, "\n\n\tif (argc < 2) {"); + f_print (fout, "\n\t\tprintf (\"usage: %%s server_host\\n\", argv[0]);\n"); + f_print (fout, "\t\texit (1);\n\t}"); + f_print (fout, "\n\thost = argv[1];\n"); + + for (l = defined; l != NULL; l = l->next) + { + def = l->val; + if (def->def_kind != DEF_PROGRAM) + { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, "\t"); + pvname (def->def_name, vp->vers_num); + f_print (fout, " (host);\n"); + } + } + f_print (fout, "exit (0);\n}\n"); +} diff --git a/tools/rpcgen/rpc_scan.c b/tools/rpcgen/rpc_scan.c new file mode 100644 index 0000000..7de6112 --- /dev/null +++ b/tools/rpcgen/rpc_scan.c @@ -0,0 +1,548 @@ +/* + * From: @(#)rpc_scan.c 1.11 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_scan.c, Scanner for the RPC protocol compiler + * Copyright (C) 1987, Sun Microsystems, Inc. + */ +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" +#include "nls.h" + +#ifndef _ +#define _(String) gettext (String) +#endif + +#define startcomment(where) (where[0] == '/' && where[1] == '*') +#define endcomment(where) (where[-1] == '*' && where[0] == '/') + +static int pushed = 0; /* is a token pushed */ +static token lasttok; /* last token, if pushed */ + +static void unget_token (token * tokp); +static void findstrconst (const char **str, const char **val); +static void findchrconst (const char **str, const char **val); +static void findconst (const char **str, const char **val); +static void findkind (const char **mark, token * tokp); +static int cppline (const char *line); +static int directive (const char *line); +static void printdirective (const char *line); +static void docppline (const char *line, int *lineno, const char **fname); + +/* + * scan expecting 1 given token + */ +void +scan (tok_kind expect, token * tokp) +{ + get_token (tokp); + if (tokp->kind != expect) + expected1 (expect); +} + +/* + * scan expecting any of the 2 given tokens + */ +void +scan2 (tok_kind expect1, tok_kind expect2, token * tokp) +{ + get_token (tokp); + if (tokp->kind != expect1 && tokp->kind != expect2) + { + expected2 (expect1, expect2); + } +} + +/* + * scan expecting any of the 3 given token + */ +void +scan3 (tok_kind expect1, tok_kind expect2, tok_kind expect3, token * tokp) +{ + get_token (tokp); + if (tokp->kind != expect1 && tokp->kind != expect2 + && tokp->kind != expect3) + { + expected3 (expect1, expect2, expect3); + } +} + +/* + * scan expecting a constant, possibly symbolic + */ +void +scan_num (token *tokp) +{ + get_token (tokp); + switch (tokp->kind) + { + case TOK_IDENT: + break; + default: + error (_("constant or identifier expected")); + } +} + +/* + * Peek at the next token + */ +void +peek (token *tokp) +{ + get_token (tokp); + unget_token (tokp); +} + +/* + * Peek at the next token and scan it if it matches what you expect + */ +int +peekscan (tok_kind expect, token *tokp) +{ + peek (tokp); + if (tokp->kind == expect) + { + get_token (tokp); + return 1; + } + return 0; +} + +/* + * Get the next token, printing out any directive that are encountered. + */ +void +get_token (token *tokp) +{ + int commenting; + + if (pushed) + { + pushed = 0; + *tokp = lasttok; + return; + } + commenting = 0; + for (;;) + { + if (*where == 0) + { + for (;;) + { + if (!fgets (curline, MAXLINESIZE, fin)) + { + tokp->kind = TOK_EOF; + *curline = 0; + where = curline; + return; + } + linenum++; + if (commenting) + { + break; + } + else if (cppline (curline)) + { + docppline (curline, &linenum, + &infilename); + } + else if (directive (curline)) + { + printdirective (curline); + } + else + { + break; + } + } + where = curline; + } + else if (isspace (*where)) + { + while (isspace (*where)) + { + where++; /* eat */ + } + } + else if (commenting) + { + for (where++; *where; where++) + { + if (endcomment (where)) + { + where++; + commenting--; + break; + } + } + } + else if (startcomment (where)) + { + where += 2; + commenting++; + } + else + { + break; + } + } + + /* + * 'where' is not whitespace, comment or directive Must be a token! + */ + switch (*where) + { + case ':': + tokp->kind = TOK_COLON; + where++; + break; + case ';': + tokp->kind = TOK_SEMICOLON; + where++; + break; + case ',': + tokp->kind = TOK_COMMA; + where++; + break; + case '=': + tokp->kind = TOK_EQUAL; + where++; + break; + case '*': + tokp->kind = TOK_STAR; + where++; + break; + case '[': + tokp->kind = TOK_LBRACKET; + where++; + break; + case ']': + tokp->kind = TOK_RBRACKET; + where++; + break; + case '{': + tokp->kind = TOK_LBRACE; + where++; + break; + case '}': + tokp->kind = TOK_RBRACE; + where++; + break; + case '(': + tokp->kind = TOK_LPAREN; + where++; + break; + case ')': + tokp->kind = TOK_RPAREN; + where++; + break; + case '<': + tokp->kind = TOK_LANGLE; + where++; + break; + case '>': + tokp->kind = TOK_RANGLE; + where++; + break; + + case '"': + tokp->kind = TOK_STRCONST; + findstrconst (&where, &tokp->str); + break; + case '\'': + tokp->kind = TOK_CHARCONST; + findchrconst (&where, &tokp->str); + break; + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + tokp->kind = TOK_IDENT; + findconst (&where, &tokp->str); + break; + + default: + if (!(isalpha (*where) || *where == '_')) + { + char buf[100]; + char *p; + + s_print (buf, _("illegal character in file: ")); + p = buf + strlen (buf); + if (isprint (*where)) + { + s_print (p, "%c", *where); + } + else + { + s_print (p, "%d", *where); + } + error (buf); + } + findkind (&where, tokp); + break; + } +} + +static void +unget_token (token * tokp) +{ + lasttok = *tokp; + pushed = 1; +} + +static void +findstrconst (const char **str, const char **val) +{ + const char *p; + char *tmp; + int size; + + p = *str; + do + { + p++; + } + while (*p && *p != '"'); + if (*p == 0) + { + error (_("unterminated string constant")); + } + p++; + size = p - *str; + tmp = alloc (size + 1); + strncpy (tmp, *str, size); + tmp[size] = 0; + *val = tmp; + *str = p; +} + +static void +findchrconst (const char **str, const char **val) +{ + const char *p; + char *tmp; + 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")); + } + tmp = alloc (size + 1); + strncpy (tmp, *str, size); + tmp[size] = 0; + *val = tmp; + *str = p; +} + +static void +findconst (const char **str, const char **val) +{ + const char *p; + char *tmp; + int size; + + p = *str; + if (*p == '0' && *(p + 1) == 'x') + { + p++; + do + { + p++; + } + while (isxdigit (*p)); + } + else + { + do + { + p++; + } + while (isdigit (*p)); + } + size = p - *str; + tmp = alloc (size + 1); + strncpy (tmp, *str, size); + tmp[size] = 0; + *val = tmp; + *str = p; +} + +static const token symbols[] = +{ + {TOK_CONST, "const"}, + {TOK_UNION, "union"}, + {TOK_SWITCH, "switch"}, + {TOK_CASE, "case"}, + {TOK_DEFAULT, "default"}, + {TOK_STRUCT, "struct"}, + {TOK_TYPEDEF, "typedef"}, + {TOK_ENUM, "enum"}, + {TOK_OPAQUE, "opaque"}, + {TOK_BOOL, "bool"}, + {TOK_VOID, "void"}, + {TOK_CHAR, "char"}, + {TOK_INT, "int"}, + {TOK_UNSIGNED, "unsigned"}, + {TOK_SHORT, "short"}, + {TOK_LONG, "long"}, + {TOK_HYPER, "hyper"}, + {TOK_FLOAT, "float"}, + {TOK_DOUBLE, "double"}, + {TOK_STRING, "string"}, + {TOK_PROGRAM, "program"}, + {TOK_VERSION, "version"}, + {TOK_EOF, "??????"}, +}; + +static void +findkind (const char **mark, token *tokp) +{ + int len; + const token *s; + const char *str; + char *tmp; + + str = *mark; + for (s = symbols; s->kind != TOK_EOF; s++) + { + len = strlen (s->str); + if (strncmp (str, s->str, len) == 0) + { + if (!isalnum (str[len]) && str[len] != '_') + { + tokp->kind = s->kind; + tokp->str = s->str; + *mark = str + len; + return; + } + } + } + tokp->kind = TOK_IDENT; + for (len = 0; isalnum (str[len]) || str[len] == '_'; len++); + tmp = alloc (len + 1); + strncpy (tmp, str, len); + tmp[len] = 0; + tokp->str = tmp; + *mark = str + len; +} + +static int +cppline (const char *line) +{ + return line == curline && *line == '#'; +} + +static int +directive (const char *line) +{ + return line == curline && *line == '%'; +} + +static void +printdirective (const char *line) +{ + f_print (fout, "%s", line + 1); +} + +static void +docppline (const char *line, int *lineno, const char **fname) +{ + char *file; + int num; + char *p; + + line++; + while (isspace (*line)) + { + line++; + } + num = atoi (line); + while (isdigit (*line)) + { + line++; + } + while (isspace (*line)) + { + line++; + } + if (*line != '"') + { + error (_("preprocessor error")); + } + line++; + p = file = alloc (strlen (line) + 1); + while (*line && *line != '"') + { + *p++ = *line++; + } + if (*line == 0) + { + error (_("preprocessor error")); + } + *p = 0; + if (*file == 0) + { + free (file); + *fname = NULL; + } + else + { + *fname = file; + } + *lineno = num - 1; +} diff --git a/tools/rpcgen/rpc_scan.h b/tools/rpcgen/rpc_scan.h new file mode 100644 index 0000000..9786a51 --- /dev/null +++ b/tools/rpcgen/rpc_scan.h @@ -0,0 +1,104 @@ +/* @(#)rpc_scan.h 1.3 90/08/29 */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * rpc_scan.h, Definitions for the RPCL scanner + */ + +/* + * kinds of tokens + */ +enum tok_kind { + TOK_IDENT, + TOK_CHARCONST, + TOK_STRCONST, + TOK_LPAREN, + TOK_RPAREN, + TOK_LBRACE, + TOK_RBRACE, + TOK_LBRACKET, + TOK_RBRACKET, + TOK_LANGLE, + TOK_RANGLE, + TOK_STAR, + TOK_COMMA, + TOK_EQUAL, + TOK_COLON, + TOK_SEMICOLON, + TOK_CONST, + TOK_STRUCT, + TOK_UNION, + TOK_SWITCH, + TOK_CASE, + TOK_DEFAULT, + TOK_ENUM, + TOK_TYPEDEF, + TOK_INT, + TOK_SHORT, + TOK_LONG, + TOK_HYPER, + TOK_UNSIGNED, + TOK_FLOAT, + TOK_DOUBLE, + TOK_OPAQUE, + TOK_CHAR, + TOK_STRING, + TOK_BOOL, + TOK_VOID, + TOK_PROGRAM, + TOK_VERSION, + TOK_EOF +}; +typedef enum tok_kind tok_kind; + +/* + * a token + */ +struct token { + tok_kind kind; + const char *str; +}; +typedef struct token token; + + +/* + * routine interface + */ +void scan(tok_kind expect, token *tokp); +void scan2(tok_kind expect1, tok_kind expect2, token *tokp); +void scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp); +void scan_num(token *tokp); +void peek(token *tokp); +int peekscan(tok_kind expect, token *tokp); +void get_token(token *tokp); +void expected1(tok_kind exp1) __attribute__ ((noreturn)); +void expected2(tok_kind exp1, tok_kind exp2) __attribute__ ((noreturn)); +void expected3(tok_kind exp1, tok_kind exp2, tok_kind exp3) + __attribute__ ((noreturn)); diff --git a/tools/rpcgen/rpc_svcout.c b/tools/rpcgen/rpc_svcout.c new file mode 100644 index 0000000..4f12a81 --- /dev/null +++ b/tools/rpcgen/rpc_svcout.c @@ -0,0 +1,1093 @@ +/* + * From: @(#)rpc_svcout.c 1.29 89/03/30 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler + */ +#include <stdio.h> +#include <string.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +static const char RQSTP[] = "rqstp"; +static const char TRANSP[] = "transp"; +static const char ARG[] = "argument"; +static const char RESULT[] = "result"; +static const char ROUTINE[] = "local"; +static char RETVAL[] = "retval"; + +char _errbuf[256]; /* For all messages */ + +static void internal_proctype (const proc_list * plist); +static void p_xdrfunc (const char *rname, const char *typename); +static void write_real_program (const definition * def); +static void write_program (const definition * def, const char *storage); +static void printerr (const char *err, const char *transp); +static void printif (const char *proc, const char *transp, const char *arg); +static void write_inetmost (const char *infile); +static void print_return (const char *space); +static void print_pmapunset (const char *space); +static void print_err_message (const char *space); +static void write_timeout_func (void); +static void write_pm_most (const char *infile, int netflag); +static void write_rpc_svc_fg (const char *infile, const char *sp); +static void open_log_file (const char *infile, const char *sp); + +static void +p_xdrfunc (const char *rname, const char *typename) +{ + if (Cflag) + f_print (fout, "\t\t_xdr_%s = (xdrproc_t) xdr_%s;\n", rname, + stringfix (typename)); + else + f_print (fout, "\t\t_xdr_%s = xdr_%s;\n", rname, stringfix (typename)); +} + +void +internal_proctype (const proc_list * plist) +{ + f_print (fout, "static "); + ptype (plist->res_prefix, plist->res_type, 1); + f_print (fout, "*"); +} + + +/* + * write most of the service, that is, everything but the registrations. + */ +void +write_most (const char *infile /* our name */ , int netflag, int nomain) +{ + if (inetdflag || pmflag) + { + const char *var_type; + /* WHY? */ + var_type = (nomain ? "extern" : ""); + 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, "\t\t/* Whether Stream or Datagram ? */\n"); + } + if (timerflag) + { +#if 0 + f_print (fout, "%s int _rpcsvcdirty;", var_type); + f_print (fout, "\t/* Still serving ? */\n"); +#else + 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"); + } +#endif + } + write_svc_aux (nomain); + } + /* write out dispatcher and stubs */ + write_programs (nomain ? NULL : "static"); + + if (nomain) + return; + + if (Cflag) + f_print (fout, "\nint\nmain (int argc, char **argv)\n"); + else + { + f_print (fout, "\nint\nmain (argc, argv)\n"); + f_print (fout, "\tint argc;\n"); + f_print (fout, "\tchar **argv;\n"); + } + f_print (fout, "{\n"); + if (inetdflag) + { + write_inetmost (infile); /* Includes call to write_rpc_svc_fg() */ + } + else + { + if (tirpcflag) + { + if (netflag) + { + f_print (fout, "\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 (const char *transp) +{ + list *l; + definition *def; + version_list *vp; + const 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); + sprintf (_errbuf, "cannot create %s service.", transp); + print_err_message (tmpbuf); + f_print (fout, "%s\t\texit (1);\n", sp); + f_print (fout, "%s\t}\n", sp); + + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) + { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, "%s\t(void) rpcb_unset (%s, %s, nconf);\n", + sp, def->def_name, vp->vers_name); + f_print (fout, "%s\tif (!svc_reg (%s, %s, %s, ", + sp, TRANSP, def->def_name, vp->vers_name); + pvname (def->def_name, vp->vers_num); + f_print (fout, ", nconf)) {\n"); + (void) sprintf (_errbuf, "unable to register (%s, %s, %s).", + def->def_name, vp->vers_name, transp); + print_err_message (tmpbuf); + f_print (fout, "%s\t\texit (1);\n", sp); + f_print (fout, "%s\t}\n", sp); + } + } + f_print (fout, "%s\tfreenetconfigent (nconf);\n", sp); +} + +/* + * write a registration for the given transport for TLI + */ +void +write_nettype_register (const char *transp) +{ + list *l; + definition *def; + version_list *vp; + + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) + { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, "\tif (!svc_create ("); + pvname (def->def_name, vp->vers_num); + f_print (fout, ", %s, %s, \"%s\")) {\n ", + def->def_name, vp->vers_name, transp); + (void) sprintf (_errbuf, + "unable to create (%s, %s) for %s.", + def->def_name, vp->vers_name, transp); + print_err_message ("\t\t"); + f_print (fout, "\t\texit (1);\n"); + f_print (fout, "\t}\n"); + } + } +} + +/* + * write the rest of the service + */ +void +write_rest (void) +{ + f_print (fout, "\n"); + if (inetdflag) + { + f_print (fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP); + (void) sprintf (_errbuf, "could not create a handle"); + print_err_message ("\t\t"); + f_print (fout, "\t\texit (1);\n"); + f_print (fout, "\t}\n"); + if (timerflag) + { + f_print (fout, "\tif (_rpcpmstart) {\n"); + f_print (fout, + "\t\t(void) signal (SIGALRM, %s closedown);\n", + Cflag ? "(SIG_PF)" : "(void(*)())"); + f_print (fout, "\t\t(void) alarm (_RPCSVC_CLOSEDOWN);\n"); + f_print (fout, "\t}\n"); + } + } + f_print (fout, "\tsvc_run ();\n"); + (void) sprintf (_errbuf, "svc_run returned"); + print_err_message ("\t"); + f_print (fout, "\texit (1);\n"); + f_print (fout, "\t/* NOTREACHED */\n"); + f_print (fout, "}\n"); +} + +void +write_programs (const char *storage) +{ + list *l; + definition *def; + + /* write out stubs for procedure definitions */ + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) + { + write_real_program (def); + } + } + + /* write out dispatcher for each program */ + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) + { + write_program (def, storage); + } + } +} + +/* write out definition of internal function (e.g. _printmsg_1(...)) + which calls server's defintion of actual function (e.g. printmsg_1(...)). + Unpacks single user argument of printmsg_1 to call-by-value format + expected by printmsg_1. */ +static void +write_real_program (const 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) + { + fprintf (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, "%s", 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"); + } + f_print (fout, " struct svc_req *%s;\n", RQSTP); + } + + f_print (fout, "{\n"); + f_print (fout, "\treturn ("); + if (Cflag || mtflag) + 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 void +write_program (const definition * def, const char *storage) +{ + version_list *vp; + proc_list *proc; + int filled; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, "\n"); + if (storage != NULL) + { + f_print (fout, "%s ", storage); + } + f_print (fout, "void\n"); + pvname (def->def_name, vp->vers_num); + + if (Cflag) + { + f_print (fout, "(struct svc_req *%s, ", RQSTP); + f_print (fout, "register SVCXPRT *%s)\n", TRANSP); + } + else + { + f_print (fout, "(%s, %s)\n", RQSTP, TRANSP); + f_print (fout, " struct svc_req *%s;\n", RQSTP); + f_print (fout, " register SVCXPRT *%s;\n", TRANSP); + } + + f_print (fout, "{\n"); + + filled = 0; + f_print (fout, "\tunion {\n"); + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + if (proc->arg_num < 2) + { /* single argument */ + if (streq (proc->args.decls->decl.type, + "void")) + { + continue; + } + filled = 1; + f_print (fout, "\t\t"); + ptype (proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + pvname (proc->proc_name, vp->vers_num); + f_print (fout, "_arg;\n"); + + } + else + { + filled = 1; + f_print (fout, "\t\t%s", proc->args.argname); + f_print (fout, " "); + pvname (proc->proc_name, vp->vers_num); + f_print (fout, "_arg;\n"); + } + } + if (!filled) + { + f_print (fout, "\t\tint fill;\n"); + } + f_print (fout, "\t} %s;\n", ARG); + if (mtflag) + { + f_print(fout, "\tunion {\n"); + for (proc = vp->procs; proc != NULL; proc = proc->next) + if (!streq (proc->res_type, "void")) + { + 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"); + + if (timerflag) +#if 0 + f_print (fout, "\t_rpcsvcdirty = 1;\n"); +#else + { + 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"); + } +#endif + + f_print (fout, "\tswitch (%s->rq_proc) {\n", RQSTP); + if (!nullproc (vp->procs)) + { + f_print (fout, "\tcase NULLPROC:\n"); + f_print (fout, + "\t\t(void) svc_sendreply (%s, (xdrproc_t) xdr_void, (char *)NULL);\n", + TRANSP); + print_return ("\t\t"); + f_print (fout, "\n"); + } + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + f_print (fout, "\tcase %s:\n", proc->proc_name); + if (proc->arg_num < 2) + { /* single argument */ + p_xdrfunc (ARG, proc->args.decls->decl.type); + } + else + { + p_xdrfunc (ARG, proc->args.argname); + } + p_xdrfunc (RESULT, proc->res_type); + if (Cflag) + { + 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); + print_return ("\t\t"); + f_print (fout, "\t}\n"); + + f_print (fout, "\tmemset ((char *)&%s, 0, sizeof (%s));\n", ARG, ARG); + printif ("getargs", TRANSP, ARG); + printerr ("decode", TRANSP); + print_return ("\t\t"); + f_print (fout, "\t}\n"); + + 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, (xdrproc_t) _xdr_%s, (char *)&%s)) {\n", + RETVAL, TRANSP, RESULT, RESULT); + else + f_print(fout, + "\tif (%s != NULL && !svc_sendreply(%s, (xdrproc_t) _xdr_%s, %s)) {\n", + RESULT, TRANSP, RESULT, RESULT); + + printerr ("systemerr", TRANSP); + f_print (fout, "\t}\n"); + + printif ("freeargs", TRANSP, ARG); + + sprintf (_errbuf, "unable to free arguments"); + print_err_message ("\t\t"); + f_print (fout, "\t\texit (1);\n"); + f_print (fout, "\t}\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"); + } +} + +static void +printerr (const char *err, const char *transp) +{ + f_print (fout, "\t\tsvcerr_%s (%s);\n", err, transp); +} + +static void +printif (const char *proc, const char *transp, const char *arg) +{ + f_print (fout, "\tif (!svc_%s (%s, (xdrproc_t) _xdr_%s, (caddr_t) &%s)) {\n", + proc, transp, arg, arg); +} + +int +nullproc (const proc_list * proc) +{ + for (; proc != NULL; proc = proc->next) + { + if (streq (proc->proc_num, "0")) + { + return 1; + } + } + return 0; +} + +static void +write_inetmost (const char *infile) +{ + f_print (fout, "\tregister SVCXPRT *%s;\n", TRANSP); + f_print (fout, "\tint sock;\n"); + f_print (fout, "\tint proto;\n"); + f_print (fout, "\tstruct sockaddr_in saddr;\n"); + f_print (fout, "\tint asize = sizeof (saddr);\n"); + f_print (fout, "\n"); + f_print (fout, + "\tif (getsockname (0, (struct sockaddr *)&saddr, &asize) == 0) {\n"); + f_print (fout, "\t\tint ssize = sizeof (int);\n\n"); + f_print (fout, "\t\tif (saddr.sin_family != AF_INET)\n"); + f_print (fout, "\t\t\texit (1);\n"); + f_print (fout, "\t\tif (getsockopt (0, SOL_SOCKET, SO_TYPE,\n"); + f_print (fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n"); + f_print (fout, "\t\t\texit (1);\n"); + f_print (fout, "\t\tsock = 0;\n"); + f_print (fout, "\t\t_rpcpmstart = 1;\n"); + f_print (fout, "\t\tproto = 0;\n"); + open_log_file (infile, "\t\t"); + f_print (fout, "\t} else {\n"); + write_rpc_svc_fg (infile, "\t\t"); + f_print (fout, "\t\tsock = RPC_ANYSOCK;\n"); + print_pmapunset ("\t\t"); + f_print (fout, "\t}\n"); +} + +static void +print_return (const char *space) +{ + if (exitnow) + f_print (fout, "%sexit (0);\n", space); + else + { + if (timerflag) + { +#if 0 + f_print (fout, "%s_rpcsvcdirty = 0;\n", space); +#else + 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); +#endif + } + f_print (fout, "%sreturn;\n", space); + } +} + +static void +print_pmapunset (const 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, "%spmap_unset (%s, %s);\n", + space, def->def_name, vp->vers_name); + } + } + } +} + +static void +print_err_message (const char *space) +{ + if (logflag) + f_print (fout, "%ssyslog (LOG_ERR, \"%%s\", \"%s\");\n", space, _errbuf); + else if (inetdflag || pmflag) + f_print (fout, "%s_msgout (\"%s\");\n", space, _errbuf); + else + f_print (fout, "%sfprintf (stderr, \"%%s\", \"%s\");\n", space, _errbuf); +} + +/* + * Write the server auxiliary function ( _msgout, timeout) + */ +void +write_svc_aux (int nomain) +{ + if (!logflag) + write_msg_out (); + if (!nomain) + write_timeout_func (); +} + +/* + * Write the _msgout function + */ + +void +write_msg_out (void) +{ + f_print (fout, "\n"); + f_print (fout, "static\n"); + if (!Cflag) + { + f_print (fout, "void _msgout (msg)\n"); + f_print (fout, "\tchar *msg;\n"); + } + else + { + f_print (fout, "void _msgout (char* msg)\n"); + } + f_print (fout, "{\n"); + f_print (fout, "#ifdef RPC_SVC_FG\n"); + if (inetdflag || pmflag) + f_print (fout, "\tif (_rpcpmstart)\n"); + f_print (fout, "\t\tsyslog (LOG_ERR, \"%%s\", msg);\n"); + f_print (fout, "\telse\n"); + f_print (fout, "\t\tfprintf (stderr, \"%%s\\n\", msg);\n"); + f_print (fout, "#else\n"); + f_print (fout, "\tsyslog (LOG_ERR, \"%%s\", msg);\n"); + f_print (fout, "#endif\n"); + f_print (fout, "}\n"); +} + +/* + * Write the timeout function + */ +static void +write_timeout_func (void) +{ + if (!timerflag) + return; + f_print (fout, "\n"); + f_print (fout, "static void\n"); + if (Cflag) + f_print (fout, "closedown (int sig)\n"); + else + f_print (fout, "closedown (sig)\n\tint sig;\n"); + f_print (fout, "{\n"); + +#if 0 + f_print (fout, "\t(void) signal (sig, %s closedown);\n", + Cflag ? "(SIG_PF)" : "(void(*)())"); +#endif + if (mtflag) + f_print(fout, "\tmutex_lock(&_svcstate_lock);\n"); +#if 0 + f_print (fout, "\tif (_rpcsvcdirty == 0) {\n"); +#else + f_print(fout, "\tif (_rpcsvcstate == _IDLE) {\n"); +#endif + 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, "\talarm (_RPCSVC_CLOSEDOWN);\n"); + f_print (fout, "}\n"); +} + +/* + * Write the most of port monitor support + */ +static void +write_pm_most (const char *infile, int netflag) +{ + list *l; + definition *def; + version_list *vp; + + f_print (fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n"); + f_print (fout, "\t\t(!strcmp(mname, \"sockmod\") ||"); + f_print (fout, " !strcmp(mname, \"timod\"))) {\n"); + f_print (fout, "\t\tchar *netid;\n"); + if (!netflag) + { /* Not included by -n option */ + f_print (fout, "\t\tstruct netconfig *nconf = NULL;\n"); + f_print (fout, "\t\tSVCXPRT *%s;\n", TRANSP); + } + if (timerflag) + f_print (fout, "\t\tint pmclose;\n"); +/* not necessary, defined in /usr/include/stdlib */ +/* f_print(fout, "\t\textern char *getenv();\n"); */ + f_print (fout, "\n"); + f_print (fout, "\t\t_rpcpmstart = 1;\n"); + if (logflag) + open_log_file (infile, "\t\t"); + f_print (fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n"); + sprintf (_errbuf, "cannot get transport name"); + print_err_message ("\t\t\t"); + f_print (fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n"); + sprintf (_errbuf, "cannot get transport info"); + print_err_message ("\t\t\t"); + f_print (fout, "\t\t}\n"); + /* + * A kludgy support for inetd services. Inetd only works with + * sockmod, and RPC works only with timod, hence all this jugglery + */ + f_print (fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n"); + f_print (fout, "\t\t\tif (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, \"timod\")) {\n"); + sprintf (_errbuf, "could not get the right module"); + print_err_message ("\t\t\t\t"); + f_print (fout, "\t\t\t\texit(1);\n"); + f_print (fout, "\t\t\t}\n"); + f_print (fout, "\t\t}\n"); + if (timerflag) + f_print (fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n"); + f_print (fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n", + TRANSP); + sprintf (_errbuf, "cannot create server handle"); + print_err_message ("\t\t\t"); + f_print (fout, "\t\t\texit(1);\n"); + f_print (fout, "\t\t}\n"); + f_print (fout, "\t\tif (nconf)\n"); + f_print (fout, "\t\t\tfreenetconfigent(nconf);\n"); + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) + { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, + "\t\tif (!svc_reg(%s, %s, %s, ", + TRANSP, def->def_name, vp->vers_name); + pvname (def->def_name, vp->vers_num); + f_print (fout, ", 0)) {\n"); + (void) sprintf (_errbuf, "unable to register (%s, %s).", + def->def_name, vp->vers_name); + print_err_message ("\t\t\t"); + f_print (fout, "\t\t\texit(1);\n"); + f_print (fout, "\t\t}\n"); + } + } + if (timerflag) + { + f_print (fout, "\t\tif (pmclose) {\n"); + f_print (fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n", + Cflag ? "(SIG_PF)" : "(void(*)())"); + f_print (fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); + f_print (fout, "\t\t}\n"); + } + f_print (fout, "\t\tsvc_run();\n"); + f_print (fout, "\t\texit(1);\n"); + f_print (fout, "\t\t/* NOTREACHED */\n"); + f_print (fout, "\t}\n"); +} + +/* + * Support for backgrounding the server if self started. + */ +static void +write_rpc_svc_fg (const char *infile, const char *sp) +{ + f_print (fout, "#ifndef RPC_SVC_FG\n"); + f_print (fout, "%sint size;\n", sp); + if (tirpcflag) + f_print (fout, "%sstruct rlimit rl;\n", sp); + if (inetdflag) + f_print (fout, "%sint pid, i;\n\n", sp); + f_print (fout, "%spid = fork();\n", sp); + f_print (fout, "%sif (pid < 0) {\n", sp); + f_print (fout, "%s\tperror(\"cannot fork\");\n", sp); + f_print (fout, "%s\texit(1);\n", sp); + f_print (fout, "%s}\n", sp); + f_print (fout, "%sif (pid)\n", sp); + f_print (fout, "%s\texit(0);\n", sp); + /* get number of file descriptors */ + if (tirpcflag) + { + f_print (fout, "%srl.rlim_max = 0;\n", sp); + f_print (fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp); + f_print (fout, "%sif ((size = rl.rlim_max) == 0)\n", sp); + f_print (fout, "%s\texit(1);\n", sp); + } + else + { + f_print (fout, "%ssize = getdtablesize();\n", sp); + } + + f_print (fout, "%sfor (i = 0; i < size; i++)\n", sp); + f_print (fout, "%s\t(void) close(i);\n", sp); + /* Redirect stderr and stdout to console */ + f_print (fout, "%si = open(\"/dev/console\", 2);\n", sp); + f_print (fout, "%s(void) dup2(i, 1);\n", sp); + f_print (fout, "%s(void) dup2(i, 2);\n", sp); + /* This removes control of the controlling terminal */ + if (tirpcflag) + f_print (fout, "%ssetsid();\n", sp); + else + { + f_print (fout, "%si = open(\"/dev/tty\", 2);\n", sp); + f_print (fout, "%sif (i >= 0) {\n", sp); + f_print (fout, "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);; + f_print (fout, "%s\t(void) close(i);\n", sp); + f_print (fout, "%s}\n", sp); + } + if (!logflag) + open_log_file (infile, sp); + f_print (fout, "#endif\n"); + if (logflag) + open_log_file (infile, sp); +} + +static void +open_log_file (const char *infile, const 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 (const char *transp) +{ + list *l; + definition *def; + version_list *vp; + const char *sp; + int isudp; + char tmpbuf[32]; + + if (inetdflag) + sp = "\t"; + else + sp = ""; + if (streq (transp, "udp") || streq (transp, "udp6")) + 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/tools/rpcgen/rpc_tblout.c b/tools/rpcgen/rpc_tblout.c new file mode 100644 index 0000000..a7d2f43 --- /dev/null +++ b/tools/rpcgen/rpc_tblout.c @@ -0,0 +1,178 @@ +/* + * From: @(#)rpc_tblout.c 1.4 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler + */ +#include <stdio.h> +#include <string.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +#define TABSIZE 8 +#define TABCOUNT 5 +#define TABSTOP (TABSIZE*TABCOUNT) + +static const char tabstr[TABCOUNT + 1] = "\t\t\t\t\t"; + +static const char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n"; +static const char tbl_end[] = "};\n"; + +static const 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 const char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n"; + +static void write_table (const definition * def); +static void printit (const char *prefix, const char *type); + +void +write_tables (void) +{ + list *l; + definition *def; + + f_print (fout, "\n"); + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) + { + write_table (def); + } + } +} + +static void +write_table (const definition * def) +{ + version_list *vp; + proc_list *proc; + int current; + int expected; + char progvers[100]; + int warning; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + warning = 0; + s_print (progvers, "%s_%s", + locase (def->def_name), vp->vers_num); + /* print the table header */ + f_print (fout, tbl_hdr, progvers); + + if (nullproc (vp->procs)) + { + expected = 0; + } + else + { + expected = 1; + f_print (fout, null_entry); + } + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + current = atoi (proc->proc_num); + if (current != expected++) + { + f_print (fout, + "\n/*\n * WARNING: table out of order\n */\n"); + if (warning == 0) + { + f_print (stderr, + "WARNING %s table is out of order\n", + progvers); + warning = 1; + nonfatalerrors = 1; + } + expected = current + 1; + } + f_print (fout, "\n\t(char *(*)())RPCGEN_ACTION("); + + /* routine to invoke */ + if (Cflag && !newstyle) + pvname_svc (proc->proc_name, vp->vers_num); + else + { + if (newstyle) + f_print (fout, "_"); /* calls internal func */ + pvname (proc->proc_name, vp->vers_num); + } + f_print (fout, "),\n"); + + /* argument info */ + if (proc->arg_num > 1) + printit ((char *) NULL, proc->args.argname); + else + /* do we have to do something special for newstyle */ + printit (proc->args.decls->decl.prefix, + proc->args.decls->decl.type); + /* result info */ + printit (proc->res_prefix, proc->res_type); + } + + /* print the table trailer */ + f_print (fout, tbl_end); + f_print (fout, tbl_nproc, progvers, progvers, progvers); + } +} + +static void +printit (const char *prefix, const 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/tools/rpcgen/rpc_util.c b/tools/rpcgen/rpc_util.c new file mode 100644 index 0000000..52aa697 --- /dev/null +++ b/tools/rpcgen/rpc_util.c @@ -0,0 +1,525 @@ +/* + * From: @(#)rpc_util.c 1.11 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_util.c, Utility routines for the RPC protocol compiler + */ +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +#define ARGEXT "argument" + +char curline[MAXLINESIZE]; /* current read line */ +const char *where = curline; /* current point in line */ +int linenum = 0; /* current line number */ + +const char *infilename; /* input filename */ + +#define NFILES 7 +const char *outfiles[NFILES]; /* output file names */ +int nfiles; + +FILE *fout; /* file pointer of current output */ +FILE *fin; /* file pointer of current input */ + +list *defined; /* list of defined things */ + +static int findit (const definition * def, const char *type); +static const char *fixit (const char *type, const char *orig); +static int typedefed (const definition * def, const char *type); +static const char *toktostr (tok_kind kind); +static void printbuf (void); +static void printwhere (void); + +/* + * Reinitialize the world + */ +void +reinitialize (void) +{ + memset (curline, 0, MAXLINESIZE); + where = curline; + linenum = 0; + defined = NULL; +} + +/* + * string equality + */ +int +streq (const char *a, const char *b) +{ + return strcmp (a, b) == 0; +} + +/* + * find a value in a list + */ +definition * +findval (list *lst, const char *val, + int (*cmp) (const definition *, const char *)) +{ + + for (; lst != NULL; lst = lst->next) + { + if (cmp (lst->val, val)) + { + return lst->val; + } + } + return NULL; +} + +/* + * store a value in a list + */ +void +storeval (list **lstp, definition *val) +{ + list **l; + list *lst; + + + for (l = lstp; *l != NULL; l = (list **) & (*l)->next); + lst = ALLOC (list); + lst->val = val; + lst->next = NULL; + *l = lst; +} + +static int +findit (const definition * def, const char *type) +{ + return streq (def->def_name, type); +} + +static const char * +fixit (const char *type, const char *orig) +{ + definition *def; + + def = findval (defined, type, findit); + if (def == NULL || def->def_kind != DEF_TYPEDEF) + { + return orig; + } + switch (def->def.ty.rel) + { + case REL_VECTOR: + 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: + return orig; + } +} + +const char * +fixtype (const char *type) +{ + return fixit (type, type); +} + +const char * +stringfix (const char *type) +{ + if (streq (type, "string")) + { + return "wrapstring"; + } + else + { + return type; + } +} + +void +ptype (const char *prefix, const char *type, int follow) +{ + if (prefix != NULL) + { + if (streq (prefix, "enum")) + { + f_print (fout, "enum "); + } + else + { + f_print (fout, "struct "); + } + } + if (streq (type, "bool")) + { + f_print (fout, "bool_t "); + } + else if (streq (type, "string")) + { + f_print (fout, "char *"); + } + else + { + f_print (fout, "%s ", follow ? fixtype (type) : type); + } +} + +static int +typedefed (const definition * def, const char *type) +{ + if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) + { + return 0; + } + else + { + return streq (def->def_name, type); + } +} + +int +isvectordef (const char *type, relation rel) +{ + definition *def; + + for (;;) + { + switch (rel) + { + case REL_VECTOR: + return !streq (type, "string"); + case REL_ARRAY: + return 0; + case REL_POINTER: + return 0; + case REL_ALIAS: + def = findval (defined, type, typedefed); + if (def == NULL) + { + return 0; + } + type = def->def.ty.old_type; + rel = def->def.ty.rel; + } + } +} + +char * +locase (const char *str) +{ + char c; + static char buf[100]; + char *p = buf; + + while ((c = *str++) != 0) + { + *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; + } + *p = 0; + return buf; +} + +void +pvname_svc (const char *pname, const char *vnum) +{ + f_print (fout, "%s_%s_svc", locase (pname), vnum); +} + +void +pvname (const char *pname, const char *vnum) +{ + f_print (fout, "%s_%s", locase (pname), vnum); +} + +/* + * print a useful (?) error message, and then die + */ +void +error (const char *msg) +{ + printwhere (); + f_print (stderr, "%s, line %d: ", infilename, linenum); + f_print (stderr, "%s\n", msg); + crash (); +} + +/* + * Something went wrong, unlink any files that we may have created and then + * die. + */ +void +crash (void) +{ + int i; + + for (i = 0; i < nfiles; i++) + { + unlink (outfiles[i]); + } + exit (1); +} + +void +record_open (const char *file) +{ + if (nfiles < NFILES) + { + outfiles[nfiles++] = file; + } + else + { + f_print (stderr, "too many files!\n"); + crash (); + } +} + +static char expectbuf[100]; + +/* + * error, token encountered was not the expected one + */ +void +expected1 (tok_kind exp1) +{ + s_print (expectbuf, "expected '%s'", + toktostr (exp1)); + error (expectbuf); +} + +/* + * error, token encountered was not one of two expected ones + */ +void +expected2 (tok_kind exp1, tok_kind exp2) +{ + s_print (expectbuf, "expected '%s' or '%s'", + toktostr (exp1), + toktostr (exp2)); + error (expectbuf); +} + +/* + * error, token encountered was not one of 3 expected ones + */ +void +expected3 (tok_kind exp1, tok_kind exp2, tok_kind exp3) +{ + s_print (expectbuf, "expected '%s', '%s' or '%s'", + toktostr (exp1), + toktostr (exp2), + toktostr (exp3)); + error (expectbuf); +} + +void +tabify (FILE * f, int tab) +{ + while (tab--) + { + (void) fputc ('\t', f); + } +} + + +static const token tokstrings[] = +{ + {TOK_IDENT, "identifier"}, + {TOK_CONST, "const"}, + {TOK_RPAREN, ")"}, + {TOK_LPAREN, "("}, + {TOK_RBRACE, "}"}, + {TOK_LBRACE, "{"}, + {TOK_LBRACKET, "["}, + {TOK_RBRACKET, "]"}, + {TOK_STAR, "*"}, + {TOK_COMMA, ","}, + {TOK_EQUAL, "="}, + {TOK_COLON, ":"}, + {TOK_SEMICOLON, ";"}, + {TOK_UNION, "union"}, + {TOK_STRUCT, "struct"}, + {TOK_SWITCH, "switch"}, + {TOK_CASE, "case"}, + {TOK_DEFAULT, "default"}, + {TOK_ENUM, "enum"}, + {TOK_TYPEDEF, "typedef"}, + {TOK_INT, "int"}, + {TOK_SHORT, "short"}, + {TOK_LONG, "long"}, + {TOK_UNSIGNED, "unsigned"}, + {TOK_DOUBLE, "double"}, + {TOK_FLOAT, "float"}, + {TOK_CHAR, "char"}, + {TOK_STRING, "string"}, + {TOK_OPAQUE, "opaque"}, + {TOK_BOOL, "bool"}, + {TOK_VOID, "void"}, + {TOK_PROGRAM, "program"}, + {TOK_VERSION, "version"}, + {TOK_EOF, "??????"} +}; + +static const char * +toktostr (tok_kind kind) +{ + const token *sp; + + for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++); + return sp->str; +} + +static void +printbuf (void) +{ + char c; + int i; + int cnt; + +#define TABSIZE 4 + + for (i = 0; (c = curline[i]) != 0; i++) + { + if (c == '\t') + { + cnt = 8 - (i % TABSIZE); + c = ' '; + } + else + { + cnt = 1; + } + while (cnt--) + { + (void) fputc (c, stderr); + } + } +} + +static void +printwhere (void) +{ + int i; + char c; + int cnt; + + printbuf (); + for (i = 0; i < where - curline; i++) + { + c = curline[i]; + if (c == '\t') + { + cnt = 8 - (i % TABSIZE); + } + else + { + cnt = 1; + } + while (cnt--) + { + (void) fputc ('^', stderr); + } + } + (void) fputc ('\n', stderr); +} + +char * +make_argname (const char *pname, const char *vname) +{ + char *name; + + name = malloc (strlen (pname) + strlen (vname) + strlen (ARGEXT) + 3); + if (!name) + { + fprintf (stderr, "failed in malloc"); + exit (1); + } + sprintf (name, "%s_%s_%s", locase (pname), vname, ARGEXT); + return name; +} + +bas_type *typ_list_h; +bas_type *typ_list_t; + +void +add_type (int len, const char *type) +{ + bas_type *ptr; + + + if ((ptr = malloc (sizeof (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 (const 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/tools/rpcgen/rpc_util.h b/tools/rpcgen/rpc_util.h new file mode 100644 index 0000000..53316d9 --- /dev/null +++ b/tools/rpcgen/rpc_util.h @@ -0,0 +1,154 @@ +/* @(#)rpc_util.h 1.5 90/08/29 */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * rpc_util.h, Useful definitions for the RPC protocol compiler + */ + +#include <stdlib.h> + +#define alloc(size) malloc((unsigned)(size)) +#define ALLOC(object) (object *) malloc(sizeof(object)) + +#define s_print (void) sprintf +#define f_print (void) fprintf + +struct list { + definition *val; + struct list *next; +}; +typedef struct list list; + +struct xdrfunc { + char *name; + int pointerp; + struct xdrfunc *next; +}; +typedef struct xdrfunc xdrfunc; + +#define PUT 1 +#define GET 2 + +/* + * Global variables + */ +#define MAXLINESIZE 1024 +extern char curline[MAXLINESIZE]; +extern const char *where; +extern int linenum; + +extern const char *infilename; +extern FILE *fout; +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; /* C++ flag */ +extern int CCflag; /* C++ flag */ +extern int tirpcflag; /* flag for generating tirpc code */ +extern int inlineflag; /* 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; + +/* + * rpc_util routines + */ +void storeval(list **lstp, definition *val); +#define STOREVAL(list,item) storeval(list,item) + +definition *findval(list *lst, const char *val, + int (*cmp)(const definition *, const char *)); +#define FINDVAL(list,item,finder) findval(list, item, finder) + +const char *fixtype(const char *type); +const char *stringfix(const char *type); +char *locase(const char *str); +void pvname_svc(const char *pname, const char *vnum); +void pvname(const char *pname, const char *vnum); +void ptype(const char *prefix, const char *type, int follow); +int isvectordef(const char *type, relation rel); +int streq(const char *a, const char *b); +void error(const char *msg); +void tabify(FILE *f, int tab); +void record_open(const char *file); +bas_type *find_type(const char *type); + + +/* + * rpc_cout routines + */ +void emit(definition *def); + +/* + * rpc_hout routines + */ +void print_datadef(definition *def); +void print_funcdef(definition *def); + +/* + * rpc_svcout routines + */ +void write_most(const char *infile, int netflag, int nomain); +void write_register(void); +void write_rest(void); +void write_programs(const char *storage); +void write_svc_aux(int nomain); +void write_inetd_register(const char *transp); +void write_netid_register(const char *); +void write_nettype_register(const char *); +/* + * rpc_clntout routines + */ +void write_stubs(void); + +/* + * rpc_tblout routines + */ +void write_tables(void); diff --git a/tools/rpcgen/rpcgen.1 b/tools/rpcgen/rpcgen.1 new file mode 100644 index 0000000..9db1b4a --- /dev/null +++ b/tools/rpcgen/rpcgen.1 @@ -0,0 +1,442 @@ +.\" @(#)rpcgen.new.1 1.1 90/11/09 TIRPC 1.0; from 40.10 of 10/10/89 +.\" Copyright (c) 1988,1990 Sun Microsystems, Inc. - All Rights Reserved. +.nr X +.if \nX=0 .ds x} rpcgen 1 "" "\&" +.if \nX=1 .ds x} rpcgen 1 "" +.if \nX=2 .ds x} rpcgen 1 "" "\&" +.if \nX=3 .ds x} rpcgen "" "" "\&" +.TH \*(x} +.SH NAME +\f4rpcgen\f1 \- an RPC protocol compiler +.SH SYNOPSIS +.ft 4 +.nf +rpcgen \f2infile\f4 +.fi +.ft 1 +.br +.ft 4 +.nf +rpcgen [\-D\f2name\f4[=\f2value\f4]] [\-T] [\-K \f2secs\fP] \f2infile\f4 +.fi +.ft 1 +.br +.ft 4 +.nf +rpcgen \-c|\-h|\-l|\-m|\-M|\-t [\-o \f2outfile\f4 ] \f2infile\f4 +.fi +.ft 1 +.br +.ft 4 +.nf +rpcgen [\-I] \-s \f2nettype\f4 [\-o \f2outfile\f4] \f2infile\f4 +.fi +.ft 1 +.br +.ft 4 +.nf +rpcgen \-n \f2netid\f4 [\-o \f2outfile\f4] \f2infile\f4 +.ft 1 +.SH DESCRIPTION +.P +\f4rpcgen\f1 +is a tool that generates C code to implement an RPC protocol. +The input to +\f4rpcgen\f1 +is a language similar to C known as +RPC Language (Remote Procedure Call Language). +.P +\f4rpcgen\f1 +is normally used as in the first synopsis where +it takes an input file and generates up to four output files. +If the +\f2infile\f1 +is named +\f4proto.x\f1, +then +\f4rpcgen\f1 +will generate a header file in +\f4proto.h\f1, +XDR routines in +\f4proto_xdr.c\f1, +server-side stubs in +\f4proto_svc.c\f1, +and client-side stubs in +\f4proto_clnt.c\f1. +With the +\f4\-T\f1 +option, +it will also generate the RPC dispatch table in +\f4proto_tbl.i\f1. +With the +\f4\-Sc\f1 +option, +it will also generate sample code which would illustrate how to use the +remote procedures on the client side. This code would be created in +\f4proto_client.c\f1. +With the +\f4\-Ss\f1 +option, +it will also generate a sample server code which would illustrate how to write +the remote procedures. This code would be created in +\f4proto_server.c\f1. +.P +The server created can be started both by the port monitors +(for example, \f4inetd\f1 or \f4listen\f1) +or by itself. +When it is started by a port monitor, +it creates servers only for the transport for which +the file descriptor \f40\fP was passed. +The name of the transport must be specified +by setting up the environmental variable +\f4PM_TRANSPORT\f1. +When the server generated by +\f4rpcgen\f1 +is executed, +it creates server handles for all the transports +specified in +\f4NETPATH\f1 +environment variable, +or if it is unset, +it creates server handles for all the visible transports from +\f4/etc/netconfig\f1 +file. +Note: +the transports are chosen at run time and not at compile time. +.P +When built for a port monitor (\f4rpcgen\f1 \f4\-I\f1), and that the server +is self-started, it backgrounds itself by default. A special define symbol +\f4RPC_SVC_FG\f1 can be used to run the server process in foreground. +.P +The second synopsis provides special features which allow +for the creation of more sophisticated RPC servers. +These features include support for user provided +\f4#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. +.P +The other three synopses shown above are used when +one does not want to generate all the output files, +but only a particular one. +Some examples of their usage is described in the +EXAMPLE +section below. +When +\f4rpcgen\f1 +is executed with the +\f4\-s\f1 +option, +it creates servers for that particular class of transports. +When +executed with the +\f4\-n\f1 +option, +it creates a server for the transport specified by +\f2netid\f1. +If +\f2infile\f1 +is not specified, +\f4rpcgen\f1 +accepts the standard input. +.P +The C preprocessor, +\f4cc \-E\f1 +[see \f4cc\fP(1)], +is run on the input file before it is actually interpreted by +\f4rpcgen\f1. +For each type of output file, +\f4rpcgen\f1 +defines a special preprocessor symbol for use by the +\f4rpcgen\f1 +programmer: +.P +.PD 0 +.TP 12 +\f4RPC_HDR\f1 +defined when compiling into header files +.TP +\f4RPC_XDR\f1 +defined when compiling into XDR routines +.TP +\f4RPC_SVC\f1 +defined when compiling into server-side stubs +.TP +\f4RPC_CLNT\f1 +defined when compiling into client-side stubs +.TP +\f4RPC_TBL\f1 +defined when compiling into RPC dispatch tables +.PD +.P +Any line beginning with +`\f4%\f1' +is passed directly into the output file, +uninterpreted by +\f4rpcgen\f1. +.P +For every data type referred to in +\f2infile\f1, +\f4rpcgen\f1 +assumes that there exists a +routine with the string +\f4xdr_\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 +.P +The following options are available: +.TP +\f4\-a\f1 +Generate all the files including sample code for client and server side. +.TP +\f4\-b\f1 +This generates code for the SunOS4.1 style of rpc. It is +for backward compatibility. This is the default. +.TP +\f4\-5\f1 +This generates code for the SysVr4 style of rpc. It is used by the +Transport Independent RPC that is in Svr4 systems. +By default rpcgen generates code for SunOS4.1 stype of rpc. +.TP +\f4\-c\f1 +Compile into XDR routines. +.TP +\f4\-C\f1 +Generate code in ANSI C. This option also generates code that could be +compiled with the C++ compiler. This is the default. +.TP +\f4\-k\f1 +Generate code in K&R C. The default is ANSI C. +.TP +\f4\-D\f2name\f4[=\f2value\f4]\f1 +Define a symbol +\f2name\f1. +Equivalent to the +\f4#define\f1 +directive in the source. +If no +\f2value\f1 +is given, +\f2value\f1 +is defined as \f41\f1. +This option may be specified more than once. +.TP +\f4\-h\f1 +Compile into +\f4C\f1 +data-definitions (a header file). +\f4\-T\f1 +option can be used in conjunction to produce a +header file which supports RPC dispatch tables. +.TP +\f4\-I\f1 +Generate a service that can be started from inetd. The default is +to generate a static service that handles transports selected with \f4\-s\f1. +Using \f4\-I\f1 allows starting a service by either method. +.TP +\f4-K\f2 secs\f1 +By default, services created using \f4rpcgen\fP wait \f4120\fP seconds +after servicing a request before exiting. +That interval can be changed using the \f4-K\fP flag. +To create a server that exits immediately upon servicing a request, +\f4-K\ 0\fP can be used. +To create a server that never exits, the appropriate argument is +\f4-K\ -1\fP. +.IP +When monitoring for a server, +some portmonitors, like +\f4listen\fP(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, \f4rpcgen\fP should be used with \f4-K\ -1\fP. +.TP +\f4\-l\f1 +Compile into client-side stubs. +.TP +\f4\-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 +\f4\-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. +.TP +\f4\-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 +\f4\-N\f1 +Use the newstyle of rpcgen. This allows procedures to have multiple arguments. +It also uses the style of parameter passing that closely resembles C. So, when +passing an argument to a remote procedure you do not have to pass a pointer to +the argument but the argument itself. This behaviour is different from the oldstyle +of rpcgen generated code. The newstyle is not the default case because of +backward compatibility. +.TP +\f4\-o \f2outfile\f1 +Specify the name of the output file. +If none is specified, +standard output is used +(\f4\-c\f1, +\f4\-h\f1, +\f4\-l\f1, +\f4\-m\f1, +\f4\-n\f1, +\f4\-s\f1, +\f4\-Sc\f1, +\f4\-Sm\f1, +\f4\-Ss\f1, +and +\f4\-t\f1 +modes only). +.TP +\f4\-s \f2nettype\f1 +Compile into server-side stubs for all the +transports belonging to the class +\f2nettype\f1. +The supported classes are +\f4netpath\f1, +\f4visible\f1, +\f4circuit_n\f1, +\f4circuit_v\f1, +\f4datagram_n\f1, +\f4datagram_v\f1, +\f4tcp\f1, +and +\f4udp\f1 +[see \f4rpc\fP(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 +\f4\-Sc\f1 +Generate sample code to show the use of remote procedure and how to bind +to the server before calling the client side stubs generated by rpcgen. +.TP +\f4\-Sm\f1 +Generate a sample Makefile which can be used for compiling the application. +.TP +\f4\-Ss\f1 +Generate skeleton code for the remote procedures on the server side. You would need +to fill in the actual code for the remote procedures. +.TP +\f4\-t\f1 +Compile into RPC dispatch table. +.TP +\f4\-T\f1 +Generate the code to support RPC dispatch tables. +.P +The options +\f4\-c\f1, +\f4\-h\f1, +\f4\-l\f1, +\f4\-m\f1, +\f4\-s\f1 +and +\f4\-t\f1 +are used exclusively to generate a particular type of file, +while the options +\f4\-D\f1 +and +\f4\-T\f1 +are global and can be used with the other options. +.br +.ne 5 +.SH NOTES +The RPC Language does not support nesting of structures. +As a work-around, +structures can be declared at the top-level, +and their name used inside other structures in +order to achieve the same effect. +.P +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. +.P +The server code generated with +\f4\-n\f1 +option refers to the transport indicated by +\f2netid\f1 +and hence is very site specific. +.SH EXAMPLE +The following example: +.IP +.ft 4 +$ rpcgen \-T prot.x +.ft 1 +.P +generates the five files: +\f4prot.h\f1, +\f4prot_clnt.c\f1, +\f4prot_svc.c\f1, +\f4prot_xdr.c\f1 +and +\f4prot_tbl.i\f1. +.P +The following example sends the C data-definitions (header file) +to the standard output. +.IP +.ft 4 +$ rpcgen \-h prot.x +.ft 1 +.P +To send the test version of the +\f4-DTEST\f1, +server side stubs for +all the transport belonging to the class +\f4datagram_n\f1 +to standard output, use: +.IP +.ft 4 +$ rpcgen \-s datagram_n \-DTEST prot.x +.ft 1 +.P +To create the server side stubs for the transport indicated +by +\f2netid\f1 +\f4tcp\f1, +use: +.IP +.ft 4 +$ rpcgen \-n tcp \-o prot_svc.c prot.x +.ft 1 +.SH "SEE ALSO" +\f4cc\fP(1). |