Index: Commands.cpp
===================================================================
RCS file: /cvsroot/babyftpd/babyftpd/Commands.cpp,v
retrieving revision 1.181
retrieving revision 1.182
diff -u -p -b -r1.181 -r1.182
--- Commands.cpp	20 May 2004 21:13:09 -0000	1.181
+++ Commands.cpp	21 May 2004 23:44:31 -0000	1.182
@@ -193,15 +193,6 @@ void *data_wrapper(void *void_data)
     pthread_mutex_unlock(&sys_log_lock);
   }
   comm.ftp_send(data->user, message);
-  // FIXME this is dangerous. we delete the data object, unknowing if the
-  // detached dns thread has returned or not, as it will write to
-  // data->hostname, which it has got as a reference it is dangerous to
-  // delete the data object, in fact we know nothing of it and no
-  // immediate solution comes to mind. except not detaching it and
-  // pthread_join(); thus waiting here until that thread returns.
-  // XXX we have done that before, and it is not an ideal sollutopn, 
-  // the way it works now with pthread_kill(); is actually better (if it
-  // works at all?).
   delete data;
   //pthread_exit(NULL);
   return(NULL);
Index: Commands2.cpp
===================================================================
RCS file: /cvsroot/babyftpd/babyftpd/Commands2.cpp,v
retrieving revision 1.4
retrieving revision 1.7
diff -u -p -b -r1.4 -r1.7
--- Commands2.cpp	21 May 2004 16:04:43 -0000	1.4
+++ Commands2.cpp	29 May 2004 21:14:04 -0000	1.7
@@ -213,8 +213,23 @@ bool Commands::help(User *user, string a
 
 bool Commands::cwd(User *user, string dir)
 { 
+  struct stat stt;
   string new_dir = Commands::parsedir(user, dir);
   
+  lstat(new_dir.c_str(), &stt);
+
+  if(S_ISLNK(stt.st_mode))
+  {
+    char *real_name = new char[65];
+    int len;
+
+    len = readlink(new_dir.c_str(), real_name, 60);
+    real_name[len] = '\0';
+    
+    new_dir = Commands::parsedir(user, real_name);
+    delete[] real_name;
+  }
+  
   if(!opendir(new_dir.c_str()))
   {
     if(errno == EACCES)
@@ -297,7 +312,7 @@ bool Commands::stor(User *user, string f
   int file_id, com_type;
 
   com_type = file[0];
-  file.erase(file.begin());
+  file.erase(0, 1);
 
   file_name = parsedir(user, file);
   
@@ -397,7 +412,7 @@ bool Commands::list(User *user, string a
   bool ret;
   
   type = argument[0];
-  argument.erase(argument.begin());
+  argument.erase(0, 1);
 
   if(argument == "")
     argument = user->current_dir;
@@ -758,7 +773,7 @@ bool Commands::rname(User *user, string 
   string file_name, message;
 
   command = argument[0];
-  argument.erase(argument.begin());
+  argument.erase(0, 1);
 
   file_name = parsedir(user, argument);
 
@@ -875,7 +890,9 @@ bool Commands::sim1(User *user, string a
   {
     string dir = user->current_dir;
     if(config->get_user(user->user_name).only_home)
-      dir.erase(1, user->root_dir.size() - 1);
+      dir.erase(0, user->root_dir.size());
+    if(dir == "")
+      dir = "/";
     message = "257 \"" + dir + "\" is current directory.\r\n";
   }
     
Index: Configuration.cpp
===================================================================
RCS file: /cvsroot/babyftpd/babyftpd/Configuration.cpp,v
retrieving revision 1.34
retrieving revision 1.36
diff -u -p -b -r1.34 -r1.36
--- Configuration.cpp	20 May 2004 22:08:54 -0000	1.34
+++ Configuration.cpp	23 May 2004 02:14:31 -0000	1.36
@@ -14,6 +14,7 @@ Configuration::Configuration()
   general.verbose = 1;
   general.log_level = 5;
   general.xferlog = 1; // log all transfers or not?
+  general.xferlog_file = "/var/log/xferlog"; // where transfer logs go
   general.no_daemon = false; // daemon mode or not?
   general.os = "UNIX"; // what OS is this?
   general.admin_email = ""; // admin email?
@@ -27,13 +28,12 @@ Configuration::Configuration()
   delete[] tmp;
   
   // these options end up as default for all users, that is, those that don't occur in the conf file get these values
-  user.id = "user_general";
-  user.user_limit = INT_MAX;
-  user.users.id = "user_general";
-  user.users.sim_data = INT_MAX;
-  user.users.idle = 900; // idle timeout after how long?
-  user.users.noftp = 0; // can this user login with ftp or not?
-  user.users.only_home = 0; // can the user traverse anything but his/her homedir FIXME: this doesn't work
+  general_user.id = "user_general";
+  general_user.sim_data = INT_MAX;
+  general_user.idle = 900; // idle timeout after how long?
+  general_user.noftp = 0; // can this user login with ftp or not?
+  general_user.only_home = 0; // can the user traverse anything but his/her homedir
+  general_user.user_limit = INT_MAX; // maximum control connections from this user
 }
 
 Configuration::~Configuration()
@@ -54,7 +54,7 @@ bool Configuration::parse_config_file()
   set_general(general, Sgeneral);
   
   get_variables(file_buff, rows, Suser, "general", 2);
-  set_user(user, Suser);
+  set_users(general_user, Suser);
   
   num_users = count_users(file_buff, rows, user_names) - 1; // first user is 0.
   
@@ -77,10 +77,11 @@ bool Configuration::parse_config_file()
 
 void Configuration::set_users(struct users_stru &usr, string &variables)
 {
-  usr.sim_data = user.users.sim_data;
-  usr.idle = user.users.idle;
-  usr.noftp = user.users.noftp;
-  usr.only_home = user.users.only_home;
+  usr.sim_data = general_user.sim_data;
+  usr.idle = general_user.idle;
+  usr.noftp = general_user.noftp;
+  usr.only_home = general_user.only_home;
+  usr.user_limit = general_user.user_limit;
   
   class StringTokenizer *var = new StringTokenizer(variables, "\n", false);
   usr.id = var->nextToken();
@@ -99,11 +100,13 @@ void Configuration::set_users(struct use
       usr.noftp = atoi(arg.c_str());
     else if(op.compare(users_op[3]) == 0)
       usr.only_home = atoi(arg.c_str());
+    else if(op.compare(users_op[4]) == 0)
+      usr.user_limit = atoi(arg.c_str());
     delete st;
   }
-  
-  cout << "configuration for: " << usr.id << " sim_data=" << usr.sim_data << " idle=" << usr.idle << " noftp=" << usr.noftp << " only_home=" << usr.only_home << endl;
   delete var;
+  
+  cout << "configuration for: " << usr.id << " sim_data=" << usr.sim_data << " idle=" << usr.idle << " noftp=" << usr.noftp << " only_home=" << usr.only_home << " user_limit=" << usr.user_limit << endl;
 }
 
 struct users_stru &Configuration::get_user(string name)
@@ -111,26 +114,7 @@ struct users_stru &Configuration::get_us
   for(int i = 0; i < num_users; i++)
     if(users[i].id == name && name != "")
       return users[i];
-  return user.users;
-}
-
-void Configuration::set_user(struct user_stru &ugen, string &variables)
-{
-  class StringTokenizer *var = new StringTokenizer(variables, "\n", false);
-  ugen.id = var->nextToken();
-  
-  for(int i = 0; i < var->countTokens(); i++)
-  {
-    string str = var->nextToken();
-    class StringTokenizer *st = new StringTokenizer(str, " ", false);
-    string op = st->nextToken();
-    string arg = st->nextToken();
-    if(op.compare(user_op[0]) == 0)
-      ugen.user_limit = atoi(arg.c_str());
-    delete st;
-    set_users(ugen.users, variables);
-  }
-  delete var;
+  return general_user;
 }
 
 int Configuration::count_users(string *&buff, int rows, string &users)
@@ -192,6 +176,8 @@ void Configuration::set_general(struct g
       gen.admin_email = arg.c_str();
     else if(op.compare(general_op[8]) == 0)
       gen.welcome_msg = arg.c_str();
+    else if(op.compare(general_op[9]) == 0)
+      gen.xferlog_file = arg.c_str();
     delete st;
   }
   delete var;
Index: Configuration.h
===================================================================
RCS file: /cvsroot/babyftpd/babyftpd/Configuration.h,v
retrieving revision 1.16
retrieving revision 1.19
diff -u -p -b -r1.16 -r1.19
--- Configuration.h	20 May 2004 21:33:43 -0000	1.16
+++ Configuration.h	23 May 2004 02:14:31 -0000	1.19
@@ -13,6 +13,7 @@ struct users_stru
   int idle;
   int noftp;
   int only_home;
+  int user_limit;
 };
 
 struct general_stru
@@ -28,16 +29,9 @@ struct general_stru
   string os;
   string admin_email;
   string welcome_msg;
+  string xferlog_file;
 };
     
-struct user_stru
-{
-  string id;
-  int user_limit;
-  struct users_stru users;
-};
-
-
 class Configuration
 {
   private:
@@ -49,20 +43,19 @@ class Configuration
     void fill_buff(string *&buff, string & filename, int rows);
     void get_variables(string *&buff, int rows, string &str, const char *key, int deep = 1);
     void set_general(struct general_stru &gen, string &variables);
-    void set_user(struct user_stru &ugen, string &variables);
     void set_users(struct users_stru &usr, string &variables);
     void trim(char *str);
   public:
     bool parse_config_file();
     string conf_file;
     struct general_stru general;
-    struct user_stru user;
+    struct users_stru general_user;
     Configuration(void);
     struct users_stru &get_user(string name);
     ~Configuration(void);
 };
 
-const string general_op[9] = 
+const string general_op[10] = 
 {
   "connection_limit",
   "port", 
@@ -72,20 +65,17 @@ const string general_op[9] = 
   "log_level", 
   "xferlog", 
   "admin_email", 
-  "welcome_msg"
-};
-
-const string user_op[1] = 
-{
-  "user_limit"
+  "welcome_msg",
+  "xferlog_file"
 };
 
-const string users_op[4] =
+const string users_op[5] =
 {
   "sim_data", 
   "idle",
   "noftp",
-  "only_home"
+  "only_home",
+  "user_limit"
 };
 
 #endif
Index: Handler.cpp
===================================================================
RCS file: /cvsroot/babyftpd/babyftpd/Handler.cpp,v
retrieving revision 1.104
retrieving revision 1.105
diff -u -p -b -r1.104 -r1.105
--- Handler.cpp	23 Apr 2004 09:52:18 -0000	1.104
+++ Handler.cpp	23 May 2004 02:14:31 -0000	1.105
@@ -45,7 +45,7 @@ class User *Handler::initializer(int soc
   user_list.push_back(user);
   pthread_mutex_unlock(&user_list_mutex);
   
-  if((int)user_list.size() > config->user.user_limit)
+  if((int)user_list.size() > config->general.connection_limit)
   {
     // reached maximum number of connections...
     comm.ftp_send(user, "421 Maximum number of connections reached, please try again later.\r\n");
Index: Log.cpp
===================================================================
RCS file: Log.cpp
diff -N Log.cpp
Index: Log.h
===================================================================
RCS file: Log.h
diff -N Log.h
Index: README
===================================================================
RCS file: /cvsroot/babyftpd/babyftpd/README,v
retrieving revision 1.3
retrieving revision 1.5
diff -u -p -b -r1.3 -r1.5
--- README	23 Dec 2002 23:39:28 -0000	1.3
+++ README	29 May 2004 21:34:48 -0000	1.5
@@ -3,3 +3,13 @@ Babyftpd version 0.0b
 This is a ftp server written mostly in c++, it is threaded. One important thing is worth mentioning. It is _not_ a finished product, don't use it if you don't know what you're doing, it might break things. It has only been tested with linux2.4 and glibc2.2.
 
 As of now no install script is provided, the executable, babyftpd, can be copied into place, but really, it is not ready for production use. to get a list of switches to be used send the switch -h.
+
+
+links:
+http://rfc959.x42.com/
+http://www.ietf.org/internet-drafts/draft-ietf-ftpext-mlst-16.txt
+http://ftp.linuxarkivet.se/pub/rfc/authors/rfc3659.txt
+http://www.ietf.org/internet-drafts/draft-preston-ftpext-deflate-01.txt
+
+more standards and the like will follow here..
+
Index: User.cpp
===================================================================
RCS file: /cvsroot/babyftpd/babyftpd/User.cpp,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -p -b -r1.37 -r1.38
--- User.cpp	20 May 2004 19:25:39 -0000	1.37
+++ User.cpp	22 May 2004 12:52:47 -0000	1.38
@@ -74,6 +74,7 @@ User::User(int socket_id, struct sockadd
   User::rest_pos = 0;
   User::host_name = inet_ntoa(User::ctrl_addr.sin_addr);
   User::root_dir = "/";
+  User::anonymous = 0;
 
   // for ability to change what we get...
   for(int fact = 0; fact != NUM_FACTS; fact++)
Index: User.h
===================================================================
RCS file: /cvsroot/babyftpd/babyftpd/User.h,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -p -b -r1.48 -r1.49
--- User.h	20 May 2004 21:33:43 -0000	1.48
+++ User.h	22 May 2004 12:52:47 -0000	1.49
@@ -78,6 +78,7 @@ class User
     bool passive;
     string temp_buf; // is this for anything but rename?
     int mlst_facts[NUM_FACTS];
+    int anonymous;
     off_t rest_pos;
     pthread_mutex_t lock;
     pthread_t thread_id;
Index: babyftpd.conf
===================================================================
RCS file: /cvsroot/babyftpd/babyftpd/Attic/babyftpd.conf,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -p -b -r1.9 -r1.10
--- babyftpd.conf	2 Mar 2003 01:01:52 -0000	1.9
+++ babyftpd.conf	23 May 2004 02:14:31 -0000	1.10
@@ -4,12 +4,14 @@ general          
   # well... this is only for testing so far =)
   port 2122
 
-
   # transfer log - on.
   xferlog 1
 
   # admin email
   admin_email you@your.host
+
+  # maximum number of control connections.
+  connection_limit 100
 }
 
 # user section, for... user stuff
@@ -20,10 +22,10 @@ user
   #   affect all users. options on specific users override general options.
   general
   {
-    # number of users? 5? :p
+    # number of control connections/user
     user_limit 5
     
-    # number of simultaneously open data connections (list & nlst excluded)
+    # number of simultaneously open data connections/control connection (list & nlst excluded)
     sim_data 3
   }
 
@@ -38,5 +40,7 @@ user
   {
     # this user can only see/touch tis /her/it's home directory
     only_home 1
+
+    user_limit 2
   }
 }
Index: generic.h
===================================================================
RCS file: /cvsroot/babyftpd/babyftpd/generic.h,v
retrieving revision 1.47
retrieving revision 1.52
diff -u -p -b -r1.47 -r1.52
--- generic.h	1 Mar 2003 21:16:51 -0000	1.47
+++ generic.h	29 May 2004 21:50:02 -0000	1.52
@@ -14,60 +14,58 @@
 
 #include <iostream>
 #include <string>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
 #include <syslog.h>
-#include <cstdio>
-#include <vector>
 #include "config.h"
 
 #ifdef __NETINCLS__
-  #include <sys/socket.h>
-  #include <arpa/inet.h>
-  #include <netinet/in.h>
-  #include <netdb.h>
-#endif
-
-#if (!defined(__STRINGTOKENIZER_H__) && !defined(__CONFIGURATION_H__))
-  #include <pthread.h>
-  #include <cerrno>
-#endif
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#endif // __NETINCLS__
+
+#if (!defined(__STRINGTOKENIZER_H__) && !defined(__CONFIGURATION_H__) && !defined(__UTILITIES_H__))
+#include <pthread.h>
+#include <cerrno>
+#include <vector>
+#endif // stuff...
 
 #ifdef __UTILITIES_H__
-  #include <cctype>
-  #include <sys/stat.h>
-#endif
+#include <cctype>
+#include <sys/stat.h>
+#endif // __UTILITIES_H__
 
 #ifdef __BABYFTPD_H__
-  #include <csignal>
-  #include <getopt.h>
-  #include <sys/stat.h>
-#endif
+#include <csignal>
+#include <getopt.h>
+#include <sys/stat.h>
+#endif // __BABYFTPD_H__
 
 #ifdef __HANDLER_H__
-  #include <csignal>
-#endif
+#include <csignal>
+#include <netdb.h>
+#endif // __HANDLER_H__
 
 #ifdef __CONFIGURATION_H__
-  #include <sys/utsname.h>
-  #include <fstream>
-  #include <climits>
-#endif
+#include <sys/utsname.h>
+#include <fstream>
+#include <climits>
+#endif // __CONFIGURATION_H__
 
 #ifdef __COMMANDS_H__
-  #include <pwd.h>
-  #include <grp.h>
-  #include <sys/sendfile.h>
-  #include <shadow.h>
-  #include <crypt.h>
-  #include <dirent.h>
-  #include <sys/fsuid.h>
-  #include <sys/stat.h>
-  #include <fstream>
-  #include <utmp.h>
-  #include <fcntl.h>
-#endif
+#include <pwd.h>
+#include <sys/stat.h>
+#endif // __COMMANDS_H__
+
+#ifdef __COMMANDS_CPP__
+#include <sys/sendfile.h>
+#endif // __COMMANDS_CPP__
+
+#ifdef __COMMANDS2_CPP__
+#include <grp.h>
+#include <shadow.h>
+#include <crypt.h>
+#include <dirent.h>
+#include <fcntl.h>
+#endif // __COMMANDS2_CPP__
 
 using namespace std;
 
@@ -79,10 +77,10 @@ class Commands;
 class Utilities;
 class StringTokenizer;
 
-#define VERSION "0.0b" // b to show that this is actually a working version, it can transfer files...
+#define VERSION "CVS: "__DATE__ // XXX remember to change this when releasing...
 
 #ifndef FTP_LOG
-  #define FTP_LOG DAEMON_LOG
+#define FTP_LOG DAEMON_LOG
 #endif // FTP_LOG
 
 #define test(a, b)   (((a) & (b)) == (b))
