xref: /plan9/sys/src/cmd/rx.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 
5 int	eof;		/* send an eof if true */
6 char	*note = "die: yankee dog";
7 char	*ruser;
8 char *key;
9 
10 void	rex(int, char*, char*);
11 void	tcpexec(int, char*, char*);
12 int	call(char *, char*, char*, char**);
13 char	*buildargs(char*[]);
14 int	send(int);
15 void	error(char*, char*);
16 void	sshexec(char *host, char *cmd);
17 
18 void
19 usage(void)
20 {
21 	fprint(2, "usage: %s [-e] [-k keypattern] [-l user] net!host command...\n", argv0);
22 	exits("usage");
23 }
24 
25 void
26 main(int argc, char *argv[])
27 {
28 	char *host, *addr, *args;
29 	int fd;
30 
31 	key = "";
32 	eof = 1;
33 	ARGBEGIN{
34 	case 'e':
35 		eof = 0;
36 		break;
37 	case 'k':
38 		key = EARGF(usage());
39 		break;
40 	case 'l':
41 		ruser = EARGF(usage());
42 		break;
43 	default:
44 		usage();
45 	}ARGEND
46 
47 	if(argc < 2)
48 		usage();
49 	host = argv[0];
50 	args = buildargs(&argv[1]);
51 
52 	/* try erexexec p9any then dial again with p9sk2 */
53 	fd = call(0, host, "rexexec", &addr);
54 	if(fd >= 0)
55 		rex(fd, args, "p9any");
56 	close(fd);
57 	fd = call(0, host, "rexexec", &addr);
58 	if(fd >= 0)
59 		rex(fd, args, "p9sk2");
60 	close(fd);
61 
62 	/* if there's an ssh port, try that */
63 	fd = call("tcp", host, "ssh", &addr);
64 	if(fd >= 0){
65 		close(fd);
66 		sshexec(host, args);
67 		/* falls through if no ssh */
68 	}
69 
70 	/* specific attempts */
71 	fd = call("tcp", host, "shell", &addr);
72 	if(fd >= 0)
73 		tcpexec(fd, addr, args);
74 
75 	error("can't dial", host);
76 	exits(0);
77 }
78 
79 int
80 call(char *net, char *host, char *service, char **na)
81 {
82 	*na = netmkaddr(host, net, service);
83 	return dial(*na, 0, 0, 0);
84 }
85 
86 void
87 rex(int fd, char *cmd, char *proto)
88 {
89 	char buf[4096];
90 	int kid, n;
91 	AuthInfo *ai;
92 
93 	ai = auth_proxy(fd, auth_getkey, "proto=%s role=client %s", proto, key);
94 	if(ai == nil){
95 		if(strcmp(proto, "p9any") == 0)
96 			return;
97 		error("auth_proxy", nil);
98 	}
99 	write(fd, cmd, strlen(cmd)+1);
100 
101 	kid = send(fd);
102 	while((n=read(fd, buf, sizeof buf))>0)
103 		if(write(1, buf, n)!=n)
104 			error("write error", 0);
105 	sleep(250);
106 	postnote(PNPROC, kid, note);/**/
107 	exits(0);
108 }
109 
110 void
111 tcpexec(int fd, char *addr, char *cmd)
112 {
113 	char *u, buf[4096];
114 	int kid, n;
115 	char *r;
116 
117 	/*
118 	 *  do the ucb authentication and send command
119 	 */
120 	u = getuser();
121 	r = ruser ? ruser : u;
122 	if(write(fd, "", 1)<0 || write(fd, u, strlen(u)+1)<0
123 	|| write(fd, r, strlen(r)+1)<0 || write(fd, cmd, strlen(cmd)+1)<0){
124 		close(fd);
125 		error("can't authenticate to", addr);
126 	}
127 
128 	/*
129 	 *  get authentication reply
130 	 */
131 	if(read(fd, buf, 1) != 1){
132 		close(fd);
133 		error("can't authenticate to", addr);
134 	}
135 	if(buf[0] != 0){
136 		while(read(fd, buf, 1) == 1){
137 			write(2, buf, 1);
138 			if(buf[0] == '\n')
139 				break;
140 		}
141 		close(fd);
142 		error("rejected by", addr);
143 	}
144 
145 	kid = send(fd);
146 	while((n=read(fd, buf, sizeof buf))>0)
147 		if(write(1, buf, n)!=n)
148 			error("write error", 0);
149 	sleep(250);
150 	postnote(PNPROC, kid, note);/**/
151 	exits(0);
152 }
153 
154 void
155 sshexec(char *host, char *cmd)
156 {
157 	execl("/bin/ssh", "ssh", "-iCm", host, cmd, 0);
158 }
159 
160 int
161 send(int fd)
162 {
163 	char buf[4096];
164 	int n;
165 	int kid;
166 	switch(kid = fork()){
167 	case -1:
168 		error("fork error", 0);
169 	case 0:
170 		break;
171 	default:
172 		return kid;
173 	}
174 	while((n=read(0, buf, sizeof buf))>0)
175 		if(write(fd, buf, n)!=n)
176 			exits("write error");
177 	if(eof)
178 		write(fd, buf, 0);
179 
180 	exits(0);
181 	return 0;			/* to keep compiler happy */
182 }
183 
184 void
185 error(char *s, char *z)
186 {
187 	if(z == 0)
188 		fprint(2, "%s: %s: %r\n", argv0, s);
189 	else
190 		fprint(2, "%s: %s %s: %r\n", argv0, s, z);
191 	exits(s);
192 }
193 
194 char *
195 buildargs(char *argv[])
196 {
197 	char *args;
198 	int m, n;
199 
200 	args = malloc(1);
201 	args[0] = '\0';
202 	n = 0;
203 	while(*argv){
204 		m = strlen(*argv) + 1;
205 		args = realloc(args, n+m +1);
206 		if(args == 0)
207 			error("malloc fail", 0);
208 		args[n] = ' ';	/* smashes old null */
209 		strcpy(args+n+1, *argv);
210 		n += m;
211 		argv++;
212 	}
213 	return args;
214 }
215