--- src/ftpd.c	2011-03-02 01:56:11.000000000 -0500
+++ src/ftpd.c	2011-03-23 01:07:57.000000000 -0400
@@ -45,7 +45,8 @@
 LDAP* ldapHandle;
 
 int no_of_server = 0 ;
-const char* SERV_LIST_FILE = "/var/opt/novell/pure-ftpd/server_list.txt";
+#define FTP_RSN_PATH    "/var/opt/novell/pure-ftpd/"
+#define SERV_LIST_FILE "/var/opt/novell/pure-ftpd/server_list.txt"
 
      
 
@@ -55,14 +56,24 @@ const char* SERV_LIST_FILE = "/var/opt/n
 #define MAX_PATH_SIZE 1000
 #define MAX_IP_SIZE 20
 #define MAX_NO_OF_SERVERS 300
+#define SITE_MSG "NCP Servers in the NDS Tree"
+#define CHK_MOD_TIME 3600
+
+#define USER_FDN_SIZE 512 
+#define OES_DIR_MASK  0022
+#define OES_FILE_MASK 0133
 
 
 char serverInfo[MAX_NO_OF_SERVERS][120]; 
 const char MOUNT_PATH[] = "/var/opt/novell/nclmnt";
 const int MOUNT_PATH_SIZE = 22;
 	
-char userFDN[512];
+char userFDN[USER_FDN_SIZE];
+static char *userName = NULL;
 static const char *getlocalhostname();
+void extractEdir_IP_Port(char *);
+char* removeWhiteSpace(char *str);
+static const char *getUserNameByUID(const uid_t uid);
 	  
 
 #ifndef HAVE_SYS_FSUID_H
@@ -1669,7 +1680,9 @@ void dopass(char *password)
         /* Clear password from memory, paranoia */        
         register volatile char *password_ = (volatile char *) password;
 		if(remote_server == 1 )
+		{
 			edir_login(account,password,authresult.uid);
+		}
 
 	if(default_home_dir != NULL)
 	{
@@ -4204,6 +4217,9 @@ void dostor(char *name, const int append
     if (quota_exceeded == 0)
 #endif
     {
+     //Bug: 674992 - Auto rename feature is not supported by Remote server Navigation
+     if (!remote_server)
+     {		
         if (autorename != 0 && restartat == (off_t) 0) {
             if (tryautorename(atomic_file, name) != 0) {
                 error(553, MSG_RENAME_FAILURE);
@@ -4217,6 +4233,7 @@ void dostor(char *name, const int append
                 atomic_file = NULL;
             }
         }
+      }
         displayrate(MSG_UPLOADED, filesize - restartat, started, name, 1);
     }
     
@@ -5345,10 +5362,13 @@ int main(int argc, char *argv[])
             break;
         }
 		case '7': {
-			//Remove directory /var/opt/novell/pure-ftpd/		  
-			system("cnt=$(ps -eaf | grep pure-ftpd | wc -l);if [[ $cnt -lt 3 ]]; then rm -r /var/opt/novell/pure-ftpd/ &> /dev/null;fi");
-			mkdir("/var/opt/novell/pure-ftpd/",0777);
-			chmod("/var/opt/novell/pure-ftpd/",0777);
+			 char tmp[MAX_PATH_SIZE] = {0};
+
+			//Remove FTP_RSN_PATH if multi-instance of the server not running		  
+			sprintf(tmp,"cnt=$(ps -em | grep pure-ftpd | wc -l);if [[ $cnt -lt 2 ]]; then rm -r %s &> /dev/null;fi",FTP_RSN_PATH); 
+			system(tmp);
+
+			mkdir(FTP_RSN_PATH,(mode_t) 0777 & ~OES_DIR_MASK);
 			remote_server = 1;
 	   		break;
 		}			
@@ -5358,9 +5378,8 @@ int main(int argc, char *argv[])
 		}	
 				  
 		case '3': {
-	   		edir_ldap_port = atoi(optarg);
-			if(edir_ldap_port <= 0 )
-				edir_ldap_port = 389;
+			/* Extract E-directory IP address & Port number */
+			extractEdir_IP_Port(optarg);
 	   		break;
 		}			
 		case '2': {
@@ -6107,10 +6122,10 @@ int edir_login(const char* user,const ch
 	time_t curr_time;
 
 	
-	// get the FDN of user from pam_nam.so
-	void * lumHandle =  dlopen("/lib64/security/pam_nam.so", RTLD_LAZY);
+	// get the FDN of user from libnam_misc.so
+	void * lumHandle =  dlopen("/usr/lib64/libnam_misc.so", RTLD_LAZY);
 	if (lumHandle == NULL)
-		lumHandle =  dlopen("/lib/security/pam_nam.so", RTLD_LAZY);
+		lumHandle =  dlopen("/usr/lib/libnam_misc.so", RTLD_LAZY);
 	if(lumHandle != NULL)
 	{
 		namGetUserFDNfromUID = (int (*)(int, char *))dlsym(lumHandle, "namGetUserFDNfromUID");
@@ -6162,6 +6181,9 @@ int edir_login(const char* user,const ch
 		
 		char* data[9];
 		char* context;
+		char tree[MAX_SERVER_FDN_SIZE] = {0};
+		char server[MAX_SERVER_FDN_SIZE] = {0};
+
 		context = index(userFDN,'.');
 		if(context != NULL)
 			context++;
@@ -6173,8 +6195,11 @@ int edir_login(const char* user,const ch
 			exit(0);
 		}	
 		
-		data[0] ="-t 127.0.0.1";
-		data[1] ="-s 127.0.0.1";
+		snprintf(tree,sizeof(tree),"-t %s",edir_ip_address);
+		snprintf(server,sizeof(server),"-s %s",edir_ip_address);
+
+		data[0] =tree;
+		data[1] =server;
 		data[2] ="-u" ; data[3] = (char*)user;
 		data[4] ="-c" ; data[5] = (char*)context;
 		data[6] ="-p" ; data[7] = (char*)passwd;
@@ -6193,10 +6218,11 @@ int edir_login(const char* user,const ch
 		waitpid(pid,NULL,0);
 
 	//create directories to store no of simultaneous logins by same user
-	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s",account);
-	mkdir(tmp, 0777);
+	snprintf(tmp,sizeof(tmp),"%s/%s",FTP_RSN_PATH,account);
+	mkdir(tmp, (mode_t) 0777 & ~OES_DIR_MASK);
+	chown(tmp,uid,(gid_t)0);
 	
-	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s/count.txt",account);
+	snprintf(tmp,sizeof(tmp),"%s/%s/count.txt",FTP_RSN_PATH,account);
 	fd = fopen(tmp,"r+");
 	
 	openCount = 1;
@@ -6214,10 +6240,12 @@ int edir_login(const char* user,const ch
 	} else
 		openCount = 1;
 
-	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s/count.txt",account);
+	snprintf(tmp,sizeof(tmp),"%s/%s/count.txt",FTP_RSN_PATH,account);
 	fd = fopen(tmp,"w+");
 	if(fd != NULL)
 	{
+		chmod(tmp,(mode_t) 0777 & ~OES_FILE_MASK);
+		chown(tmp,uid,(gid_t)0);
 		fwrite(&openCount,sizeof(int),1,fd);
 		fclose(fd);	
 	}
@@ -6252,18 +6280,26 @@ int edir_login(const char* user,const ch
 
 int mount_remote_server(const char* where,char* nss_loc,char* remote_server)
 {
-	char tmp[MAX_PATH_SIZE+1000],path[MAX_PATH_SIZE];
+	char tmp[2*MAX_PATH_SIZE] = {0},path[MAX_PATH_SIZE] = {0};
 	char* str1,*server;
-	int err,i;
 	struct hostent *he;
 	struct in_addr ipv4addr;
 	//mnt_loc         - mounted path name by novell client (server name)
 	//ncl_req_name    - Request used in novell client (IP - preferably) 
-	char mnt_loc[MAX_SERVER_SIZE],ncl_req_name[MAX_SERVER_SIZE],ip[MAX_IP_SIZE];
+	char mnt_loc[MAX_SERVER_SIZE] ={0},ncl_req_name[MAX_SERVER_SIZE] = {0},ip[MAX_IP_SIZE] = {0};
 	struct in_addr addr;	
 	char*  context = NULL;
+	int pid = 0,ret =0,status = 0,i = 0;
+	// Get user Name for NWLOGIN
+	char *userNameWithSpace =  getUserNameByUID(authresult.uid);
+	
+	userName = removeWhiteSpace(userNameWithSpace);
+	if (NULL == userName)
+	{
+		userName = account;
+	}
 	
-	if((where != NULL ) &&(strncmp(where,"//",2 ) ==0))
+	if((where != NULL ) && (strncmp(where,"//",2 ) ==0) && (strlen(where) > 2) )
 	{
 
 		if( no_of_server <= 0) 
@@ -6276,6 +6312,11 @@ int mount_remote_server(const char* wher
 		str1 = (char*) where+2;
 		server = strtok(str1,"/");
 
+		if ( NULL == server)
+		{
+			return -1;
+		}
+
 		/*
 		   Get the server name/ip address of remote server
 		   Remote server name in ftp request can be either server name / DNS name / IP
@@ -6338,19 +6379,37 @@ int mount_remote_server(const char* wher
 		 * nwlogin as logged in ftp user. 
 		 * nwlogin does not require password here. novell client reuses exising connection
 		 */		
-		snprintf(tmp,sizeof(tmp),"sudo -u '%s' /opt/novell/ncl/bin/nwlogin -s '%s' -u '%s' -c '%s' -p x > /dev/null",account,ncl_req_name,account,context);
-		err= system(tmp);
 
-		if(err !=0 )
+		pid = fork();
+		if (!pid)
+       		{
+			
+			 setuid(authresult.uid);
+		         seteuid(authresult.uid);
+
+	                //redirect all nwlogin output to /dev/null to aviod sending wrong response to ftp client
+        	        stdout = freopen("/dev/null", "w", stdout);
+
+               		ret = execl("/opt/novell/ncl/bin/nwlogin","nwlogin","-s",ncl_req_name,"-u",userName,"-c",context,"-p","x",NULL );
+	              	if (ret != 0)
 		{
-			snprintf(tmp,sizeof(tmp),"Novell Client Login Failed with error %d ",err);
+				snprintf(tmp,sizeof(tmp),"Novell Client Login Failed with error %d ",errno);
 			logfile(LOG_ERR,tmp);
-			return -1;
+        	               	exit(0);
+                	}
+        	}
+		else
+		{
+                	waitpid(pid,&status,0);
+			if (status != 0)
+			{
+				snprintf(tmp,sizeof(tmp),"Novell Client Login Failed with error %d ",status);
+				logfile(LOG_ERR,tmp);
+			}
 		}
-
 		
 		if(nss_loc != NULL)
-			snprintf(nss_loc,MAX_PATH_SIZE,"%s/%s/%s/%s",MOUNT_PATH,account,mnt_loc,path);
+			snprintf(nss_loc,MAX_PATH_SIZE,"%s/%s/%s/%s",MOUNT_PATH,userName,mnt_loc,path);
 	
 		snprintf(tmp,sizeof(tmp),"ncl mount point:%s ftp request server name:%s ncl request server name:%s\n",nss_loc,remote_server,ncl_req_name);
 		logfile(LOG_DEBUG,tmp);
@@ -6367,7 +6426,12 @@ int umount_remote_server()
 	int openCount = 0;
 	FILE* fd = NULL;
 	
-	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s/count.txt",account);
+	if (NULL == userName)
+	{
+		userName=account;
+	}
+	
+	snprintf(tmp,sizeof(tmp),"%s/%s/count.txt",FTP_RSN_PATH,account);
 	fd = fopen(tmp,"r+");
 	if(fd != NULL)
 	{
@@ -6383,23 +6447,51 @@ int umount_remote_server()
 		fclose(fd);	
 		
 		fd = fopen(tmp,"w+");
+		chmod(tmp,(mode_t) 0777 & ~OES_FILE_MASK);
 		fwrite(&openCount,sizeof(int),1,fd);
 		fclose(fd);	
 	} else	
-		logfile(LOG_ERR,"File Open failed");
+		logfile(LOG_ERR,"File Open failed tmp:[%s] errno:[%s] uid:[%d] eid:[%d]",tmp,strerror(errno),getuid(),geteuid());
 	
 	//nwlogout is not called when same ftp user is logged in more than once
 	if(openCount <= 0)	
 	{	
-		snprintf(tmp,sizeof(tmp),"sudo -u '%s' /opt/novell/ncl/bin/nwlogout -f -a > /dev/null",account);
-		system(tmp); 
+		int pid = 0,ret = 0,status = 0;	
+
+		pid = fork();
+                if (!pid)
+                {
+                	setuid(authresult.uid);
+                	seteuid(authresult.uid);
+
+                        //redirect all nwlogout output to /dev/null to aviod sending wrong response to ftp client
+                        stdout = freopen("/dev/null", "w", stdout);
+
+			ret = execl("/opt/novell/ncl/bin/nwlogout","nwlogout","-f","-a",NULL );
+                        if (ret != 0)
+                        {
+                                snprintf(tmp,sizeof(tmp),"Novell Client Logout Failed with error %d ",errno);
+                                logfile(LOG_ERR,tmp);
+                                exit(0);
+                        }
+		}
+		else
+                {
+                        waitpid(pid,&status,0);
+                        if (status != 0)
+                        {
+                                snprintf(tmp,sizeof(tmp),"Novell Client Logout Failed with error %d ",status);
+                                logfile(LOG_ERR,tmp);
+				return -1;
+                        }
+                }
 	}	
 	return 0;
 }
 
 int get_remote_server_path(char* path)
 {	
-	char tmp[MAX_PATH_SIZE];
+	char tmp[MAX_PATH_SIZE] = {0};
 	
 	if (path == NULL)
 		return -1;
@@ -6410,22 +6502,97 @@ int get_remote_server_path(char* path)
 		snprintf(tmp,sizeof(tmp),"//%s",path+MOUNT_PATH_SIZE+1+strlen(account)+1);
 		strncpy(path,tmp,MAX_PATH_SIZE);
 	}	
+	else
+	{
+		return -1;
+	}
+	
 	return 0;
 }	
 
-// response for site slist command
+/**
+ * Description: This function is used to extract E-directory IP address
+ * and Port number.
+ *
+ * Input: Charcter string which have IP address & port number.
+ *
+ * Output: None.
+ */
+void extractEdir_IP_Port(char *optarg)
+{
+	char *ip_address;
+        char *port;
+
+	/* extract ip address */
+        ip_address=strtok(optarg,":");
+
+	/* extract port and validate the port */
+        if ( (NULL != ip_address) && (NULL != (port= strtok(NULL,":"))))
+        {
+        	edir_ip_address = strdup(ip_address);
+                edir_ldap_port = atoi(port);
+                
+		if((edir_ldap_port <= 0) || (edir_ldap_port > 65535))
+                	edir_ldap_port = 389;
+        }
+        else
+        {
+		/* Assign default IP address & port number */
+                edir_ip_address = "127.0.0.1";
+                edir_ldap_port = 389;
+        }
+
+	return;
+}
+
+/**
+ * Description: This function is used to get file modified
+ * time in seconds.
+ *
+ * Input: fileName - file from which modified time to be calculated.
+ *
+ * Output: integer which holds the modified time in seconds
+ */
+static int getModTime(char *fileName)
+{
+        struct stat fileStat = {0};
+        struct timeval curTime = {0};
+
+        // get the file status from the file.
+        if (stat(fileName,&fileStat) < 0)
+        {
+                return -1;
+        }
+
+	// get the current time.
+        gettimeofday(&curTime,NULL);
+
+        return (curTime.tv_sec - fileStat.st_mtime);
+}
+
+/** 
+ * Description: This function is used to response for site slist command.
+ *
+ * Input: None
+ *
+ * Output: integer which return the status
+ *
+ */
 int do_list_servers()
 {
 	FILE* file;
 	char buffer[2*MAX_SERVER_FDN_SIZE];
 	int serverLen;
-	char server[200],*ip;
+	char server[MAX_SERVER_FDN_SIZE + 2],countMsg[MAX_SERVER_FDN_SIZE +1]={0},*ip;
+	int nodeCount= 0;
 	
-	if( ( no_of_server <= 0) && (get_server_list_from_file() < 0))
+	if( (( no_of_server <= 0) && (get_server_list_from_file() < 0)) || (getModTime(SERV_LIST_FILE) >= CHK_MOD_TIME))
 		 get_server_list_from_edir();
 	
-	file = fopen (SERV_LIST_FILE,"r"); 
+	// Code added for Bug Fix: "534424 - FTP-RSN: Site slist doesn't list server count as in netware"
+	addreply_noformat(200, SITE_MSG);
 	
+	file = fopen (SERV_LIST_FILE,"r"); 
     if(file != NULL)
 	{	
 		while (!feof (file))
@@ -6442,12 +6609,19 @@ int do_list_servers()
 				serverLen = MAX_SERVER_FDN_SIZE;	
 			
 			snprintf(server,serverLen+1,"%s",buffer);
-			addreply_noformat(0, server);
+			
+			// Code added for Bug Fix: "534424 - FTP-RSN: Site slist doesn't list server count as in netware"
+			addreply_noformat(200, server);
+			nodeCount++;
 		}	
 		
 		fclose(file);
 	}  
 
+        // Code added for Bug Fix: "534424 - FTP-RSN: Site slist doesn't list server count as in netware"
+	snprintf(countMsg,MAX_SERVER_FDN_SIZE," %d \"NCP Server\"(s)",nodeCount);
+	addreply_noformat(200, countMsg);
+
 	return 0;
 	
 }
@@ -6455,7 +6629,7 @@ int do_list_servers()
 				  
 int ldap_connect(const char* username,const char*passwd)
 {	
-    	ldapHandle = ldap_init("127.0.0.1",edir_ldap_port);
+    	ldapHandle = ldap_init(edir_ip_address,edir_ldap_port);
     	if (ldapHandle == NULL)
     	{
 			return -1;
@@ -6499,6 +6673,7 @@ int get_server_list_from_edir()
 	if(rc == LDAP_SUCCESS )
 	{
 		file = fopen (SERV_LIST_FILE,"w+"); 
+		chmod(SERV_LIST_FILE,(mode_t) 0777 & ~OES_FILE_MASK);
 		for(entry = ldap_first_entry(ldapHandle,searchResult) ; entry != NULL ;
 				entry = ldap_next_entry(ldapHandle,entry))
 	    	    {
@@ -6633,3 +6808,63 @@ int get_server(char*ip, char*server)
 	return -1;
 }
 	   
+
+/* This function is used to remove all the white space characters.
+ *
+ * Input: String 
+ *
+ * Output: remove white space string
+ */ 
+char* removeWhiteSpace(char *str)
+{
+        char *userNameStr;
+        int i=0;
+
+        if (NULL == str)
+        {
+                return NULL;
+        }
+
+        userNameStr=strdup(str);
+
+        // Remove White Space characters
+        for(i = 0;(userNameStr[i] != '\0') || (userNameStr[i] != 0);i++)
+        {
+                if (userNameStr[i] ==' ')
+                {
+                        userNameStr[i] ='\0';
+                }
+        }
+
+        return userNameStr;
+}
+
+
+/* This function is used to get the UserName by using UID
+ *
+ * Input : User ID
+ *
+ * Output : user name	
+ */
+static const char *getUserNameByUID(const uid_t uid)
+{
+    struct passwd *pwd = NULL;
+    char *userName = NULL;
+    
+    if ((userName = malloc((size_t) 32U)) == NULL)
+    {
+        die_mem();
+    }
+
+    pwd = getpwuid(uid);
+    if (pwd != NULL)
+    {
+        /* LUM enabled user supported upto 31 charcters, RSN also should should support the same - Karthikeyan ,Bug ID 643981 */
+        if (SNCHECK(snprintf(userName, (size_t) 32U,"%-10.32s", pwd->pw_name), (size_t) 32U))
+	{
+            _EXIT(EXIT_FAILURE);
+        }
+    }
+
+    return userName;
+}
--- src/globals.h	2011-03-02 01:56:11.000000000 -0500
+++ src/globals.h	2011-03-02 02:02:24.000000000 -0500
@@ -30,6 +30,7 @@ GLOBAL0(signed char no_ipv4);           
 GLOBAL0(signed char remote_server);                    /* OES remote server supported or not*/
 GLOBAL0(signed char disallow_list_oes_server);         /* list remote OES server supported or not*/
 GLOBAL(unsigned int edir_ldap_port,389);                 /* edirectory ldap port*/
+GLOBAL0(char *edir_ip_address);                 /* edirectory ip address */
 GLOBAL0(char *default_home_dir);                /* default home dir */
 GLOBAL(const size_t cmdsize, MAXPATHLEN + 16U);
 GLOBAL0(char cmd[MAXPATHLEN + 32U]);        /* command line - about 30 chars for command */
--- src/ls.c	2011-03-02 01:56:11.000000000 -0500
+++ src/ls.c	2011-03-22 03:31:38.000000000 -0400
@@ -767,6 +767,8 @@ void donlist(char *arg, const int on_ctr
              const int split_args)
 {
     int c;
+    // support full remote server path
+    char curPath[MAX_PATH_SIZE]= {0} ,nss_loc[MAX_PATH_SIZE] = {0}, traPath[MAX_PATH_SIZE] = {0};
 
     matches = 0U;
 
@@ -851,10 +853,33 @@ void donlist(char *arg, const int on_ctr
 
         justone = 1;            /* just one argument, so don't print dir name */
 
-	// support full remote server path
- 	 char nss_loc[MAX_PATH_SIZE];
- 	if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+
+	if (remote_server == 1)
+	{
+		if(NULL == getcwd(curPath, sizeof curPath - (size_t) 1U))
+		{
+            		logfile(LOG_ERR," Get current working directory failed");
+		}
+		else
+		{
+			//set the current working directory  
+			strncpy(wd,curPath,strlen(curPath) + 1);
+			get_remote_server_path(curPath);
+		}
+
+		if (opt_l_ == 1)
+		{
+			if ((strncmp(curPath,"//",2) != 0) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+			{
 		arg = nss_loc;
+			}
+			else if ( (mount_remote_server(curPath,nss_loc,NULL) ==0))
+			{
+				snprintf(traPath,sizeof(traPath),"%s/%s",nss_loc,arg);
+				arg = traPath;
+			}
+		}
+	}
 
         do {
             glob_t g;
@@ -975,4 +1000,8 @@ void donlist(char *arg, const int on_ctr
     }
     end:
     chdir(wd);
+    if (remote_server == 1)
+    {
+	get_remote_server_path(wd);		
+    }	
 }
--- src/ftp_parser.c	2011-03-02 01:56:11.000000000 -0500
+++ src/ftp_parser.c	2011-03-22 00:40:24.000000000 -0400
@@ -518,7 +518,11 @@ void parser(void)
     		// support full remote server path
     		char nss_loc[MAX_PATH_SIZE];
     		if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+		{
 	    		arg = nss_loc;
+			//Bug: 674992 - Auto rename feature is not supported by Remote server Navigation
+			autorename = 0;
+		}
                 arg = revealextraspc(arg);
                 if (*arg != 0) {
 #ifdef WITH_TLS
@@ -785,6 +789,11 @@ void parser(void)
             } else if (!strcmp(cmd, "mdtm")) {
                 domdtm(arg);
             } else if (!strcmp(cmd, "size")) {
+	    		char nss_loc[MAX_PATH_SIZE] = {0};
+    			if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+			{
+	    			arg = nss_loc;
+			}
                 dosize(arg);
 #ifndef MINIMAL
             } else if (!strcmp(cmd, "chmod")) {
