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