2 ce3844d2 2021-12-14 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
4 ce3844d2 2021-12-14 op * Permission to use, copy, modify, and distribute this software for any
5 ce3844d2 2021-12-14 op * purpose with or without fee is hereby granted, provided that the above
6 ce3844d2 2021-12-14 op * copyright notice and this permission notice appear in all copies.
8 ce3844d2 2021-12-14 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 ce3844d2 2021-12-14 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 ce3844d2 2021-12-14 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 ce3844d2 2021-12-14 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 ce3844d2 2021-12-14 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 ce3844d2 2021-12-14 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 ce3844d2 2021-12-14 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 ce3844d2 2021-12-14 op #include "compat.h"
19 ce3844d2 2021-12-14 op #include <sys/types.h>
20 ce3844d2 2021-12-14 op #include <sys/socket.h>
22 423f02f5 2021-12-28 cage #include <assert.h>
23 ce3844d2 2021-12-14 op #include <netdb.h>
24 ce3844d2 2021-12-14 op #include <limits.h>
25 ce3844d2 2021-12-14 op #include <stdio.h>
26 ce3844d2 2021-12-14 op #include <stdlib.h>
27 ce3844d2 2021-12-14 op #include <string.h>
28 ce3844d2 2021-12-14 op #include <syslog.h>
29 ce3844d2 2021-12-14 op #include <tls.h>
30 ce3844d2 2021-12-14 op #include <unistd.h>
32 423f02f5 2021-12-28 cage #if HAVE_LIBREADLINE
33 ce3844d2 2021-12-14 op #include <readline/readline.h>
34 ce3844d2 2021-12-14 op #include <readline/history.h>
37 423f02f5 2021-12-28 cage #ifndef nitems
38 423f02f5 2021-12-28 cage #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
41 ce3844d2 2021-12-14 op #include "9pclib.h"
42 ce3844d2 2021-12-14 op #include "kamid.h"
43 ce3844d2 2021-12-14 op #include "utils.h"
44 ce3844d2 2021-12-14 op #include "log.h"
48 ce3844d2 2021-12-14 op const char *crtpath;
49 ce3844d2 2021-12-14 op const char *keypath;
52 ce3844d2 2021-12-14 op struct tls_config *tlsconf;
53 ce3844d2 2021-12-14 op struct tls *ctx;
55 423f02f5 2021-12-28 cage struct evbuffer *buf;
56 423f02f5 2021-12-28 cage struct evbuffer *dirbuf;
57 423f02f5 2021-12-28 cage uint32_t msize;
60 ce3844d2 2021-12-14 op #define PWDFID 0
62 423f02f5 2021-12-28 cage #define ASSERT_EMPTYBUF() assert(EVBUFFER_LENGTH(buf) == 0)
64 423f02f5 2021-12-28 cage #if HAVE_LIBREADLINE
66 688f54f0 2021-12-14 op read_line(const char *prompt)
71 688f54f0 2021-12-14 op if ((line = readline(prompt)) == NULL)
73 688f54f0 2021-12-14 op /* XXX: trim spaces? */
74 688f54f0 2021-12-14 op if (*line == '\0') {
79 688f54f0 2021-12-14 op add_history(line);
84 688f54f0 2021-12-14 op read_line(const char *prompt)
86 688f54f0 2021-12-14 op char *ch, *line = NULL;
87 688f54f0 2021-12-14 op size_t linesize = 0;
88 688f54f0 2021-12-14 op ssize_t linelen;
90 423f02f5 2021-12-28 cage printf("%s", prompt);
91 423f02f5 2021-12-28 cage fflush(stdout);
93 688f54f0 2021-12-14 op linelen = getline(&line, &linesize, stdin);
94 688f54f0 2021-12-14 op if (linelen == -1)
97 688f54f0 2021-12-14 op if ((ch = strchr(line, '\n')) != NULL)
103 a97ec9eb 2021-12-23 op static void __dead
104 ce3844d2 2021-12-14 op usage(int ret)
106 ce3844d2 2021-12-14 op fprintf(stderr, "usage: %s [-c] host[:port] [path]\n",
107 ce3844d2 2021-12-14 op getprogname());
108 ce3844d2 2021-12-14 op fprintf(stderr, PACKAGE_NAME " suite version " PACKAGE VERSION "\n");
113 423f02f5 2021-12-28 cage do_send(void)
117 423f02f5 2021-12-28 cage while (EVBUFFER_LENGTH(evb) != 0) {
118 423f02f5 2021-12-28 cage r = tls_write(ctx, EVBUFFER_DATA(evb), EVBUFFER_LENGTH(evb));
119 423f02f5 2021-12-28 cage switch (r) {
120 423f02f5 2021-12-28 cage case TLS_WANT_POLLIN:
121 423f02f5 2021-12-28 cage case TLS_WANT_POLLOUT:
124 423f02f5 2021-12-28 cage errx(1, "tls: %s", tls_error(ctx));
126 423f02f5 2021-12-28 cage evbuffer_drain(evb, r);
131 423f02f5 2021-12-28 cage static void
132 423f02f5 2021-12-28 cage mustread(void *d, size_t len)
136 423f02f5 2021-12-28 cage while (len != 0) {
137 423f02f5 2021-12-28 cage switch (r = tls_read(ctx, d, len)) {
138 423f02f5 2021-12-28 cage case TLS_WANT_POLLIN:
139 423f02f5 2021-12-28 cage case TLS_WANT_POLLOUT:
142 423f02f5 2021-12-28 cage errx(1, "tls: %s", tls_error(ctx));
150 423f02f5 2021-12-28 cage static void
151 423f02f5 2021-12-28 cage recv_msg(void)
153 423f02f5 2021-12-28 cage uint32_t len;
155 423f02f5 2021-12-28 cage char tmp[BUFSIZ];
157 423f02f5 2021-12-28 cage mustread(&len, sizeof(len));
158 423f02f5 2021-12-28 cage len = le32toh(len);
159 423f02f5 2021-12-28 cage if (len < HEADERSIZE)
160 423f02f5 2021-12-28 cage errx(1, "read message of invalid length %d", len);
162 423f02f5 2021-12-28 cage len -= 4; /* skip the length just read */
164 423f02f5 2021-12-28 cage while (len != 0) {
165 423f02f5 2021-12-28 cage switch (r = tls_read(ctx, tmp, sizeof(tmp))) {
166 423f02f5 2021-12-28 cage case TLS_WANT_POLLIN:
167 423f02f5 2021-12-28 cage case TLS_WANT_POLLOUT:
170 423f02f5 2021-12-28 cage errx(1, "tls: %s", tls_error(ctx));
173 423f02f5 2021-12-28 cage evbuffer_add(buf, tmp, r);
178 423f02f5 2021-12-28 cage static uint64_t
179 423f02f5 2021-12-28 cage np_read64(struct evbuffer *buf)
181 423f02f5 2021-12-28 cage uint64_t n;
183 423f02f5 2021-12-28 cage evbuffer_remove(buf, &n, sizeof(n));
184 423f02f5 2021-12-28 cage return le64toh(n);
187 423f02f5 2021-12-28 cage static uint32_t
188 423f02f5 2021-12-28 cage np_read32(struct evbuffer *buf)
190 423f02f5 2021-12-28 cage uint32_t n;
192 423f02f5 2021-12-28 cage evbuffer_remove(buf, &n, sizeof(n));
193 423f02f5 2021-12-28 cage return le32toh(n);
196 423f02f5 2021-12-28 cage static uint16_t
197 423f02f5 2021-12-28 cage np_read16(struct evbuffer *buf)
199 423f02f5 2021-12-28 cage uint16_t n;
201 423f02f5 2021-12-28 cage evbuffer_remove(buf, &n, sizeof(n));
202 423f02f5 2021-12-28 cage return le16toh(n);
205 423f02f5 2021-12-28 cage static uint16_t
206 423f02f5 2021-12-28 cage np_read8(struct evbuffer *buf)
210 423f02f5 2021-12-28 cage evbuffer_remove(buf, &n, sizeof(n));
214 423f02f5 2021-12-28 cage static char *
215 423f02f5 2021-12-28 cage np_readstr(struct evbuffer *buf)
217 423f02f5 2021-12-28 cage uint16_t len;
220 423f02f5 2021-12-28 cage len = np_read16(buf);
221 423f02f5 2021-12-28 cage assert(EVBUFFER_LENGTH(buf) >= len);
223 423f02f5 2021-12-28 cage if ((str = calloc(1, len+1)) == NULL)
224 423f02f5 2021-12-28 cage err(1, "calloc");
225 423f02f5 2021-12-28 cage evbuffer_remove(buf, str, len);
226 423f02f5 2021-12-28 cage return str;
229 423f02f5 2021-12-28 cage static void
230 423f02f5 2021-12-28 cage np_read_qid(struct evbuffer *buf, struct qid *qid)
232 423f02f5 2021-12-28 cage assert(EVBUFFER_LENGTH(buf) >= QIDSIZE);
234 423f02f5 2021-12-28 cage qid->type = np_read8(buf);
235 423f02f5 2021-12-28 cage qid->vers = np_read32(buf);
236 423f02f5 2021-12-28 cage qid->path = np_read64(buf);
239 423f02f5 2021-12-28 cage static void
240 423f02f5 2021-12-28 cage expect(uint8_t type)
244 423f02f5 2021-12-28 cage t = np_read8(buf);
245 423f02f5 2021-12-28 cage if (t == type)
248 423f02f5 2021-12-28 cage if (t == Terror) {
251 423f02f5 2021-12-28 cage err = np_readstr(buf);
252 423f02f5 2021-12-28 cage errx(1, "expected %s, got error %s",
253 423f02f5 2021-12-28 cage pp_msg_type(type), err);
256 423f02f5 2021-12-28 cage errx(1, "expected %s, got msg type %s",
257 423f02f5 2021-12-28 cage pp_msg_type(type), pp_msg_type(t));
260 423f02f5 2021-12-28 cage static void
261 423f02f5 2021-12-28 cage expect2(uint8_t type, uint16_t tag)
263 423f02f5 2021-12-28 cage uint16_t t;
265 423f02f5 2021-12-28 cage expect(type);
267 423f02f5 2021-12-28 cage t = np_read16(buf);
268 423f02f5 2021-12-28 cage if (t == tag)
271 423f02f5 2021-12-28 cage errx(1, "expected tag 0x%x, got 0x%x", tag, t);
274 423f02f5 2021-12-28 cage static void
275 ce3844d2 2021-12-14 op do_version(void)
277 423f02f5 2021-12-28 cage char *version;
279 ce3844d2 2021-12-14 op tversion(VERSION9P, MSIZE9P);
281 423f02f5 2021-12-28 cage recv_msg();
282 423f02f5 2021-12-28 cage expect2(Rversion, NOTAG);
284 423f02f5 2021-12-28 cage msize = np_read32(buf);
285 423f02f5 2021-12-28 cage version = np_readstr(buf);
287 423f02f5 2021-12-28 cage if (msize > MSIZE9P)
288 423f02f5 2021-12-28 cage errx(1, "got unexpected msize: %d", msize);
289 423f02f5 2021-12-28 cage if (strcmp(version, VERSION9P))
290 423f02f5 2021-12-28 cage errx(1, "unexpected 9p version: %s", version);
292 423f02f5 2021-12-28 cage free(version);
293 423f02f5 2021-12-28 cage ASSERT_EMPTYBUF();
297 ce3844d2 2021-12-14 op do_attach(const char *path)
299 423f02f5 2021-12-28 cage const char *user;
300 423f02f5 2021-12-28 cage struct qid qid;
302 ce3844d2 2021-12-14 op if (path == NULL)
304 423f02f5 2021-12-28 cage if ((user = getenv("USER")) == NULL)
305 423f02f5 2021-12-28 cage user = "flan";
307 423f02f5 2021-12-28 cage tattach(PWDFID, NOFID, user, path);
309 423f02f5 2021-12-28 cage recv_msg();
310 423f02f5 2021-12-28 cage expect2(Rattach, iota_tag);
311 423f02f5 2021-12-28 cage np_read_qid(buf, &qid);
313 423f02f5 2021-12-28 cage ASSERT_EMPTYBUF();
316 423f02f5 2021-12-28 cage static uint32_t
317 423f02f5 2021-12-28 cage do_open(uint32_t fid, uint8_t mode)
319 423f02f5 2021-12-28 cage struct qid qid;
320 423f02f5 2021-12-28 cage uint32_t iounit;
322 423f02f5 2021-12-28 cage topen(fid, mode);
324 423f02f5 2021-12-28 cage recv_msg();
325 423f02f5 2021-12-28 cage expect2(Ropen, iota_tag);
327 423f02f5 2021-12-28 cage np_read_qid(buf, &qid);
328 423f02f5 2021-12-28 cage iounit = np_read32(buf);
330 423f02f5 2021-12-28 cage ASSERT_EMPTYBUF();
332 423f02f5 2021-12-28 cage return iounit;
336 423f02f5 2021-12-28 cage do_clunk(uint32_t fid)
338 423f02f5 2021-12-28 cage tclunk(fid);
340 423f02f5 2021-12-28 cage recv_msg();
341 423f02f5 2021-12-28 cage expect2(Rclunk, iota_tag);
343 423f02f5 2021-12-28 cage ASSERT_EMPTYBUF();
346 423f02f5 2021-12-28 cage static void
347 423f02f5 2021-12-28 cage dup_fid(int fid, int nfid)
349 423f02f5 2021-12-28 cage uint16_t nwqid;
351 423f02f5 2021-12-28 cage twalk(fid, nfid, NULL, 0);
353 423f02f5 2021-12-28 cage recv_msg();
354 423f02f5 2021-12-28 cage expect2(Rwalk, iota_tag);
356 423f02f5 2021-12-28 cage nwqid = np_read16(buf);
357 423f02f5 2021-12-28 cage assert(nwqid == 0);
359 423f02f5 2021-12-28 cage ASSERT_EMPTYBUF();
362 423f02f5 2021-12-28 cage static void
363 ce3844d2 2021-12-14 op do_connect(const char *connspec, const char *path)
365 ce3844d2 2021-12-14 op int handshake;
366 ce3844d2 2021-12-14 op char *host, *colon;
367 ce3844d2 2021-12-14 op const char *port;
369 ce3844d2 2021-12-14 op host = xstrdup(connspec);
370 ce3844d2 2021-12-14 op if ((colon = strchr(host, ':')) != NULL) {
371 ce3844d2 2021-12-14 op *colon = '\0';
372 ce3844d2 2021-12-14 op port = ++colon;
374 ce3844d2 2021-12-14 op port = "1337";
377 ce3844d2 2021-12-14 op fatalx("non-tls mode is not supported");
379 ce3844d2 2021-12-14 op if ((tlsconf = tls_config_new()) == NULL)
380 ce3844d2 2021-12-14 op fatalx("tls_config_new");
381 ce3844d2 2021-12-14 op tls_config_insecure_noverifycert(tlsconf);
382 ce3844d2 2021-12-14 op tls_config_insecure_noverifyname(tlsconf);
383 ce3844d2 2021-12-14 op if (tls_config_set_keypair_file(tlsconf, crtpath, keypath) == -1)
384 ce3844d2 2021-12-14 op fatalx("can't load certs (%s, %s)", crtpath, keypath);
386 ce3844d2 2021-12-14 op if ((ctx = tls_client()) == NULL)
387 ce3844d2 2021-12-14 op fatal("tls_client");
388 ce3844d2 2021-12-14 op if (tls_configure(ctx, tlsconf) == -1)
389 ce3844d2 2021-12-14 op fatalx("tls_configure: %s", tls_error(ctx));
391 ce3844d2 2021-12-14 op printf("connecting to %s:%s...", host, port);
392 ce3844d2 2021-12-14 op fflush(stdout);
394 ce3844d2 2021-12-14 op if (tls_connect(ctx, host, port) == -1)
395 ce3844d2 2021-12-14 op fatalx("can't connect to %s:%s: %s", host, port,
396 ce3844d2 2021-12-14 op tls_error(ctx));
398 ce3844d2 2021-12-14 op for (handshake = 0; !handshake;) {
399 ce3844d2 2021-12-14 op switch (tls_handshake(ctx)) {
401 ce3844d2 2021-12-14 op fatalx("tls_handshake: %s", tls_error(ctx));
403 ce3844d2 2021-12-14 op handshake = 1;
408 ce3844d2 2021-12-14 op printf(" done!\n");
410 ce3844d2 2021-12-14 op do_version();
411 ce3844d2 2021-12-14 op do_attach(path);
416 423f02f5 2021-12-28 cage static void
417 423f02f5 2021-12-28 cage cmd_bell(int argc, const char **argv)
419 423f02f5 2021-12-28 cage if (argc == 0) {
420 423f02f5 2021-12-28 cage bell = !bell;
422 423f02f5 2021-12-28 cage puts("bell mode enabled");
424 423f02f5 2021-12-28 cage puts("bell mode disabled");
428 423f02f5 2021-12-28 cage if (argc != 1)
429 423f02f5 2021-12-28 cage goto usage;
431 423f02f5 2021-12-28 cage if (!strcmp(*argv, "on")) {
433 423f02f5 2021-12-28 cage puts("bell mode enabled");
437 423f02f5 2021-12-28 cage if (!strcmp(*argv, "off")) {
439 423f02f5 2021-12-28 cage puts("bell mode disabled");
444 423f02f5 2021-12-28 cage printf("bell [on | off]\n");
447 423f02f5 2021-12-28 cage static void
448 423f02f5 2021-12-28 cage cmd_bye(int argc, const char **argv)
450 423f02f5 2021-12-28 cage log_warnx("bye\n");
454 423f02f5 2021-12-28 cage static void
455 423f02f5 2021-12-28 cage cmd_ls(int argc, const char **argv)
457 423f02f5 2021-12-28 cage uint64_t off = 0;
458 423f02f5 2021-12-28 cage uint32_t len;
460 423f02f5 2021-12-28 cage if (argc != 0) {
461 423f02f5 2021-12-28 cage printf("ls don't take arguments (yet)\n");
465 423f02f5 2021-12-28 cage dup_fid(PWDFID, 1);
466 423f02f5 2021-12-28 cage do_open(1, KOREAD);
468 423f02f5 2021-12-28 cage evbuffer_drain(dirbuf, EVBUFFER_LENGTH(dirbuf));
471 423f02f5 2021-12-28 cage tread(1, off, BUFSIZ);
473 423f02f5 2021-12-28 cage recv_msg();
474 423f02f5 2021-12-28 cage expect2(Rread, iota_tag);
476 423f02f5 2021-12-28 cage len = np_read32(buf);
477 423f02f5 2021-12-28 cage if (len == 0)
480 423f02f5 2021-12-28 cage evbuffer_add_buffer(dirbuf, buf);
481 423f02f5 2021-12-28 cage off += len;
483 423f02f5 2021-12-28 cage ASSERT_EMPTYBUF();
486 423f02f5 2021-12-28 cage while (EVBUFFER_LENGTH(dirbuf) != 0) {
487 423f02f5 2021-12-28 cage struct qid qid;
488 423f02f5 2021-12-28 cage uint64_t len;
489 423f02f5 2021-12-28 cage uint16_t size;
490 423f02f5 2021-12-28 cage char *name;
492 423f02f5 2021-12-28 cage size = np_read16(dirbuf);
493 423f02f5 2021-12-28 cage assert(size <= EVBUFFER_LENGTH(dirbuf));
495 423f02f5 2021-12-28 cage np_read16(dirbuf); /* skip type */
496 423f02f5 2021-12-28 cage np_read32(dirbuf); /* skip dev */
498 423f02f5 2021-12-28 cage np_read_qid(dirbuf, &qid);
499 423f02f5 2021-12-28 cage printf("%s ", pp_qid_type(qid.type));
501 423f02f5 2021-12-28 cage np_read32(dirbuf); /* skip mode */
502 423f02f5 2021-12-28 cage np_read32(dirbuf); /* skip atime */
503 423f02f5 2021-12-28 cage np_read32(dirbuf); /* skip mtime */
505 423f02f5 2021-12-28 cage len = np_read64(dirbuf);
506 423f02f5 2021-12-28 cage printf("%llu ", (unsigned long long)len);
508 423f02f5 2021-12-28 cage name = np_readstr(dirbuf);
509 423f02f5 2021-12-28 cage printf("%s\n", name);
510 423f02f5 2021-12-28 cage free(name);
512 423f02f5 2021-12-28 cage free(np_readstr(dirbuf)); /* skip uid */
513 423f02f5 2021-12-28 cage free(np_readstr(dirbuf)); /* skip gid */
514 423f02f5 2021-12-28 cage free(np_readstr(dirbuf)); /* skip muid */
517 423f02f5 2021-12-28 cage do_clunk(1);
520 423f02f5 2021-12-28 cage static void
521 423f02f5 2021-12-28 cage cmd_verbose(int argc, const char **argv)
523 423f02f5 2021-12-28 cage if (argc == 0) {
524 423f02f5 2021-12-28 cage log_setverbose(!log_getverbose());
525 423f02f5 2021-12-28 cage if (log_getverbose())
526 423f02f5 2021-12-28 cage puts("verbose mode enabled");
528 423f02f5 2021-12-28 cage puts("verbose mode disabled");
532 423f02f5 2021-12-28 cage if (argc != 1)
533 423f02f5 2021-12-28 cage goto usage;
535 423f02f5 2021-12-28 cage if (!strcmp(*argv, "on")) {
536 423f02f5 2021-12-28 cage log_setverbose(1);
537 423f02f5 2021-12-28 cage puts("verbose mode enabled");
541 423f02f5 2021-12-28 cage if (!strcmp(*argv, "off")) {
542 423f02f5 2021-12-28 cage log_setverbose(0);
543 423f02f5 2021-12-28 cage puts("verbose mode disabled");
548 423f02f5 2021-12-28 cage printf("verbose [on | off]\n");
551 423f02f5 2021-12-28 cage static void
552 423f02f5 2021-12-28 cage excmd(int argc, const char **argv)
554 423f02f5 2021-12-28 cage struct cmd {
555 423f02f5 2021-12-28 cage const char *name;
556 423f02f5 2021-12-28 cage void (*fn)(int, const char **);
557 423f02f5 2021-12-28 cage } cmds[] = {
558 423f02f5 2021-12-28 cage {"bell", cmd_bell},
559 423f02f5 2021-12-28 cage {"bye", cmd_bye},
560 423f02f5 2021-12-28 cage {"ls", cmd_ls},
561 423f02f5 2021-12-28 cage {"quit", cmd_bye},
562 423f02f5 2021-12-28 cage {"verbose", cmd_verbose},
566 423f02f5 2021-12-28 cage if (argc == 0)
568 423f02f5 2021-12-28 cage for (i = 0; i < nitems(cmds); ++i) {
569 423f02f5 2021-12-28 cage if (!strcmp(cmds[i].name, *argv)) {
570 423f02f5 2021-12-28 cage cmds[i].fn(argc-1, argv+1);
575 423f02f5 2021-12-28 cage log_warnx("unknown command %s", *argv);
579 ce3844d2 2021-12-14 op main(int argc, char **argv)
583 ce3844d2 2021-12-14 op log_init(1, LOG_DAEMON);
584 423f02f5 2021-12-28 cage log_setverbose(0);
585 ce3844d2 2021-12-14 op log_procinit(getprogname());
587 ce3844d2 2021-12-14 op while ((ch = getopt(argc, argv, "C:cK:")) != -1) {
588 ce3844d2 2021-12-14 op switch (ch) {
590 ce3844d2 2021-12-14 op crtpath = optarg;
596 ce3844d2 2021-12-14 op keypath = optarg;
602 ce3844d2 2021-12-14 op argc -= optind;
603 ce3844d2 2021-12-14 op argv += optind;
605 ce3844d2 2021-12-14 op if (argc == 0)
608 ce3844d2 2021-12-14 op if ((evb = evbuffer_new()) == NULL)
609 ce3844d2 2021-12-14 op fatal("evbuffer_new");
611 423f02f5 2021-12-28 cage if ((buf = evbuffer_new()) == NULL)
612 423f02f5 2021-12-28 cage fatal("evbuffer_new");
614 423f02f5 2021-12-28 cage if ((dirbuf = evbuffer_new()) == NULL)
615 423f02f5 2021-12-28 cage fatal("evbuferr_new");
617 ce3844d2 2021-12-14 op do_connect(argv[0], argv[1]);
619 423f02f5 2021-12-28 cage /* cmd_ls(0, NULL); */
622 423f02f5 2021-12-28 cage int argc = 0;
623 423f02f5 2021-12-28 cage char *line, *argv[16] = {0}, **ap;
625 423f02f5 2021-12-28 cage if ((line = read_line("kamiftp> ")) == NULL)
628 423f02f5 2021-12-28 cage for (argc = 0, ap = argv; ap < &argv[15] &&
629 423f02f5 2021-12-28 cage (*ap = strsep(&line, " \t")) != NULL;) {
630 423f02f5 2021-12-28 cage if (**ap != '\0')
631 423f02f5 2021-12-28 cage ap++, argc++;
633 423f02f5 2021-12-28 cage excmd(argc, (const char **)argv);
635 423f02f5 2021-12-28 cage if (bell) {
636 423f02f5 2021-12-28 cage printf("\a");
637 423f02f5 2021-12-28 cage fflush(stdout);
640 423f02f5 2021-12-28 cage free(line);
643 ce3844d2 2021-12-14 op printf("\n");