Commit | Line | Data |
---|---|---|
f0bb4ca8 | 1 | #ifndef lint |
40d6b022 | 2 | static char sccsid[] = "@(#)rcmd.c 4.3 %G%"; |
f0bb4ca8 BJ |
3 | #endif |
4 | ||
5 | #include <stdio.h> | |
6 | #include <sys/types.h> | |
7 | #include <sys/socket.h> | |
40d6b022 SL |
8 | |
9 | #include <netinet/in.h> | |
10 | ||
3f5b52bc | 11 | #include <netdb.h> |
40d6b022 | 12 | #include <errno.h> |
f0bb4ca8 BJ |
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 | { | |
40d6b022 | 24 | int s, timo = 1; |
f0bb4ca8 BJ |
25 | struct sockaddr_in sin, sin2, from; |
26 | char c; | |
27 | short port; | |
40d6b022 | 28 | int lport = IPPORT_RESERVED - 1; |
3f5b52bc | 29 | struct hostent *hp; |
f0bb4ca8 | 30 | |
3f5b52bc SL |
31 | hp = gethostbyname(*ahost); |
32 | if (hp == 0) { | |
f0bb4ca8 BJ |
33 | fprintf(stderr, "%s: unknown host\n", *ahost); |
34 | return (-1); | |
35 | } | |
3f5b52bc | 36 | *ahost = hp->h_name; |
f0bb4ca8 | 37 | retry: |
40d6b022 | 38 | s = rresvport(rcmdoptions|SO_KEEPALIVE, &lport); |
f0bb4ca8 BJ |
39 | if (s < 0) |
40 | return (-1); | |
3f5b52bc | 41 | sin.sin_family = hp->h_addrtype; |
40d6b022 SL |
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 | } | |
f0bb4ca8 BJ |
50 | if (errno == ECONNREFUSED && timo <= 16) { |
51 | (void) close(s); | |
52 | sleep(timo); | |
53 | timo *= 2; | |
54 | goto retry; | |
55 | } | |
40d6b022 | 56 | perror(hp->h_name); |
f0bb4ca8 BJ |
57 | return (-1); |
58 | } | |
40d6b022 | 59 | lport--; |
f0bb4ca8 BJ |
60 | if (fd2p == 0) { |
61 | write(s, "", 1); | |
62 | port = 0; | |
63 | } else { | |
64 | char num[8]; | |
40d6b022 | 65 | int s2 = rresvport(rcmdoptions|SO_ACCEPTCONN, &lport), s3; |
f0bb4ca8 BJ |
66 | |
67 | if (s2 < 0) { | |
68 | (void) close(s); | |
69 | return (-1); | |
70 | } | |
40d6b022 | 71 | listen(s2, 1); |
f0bb4ca8 | 72 | socketaddr(s2, &sin2); |
3f5b52bc | 73 | port = htons((u_short)sin2.sin_port); |
f0bb4ca8 BJ |
74 | (void) sprintf(num, "%d", port); |
75 | (void) write(s, num, strlen(num)+1); | |
40d6b022 SL |
76 | { int len = sizeof (from); |
77 | s3 = accept(s2, &from, &len, 0); | |
78 | close(s2); | |
79 | if (s3 < 0) { | |
f0bb4ca8 | 80 | perror("accept"); |
40d6b022 | 81 | port = 0; |
f0bb4ca8 | 82 | goto bad; |
40d6b022 | 83 | } |
f0bb4ca8 | 84 | } |
40d6b022 SL |
85 | *fd2p = s3; |
86 | from.sin_port = ntohs((u_short)from.sin_port); | |
f0bb4ca8 BJ |
87 | if (from.sin_family != AF_INET || |
88 | from.sin_port >= IPPORT_RESERVED) { | |
89 | fprintf(stderr, | |
90 | "socket: protocol failure in circuit setup.\n"); | |
40d6b022 | 91 | goto bad2; |
f0bb4ca8 | 92 | } |
f0bb4ca8 BJ |
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); | |
40d6b022 | 99 | goto bad2; |
f0bb4ca8 BJ |
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 | } | |
40d6b022 | 107 | goto bad2; |
f0bb4ca8 BJ |
108 | } |
109 | return (s); | |
40d6b022 | 110 | bad2: |
f0bb4ca8 BJ |
111 | if (port) |
112 | (void) close(*fd2p); | |
40d6b022 | 113 | bad: |
f0bb4ca8 BJ |
114 | (void) close(s); |
115 | return (-1); | |
116 | } | |
117 | ||
40d6b022 SL |
118 | rresvport(options, alport) |
119 | int options, *alport; | |
f0bb4ca8 BJ |
120 | { |
121 | struct sockaddr_in sin; | |
f0bb4ca8 BJ |
122 | int s; |
123 | ||
40d6b022 SL |
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); | |
f0bb4ca8 | 129 | for (;;) { |
40d6b022 SL |
130 | sin.sin_port = htons((u_short)*alport); |
131 | if (bind(s, (caddr_t)&sin, sizeof (sin), 0) >= 0) | |
f0bb4ca8 BJ |
132 | return (s); |
133 | if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { | |
134 | perror("socket"); | |
135 | return (-1); | |
136 | } | |
40d6b022 SL |
137 | (*alport)--; |
138 | if (*alport == IPPORT_RESERVED/2) { | |
f0bb4ca8 BJ |
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 | } | |
40d6b022 SL |
178 | |
179 | socketaddr(x, y) | |
180 | { | |
181 | ||
182 | syscall(103,x,y); | |
183 | } |