| 1 | #ifndef lint |
| 2 | static char sccsid[] = "@(#)rcmd.c 4.3 %G%"; |
| 3 | #endif |
| 4 | |
| 5 | #include <stdio.h> |
| 6 | #include <sys/types.h> |
| 7 | #include <sys/socket.h> |
| 8 | |
| 9 | #include <netinet/in.h> |
| 10 | |
| 11 | #include <netdb.h> |
| 12 | #include <errno.h> |
| 13 | |
| 14 | extern errno; |
| 15 | char *index(), *sprintf(); |
| 16 | int rcmdoptions; |
| 17 | |
| 18 | rcmd(ahost, rport, locuser, remuser, cmd, fd2p) |
| 19 | char **ahost; |
| 20 | int rport; |
| 21 | char *locuser, *remuser, *cmd; |
| 22 | int *fd2p; |
| 23 | { |
| 24 | int s, timo = 1; |
| 25 | struct sockaddr_in sin, sin2, from; |
| 26 | char c; |
| 27 | short port; |
| 28 | int lport = IPPORT_RESERVED - 1; |
| 29 | struct hostent *hp; |
| 30 | |
| 31 | hp = gethostbyname(*ahost); |
| 32 | if (hp == 0) { |
| 33 | fprintf(stderr, "%s: unknown host\n", *ahost); |
| 34 | return (-1); |
| 35 | } |
| 36 | *ahost = hp->h_name; |
| 37 | retry: |
| 38 | s = rresvport(rcmdoptions|SO_KEEPALIVE, &lport); |
| 39 | if (s < 0) |
| 40 | return (-1); |
| 41 | sin.sin_family = hp->h_addrtype; |
| 42 | bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); |
| 43 | sin.sin_port = htons((u_short)rport); |
| 44 | if (connect(s, (caddr_t)&sin, sizeof (sin), 0) < 0) { |
| 45 | if (errno == EADDRINUSE) { |
| 46 | close(s); |
| 47 | lport--; |
| 48 | goto retry; |
| 49 | } |
| 50 | if (errno == ECONNREFUSED && timo <= 16) { |
| 51 | (void) close(s); |
| 52 | sleep(timo); |
| 53 | timo *= 2; |
| 54 | goto retry; |
| 55 | } |
| 56 | perror(hp->h_name); |
| 57 | return (-1); |
| 58 | } |
| 59 | lport--; |
| 60 | if (fd2p == 0) { |
| 61 | write(s, "", 1); |
| 62 | port = 0; |
| 63 | } else { |
| 64 | char num[8]; |
| 65 | int s2 = rresvport(rcmdoptions|SO_ACCEPTCONN, &lport), s3; |
| 66 | |
| 67 | if (s2 < 0) { |
| 68 | (void) close(s); |
| 69 | return (-1); |
| 70 | } |
| 71 | listen(s2, 1); |
| 72 | socketaddr(s2, &sin2); |
| 73 | port = htons((u_short)sin2.sin_port); |
| 74 | (void) sprintf(num, "%d", port); |
| 75 | (void) write(s, num, strlen(num)+1); |
| 76 | { int len = sizeof (from); |
| 77 | s3 = accept(s2, &from, &len, 0); |
| 78 | close(s2); |
| 79 | if (s3 < 0) { |
| 80 | perror("accept"); |
| 81 | port = 0; |
| 82 | goto bad; |
| 83 | } |
| 84 | } |
| 85 | *fd2p = s3; |
| 86 | from.sin_port = ntohs((u_short)from.sin_port); |
| 87 | if (from.sin_family != AF_INET || |
| 88 | from.sin_port >= IPPORT_RESERVED) { |
| 89 | fprintf(stderr, |
| 90 | "socket: protocol failure in circuit setup.\n"); |
| 91 | goto bad2; |
| 92 | } |
| 93 | } |
| 94 | (void) write(s, locuser, strlen(locuser)+1); |
| 95 | (void) write(s, remuser, strlen(remuser)+1); |
| 96 | (void) write(s, cmd, strlen(cmd)+1); |
| 97 | if (read(s, &c, 1) != 1) { |
| 98 | perror(*ahost); |
| 99 | goto bad2; |
| 100 | } |
| 101 | if (c != 0) { |
| 102 | while (read(s, &c, 1) == 1) { |
| 103 | (void) write(2, &c, 1); |
| 104 | if (c == '\n') |
| 105 | break; |
| 106 | } |
| 107 | goto bad2; |
| 108 | } |
| 109 | return (s); |
| 110 | bad2: |
| 111 | if (port) |
| 112 | (void) close(*fd2p); |
| 113 | bad: |
| 114 | (void) close(s); |
| 115 | return (-1); |
| 116 | } |
| 117 | |
| 118 | rresvport(options, alport) |
| 119 | int options, *alport; |
| 120 | { |
| 121 | struct sockaddr_in sin; |
| 122 | int s; |
| 123 | |
| 124 | sin.sin_family = AF_INET; |
| 125 | sin.sin_addr.s_addr = 0; |
| 126 | s = socket(0, SOCK_STREAM, 0, 0); |
| 127 | if (s < 0) |
| 128 | return (-1); |
| 129 | for (;;) { |
| 130 | sin.sin_port = htons((u_short)*alport); |
| 131 | if (bind(s, (caddr_t)&sin, sizeof (sin), 0) >= 0) |
| 132 | return (s); |
| 133 | if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { |
| 134 | perror("socket"); |
| 135 | return (-1); |
| 136 | } |
| 137 | (*alport)--; |
| 138 | if (*alport == IPPORT_RESERVED/2) { |
| 139 | fprintf(stderr, "socket: All ports in use\n"); |
| 140 | return (-1); |
| 141 | } |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | ruserok(rhost, ruser, luser) |
| 146 | char *rhost, *ruser, *luser; |
| 147 | { |
| 148 | FILE *hostf; |
| 149 | char ahost[32]; |
| 150 | int first = 1; |
| 151 | |
| 152 | hostf = fopen("/etc/hosts.equiv", "r"); |
| 153 | again: |
| 154 | if (hostf) { |
| 155 | while (fgets(ahost, sizeof (ahost), hostf)) { |
| 156 | char *user; |
| 157 | if (index(ahost, '\n')) |
| 158 | *index(ahost, '\n') = 0; |
| 159 | user = index(ahost, ' '); |
| 160 | if (user) |
| 161 | *user++ = 0; |
| 162 | if (!strcmp(rhost, ahost) && |
| 163 | !strcmp(ruser, user ? user : luser)) |
| 164 | goto ok; |
| 165 | } |
| 166 | (void) fclose(hostf); |
| 167 | } |
| 168 | if (first == 1) { |
| 169 | first = 0; |
| 170 | hostf = fopen(".rhosts", "r"); |
| 171 | goto again; |
| 172 | } |
| 173 | return (-1); |
| 174 | ok: |
| 175 | (void) fclose(hostf); |
| 176 | return (0); |
| 177 | } |
| 178 | |
| 179 | socketaddr(x, y) |
| 180 | { |
| 181 | |
| 182 | syscall(103,x,y); |
| 183 | } |