commit - 64d8db89b9ae1d0770f75cd7638f1ac14d4bb677
commit + 9c48f915c93a4d5ad0f7aa91b62f047f68054089
blob - d01b9d73af35372622b0075071ffbd6c108fa4d0
blob + 25002f0aacbc119a06152d97e75906764bb8ad7e
--- kamiftp/ftp.c
+++ kamiftp/ftp.c
putchar('\n');
do_clunk(fid);
+}
+
+static int
+woc_file(int fd, const char *prompt, const char *path)
+{
+ struct qid qid;
+ const char *n = NULL;
+ char *errstr;
+ int nfid, miss;
+
+ nfid = pwdfid+1;
+ errstr = walk_path(pwdfid, nfid, path, &miss, &qid);
+ if (errstr != NULL && miss > 1) {
+ printf("%s: %s\n", path, errstr);
+ free(errstr);
+ return -1;
+ }
+
+ if (errstr != NULL || miss == 1) {
+ char p[PATH_MAX], *dn;
+
+ /*
+ * If it's only one component missing (the file name), walk
+ * to the parent directory and try to create the file.
+ */
+
+ if (strlcpy(p, path, sizeof(p)) >= sizeof(p)) {
+ printf("path too long: %s\n", path);
+ return -1;
+ }
+ dn = dirname(p);
+
+ if (!strcmp(dn, ".")) {
+ errstr = dup_fid(pwdfid, nfid);
+ miss = 0;
+ } else
+ errstr = walk_path(pwdfid, nfid, dn, &miss, &qid);
+
+ if (errstr != NULL) {
+ printf("%s: %s\n", dn, errstr);
+ free(errstr);
+ return -1;
+ }
+
+ if (miss != 0) {
+ printf("%s: not a directory\n", dn);
+ return -1;
+ }
+
+ if ((n = strrchr(path, '/')) != NULL)
+ n++;
+ else
+ n = path;
+ }
+
+ free(errstr);
+
+ if (miss > 1) {
+ printf("can't create %s: missing %d path component(s)\n",
+ path, miss);
+ return -1;
+ }
+
+ send_fid(nfid, n, fd, prompt);
+ return 0;
}
static void
}
static void
+cmd_edit(int argc, const char **argv)
+{
+ struct qid qid;
+ int nfid, tmpfd, miss;
+ char sfn[TMPFSTRLEN], p[PATH_MAX], *name, *errstr;
+ const char *ed;
+
+ if (argc != 1) {
+ puts("usage: edit file");
+ return;
+ }
+
+ if ((ed = getenv("VISUAL")) == NULL &&
+ (ed = getenv("EDITOR")) == NULL)
+ ed = "ed";
+
+ nfid = pwdfid+1;
+ 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 ((tmpfd = tmp_file(sfn)) == -1) {
+ do_clunk(nfid);
+ return;
+ }
+
+ strlcpy(p, *argv, sizeof(p));
+ name = basename(p);
+
+ fetch_fid(nfid, tmpfd, name);
+ close(tmpfd);
+
+ spawn(ed, sfn, NULL);
+
+ /*
+ * Re-open the file because it's not guaranteed that the
+ * file descriptor tmpfd is still associated with the file
+ * pointed by sfn: it's not uncommon for editor to write
+ * a backup file and then rename(2) it to the file name.
+ */
+ if ((tmpfd = open(sfn, O_RDONLY)) == -1) {
+ warn("can't open %s", sfn);
+ goto end;
+ }
+
+ woc_file(tmpfd, *argv, name);
+ close(tmpfd);
+
+end:
+ unlink(sfn);
+}
+
+static void
cmd_get(int argc, const char **argv)
{
struct qid qid;
cmd_put(int argc, const char **argv)
{
struct qid qid;
- const char *l, *n = NULL;
- char *errstr;
- int nfid, fd, miss;
+ const char *l;
+ int fd;
if (argc != 1 && argc != 2) {
printf("usage: put local-file [remote-file]\n");
l++; /* skip / */
else
l = argv[0];
-
- nfid = pwdfid+1;
- errstr = walk_path(pwdfid, nfid, l, &miss, &qid);
- if (errstr != NULL && miss > 1) {
- printf("%s: %s\n", l, errstr);
- free(errstr);
- return;
- }
-
- if (errstr != NULL || miss == 1) {
- char p[PATH_MAX], *dn;
- /*
- * If it's only one component missing (the file name), walk
- * to the parent directory and try to create the file.
- */
-
- if (strlcpy(p, l, sizeof(p)) >= sizeof(p)) {
- printf("path too long: %s\n", l);
- return;
- }
- dn = dirname(p);
-
- if (!strcmp(dn, ".")) {
- errstr = dup_fid(pwdfid, nfid);
- miss = 0;
- } else
- errstr = walk_path(pwdfid, nfid, dn, &miss, &qid);
-
- if (errstr != NULL) {
- printf("%s: %s\n", dn, errstr);
- free(errstr);
- return;
- }
-
- if (miss != 0) {
- printf("%s: not a directory\n", dn);
- return;
- }
-
- if ((n = strrchr(l, '/')) != NULL)
- n++;
- else
- n = l;
- }
-
- free(errstr);
-
- if (miss > 1) {
- printf("can't create %s: missing %d path component(s)\n",
- l, miss);
- return;
- }
-
if ((fd = open(argv[0], O_RDONLY)) == -1) {
warn("%s", argv[0]);
return;
}
- send_fid(nfid, n, fd, argv[0]);
+ woc_file(fd, argv[0], l);
close(fd);
}
{"bell", cmd_bell},
{"bye", cmd_bye},
{"cd", cmd_cd},
+ {"edit", cmd_edit},
{"get", cmd_get},
{"lcd", cmd_lcd},
{"lpwd", cmd_lpwd},