commit - 9c9e60d1c17cfe7ba0561ee4c2561b67bf9d455e
commit + 55e8c065589748eb51bc37751156a74c96051ed6
blob - f440e1a8a3df489a8069f6beaf66b4148d42ebcf
blob + 1f3fe3b330c9607e0c96b8ed5b6eb5766cbbdda7
--- kamiftp/ftp.c
+++ kamiftp/ftp.c
log_warnx("unknown command %s", *argv);
}
+static int
+parsecmd(char *cmd, char **argv, size_t len)
+{
+ int escape, quote;
+ int argc = 0;
+
+ memset(argv, 0, sizeof(*argv) * len);
+
+ while (argc < len) {
+ while (isspace((unsigned char)*cmd))
+ cmd++;
+ if (*cmd == '\0')
+ break;
+
+ argv[argc++] = cmd;
+ escape = quote = 0;
+ for (; *cmd != '\0'; ++cmd) {
+ if (escape) {
+ escape = 0;
+ continue;
+ }
+ if (*cmd == '\\') {
+ escape = 1;
+ memmove(cmd, cmd + 1, strlen(cmd));
+ cmd--;
+ continue;
+ }
+ if (*cmd == quote) {
+ quote = 0;
+ memmove(cmd, cmd + 1, strlen(cmd));
+ cmd--;
+ continue;
+ }
+ if (*cmd == '\'' || *cmd == '"') {
+ quote = *cmd;
+ memmove(cmd, cmd + 1, strlen(cmd));
+ cmd--;
+ continue;
+ }
+ if (quote)
+ continue;
+
+ if (isspace((unsigned char)*cmd))
+ break;
+ }
+
+ if (*cmd == '\0' && (escape || quote)) {
+ fprintf(stderr, "unterminated %s\n",
+ escape ? "escape" : "quote");
+ return -1;
+ }
+
+ if (*cmd == '\0')
+ break;
+ *cmd++ = '\0';
+ }
+
+ if (*cmd != '\0') {
+ fprintf(stderr, "too many arguments\n");
+ return -1;
+ }
+ return argc;
+}
+
static void
cd_or_fetch(const char *path, const char *outfile)
{
cd_or_fetch(path, outfile);
for (;;) {
- int argc = 0;
+ int argc;
char *line, *argv[16] = {0}, **ap;
if ((line = read_line("kamiftp> ")) == NULL)
break;
- for (argc = 0, ap = argv; ap < &argv[15] &&
- (*ap = strsep(&line, " \t")) != NULL;) {
- if (**ap != '\0')
- ap++, argc++;
+ if ((argc = parsecmd(line, argv, nitems(argv) - 1)) == -1) {
+ free(line);
+ continue;
}
+
+ argv[argc] = NULL;
excmd(argc, (const char **)argv);
if (bell)
blob - c22fcc820b2e07e26fd86cddbbfb5c72d61925e3
blob + 7a2e955493ea2859b0cc85000c46269522c2afbe
--- kamiftp/kamiftp.1
+++ kamiftp/kamiftp.1
names a directory.
.El
.Pp
+.Nm
+parses the input similarly to
+.Xr sh .
+Words are splitted on spaces, multiple spaces are collapsed into one.
+Quoting with
+.Sq '
+or
+.Sq \&"
+can be used to preserve spaces and other quotes.
+.Sq \e
+can be used to quote the following character.
+No special meaning is given to
+.Sq \e
+sequences
+.Po i.e.\& Sq \en
+is just the
+.Sq n
+character
+.Pc .
+.Pp
The following commands are recognized by
.Nm :
.Bl -tag -width Ds