11 Commits

Author SHA1 Message Date
c0e0e9b80a WIP: rpcgen, pollts 2018-03-25 23:13:32 +02:00
Arne Welzel
35b65c5af1 minix/tests/arm: naive tests to cause data aborts
Some assembly code to cause unaligned access as well as
segmentation faults to exercise the data abort path.

Change-Id: Ie419114b76a8db849537a94fda781019cf14d50d
2018-03-25 17:44:11 +02:00
Arne Welzel
0dd719f1bd kernel/arm: send SIGSEGV to processes
On second thought, handle unknown faults caused by processes by sending
SIGSEGV to them instead of bringing the whole system to a grind.

arm/archconst: use values defined in armreg.h

Change-Id: Ieed5bb06910ab0c8eef1e68b0b4eec680867acd3
2018-03-25 15:16:29 +02:00
Arne Welzel
5e9e5b98f6 bsd.own.mk: use -mno-unaligned-access on ARM
Without this option, gcc may emit code accessing unaligned memory. This,
and the fact that SCTRL.A (System Control Register - Alignment Check) is
set to 1 in Minix causes data aborts when such code is encountered.

This was the cause of #104. The `minix-service' executable caused
unaligned memory accesses calling into getpwnam(). These then trigger
data abort exceptions. On ARM, these were previously forwarded to `vm'
as pagefaults. However, `vm' did not properly handle them, but instead
allocated one page for the faulting address (over and over again) and
then resumed the process at the faulting instruction (over and over
again). This behavior masked the whole story as an OOM.

Below the assembly version getpwent.c in which unaligned memory
accesses are even highlighted...

 ...
 341         ldr     lr, [sp, #48]
 342         cmp     lr, #0
 343         bne     .L46
 344         ldr     r0, [r4]        @ unaligned
 345         add     r1, r7, #5
 346         str     r0, [sp, #4]    @ unaligned
 347         ldr     r4, [sp, #4]
 348         mov     r5, r4, asr #31
 349         strd    r4, [r8, #40]
 ...

This should fix #104. It was tested on an actual Beaglebone Black.

An alternative fix would be to disable alignment checking by setting
SCTRL.A to 0 and allowing unaligned memory accesses.

Change-Id: I4d366eb0af1b2936bca369fd28014fb829228ad5
2018-03-25 11:23:21 +02:00
Arne Welzel
7c3424c244 kernel/arm: do not treat all data aborts as pagefaults
For now, distinguish alignment, translation and permission faults.
The first kind of faults cause the kernel to send SIGBUS to the
process causing the fault, the latter two are forwarded to `vm' as
pagefaults. Previously, any data abort was forwarded to `vm' as
a pagefault, resulting in hard to debug issue #104.

Any unhandled fault status results in a disaster. This seems
better than naively hoping `vm' can do something about it.

Change-Id: I526f575bb2681e087e20fd49c5c0846cdd450c31
2018-03-25 11:22:35 +02:00
Marcelo Alencar
a27e58e1f7 Fix brazilian ABNT2 keymap
This adds two missing keys (0x73 and 0x7e) and fixes KP_PERIOD (it
should type a comma, not a period), as mentioned in

https://groups.google.com/d/msg/minix3/Pezep_HOL3I/mnfZXAeLsTMJ

Closes #247

Change-Id: Id85d04e36adcaa1a502cac8e5013396ea92502fe
2018-03-23 07:38:56 +01:00
blackdragonepic
4667c87c4d remove a duplicate include
removed #include <minix/type.h> duplicate

Closes #246

Change-Id: Icd575c452d562eb601133157a77d9d995ce043e9
2018-03-23 07:38:25 +01:00
Nik Nyby
2117e99cef Update usage man page: remove reference to /usr/ast
This directory no longer exists, probably since the netbsd file layout
re-organization.

Closes #244

Change-Id: Ie4e3761dbf3adbdd76cb6323f920a4abab6b29d5
2018-03-23 07:37:54 +01:00
Nik Nyby
9866ad31fd fs/mfs: Remove a few assert.h includes
Those are unnecessary.

Closes #241

Change-Id: I26db0f07c65e7d078e642001b97e6d4313e6660a
2018-03-23 07:36:59 +01:00
Nik Nyby
24f3305be0 mkfs.mfs: fix typo in error message
Closes #242

Change-Id: I91ec2b36b2abfa897a43c97d886578fd28a5c768
2018-03-23 07:33:25 +01:00
Krystian Lewandowski
b2ee0702ff pci server crashes during boot on Qubes OS
I tried to launch Minix3 in Qubes OS. While there is no problem to boot
minix as a qube (in Qubes OS terminology) before 3641562, it fails with
the commit (and after). I didn't digg into PCI handling but this change
fixes the problem. Minix handles NULL case from pci_subclass_name.

Change-Id: I162424d92b613598e6eb845a71f90a02e31041db
2017-11-16 23:05:02 +01:00
39 changed files with 6844 additions and 33 deletions

View File

@@ -0,0 +1,9 @@
#
# Sorted using sort_set.pl in releasetools.
# to add an entry simply add it at the end of the
# file and run
# ../../../../releasetools/sort_set.pl < mi > out
# mv out mi
#
./usr/tests/minix-posix/test_arm_segfault minix-tests
./usr/tests/minix-posix/test_arm_unaligned minix-tests

View File

@@ -43,12 +43,9 @@ INCS+= ieeefp.h
INCSDIR= /usr/include
.if defined(__MINIX)
# RPC is not compiled in the libc. This include also needs
# rpcgen, which can be compiled if needed.
SUBDIR+= ../minix/include
.else
SUBDIR= rpc
.endif # defined(__MINIX)
SUBDIR= rpc
SUBDIR+= ../common/include/prop
SUBDIR+= ../common/include/ppath

View File

@@ -91,11 +91,7 @@ SUBDIR+= pkgconfig
.include "${.CURDIR}/regex/Makefile.inc"
.endif
.include "${.CURDIR}/resolv/Makefile.inc"
.if defined(__MINIX)
# RPC needs pollts() and a reserved port allocator.
.else
.include "${.CURDIR}/rpc/Makefile.inc"
.endif # defined(__MINIX)
.include "${.CURDIR}/ssp/Makefile.inc"
.include "${.CURDIR}/stdio/Makefile.inc"
.include "${.CURDIR}/stdlib/Makefile.inc"

View File

@@ -59,6 +59,9 @@ __RCSID("$NetBSD: clnt_generic.c,v 1.33 2014/05/28 14:45:19 christos Exp $");
#include <stdlib.h>
#include <unistd.h>
#if defined(__minix)
#include <signal.h>
#endif
#include "svc_fdset.h"
#include "rpc_internal.h"

View File

@@ -53,7 +53,7 @@
K(GRAVE_ACCENT) = { '\'', '"', A('\''),A('\''),A('"'), C('@') },
K(COMMA) = { ',', '<', A(','), A(','), A('<'), C('@') },
K(PERIOD) = { '.', '>', A('.'), A('.'), A('>'), C('@') },
K(SLASH) = { 59, 58, A(59), A(58), A(59), C('@') },
K(SLASH) = { ';', ':', A(';'), A(';'), A(':'), C('@') },
K(CAPS_LOCK) = { CALOCK, CALOCK, CALOCK, CALOCK, CALOCK, CALOCK },
K(F1) = { F1, SF1, AF1, AF1, ASF1, CF1 },
K(F2) = { F2, SF2, AF2, AF2, ASF2, CF2 },
@@ -94,10 +94,11 @@
K(KP_8) = { NUP, '8', AUP, AUP, A('8'), CUP },
K(KP_9) = { NPGUP, '9', APGUP, APGUP, A('9'), CPGUP },
K(KP_0) = { NINSRT, '0', AINSRT, AINSRT, A('0'), CINSRT },
K(KP_PERIOD) = { NDEL, '.', A(DEL), A(DEL), A('.'), DEL },
K(KP_PERIOD) = { NDEL, ',', A(DEL), A(DEL), A(','), DEL },
K(EUROPE_2) = { '\\', '|', A('\\'),A('|'), A('\\'),C('@') },
K(APPLICATION) = { C('M'), C('M'), CA('M'),CA('M'),CA('M'),C('J') },
K(KP_EQUAL) = { '?', 0, 0, 0, 0, 0 },
K(I10L_1) = { '/', '?', A('/'), A('/'), A('?'), C('@') },
K(EQUAL_SIGN) = { '.', '.', 0, 0, 0, 0 },
K(SYSREQ) = { C('M'), C('M'), CA('M'),CA('M'),CA('M'),C('J') },
K(LEFT_CTRL) = { LCTRL, LCTRL, LCTRL, LCTRL, LCTRL, LCTRL },
K(LEFT_SHIFT) = { LSHIFT, LSHIFT, LSHIFT, LSHIFT, LSHIFT, LSHIFT },

View File

@@ -1,7 +1,6 @@
#include "fs.h"
#include "inode.h"
#include "clean.h"
#include <assert.h>
/*===========================================================================*
* fs_sync *

View File

@@ -1,6 +1,5 @@
#include "fs.h"
#include <string.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include "inode.h"

View File

@@ -109,6 +109,36 @@ static void pagefault( struct proc *pr,
return;
}
static void
data_abort(int is_nested, struct proc *pr, reg_t *saved_lr,
struct ex_s *ep, u32_t dfar, u32_t dfsr)
{
/* Extract fault status bit [0:3, 10] from DFSR */
u32_t fs = dfsr & 0x0F;
fs |= ((dfsr >> 6) & 0x10);
/* Translation and permission faults are handled as pagefaults. */
if (is_trans_fault(fs) || is_perm_fault(fs)) {
pagefault(pr, saved_lr, is_nested, dfar, dfsr);
} else if (!is_nested) {
/* A user process caused some other kind of data abort. */
int signum = SIGSEGV;
if (is_align_fault(fs)) {
signum = SIGBUS;
} else {
printf("KERNEL: unknown data abort by proc %d sending "
"SIGSEGV (dfar=0x%lx dfsr=0x%lx fs=0x%lx)\n",
proc_nr(pr), dfar, dfsr, fs);
}
cause_sig(proc_nr(pr), signum);
} else { /* is_nested */
printf("KERNEL: inkernel data abort - disaster (dfar=0x%lx "
"dfsr=0x%lx fs=0x%lx)\n", dfar, dfsr, fs);
inkernel_disaster(pr, saved_lr, ep, is_nested);
}
}
static void inkernel_disaster(struct proc *saved_proc,
reg_t *saved_lr, struct ex_s *ep,
int is_nested)
@@ -171,7 +201,7 @@ void exception_handler(int is_nested, reg_t *saved_lr, int vector)
}
if (vector == DATA_ABORT_VECTOR) {
pagefault(saved_proc, saved_lr, is_nested, read_dfar(), read_dfsr());
data_abort(is_nested, saved_proc, saved_lr, ep, read_dfar(), read_dfsr());
return;
}

View File

@@ -21,6 +21,16 @@
#define INTERRUPT_VECTOR 6
#define FAST_INTERRUPT_VECTOR 7
/* Data abort helper */
#define is_align_fault(fault_status) \
((fault_status) == FAULT_ALIGN_0)
#define is_trans_fault(fault_status) \
(((fault_status) == FAULT_TRANS_S) || ((fault_status) == FAULT_TRANS_P))
#define is_perm_fault(fault_status) \
(((fault_status) == FAULT_PERM_S) || ((fault_status) == FAULT_PERM_P))
/*
* defines how many bytes are reserved at the top of the kernel stack for global
* information like currently scheduled process or current cpu id

View File

@@ -35,9 +35,11 @@
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/poll.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
int
poll(struct pollfd *p, nfds_t nfds, int timout)
@@ -100,3 +102,28 @@ poll(struct pollfd *p, nfds_t nfds, int timout)
}
return rval;
}
int
pollts(struct pollfd * __restrict fds, nfds_t nfds, const struct timespec * __restrict ts,
const sigset_t * __restrict sigmask)
{
sigset_t oldmask;
int timeout, rval;
if (NULL != sigmask) {
sigprocmask(SIG_SETMASK, sigmask, &oldmask);
}
if (NULL != ts) {
timeout = ts->tv_sec * 1000 + ts->tv_nsec / 1000;
rval = poll(fds, nfds, timeout);
} else {
rval = poll(fds, nfds, INFTIM);
}
if (NULL != sigmask) {
sigprocmask(SIG_SETMASK, &oldmask, NULL);
}
return rval;
}

View File

@@ -876,11 +876,6 @@ When exiting MINIX running under DOS the Boot Monitor's
.B exit
command will return you to the DOS prompt. The Boot Monitor and MINIX
are together just a pretty big DOS program as far DOS is concerned.
.SH FILES
.TP 12
.B /usr/ast
Honorary home directory of Andrew S. Tanenbaum. Doubles as the place where
the default setup for a new user is found.
.SH "SEE ALSO"
.BR dosminix (8),
.BR monitor (8),

View File

@@ -13,7 +13,6 @@
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/ds.h>
#include <minix/type.h>
#include <minix/endpoint.h>
#include <minix/minlib.h>
#include <minix/type.h>

View File

@@ -126,6 +126,8 @@ PROGS+= test63 mod
OBJS.${o} += common.o
.endfor
.include "./arch/${MACHINE_ARCH}/Makefile.inc"
# LSC Make sure there is not leftover after a failed testrun
clean: .PHONY .MAKE
@rm -rf DIR*

View File

@@ -0,0 +1,7 @@
PROGS+= test_arm_segfault
PROGS+= test_arm_unaligned
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}
test_arm_segfault.o : test_arm_segfault.S
test_arm_unaligned.o : test_arm_unaligned.S

View File

@@ -0,0 +1,16 @@
.text
.global main
main:
push {lr}
ldr r0, =0xDEADBEE0 /* Hopefully this is not mapped... */
ldr r1, [r0]
ldr r0, =0x01010100 /* In case we survived, try something else */
ldr r1, [r0]
ldr r0, =msg
bl puts
mov r0, #0 /* test should check for non-zero exit code / signal */
pop {pc}
msg:
.ascii "ERROR - caused no segfault\n"

View File

@@ -0,0 +1,26 @@
.text
.global main
main:
push {lr}
mov r0, sp
/* This should work */
ldr r0, [sp]
/* Unalign it */
add r0, #2
/* Try a non-word aligned word-load, this may work if SCTRL.A == 0 */
ldr r1, [r0]
/* Load non-word aligned dword, should die even with SCTRL.A == 0 */
ldrd r2, r3, [r0]
ldr r0, =msg
bl puts
mov r0, #0 /* test should check for non-zero exit code / signal */
pop {pc}
msg:
.ascii "ERROR - caused no sigbus\n"

View File

View File

@@ -264,7 +264,7 @@ main(int argc, char *argv[])
/* Determine the size of the device if not specified as -b or proto. */
maxblocks = sizeup(argv[optind]);
if (bblocks != 0 && bblocks + fs_offset_blocks > maxblocks && !insertmode) {
errx(4, "Given size -b %d exeeds device capacity(%d)\n", bblocks, maxblocks);
errx(4, "Given size -b %d exceeds device capacity(%d)\n", bblocks, maxblocks);
}
if (argc - optind == 1 && bblocks == 0) {

View File

@@ -82,6 +82,11 @@ SMP_FLAGS += -DCONFIG_MAX_CPUS=${CONFIG_MAX_CPUS}
CPPFLAGS+= ${SMP_FLAGS}
# Disabled unaligned accesses on ARM
.if !empty(MACHINE_ARCH:Mearm*)
CFLAGS+= -mno-unaligned-access
.endif
__uname_s!= uname -s
.if ${__uname_s:Uunknown} == "Minix"
USETOOLS?= never

View File

@@ -617,7 +617,11 @@ pci_subclass_name(pcireg_t reg)
subclassp++;
}
return subclassp->name;
if (subclassp) {
return subclassp->name;
} else {
return NULL;
}
}
#endif /* defined(__minix) && defined(_PCI_SERVER) */

View File

@@ -12,7 +12,7 @@ SUBDIR+= tls_dso .WAIT # sync
# LSC: db hangs, so compiled, installed, but not added to the testsuite by
# default
SUBDIR+= db
TESTS_SUBDIRS+= hash inet locale net regex stdlib
TESTS_SUBDIRS+= hash inet locale net regex rpc stdlib
TESTS_SUBDIRS+= stdio string termios time
.if !defined(__MINIX)

View File

@@ -5,19 +5,19 @@
TESTSDIR= ${TESTSBASE}/lib/libc/gen
TESTS_SUBDIRS= execve
TESTS_SUBDIRS+= posix_spawn
#TESTS_SUBDIRS+= posix_spawn
TESTS_C+= t_alarm
TESTS_C+= t_assert
TESTS_C+= t_basedirname
TESTS_C+= t_closefrom
TESTS_C+= t_cpuset
#TESTS_C+= t_closefrom
#TESTS_C+= t_cpuset
TESTS_C+= t_dir
TESTS_C+= t_floatunditf
TESTS_C+= t_fmtcheck
TESTS_C+= t_fnmatch
TESTS_C+= t_fpclassify
TESTS_C+= t_fpsetmask
#TESTS_C+= t_fpsetmask
TESTS_C+= t_fpsetround
TESTS_C+= t_ftok
TESTS_C+= t_getcwd
@@ -25,16 +25,16 @@ TESTS_C+= t_getgrent
TESTS_C+= t_glob
TESTS_C+= t_humanize_number
TESTS_C+= t_isnan
TESTS_C+= t_nice
#TESTS_C+= t_nice
TESTS_C+= t_pause
TESTS_C+= t_raise
TESTS_C+= t_randomid
TESTS_C+= t_realpath
TESTS_C+= t_setdomainname
TESTS_C+= t_sethostname
TESTS_C+= t_siginfo
TESTS_C+= t_sleep
TESTS_C+= t_syslog
#TESTS_C+= t_siginfo
#TESTS_C+= t_sleep
#TESTS_C+= t_syslog
TESTS_C+= t_time
TESTS_C+= t_ttyname
TESTS_C+= t_vis

View File

@@ -112,7 +112,7 @@ SUBDIR+= gencat \
makewhatis mtree nbperf .WAIT uudecode
.endif
SUBDIR+= cat join lorder m4 mkdep tsort .WAIT yacc .WAIT awk .WAIT lex
SUBDIR+= cat rpcgen join lorder m4 mkdep tsort .WAIT yacc .WAIT awk .WAIT lex
.if ${TOOLS_BUILDRUMP} == "no"
SUBDIR += .WAIT texinfo \

6
tools/rpcgen/Makefile Normal file
View File

@@ -0,0 +1,6 @@
# $NetBSD: Makefile,v 1.4 2002/12/08 20:20:05 thorpej Exp $
HOSTPROGNAME= ${_TOOL_PREFIX}rpcgen
HOST_SRCDIR= usr.bin/rpcgen
.include "${.CURDIR}/../Makefile.host"

7
usr.bin/rpcgen/Makefile Normal file
View File

@@ -0,0 +1,7 @@
# $NetBSD: Makefile,v 1.13 2013/08/11 08:03:10 dholland Exp $
PROG= rpcgen
SRCS= rpc_clntout.c rpc_cout.c rpc_hout.c rpc_main.c rpc_parse.c rpc_scan.c \
rpc_svcout.c rpc_util.c rpc_sample.c rpc_tblout.c
.include <bsd.prog.mk>

View File

@@ -0,0 +1,264 @@
/* $NetBSD: rpc_clntout.c,v 1.15 2013/12/15 00:40:17 christos Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
#if 0
static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI";
#else
__RCSID("$NetBSD: rpc_clntout.c,v 1.15 2013/12/15 00:40:17 christos Exp $");
#endif
#endif
/*
* rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
* Copyright (C) 1987, Sun Microsytsems, Inc.
*/
#include <stdio.h>
#include <string.h>
#include <rpc/types.h>
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
static void write_program(definition *);
static const char *ampr(const char *);
static const char *aster(const char *);
static void printbody(proc_list *);
#define DEFAULT_TIMEOUT 25 /* in seconds */
static char RESULT[] = "clnt_res";
void
write_stubs(void)
{
list *l;
definition *def;
f_print(fout,
"\n/* Default timeout can be changed using clnt_control() */\n");
f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
DEFAULT_TIMEOUT);
for (l = defined; l != NULL; l = l->next) {
def = (definition *) l->val;
if (def->def_kind == DEF_PROGRAM) {
write_program(def);
}
}
}
static void
write_program(definition *def)
{
version_list *vp;
proc_list *proc;
for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
for (proc = vp->procs; proc != NULL; proc = proc->next) {
f_print(fout, "\n");
if (Mflag)
f_print(fout, "enum clnt_stat\n");
else {
ptype(proc->res_prefix, proc->res_type, 1);
f_print(fout, "*\n");
}
pvname(proc->proc_name, vp->vers_num);
printarglist(proc, RESULT, "clnt", "CLIENT *");
f_print(fout, "{\n");
printbody(proc);
f_print(fout, "}\n");
}
}
}
/* Writes out declarations of procedure's argument list.
In either ANSI C style, in one of old rpcgen style (pass by reference),
or new rpcgen style (multiple arguments, pass by value);
*/
/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
void
printarglist(proc_list *proc, const char *result,
const char *addargname, const char *addargtype)
{
decl_list *l;
if (!newstyle) { /* old style: always pass argument by
* reference */
f_print(fout, "(");
ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
f_print(fout, "*argp, ");
if (Mflag) {
if (streq(proc->res_type, "void"))
f_print(fout, "char ");
else
ptype(proc->res_prefix, proc->res_type, 0);
f_print(fout, "%s%s, ", aster(proc->res_type),
result);
}
f_print(fout, "%s%s)\n", addargtype, addargname);
} else {
f_print(fout, "(");
if (!streq(proc->args.decls->decl.type, "void")) {
/* new style, 1 or multiple arguments */
for (l = proc->args.decls; l != NULL; l = l->next)
pdeclaration(proc->args.argname,
&l->decl, 0, ", ");
}
if (Mflag) {
if (streq(proc->res_type, "void"))
f_print(fout, "char ");
else
ptype(proc->res_prefix, proc->res_type, 0);
f_print(fout, "%s%s, ", aster(proc->res_type),
result);
}
f_print(fout, "%s%s)\n", addargtype, addargname);
}
}
static const char *
ampr(const char *type)
{
if (isvectordef(type, REL_ALIAS)) {
return ("");
} else {
return ("&");
}
}
static const char *
aster(const char *type)
{
if (isvectordef(type, REL_ALIAS)) {
return ("");
} else {
return ("*");
}
}
static void
printbody(proc_list *proc)
{
decl_list *l;
bool_t args2 = (proc->arg_num > 1);
/* For new style with multiple arguments, need a structure in which to
* stuff the arguments. */
if (newstyle && args2) {
f_print(fout, "\t%s", proc->args.argname);
f_print(fout, " arg;\n");
}
if (!Mflag) {
f_print(fout, "\tstatic ");
if (streq(proc->res_type, "void"))
f_print(fout, "char ");
else
ptype(proc->res_prefix, proc->res_type, 0);
f_print(fout, "%s;\n", RESULT);
}
f_print(fout, "\n");
if (!Mflag)
f_print(fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n",
ampr(proc->res_type), RESULT, RESULT);
if (newstyle && !args2 && (streq(proc->args.decls->decl.type, "void"))) {
/* newstyle, 0 arguments */
if (Mflag) {
f_print(fout, "\treturn (clnt_call(clnt, %s, xdr_void",
proc->proc_name);
f_print(fout, ", NULL, xdr_%s, %s, TIMEOUT));\n",
stringfix(proc->res_type), RESULT);
} else {
f_print(fout, "\tif (clnt_call(clnt, %s, xdr_void, ",
proc->proc_name);
f_print(fout,
"NULL, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n",
stringfix(proc->res_type), ampr(proc->res_type),
RESULT);
}
} else {
if (newstyle && args2) {
/* newstyle, multiple arguments: stuff arguments into
* structure */
for (l = proc->args.decls; l != NULL; l = l->next) {
f_print(fout, "\targ.%s = %s;\n",
l->decl.name, l->decl.name);
}
if (Mflag) {
f_print(fout,
"\treturn (clnt_call(clnt, %s, xdr_%s, &arg, xdr_%s, %s, TIMEOUT));\n",
proc->proc_name, proc->args.argname,
stringfix(proc->res_type), RESULT);
} else {
f_print(fout,
"\tif (clnt_call(clnt, %s, xdr_%s, &arg, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n",
proc->proc_name, proc->args.argname,
stringfix(proc->res_type),
ampr(proc->res_type), RESULT);
}
} else { /* single argument, new or old style */
if (Mflag) {
f_print(fout,
"\treturn (clnt_call(clnt, %s, xdr_%s, %s%s, xdr_%s, %s, TIMEOUT));\n",
proc->proc_name,
stringfix(proc->args.decls->decl.type),
(newstyle ? "&" : ""),
(newstyle ? proc->args.decls->decl.name : "argp"),
stringfix(proc->res_type), RESULT);
} else {
f_print(fout,
"\tif (clnt_call(clnt, %s, xdr_%s, %s%s, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n",
proc->proc_name,
stringfix(proc->args.decls->decl.type),
(newstyle ? "&" : ""),
(newstyle ? proc->args.decls->decl.name : "argp"),
stringfix(proc->res_type),
ampr(proc->res_type), RESULT);
}
}
}
if (!Mflag) {
f_print(fout, "\t\treturn (NULL);\n");
if (streq(proc->res_type, "void"))
f_print(fout, "\treturn ((void *)%s%s);\n",
ampr(proc->res_type), RESULT);
else
f_print(fout, "\treturn (%s%s);\n",
ampr(proc->res_type), RESULT);
}
}

725
usr.bin/rpcgen/rpc_cout.c Normal file
View File

@@ -0,0 +1,725 @@
/* $NetBSD: rpc_cout.c,v 1.37 2015/09/20 16:57:13 kamil Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
#if 0
static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI";
#else
__RCSID("$NetBSD: rpc_cout.c,v 1.37 2015/09/20 16:57:13 kamil Exp $");
#endif
#endif
/*
* rpc_cout.c, XDR routine outputter for the RPC protocol compiler
*/
#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
static int findtype(definition *, const char *);
static int undefined(const char *);
static void print_generic_header(const char *, int);
static void print_header(definition *);
static void print_prog_header(proc_list *);
static void print_trailer(void);
static void print_ifopen(int, const char *);
static void print_ifarg(const char *);
static void print_ifsizeof(const char *, const char *);
static void print_ifclose(int);
static void print_ifstat(int, const char *, const char *, relation,
const char *, const char *, const char *);
static void emit_enum(definition *);
static void emit_program(definition *);
static void emit_union(definition *);
static void emit_struct(definition *);
static void emit_typedef(definition *);
static void print_stat(int, declaration *);
/*
* Emit the C-routine for the given definition
*/
void
emit(definition *def)
{
if (def->def_kind == DEF_CONST) {
return;
}
if (def->def_kind == DEF_PROGRAM) {
emit_program(def);
return;
}
if (def->def_kind == DEF_TYPEDEF) {
/* now we need to handle declarations like struct typedef foo
* foo; since we dont want this to be expanded into 2 calls to
* xdr_foo */
if (strcmp(def->def.ty.old_type, def->def_name) == 0)
return;
};
print_header(def);
switch (def->def_kind) {
case DEF_UNION:
emit_union(def);
break;
case DEF_ENUM:
emit_enum(def);
break;
case DEF_STRUCT:
emit_struct(def);
break;
case DEF_TYPEDEF:
emit_typedef(def);
break;
case DEF_PROGRAM:
case DEF_CONST:
errx(1, "Internal error at %s:%d: Case %d not handled",
__FILE__, __LINE__, def->def_kind);
break;
}
print_trailer();
}
static int
findtype(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");
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");
}
static void
print_header(definition *def)
{
print_generic_header(def->def_name,
def->def_kind != DEF_TYPEDEF ||
!isvectordef(def->def.ty.old_type, def->def.ty.rel));
}
static void
print_prog_header(proc_list *plist)
{
print_generic_header(plist->args.argname, 1);
}
static void
print_trailer(void)
{
f_print(fout, "\treturn (TRUE);\n");
f_print(fout, "}\n");
}
static void
print_ifopen(int indent, const char *name)
{
char _t_kludge[32];
/*
* XXX Solaris seems to strip the _t. No idea why.
*/
if (!strcmp(name, "rpcprog_t") || !strcmp(name, "rpcvers_t") ||
!strcmp(name, "rpcproc_t") || !strcmp(name, "rpcprot_t") ||
!strcmp(name, "rpcport_t") || !strcmp(name, "rpcpinline_t")) {
strncpy(_t_kludge, name, strlen(name) - 2);
name = _t_kludge;
}
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(const char *prefix, const char *type)
{
if (streq(type, "bool")) {
f_print(fout, ", (u_int)sizeof(bool_t), (xdrproc_t)xdr_bool");
} else {
f_print(fout, ", (u_int)sizeof(");
if (undefined(type) && prefix) {
f_print(fout, "%s ", prefix);
}
f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type);
}
}
static void
print_ifclose(int indent)
{
f_print(fout, "))\n");
tabify(fout, indent);
f_print(fout, "\treturn (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 **)(void *)");
f_print(fout, "%s", objname);
print_ifsizeof(prefix, type);
break;
case REL_VECTOR:
if (streq(type, "string")) {
alt = "string";
} else
if (streq(type, "opaque")) {
alt = "opaque";
}
if (alt) {
print_ifopen(indent, alt);
print_ifarg(objname);
} else {
print_ifopen(indent, "vector");
print_ifarg("(char *)(void *)");
f_print(fout, "%s", objname);
}
print_ifarg(amax);
if (!alt) {
print_ifsizeof(prefix, type);
}
break;
case REL_ARRAY:
if (streq(type, "string")) {
alt = "string";
} else
if (streq(type, "opaque")) {
alt = "bytes";
}
if (streq(type, "string")) {
print_ifopen(indent, alt);
print_ifarg(objname);
} else {
if (alt) {
print_ifopen(indent, alt);
} else {
print_ifopen(indent, "array");
}
print_ifarg("(char **)(void *)");
if (*objname == '&') {
f_print(fout, "%s.%s_val, (u_int *)%s.%s_len",
objname, name, objname, name);
} else {
f_print(fout, "&%s->%s_val, (u_int *)&%s->%s_len",
objname, name, objname, name);
}
}
print_ifarg(amax);
if (!alt) {
print_ifsizeof(prefix, type);
}
break;
case REL_ALIAS:
print_ifopen(indent, type);
print_ifarg(objname);
break;
}
print_ifclose(indent);
}
/* ARGSUSED */
static void
emit_enum(definition *def)
{
tabify(fout, 1);
f_print(fout, "{\n");
tabify(fout, 2);
f_print(fout, "enum_t et = (enum_t)*objp;\n");
print_ifopen(2, "enum");
print_ifarg("&et");
print_ifclose(2);
tabify(fout, 2);
f_print(fout, "*objp = (%s)et;\n", def->def_name);
tabify(fout, 1);
f_print(fout, "}\n");
}
static void
emit_program(definition *def)
{
decl_list *dl;
version_list *vlist;
proc_list *plist;
for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next)
for (plist = vlist->procs; plist != NULL; plist = plist->next) {
if (!newstyle || plist->arg_num < 2)
continue; /* old style, or single
* argument */
print_prog_header(plist);
for (dl = plist->args.decls; dl != NULL;
dl = dl->next)
print_stat(1, &dl->decl);
print_trailer();
}
}
static void
emit_union(definition *def)
{
declaration *dflt;
case_list *cl;
declaration *cs;
char *object;
static const char vecformat[] = "objp->%s_u.%s";
static const char format[] = "&objp->%s_u.%s";
f_print(fout, "\n");
print_stat(1, &def->def.un.enum_decl);
f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name);
for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
f_print(fout, "\tcase %s:\n", cl->case_name);
if (cl->contflag == 1) /* a continued case statement */
continue;
cs = &cl->case_decl;
if (!streq(cs->type, "void")) {
object = alloc(strlen(def->def_name) + strlen(format) +
strlen(cs->name) + 1);
if (isvectordef(cs->type, cs->rel)) {
s_print(object, vecformat, def->def_name,
cs->name);
} else {
s_print(object, format, def->def_name,
cs->name);
}
print_ifstat(2, cs->prefix, cs->type, cs->rel,
cs->array_max, object, cs->name);
free(object);
}
f_print(fout, "\t\tbreak;\n");
}
dflt = def->def.un.default_decl;
f_print(fout, "\tdefault:\n");
if (dflt != NULL) {
if (!streq(dflt->type, "void")) {
object = alloc(strlen(def->def_name) + strlen(format) +
strlen(dflt->name) + 1);
if (isvectordef(dflt->type, dflt->rel)) {
s_print(object, vecformat, def->def_name,
dflt->name);
} else {
s_print(object, format, def->def_name,
dflt->name);
}
print_ifstat(2, dflt->prefix, dflt->type, dflt->rel,
dflt->array_max, object, dflt->name);
free(object);
}
f_print(fout, "\t\tbreak;\n");
} else {
f_print(fout, "\t\treturn (FALSE);\n");
}
f_print(fout, "\t}\n");
}
static void
emit_struct(definition *def)
{
decl_list *dl;
int i, j, size, flag;
decl_list *cur = NULL, *psav;
bas_type *ptr;
char *sizestr;
const char *plus;
char ptemp[256];
int can_inline;
if (doinline == 0) {
f_print(fout, "\n");
for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
print_stat(1, &dl->decl);
return;
}
size = 0;
can_inline = 0;
for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
if ((dl->decl.prefix == NULL) &&
((ptr = find_type(dl->decl.type)) != NULL) &&
((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) {
if (dl->decl.rel == REL_ALIAS)
size += ptr->length;
else {
can_inline = 1;
break; /* can be inlined */
};
} else {
if (size >= doinline) {
can_inline = 1;
break; /* can be inlined */
}
size = 0;
}
if (size > doinline)
can_inline = 1;
if (can_inline == 0) { /* can not inline, drop back to old mode */
f_print(fout, "\n");
for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
print_stat(1, &dl->decl);
return;
};
/* May cause lint to complain. but ... */
f_print(fout, "\tint32_t *buf;\n");
flag = PUT;
f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n");
for (j = 0; j < 2; j++) {
i = 0;
size = 0;
sizestr = NULL;
for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { /* xxx */
/* now walk down the list and check for basic types */
if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) {
if (i == 0)
cur = dl;
i++;
if (dl->decl.rel == REL_ALIAS)
size += ptr->length;
else {
/* this is required to handle arrays */
if (sizestr == NULL)
plus = "";
else
plus = " + ";
if (ptr->length != 1)
s_print(ptemp, "%s%s * %d", plus, dl->decl.array_max, ptr->length);
else
s_print(ptemp, "%s%s", plus, dl->decl.array_max);
/* now concatenate to sizestr !!!! */
if (sizestr == NULL)
sizestr = strdup(ptemp);
else {
char *nsizestr;
nsizestr = realloc(sizestr, strlen(sizestr) + strlen(ptemp) + 1);
if (nsizestr == NULL) {
err(EXIT_FAILURE, "realloc");
}
sizestr = nsizestr;
sizestr = strcat(sizestr, ptemp); /* build up length of
* array */
}
}
} else {
if (i > 0) {
if (sizestr == NULL && size < doinline) {
/* don't expand into inline
* code if size < doinline */
while (cur != dl) {
print_stat(2, &cur->decl);
cur = cur->next;
}
} else {
/* were already looking at a
* xdr_inlineable structure */
if (sizestr == NULL)
f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);\n",
size);
else
if (size == 0)
f_print(fout,
"\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %s * BYTES_PER_XDR_UNIT);\n",
sizestr);
else
f_print(fout,
"\t\tbuf = (int32_t *)XDR_INLINE(xdrs, (%d + %s) * BYTES_PER_XDR_UNIT);\n",
size, sizestr);
f_print(fout, "\t\tif (buf == NULL) {\n");
psav = cur;
while (cur != dl) {
print_stat(3, &cur->decl);
cur = cur->next;
}
f_print(fout, "\t\t} else {\n");
cur = psav;
while (cur != dl) {
emit_inline(&cur->decl, flag);
cur = cur->next;
}
f_print(fout, "\t\t}\n");
}
}
size = 0;
i = 0;
if (sizestr) {
free(sizestr);
sizestr = NULL;
}
print_stat(2, &dl->decl);
}
}
if (i > 0) {
if (sizestr == NULL && size < doinline) {
/* don't expand into inline code if size <
* doinline */
while (cur != dl) {
print_stat(2, &cur->decl);
cur = cur->next;
}
} else {
/* were already looking at a xdr_inlineable
* structure */
if (sizestr == NULL)
f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);\n",
size);
else
if (size == 0)
f_print(fout,
"\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %s * BYTES_PER_XDR_UNIT);\n",
sizestr);
else
f_print(fout,
"\t\tbuf = (int32_t *)XDR_INLINE(xdrs, (%d + %s) * BYTES_PER_XDR_UNIT);\n",
size, sizestr);
f_print(fout, "\t\tif (buf == NULL) {\n");
psav = cur;
while (cur != NULL) {
print_stat(3, &cur->decl);
cur = cur->next;
}
f_print(fout, "\t\t} else {\n");
cur = psav;
while (cur != dl) {
emit_inline(&cur->decl, flag);
cur = cur->next;
}
f_print(fout, "\t\t}\n");
}
}
if (flag == PUT) {
flag = GET;
f_print(fout, "\t} else if (xdrs->x_op == XDR_DECODE) {\n");
}
}
f_print(fout, "\t} else {\n");
/* now take care of XDR_FREE case */
for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
print_stat(2, &dl->decl);
f_print(fout, "\t}\n");
}
static void
emit_typedef(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;
f_print(fout, "\n");
print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
}
static void
print_stat(int indent, 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);
}
void
emit_inline(declaration *decl, int flag)
{
/*check whether an array or not */
switch (decl->rel) {
case REL_ALIAS:
emit_single_in_line(decl, flag, REL_ALIAS);
break;
case REL_VECTOR:
f_print(fout, "\t\t\t{\n");
f_print(fout, "\t\t\t\tint i;\n");
f_print(fout, "\t\t\t\t%s *genp;\n", decl->type);
f_print(fout, "\n");
f_print(fout, "\t\t\t\tfor (i = 0, genp = objp->%s;\n",
decl->name);
f_print(fout, "\t\t\t\t i < %s; i++) {\n\t\t",
decl->array_max);
emit_single_in_line(decl, flag, REL_VECTOR);
f_print(fout, "\t\t\t\t}\n\t\t\t}\n");
break;
case REL_ARRAY:
case REL_POINTER:
errx(1, "Internal error at %s:%d: Case %d not handled",
__FILE__, __LINE__, decl->rel);
}
}
void
emit_single_in_line(declaration *decl, int flag, relation rel)
{
const char *upp_case;
char *freeable;
int freed = 0;
if (flag == PUT)
f_print(fout, "\t\t\tIXDR_PUT_");
else
if (rel == REL_ALIAS)
f_print(fout, "\t\t\tobjp->%s = IXDR_GET_", decl->name);
else
f_print(fout, "\t\t\t*genp++ = IXDR_GET_");
upp_case = freeable = upcase(decl->type);
/* hack - XX */
if (strcmp(upp_case, "INT") == 0) {
free(freeable);
freed = 1;
upp_case = "INT32";
} else if (strcmp(upp_case, "U_INT") == 0) {
free(freeable);
freed = 1;
upp_case = "U_INT32";
}
if (flag == PUT) {
if (rel == REL_ALIAS)
f_print(fout, "%s(buf, objp->%s);\n", upp_case, decl->name);
else
f_print(fout, "%s(buf, *genp++);\n", upp_case);
} else
f_print(fout, "%s(buf);\n", upp_case);
if (!freed)
free(freeable);
}
char *
upcase(const char *str)
{
char *ptr, *hptr;
ptr = malloc(strlen(str) + 1);
if (ptr == NULL) {
errx(EXIT_FAILURE, "Out of memory");
}
hptr = ptr;
while (*str != '\0')
*ptr++ = toupper((unsigned char)*str++);
*ptr = '\0';
return (hptr);
}

543
usr.bin/rpcgen/rpc_hout.c Normal file
View File

@@ -0,0 +1,543 @@
/* $NetBSD: rpc_hout.c,v 1.24 2015/09/20 15:45:07 kamil Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
#if 0
static char sccsid[] = "@(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI";
#else
__RCSID("$NetBSD: rpc_hout.c,v 1.24 2015/09/20 15:45:07 kamil Exp $");
#endif
#endif
/*
* rpc_hout.c, Header file outputter for the RPC protocol compiler
*/
#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
static void pconstdef(definition *);
static void pargdef(definition *);
static void pstructdef(definition *);
static void puniondef(definition *);
static void pdefine(const char *, const char *);
static void puldefine(const char *, const char *);
static int define_printed(proc_list *, version_list *);
static void pprogramdef(definition *);
static void penumdef(definition *);
static void ptypedef(definition *);
static int undefined2(const char *, const char *);
static void cplusplusstart(void);
static void cplusplusend(void);
/*
* 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;
}
}
void
print_progdef(definition *def)
{
switch (def->def_kind) {
case DEF_PROGRAM:
f_print(fout, "\n");
pprogramdef(def);
break;
case DEF_CONST:
case DEF_TYPEDEF:
case DEF_ENUM:
case DEF_UNION:
case DEF_STRUCT:
break;
}
}
void
print_funcdef(definition *def, int *did)
{
switch (def->def_kind) {
case DEF_PROGRAM:
case DEF_CONST:
break;
case DEF_TYPEDEF:
case DEF_ENUM:
case DEF_UNION:
case DEF_STRUCT:
if (!*did) {
f_print(fout, "\n");
cplusplusstart();
*did = 1;
}
pxdrfuncdecl(def->def_name,
def->def_kind != DEF_TYPEDEF ||
!isvectordef(def->def.ty.old_type, def->def.ty.rel));
break;
}
}
void
print_funcend(int did) {
if (did) {
cplusplusend();
}
}
void
pxdrfuncdecl(const char *name, int pointerp)
{
f_print(fout, "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;
char *name;
proc_list *plist;
int did;
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);
}
}
did = 0;
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 */
}
if (!did) {
cplusplusstart();
did = 1;
}
pxdrfuncdecl(plist->args.argname, 1);
}
}
if (did) {
cplusplusend();
}
}
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 void
puldefine(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);
}
}
}
errx(1, "Internal error at %s:%d: procedure not found",
__FILE__, __LINE__);
/* NOTREACHED */
}
static void
cplusplusstart(void)
{
if (BSDflag)
f_print(fout, "__BEGIN_DECLS\n");
else
f_print(fout, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
}
static void
cplusplusend(void)
{
if (BSDflag)
f_print(fout, "__END_DECLS\n");
else
f_print(fout, "#ifdef __cplusplus\n};\n#endif\n");
}
static void
pprogramdef(definition *def)
{
version_list *vers;
proc_list *proc;
pargdef(def);
puldefine(def->def_name, def->def.pr.prog_num);
for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
if (tblflag) {
f_print(fout, "extern struct rpcgen_table %s_%s_table[];\n",
locase(def->def_name), vers->vers_num);
f_print(fout, "extern %s_%s_nproc;\n",
locase(def->def_name), vers->vers_num);
}
puldefine(vers->vers_name, vers->vers_num);
for (proc = vers->procs; proc != NULL; proc = proc->next) {
if (!define_printed(proc, def->def.pr.versions)) {
puldefine(proc->proc_name, proc->proc_num);
}
}
}
/*
* Print out 3 definitions, one for ANSI-C, another for C++, a
* third for old style C
*/
f_print(fout, "\n");
cplusplusstart();
for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
for (proc = vers->procs; proc != NULL; proc = proc->next) {
pprocdef(proc, vers, "CLIENT *", 0);
pprocdef(proc, vers, "struct svc_req *", 1);
}
}
cplusplusend();
}
void
pprocdef(proc_list *proc, version_list *vp, const char *addargtype,
int server_p)
{
decl_list *dl;
if (Mflag) {
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);
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, "*");
f_print(fout, ", ");
}
}
if (Mflag) {
if (streq(proc->res_type, "void"))
f_print(fout, "char");
else
ptype(proc->res_prefix, proc->res_type, 0);
if (!isvectordef(proc->res_type, REL_ALIAS))
f_print(fout, "*");
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;
const char *first = "";
f_print(fout, "enum %s {\n", name);
for (l = def->def.en.vals; l != NULL; l = l->next) {
f_print(fout, "%s\t%s", first, 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++);
}
}
first = ",\n";
}
f_print(fout, "\n};\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);
}

1172
usr.bin/rpcgen/rpc_main.c Normal file

File diff suppressed because it is too large Load Diff

618
usr.bin/rpcgen/rpc_parse.c Normal file
View File

@@ -0,0 +1,618 @@
/* $NetBSD: rpc_parse.c,v 1.21 2015/05/09 23:29:51 dholland Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
#if 0
static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI";
#else
__RCSID("$NetBSD: rpc_parse.c,v 1.21 2015/05/09 23:29:51 dholland Exp $");
#endif
#endif
/*
* rpc_parse.c, Parser for the RPC protocol compiler
* Copyright (C) 1987 Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rpc/types.h"
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
#define ARGNAME "arg"
static void isdefined(definition *);
static void def_struct(definition *);
static void def_program(definition *);
static void def_enum(definition *);
static void def_const(definition *);
static void def_union(definition *);
static void check_type_name(const char *, int);
static void def_typedef(definition *);
static void get_declaration(declaration *, defkind);
static void get_prog_declaration(declaration *, defkind, int);
static void get_type(const char **, const char **, defkind);
static void unsigned_dec(const char **);
/*
* 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("Expected definition keyword");
}
scan(TOK_SEMICOLON, &tok);
isdefined(defp);
return (defp);
}
static void
isdefined(definition *defp)
{
STOREVAL(&defined, defp);
}
static void
def_struct(definition *defp)
{
token tok;
declaration dec;
decl_list *decls;
decl_list **tailp;
defp->def_kind = DEF_STRUCT;
scan(TOK_IDENT, &tok);
defp->def_name = tok.str;
scan(TOK_LBRACE, &tok);
tailp = &defp->def.st.decls;
do {
get_declaration(&dec, DEF_STRUCT);
decls = ALLOC(decl_list);
decls->decl = dec;
*tailp = decls;
tailp = &decls->next;
scan(TOK_SEMICOLON, &tok);
peek(&tok);
} while (tok.kind != TOK_RBRACE);
get_token(&tok);
*tailp = NULL;
}
static void
def_program(definition *defp)
{
token tok;
declaration dec;
decl_list *decls;
decl_list **tailp;
version_list *vlist;
version_list **vtailp;
proc_list *plist;
proc_list **ptailp;
int num_args;
bool_t isvoid = FALSE; /* whether first argument is void */
defp->def_kind = DEF_PROGRAM;
scan(TOK_IDENT, &tok);
defp->def_name = tok.str;
scan(TOK_LBRACE, &tok);
vtailp = &defp->def.pr.versions;
tailp = &defp->def.st.decls;
scan(TOK_VERSION, &tok);
do {
scan(TOK_IDENT, &tok);
vlist = ALLOC(version_list);
vlist->vers_name = tok.str;
scan(TOK_LBRACE, &tok);
ptailp = &vlist->procs;
do {
/* get result type */
plist = ALLOC(proc_list);
get_type(&plist->res_prefix, &plist->res_type,
DEF_PROGRAM);
if (streq(plist->res_type, "opaque")) {
error("Illegal result type");
}
scan(TOK_IDENT, &tok);
plist->proc_name = tok.str;
scan(TOK_LPAREN, &tok);
/* get args - first one */
num_args = 1;
isvoid = FALSE;
/* type of DEF_PROGRAM in the first
* get_prog_declaration and DEF_STURCT in the next
* allows void as argument if it is the only argument */
get_prog_declaration(&dec, DEF_PROGRAM, num_args);
if (streq(dec.type, "void"))
isvoid = TRUE;
decls = ALLOC(decl_list);
plist->args.decls = decls;
decls->decl = dec;
tailp = &decls->next;
/* get args */
while (peekscan(TOK_COMMA, &tok)) {
num_args++;
get_prog_declaration(&dec, DEF_STRUCT,
num_args);
decls = ALLOC(decl_list);
decls->decl = dec;
*tailp = decls;
if (streq(dec.type, "void"))
isvoid = TRUE;
tailp = &decls->next;
}
/* multiple arguments are only allowed in newstyle */
if (!newstyle && num_args > 1) {
error("Only one argument is allowed");
}
if (isvoid && num_args > 1) {
error("Illegal use of void in program definition");
}
*tailp = NULL;
scan(TOK_RPAREN, &tok);
scan(TOK_EQUAL, &tok);
scan_num(&tok);
scan(TOK_SEMICOLON, &tok);
plist->proc_num = tok.str;
plist->arg_num = num_args;
*ptailp = plist;
ptailp = &plist->next;
peek(&tok);
} while (tok.kind != TOK_RBRACE);
*ptailp = NULL;
*vtailp = vlist;
vtailp = &vlist->next;
scan(TOK_RBRACE, &tok);
scan(TOK_EQUAL, &tok);
scan_num(&tok);
vlist->vers_num = tok.str;
/* make the argument structure name for each arg */
for (plist = vlist->procs; plist != NULL;
plist = plist->next) {
plist->args.argname = make_argname(plist->proc_name,
vlist->vers_num);
/* free the memory ?? */
}
scan(TOK_SEMICOLON, &tok);
scan2(TOK_VERSION, TOK_RBRACE, &tok);
} while (tok.kind == TOK_VERSION);
scan(TOK_EQUAL, &tok);
scan_num(&tok);
defp->def.pr.prog_num = tok.str;
*vtailp = NULL;
}
static void
def_enum(definition *defp)
{
token tok;
enumval_list *elist;
enumval_list **tailp;
defp->def_kind = DEF_ENUM;
scan(TOK_IDENT, &tok);
defp->def_name = tok.str;
scan(TOK_LBRACE, &tok);
tailp = &defp->def.en.vals;
do {
scan(TOK_IDENT, &tok);
elist = ALLOC(enumval_list);
elist->name = tok.str;
elist->assignment = NULL;
scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
if (tok.kind == TOK_EQUAL) {
scan_num(&tok);
elist->assignment = tok.str;
scan2(TOK_COMMA, TOK_RBRACE, &tok);
}
*tailp = elist;
tailp = &elist->next;
} while (tok.kind != TOK_RBRACE);
*tailp = NULL;
}
static void
def_const(definition *defp)
{
token tok;
defp->def_kind = DEF_CONST;
scan(TOK_IDENT, &tok);
defp->def_name = tok.str;
scan(TOK_EQUAL, &tok);
scan2(TOK_IDENT, TOK_STRCONST, &tok);
defp->def.co = tok.str;
}
static void
def_union(definition *defp)
{
token tok;
declaration dec;
case_list *cases;
case_list **tailp;
defp->def_kind = DEF_UNION;
scan(TOK_IDENT, &tok);
defp->def_name = tok.str;
scan(TOK_SWITCH, &tok);
scan(TOK_LPAREN, &tok);
get_declaration(&dec, DEF_UNION);
defp->def.un.enum_decl = dec;
tailp = &defp->def.un.cases;
scan(TOK_RPAREN, &tok);
scan(TOK_LBRACE, &tok);
scan(TOK_CASE, &tok);
while (tok.kind == TOK_CASE) {
scan2(TOK_IDENT, TOK_CHARCONST, &tok);
cases = ALLOC(case_list);
cases->case_name = tok.str;
scan(TOK_COLON, &tok);
/* now peek at next token */
if (peekscan(TOK_CASE, &tok)) {
do {
scan2(TOK_IDENT, TOK_CHARCONST, &tok);
cases->contflag = 1; /* continued case
* statement */
*tailp = cases;
tailp = &cases->next;
cases = ALLOC(case_list);
cases->case_name = tok.str;
scan(TOK_COLON, &tok);
} while (peekscan(TOK_CASE, &tok));
}
get_declaration(&dec, DEF_UNION);
cases->case_decl = dec;
cases->contflag = 0; /* no continued case statement */
*tailp = cases;
tailp = &cases->next;
scan(TOK_SEMICOLON, &tok);
scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
}
*tailp = NULL;
if (tok.kind == TOK_DEFAULT) {
scan(TOK_COLON, &tok);
get_declaration(&dec, DEF_UNION);
defp->def.un.default_decl = ALLOC(declaration);
*defp->def.un.default_decl = dec;
scan(TOK_SEMICOLON, &tok);
scan(TOK_RBRACE, &tok);
} else {
defp->def.un.default_decl = NULL;
}
}
static const char *const reserved_words[] = {
"array",
"bytes",
"destroy",
"free",
"getpos",
"inline",
"pointer",
"reference",
"setpos",
"sizeof",
"union",
"vector",
NULL
};
static const char *const 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;
for (i = 0; reserved_words[i] != NULL; i++) {
if (strcmp(name, reserved_words[i]) == 0) {
error("Illegal (reserved) name '%s' in type definition", name);
}
}
if (new_type) {
for (i = 0; reserved_types[i] != NULL; i++) {
if (strcmp(name, reserved_types[i]) == 0) {
error("Illegal (reserved) name '%s' in type definition", name);
}
}
}
}
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 = "(u_int)~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[255]; /* 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 = 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 = "(u_int)~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 = "(u_int)~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 = "longlong_t";
(void) peekscan(TOK_INT, &tok);
break;
case TOK_VOID:
if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
error("Void is 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:
case TOK_QUAD:
*typep = tok.str;
break;
default:
error("Type specifier expected");
}
}
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_longlong_t";
(void) peekscan(TOK_INT, &tok);
break;
case TOK_INT:
get_token(&tok);
*typep = "u_int";
break;
default:
*typep = "u_int";
break;
}
}

168
usr.bin/rpcgen/rpc_parse.h Normal file
View File

@@ -0,0 +1,168 @@
/* $NetBSD: rpc_parse.h,v 1.6 2015/05/09 21:44:47 christos Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/* @(#)rpc_parse.h 1.3 90/08/29 (C) 1987 SMI */
/*
* rpc_parse.h, Definitions for the RPCL parser
*/
enum defkind {
DEF_CONST,
DEF_STRUCT,
DEF_UNION,
DEF_ENUM,
DEF_TYPEDEF,
DEF_PROGRAM
};
typedef enum defkind defkind;
typedef 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 {
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;

275
usr.bin/rpcgen/rpc_sample.c Normal file
View File

@@ -0,0 +1,275 @@
/* $NetBSD: rpc_sample.c,v 1.13 2013/12/15 00:40:17 christos Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
#if 0
static char sccsid[] = "@(#)rpc_sample.c 1.1 90/08/30 (C) 1987 SMI";
#else
__RCSID("$NetBSD: rpc_sample.c,v 1.13 2013/12/15 00:40:17 christos Exp $");
#endif
#endif
/*
* rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler
*/
#include <stdio.h>
#include <string.h>
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
static char RQSTP[] = "rqstp";
static void write_sample_client(const char *, version_list *);
static void write_sample_server(definition *);
static void return_type(proc_list *);
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;
decl_list *l;
f_print(fout, "\n\nvoid\n");
pvname(program_name, vp->vers_num);
f_print(fout, "(char *host)\n{\n");
f_print(fout, "\tCLIENT *clnt;\n");
for (proc = vp->procs; proc != NULL; proc = proc->next) {
/* print out declarations for arguments */
if (proc->arg_num < 2 && !newstyle) {
f_print(fout, "\t");
if (streq(proc->args.decls->decl.type, "void"))
f_print(fout, "char "); /* cannot have "void"
* type */
else
ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
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);
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_%s;\n", l->decl.name);
/* pdeclaration(proc->args.argname, &l->decl, 1, ";\n" );*/
}
}
}
/* print out declarations for results */
f_print(fout, "\t");
if (streq(proc->res_type, "void"))
f_print(fout, "char"); /* cannot have "void"
* type */
else
ptype(proc->res_prefix, proc->res_type, 1);
if (!Mflag)
f_print(fout, "*");
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_res;\n");
}
f_print(fout, "\n");
/* generate creation of client handle */
f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n",
program_name, vp->vers_name, tirpcflag ? "netpath" : "udp");
f_print(fout, "\tif (clnt == NULL) {\n");
f_print(fout, "\t\tclnt_pcreateerror(host);\n");
f_print(fout, "\t\texit(1);\n\t}\n");
/* generate calls to procedures */
for (proc = vp->procs; proc != NULL; proc = proc->next) {
if (Mflag)
f_print(fout, "\tif (");
else {
f_print(fout, "\t");
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_res = ");
}
pvname(proc->proc_name, vp->vers_num);
if (proc->arg_num < 2 && !newstyle) {
f_print(fout, "(");
if (streq(proc->args.decls->decl.type, "void")) /* cast to void* */
f_print(fout, "(void *)");
f_print(fout, "&");
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_arg, ");
} else {
if (streq(proc->args.decls->decl.type, "void")) {
f_print(fout, "(clnt);\n");
} else {
f_print(fout, "(");
for (l = proc->args.decls; l != NULL; l = l->next) {
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_%s, ", l->decl.name);
}
}
}
if (Mflag) {
f_print(fout, "&");
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_res, clnt) != RPC_SUCCESS)\n");
} else {
f_print(fout, "clnt);\n");
f_print(fout, "\tif (");
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_res == NULL)\n");
}
f_print(fout, "\t\tclnt_perror(clnt, \"call failed\");\n");
}
f_print(fout, "\tclnt_destroy(clnt);\n");
f_print(fout, "}\n");
}
static void
write_sample_server(definition *def)
{
version_list *vp;
proc_list *proc;
for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
for (proc = vp->procs; proc != NULL; proc = proc->next) {
f_print(fout, "\n");
if (Mflag)
f_print(fout, "bool_t\n");
else {
return_type(proc);
f_print(fout, "*\n");
}
pvname_svc(proc->proc_name, vp->vers_num);
printarglist(proc, "result", RQSTP, "struct svc_req *");
f_print(fout, "{\n");
if (Mflag) {
f_print(fout, "\tbool_t retval = TRUE;\n");
} else {
f_print(fout, "\tstatic ");
if (streq(proc->res_type, "void"))
f_print(fout, "char "); /* cannot have void type */
else
return_type(proc);
f_print(fout, "result;\n");
}
f_print(fout,
"\n\t/*\n\t * insert server code here\n\t */\n\n");
if (Mflag) {
f_print(fout, "\treturn (retval);\n");
} else {
if (streq(proc->res_type, "void"))
f_print(fout, "\treturn ((void *)&result);\n");
else
f_print(fout, "\treturn (&result);\n");
}
f_print(fout, "}\n");
}
}
}
static void
return_type(proc_list *plist)
{
ptype(plist->res_prefix, plist->res_type, 1);
}
void
add_sample_msg(void)
{
f_print(fout, "/*\n");
f_print(fout, " * This is sample code generated by rpcgen.\n");
f_print(fout, " * These are only templates and you can use them\n");
f_print(fout, " * as a guideline for developing your own functions.\n");
f_print(fout, " */\n\n");
}
void
write_sample_clnt_main(void)
{
list *l;
definition *def;
version_list *vp;
f_print(fout, "\n\n");
f_print(fout, "int\nmain(int argc, char *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, "\texit(0);\n");
f_print(fout, "}\n");
}

492
usr.bin/rpcgen/rpc_scan.c Normal file
View File

@@ -0,0 +1,492 @@
/* $NetBSD: rpc_scan.c,v 1.15 2015/05/09 23:28:43 dholland Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
#if 0
static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI";
#else
__RCSID("$NetBSD: rpc_scan.c,v 1.15 2015/05/09 23:28:43 dholland Exp $");
#endif
#endif
/*
* rpc_scan.c, Scanner for the RPC protocol compiler
* Copyright (C) 1987, Sun Microsystems, Inc.
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
#define startcomment(where) (where[0] == '/' && where[1] == '*')
#define endcomment(where) (where[-1] == '*' && where[0] == '/')
static void unget_token(token *);
static void findstrconst(char **, const char **);
static void findchrconst(char **, const char **);
static void findconst(char **, const char **);
static void findkind(char **, token *);
static int cppline(const char *);
static int directive(const char *);
static void printdirective(const char *);
static void docppline(char *, int *, const char **);
static int pushed = 0; /* is a token pushed */
static token lasttok; /* last token, if pushed */
/*
* scan expecting 1 given token
*/
void
scan(tok_kind expect, token *tokp)
{
get_token(tokp);
if (tokp->kind != expect) {
expected1(expect);
}
}
/*
* scan expecting any of the 2 given tokens
*/
void
scan2(tok_kind expect1, tok_kind expect2, token *tokp)
{
get_token(tokp);
if (tokp->kind != expect1 && tokp->kind != expect2) {
expected2(expect1, expect2);
}
}
/*
* scan expecting any of the 3 given token
*/
void
scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp)
{
get_token(tokp);
if (tokp->kind != expect1 && tokp->kind != expect2
&& tokp->kind != expect3) {
expected3(expect1, expect2, expect3);
}
}
/*
* scan expecting a constant, possibly symbolic
*/
void
scan_num(token *tokp)
{
get_token(tokp);
switch (tokp->kind) {
case TOK_IDENT:
break;
default:
error("Expected constant or identifier");
}
}
/*
* Peek at the next token
*/
void
peek(token *tokp)
{
get_token(tokp);
unget_token(tokp);
}
/*
* Peek at the next token and scan it if it matches what you expect
*/
int
peekscan(tok_kind expect, token *tokp)
{
peek(tokp);
if (tokp->kind == expect) {
get_token(tokp);
return (1);
}
return (0);
}
/*
* Get the next token, printing out any directive that are encountered.
*/
void
get_token(token *tokp)
{
int commenting;
if (pushed) {
pushed = 0;
*tokp = lasttok;
return;
}
commenting = 0;
for (;;) {
if (*where == 0) {
for (;;) {
if (!fgets(curline, MAXLINESIZE, fin)) {
tokp->kind = TOK_EOF;
*where = 0;
return;
}
linenum++;
if (commenting) {
break;
} else
if (cppline(curline)) {
docppline(curline, &linenum,
&infilename);
} else
if (directive(curline)) {
printdirective(curline);
} else {
break;
}
}
where = curline;
} else
if (isspace((unsigned char)*where)) {
while (isspace((unsigned char)*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((unsigned char)*where) || *where == '_')) {
if (isprint((unsigned char)*where)) {
error("Illegal character '%c' in file", *where);
} else {
error("Illegal character %d in file", *where);
}
}
findkind(&where, tokp);
break;
}
}
static void
unget_token(token *tokp)
{
lasttok = *tokp;
pushed = 1;
}
static void
findstrconst(char **str, const char **val)
{
char *p;
int size;
char *tmp;
p = *str;
do {
p++;
} while (*p && *p != '"');
if (*p == 0) {
error("Unterminated string constant");
}
p++;
size = p - *str;
tmp = alloc(size + 1);
(void) strncpy(tmp, *str, size);
tmp[size] = 0;
*val = tmp;
*str = p;
}
static void
findchrconst(char **str, const char **val)
{
char *p;
int size;
char *tmp;
p = *str;
do {
p++;
} while (*p && *p != '\'');
if (*p == 0) {
error("Unterminated string constant");
}
p++;
size = p - *str;
if (size != 3) {
error("Empty character");
}
tmp = alloc(size + 1);
(void) strncpy(tmp, *str, size);
tmp[size] = 0;
*val = tmp;
*str = p;
}
static void
findconst(char **str, const char **val)
{
char *p;
int size;
char *tmp;
p = *str;
if (*p == '0' && *(p + 1) == 'x') {
p++;
do {
p++;
} while (isxdigit((unsigned char)*p));
} else {
do {
p++;
} while (isdigit((unsigned char)*p));
}
size = p - *str;
tmp = alloc(size + 1);
(void) 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_QUAD, "quadruple"},
{TOK_STRING, "string"},
{TOK_PROGRAM, "program"},
{TOK_VERSION, "version"},
{TOK_EOF, "??????"},
};
static void
findkind(char **mark, token *tokp)
{
int len;
const token *s;
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((unsigned char)str[len]) &&
str[len] != '_') {
tokp->kind = s->kind;
tokp->str = s->str;
*mark = str + len;
return;
}
}
}
tokp->kind = TOK_IDENT;
for (len = 0; isalnum((unsigned char)str[len]) ||
str[len] == '_'; len++);
tmp = alloc(len + 1);
(void) 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(char *line, int *lineno, const char **fname)
{
char *file;
int num;
char *p;
line++;
while (isspace((unsigned char)*line)) {
line++;
}
num = atoi(line);
while (isdigit((unsigned char)*line)) {
line++;
}
while (isspace((unsigned char)*line)) {
line++;
}
if (*line != '"') {
error("Preprocessor error");
}
line++;
p = file = alloc(strlen(line) + 1);
while (*line && *line != '"') {
*p++ = *line++;
}
if (*line == 0) {
error("Preprocessor error");
}
*p = 0;
if (*file == 0) {
*fname = NULL;
free(file);
} else {
*fname = file;
}
*lineno = num - 1;
}

108
usr.bin/rpcgen/rpc_scan.h Normal file
View File

@@ -0,0 +1,108 @@
/* $NetBSD: rpc_scan.h,v 1.10 2015/05/09 21:44:47 christos Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/* @(#)rpc_scan.h 1.3 90/08/29 (C) 1987 SMI */
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
/*
* rpc_scan.h, Definitions for the RPCL scanner
*/
/*
* kinds of tokens
*/
enum tok_kind {
TOK_IDENT,
TOK_CHARCONST,
TOK_STRCONST,
TOK_LPAREN,
TOK_RPAREN,
TOK_LBRACE,
TOK_RBRACE,
TOK_LBRACKET,
TOK_RBRACKET,
TOK_LANGLE,
TOK_RANGLE,
TOK_STAR,
TOK_COMMA,
TOK_EQUAL,
TOK_COLON,
TOK_SEMICOLON,
TOK_CONST,
TOK_STRUCT,
TOK_UNION,
TOK_SWITCH,
TOK_CASE,
TOK_DEFAULT,
TOK_ENUM,
TOK_TYPEDEF,
TOK_INT,
TOK_SHORT,
TOK_LONG,
TOK_HYPER,
TOK_UNSIGNED,
TOK_FLOAT,
TOK_DOUBLE,
TOK_QUAD,
TOK_OPAQUE,
TOK_CHAR,
TOK_STRING,
TOK_BOOL,
TOK_VOID,
TOK_PROGRAM,
TOK_VERSION,
TOK_EOF
};
typedef enum tok_kind tok_kind;
/*
* a token
*/
struct token {
tok_kind kind;
const char *str;
};
typedef struct token token;
/*
* routine interface
*/
void scan(tok_kind, token *);
void scan2(tok_kind, tok_kind, token *);
void scan3(tok_kind, tok_kind, tok_kind, token *);
void scan_num(token *);
void peek(token *);
int peekscan(tok_kind, token *);
void get_token(token *);

969
usr.bin/rpcgen/rpc_svcout.c Normal file
View File

@@ -0,0 +1,969 @@
/* $NetBSD: rpc_svcout.c,v 1.30 2015/09/20 15:52:11 kamil Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
#if 0
static char sccsid[] = "@(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI";
#else
__RCSID("$NetBSD: rpc_svcout.c,v 1.30 2015/09/20 15:52:11 kamil Exp $");
#endif
#endif
/*
* rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
*/
#include <stdio.h>
#include <string.h>
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
static char RQSTP[] = "rqstp";
static char TRANSP[] = "transp";
static char ARG[] = "argument";
static char RESULT[] = "result";
static char ROUTINE[] = "local";
static void p_xdrfunc(const char *, const char *);
static void internal_proctype(proc_list *);
static void write_real_program(definition *);
static void write_program(definition *, const char *);
static void printerr(const char *, const char *);
static void printif(const char *, const char *, const char *, const char *);
static void write_inetmost(char *);
static void print_return(const char *);
static void print_pmapunset(const char *);
static void print_err_message(const char *);
static void write_timeout_func(void);
static void write_caller_func(void);
static void write_pm_most(char *, int);
static void write_rpc_svc_fg(char *, const char *);
static void open_log_file(char *, const char *);
static const char *aster(const char *);
char _errbuf[256]; /* For all messages */
static void
p_xdrfunc(const char *rname, const char *typename)
{
f_print(fout, "\t\txdr_%s = (xdrproc_t)xdr_%s;\n", rname,
stringfix(typename));
}
static void
internal_proctype(proc_list *plist)
{
f_print(fout, "static ");
ptype(plist->res_prefix, plist->res_type, 1);
if (!Mflag)
f_print(fout, "*");
}
/*
* write most of the service, that is, everything but the registrations.
*/
void
write_most(char *infile /* our name */, int netflag, int nomain)
{
if (inetdflag || pmflag) {
const char *var_type;
var_type = (nomain ? "" : "static ");
f_print(fout, "%sint _rpcpmstart;", var_type);
f_print(fout, "\t\t/* Started by a port monitor ? */\n");
f_print(fout, "%sint _rpcfdtype;", var_type);
f_print(fout, "\t\t/* Whether Stream or Datagram ? */\n");
if (timerflag) {
f_print(fout, "%sint _rpcsvcdirty;", var_type);
f_print(fout, "\t/* Still serving ? */\n");
}
write_svc_aux(nomain);
}
/* write out dispatcher and stubs */
write_programs(nomain ? NULL : "static");
if (nomain)
return;
f_print(fout, "\n\n");
f_print(fout, "int main(int, char *[]);\n");
f_print(fout, "\nint\n");
f_print(fout, "main(int argc, char *argv[])\n");
f_print(fout, "{\n");
if (inetdflag) {
write_inetmost(infile); /* Includes call to write_rpc_svc_fg() */
} else {
if (tirpcflag) {
if (netflag) {
f_print(fout, "\tSVCXPRT *%s;\n", TRANSP);
f_print(fout, "\tstruct netconfig *nconf = NULL;\n");
}
f_print(fout, "\tpid_t pid;\n");
f_print(fout, "\tint i;\n");
f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n");
write_pm_most(infile, netflag);
f_print(fout, "\telse {\n");
write_rpc_svc_fg(infile, "\t\t");
f_print(fout, "\t}\n");
} else {
f_print(fout, "\tSVCXPRT *%s;\n", TRANSP);
f_print(fout, "\n");
print_pmapunset("\t");
}
}
if (logflag && !inetdflag) {
open_log_file(infile, "\t");
}
}
/*
* write a registration for the given transport
*/
void
write_netid_register(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);
f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
(void) sprintf(_errbuf, "cannot create %s service.", transp);
print_err_message(tmpbuf);
f_print(fout, "%s\t\texit(1);\n", sp);
f_print(fout, "%s\t}\n", sp);
for (l = defined; l != NULL; l = l->next) {
def = (definition *) l->val;
if (def->def_kind != DEF_PROGRAM) {
continue;
}
for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
f_print(fout,
"%s\t(void) rpcb_unset(%s, %s, nconf);\n",
sp, def->def_name, vp->vers_name);
f_print(fout,
"%s\tif (!svc_reg(%s, %s, %s, ",
sp, TRANSP, def->def_name, vp->vers_name);
pvname(def->def_name, vp->vers_num);
f_print(fout, ", nconf)) {\n");
(void) sprintf(_errbuf, "unable to register (%s, %s, %s).",
def->def_name, vp->vers_name, transp);
print_err_message(tmpbuf);
f_print(fout, "%s\t\texit(1);\n", sp);
f_print(fout, "%s\t}\n", sp);
}
}
f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp);
}
/*
* write a registration for the given transport for TLI
*/
void
write_nettype_register(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 == 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, (SIG_PF)closedown);\n");
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 definition of actual function (e.g. printmsg_1(...)).
Unpacks single user argument of printmsg_1 to call-by-value format
expected by printmsg_1. */
static void
write_real_program(definition *def)
{
version_list *vp;
proc_list *proc;
decl_list *l;
if (!newstyle)
return; /* not needed for old style */
for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
for (proc = vp->procs; proc != NULL; proc = proc->next) {
f_print(fout, "\n");
internal_proctype(proc);
f_print(fout, "\n_");
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "(");
/* arg name */
if (proc->arg_num > 1)
f_print(fout, "%s ",
proc->args.argname);
else
ptype(proc->args.decls->decl.prefix,
proc->args.decls->decl.type, 0);
f_print(fout, "*argp, ");
if (Mflag) {
if (streq(proc->res_type, "void"))
f_print(fout, "char ");
else
ptype(proc->res_prefix,
proc->res_type, 0);
f_print(fout, "%sresult, ",
aster(proc->res_type));
}
f_print(fout, "struct svc_req *%s)\n", RQSTP);
f_print(fout, "{\n");
f_print(fout, "\treturn (");
pvname_svc(proc->proc_name, vp->vers_num);
f_print(fout, "(");
if (proc->arg_num < 2) { /* single argument */
if (!streq(proc->args.decls->decl.type, "void"))
f_print(fout, "*argp, "); /* non-void */
} else {
for (l = proc->args.decls; l != NULL; l = l->next)
f_print(fout, "argp->%s, ", l->decl.name);
}
f_print(fout, "%s));\n}\n", RQSTP);
}
}
}
static void
write_program(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 ");
pvname(def->def_name, vp->vers_num);
f_print(fout, "(struct svc_req *%s, ", RQSTP);
f_print(fout, "SVCXPRT *%s);\n", TRANSP);
f_print(fout, "\n");
if (storage != NULL) {
f_print(fout, "%s ", storage);
}
f_print(fout, "void\n");
pvname(def->def_name, vp->vers_num);
f_print(fout, "(struct svc_req *%s, ", RQSTP);
f_print(fout, "SVCXPRT *%s)\n", TRANSP);
f_print(fout, "{\n");
filled = 0;
f_print(fout, "\tunion {\n");
for (proc = vp->procs; proc != NULL; proc = proc->next) {
if (proc->arg_num < 2) { /* single argument */
if (streq(proc->args.decls->decl.type,
"void")) {
continue;
}
filled = 1;
f_print(fout, "\t\t");
ptype(proc->args.decls->decl.prefix,
proc->args.decls->decl.type, 0);
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_arg;\n");
} else {
filled = 1;
f_print(fout, "\t\t%s", proc->args.argname);
f_print(fout, " ");
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_arg;\n");
}
}
if (!filled) {
f_print(fout, "\t\tint fill;\n");
}
f_print(fout, "\t} %s;\n", ARG);
if (Mflag) {
f_print(fout, "\tunion {\n");
for (proc = vp->procs; proc != NULL; proc = proc->next) {
f_print(fout, "\t\t");
if (streq(proc->res_type, "void"))
f_print(fout, "char ");
else
ptype(proc->res_prefix, proc->res_type,
1);
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_res;\n");
}
f_print(fout, "\t} %s;\n", RESULT);
f_print(fout, "\tbool_t retval;\n");
} else
f_print(fout, "\tchar *%s;\n", RESULT);
f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT);
if (Mflag)
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);
f_print(fout, "\n");
if (callerflag)
f_print(fout, "\tcaller = transp;\n"); /* EVAS */
if (timerflag)
f_print(fout, "\t_rpcsvcdirty = 1;\n");
f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
if (!nullproc(vp->procs)) {
f_print(fout, "\tcase NULLPROC:\n");
f_print(fout,
"\t\t(void) svc_sendreply(%s, (xdrproc_t)xdr_void, 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 (Mflag)
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);
if (newstyle) { /* new style: calls internal routine */
f_print(fout, "_");
pvname(proc->proc_name, vp->vers_num);
} else {
pvname_svc(proc->proc_name, vp->vers_num);
}
f_print(fout, ";\n");
f_print(fout, "\t\tbreak;\n\n");
}
f_print(fout, "\tdefault:\n");
printerr("noproc", TRANSP);
print_return("\t\t");
f_print(fout, "\t}\n");
f_print(fout, "\t(void) memset(&%s, 0, sizeof(%s));\n", ARG, ARG);
printif("getargs", TRANSP, "(caddr_t)&", ARG);
printerr("decode", TRANSP);
print_return("\t\t");
f_print(fout, "\t}\n");
if (Mflag)
f_print(fout, "\tretval = (*%s)((char *)&%s, (void *)&%s, %s);\n",
ROUTINE, ARG, RESULT, RQSTP);
else
f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n",
RESULT, ROUTINE, ARG, RQSTP);
if (Mflag)
f_print(fout,
"\tif (retval > 0 && !svc_sendreply(%s, xdr_%s, (char *)&%s)) {\n",
TRANSP, RESULT, RESULT);
else
f_print(fout,
"\tif (%s != NULL && !svc_sendreply(%s, xdr_%s, %s)) {\n",
RESULT, TRANSP, RESULT, RESULT);
printerr("systemerr", TRANSP);
f_print(fout, "\t}\n");
printif("freeargs", TRANSP, "(caddr_t)&", ARG);
(void) sprintf(_errbuf, "unable to free arguments");
print_err_message("\t\t");
f_print(fout, "\t\texit(1);\n");
f_print(fout, "\t}\n");
if (Mflag) {
f_print(fout, "\tif (!");
pvname(def->def_name, vp->vers_num);
f_print(fout, "_freeresult");
f_print(fout, "(%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, "\t\texit(1);\n");
f_print(fout, "\t}\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 *prefix, const char *arg)
{
f_print(fout, "\tif (!svc_%s(%s, xdr_%s, %s%s)) {\n",
proc, transp, arg, prefix, arg);
}
int
nullproc(proc_list *proc)
{
for (; proc != NULL; proc = proc->next) {
if (streq(proc->proc_num, "0")) {
return (1);
}
}
return (0);
}
static void
write_inetmost(char *infile)
{
f_print(fout, "\tSVCXPRT *%s = NULL;\n", TRANSP);
f_print(fout, "\tint sock;\n");
f_print(fout, "\tint proto = 0;\n");
f_print(fout, "\tstruct sockaddr_in saddr;\n");
f_print(fout, "\tsocklen_t asize = (socklen_t)sizeof(saddr);\n");
f_print(fout, "\n");
f_print(fout,
"\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
f_print(fout, "\t\tsocklen_t ssize = (socklen_t)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(void *)&_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)
f_print(fout, "%s_rpcsvcdirty = 0;\n", space);
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, "%s(void) pmap_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\");\n", space, _errbuf);
else
if (inetdflag || pmflag)
f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf);
else
f_print(fout, "%sfprintf(stderr, \"%s\");\n", space, _errbuf);
}
/*
* Write the server auxiliary function ( _msgout, timeout)
*/
void
write_svc_aux(int nomain)
{
if (!logflag)
write_msg_out();
if (!nomain)
write_timeout_func();
if (callerflag) /* EVAS */
write_caller_func(); /* EVAS */
}
/*
* Write the _msgout function
*/
void
write_msg_out(void)
{
f_print(fout, "\n");
f_print(fout, "static\n");
f_print(fout, "void _msgout(const char *msg)\n");
f_print(fout, "{\n");
f_print(fout, "#ifdef RPC_SVC_FG\n");
if (inetdflag || pmflag)
f_print(fout, "\tif (_rpcpmstart)\n");
f_print(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n");
f_print(fout, "\telse\n");
f_print(fout, "\t\t(void) fprintf(stderr, \"%%s\\n\", msg);\n");
f_print(fout, "#else\n");
f_print(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n");
f_print(fout, "#endif\n");
f_print(fout, "}\n");
}
/*
* Write the timeout function
*/
static void
write_timeout_func(void)
{
if (!timerflag)
return;
f_print(fout, "\n");
f_print(fout, "static void closedown(void);\n");
f_print(fout, "\n");
f_print(fout, "static void\n");
f_print(fout, "closedown(void)\n");
f_print(fout, "{\n");
f_print(fout, "\tif (_rpcsvcdirty == 0) {\n");
f_print(fout, "\t\textern fd_set svc_fdset;\n");
f_print(fout, "\t\tstatic int size;\n");
f_print(fout, "\t\tint i, openfd;\n");
if (tirpcflag && pmflag) {
f_print(fout, "\t\tstruct t_info tinfo;\n\n");
f_print(fout, "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n");
} else {
f_print(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n");
}
f_print(fout, "\t\t\texit(0);\n");
f_print(fout, "\t\tif (size == 0) {\n");
if (tirpcflag) {
f_print(fout, "\t\t\tstruct rlimit rl;\n\n");
f_print(fout, "\t\t\trl.rlim_max = 0;\n");
f_print(fout, "\t\t\tif (getrlimit(RLIMIT_NOFILE, &rl) == -1)\n");
f_print(fout, "\t\t\t\treturn;\n");
f_print(fout, "\t\t\tif ((size = rl.rlim_max) == 0)\n");
f_print(fout, "\t\t\t\treturn;\n");
} else {
f_print(fout, "\t\t\tsize = getdtablesize();\n");
}
f_print(fout, "\t\t}\n");
f_print(fout, "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n");
f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
f_print(fout, "\t\t\t\topenfd++;\n");
f_print(fout, "\t\tif (openfd <= (_rpcpmstart?0:1))\n");
f_print(fout, "\t\t\texit(0);\n");
f_print(fout, "\t}\n");
f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
f_print(fout, "}\n");
}
static void
write_caller_func(void)
{ /* EVAS */
#define P(s) f_print(fout, s);
P("\n");
P("char *svc_caller()\n");
P("{\n");
P(" struct sockaddr_in actual;\n");
P(" struct hostent *hp;\n");
P(" static struct in_addr prev;\n");
P(" static char cname[128];\n\n");
P(" actual = *svc_getcaller(caller);\n\n");
P(" if (memcmp((char *)&actual.sin_addr, (char *)&prev,\n");
P(" sizeof(struct in_addr)) == 0)\n");
P(" return (cname);\n\n");
P(" prev = actual.sin_addr;\n\n");
P(" hp = gethostbyaddr((char *)&actual.sin_addr, sizeof(actual.sin_addr), AF_INET);\n");
P(" if (hp == NULL) { /* dummy one up */\n");
P(" extern char *inet_ntoa();\n");
P(" strlcpy(cname, inet_ntoa(actual.sin_addr), sizeof(cname));\n");
P(" } else {\n");
P(" strlcpy(cname, hp->h_name, sizeof(cname));\n");
P(" }\n\n");
P(" return (cname);\n");
P("}\n");
#undef P
}
/*
* Write the most of port monitor support
*/
static void
write_pm_most(char *infile, int netflag)
{
list *l;
definition *def;
version_list *vp;
f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n");
f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||");
f_print(fout, " !strcmp(mname, \"timod\"))) {\n");
f_print(fout, "\t\tchar *netid;\n");
if (!netflag) { /* Not included by -n option */
f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n");
f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP);
}
if (timerflag)
f_print(fout, "\t\tint pmclose;\n");
/* not necessary, defined in /usr/include/stdlib */
/* f_print(fout, "\t\textern char *getenv();\n");*/
f_print(fout, "\n");
f_print(fout, "\t\t_rpcpmstart = 1;\n");
if (logflag)
open_log_file(infile, "\t\t");
f_print(fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n");
sprintf(_errbuf, "cannot get transport name");
print_err_message("\t\t\t");
f_print(fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n");
sprintf(_errbuf, "cannot get transport info");
print_err_message("\t\t\t");
f_print(fout, "\t\t}\n");
/*
* A kludgy support for inetd services. Inetd only works with
* sockmod, and RPC works only with timod, hence all this jugglery
*/
f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n");
f_print(fout, "\t\t\tif (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, \"timod\")) {\n");
sprintf(_errbuf, "could not get the right module");
print_err_message("\t\t\t\t");
f_print(fout, "\t\t\t\texit(1);\n");
f_print(fout, "\t\t\t}\n");
f_print(fout, "\t\t}\n");
if (timerflag)
f_print(fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
f_print(fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n",
TRANSP);
sprintf(_errbuf, "cannot create server handle");
print_err_message("\t\t\t");
f_print(fout, "\t\t\texit(1);\n");
f_print(fout, "\t\t}\n");
f_print(fout, "\t\tif (nconf)\n");
f_print(fout, "\t\t\tfreenetconfigent(nconf);\n");
for (l = defined; l != NULL; l = l->next) {
def = (definition *) l->val;
if (def->def_kind != DEF_PROGRAM) {
continue;
}
for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
f_print(fout,
"\t\tif (!svc_reg(%s, %s, %s, ",
TRANSP, def->def_name, vp->vers_name);
pvname(def->def_name, vp->vers_num);
f_print(fout, ", 0)) {\n");
(void) sprintf(_errbuf, "unable to register (%s, %s).",
def->def_name, vp->vers_name);
print_err_message("\t\t\t");
f_print(fout, "\t\t\texit(1);\n");
f_print(fout, "\t\t}\n");
}
}
if (timerflag) {
f_print(fout, "\t\tif (pmclose) {\n");
f_print(fout, "\t\t\t(void) signal(SIGALRM, (SIGPF)closedown);\n");
f_print(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
f_print(fout, "\t\t}\n");
}
f_print(fout, "\t\tsvc_run();\n");
f_print(fout, "\t\texit(1);\n");
f_print(fout, "\t\t/* NOTREACHED */\n");
f_print(fout, "\t}\n");
}
/*
* Support for backgrounding the server if self started.
*/
static void
write_rpc_svc_fg(char *infile, 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\terr(EXIT_FAILURE, \"cannot fork\");\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, "%sif (getrlimit(RLIMIT_NOFILE, &rl) == -1)\n", sp);
f_print(fout, "%s\terr(EXIT_FAILURE, \"getrlimit(RLIMIT_NOFILE)\");\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, NULL);\n", sp);
f_print(fout, "%s\t(void) close(i);\n", sp);
f_print(fout, "%s}\n", sp);
}
if (!logflag)
open_log_file(infile, sp);
f_print(fout, "#endif\n");
if (logflag)
open_log_file(infile, sp);
}
static void
open_log_file(char *infile, const char *sp)
{
char *s, *p;
s = strrchr(infile, '.');
if (s)
*s = '\0';
p = strrchr(infile, '/');
if (p)
p++;
else
p = infile;
f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, p);
if (s)
*s = '.';
}
/*
* write a registration for the given transport for Inetd
*/
void
write_inetd_register(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"))
isudp = 1;
else
isudp = 0;
f_print(fout, "\n");
if (inetdflag) {
f_print(fout, "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n",
isudp ? "SOCK_DGRAM" : "SOCK_STREAM");
}
if (inetdflag && streq(transp, "tcp")) {
f_print(fout, "%s\tif (_rpcpmstart)\n", sp);
f_print(fout, "%s\t\t%s = svc%s_create(%s",
sp, TRANSP, "fd", inetdflag ? "sock" : "RPC_ANYSOCK");
if (!isudp)
f_print(fout, ", 0, 0");
f_print(fout, ");\n");
f_print(fout, "%s\telse\n", sp);
f_print(fout, "%s\t\t%s = svc%s_create(%s",
sp, TRANSP, transp, inetdflag ? "sock" : "RPC_ANYSOCK");
if (!isudp)
f_print(fout, ", 0, 0");
f_print(fout, ");\n");
} else {
f_print(fout, "%s\t%s = svc%s_create(%s",
sp, TRANSP, transp, inetdflag ? "sock" : "RPC_ANYSOCK");
if (!isudp)
f_print(fout, ", 0, 0");
f_print(fout, ");\n");
}
f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
(void) sprintf(_errbuf, "cannot create %s service.", transp);
(void) sprintf(tmpbuf, "%s\t\t", sp);
print_err_message(tmpbuf);
f_print(fout, "%s\t\texit(1);\n", sp);
f_print(fout, "%s\t}\n", sp);
if (inetdflag) {
f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp);
f_print(fout, "%s\tproto = IPPROTO_%s;\n",
sp, isudp ? "UDP" : "TCP");
}
for (l = defined; l != NULL; l = l->next) {
def = (definition *) l->val;
if (def->def_kind != DEF_PROGRAM) {
continue;
}
for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
f_print(fout, "%s\tif (!svc_register(%s, %s, %s, ",
sp, TRANSP, def->def_name, vp->vers_name);
pvname(def->def_name, vp->vers_num);
if (inetdflag)
f_print(fout, ", proto)) {\n");
else
f_print(fout, ", IPPROTO_%s)) {\n",
isudp ? "UDP" : "TCP");
(void) sprintf(_errbuf, "unable to register (%s, %s, %s).",
def->def_name, vp->vers_name, transp);
print_err_message(tmpbuf);
f_print(fout, "%s\t\texit(1);\n", sp);
f_print(fout, "%s\t}\n", sp);
}
}
if (inetdflag)
f_print(fout, "\t}\n");
}
static const char *
aster(const char *type)
{
if (isvectordef(type, REL_ALIAS)) {
return ("");
} else {
return ("*");
}
}

181
usr.bin/rpcgen/rpc_tblout.c Normal file
View File

@@ -0,0 +1,181 @@
/* $NetBSD: rpc_tblout.c,v 1.14 2013/12/15 00:40:17 christos Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
#if 0
static char sccsid[] = "@(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI";
#else
__RCSID("$NetBSD: rpc_tblout.c,v 1.14 2013/12/15 00:40:17 christos Exp $");
#endif
#endif
/*
* rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
#define TABSIZE 8
#define TABCOUNT 5
#define TABSTOP (TABSIZE*TABCOUNT)
static char tabstr[TABCOUNT + 1] = "\t\t\t\t\t";
static const char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n";
static const char tbl_end[] = "};\n";
static const char null_entry[] = "\t(char *(*)())0,\n\
\t(xdrproc_t)xdr_void,\t\t0,\n\
\t(xdrproc_t)xdr_void,\t\t0,\n";
static const char tbl_nproc[] =
"u_int %s_nproc =\n\t(u_int)(sizeof(%s_table)/sizeof(%s_table[0]));\n\n";
static void write_table(definition *);
static void printit(const char *, const char *);
void
write_tables(void)
{
list *l;
definition *def;
f_print(fout, "\n");
for (l = defined; l != NULL; l = l->next) {
def = (definition *) l->val;
if (def->def_kind == DEF_PROGRAM) {
write_table(def);
}
}
}
static void
write_table(definition *def)
{
version_list *vp;
proc_list *proc;
int current;
int expected;
char progvers[100];
int warning;
for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
warning = 0;
s_print(progvers, "%s_%s",
locase(def->def_name), vp->vers_num);
/* print the table header */
f_print(fout, tbl_hdr, progvers);
if (nullproc(vp->procs)) {
expected = 0;
} else {
expected = 1;
f_print(fout, null_entry);
}
for (proc = vp->procs; proc != NULL; proc = proc->next) {
if (expected != 0)
f_print(fout, "\n");
current = atoi(proc->proc_num);
if (current != expected++) {
f_print(fout,
"/*\n * WARNING: table out of order\n */\n\n");
if (warning == 0) {
f_print(stderr,
"WARNING %s table is out of order\n",
progvers);
warning = 1;
nonfatalerrors = 1;
}
expected = current + 1;
}
f_print(fout, "\t(char *(*)())RPCGEN_ACTION(");
/* routine to invoke */
if (!newstyle)
pvname_svc(proc->proc_name, vp->vers_num);
else {
if (newstyle)
f_print(fout, "_"); /* calls internal func */
pvname(proc->proc_name, vp->vers_num);
}
f_print(fout, "),\n");
/* argument info */
if (proc->arg_num > 1)
printit(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, "(u_int)sizeof(");
/* XXX: should "follow" be 1 ??? */
ptype(prefix, type, 0);
f_print(fout, ")");
}
f_print(fout, ",\n");
}

479
usr.bin/rpcgen/rpc_util.c Normal file
View File

@@ -0,0 +1,479 @@
/* $NetBSD: rpc_util.c,v 1.18 2015/09/20 16:57:13 kamil Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
#if 0
static char sccsid[] = "@(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI";
#else
__RCSID("$NetBSD: rpc_util.c,v 1.18 2015/09/20 16:57:13 kamil Exp $");
#endif
#endif
/*
* rpc_util.c, Utility routines for the RPC protocol compiler
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <err.h>
#include <ctype.h>
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
#define ARGEXT "argument"
static void printwhere(void);
char curline[MAXLINESIZE]; /* current read line */
char *where = curline; /* current point in line */
int linenum = 0; /* current line number */
const char *infilename; /* input filename */
#define NFILES 7
static 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 const char *toktostr(tok_kind);
static void printbuf(void);
static void printwhere(void);
static int findit(definition *, const char *);
static const char *fixit(const char *, const char *);
static int typedefed(definition *, const char *);
/*
* 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)(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(definition *def, const char *type)
{
return (streq(def->def_name, type));
}
static const char *
fixit(const char *type, const char *orig)
{
definition *def;
def = (definition *) FINDVAL(defined, type, findit);
if (def == NULL || def->def_kind != DEF_TYPEDEF) {
return (orig);
}
switch (def->def.ty.rel) {
case REL_VECTOR:
return (def->def.ty.old_type);
case REL_ALIAS:
return (fixit(def->def.ty.old_type, orig));
default:
return (orig);
}
}
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(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 = (definition *) 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
*/
__printflike(1, 2) void
error(const char *msg, ...)
{
va_list ap;
printwhere();
fprintf(stderr, "%s:%d: ", infilename, linenum);
va_start(ap, msg);
vfprintf(stderr, msg, ap);
va_end(ap);
fprintf(stderr, "\n");
errx(EXIT_FAILURE, "Cannot recover from this error");
}
/*
* Something went wrong, unlink any files that we may have created and then
* die.
*/
void
crash(void)
{
int i;
if (!docleanup)
return;
for (i = 0; i < nfiles; i++) {
(void) unlink(outfiles[i]);
}
}
void
record_open(const char *file)
{
if (nfiles < NFILES) {
outfiles[nfiles++] = file;
} else {
errx(EXIT_FAILURE, "Too many files!");
}
}
/*
* error, token encountered was not the expected one
*/
void
expected1(tok_kind exp1)
{
error("Expected '%s'", toktostr(exp1));
}
/*
* error, token encountered was not one of two expected ones
*/
void
expected2(tok_kind exp1, tok_kind exp2)
{
error("Expected '%s' or '%s'",
toktostr(exp1),
toktostr(exp2));
}
/*
* error, token encountered was not one of 3 expected ones
*/
void
expected3(tok_kind exp1, tok_kind exp2, tok_kind exp3)
{
error("Expected '%s', '%s', or '%s'",
toktostr(exp1),
toktostr(exp2),
toktostr(exp3));
}
void
tabify(FILE *f, int tab)
{
while (tab--) {
(void) fputc('\t', f);
}
}
static token tokstrings[] = {
{TOK_IDENT, "identifier"},
{TOK_CONST, "const"},
{TOK_RPAREN, ")"},
{TOK_LPAREN, "("},
{TOK_RBRACE, "}"},
{TOK_LBRACE, "{"},
{TOK_LBRACKET, "["},
{TOK_RBRACKET, "]"},
{TOK_STAR, "*"},
{TOK_COMMA, ","},
{TOK_EQUAL, "="},
{TOK_COLON, ":"},
{TOK_SEMICOLON, ";"},
{TOK_UNION, "union"},
{TOK_STRUCT, "struct"},
{TOK_SWITCH, "switch"},
{TOK_CASE, "case"},
{TOK_DEFAULT, "default"},
{TOK_ENUM, "enum"},
{TOK_TYPEDEF, "typedef"},
{TOK_INT, "int"},
{TOK_SHORT, "short"},
{TOK_LONG, "long"},
{TOK_UNSIGNED, "unsigned"},
{TOK_DOUBLE, "double"},
{TOK_FLOAT, "float"},
{TOK_CHAR, "char"},
{TOK_STRING, "string"},
{TOK_OPAQUE, "opaque"},
{TOK_BOOL, "bool"},
{TOK_VOID, "void"},
{TOK_PROGRAM, "program"},
{TOK_VERSION, "version"},
{TOK_EOF, "??????"}
};
static const char *
toktostr(tok_kind kind)
{
token *sp;
for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++);
return (sp->str);
}
static void
printbuf(void)
{
char c;
int i;
int cnt;
#define TABSIZE 4
for (i = 0; (c = curline[i]) != '\0'; i++) {
if (c == '\t') {
cnt = 8 - (i % TABSIZE);
c = ' ';
} else {
cnt = 1;
}
while (cnt--) {
(void) fputc(c, stderr);
}
}
}
static void
printwhere(void)
{
int i;
char c;
int cnt;
printbuf();
for (i = 0; i < where - curline; i++) {
c = curline[i];
if (c == '\t') {
cnt = 8 - (i % TABSIZE);
} else {
cnt = 1;
}
while (cnt--) {
(void) fputc('^', stderr);
}
}
(void) fputc('\n', stderr);
}
char *
make_argname(const char *pname, const char *vname)
{
char *name;
size_t len;
len = strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3;
name = malloc(len);
if (!name) {
err(EXIT_FAILURE, "malloc");
}
snprintf(name, len, "%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) {
err(EXIT_FAILURE, "malloc");
}
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);
}

178
usr.bin/rpcgen/rpc_util.h Normal file
View File

@@ -0,0 +1,178 @@
/* $NetBSD: rpc_util.h,v 1.12 2015/05/13 20:13:21 joerg Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/* @(#)rpc_util.h 1.5 90/08/29 (C) 1987 SMI */
/*
* rpc_util.h, Useful definitions for the RPC protocol compiler
*/
#define alloc(size) ((char *)malloc((size_t)(size)))
#define ALLOC(object) ((object *)malloc(sizeof(object)))
#define s_print (void) sprintf
#define f_print (void) fprintf
struct list {
definition *val;
struct list *next;
};
typedef struct list list;
#define PUT 1
#define GET 2
/*
* Global variables
*/
#define MAXLINESIZE 1024
extern char curline[MAXLINESIZE];
extern char *where;
extern int linenum;
extern int docleanup;
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;
/*
* All the option flags
*/
extern int inetdflag;
extern int pmflag;
extern int tblflag;
extern int BSDflag;
extern int logflag;
extern int newstyle;
extern int Mflag; /* multithread flag */
extern int tirpcflag; /* flag for generating tirpc code */
extern int doinline; /* if this is 0, then do not generate inline code */
extern int callerflag;
/*
* Other flags related with inetd jumpstart.
*/
extern int indefinitewait;
extern int exitnow;
extern int timerflag;
extern int nonfatalerrors;
/*
* rpc_util routines
*/
#define STOREVAL(list,item) \
storeval(list,item)
#define FINDVAL(list,item,finder) \
findval(list, item, finder)
void reinitialize(void);
int streq(const char *, const char *);
definition *findval(list *, const char *,
int (*)(definition *, const char *));
void storeval(list **, definition *);
const char *fixtype(const char *);
const char *stringfix(const char *);
void ptype(const char *, const char *, int);
int isvectordef(const char *, relation);
char *locase(const char *);
void pvname_svc(const char *, const char *);
void pvname(const char *, const char *);
__dead __printflike(1, 2) void error(const char *, ...);
void crash(void);
void record_open(const char *);
void expected1(tok_kind) __dead;
void expected2(tok_kind, tok_kind) __dead;
void expected3(tok_kind, tok_kind, tok_kind) __dead;
void tabify(FILE *, int);
char *make_argname(const char *, const char *);
void add_type(int, const char *);
bas_type *find_type(const char *);
/*
* rpc_cout routines
*/
void emit(definition *);
void emit_inline(declaration *, int);
void emit_single_in_line(declaration *, int, relation);
char *upcase(const char *);
/*
* rpc_hout routines
*/
void print_datadef(definition *);
void print_progdef(definition *);
void print_funcdef(definition *, int *);
void print_funcend(int);
void pxdrfuncdecl(const char *, int);
void pprocdef(proc_list *, version_list *, const char *, int);
void pdeclaration(const char *, declaration *, int, const char *);
/*
* rpc_svcout routines
*/
void write_most(char *, int, int);
void write_netid_register(const char *);
void write_nettype_register(const char *);
void write_rest(void);
void write_programs(const char *);
int nullproc(proc_list *);
void write_svc_aux(int);
void write_msg_out(void);
void write_inetd_register(const char *);
/*
* rpc_clntout routines
*/
void write_stubs(void);
void printarglist(proc_list *, const char *, const char *, const char *);
/*
* rpc_tblout routines
*/
void write_tables(void);
/*
* rpc_sample routines
*/
void write_sample_svc(definition *);
int write_sample_clnt(definition *);
void add_sample_msg(void);
void write_sample_clnt_main(void);

501
usr.bin/rpcgen/rpcgen.1 Normal file
View File

@@ -0,0 +1,501 @@
.\" $NetBSD: rpcgen.1,v 1.24 2013/12/15 09:18:14 wiz Exp $
.\" from: @(#)rpcgen.new.1 1.1 90/11/09 TIRPC 1.0; from 40.10 of 10/10/89
.\" Copyright (c) 1988,1990 Sun Microsystems, Inc. - All Rights Reserved.
.Dd December 14, 2013
.Dt RPCGEN 1
.Os
.Sh NAME
.Nm rpcgen
.Nd Remote Procedure Call (RPC) protocol compiler
.Sh SYNOPSIS
.Nm
.Ar infile
.Nm
.Op Fl AaBbILMNTv
.Op Fl D Ar name Op =value
.Op Fl i Ar size
.Op Fl K Ar secs
.Op Fl Y Ar pathname
.Ar infile
.Nm
.Fl c Li |
.Fl h Li |
.Fl l Li |
.Fl m Li |
.Fl t Li |
.Fl S\&c Li |
.Fl S\&s
.\" .Fl S\&m
.Op Fl o Ar outfile
.Op Ar infile
.Nm
.Op Fl s Ar nettype
.Op Fl o Ar outfile
.Op Ar infile
.Nm
.Op Fl n Ar netid
.Op Fl o Ar outfile
.Op Ar infile
.Sh DESCRIPTION
.Nm
is a tool that generates C code to implement an
.Tn RPC
protocol.
The input to
.Nm
is a language similar to C known as
.Tn RPC
Language (Remote Procedure Call Language).
.Nm
is normally used as in the first synopsis where
it takes an input file and generates up to four output files.
If the
.Ar infile
is named
.Pa proto.x ,
then
.Nm
will generate a header file in
.Pa proto.h ,
.Tn XDR
routines in
.Pa proto_xdr.c ,
server-side stubs in
.Pa proto_svc.c ,
and client-side stubs in
.Pa proto_clnt.c .
With the
.Fl T
option,
it will also generate the
.Tn RPC
dispatch table in
.Pa proto_tbl.i .
With the
.Fl S\&c
option,
it will also generate sample code which would illustrate how to use the
remote procedures on the client side.
This code would be created in
.Pa proto_client.c .
With the
.Fl S\&s
option,
it will also generate a sample server code which would illustrate how to write
the remote procedures.
This code would be created in
.Pa proto_server.c .
.Pp
The server created can be started both by the port monitors
(for example,
.Em inetd
or
.Em listen )
or by itself.
When it is started by a port monitor,
it creates servers only for the transport for which
the file descriptor 0 was passed.
The name of the transport must be specified
by setting up the environmental variable
.Ev PM_TRANSPORT .
When the server generated by
.Nm
is executed,
it creates server handles for all the transports
specified in
.Ev NETPATH
environment variable,
or if it is unset,
it creates server handles for all the visible transports from
.Pa /etc/netconfig
file.
.Pp
.Em Note :
the transports are chosen at run time and not at compile time.
When the server is self-started,
it backgrounds itself by default.
A special define symbol
.Dv RPC_SVC_FG
can be used to run the server process in foreground.
.Pp
The second synopsis provides special features which allow
for the creation of more sophisticated
.Tn RPC
servers.
These features include support for user provided
.Li #defines
and
.Tn RPC
dispatch tables.
The entries in the
.Tn RPC
dispatch table contain:
.Pp
.Bl -inset -offset indent -compact
.It +
pointers to the service routine corresponding to that procedure,
.It +
a pointer to the input and output arguments,
.It +
the size of these routines
.El
.Pp
A server can use the dispatch table to check authorization
and then to execute the service routine;
a client library may use it to deal with the details of storage
management and
.Tn XDR
data conversion.
.Pp
The other three synopses shown above are used when
one does not want to generate all the output files,
but only a particular one.
Some examples of their usage is described in the
.Sx EXAMPLES
section below.
When
.Nm
is executed with the
.Fl s
option,
it creates servers for that particular class of transports.
When
executed with the
.Fl n
option,
it creates a server for the transport specified by
.Em netid .
If
.Ar infile
is not specified,
.Nm
accepts the standard input.
.Pp
The C preprocessor,
.Xr cpp 1
is run on the input file before it is actually interpreted by
.Nm
For each type of output file,
.Nm
defines a special preprocessor symbol for use by the
.Nm
programmer:
.Bl -tag -width RPC_CLNT
.It Dv RPC_HDR
defined when compiling into header files
.It Dv RPC_XDR
defined when compiling into
.Tn XDR
routines
.It Dv RPC_SVC
defined when compiling into server-side stubs
.It Dv RPC_CLNT
defined when compiling into client-side stubs
.It Dv RPC_TBL
defined when compiling into
.Tn RPC
dispatch tables
.El
.Pp
Any line beginning with
.Sq %
is passed directly into the output file,
uninterpreted by
.Nm .
.Pp
For every data type referred to in
.Ar infile
.Nm
assumes that there exists a
routine with the string
.Dq xdr_
prepended to the name of the data type.
If this routine does not exist in the
.Tn RPC/XDR
library, it must be provided.
Providing an undefined data type
allows customization of
.Tn XDR
routines.
.Sh OPTIONS
.Bl -tag -width indent
.It Fl A
Generate an
.Fn svc_caller
function.
.It Fl a
Generate all the files including sample code for client and server side.
.It Fl B
Generate BSD cplusplus macros (__BEGIN_DECLS, __END_DECLS).
.It Fl b
Compile stubs in "backwards compatible" mode, disabling support for
transport-independent RPC.
The
.Fl b
should always be specified when generating files for
.Nx ,
since there is no transport-independent RPC support in
.Nx .
.It Fl c
Compile into
.Tn XDR
routines.
.It Fl D Ar name Ns Op Ar =value
Define a symbol
.Dv name .
Equivalent to the
.Dv #define
directive in the source.
If no
.Dv value
is given,
.Dv value
is defined as 1.
This option may be specified more than once.
.It Fl h
Compile into C data-definitions (a header file).
The
.Fl T
option can be used in conjunction to produce a
header file which supports
.Tn RPC
dispatch tables.
.It Fl I
Support
.Xr inetd 8
in the server side stubs.
Servers generated using this flag can either be standalone or
started from
.Xr inetd 8 .
If a server is started as standalone, then it places itself
in the background, unless
.Dv RCP_SVC_FG
is defined, or the server is compiled without
.Fl I .
.It Fl i Ar size
Size to decide when to start generating inline code.
The default size is 3.
.It Fl K Ar secs
By default, services created using
.Nm
wait 120 seconds
after servicing a request before exiting.
That interval can be changed using the
.Fl K
flag.
To create a server that exits immediately upon servicing a request,
.Dq Fl K No 0
can be used.
To create a server that never exits, the appropriate argument is
.Dq Fl K No -1 .
.Pp
When monitoring for a server,
some port monitors, like the
.At V.4
utility
.Ic listen ,
.Em always
spawn a new process in response to a service request.
If it is known that a server will be used with such a monitor, the
server should exit immediately on completion.
For such servers,
.Nm
should be used with
.Dq Fl K No -1 .
.It Fl L
Server errors will be sent to syslog instead of stderr.
.It Fl l
Compile into client-side stubs.
.Xr inetd 8 .
.It Fl M
Generate thread-safe stubs.
This alters the calling pattern of client and
server stubs so that storage for results is allocated by the caller.
Note
that all components for a particular service (stubs, client and service
wrappers, etc.) must be built either with or without the
.Fl M
flag.
.It Fl m
Compile into server-side stubs,
but do not generate a
.Fn main
routine.
This option is useful for doing callback-routines
and for users who need to write their own
.Fn main
routine to do initialization.
.It Fl N
Use the newstyle of
.Nm .
This allows procedures to have multiple arguments.
It also uses the style of parameter passing that closely resembles C.
So, when passing an argument to a remote procedure you do not have
to pass a pointer to the argument but the argument itself.
This behaviour is different from the oldstyle
of
.Nm
generated code.
The newstyle is not the default case because of backward compatibility.
.It Fl n Ar netid
Compile into server-side stubs for the transport
specified by
.Ar netid .
There should be an entry for
.Ar netid
in the
netconfig database.
This option may be specified more than once,
so as to compile a server that serves multiple transports.
.It Fl o Ar outfile
Specify the name of the output file.
If none is specified,
standard output is used
.Po
.Fl c Fl h Fl l
.Fl m Fl n Fl s
modes only
.Pc
.It Fl s Ar nettype
Compile into server-side stubs for all the
transports belonging to the class
.Ar nettype .
The supported classes are
.Em netpath ,
.Em visible ,
.Em circuit_n ,
.Em circuit_v ,
.Em datagram_n ,
.Em datagram_v ,
.Em tcp ,
and
.Em udp
[see
.Xr rpc 3
for the meanings associated with these classes.
.Em Note :
.Bx
currently supports only the
.Em tcp
and
.Em udp
classes].
This option may be specified more than once.
.Em Note :
the transports are chosen at run time and not at compile time.
.It Fl S\&c
Generate sample code to show the use of remote procedure and how to bind
to the server before calling the client side stubs generated by
.Nm .
.It Fl S\&s
Generate skeleton code for the remote procedures on the server side.
You would need
to fill in the actual code for the remote procedures.
.\" .It Fl S\&m
.\" Generate a sample Makefile that can be used to compile the application.
.It Fl T
Generate the code to support
.Tn RPC
dispatch tables.
.It Fl t
Compile into
.Tn RPC
dispatch table.
.It Fl v
Display the version number.
.It Fl Y Ar pathname
Specify the directory where
.Nm
looks for the C pre-processor.
.El
.Pp
The options
.Fl c ,
.Fl h ,
.Fl l ,
.Fl m ,
.Fl s ,
and
.Fl t
are used exclusively to generate a particular type of file,
while the options
.Fl D
and
.Fl T
are global and can be used with the other options.
.Sh ENVIRONMENT
If the
.Ev RPCGEN_CPP
environment variable is set, its value is used as the pathname of the
C preprocessor to be run on the input file.
.Sh NOTES
The
.Tn RPC
Language does not support nesting of structures.
As a work-around,
structures can be declared at the top-level,
and their name used inside other structures in
order to achieve the same effect.
.Pp
Name clashes can occur when using program definitions,
since the apparent scoping does not really apply.
Most of these can be avoided by giving
unique names for programs,
versions,
procedures and types.
.Pp
The server code generated with
.Fl n
option refers to the transport indicated by
.Em netid
and hence is very site specific.
.Sh EXAMPLES
The command
.Pp
.Bd -literal -offset indent
$ rpcgen -T prot.x
.Ed
.Pp
generates the five files:
.Pa prot.h ,
.Pa prot_clnt.c ,
.Pa prot_svc.c ,
.Pa prot_xdr.c
and
.Pa prot_tbl.i .
.Pp
The following example sends the C data-definitions (header file)
to standard output.
.Pp
.Bd -literal -offset indent
$ rpcgen -h prot.x
.Ed
.Pp
To send the test version of the
.Dv -DTEST ,
server side stubs for
all the transport belonging to the class
.Em datagram_n
to standard output, use:
.Pp
.Bd -literal -offset indent
$ rpcgen -s datagram_n -DTEST prot.x
.Ed
.Pp
To create the server side stubs for the transport indicated by
.Em netid
.Em tcp ,
use:
.Pp
.Bd -literal -offset indent
$ rpcgen -n tcp -o prot_svc.c prot.x
.Ed
.Sh SEE ALSO
.Xr cpp 1 ,
.Xr inetd 8
.Sh HISTORY
The
.Fl M
option was first implemented in RedHat Linux, and was reimplemented by
Charles M. Hannum in
.Nx 1.6 .