Feed a small RPC language definition to rpcgen and it hands back a C header, XDR routines, client stubs and server stubs in one pass. This walkthrough uses rpcgen 1.4.2 from the rpcsvc-proto package. Allow about 15 minutes for the first run, plus more time to adapt the interface to your own application.
You need a shell, rpcgen, a C compiler and a writable working directory. None of the commands below need root. Use a private directory for generated files so an experiment cannot overwrite an existing source tree.
Checkpoint: if the version check works and you have a fresh working directory, move on to step 1. Missing rpcgen? Install the rpcsvc-proto package through your distribution's normal package manager, then repeat the check.
$ command -v rpcgen
/usr/bin/rpcgen
$ rpcgen --version
rpcgen (rpcsvc-proto) 1.4.2
Make a file named ping.x declaring one program, one version and one procedure. The procedure takes no argument and returns no value, which keeps the generated files easy to inspect. The hexadecimal program number is an example, not a registration for a production service.
$ mkdir -p "$HOME/rpcgen-demo"
$ cd "$HOME/rpcgen-demo"
$ cat > ping.x <<'EOF'
program PING_PROG {
version PING_VERS {
void PING(void) = 1;
} = 1;
} = 0x20000001;
EOF
rpcgen runs the C preprocessor over the input before interpreting it. That makes preprocessor directives and conditional definitions useful, but it also means a stray macro can silently change the interface. Keep the definition reviewable, and reach for rpcgen -DNAME only when you actually have a conditional branch to select.
Run rpcgen with the definition as its only input. With ping.x, normal mode derives four names from the base name: a header, XDR routines, client-side stubs and server-side stubs.
$ rpcgen ping.x
$ printf '%s\n' ping.h ping_xdr.c ping_clnt.c ping_svc.c | xargs -n1 test -f
$ ls -1
ping.h
ping.x
ping_clnt.c
ping_svc.c
ping_xdr.c
A successful command is not proof the interface is right. Open the generated header and check for the names you expect:
$ grep -E 'PING_(PROG|VERS)|ping_1' ping.h
#define PING_PROG 0x20000001
#define PING_VERS 1
extern void * ping_1(void *, CLIENT *);
extern void * ping_1_svc(void *, struct svc_req *);
Checkpoint: stop here if any generated file has an unexpected name, or if an old file just got replaced. Restore it from version control or backup before continuing. Never run rpcgen in a directory holding hand-edited generated files unless you have deliberately chosen to overwrite them.
Use a mode flag when you need only one class of output. -h writes C data definitions, and -o names the output explicitly. Without -o, these single-output modes print to standard output, handy for inspection but easy to lose in a scrolling terminal.
$ rpcgen -h -o checked-ping.h ping.x
$ grep -E 'PING_(PROG|VERS)' checked-ping.h
#define PING_PROG 0x20000001
#define PING_VERS 1
The other focused modes: -c for XDR routines, -l for client stubs, -m for server stubs without a generated main routine, -t for a dispatch table, and -s or -n for server-side stubs tied to a transport class or identifier. These flags describe what gets generated; they do not compile anything.
If your server needs an RPC dispatch table, add -T. It is a global option, so use it alongside normal generation and check for the extra table file:
$ mkdir -p dispatch
$ cd dispatch
$ rpcgen -T -o ping.h ../ping.x
$ rpcgen -T -c -o ping_xdr.c ../ping.x
$ rpcgen -T -l -o ping_clnt.c ../ping.x
$ rpcgen -T -m -o ping_svc.c ../ping.x
$ rpcgen -T -t -o ping_tbl.i ../ping.x
$ test -s ping_tbl.i && echo "dispatch table generated"
dispatch table generated
Spelling out each file this way avoids guessing which files a later build step will regenerate. For the ordinary five-file set, rpcgen -T ping.x is shorter and produces the table alongside the header and stubs in one go.
Generated code includes <rpc/rpc.h>, so a clean rpcgen run says nothing about whether your compiler actually has the RPC headers and library. Check the generated text first, then ask the compiler for syntax-only validation using your system's own include and library layout:
$ grep -nE '^#include|_RPCGEN|ping_1' ping.h ping_clnt.c ping_svc.c ping_xdr.c
$ cc -fsyntax-only -I. ping_xdr.c ping_clnt.c ping_svc.c
$ echo $?
0
Compiler cannot find rpc/rpc.h? That is a missing development package or include path, not a flaw in your RPC definition. Reports a duplicate identifier or an unexpected procedure signature instead? Check the program, version, procedure and type names in ping.x. The manpage warns that apparent scoping does not prevent name clashes, so keep names unique across a larger interface.
Normal server generation creates a static service for the transports selected with -s. -I also makes a service suitable for starting from inetd. A generated service can create handles for transports named by NETPATH; when that variable is unset, it falls back to the visible transports in /etc/netconfig. These are run-time choices, not compile-time ones.
Do not deploy a generated server just because it compiles. Review the transport and launcher configuration, restrict exposure with your host's normal network controls, and test with a non-production program number first. -n mode embeds a particular transport identifier and is therefore site-specific.
Warning: generated services wait 120 seconds after servicing a request by default. Use -K 0 if the service should exit immediately after a request, or -K -1 if it should never exit. Only use -K -1 for a service started by a port monitor whose process model actually requires it, and check the generated service against its launcher before changing this value.
-N for the new style, which permits multiple arguments and passes them in a C-like way. It is not the default because old generated interfaces still use the historical style.NETPATH or /etc/netconfig inputs; transport selection is part of the build environment, not just the .x file.To undo this walkthrough, remove only the private demo directory once you have confirmed it holds no useful work. Under version control, use the repository's normal restore process for generated files and review the diff before committing. Never remove a shared source directory or a production-generated service as part of cleanup.
rpcgen --version reports the rpcsvc-proto build you intend to use..x file has distinct program, version, procedure and type names.-K settings are documented before anything starts.