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