prcmd(3N)prcmd(3N)NAME
prcmd - return streams to parallel remote commands
SYNOPSIS
Remarks
These functions reside in and are linked using the option to the or
command.
DESCRIPTION
is an interface similar to that allows a client-side calling program to
use an existing server side daemon. however, performs in parallel
across multiple systems, the time consuming steps associated with exe‐
cuting commands remotely (connection, command invocation, and command
execution/interaction). With only command execution and interaction is
under the control of the calling program, and it requires the calling
program to perform its own calls in order to manage multiple (parallel)
connections.
Features of the existing server-side remote-shell daemon include: well
known service, access control, and shell processing of the command
line.
The calling program passes a pointer (hostp) to the first node in a
list of hosts for which to initiate, or continue, remote command pro‐
cessing via Internet socket connections. It also supplies the number
of hosts in the list (num_hosts).
The calling program makes repeated calls to to advance the status of
the host connections. Each call to causes a single call of to check
the status of all connections that require checking (if there are any).
Once a connection (to a remote command) is ready for reading, the call‐
ing program can read data from it, optionally write data to it, and
then wait for more data to be ready to read back from it.
Header File
The header file defines a structure containing the following fields of
interest:
char *prc_hostid; /* host name or IP address */
int prc_prev_status; /* previous connection status */
int prc_conn_status; /* connection status */
time_t prc_conn_time; /* time of connection */
int prc_errno; /* for failed connections */
char *prc_errmsg; /* string from remshd */
FILE *prc_fp; /* file ptr to stdin/stdout */
FILE *prc_fp2; /* file pointer to stderr */
int prc_conn_close; /* flag: close connection */
int prc_caller_status; /* caller's info about conn */
The calling program should change only the and possibly fields, as
explained below. The other fields should be considered read-only.
The header file also defines the following macros of interest:
PRC_OK /* function succeeded, check entries */
PRC_ERR_NETWORKING /* no networking on calling program's system */
PRC_ERR_NOFILE /* cannot get even one file descriptor */
PRC_ERR_RCMD /* cannot get ``shell'' service num/etc. */
PRC_ERR_SELECT /* select() failed */
PRC_CSBIT_ERR /* connection has errored out */
PRC_CONN_NONE /* needs connection */
PRC_CONN1_WAIT /* waiting for stdio connect() */
PRC_CONN2_WAIT /* waiting for stderr connect() */
PRC_CONN3_WAIT /* waiting for remshd reply */
PRC_READ_WAIT /* waiting for data */
PRC_READ_READY /* data is ready to read */
PRC_CONN_DONE /* connection closed */
PRC_CONN_NO_IPS /* can't get IP addresses */
PRC_CONN_FAILED /* various causes */
PRC_CONN_REFUSED /* by remote system */
PRC_CONN_TIMEOUT /* during connection attempt */
typedef struct prc_host *prcp_t;
#define PRC_NULLP ((prcp_t) 0)
#define PRC_SIZE (sizeof (struct prc_host))
Data Initialization
The program calling should create an array of structures with one node
for each target system. It should then call using that array (hostp)
and its size (num_hosts), a desired initial value (caller_status) for
each host's field, a command to be executed when initiating a remote
connection to a host, and a timeout value to apply to each host during
setup of its connection. This call sets the values of most fields for
each host. The calling program can change each host's value for but
normally they are all initialized to the same value.
Finally, initialize the following field in each array element before
the first call to
Either a system name (with or without domain suffix)
or an Internet address in dot notation. This value differs
for each host; it's easier for the calling program to set
the values directly than to pass a list into
This value is a pointer to memory allocated by the calling
program. Avoid destroying the underlying data until estab‐
lishes a connection to the host. After that, it no longer
needs
Like does name lookup on host names to get internet
addresses; but unlike it does not modify the calling pro‐
gram's values.
Common Error Handling
Each time is called, it scans the host list looking for actions to take
based on each host's field and its field, as described below. Errors
are generally handled as follows:
Failure If any system call fails while working on a given host's con‐
nection, except as noted below, sets that host's field to
sets its to the returned value from the failed call, and
closes all file (socket) descriptors, and stream pointers (if
any), that are associated with the host.
Refusal If any failure occurs on the remote side of a connection, as
described below, or if an invalid attempt is made to connect
back to a host's standard error port, sets to and closes the
files specified by the host's and fields. If any message is
available from the remote (up to a limit of characters) and
succeeds, saves the message text in a location pointed to by
the field; otherwise that field remains a null pointer. If
instead the refusal occurs for "local" reasons and an value
is available, sets to that value, otherwise to 0.
Timeout A connection times out when it is in or state (see below),
reports that the host is not ready for I/O, and at least
timeout seconds have elapsed since the host entered that
state. The test is low-precision, to the second, using In
this case, sets the field for the host to and closes the
files specified by the host's and fields.
A host specified by name can be listed with multiple IP addresses in
the hosts database. In that case, when a connection to one of that
host's IP addresses fails, is refused, or times out before reaching the
state, attempts to open a new connection on the host's next IP address
(up to a limit of five IP addresses per host). A failure is not
returned for a given host until all of its IP addresses have been
tried.
Host/Connection Status
See for additional information on how calling programs should handle
the following connection status conditions.
maps the value from a name to one or more IP addresses (if
it does not appear to already be an address), maps
the IP addresses to binary, gets an Internet socket
bound to a reserved port number for communicating
with the host, maps the socket descriptor to a
stream pointer using and performs a non-blocking of
the socket descriptor to the remote host's "shell"
service. The socket's send and receive buffer
sizes are the default; the calling program can
change the sizes with at any time, subject to the
restrictions documented in setsockopt(2).
If (see gethostbyname(3N)) or (see inet_addr(3N))
fails, sets the field to
Information needed for an connection includes the
port number for the "shell" service and the user
name of the effective user ID as the local and
remote user names. looks up this information the
first time it makes a connection. If cannot obtain
this information it returns (and tries again each
time it's called).
If fails with any of the following local-host
errors: or returns and the status of the host list
is unspecified.
If fails with or which means the process or the
system is out of file descriptors, or if there are
no available reserved ports, the field is left as
for later retries. After checking all host
entries, if has no open files (sockets) for any
host, and it didn't close any files during this
call, it returns — that is, all file descriptors
are in use for this process, but none by
If succeeds, or if it fails with which is normal
for a non-blocking connect request, sets to to the
current system clock in seconds, and to the stream
pointer for this socket. This host is then
included in the list per (see below).
includes this host in the
list for write-readiness. If the connection is not
ready for writing, the field is left unchanged.
When the connection is ready for writing, returns
the socket to "blocking", starts a connection for
standard error back from the remote command, sets
to the file pointer for this connection, writes
standard remsh connection information (see
remshd(1M) and also above) to the remote process
with temporarily ignored, changes to and sets to
the current system clock in seconds.
If a connection is refused, gets or on attempt to
write remsh connection information, and handles the
error as previously described in the section called
includes this host in the
list for read-readiness — for both (in case of
error) and (in case of successful connection back
to the standard error port). When neither connec‐
tion is ready for reading, the field is left
unchanged.
When the standard error connection is ready for
reading, does an on it, closes the old and revises
the value to a new file pointer for the new
socket/fd, changes to and sets to the current sys‐
tem clock in seconds.
If only the stdout connection is ready for reading,
this indicates a failure. treats this as a refused
connection, as described earlier under
Note that a host is "held" in or status if there are no available file
descriptors or reserved ports when one is needed.
includes this host in the
list for read-readiness. If the connection is not
ready for reading, the field is left unchanged.
When the connection is ready for reading, consumes
the null byte on stdout from sets to and resets to
the current system clock in seconds for use by the
calling program during the ensuing conversation.
If anything other than a null byte arrives, this
indicates a failure. treats this as a refused con‐
nection, as described previously.
includes this host in the
list for read-readiness. When the connection is
not ready for reading, the field is left unchanged.
Note, the remote command might be waiting for the
calling program to write data to it.
When the connection is ready for reading, sets to
treats a host in this status the same as
If the connection is not ready for reading, sets
back to
ignores this host's entry.
enters this state from any other state when the
field (set by the calling program) is non-zero. It
closes the files specified by and (if not already
null), sets those fields to null, and resets the
field to 0.
With any of these failure status values,
ignores this host's entry,
except if is set, the entry's
field is set to
Changes in Host Status
After each call, the field for each host's entry
is set to the previous value of its field. The
calling program can use to quickly check for a new
status for any host. This is useful for once-only
logging or display of status values except and —
each of these states can be entered many times
during a conversation.
Note that a host can leave and then re-enter sta‐
tus if it has multiple IP addresses, a connection
to one IP fails, and there are no files or ports
available to try the host's next IP address.
The calling program can freely use the field to
record additional information about the status of
each connection.
Usage Notes
Once a connection is made, and a host is in one of
the states, control of the "conversation" between
the calling program and remote host belongs to the
calling program. Conversations are of two types:
1. calling program communicates first
2. remote command communicates first
If the calling program communicates first, it must
use the field, or other means, to remember whether
or not it has sent initial data to the command;
and it must send that data upon the host entering
the state the first time. If the command communi‐
cates first, or in any conversation after the
calling program sends initial data, the calling
program must "track" the conversation to know when
to send more data, if any, and when to close the
conversation by setting
Before the calling program can send the next
input, or close the connection, it might have to
wait through a series of and states (until all
bytes of a single response from a command are
received).
After each call, the calling program should check
the return value for a serious error. If the
return value is the calling program should next
scan the hostp array and check (if desired) and
fields for each host. The calling program only
needs to take action for certain status values
(marked with · below).
After the first call: Indicates the process
ran out of socket (file)
descriptors, or reserved
ports, after making at least
one (still open) connection
(in this call, or in a previ‐
ous call). Connection to this
host is attempted again on the
next call. The calling pro‐
gram can increase the number
of available file descriptors
(by closing files or calling
or wait for existing connec‐
tions to finish their communi‐
cations.
These are internal states of little
interest to the calling program.
No action is
needed except to
call again
later. If the
calling program
might log/dis‐
play the host's
new status.
Command is running but has not yet
produced output.
If the calling
program communi‐
cates first,
meaning the com‐
mand needs some
initial input,
write it to the
file specified
by and remember
that this was
done, probably
by using the
field. Other‐
wise no action
is required,
except maybe to
log/display the
connection's
status.
Command produced output that is
ready for reading.
After reading
the output, if
the command
needs more
input, write it
now to the file
specified by If
instead the con‐
versation is
done, set the
field non-zero.
Command is done; connection was
closed in
response to the
calling program
setting the
field. No
action is
required.
The calling program can use to
quickly detect any error status. It
can use to detect that any failure
condition is new so it is only han‐
dled once, or use to record that it
was processed the first time it
appears in a return from In each
case the calling program should han‐
dle or report the error as desired.
The field appears to
be a name, not
an address, and
fails for it, or
fails on a
numeric value.
The remaining conditions only refer
to the cause of failure on the last
of the host's IP addresses, if it
has more than one.
Connection could not be initiated
for some reason (on any of the
host's
IP addresses)
due to failure
on the local
system. is set
to the value
from a failed
system call.
Connection refused. Per errno(2):
"This usually
results from
trying to con‐
nect to a ser‐
vice that is
inactive on the
foreign host."
It can also be
due to any other
remote failure,
including access
denial; and to
an improper con‐
nection attempt
on the standard
error port.
The calling pro‐
gram should
check the host's
field. If it is
not a null
pointer, message
text is avail‐
able from the
remote command;
and the calling
program must the
pointer when
done using the
value.
Connection timed out.
The connection
has remained in
one of the or
states for more
than timeout
seconds without
becoming ready
for I/O.
If the calling program performs
unbuffered I/O using socket (file)
descriptors instead of streams, it
can refer to (see fileno(3S)).
If the calling program needs to send
a signal to a remote command, it can
write the signal number to the file
specified by (see rcmd(3N)).
There is no way to tell to close
down all connections, except by set‐
ting for all hosts, and calling once
more. This causes to be set to
Regarding Timeouts
is designed to maximize the number
of parallel connections, and to max‐
imize control by the calling pro‐
gram. Therefore always calls with a
timeout value of zero (immediate
polling). It is the responsibility
of the calling program to avoid
calling more frequently than is nec‐
essary (therefore consuming exces‐
sive CPU time). For example, the
calling program might call (see
sleep(3C)) between calls. Note:
This is unnecessary if the calling
program is itself periodically
invoked by timer interrupts, or if
it performs other (time-consuming)
tasks between calls.
A timeout will occur if the host's
connection remains in one of the
wait states, or for more than time‐
out seconds without becoming ready
for I/O, and no untried IP addresses
for this host remain. When a host's
connection reaches state the first
time, resets the host's field but
does not check the host again for
timeout. The calling program can do
this if desired. The calling pro‐
gram is also permitted to reset
(update) the field as the communica‐
tions proceed (for example, each
time it writes data to the remote
command).
RETURN VALUE
Call succeeded; check the host list
for
and field
values. If
fails with
(due to a
signal
arriving),
returns
control to
the calling
program
with In
this case
some con‐
nections
might have
been
started
(entered
the state)
or stopped
(entered
the state),
under the
calling
program's
control,
but none
has
advanced
due to I/O
status;
call again
as usual.
A call failed
due to any
of a number
of serious
networking
problems
(see ear‐
lier list),
indicating
the local
host's net‐
working is
not
enabled,
and is use‐
less; is
set on
return from
A call failed
with or or
there were
no more
available
reserved
ports, at a
time when
had no open
connections
(sockets).
This means
further
attempts to
open con‐
nections
are futile
until the
calling
program, or
the system,
frees some
file
descrip‐
tors, or
reserved
ports.
Unable to get the "shell" service
port number or the username
for the
effective
user ID.
It's not
useful to
call again
unless this
condition
is cor‐
rected.
A call failed
(other than
with is set
on return
from The
data in the
host list
is valid
but no
hosts are
read-ready
or write-
ready, even
if marked
from a pre‐
vious suc‐
cessful
call.
DIAGNOSTICS
Unlike does not copy messages from
to the local standard error when
fails. It just puts the host in
state.
EXAMPLES
The following code fragment illus‐
trates how to allocate and initial‐
ize an array of hosts, and call once
for the entire list of hosts:
int index;
struct prc_host prc_host [MAXHOSTS];
prcmd_init (prc_host, argc, 0, REMCMD, TIMEOUT);
for (index = 0; index < argc; ++index)
(prc_host[index].prc_hostid) = argv [index];
if ((rc = prcmd (prc_host, argc)) != PRC_OK)
...
WARNINGS
is unsafe in multi-thread applica‐
tions.
Like should only be called by a
privileged process. Otherwise it
puts every host in status with = 13
because it cannot to any reserved
port.
At this time calls are done on files
specified by only, not assumes that
the remote command will never write
to standard error and then block,
but will instead terminate or other‐
wise close stdout. When stdout is
read-ready, the calling program can
safely do a blocking on and upon EOF
or error, check with a blocking
(Exception: For status both files
are selected since either might come
ready depending on success or fail‐
ure, as described earlier. However,
this exception is handled internal
to and does not affect the calling
program.)
Note that saves a pointer to the
value of command, not the value
itself, so the calling program must
preserve the value through all calls
of
times out after about two minutes,
even with non-blocking I/O. If this
happens to a host's connection, the
result is indistinguishable from
since returns in either case. This
is not a problem if the calling pro‐
gram allows less than two minutes
for a connection, that is, sends a
timeout value less than 120, and
calls frequently enough that the
latter catches the timeout itself
before does.
Be careful when using buffered I/O.
Avoid calls to and similar functions
in circumstances where they might
block indefinitely if less data is
available than requested. Also, be
sure to read all available data from
a host via the file specified by
before waiting again for a connec‐
tion to be read-ready. The connec‐
tion might appear not-ready even
though buffered, pending data was
already read by the stdio library,
and is available. Avoiding these
problems might require the use of
non-blocking I/O; see fcntl(2).
Be careful about writing to a socket
that might be closed if the remote
command terminates, or if the con‐
nection is lost. This can cause the
calling process to receive The call‐
ing program must handle this signal
if appropriate.
When handling a host whose connec‐
tion failed with remember to the
host's pointer if it is non-null.
This can be skipped if regaining
malloc'd memory is not required.
Performance Issues
It is faster to call with host IDs
specified as internet addresses
rather than names, because will not
need to look up each host in the
hosts database. However, when doing
so with hosts that have multiple
internet addresses, only the speci‐
fied internet address is tried.
There is a limit of about 512
reserved ports on each system, and a
soft limit for the number of avail‐
able file descriptors for each
process. Each specified host
requires two reserved ports and two
file descriptors for the connection
to check its status. defers (seri‐
alizes) additional connections once
all ports or file descriptors are in
use, so additional hosts are not
ignored, but the time required for
all connections to complete
increases accordingly. To improve
performance, it might be necessary
to increase the limit on open files
if there are a lot of hosts; see
setrlimit(2).
AUTHOR
was developed by Hewlett-Packard.
SEE ALSOremshd(1M), accept(2), bind(2), con‐
nect(2), errno(2), fcntl(2),
read(2), select(2), setsockopt(2),
socket(2), time(2), fdopen(3S),
fileno(3S), gethostbyname(3N),
inet_addr(3N), malloc(3C), rcmd(3N),
sleep(3C).
prcmd(3N)