rexec_r()--Issue a Command on a Remote Host


  Syntax
 #include <arpa/rexec.h>

 int rexec_r(char **host,
            int port,
            char *user,
            char *password,
            char *command,
            int *errorDescriptor,
            struct hostent_data *hostEntData);

  Service Program Name: QSOSRV2

  Default Public Authority: *USE

  Threadsafe: Yes

The rexec_r() function is used to open a connection to a remote host and send a user ID, password, and command to the remote host. The remote host verifies that the user ID and password are valid. The command will be issued after the user ID and password are validated.


Parameters

host (Input) 
A pointer to a character string that identifies the name of a remote host.

port (Input) 
The well-known Internet port to use for the connection. A pointer to the structure that contains the necessary port can be obtained by issuing the following call:

   struct servent servEnt;
   struct servent_data servEntData;
   memset(&servEntData.serve_control_blk, 0x00, sizeof(struct netdb_control_block));
   getservbyname_r("exec", "tcp", &servEnt, &servEntData);

The port returned by getservbyname_r() is the port that the remote host is listening on for incoming rexec_r() connections.

user (Input) 
A character string that identifies a valid user on the remote host.

password (Input) 
A character string that identifies the password for the user on the remote host. Specify a value of NULL if password security is not active on the remote host.

command (Input) 
A character string that identifies the command to be issued on the remote host.

errorDescriptor (Input/Output) 
One of the following values:
non-NULL A second connection is set up, and a descriptor for it is placed in the errorDescriptor parameter. This connection provides standard error results of the remote command. This information will also include remote authorization failure if rexec() is unsuccessful.

NULL The standard error results of the remote command is the same as the standard output return value.


hostEntData (Input/Output) 
One of the following values:
non-NULL A pointer to the hostent_data structure, which is used to pass and preserve results between function calls. rexec_r() performs a gethostbyname_r() and each thread needs its own host data. The field host_control_block in the hostent_data structure must be initialized to hexadecimal zeros before its initial use. If compatibility with other platforms is required, then the entire hostent_data structure must be initialized to hexadecimal zeros before its initial use. The hostent_data structure is defined in <netdb.h>.

Start of V7R1 changesNULL IPv6 support is enabled. getaddrinfo is called with ai_flags set to AI_ADDRCONFIG | AI_V4MAPPED instead of gethostbyname_r(). The non-negative return value will be an AF_INET6 socket descriptor. If errorDescriptor was specified, it will also be an AF_INET6 socket descriptor. End of V7R1 changes

Return Value

rexec_r() returns an integer. Possible values are:

Non-negative
(successful) A socket to the remote command is returned and can be used to receive results of running the command on the remote host.

[-1]
(unsuccessful) Refer to errno for a description of the failure.

Authorities

No authorization is required.


Error Conditions

When the rexec_r() API fails, errno can be set to one of following:

[ECONNABORTED] Connection ended abnormally.

[ECONNREFUSED] The destination socket refused an attempted connect operation.

This error occurs when the rexec server on the remote system is not active.

[ECONNRESET] A connection with a remote socket was reset by that socket.

[EFAULT] Bad address.

System detected an address which was not valid while attempting to access the address parameters.

[EHOSTUNREACH] A route to the remote host is not available.

[EINTR] Interrupted function call.

[EINVAL] Parameter not valid.

This error code occurs when the hostEntData structure has not been initialized to hexadecimal zeros. For corrective action, see the description for structure hostent_data.

[EMFILE] Too many descriptors for this process.

[ENFILE] Too many descriptors in system.

[EPIPE] Broken pipe.

[ETIMEDOUT] A remote host did not respond within the timeout period.

This error code is returned when connection establishment times out. No connection is established. A possible cause may be that the partner application is bound, but the partner application has not yet issued a listen().

[EUNATCH] The protocol required to support address family AF_INET, is not available at this time.

[EUNKNOWN] Unknown system state.


Usage Notes


Related Information


Example

The following example shows how rexec_r() is used.

Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <qtqiconv.h>
#include <arpa/rexec.h>
#include <errno.h>

#define BufLen 256

void main()
{
  int sd = -1, rc;
  int responseLen = BufLen;
  int outbytesleft = BufLen;
  int bytesRead, saveBytesRead;
  struct hostent_data host_ent_data;
  struct servent serv_ent;
  struct servent_data serv_ent_data;
  char inbuf[BufLen];
  char outbuf[BufLen];
  char *inbufPtr = (char *)inbuf;
  char *outbufPtr = (char *)outbuf;
  iconv_t cd;
  QtqCode_T toCode   = {0,0,0,0,0,0};    /* Convert to job CCSID */
  QtqCode_T fromCode = {819,0,0,1,0,0};  /* ASCII CCSID */
  char *host;
  char remoteHost[256] = "remoteHost";
  char user[32] = "userName";
  char password[32] = "myPassword";
  char cmd[256] = "commandToRun";
  int *errordesc = NULL;

  /* Must zero this out before call or results will be unpredictable. */
  memset(&serv_ent_data.serve_control_blk, 0x00, sizeof(struct netdb_control_block));

  /* retrieve the rexec server port number */
  rc = getservbyname_r("exec", "tcp", &serv_ent, &serv_ent_data);
  if (rc < 0)
    printf("getservbyname_r() failed with errno = %d\n",errno);

  /* must zero this out before call or results will be unpredictable. */
  memset((void *)&host_ent_data.host_control_blk, 0x00, sizeof(struct netdb_control_block));
  host = remoteHost;
   errno = 0;

  /* issue the rexec_r API */
  sd = rexec_r(&host, serv_ent.s_port, user, password, cmd, errordesc, &host_ent_data);
  if (sd == -1) /* check if rexec_r() failed */
  {
    if (errno)
      printf("rexec_r() failed with errno = %d\n",errno);
    else
      printf("Either the host does not exist or remote authentication failed.\n");
  }
  else /* rexec_r() was successful */
  {
    bytesRead = recv(sd, inbuf, responseLen, 0);
    if (bytesRead > 0)
    {
      saveBytesRead = bytesRead;
      inbuf[bytesRead-1] = 0;  /* Null terminate */
      /* translate from ASCII to EBCDIC */
      cd = QtqIconvOpen(&toCode, &fromCode);
      iconv(cd,
            (unsigned char **)&inbufPtr,
            (unsigned int *)&bytesRead,
            (unsigned char **)&outbufPtr,
            (unsigned int *)&outbytesleft);
      iconv_close(cd);
      outbufPtr -= saveBytesRead;  /* Reset the buffer pointers */
      printf("%s\n",outbufPtr);
    }
    else if (bytesRead == 0)
      printf("The remote host closed the connection.\n");
    else
      printf("recv() failed with errno = %d\n",errno);
  }
  if (sd != -1)
    close(sd);  /* close the connection. */
  return;
}


API introduced: V5R1

[ Back to top | UNIX-Type APIs | APIs by category ]