commit df9bb54d629f5085f152e8d6d5f4d098a2adfba2 from: Omar Polo date: Wed Nov 23 14:37:51 2022 UTC kamiftp: add -o to chose the path where to save the named file commit - 5d0dedb3fb1363a2f04e15ddc46ea427e40db91c commit + df9bb54d629f5085f152e8d6d5f4d098a2adfba2 blob - b850a5a3288dd240db30eeed8d7d6b7dc35118a3 blob + f18ce8bdca1bd2d26638738750cc0d127703c530 --- kamiftp/ftp.c +++ kamiftp/ftp.c @@ -213,7 +213,7 @@ tty_resized(int signo) static void __dead usage(int ret) { - fprintf(stderr, "usage: %s [-c] [-C cert] [-K key] " + fprintf(stderr, "usage: %s [-c] [-C cert] [-K key] [-o output] " "[user@]host[:port][/path]\n", getprogname()); fprintf(stderr, "kamid suite version " KAMID_VERSION "\n"); exit(ret); @@ -1584,10 +1584,9 @@ excmd(int argc, const char **argv) } static void -cd_or_fetch(const char *path) +cd_or_fetch(const char *path, const char *outfile) { struct qid qid; - const char *l; char *errstr; int fd, nfid, miss; @@ -1604,22 +1603,32 @@ cd_or_fetch(const char *path) errc(1, ENOENT, "walk %s", path); if (qid.type & QTDIR) { + if (outfile) + errx(1, "can't fetch directory %s", path); do_clunk(pwdfid); pwdfid = nfid; return; } - if ((l = strrchr(path, '/')) == NULL) - l = path; - else - l++; - if (*l == '\0') - errx(1, "invalid path: missing file name: %s", path); + if (outfile == NULL) { + if ((outfile = strrchr(path, '/')) == NULL) + outfile = path; + else + outfile++; + if (*outfile == '\0') + errx(1, "invalid path: missing file name: %s", + path); + } - if ((fd = open(l, O_WRONLY|O_CREAT, 0644)) == -1) - err(1, "can't open for writing %s", l); - if (fetch_fid(nfid, fd, l) == -1) - err(1, "write %s", l); + if (strcmp(outfile, "-") != 0) { + fd = open(outfile, O_WRONLY|O_CREAT, 0644); + if (fd == -1) + err(1, "can't open for writing %s", outfile); + } else + fd = 1; + + if (fetch_fid(nfid, fd, outfile) == -1) + err(1, "write %s", outfile); close(fd); fclose(fp); exit(0); @@ -1670,13 +1679,14 @@ int main(int argc, char **argv) { const char *user, *host, *port, *path; + const char *outfile = NULL; int ch; log_init(1, LOG_DAEMON); log_setverbose(0); log_procinit(getprogname()); - while ((ch = getopt(argc, argv, "C:cK:")) != -1) { + while ((ch = getopt(argc, argv, "C:cK:o:")) != -1) { switch (ch) { case 'C': tls = 1; @@ -1689,6 +1699,9 @@ main(int argc, char **argv) tls = 1; keypath = optarg; break; + case 'o': + outfile = optarg; + break; default: usage(1); } @@ -1702,6 +1715,8 @@ main(int argc, char **argv) host = parse_addr(argv[0], &user, &port, &path); if (path == NULL && argv[1] != NULL) path = argv[1]; + if (outfile && path == NULL) + usage(1); signal(SIGPIPE, SIG_IGN); if (isatty(1)) { @@ -1721,7 +1736,7 @@ main(int argc, char **argv) do_connect(host, port, user); if (path) - cd_or_fetch(path); + cd_or_fetch(path, outfile); for (;;) { int argc = 0; blob - 9c533666fa46400322e16af1b66d1e193415af96 blob + 5706af0a53ea1fd8d42d9669743e84827544b93d --- kamiftp/kamiftp.1 +++ kamiftp/kamiftp.1 @@ -23,6 +23,7 @@ .Op Fl c .Op Fl C Ar cert .Op Fl K Ar key +.Op Fl o Ar output .Oo Ar user Ns @ Oc Ns Ar host Ns Oo : Ns Ar port Oc Ns Op / Ns Ar path .Sh DESCRIPTION .Nm @@ -58,6 +59,19 @@ If not given, the file passed to will be used. Implies .Fl c . +.It Fl o Ar output +When fetching the file specified to the command line, +save its content in +.Ar output . +To write the content to standard output, use +.Sq - . +It's an error to specify +.Fl o +when not givin a +.Ar path +or when +.Ar path +names a directory. .El .Pp The following commands are recognized by