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