if (canonname) {
sfree(fullname);
return canonname;
- } else
- return fullname;
+ } else {
+ /*
+ * Attempt number 2. Some FXP_REALPATH implementations
+ * (glibc-based ones, in particular) require the _whole_
+ * path to point to something that exists, whereas others
+ * (BSD-based) only require all but the last component to
+ * exist. So if the first call failed, we should strip off
+ * everything from the last slash onwards and try again,
+ * then put the final component back on.
+ *
+ * Special cases:
+ *
+ * - if the last component is "/." or "/..", then we don't
+ * bother trying this because there's no way it can work.
+ *
+ * - if the thing actually ends with a "/", we remove it
+ * before we start. Except if the string is "/" itself
+ * (although I can't see why we'd have got here if so,
+ * because surely "/" would have worked the first
+ * time?), in which case we don't bother.
+ *
+ * - if there's no slash in the string at all, give up in
+ * confusion (we expect at least one because of the way
+ * we constructed the string).
+ */
+
+ int i;
+ char *returnname;
+
+ i = strlen(fullname);
+ if (i > 2 && fullname[i-1] == '/')
+ fullname[--i] = '\0'; /* strip trailing / unless at pos 0 */
+ while (i > 0 && fullname[--i] != '/');
+
+ /*
+ * Give up on special cases.
+ */
+ if (fullname[i] != '/' || /* no slash at all */
+ !strcmp(fullname+i, "/.") || /* ends in /. */
+ !strcmp(fullname+i, "/..") || /* ends in /.. */
+ !strcmp(fullname, "/")) {
+ return fullname;
+ }
+
+ /*
+ * Now i points at the slash. Deal with the final special
+ * case i==0 (ie the whole path was "/nonexistentfile").
+ */
+ fullname[i] = '\0'; /* separate the string */
+ if (i == 0) {
+ canonname = fxp_realpath("/");
+ } else {
+ canonname = fxp_realpath(fullname);
+ }
+
+ if (!canonname)
+ return fullname; /* even that failed; give up */
+
+ /*
+ * We have a canonical name for all but the last path
+ * component. Concatenate the last component and return.
+ */
+ returnname = dupcat(canonname,
+ canonname[strlen(canonname)-1] == '/' ? "" : "/",
+ fullname+i+1, NULL);
+ sfree(fullname);
+ sfree(canonname);
+ return returnname;
+ }
}
/* ----------------------------------------------------------------------
fp = fopen(fname, "rb");
if (!fp) {
printf("local: unable to open %s\n", fname);
- fxp_close(fh);
sfree(outfname);
return 0;
}
fprintf(stderr,
"Fatal: unable to initialise SFTP: %s\n",
fxp_error());
+ return;
}
/*
}
static char *password = NULL;
-static int get_password(const char *prompt, char *str, int maxlen)
+static int get_line(const char *prompt, char *str, int maxlen, int is_pw)
{
HANDLE hin, hout;
- DWORD savemode, i;
+ DWORD savemode, newmode, i;
if (password) {
static int tried_once = 0;
}
GetConsoleMode(hin, &savemode);
- SetConsoleMode(hin, (savemode & (~ENABLE_ECHO_INPUT)) |
- ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT);
+ newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT;
+ if (is_pw)
+ newmode &= ~ENABLE_ECHO_INPUT;
+ else
+ newmode |= ENABLE_ECHO_INPUT;
+ SetConsoleMode(hin, newmode);
WriteFile(hout, prompt, strlen(prompt), &i, NULL);
ReadFile(hin, str, maxlen-1, &i, NULL);
if ((int)i > maxlen) i = maxlen-1; else i = i - 2;
str[i] = '\0';
- WriteFile(hout, "\r\n", 2, &i, NULL);
+ if (is_pw)
+ WriteFile(hout, "\r\n", 2, &i, NULL);
return 1;
}
char *err;
flags = FLAG_STDERR;
- ssh_get_password = &get_password;
+ ssh_get_line = &get_line;
init_winsock();
sk_init();