/**************************************************************************** * libs/libc/netdb/lib_rexec.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: rexec_af * * Description: * The rexec() function works over IPv4 (AF_INET). By contrast, * the rexec_af() function provides an extra argument, af, that allows * the caller to select the protocol. This argument can be specified * as AF_INET, AF_INET6, or AF_UNSPEC (to allow the implementation to * select the protocol). * * Input Parameters: * * Returned Value: * OK on success; -1 on failure with the errno variable set appropriately. * ****************************************************************************/ int rexec_af(FAR char **ahost, int inport, FAR const char *user, FAR const char *passwd, FAR const char *cmd, FAR int *fd2p, sa_family_t af) { FAR struct addrinfo *res; struct addrinfo hints; char port_str[12]; int sock; int ret; if (!cmd || !ahost) { set_errno(EINVAL); return -1; } snprintf(port_str, sizeof(port_str), "%d", ntohs(inport)); memset(&hints, 0, sizeof(hints)); hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; ret = getaddrinfo(*ahost, port_str, &hints, &res); if (ret < 0) { return -1; } if (res->ai_canonname) { *ahost = strdup(res->ai_canonname); if (*ahost == NULL) { set_errno(ENOMEM); goto addr_out; } } else { *ahost = NULL; set_errno(ENOENT); goto addr_out; } sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) { goto sock_out; } if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { goto conn_out; } /* ignore second connection(fd2p always is NULL) */ write(sock, "", 1); /* Send username */ if (user) { ret = write(sock, user, strlen(user) + 1); } else { ret = write(sock, "", 1); } if (ret < 0) { goto conn_out; } /* Send passwd */ if (passwd) { ret = write(sock, passwd, strlen(passwd) + 1); } else { ret = write(sock, "", 1); } if (ret < 0) { goto conn_out; } /* Send command */ ret = write(sock, cmd, strlen(cmd) + 1); if (ret < 0) { goto conn_out; } freeaddrinfo(res); return sock; conn_out: close(sock); sock_out: free(ahost); addr_out: freeaddrinfo(res); return -1; } /**************************************************************************** * Name: rexec * * Description: * The rexec() function looks up the host *ahost using gethostbyname(), * returning -1 if the host does not exist. Otherwise, *ahost is set to * standard name of the host. If a username and password are both * specified, then these are used to authenticate to the foreign host; * otherwise the environment and then the .netrc file in user's home * direcotry are searched for appropiate information. If all the fails, * the user is prompted for the information. * * The port inport specifies which well-known DARPA Internet port to * use for the connection; the call getservbyname("exec", "tcp") will * return a pointer to a structure that contains the necessary port. * The protocol for connection is described in detail in rexecd(8). * * If the connection succeeds, a socket in the Internet domain of type * SOCK_STREAM is returned to the caller, and given to the remote * command as stdin and stdout. If fd2p is nonzero, then an auxiliary * channel to a control process will be setup, and a file descriptor for * it will be placed in *fd2p. The control process will return diagnostic * output from the command on this channel, and will also * accept bytes on this channel as being UNIX signal numbers, to be * forwarded to the process group of the command. The diagnostic * information returned does not include remote authorization failure, * as the secondary connection is set up after authorization has been * verified. If fd2p is 0, then the stderr (unit2 of the remote command) * will be made the same as the stdout and no provision is made for * sending arbitrary signals to the remote process, although you may * be able to get its attention by using out-of-band data. * * The rexec() function works over IPv4 (AF_INET). * * Input Parameters: * * Returned Value: * OK on success; -1 on failure with the errno variable set appropriately. * ****************************************************************************/ int rexec(FAR char **ahost, int inport, FAR const char *user, FAR const char *passwd, FAR const char *cmd, FAR int *fd2p) { return rexec_af(ahost, inport, user, passwd, cmd, fd2p, AF_INET); }