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