]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/9pcon.c
change icanhasvmx to report extra info only with -v
[plan9front.git] / sys / src / cmd / aux / 9pcon.c
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include <bio.h>
6
7 uint messagesize = 65536;       /* just a buffer size */
8
9 void
10 usage(void)
11 {
12         fprint(2, "usage: aux/9pcon [-m messagesize] /srv/service | -c command | -n networkaddress\n");
13         exits("usage");
14 }
15
16 int
17 connectcmd(char *cmd)
18 {
19         int p[2];
20
21         if(pipe(p) < 0)
22                 return -1;
23         switch(fork()){
24         case -1:
25                 fprint(2, "fork failed: %r\n");
26                 _exits("exec");
27         case 0:
28                 dup(p[0], 0);
29                 dup(p[0], 1);
30                 close(p[1]);
31                 execl("/bin/rc", "rc", "-c", cmd, nil);
32                 fprint(2, "exec failed: %r\n");
33                 _exits("exec");
34         default:
35                 close(p[0]);
36                 return p[1];
37         }
38 }
39
40 void
41 watch(int fd)
42 {
43         int n;
44         uchar *buf;
45         Fcall f;
46         
47         buf = malloc(messagesize);
48         if(buf == nil)
49                 sysfatal("out of memory");
50
51         while((n = read9pmsg(fd, buf, messagesize)) > 0){
52                 if(convM2S(buf, n, &f) != n){
53                         print("convM2S: %r\n");
54                         continue;
55                 }
56                 print("\t<- %F\n", &f);
57         }
58         if(n == 0)
59                 print("server eof\n");
60         else
61                 print("read9pmsg from server: %r\n");
62 }
63
64 char*
65 tversion(Fcall *f, int, char **argv)
66 {
67         f->msize = strtol(argv[0], 0, 0);
68         if(f->msize > messagesize)
69                 return "message size too big; use -m option on command line";
70         f->version = argv[1];
71         return nil;
72 }
73
74 char*
75 tauth(Fcall *f, int, char **argv)
76 {
77         f->afid = strtol(argv[0], 0, 0);
78         f->uname = argv[1];
79         f->aname = argv[2];
80         return nil;
81 }
82
83 char*
84 tflush(Fcall *f, int, char **argv)
85 {
86         f->oldtag = strtol(argv[0], 0, 0);
87         return nil;
88 }
89
90 char*
91 tattach(Fcall *f, int, char **argv)
92 {
93         f->fid = strtol(argv[0], 0, 0);
94         f->afid = strtol(argv[1], 0, 0);
95         f->uname = argv[2];
96         f->aname = argv[3];
97         return nil;
98 }
99
100 char*
101 twalk(Fcall *f, int argc, char **argv)
102 {
103         int i;
104
105         if(argc < 2)
106                 return "usage: Twalk tag fid newfid [name...]";
107         f->fid = strtol(argv[0], 0, 0);
108         f->newfid = strtol(argv[1], 0, 0);
109         f->nwname = argc-2;
110         if(f->nwname > MAXWELEM)
111                 return "too many names";
112         for(i=0; i<argc-2; i++)
113                 f->wname[i] = argv[2+i];
114         return nil;
115 }
116
117 char*
118 topen(Fcall *f, int, char **argv)
119 {
120         f->fid = strtol(argv[0], 0, 0);
121         f->mode = strtol(argv[1], 0, 0);
122         return nil;
123 }
124
125 char*
126 tcreate(Fcall *f, int, char **argv)
127 {
128         f->fid = strtol(argv[0], 0, 0);
129         f->name = argv[1];
130         f->perm = strtoul(argv[2], 0, 8);
131         f->mode = strtol(argv[3], 0, 0);
132         return nil;
133 }
134
135 char*
136 tread(Fcall *f, int, char **argv)
137 {
138         f->fid = strtol(argv[0], 0, 0);
139         f->offset = strtoll(argv[1], 0, 0);
140         f->count = strtol(argv[2], 0, 0);
141         return nil;
142 }
143
144 char*
145 twrite(Fcall *f, int, char **argv)
146 {
147         f->fid = strtol(argv[0], 0, 0);
148         f->offset = strtoll(argv[1], 0, 0);
149         f->data = argv[2];
150         f->count = strlen(argv[2]);
151         return nil;
152 }
153
154 char*
155 tclunk(Fcall *f, int, char **argv)
156 {
157         f->fid = strtol(argv[0], 0, 0);
158         return nil;
159 }
160
161 char*
162 tremove(Fcall *f, int, char **argv)
163 {
164         f->fid = strtol(argv[0], 0, 0);
165         return nil;
166 }
167
168 char*
169 tstat(Fcall *f, int, char **argv)
170 {
171         f->fid = strtol(argv[0], 0, 0);
172         return nil;
173 }
174
175 ulong
176 xstrtoul(char *s)
177 {
178         if(strcmp(s, "~0") == 0)
179                 return ~0UL;
180         return strtoul(s, 0, 0);
181 }
182
183 uvlong
184 xstrtoull(char *s)
185 {
186         if(strcmp(s, "~0") == 0)
187                 return ~0ULL;
188         return strtoull(s, 0, 0);
189 }
190
191 char*
192 twstat(Fcall *f, int, char **argv)
193 {
194         static uchar buf[DIRMAX];
195         Dir d;
196
197         memset(&d, 0, sizeof d);
198         nulldir(&d);
199         d.name = argv[1];
200         d.uid = argv[2];
201         d.gid = argv[3];
202         d.mode = xstrtoul(argv[4]);
203         d.mtime = xstrtoul(argv[5]);
204         d.length = xstrtoull(argv[6]);
205
206         f->fid = strtol(argv[0], 0, 0);
207         f->stat = buf;
208         f->nstat = convD2M(&d, buf, sizeof buf);
209         if(f->nstat < BIT16SZ)
210                 return "convD2M failed (internal error)";
211
212         return nil;
213 }
214
215 int taggen;
216
217 char*
218 settag(Fcall*, int, char **argv)
219 {
220         static char buf[120];
221
222         taggen = strtol(argv[0], 0, 0)-1;
223         snprint(buf, sizeof buf, "next tag is %d", taggen+1);
224         return buf;
225 }
226
227 typedef struct Cmd Cmd;
228 struct Cmd {
229         char *name;
230         int type;
231         int argc;
232         char *usage;
233         char *(*fn)(Fcall *f, int, char**);
234 };
235
236 Cmd msg9p[] = {
237         "Tversion", Tversion, 2, "messagesize version", tversion,
238         "Tauth", Tauth, 3, "afid uname aname", tauth,
239         "Tflush", Tflush, 1, "oldtag", tflush,
240         "Tattach", Tattach, 4, "fid afid uname aname", tattach,
241         "Twalk", Twalk, 0, "fid newfid [name...]", twalk,
242         "Topen", Topen, 2, "fid mode", topen,
243         "Tcreate", Tcreate, 4, "fid name perm mode", tcreate,
244         "Tread", Tread, 3, "fid offset count", tread,
245         "Twrite", Twrite, 3, "fid offset data", twrite,
246         "Tclunk", Tclunk, 1, "fid", tclunk,
247         "Tremove", Tremove, 1, "fid", tremove,
248         "Tstat", Tstat, 1, "fid", tstat,
249         "Twstat", Twstat, 7, "fid name uid gid mode mtime length", twstat,
250         "nexttag", 0, 0, "", settag,
251 };
252
253 void
254 shell9p(int fd)
255 {
256         char *e, *f[10], *p;
257         uchar *buf;
258         int i, n, nf;
259         Biobuf b;
260         Fcall t;
261
262         buf = malloc(messagesize);
263         if(buf == nil){
264                 fprint(2, "out of memory\n");
265                 return;
266         }
267
268         taggen = 0;
269         Binit(&b, 0, OREAD);
270         while(p = Brdline(&b, '\n')){
271                 p[Blinelen(&b)-1] = '\0';
272                 if(p[0] == '#')
273                         continue;
274                 if((nf = tokenize(p, f, nelem(f))) == 0)
275                         continue;
276                 for(i=0; i<nelem(msg9p); i++)
277                         if(strcmp(f[0], msg9p[i].name) == 0)
278                                 break;
279                 if(i == nelem(msg9p)){
280                         fprint(2, "?unknown message\n");
281                         continue;
282                 }
283                 memset(&t, 0, sizeof t);
284                 t.type = msg9p[i].type;
285                 if(t.type == Tversion)
286                         t.tag = NOTAG;
287                 else
288                         t.tag = ++taggen;
289                 if(nf < 1 || (msg9p[i].argc && nf != 1+msg9p[i].argc)){
290                         fprint(2, "?usage: %s %s\n", msg9p[i].name, msg9p[i].usage);
291                         continue;
292                 }
293                 if(e = msg9p[i].fn(&t, nf-1, f+1)){
294                         fprint(2, "?%s\n", e);
295                         continue;
296                 }
297                 n = convS2M(&t, buf, messagesize);
298                 if(n <= BIT16SZ){
299                         fprint(2, "?message too large for buffer\n");
300                         continue;
301                 }
302                 if(write(fd, buf, n) != n){
303                         fprint(2, "?write fails: %r\n");
304                         break;
305                 }
306                 print("\t-> %F\n", &t);
307         }
308 }
309                 
310 void
311 main(int argc, char **argv)
312 {
313         int fd, pid, cmd, net;
314
315         cmd = 0;
316         net = 0;
317         ARGBEGIN{
318         case 'c':
319                 cmd = 1;
320                 break;
321         case 'm':
322                 messagesize = strtol(EARGF(usage()), 0, 0);
323                 break;
324         case 'n':
325                 net = 1;
326                 break;
327         default:
328                 usage();
329         }ARGEND
330
331         fmtinstall('F', fcallfmt);
332         fmtinstall('D', dirfmt);
333         fmtinstall('M', dirmodefmt);
334
335         if(argc != 1)
336                 usage();
337
338         if(cmd && net)
339                 usage();
340
341         if(cmd)
342                 fd = connectcmd(argv[0]);
343         else if(net){
344                 fd = dial(netmkaddr(argv[0], "net", "9fs"), 0, 0, 0);
345                 if(fd < 0)
346                         sysfatal("dial: %r");
347         }else{
348                 fd = open(argv[0], ORDWR);
349                 if(fd < 0)
350                         sysfatal("open: %r");
351         }
352
353         switch(pid = rfork(RFPROC|RFMEM)){
354         case -1:
355                 sysfatal("rfork: %r");
356                 break;
357         case 0:
358                 watch(fd);
359                 postnote(PNPROC, getppid(), "kill");
360                 break;
361         default:
362                 shell9p(fd);
363                 postnote(PNPROC, pid, "kill");
364                 break;
365         }
366         exits(nil);
367 }