xref: /original-bsd/lib/libcompat/4.3/rexec.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1980, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)rexec.c	8.1 (Berkeley) 06/04/93";
10 #endif /* LIBC_SCCS and not lint */
11 
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 
15 #include <netinet/in.h>
16 
17 #include <stdio.h>
18 #include <netdb.h>
19 #include <errno.h>
20 
21 extern	errno;
22 char	*index();
23 int	rexecoptions;
24 char	*getpass(), *getlogin();
25 
26 rexec(ahost, rport, name, pass, cmd, fd2p)
27 	char **ahost;
28 	int rport;
29 	char *name, *pass, *cmd;
30 	int *fd2p;
31 {
32 	struct sockaddr_in sin, sin2, from;
33 	struct hostent *hp;
34 	u_short port;
35 	int s, timo = 1, s3;
36 	char c;
37 
38 	hp = gethostbyname(*ahost);
39 	if (hp == 0) {
40 		herror(*ahost);
41 		return (-1);
42 	}
43 	*ahost = hp->h_name;
44 	ruserpass(hp->h_name, &name, &pass);
45 retry:
46 	s = socket(AF_INET, SOCK_STREAM, 0);
47 	if (s < 0) {
48 		perror("rexec: socket");
49 		return (-1);
50 	}
51 	sin.sin_family = hp->h_addrtype;
52 	sin.sin_port = rport;
53 	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
54 	if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
55 		if (errno == ECONNREFUSED && timo <= 16) {
56 			(void) close(s);
57 			sleep(timo);
58 			timo *= 2;
59 			goto retry;
60 		}
61 		perror(hp->h_name);
62 		return (-1);
63 	}
64 	if (fd2p == 0) {
65 		(void) write(s, "", 1);
66 		port = 0;
67 	} else {
68 		char num[8];
69 		int s2, sin2len;
70 
71 		s2 = socket(AF_INET, SOCK_STREAM, 0);
72 		if (s2 < 0) {
73 			(void) close(s);
74 			return (-1);
75 		}
76 		listen(s2, 1);
77 		sin2len = sizeof (sin2);
78 		if (getsockname(s2, (struct sockaddr *)&sin2, &sin2len) < 0 ||
79 		  sin2len != sizeof (sin2)) {
80 			perror("getsockname");
81 			(void) close(s2);
82 			goto bad;
83 		}
84 		port = ntohs((u_short)sin2.sin_port);
85 		(void) sprintf(num, "%u", port);
86 		(void) write(s, num, strlen(num)+1);
87 		{ int len = sizeof (from);
88 		  s3 = accept(s2, (struct sockaddr *)&from, &len);
89 		  close(s2);
90 		  if (s3 < 0) {
91 			perror("accept");
92 			port = 0;
93 			goto bad;
94 		  }
95 		}
96 		*fd2p = s3;
97 	}
98 	(void) write(s, name, strlen(name) + 1);
99 	/* should public key encypt the password here */
100 	(void) write(s, pass, strlen(pass) + 1);
101 	(void) write(s, cmd, strlen(cmd) + 1);
102 	if (read(s, &c, 1) != 1) {
103 		perror(*ahost);
104 		goto bad;
105 	}
106 	if (c != 0) {
107 		while (read(s, &c, 1) == 1) {
108 			(void) write(2, &c, 1);
109 			if (c == '\n')
110 				break;
111 		}
112 		goto bad;
113 	}
114 	return (s);
115 bad:
116 	if (port)
117 		(void) close(*fd2p);
118 	(void) close(s);
119 	return (-1);
120 }
121