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