xref: /original-bsd/lib/libc/net/rcmd.c (revision 6b7db209)
1 #ifndef lint
2 static char sccsid[] = "@(#)rcmd.c	4.4 12/17/82";
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 = 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(AF_INET, 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 }
184