diff --git a/contrib/lukemftpd/src/cmds.c b/contrib/lukemftpd/src/cmds.c index 334078f4385d..7a287ea59275 100644 --- a/contrib/lukemftpd/src/cmds.c +++ b/contrib/lukemftpd/src/cmds.c @@ -1,4 +1,4 @@ -/* $NetBSD: cmds.c,v 1.18 2002/10/12 08:35:16 darrenr Exp $ */ +/* $NetBSD: cmds.c,v 1.20 2003/01/08 18:07:31 manu Exp $ */ /* * Copyright (c) 1999-2001 The NetBSD Foundation, Inc. @@ -101,7 +101,7 @@ #include #ifndef lint -__RCSID("$NetBSD: cmds.c,v 1.18 2002/10/12 08:35:16 darrenr Exp $"); +__RCSID("$NetBSD: cmds.c,v 1.20 2003/01/08 18:07:31 manu Exp $"); #endif /* not lint */ #include @@ -171,6 +171,8 @@ struct ftpfact facttab[] = { #define FACTTABSIZE (sizeof(facttab) / sizeof(struct ftpfact)) +static char cached_path[MAXPATHLEN + 1] = "/"; +static void discover_path(char *, const char *); void cwd(const char *path) @@ -181,6 +183,9 @@ cwd(const char *path) else { show_chdir_messages(250); ack("CWD"); + if (getcwd(cached_path, MAXPATHLEN) == NULL) { + discover_path(cached_path, path); + } } } @@ -404,11 +409,15 @@ pwd(void) { char path[MAXPATHLEN]; - if (getcwd(path, sizeof(path) - 1) == NULL) - reply(550, "Can't get the current directory: %s.", - strerror(errno)); - else - replydirname(path, "is the current directory."); + if (getcwd(path, sizeof(path) - 1) == NULL) { + if (chdir(cached_path) < 0) { + reply(550, "Can't get the current directory: %s.", + strerror(errno)); + return; + } + (void)strlcpy(path, cached_path, MAXPATHLEN); + } + replydirname(path, "is the current directory."); } void @@ -844,3 +853,126 @@ replydirname(const char *name, const char *message) *p = '\0'; reply(257, "\"%s\" %s", npath, message); } + +static void +discover_path(last_path, new_path) + char *last_path; + const char *new_path; +{ + char tp[MAXPATHLEN + 1] = ""; + char tq[MAXPATHLEN + 1] = ""; + char *cp; + char *cq; + int sz1, sz2; + int nomorelink; + struct stat st1, st2; + + if (new_path[0] != '/') { + (void)strlcpy(tp, last_path, MAXPATHLEN); + (void)strlcat(tp, "/", MAXPATHLEN); + } + (void)strlcat(tp, new_path, MAXPATHLEN); + (void)strlcat(tp, "/", MAXPATHLEN); + + /* + * resolve symlinks. A symlink may introduce another symlink, so we + * loop trying to resolve symlinks until we don't find any of them. + */ + do { + /* Collapse any // into / */ + while ((cp = strstr(tp, "//")) != NULL) + (void)memmove(cp, cp + 1, strlen(cp) - 1 + 1); + + /* Collapse any /./ into / */ + while ((cp = strstr(tp, "/./")) != NULL) + (void)memmove(cp, cp + 2, strlen(cp) - 2 + 1); + + cp = tp; + nomorelink = 1; + + while ((cp = strstr(++cp, "/")) != NULL) { + sz1 = (u_long)cp - (u_long)tp; + if (sz1 > MAXPATHLEN) + goto bad; + *cp = 0; + sz2 = readlink(tp, tq, MAXPATHLEN); + *cp = '/'; + + /* If this is not a symlink, move to next / */ + if (sz2 <= 0) + continue; + + /* + * We found a symlink, so we will have to + * do one more pass to check there is no + * more symlink in the path + */ + nomorelink = 0; + + /* + * Null terminate the string and remove trailing / + */ + tq[sz2] = 0; + sz2 = strlen(tq); + if (tq[sz2 - 1] == '/') + tq[--sz2] = 0; + + /* + * Is this an absolute link or a relative link? + */ + if (tq[0] == '/') { + /* absolute link */ + if (strlen(cp) + sz2 > MAXPATHLEN) + goto bad; + memmove(tp + sz2, cp, strlen(cp) + 1); + memcpy(tp, tq, sz2); + } else { + /* relative link */ + for (cq = cp - 1; *cq != '/'; cq--); + if (strlen(tp) - ((u_long)cq - (u_long)cp) + + 1 + sz2 > MAXPATHLEN) + goto bad; + (void)memmove(cq + 1 + sz2, + cp, strlen(cp) + 1); + (void)memcpy(cq + 1, tq, sz2); + } + + /* + * start over, looking for new symlinks + */ + break; + } + } while (nomorelink == 0); + + /* Collapse any /foo/../ into /foo/ */ + while ((cp = strstr(tp, "/../")) != NULL) { + /* ^/../foo/ becomes ^/foo/ */ + if (cp == tp) { + (void)memmove(cp, cp + 3, + strlen(cp) - 3 + 1); + } else { + for (cq = cp - 1; *cq != '/'; cq--); + (void)memmove(cq, cp + 3, + strlen(cp) - 3 + 1); + } + } + + /* strip strailing / */ + if (strlen(tp) != 1) + tp[strlen(tp) - 1] = '\0'; + + /* check that the path is correct */ + stat(tp, &st1); + stat(".", &st2); + if ((st1.st_dev != st2.st_dev) || (st1.st_ino != st2.st_ino)) + goto bad; + + (void)strlcpy(last_path, tp, MAXPATHLEN); + return; + +bad: + (void)strlcat(last_path, "/", MAXPATHLEN); + (void)strlcat(last_path, new_path, MAXPATHLEN); + return; +} + diff --git a/contrib/lukemftpd/src/ftpcmd.y b/contrib/lukemftpd/src/ftpcmd.y index 1039d5138822..42a7131e3d39 100644 --- a/contrib/lukemftpd/src/ftpcmd.y +++ b/contrib/lukemftpd/src/ftpcmd.y @@ -1,4 +1,4 @@ -/* $NetBSD: ftpcmd.y,v 1.71 2002/10/12 08:35:17 darrenr Exp $ */ +/* $NetBSD: ftpcmd.y,v 1.73 2003/01/22 04:33:35 lukem Exp $ */ /*- * Copyright (c) 1997-2002 The NetBSD Foundation, Inc. @@ -83,7 +83,7 @@ #if 0 static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94"; #else -__RCSID("$NetBSD: ftpcmd.y,v 1.71 2002/10/12 08:35:17 darrenr Exp $"); +__RCSID("$NetBSD: ftpcmd.y,v 1.73 2003/01/22 04:33:35 lukem Exp $"); #endif #endif /* not lint */ @@ -1222,7 +1222,7 @@ struct tab cmdtab[] = { { "SMNT", SMNT, ARGS, 0, "(structure mount)" }, { "QUIT", QUIT, NOARGS, 1, "(terminate service)" }, { "REIN", REIN, NOARGS, 0, "(reinitialize server state)" }, - { "PORT", PORT, ARGS, 1, " b0, b1, b2, b3, b4" }, + { "PORT", PORT, ARGS, 1, " b0, b1, b2, b3, b4, b5" }, { "LPRT", LPRT, ARGS, 1, " af, hal, h1, h2, h3,..., pal, p1, p2..." }, { "EPRT", EPRT, STR1, 1, " |af|addr|port|" }, { "PASV", PASV, NOARGS, 1, "(set server in passive mode)" }, diff --git a/contrib/lukemftpd/src/popen.c b/contrib/lukemftpd/src/popen.c index aaaebcabf2a0..7a7c6c461ac1 100644 --- a/contrib/lukemftpd/src/popen.c +++ b/contrib/lukemftpd/src/popen.c @@ -1,4 +1,4 @@ -/* $NetBSD: popen.c,v 1.26 2001/04/25 01:46:26 lukem Exp $ */ +/* $NetBSD: popen.c,v 1.28 2003/01/16 09:41:38 kleink Exp $ */ /*- * Copyright (c) 1999-2001 The NetBSD Foundation, Inc. @@ -78,7 +78,7 @@ #if 0 static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 4/6/94"; #else -__RCSID("$NetBSD: popen.c,v 1.26 2001/04/25 01:46:26 lukem Exp $"); +__RCSID("$NetBSD: popen.c,v 1.28 2003/01/16 09:41:38 kleink Exp $"); #endif #endif /* not lint */ @@ -229,7 +229,7 @@ ftpd_pclose(FILE *iop) { int fdes, status; pid_t pid; - sigset_t sigset, osigset; + sigset_t nsigset, osigset; /* * pclose returns -1 if stream is not associated with a @@ -238,11 +238,11 @@ ftpd_pclose(FILE *iop) if (pids == 0 || pids[fdes = fileno(iop)] == 0) return (-1); (void)fclose(iop); - sigemptyset(&sigset); - sigaddset(&sigset, SIGINT); - sigaddset(&sigset, SIGQUIT); - sigaddset(&sigset, SIGHUP); - sigprocmask(SIG_BLOCK, &sigset, &osigset); + sigemptyset(&nsigset); + sigaddset(&nsigset, SIGINT); + sigaddset(&nsigset, SIGQUIT); + sigaddset(&nsigset, SIGHUP); + sigprocmask(SIG_BLOCK, &nsigset, &osigset); while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR) continue; sigprocmask(SIG_SETMASK, &osigset, NULL); diff --git a/contrib/lukemftpd/src/version.h b/contrib/lukemftpd/src/version.h index 482a47a4e854..4ffeb8a9b601 100644 --- a/contrib/lukemftpd/src/version.h +++ b/contrib/lukemftpd/src/version.h @@ -1,4 +1,4 @@ -/* $NetBSD: version.h,v 1.48 2002/10/26 04:19:56 lukem Exp $ */ +/* $NetBSD: version.h,v 1.50 2003/01/22 04:46:08 lukem Exp $ */ /*- * Copyright (c) 1999-2002 The NetBSD Foundation, Inc. * All rights reserved. @@ -36,5 +36,5 @@ */ #ifndef FTPD_VERSION -#define FTPD_VERSION "NetBSD-ftpd 20021130" +#define FTPD_VERSION "NetBSD-ftpd 20030122" #endif