]> git.sesse.net Git - betaftpd/blobdiff - ftpd.c
Fixed a problem where the server might segfault if there was an error occuring while...
[betaftpd] / ftpd.c
diff --git a/ftpd.c b/ftpd.c
index 812a95756005e766458d1abcacc665088a441b4c..23a7134e51665e384d598839ef28770e3faa95b1 100644 (file)
--- a/ftpd.c
+++ b/ftpd.c
@@ -184,6 +184,7 @@ struct ftran *first_ftran = NULL;
 #if WANT_DCACHE
 struct dcache *first_dcache = NULL;
 #endif
+char message_buf[512];
 
 #if HAVE_POLL
 unsigned int highest_fds = 0;
@@ -365,7 +366,7 @@ struct conn *alloc_new_conn(const int sock)
        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);
@@ -390,6 +391,7 @@ struct conn *alloc_new_conn(const int sock)
 #if WANT_ASCII
        c->ascii_mode = 0;
 #endif
+       c->free_me = 0;
 
        /*
         * equals:
@@ -406,7 +408,7 @@ struct conn *alloc_new_conn(const int sock)
 
        time(&(c->last_transfer));
 
-       /*list_clients();*/
+       /* list_clients(); */
 
        return c;
 }
@@ -596,7 +598,12 @@ int process_all_clients(const fd_set * const active_clients, const int num_ac)
  */
 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
@@ -1117,10 +1124,14 @@ void accept_new_client(int * const server_sock)
                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);
                }
        }
 }
@@ -1192,23 +1203,26 @@ void remove_bytes(struct conn * const c, const int num)
  *             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);
-       }
 }
 
 /*