Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/ftpd various fixes suggested by Robert Elz:
details: https://anonhg.NetBSD.org/src/rev/596a0dda7234
branches: trunk
changeset: 488144:596a0dda7234
user: lukem <lukem%NetBSD.org@localhost>
date: Mon Jun 19 15:15:03 2000 +0000
description:
various fixes suggested by Robert Elz:
* implement closedataconn() and use appropriately (including in mlsd())
* only put leading space in front of MLST output (not MLSD output)
* MLSD: only output pdir and cdir entries when the type fact is requested.
* change error code for giving MLSD a non-directory from 550 to 501
* remove MLSx Type fact support for UNIX.* for now; it's not standardised yet.
* do a check_login when MLSD and MLST are given no args
* detect & complain about null facts in OPTS MLST
* cache getgroups() at login instead of calling each time in fact_perm()
other mods:
* implement cprintf(); as per fprintf() but increments total_bytes{,_out}
* implement CPUTC(); as per putc() but increments total_bytes{,_out}
* implement base64_encode()
* fact_unique() display base64 encoding of dev_t and ino_t rather than
hex output; should scale if size of those changes
* change reply() so that a negative code acts as the initial line in a reply,
code == 0 prefixes the line with 4 spaces, and code > 0 works as before.
deprecate lreply(code, ) and lreply(0, ) in favour of reply(-code, ) and
reply(0, ) respectively.
* use cprintf() and CPUTC() appropriately (often instead of printf(),
lreply(-2, ) or lreply(-1, ).
now we actually account for the data sent by MLST and MLSD.
* remove DEBUG support for sending MLSD output to control connection instead
of data connection (my ftp client now supports MLSD :-)
diffstat:
libexec/ftpd/cmds.c | 249 ++++++++++++++++++++++++------------------------
libexec/ftpd/conf.c | 49 ++++-----
libexec/ftpd/extern.h | 11 +-
libexec/ftpd/ftpcmd.y | 47 +++-----
libexec/ftpd/ftpd.8 | 18 ++-
libexec/ftpd/ftpd.c | 244 ++++++++++++++++++++++-------------------------
libexec/ftpd/version.h | 4 +-
7 files changed, 302 insertions(+), 320 deletions(-)
diffs (truncated from 1464 to 300 lines):
diff -r 2f5fed8da8bb -r 596a0dda7234 libexec/ftpd/cmds.c
--- a/libexec/ftpd/cmds.c Mon Jun 19 14:58:37 2000 +0000
+++ b/libexec/ftpd/cmds.c Mon Jun 19 15:15:03 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cmds.c,v 1.2 2000/06/16 23:17:41 explorer Exp $ */
+/* $NetBSD: cmds.c,v 1.3 2000/06/19 15:15:03 lukem Exp $ */
/*
* Copyright (c) 1999-2000 The NetBSD Foundation, Inc.
@@ -101,7 +101,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: cmds.c,v 1.2 2000/06/16 23:17:41 explorer Exp $");
+__RCSID("$NetBSD: cmds.c,v 1.3 2000/06/19 15:15:03 lukem Exp $");
#endif /* not lint */
#include <sys/param.h>
@@ -133,15 +133,13 @@
} factelem;
static void ack(const char *);
+static void base64_encode(const char *, size_t, char *, int);
static void fact_type(const char *, FILE *, factelem *);
static void fact_size(const char *, FILE *, factelem *);
static void fact_modify(const char *, FILE *, factelem *);
static void fact_perm(const char *, FILE *, factelem *);
static void fact_unique(const char *, FILE *, factelem *);
-static void fact_unix_group(const char *, FILE *, factelem *);
-static void fact_unix_mode(const char *, FILE *, factelem *);
-static void fact_unix_owner(const char *, FILE *, factelem *);
-static int matchgroup(gid_t, gid_t *, int);
+static int matchgroup(gid_t);
static void mlsname(FILE *, factelem *);
static void replydirname(const char *, const char *);
@@ -154,13 +152,11 @@
struct ftpfact facttab[] = {
{ "Type", 1, fact_type },
+#define FACT_TYPE 0
{ "Size", 1, fact_size },
{ "Modify", 1, fact_modify },
{ "Perm", 1, fact_perm },
{ "Unique", 1, fact_unique },
- { "UNIX.mode", 1, fact_unix_mode },
- { "UNIX.owner", 0, fact_unix_owner },
- { "UNIX.group", 0, fact_unix_group },
/* "Create" */
/* "Lang" */
/* "Media-Type" */
@@ -199,16 +195,16 @@
{
int i;
- lreply(211, "Features supported");
- lreply(-1, " MDTM");
- lreply(-2, " MLST ");
+ reply(-211, "Features supported");
+ cprintf(stdout, " MDTM\r\n");
+ cprintf(stdout, " MLST ");
for (i = 0; facttab[i].name; i++)
- lreply(-2, "%s%s;", facttab[i].name,
+ cprintf(stdout, "%s%s;", facttab[i].name,
facttab[i].enabled ? "*" : "");
- lreply(-1, "");
- lreply(-1, " REST STREAM");
- lreply(-1, " SIZE");
- lreply(-1, " TVFS");
+ cprintf(stdout, "\r\n");
+ cprintf(stdout, " REST STREAM\r\n");
+ cprintf(stdout, " SIZE\r\n");
+ cprintf(stdout, " TVFS\r\n");
reply(211, "End");
}
@@ -228,13 +224,15 @@
void
mlsd(const char *path)
{
- FILE *dout;
- DIR *dirp;
- struct dirent *dp;
- struct stat sb, pdirstat;
- char name[MAXPATHLEN];
+ struct dirent *dp;
+ struct stat sb, pdirstat;
factelem f;
+ FILE *dout;
+ DIR *dirp;
+ char name[MAXPATHLEN];
+ int hastypefact;
+ hastypefact = facttab[FACT_TYPE].enabled;
if (path == NULL)
path = ".";
if (stat(path, &pdirstat) == -1) {
@@ -244,53 +242,48 @@
}
if (! S_ISDIR(pdirstat.st_mode)) {
errno = ENOTDIR;
- goto mlsdperror;
+ perror_reply(501, path);
+ return;
}
-#ifdef DEBUG /* send mlsd to ctrl connection not data connection */
- dout = stdout;
- lreply(250, "MLSD %s", path);
-#else
dout = dataconn("MLSD", (off_t)-1, "w");
if (dout == NULL)
return;
-#endif
if ((dirp = opendir(path)) == NULL)
goto mlsdperror;
f.stat = &sb;
while ((dp = readdir(dirp)) != NULL) {
snprintf(name, sizeof(name), "%s/%s", path, dp->d_name);
-/* printf("got >%s< >%s<\n", dp->d_name, name); */
+ if (ISDOTDIR(dp->d_name)) { /* special case curdir: */
+ if (! hastypefact)
+ continue;
+ f.pdirstat = NULL; /* require stat of parent */
+ f.display = path; /* set name to real name */
+ f.iscurdir = 1; /* flag name is curdir */
+ } else {
+ if (ISDOTDOTDIR(dp->d_name)) {
+ if (! hastypefact)
+ continue;
+ f.pdirstat = NULL;
+ } else
+ f.pdirstat = &pdirstat; /* cache parent stat */
+ f.display = dp->d_name;
+ f.iscurdir = 0;
+ }
if (stat(name, &sb) == -1)
continue;
f.path = name;
- if (ISDOTDIR(dp->d_name)) { /* special case curdir: */
- f.display = path; /* set name to real name */
- f.iscurdir = 1; /* flag name is curdir */
- f.pdirstat = NULL; /* require stat of parent */
- } else {
- f.display = dp->d_name;
- f.iscurdir = 0;
- if (ISDOTDOTDIR(dp->d_name))
- f.pdirstat = NULL;
- else
- f.pdirstat = &pdirstat; /* cache parent stat */
- }
mlsname(dout, &f);
}
(void)closedir(dirp);
-#ifdef DEBUG
- reply(250, "End");
-#else
if (ferror(dout) != 0)
perror_reply(550, "Data connection");
else
reply(226, "MLSD complete.");
- (void) fclose(dout);
+ closedataconn(dout);
total_xfers_out++;
total_xfers++;
-#endif
}
void
@@ -305,12 +298,13 @@
perror_reply(550, path);
return;
}
- lreply(250, "MLST %s", path);
+ reply(-250, "MLST %s", path);
f.path = path;
f.display = path;
f.stat = &sb;
f.pdirstat = NULL;
f.iscurdir = 0;
+ CPUTC(' ', stdout);
mlsname(stdout, &f);
reply(250, "End");
}
@@ -341,37 +335,47 @@
/* special case: MLST */
if (strcasecmp(command, "MLST") == 0) {
+ int enabled[sizeof(facttab) / sizeof(struct ftpfact)];
int i, onedone;
+ size_t len;
char *p;
- for (i = 0; facttab[i].name; i++)
- facttab[i].enabled = 0;
+ for (i = 0; i < sizeof(enabled) / sizeof(int); i++)
+ enabled[i] = 0;
if (ep == NULL || *ep == '\0')
goto displaymlstopts;
/* don't like spaces, and need trailing ; */
- if (strchr(ep, ' ') != NULL || ep[strlen(ep) - 1] != ';') {
+ len = strlen(ep);
+ if (strchr(ep, ' ') != NULL || ep[len - 1] != ';') {
+ badmlstopt:
reply(501, "Invalid MLST options");
return;
}
+ ep[len - 1] = '\0';
while ((p = strsep(&ep, ";")) != NULL) {
+ if (*p == '\0')
+ goto badmlstopt;
for (i = 0; facttab[i].name; i++)
if (strcasecmp(p, facttab[i].name) == 0) {
- facttab[i].enabled = 1;
+ enabled[i] = 1;
break;
}
}
displaymlstopts:
- lreply(-2, "200 MLST OPTS");
+ for (i = 0; facttab[i].name; i++)
+ facttab[i].enabled = enabled[i];
+ cprintf(stdout, "200 MLST OPTS");
for (i = onedone = 0; facttab[i].name; i++) {
if (facttab[i].enabled) {
- lreply(-2, "%s%s;", onedone ? "" : " ",
+ cprintf(stdout, "%s%s;", onedone ? "" : " ",
facttab[i].name);
onedone++;
}
}
- lreply(-1, "");
+ cprintf(stdout, "\r\n");
+ fflush(stdout);
return;
}
@@ -488,7 +492,8 @@
argv[2] = (char *)filename;
fin = ftpd_popen(argv, "r", STDOUT_FILENO);
- lreply(211, "status of %s:", filename);
+ reply(-211, "status of %s:", filename);
+/* XXX: use fgetln() or fparseln() here? */
while ((c = getc(fin)) != EOF) {
if (c == '\n') {
if (ferror(stdout)){
@@ -502,13 +507,9 @@
(void) ftpd_pclose(fin);
return;
}
- (void) putchar('\r');
- total_bytes++;
- total_bytes_out++;
+ CPUTC('\r', stdout);
}
- (void) putchar(c);
- total_bytes++;
- total_bytes_out++;
+ CPUTC(c, stdout);
}
(void) ftpd_pclose(fin);
reply(211, "End of Status");
@@ -523,13 +524,40 @@
reply(250, "%s command successful.", s);
}
+/*
+ * Encode len bytes starting at clear using base64 encoding into encoded,
+ * which should be at least ((len + 2) * 4 / 3 + 1) in size.
+ * If nulterm is non-zero, terminate with \0 else pad to len with `='.
+ */
+static void
+base64_encode(const char *clear, size_t len, char *encoded, int nulterm)
+{
+ static const char enc[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ char *cp;
+ int i;
+
+ cp = encoded;
+ for (i = 0; i < len; i += 3) {
+ *(cp++) = enc[((clear[i + 0] >> 2))];
+ *(cp++) = enc[((clear[i + 0] << 4) & 0x30)
+ | ((clear[i + 1] >> 4) & 0x0f)];
+ *(cp++) = enc[((clear[i + 1] << 2) & 0x3c)
+ | ((clear[i + 2] >> 6) & 0x03)];
+ *(cp++) = enc[((clear[i + 2] ) & 0x3f)];
+ }
+ *cp = '\0';
+ while (i-- > len)
+ *(--cp) = nulterm ? '\0' : '=';
+}
+
static void
fact_modify(const char *fact, FILE *fd, factelem *fe)
{
Home |
Main Index |
Thread Index |
Old Index