#if WANT_DCACHE
struct dcache *first_dcache = NULL;
#endif
+char message_buf[512];
#if HAVE_POLL
unsigned int highest_fds = 0;
const unsigned int one = 1;
struct conn *c = (struct conn *)(malloc(sizeof(struct conn)));
- if (c == NULL) return c;
+ if (c == NULL) return NULL;
if (sock != -1) {
ioctl(sock, FIONBIO, &one);
#if WANT_ASCII
c->ascii_mode = 0;
#endif
+ c->free_me = 0;
/*
* equals:
time(&(c->last_transfer));
- /*list_clients();*/
+ /* list_clients(); */
return c;
}
*/
void finish_transfer(struct ftran * const f)
{
- numeric(f->owner, 226, "Transfer complete.");
+ char finished[] = "226 Transfer complete.\r\n";
+ if (send(f->owner->sock, finished, sizeof(finished), 0) == -1 && errno == EPIPE) {
+ destroy_conn(f->owner);
+ return;
+ }
+
time(&(f->owner->last_transfer));
#if WANT_XFERLOG
{
struct ftran *f = NULL, *next = first_ftran->next_ftran;
int checked_through = 0;
- struct sockaddr tempaddr;
- int tempaddr_len = sizeof(tempaddr);
+ int tempaddr_len = sizeof(struct sockaddr_in);
while (next != NULL && checked_through < num_ac) {
f = next;
next = f->next_ftran;
-#if HAVE_UPLOAD
- if (f->upload == 1 && fds[f->sock].revents & POLLHUP) {
+#if WANT_UPLOAD
+ if ((f->upload == 1) && (fds[f->sock].revents & POLLHUP)) {
finish_transfer(f);
continue;
}
if (f->state == 2) { /* incoming PASV */
const unsigned int one = 1;
- const int tempsock = accept(f->sock, (struct sockaddr *)&tempaddr,
- &tempaddr_len);
+ const int tempsock = accept(f->sock, &(f->sin), &tempaddr_len);
del_fd(f->sock);
if (xferlog == NULL) return;
- strftime(temp, 256, "%a %b %d %H:%M:%S %Y", t);
+ strftime(temp, 256, "%a %b %d %H:%M:%S %Y", t);
#if WANT_UPLOAD
- fprintf(xferlog, "%s %u %s %lu %s b _ %c a %s ftp 0 * \n",
+ fprintf(xferlog, "%s %u %s %lu %s b _ %c %c %s ftp 0 *\n",
#else
- fprintf(xferlog, "%s %u %s %lu %s b _ o a %s ftp 0 *\n",
+ fprintf(xferlog, "%s %u %s %lu %s b _ o %c %s ftp 0 *\n",
#endif
temp, (int)(difftime(now, f->tran_start)),
inet_ntoa(f->sin.sin_addr), f->size,
#if WANT_UPLOAD
(f->upload) ? 'i' : 'o',
#endif
- f->owner->username);
+ (f->owner->auth == 4) ? 'r' : 'a', f->owner->username);
fflush(xferlog);
#if 0
#warning No xferlog support for nonroot yet
#else
/* open xferlog */
- xferlog = fopen("/var/log/xferlog", "r+");
- if (xferlog == NULL) xferlog = fopen("/usr/adm/xferlog", "r+");
+ xferlog = fopen("/var/log/xferlog", "a");
+ if (xferlog == NULL) xferlog = fopen("/usr/adm/xferlog", "a");
if (xferlog != NULL) {
fseek(xferlog, 0L, SEEK_END);
struct conn * const c = alloc_new_conn(tempsock);
num_err = 0;
if (c != NULL) {
- numeric(c, 220, "BetaFTPD " VERSION " ready.");
+ char hello[] = "220 BetaFTPD " VERSION " ready.\r\n";
+
#if WANT_STAT
memcpy(&(c->addr), &tempaddr, sizeof(struct sockaddr));
#endif
+
+ if (send(tempsock, hello, sizeof(hello), 0) == -1 && errno == EPIPE)
+ destroy_conn(c);
}
}
}
* you can use this command much the same way as you
* would use a printf() (with all the normal %s, %d,
* etc.), since it actually uses printf() internally.
+ *
+ * This command doesn't actually SEND the data -- it
+ * just puts it in a buffer which is sent after the
+ * command handler has completed. The reasons for this
+ * are simple -- it makes error checking and cleanup
+ * MUCH cleaner, so we won't have to check for errors
+ * in every single little branch of the code.
*/
void numeric(struct conn * const c, const int numeric, const char * const format, ...)
{
- char buf[256], fmt[256];
+ char fmt[256];
va_list args;
int i, err;
+ int in_buf = strlen(message_buf);
snprintf(fmt, 256, "%03u %s\r\n", numeric, format);
va_start(args, format);
- i = vsnprintf(buf, 256, fmt, args);
+ i = vsnprintf(message_buf + in_buf, 512 - in_buf, fmt, args);
va_end(args);
-
- err = send(c->sock, buf, i, 0);
- if (err == -1 && errno == EPIPE) {
- destroy_conn(c);
- }
}
/*