home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / cvs-1.8.7-src.tgz / tar.out / fsf / cvs / macintosh / rcmd.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  7KB  |  250 lines

  1. /*    $NetBSD: rcmd.c,v 1.12 1995/06/03 22:33:34 mycroft Exp $    */
  2.  
  3. /*
  4.  * Copyright (c) 1983, 1993, 1994
  5.  *    The Regents of the University of California.  All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  * 3. All advertising materials mentioning features or use of this software
  16.  *    must display the following acknowledgement:
  17.  *    This product includes software developed by the University of
  18.  *    California, Berkeley and its contributors.
  19.  * 4. Neither the name of the University nor the names of its contributors
  20.  *    may be used to endorse or promote products derived from this software
  21.  *    without specific prior written permission.
  22.  *
  23.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  */
  35.  
  36. #include "mac_config.h"
  37. #if defined(LIBC_SCCS) && !defined(lint)
  38. #if 0
  39. static char sccsid[] = "@(#)rcmd.c    8.3 (Berkeley) 3/26/94";
  40. #else
  41. static char *rcsid = "$NetBSD: rcmd.c,v 1.12 1995/06/03 22:33:34 mycroft Exp $";
  42. #endif
  43. #endif /* LIBC_SCCS and not lint */
  44.  
  45. #define MAXPATHLEN 1024
  46. #ifndef MAXHOSTNAMELEN
  47. #define    MAXHOSTNAMELEN    256
  48. #endif
  49.  
  50. #include <GUSI.h>
  51. #include <sys/errno.h>
  52. #include <sys/socket.h>
  53. #include <sys/stat.h>
  54.  
  55. #include <netinet/in.h>
  56.  
  57. #include <signal.h>
  58. #include <fcntl.h>
  59. #include <netdb.h>
  60. #include <unistd.h>
  61. #include <pwd.h>
  62. #include <stdio.h>
  63. #include <ctype.h>
  64. #include <string.h>
  65.  
  66. int
  67. rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
  68.     char **ahost;
  69.     u_short rport;
  70.     const char *locuser, *remuser, *cmd;
  71.     int *fd2p;
  72. {
  73.     struct hostent *hp;
  74.     struct sockaddr_in sin, from;
  75.     fd_set reads;
  76.     long oldmask;
  77.     pid_t pid;
  78.     int s, lport, timo;
  79.     char c;
  80.  
  81.     pid = getpid();
  82.     hp = gethostbyname(*ahost);
  83.     if (hp == NULL) {
  84.         /*herror(*ahost);*/
  85.         (void)fprintf(stderr,
  86.                     "rcmd: socket: gethostbyname failed for %s\n", *ahost);
  87.         return (-1);
  88.     }
  89.     *ahost = hp->h_name;
  90.     /* oldmask = sigblock(sigmask(SIGURG)); */
  91.     for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
  92.         s = rresvport(&lport);
  93.         if (s < 0) {
  94.             if (errno == EDEADLK) /* EDEADLK */
  95.                 (void)fprintf(stderr,
  96.                     "rcmd: socket: All ports in use\n");
  97.             else
  98.                 (void)fprintf(stderr, "rcmd: socket: %s\n",
  99.                     strerror(errno));
  100.             /* sigsetmask(oldmask); */
  101.             return (-1);
  102.         }
  103.         fcntl(s, F_SETOWN, pid);
  104.         sin.sin_len = sizeof(struct sockaddr_in);
  105.         sin.sin_family = hp->h_addrtype;
  106.         sin.sin_port = rport;
  107.         bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
  108.         if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
  109.             break;
  110.         (void)close(s);
  111.         if (errno == EADDRINUSE) {
  112.             lport--;
  113.             continue;
  114.         }
  115.         if (errno == ECONNREFUSED && timo <= 16) {
  116.             (void)sleep(timo);
  117.             timo *= 2;
  118.             continue;
  119.         }
  120.         if (hp->h_addr_list[1] != NULL) {
  121.             int oerrno = errno;
  122.  
  123.             (void)fprintf(stderr, "connect to address %s: ",
  124.                 inet_ntoa(sin.sin_addr));
  125.             errno = oerrno;
  126.             perror(0);
  127.             hp->h_addr_list++;
  128.             bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
  129.             (void)fprintf(stderr, "Trying %s...\n",
  130.                 inet_ntoa(sin.sin_addr));
  131.             continue;
  132.         }
  133.         (void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno));
  134.         /* sigsetmask(oldmask); */
  135.         return (-1);
  136.     }
  137.     lport--;
  138.     if (fd2p == 0) {
  139.         write(s, "", 1);
  140.         lport = 0;
  141.     } else {
  142.         char num[8];
  143.         int s2 = rresvport(&lport), s3;
  144.         int len = sizeof(from);
  145.         if (s2 < 0)
  146.             goto bad;
  147.         listen(s2, 1);
  148.         /*(void)snprintf(num, sizeof(num), "%d", lport);*/
  149.         sprintf(num,"%d", lport);
  150.         if (write(s, num, strlen(num)+1) != strlen(num)+1) {
  151.             (void)fprintf(stderr,
  152.                 "rcmd: write (setting up stderr): %s\n",
  153.                 strerror(errno));
  154.             (void)close(s2);
  155.             goto bad;
  156.         }
  157.         FD_ZERO(&reads);
  158.         FD_SET(s, &reads);
  159.         FD_SET(s2, &reads);
  160.         errno = 0;
  161.         if (select(MAX(s, s2) + 1, &reads, 0, 0, 0) < 1 ||
  162.             !FD_ISSET(s2, &reads)) {
  163.             if (errno != 0)
  164.                 (void)fprintf(stderr,
  165.                     "rcmd: select (setting up stderr): %s\n",
  166.                     strerror(errno));
  167.             else
  168.                 (void)fprintf(stderr,
  169.                 "select: protocol failure in circuit setup\n");
  170.             (void)close(s2);
  171.             goto bad;
  172.         }
  173.         s3 = accept(s2, (struct sockaddr *)&from, &len);
  174.         (void)close(s2);
  175.         if (s3 < 0) {
  176.             (void)fprintf(stderr,
  177.                 "rcmd: accept: %s\n", strerror(errno));
  178.             lport = 0;
  179.             goto bad;
  180.         }
  181.         *fd2p = s3;
  182.         from.sin_port = ntohs(from.sin_port);
  183.         if (from.sin_family != AF_INET ||
  184.             from.sin_port >= IPPORT_RESERVED ||
  185.             from.sin_port < IPPORT_RESERVED / 2) {
  186.             (void)fprintf(stderr,
  187.                 "socket: protocol failure in circuit setup.\n");
  188.             goto bad2;
  189.         }
  190.     }
  191.     (void)write(s, locuser, strlen(locuser)+1);
  192.     (void)write(s, remuser, strlen(remuser)+1);
  193.     (void)write(s, cmd, strlen(cmd)+1);
  194.     if (read(s, &c, 1) != 1) {
  195.         (void)fprintf(stderr,
  196.             "rcmd: %s: %s\n", *ahost, strerror(errno));
  197.         goto bad2;
  198.     }
  199.     if (c != 0) {
  200.         while (read(s, &c, 1) == 1) {
  201.             (void)write(STDERR_FILENO, &c, 1);
  202.             if (c == '\n')
  203.                 break;
  204.         }
  205.         goto bad2;
  206.     }
  207.     /* sigsetmask(oldmask); */
  208.     return (s);
  209. bad2:
  210.     if (lport)
  211.         (void)close(*fd2p);
  212. bad:
  213.     (void)close(s);
  214.     /* sigsetmask(oldmask); */
  215.     return (-1);
  216. }
  217.  
  218. int
  219. rresvport(alport)
  220.     int *alport;
  221. {
  222.     struct sockaddr_in sin;
  223.     int s;
  224.  
  225.     sin.sin_len = sizeof(struct sockaddr_in);
  226.     sin.sin_family = AF_INET;
  227.     sin.sin_addr.s_addr = INADDR_ANY;
  228.     s = socket(AF_INET, SOCK_STREAM, 0);
  229.     if (s < 0)
  230.         return (-1);
  231.     for (;;) {
  232.         sin.sin_port = htons((u_short)*alport);
  233.         if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
  234.             return (s);
  235.         if (errno != EADDRINUSE) {
  236.             (void)close(s);
  237.             (void)fprintf(stderr, "rresvport: bind failed with %d\n", errno);
  238.             return (-1);
  239.         }
  240.         (*alport)--;
  241.         if (*alport == IPPORT_RESERVED/2) {
  242.             (void)close(s);
  243.             errno = EDEADLK;        /* close */
  244.             (void)fprintf(stderr, "rresvport: bind failed with EDEADLCK\n");
  245.             return (-1);
  246.         }
  247.     }
  248. }
  249.  
  250.