commit - 02571aa1629b9b5c719efd01e80dfd26b96db27e
commit + 1c9ab7cf791709ef1ccaca3435cfbc2c3b49272b
blob - a205d6b295360cd36e7c40e6572f08d5a299f20c
blob + 93eccac000e2849b6eef92b5822f79462680bb74
--- kamiftp/ftp.c
+++ kamiftp/ftp.c
}
static void
+cmd_pipe(int argc, const char **argv)
+{
+ struct qid qid;
+ pid_t pid;
+ int nfid, tmpfd, miss, status;
+ int filedes[2]; /* read end, write end */
+ char *errstr;
+
+ if (argc < 2) {
+ puts("usage: pipe remote-file cmd [args...]");
+ return;
+ }
+
+ nfid = nextfid();
+ errstr = walk_path(pwdfid, nfid, *argv, &miss, &qid);
+ if (errstr != NULL) {
+ printf("%s: %s\n", *argv, errstr);
+ free(errstr);
+ return;
+ }
+
+ if (miss != 0 || qid.type != 0) {
+ printf("%s: not a file\n", *argv);
+ if (miss == 0)
+ do_clunk(nfid);
+ return;
+ }
+
+ if (pipe(filedes) == -1)
+ err(1, "pipe");
+
+ switch (pid = vfork()) {
+ case -1:
+ err(1, "vfork");
+ case 0:
+ close(filedes[1]);
+ if (dup2(filedes[0], 0) == -1)
+ err(1, "dup2");
+ execvp(argv[1], (char *const *)argv + 1);
+ err(1, "execvp");
+ }
+
+ close(filedes[0]);
+ if (fetch_fid(nfid, filedes[1], *argv) == -1)
+ warnx("failed to fetch all the file");
+ close(filedes[1]);
+
+ waitpid(pid, &status, 0);
+}
+
+static void
cmd_put(int argc, const char **argv)
{
struct qid qid;
{"lpwd", cmd_lpwd},
{"ls", cmd_ls},
{"page", cmd_page},
+ {"pipe", cmd_pipe},
{"put", cmd_put},
{"quit", cmd_bye},
{"rename", cmd_rename},
if (argc == 0)
usage(1);
+ signal(SIGPIPE, SIG_IGN);
if (isatty(1)) {
tty_p = 1;
resized = 1;
blob - e6bd4dee49b0b1bf87619d7f9f8448da5eec9cb7
blob + 4847cd4af7874d36102d6e01b399e4bd2983c531
--- kamiftp/kamiftp.1
+++ kamiftp/kamiftp.1
and open it with the
.Ev PAGER
.Pq Xr less 1 by default .
+.It Ic pipe Ar remote-file Ar cmd Op Ar args...
+Fetch
+.Ar remote-file
+and pass it as standard input for
+.Ar cmd
+(with optional
+.Ar args Ns ).
.It Ic put Ar local-file Op Ar remote-file
Upload
.Ar local-file