xref: /plan9-contrib/sys/src/cmd/rx.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
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*);
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 */
52 	fd = call(0, host, "rexexec", &addr);
53 	if(fd >= 0)
54 		rex(fd, args);
55 
56 	error("can't dial", host);
57 	exits(0);
58 }
59 
60 int
61 call(char *net, char *host, char *service, char **na)
62 {
63 	*na = netmkaddr(host, net, service);
64 	return dial(*na, 0, 0, 0);
65 }
66 
67 void
68 rex(int fd, char *cmd)
69 {
70 	char buf[4096];
71 	int kid, n;
72 	AuthInfo *ai;
73 
74 	ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client");
75 	if(ai == nil)
76 		error("auth_proxy", nil);
77 	write(fd, cmd, strlen(cmd)+1);
78 
79 	kid = send(fd);
80 	while((n=read(fd, buf, sizeof buf))>0)
81 		if(write(1, buf, n)!=n)
82 			error("write error", 0);
83 	sleep(250);
84 	postnote(PNPROC, kid, note);/**/
85 	exits(0);
86 }
87 
88 void
89 tcpexec(int fd, char *addr, char *cmd)
90 {
91 	char *u, buf[4096];
92 	int kid, n;
93 	char *r;
94 
95 	/*
96 	 *  do the ucb authentication and send command
97 	 */
98 	u = getuser();
99 	r = ruser ? ruser : u;
100 	if(write(fd, "", 1)<0 || write(fd, u, strlen(u)+1)<0
101 	|| write(fd, r, strlen(r)+1)<0 || write(fd, cmd, strlen(cmd)+1)<0){
102 		close(fd);
103 		error("can't authenticate to", addr);
104 	}
105 
106 	/*
107 	 *  get authentication reply
108 	 */
109 	if(read(fd, buf, 1) != 1){
110 		close(fd);
111 		error("can't authenticate to", addr);
112 	}
113 	if(buf[0] != 0){
114 		while(read(fd, buf, 1) == 1){
115 			write(2, buf, 1);
116 			if(buf[0] == '\n')
117 				break;
118 		}
119 		close(fd);
120 		error("rejected by", addr);
121 	}
122 
123 	kid = send(fd);
124 	while((n=read(fd, buf, sizeof buf))>0)
125 		if(write(1, buf, n)!=n)
126 			error("write error", 0);
127 	sleep(250);
128 	postnote(PNPROC, kid, note);/**/
129 	exits(0);
130 }
131 
132 int
133 send(int fd)
134 {
135 	char buf[4096];
136 	int n;
137 	int kid;
138 	switch(kid = fork()){
139 	case -1:
140 		error("fork error", 0);
141 	case 0:
142 		break;
143 	default:
144 		return kid;
145 	}
146 	while((n=read(0, buf, sizeof buf))>0)
147 		if(write(fd, buf, n)!=n)
148 			exits("write error");
149 	if(eof)
150 		write(fd, buf, 0);
151 
152 	exits(0);
153 	return 0;			/* to keep compiler happy */
154 }
155 
156 void
157 error(char *s, char *z)
158 {
159 	if(z == 0)
160 		fprint(2, "%s: %s: %r\n", argv0, s);
161 	else
162 		fprint(2, "%s: %s %s: %r\n", argv0, s, z);
163 	exits(s);
164 }
165 
166 char *
167 buildargs(char *argv[])
168 {
169 	char *args;
170 	int m, n;
171 
172 	args = malloc(1);
173 	args[0] = '\0';
174 	n = 0;
175 	while(*argv){
176 		m = strlen(*argv) + 1;
177 		args = realloc(args, n+m +1);
178 		if(args == 0)
179 			error("malloc fail", 0);
180 		args[n] = ' ';	/* smashes old null */
181 		strcpy(args+n+1, *argv);
182 		n += m;
183 		argv++;
184 	}
185 	return args;
186 }
187