Remove trailing slashes from service name
[ira/wip.git] / source / client / client.c
index 1fbee70645c9ecb1f34af586f5f1ac4f06b09d57..ed33d42081c6ea1e7af83a7371366b00a9160ec3 100644 (file)
@@ -8,7 +8,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "client/client_proto.h"
+#include "include/rpc_client.h"
 #ifndef REGISTER
 #define REGISTER 0
 #endif
 
-extern BOOL AllowDebugChange;
-extern BOOL override_logfile;
+extern bool AllowDebugChange;
+extern bool override_logfile;
 extern char tar_type;
-extern BOOL in_client;
+extern bool in_client;
 static int port = 0;
 pstring cur_dir = "\\";
 static pstring cd_path = "";
@@ -38,7 +38,7 @@ static pstring service;
 static pstring desthost;
 static pstring username;
 static pstring calling_name;
-static BOOL grepable=False;
+static bool grepable=False;
 static char *cmdstr = NULL;
 
 static int io_bufsize = 64512;
@@ -49,6 +49,10 @@ extern int max_protocol;
 static int process_tok(pstring tok);
 static int cmd_help(void);
 
+static TALLOC_CTX *ctx;
+#define CREATE_ACCESS_READ READ_CONTROL_ACCESS
+static pstring cwd;
+
 /* 30 second timeout on most commands */
 #define CLIENT_TIMEOUT (30*1000)
 #define SHORT_TIMEOUT (5*1000)
@@ -59,26 +63,27 @@ static int cmd_help(void);
 time_t newer_than = 0;
 static int archive_level = 0;
 
-static BOOL translation = False;
-static BOOL have_ip;
+static bool translation = False;
+static bool have_ip;
 
 /* clitar bits insert */
 extern int blocksize;
-extern BOOL tar_inc;
-extern BOOL tar_reset;
+extern bool tar_inc;
+extern bool tar_reset;
 /* clitar bits end */
  
 
-static BOOL prompt = True;
+static bool prompt = True;
 
-static BOOL recurse = False;
-BOOL lowercase = False;
+static bool recurse = False;
+static bool showacls = False;
+bool lowercase = False;
 
-static struct in_addr dest_ip;
+static struct sockaddr_storage dest_ss;
 
 #define SEPARATORS " \t\n\r"
 
-static BOOL abort_mget = True;
+static bool abort_mget = True;
 
 static pstring fileselection = "";
 
@@ -97,7 +102,8 @@ static double dir_total;
 
 struct cli_state *cli;
 
-
+static char CLI_DIRSEP_CHAR = '\\';
+static char CLI_DIRSEP_STR[] = { '\\', '\0' };
 
 /****************************************************************************
  Write to a local file with CR/LF->LF translation if appropriate. Return the 
@@ -187,6 +193,10 @@ static void send_message(void)
                        msg[l] = c;   
                }
 
+               if ((total_len > 0) && (strlen(msg) == 0)) {
+                       break;
+               }
+
                if (!cli_message_text(cli, msg, l, grp_id)) {
                        d_printf("SMBsendtxt failed (%s)\n",cli_errstr(cli));
                        return;
@@ -216,7 +226,7 @@ static int do_dskattr(void)
        struct cli_state *targetcli;
        pstring targetpath;
 
-       if ( !cli_resolve_path( "", cli, cur_dir, &targetcli, targetpath ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, cur_dir, &targetcli, targetpath ) ) {
                d_printf("Error in dskattr: %s\n", cli_errstr(cli));
                return 1;
        }
@@ -264,29 +274,27 @@ static int do_cd(char *newdir)
 
        pstrcpy(saved_dir, cur_dir);
 
-       if (*p == '\\')
+       if (*p == CLI_DIRSEP_CHAR) {
                pstrcpy(cur_dir,p);
-       else
+       } else {
                pstrcat(cur_dir,p);
-
-       if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
-               pstrcat(cur_dir, "\\");
+               if ((cur_dir[0] != '\0') && (*(cur_dir+strlen(cur_dir)-1) != CLI_DIRSEP_CHAR)) {
+                       pstrcat(cur_dir, CLI_DIRSEP_STR);
+               }
        }
        
-       dos_clean_name(cur_dir);
+       pstring_clean_name(cur_dir);
        pstrcpy( dname, cur_dir );
-       pstrcat(cur_dir,"\\");
-       dos_clean_name(cur_dir);
        
-       if ( !cli_resolve_path( "", cli, dname, &targetcli, targetpath ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, dname, &targetcli, targetpath ) ) {
                d_printf("cd %s: %s\n", dname, cli_errstr(cli));
                pstrcpy(cur_dir,saved_dir);
                goto out;
        }
 
-       
-       if ( strequal(targetpath,"\\" ) )
-               return 0;   
+       if (strequal(targetpath,CLI_DIRSEP_STR )) {
+               return 0;
+       }
                
        /* Use a trans2_qpathinfo to test directories for modern servers.
           Except Win9x doesn't support the qpathinfo_basic() call..... */ 
@@ -304,8 +312,8 @@ static int do_cd(char *newdir)
                        goto out;
                }               
        } else {
-               pstrcat( targetpath, "\\" );
-               dos_clean_name( targetpath );
+               pstrcat( targetpath, CLI_DIRSEP_STR );
+               pstring_clean_name( targetpath );
                
                if ( !cli_chkpath(targetcli, targetpath) ) {
                        d_printf("cd %s: %s\n", dname, cli_errstr(targetcli));
@@ -339,11 +347,24 @@ static int cmd_cd(void)
        return rc;
 }
 
+/****************************************************************************
+ Change directory.
+****************************************************************************/
+
+static int cmd_cd_oneup(void)
+{
+       pstring buf;
+
+       pstrcpy(buf, "..");
+       return do_cd(buf);
+}
+
+
 /*******************************************************************
  Decide if a file should be operated on.
 ********************************************************************/
 
-static BOOL do_this_one(file_info *finfo)
+static bool do_this_one(file_info *finfo)
 {
        if (finfo->mode & aDIR)
                return(True);
@@ -354,7 +375,7 @@ static BOOL do_this_one(file_info *finfo)
                return False;
        }
 
-       if (newer_than && finfo->mtime < newer_than) {
+       if (newer_than && finfo->mtime_ts.tv_sec < newer_than) {
                DEBUG(3,("newer_than %s failed\n", finfo->name));
                return(False);
        }
@@ -374,13 +395,47 @@ static BOOL do_this_one(file_info *finfo)
 static void display_finfo(file_info *finfo)
 {
        if (do_this_one(finfo)) {
-               time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
-               d_printf("  %-30s%7.7s %8.0f  %s",
-                        finfo->name,
-                        attrib_string(finfo->mode),
-                        (double)finfo->size,
-                        asctime(localtime(&t)));
-               dir_total += finfo->size;
+               time_t t = finfo->mtime_ts.tv_sec; /* the time is assumed to be passed as GMT */
+               if (!showacls) {
+                       d_printf("  %-30s%7.7s %8.0f  %s",
+                                finfo->name,
+                                attrib_string(finfo->mode),
+                               (double)finfo->size,
+                               time_to_asc(t));
+                       dir_total += finfo->size;
+               } else {
+                       pstring afname;
+                       int fnum;
+
+                       /* skip if this is . or .. */
+                       if ( strequal(finfo->name,"..") || strequal(finfo->name,".") )
+                               return;
+                       /* create absolute filename for cli_nt_create() FIXME */
+                       pstrcpy( afname, cwd);
+                       pstrcat( afname, CLI_DIRSEP_STR);
+                       pstrcat( afname, finfo->name);
+                       /* print file meta date header */
+                       d_printf( "FILENAME:%s\n", afname);
+                       d_printf( "MODE:%s\n", attrib_string(finfo->mode));
+                       d_printf( "SIZE:%.0f\n", (double)finfo->size);
+                       d_printf( "MTIME:%s", time_to_asc(t));
+                       fnum = cli_nt_create(finfo->cli, afname, CREATE_ACCESS_READ);
+                       if (fnum == -1) {
+                               DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
+                                       afname,
+                                       cli_errstr( finfo->cli)));
+                       } else {
+                               SEC_DESC *sd = NULL;
+                               sd = cli_query_secdesc(finfo->cli, fnum, ctx);
+                               if (!sd) {
+                                       DEBUG( 0, ("display_finfo() failed to "
+                                               "get security descriptor: %s",
+                                               cli_errstr( finfo->cli)));
+                               } else {
+                                       display_sec_desc(sd);
+                               }
+                       }
+               }
        }
 }
 
@@ -395,8 +450,8 @@ static void do_du(file_info *finfo)
        }
 }
 
-static BOOL do_list_recurse;
-static BOOL do_list_dirs;
+static bool do_list_recurse;
+static bool do_list_dirs;
 static char *do_list_queue = 0;
 static long do_list_queue_size = 0;
 static long do_list_queue_start = 0;
@@ -431,7 +486,7 @@ static void init_do_list_queue(void)
 {
        reset_do_list_queue();
        do_list_queue_size = 1024;
-       do_list_queue = SMB_MALLOC(do_list_queue_size);
+       do_list_queue = (char *)SMB_MALLOC(do_list_queue_size);
        if (do_list_queue == 0) { 
                d_printf("malloc fail for size %d\n",
                         (int)do_list_queue_size);
@@ -447,7 +502,14 @@ static void adjust_do_list_queue(void)
         * If the starting point of the queue is more than half way through,
         * move everything toward the beginning.
         */
-       if (do_list_queue && (do_list_queue_start == do_list_queue_end)) {
+
+       if (do_list_queue == NULL) {
+               DEBUG(4,("do_list_queue is empty\n"));
+               do_list_queue_start = do_list_queue_end = 0;
+               return;
+       }
+               
+       if (do_list_queue_start == do_list_queue_end) {
                DEBUG(4,("do_list_queue is empty\n"));
                do_list_queue_start = do_list_queue_end = 0;
                *do_list_queue = '\0';
@@ -468,7 +530,7 @@ static void add_to_do_list_queue(const char* entry)
                do_list_queue_size *= 2;
                DEBUG(4,("enlarging do_list_queue to %d\n",
                         (int)do_list_queue_size));
-               do_list_queue = SMB_REALLOC(do_list_queue, do_list_queue_size);
+               do_list_queue = (char *)SMB_REALLOC(do_list_queue, do_list_queue_size);
                if (! do_list_queue) {
                        d_printf("failure enlarging do_list_queue to %d bytes\n",
                                 (int)do_list_queue_size);
@@ -517,7 +579,7 @@ static void do_list_helper(const char *mntpoint, file_info *f, const char *mask,
 
        /* save the directory */
        pstrcpy( f->dir, mask );
-       if ( (dir_end = strrchr( f->dir, '\\' )) != NULL ) {
+       if ( (dir_end = strrchr( f->dir, CLI_DIRSEP_CHAR )) != NULL ) {
                *dir_end = '\0';
        }
 
@@ -538,12 +600,13 @@ static void do_list_helper(const char *mntpoint, file_info *f, const char *mask,
 
                        pstrcpy(mask2, mntpoint);
                        pstrcat(mask2, mask);
-                       p = strrchr_m(mask2,'\\');
+                       p = strrchr_m(mask2,CLI_DIRSEP_CHAR);
                        if (!p)
                                return;
                        p[1] = 0;
                        pstrcat(mask2, f->name);
-                       pstrcat(mask2,"\\*");
+                       pstrcat(mask2,CLI_DIRSEP_STR);
+                       pstrcat(mask2,"*");
                        add_to_do_list_queue(mask2);
                }
                return;
@@ -558,7 +621,7 @@ static void do_list_helper(const char *mntpoint, file_info *f, const char *mask,
  A wrapper around cli_list that adds recursion.
 ****************************************************************************/
 
-void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec, BOOL dirs)
+void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),bool rec, bool dirs)
 {
        static int in_do_list = 0;
        struct cli_state *targetcli;
@@ -592,7 +655,7 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec,
                        
                        /* check for dfs */
                        
-                       if ( !cli_resolve_path( "", cli, head, &targetcli, targetpath ) ) {
+                       if ( !cli_resolve_path_pstring( "", cli, head, &targetcli, targetpath ) ) {
                                d_printf("do_list: [%s] %s\n", head, cli_errstr(cli));
                                remove_do_list_queue_head();
                                continue;
@@ -605,21 +668,24 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec,
                                char* save_ch = 0;
                                if ((strlen(next_file) >= 2) &&
                                    (next_file[strlen(next_file) - 1] == '*') &&
-                                   (next_file[strlen(next_file) - 2] == '\\')) {
+                                   (next_file[strlen(next_file) - 2] == CLI_DIRSEP_CHAR)) {
                                        save_ch = next_file +
                                                strlen(next_file) - 2;
                                        *save_ch = '\0';
+                                       if (showacls) /* cwd is only used if showacls is on */
+                                               pstrcpy( cwd, next_file);
                                }
-                               d_printf("\n%s\n",next_file);
+                               if (!showacls) /* don't disturbe the showacls output */
+                                       d_printf("\n%s\n",next_file);
                                if (save_ch) {
-                                       *save_ch = '\\';
+                                       *save_ch = CLI_DIRSEP_CHAR;
                                }
                        }
                }
        } else {
                /* check for dfs */
                        
-               if ( cli_resolve_path( "", cli, mask, &targetcli, targetpath ) ) {
+               if ( cli_resolve_path_pstring( "", cli, mask, &targetcli, targetpath ) ) {
                        if (cli_list(targetcli, targetpath, attribute, do_list_helper, NULL) == -1) 
                                d_printf("%s listing %s\n", cli_errstr(targetcli), targetpath);
                }
@@ -645,17 +711,17 @@ static int cmd_dir(void)
        int rc;
        
        dir_total = 0;
-       if (strcmp(cur_dir, "\\") != 0) {
+       if (strcmp(cur_dir, CLI_DIRSEP_STR) != 0) {
                pstrcpy(mask,cur_dir);
-               if(mask[strlen(mask)-1]!='\\')
-                       pstrcat(mask,"\\");
+               if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR))
+                       pstrcat(mask,CLI_DIRSEP_STR);
        } else {
-               pstrcpy(mask, "\\");
+               pstrcpy(mask, CLI_DIRSEP_STR);
        }
        
        if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
                dos_format(p);
-               if (*p == '\\')
+               if (*p == CLI_DIRSEP_CHAR)
                        pstrcpy(mask,p + 1);
                else
                        pstrcat(mask,p);
@@ -663,6 +729,11 @@ static int cmd_dir(void)
                pstrcat(mask,"*");
        }
 
+       if (showacls) {
+               /* cwd is only used if showacls is on */
+               pstrcpy(cwd, cur_dir);
+       }
+
        do_list(mask, attribute, display_finfo, recurse, True);
 
        rc = do_dskattr();
@@ -686,12 +757,12 @@ static int cmd_du(void)
        
        dir_total = 0;
        pstrcpy(mask,cur_dir);
-       if(mask[strlen(mask)-1]!='\\')
-               pstrcat(mask,"\\");
+       if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR))
+               pstrcat(mask,CLI_DIRSEP_STR);
        
        if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
                dos_format(p);
-               if (*p == '\\')
+               if (*p == CLI_DIRSEP_CHAR)
                        pstrcpy(mask,p);
                else
                        pstrcat(mask,p);
@@ -708,14 +779,34 @@ static int cmd_du(void)
        return rc;
 }
 
+static int cmd_echo(void)
+{
+       fstring num;
+       pstring data;
+
+       if (!next_token_nr(NULL, num, NULL, sizeof(num))
+           || !next_token_nr(NULL, data, NULL, sizeof(data))) {
+               d_printf("echo <num> <data>\n");
+               return 1;
+       }
+
+       if (!cli_echo(cli, atoi(num), (uint8 *)data, strlen(data))) {
+               d_printf("echo failed: %s\n",
+                        nt_errstr(cli_get_nt_error(cli)));
+               return 1;
+       }
+
+       return 0;
+}
+
 /****************************************************************************
  Get a file from rname to lname
 ****************************************************************************/
 
-static int do_get(char *rname, char *lname, BOOL reget)
+static int do_get(char *rname, char *lname, bool reget)
 {  
        int handle = 0, fnum;
-       BOOL newhandle = False;
+       bool newhandle = False;
        char *data;
        struct timeval tp_start;
        int read_size = io_bufsize;
@@ -732,24 +823,13 @@ static int do_get(char *rname, char *lname, BOOL reget)
                strlower_m(lname);
        }
 
-       if ( !cli_resolve_path( "", cli, rname, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, rname, &targetcli, targetname ) ) {
                d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
                return 1;
        }
 
        GetTimeOfDay(&tp_start);
        
-       if ( targetcli->dfsroot ) {
-               pstring path;
-
-               /* we need to refer to the full \server\share\path format 
-                  for dfs shares */
-
-               pstrcpy( path, targetname );
-               cli_dfs_make_full_path( targetname, targetcli->desthost, 
-                       targetcli->share, path);
-       }
-
        fnum = cli_open(targetcli, targetname, O_RDONLY, DENY_NONE);
 
        if (fnum == -1) {
@@ -864,7 +944,7 @@ static int cmd_get(void)
        char *p;
 
        pstrcpy(rname,cur_dir);
-       pstrcat(rname,"\\");
+       pstrcat(rname,CLI_DIRSEP_STR);
        
        p = rname + strlen(rname);
        
@@ -873,7 +953,7 @@ static int cmd_get(void)
                return 1;
        }
        pstrcpy(lname,p);
-       dos_clean_name(rname);
+       pstring_clean_name(rname);
        
        next_token_nr(NULL,lname,NULL,sizeof(lname));
        
@@ -920,7 +1000,7 @@ static void do_mget(file_info *finfo)
        pstrcpy(saved_curdir,cur_dir);
 
        pstrcat(cur_dir,finfo->name);
-       pstrcat(cur_dir,"\\");
+       pstrcat(cur_dir,CLI_DIRSEP_STR);
 
        unix_format(finfo->name);
        if (lowercase)
@@ -959,7 +1039,7 @@ static int cmd_more(void)
        int rc = 0;
 
        pstrcpy(rname,cur_dir);
-       pstrcat(rname,"\\");
+       pstrcat(rname,CLI_DIRSEP_STR);
        
        slprintf(lname,sizeof(lname)-1, "%s/smbmore.XXXXXX",tmpdir());
        fd = smb_mkstemp(lname);
@@ -974,7 +1054,7 @@ static int cmd_more(void)
                unlink(lname);
                return 1;
        }
-       dos_clean_name(rname);
+       pstring_clean_name(rname);
 
        rc = do_get(rname, lname, False);
 
@@ -1008,10 +1088,10 @@ static int cmd_mget(void)
 
        while (next_token_nr(NULL,p,NULL,sizeof(buf))) {
                pstrcpy(mget_mask,cur_dir);
-               if(mget_mask[strlen(mget_mask)-1]!='\\')
-                       pstrcat(mget_mask,"\\");
+               if ((mget_mask[0] != '\0') && (mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR))
+                       pstrcat(mget_mask,CLI_DIRSEP_STR);
                
-               if (*p == '\\')
+               if (*p == CLI_DIRSEP_CHAR)
                        pstrcpy(mget_mask,p);
                else
                        pstrcat(mget_mask,p);
@@ -1020,8 +1100,8 @@ static int cmd_mget(void)
 
        if (!*mget_mask) {
                pstrcpy(mget_mask,cur_dir);
-               if(mget_mask[strlen(mget_mask)-1]!='\\')
-                       pstrcat(mget_mask,"\\");
+               if(mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR)
+                       pstrcat(mget_mask,CLI_DIRSEP_STR);
                pstrcat(mget_mask,"*");
                do_list(mget_mask, attribute,do_mget,False,True);
        }
@@ -1033,12 +1113,12 @@ static int cmd_mget(void)
  Make a directory of name "name".
 ****************************************************************************/
 
-static BOOL do_mkdir(char *name)
+static bool do_mkdir(char *name)
 {
        struct cli_state *targetcli;
        pstring targetname;
        
-       if ( !cli_resolve_path( "", cli, name, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, name, &targetcli, targetname ) ) {
                d_printf("mkdir %s: %s\n", name, cli_errstr(cli));
                return False;
        }
@@ -1056,7 +1136,7 @@ static BOOL do_mkdir(char *name)
  Show 8.3 name of a file.
 ****************************************************************************/
 
-static BOOL do_altname(char *name)
+static bool do_altname(char *name)
 {
        pstring altname;
        if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
@@ -1076,6 +1156,7 @@ static BOOL do_altname(char *name)
 static int cmd_quit(void)
 {
        cli_cm_shutdown();
+       talloc_destroy( ctx);
        exit(0);
        /* NOTREACHED */
        return 0;
@@ -1103,17 +1184,23 @@ static int cmd_mkdir(void)
        if (recurse) {
                pstring ddir;
                pstring ddir2;
+               struct cli_state *targetcli;
+               pstring targetname;
                *ddir2 = 0;
                
-               pstrcpy(ddir,mask);
+               if ( !cli_resolve_path_pstring( "", cli, mask, &targetcli, targetname ) ) {
+                       return 1;
+               }
+
+               pstrcpy(ddir,targetname);
                trim_char(ddir,'.','\0');
                p = strtok(ddir,"/\\");
                while (p) {
                        pstrcat(ddir2,p);
-                       if (!cli_chkpath(cli, ddir2)) { 
+                       if (!cli_chkpath(targetcli, ddir2)) { 
                                do_mkdir(ddir2);
                        }
-                       pstrcat(ddir2,"\\");
+                       pstrcat(ddir2,CLI_DIRSEP_STR);
                        p = strtok(NULL,"/\\");
                }        
        } else {
@@ -1150,7 +1237,7 @@ static int cmd_altname(void)
  Put a single file.
 ****************************************************************************/
 
-static int do_put(char *rname, char *lname, BOOL reput)
+static int do_put(char *rname, char *lname, bool reput)
 {
        int fnum;
        XFILE *f;
@@ -1163,7 +1250,7 @@ static int do_put(char *rname, char *lname, BOOL reput)
        struct cli_state *targetcli;
        pstring targetname;
        
-       if ( !cli_resolve_path( "", cli, rname, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, rname, &targetcli, targetname ) ) {
                d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
                return 1;
        }
@@ -1293,7 +1380,7 @@ static int cmd_put(void)
        char *p=buf;
        
        pstrcpy(rname,cur_dir);
-       pstrcat(rname,"\\");
+       pstrcat(rname,CLI_DIRSEP_STR);
   
        if (!next_token_nr(NULL,p,NULL,sizeof(buf))) {
                d_printf("put <filename>\n");
@@ -1306,7 +1393,7 @@ static int cmd_put(void)
        else
                pstrcat(rname,lname);
        
-       dos_clean_name(rname);
+       pstring_clean_name(rname);
 
        {
                SMB_STRUCT_STAT st;
@@ -1329,7 +1416,7 @@ static int cmd_put(void)
 static struct file_list {
        struct file_list *prev, *next;
        char *file_path;
-       BOOL isdir;
+       bool isdir;
 } *file_list;
 
 /****************************************************************************
@@ -1353,7 +1440,7 @@ static void free_file_list (struct file_list *list_head)
  the specified name.
 ****************************************************************************/
 
-static BOOL seek_list(struct file_list *list, char *name)
+static bool seek_list(struct file_list *list, char *name)
 {
        while (list) {
                trim_string(list->file_path,"./","\n");
@@ -1384,14 +1471,14 @@ static int cmd_select(void)
 ****************************************************************************/
 
 static int file_find(struct file_list **list, const char *directory, 
-                     const char *expression, BOOL match)
+                     const char *expression, bool match)
 {
        SMB_STRUCT_DIR *dir;
        struct file_list *entry;
         struct stat statbuf;
         int ret;
         char *path;
-       BOOL isdir;
+       bool isdir;
        const char *dname;
 
         dir = sys_opendir(directory);
@@ -1620,13 +1707,13 @@ static void do_del(file_info *finfo)
 {
        pstring mask;
 
-       pstr_sprintf( mask, "%s\\%s", finfo->dir, finfo->name );
+       pstr_sprintf( mask, "%s%c%s", finfo->dir, CLI_DIRSEP_CHAR, finfo->name );
 
        if (finfo->mode & aDIR) 
                return;
 
-       if (!cli_unlink(cli, mask)) {
-               d_printf("%s deleting remote file %s\n",cli_errstr(cli),mask);
+       if (!cli_unlink(finfo->cli, mask)) {
+               d_printf("%s deleting remote file %s\n",cli_errstr(finfo->cli),mask);
        }
 }
 
@@ -1657,15 +1744,54 @@ static int cmd_del(void)
 }
 
 /****************************************************************************
+ Wildcard delete some files.
 ****************************************************************************/
 
-static int cmd_open(void)
+static int cmd_wdel(void)
 {
        pstring mask;
        pstring buf;
+       uint16 attribute;
        struct cli_state *targetcli;
        pstring targetname;
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("wdel 0x<attrib> <wcard>\n");
+               return 1;
+       }
+
+       attribute = (uint16)strtol(buf, (char **)NULL, 16);
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("wdel 0x<attrib> <wcard>\n");
+               return 1;
+       }
+
+       pstrcpy(mask,cur_dir);
+       pstrcat(mask,buf);
+
+       if ( !cli_resolve_path_pstring( "", cli, mask, &targetcli, targetname ) ) {
+               d_printf("cmd_wdel %s: %s\n", mask, cli_errstr(cli));
+               return 1;
+       }
        
+       if (!cli_unlink_full(targetcli, targetname, attribute)) {
+               d_printf("%s deleting remote files %s\n",cli_errstr(targetcli),targetname);
+       }
+       return 0;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static int cmd_open(void)
+{
+       pstring mask;
+       pstring buf;
+       struct cli_state *targetcli;
+       pstring targetname;
+       int fnum;
+
        pstrcpy(mask,cur_dir);
        
        if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
@@ -1674,12 +1800,323 @@ static int cmd_open(void)
        }
        pstrcat(mask,buf);
 
-       if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, mask, &targetcli, targetname ) ) {
                d_printf("open %s: %s\n", mask, cli_errstr(cli));
                return 1;
        }
        
-       cli_nt_create(targetcli, targetname, FILE_READ_DATA);
+       fnum = cli_nt_create(targetcli, targetname, FILE_READ_DATA|FILE_WRITE_DATA);
+       if (fnum == -1) {
+               fnum = cli_nt_create(targetcli, targetname, FILE_READ_DATA);
+               if (fnum != -1) {
+                       d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
+               } else {
+                       d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
+               }
+       } else {
+               d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
+       }
+
+       return 0;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static int cmd_posix_open(void)
+{
+       pstring mask;
+       pstring buf;
+       struct cli_state *targetcli;
+       pstring targetname;
+       mode_t mode;
+       int fnum;
+
+       pstrcpy(mask,cur_dir);
+       
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_open <filename> 0<mode>\n");
+               return 1;
+       }
+       pstrcat(mask,buf);
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_open <filename> 0<mode>\n");
+               return 1;
+       }
+       mode = (mode_t)strtol(buf, (char **)NULL, 8);
+
+       if (!cli_resolve_path_pstring( "", cli, mask, &targetcli, targetname )) {
+               d_printf("posix_open %s: %s\n", mask, cli_errstr(cli));
+               return 1;
+       }
+       
+       fnum = cli_posix_open(targetcli, targetname, O_CREAT|O_RDWR, mode);
+       if (fnum == -1) {
+               fnum = cli_posix_open(targetcli, targetname, O_CREAT|O_RDONLY, mode);
+               if (fnum != -1) {
+                       d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
+               } else {
+                       d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
+               }
+       } else {
+               d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
+       }
+
+       return 0;
+}
+
+static int cmd_posix_mkdir(void)
+{
+       pstring mask;
+       pstring buf;
+       struct cli_state *targetcli;
+       pstring targetname;
+       mode_t mode;
+       int fnum;
+
+       pstrcpy(mask,cur_dir);
+       
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_mkdir <filename> 0<mode>\n");
+               return 1;
+       }
+       pstrcat(mask,buf);
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_mkdir <filename> 0<mode>\n");
+               return 1;
+       }
+       mode = (mode_t)strtol(buf, (char **)NULL, 8);
+
+       if (!cli_resolve_path_pstring( "", cli, mask, &targetcli, targetname )) {
+               d_printf("posix_mkdir %s: %s\n", mask, cli_errstr(cli));
+               return 1;
+       }
+
+       fnum = cli_posix_mkdir(targetcli, targetname, mode);
+       if (fnum == -1) {
+               d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
+       } else {
+               d_printf("posix_mkdir created directory %s\n", targetname);
+       }
+
+       return 0;
+}
+
+static int cmd_posix_unlink(void)
+{
+       pstring mask;
+       pstring buf;
+       struct cli_state *targetcli;
+       pstring targetname;
+
+       pstrcpy(mask,cur_dir);
+       
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_unlink <filename>\n");
+               return 1;
+       }
+       pstrcat(mask,buf);
+
+       if (!cli_resolve_path_pstring( "", cli, mask, &targetcli, targetname )) {
+               d_printf("posix_unlink %s: %s\n", mask, cli_errstr(cli));
+               return 1;
+       }
+       
+       if (!cli_posix_unlink(targetcli, targetname)) {
+               d_printf("Failed to unlink file %s. %s\n", targetname, cli_errstr(cli));
+       } else {
+               d_printf("posix_unlink deleted file %s\n", targetname);
+       }
+
+       return 0;
+}
+
+static int cmd_posix_rmdir(void)
+{
+       pstring mask;
+       pstring buf;
+       struct cli_state *targetcli;
+       pstring targetname;
+
+       pstrcpy(mask,cur_dir);
+       
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_rmdir <filename>\n");
+               return 1;
+       }
+       pstrcat(mask,buf);
+
+       if (!cli_resolve_path_pstring( "", cli, mask, &targetcli, targetname)) {
+               d_printf("posix_rmdir %s: %s\n", mask, cli_errstr(cli));
+               return 1;
+       }
+       
+       if (!cli_posix_rmdir(targetcli, targetname)) {
+               d_printf("Failed to unlink directory %s. %s\n", targetname, cli_errstr(cli));
+       } else {
+               d_printf("posix_rmdir deleted directory %s\n", targetname);
+       }
+
+       return 0;
+}
+
+static int cmd_close(void)
+{
+       fstring buf;
+       int fnum;
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("close <fnum>\n");
+               return 1;
+       }
+
+       fnum = atoi(buf);
+       /* We really should use the targetcli here.... */
+       if (!cli_close(cli, fnum)) {
+               d_printf("close %d: %s\n", fnum, cli_errstr(cli));
+               return 1;
+       }
+       return 0;
+}
+
+static int cmd_posix(void)
+{
+       uint16 major, minor;
+       uint32 caplow, caphigh;
+       pstring caps;
+
+       if (!SERVER_HAS_UNIX_CIFS(cli)) {
+               d_printf("Server doesn't support UNIX CIFS extensions.\n");
+               return 1;
+       }
+
+       if (!cli_unix_extensions_version(cli, &major, &minor, &caplow, &caphigh)) {
+               d_printf("Can't get UNIX CIFS extensions version from server.\n");
+               return 1;
+       }
+
+       d_printf("Server supports CIFS extensions %u.%u\n", (unsigned int)major, (unsigned int)minor);
+
+       *caps = '\0';
+        if (caplow & CIFS_UNIX_FCNTL_LOCKS_CAP) {
+               pstrcat(caps, "locks ");
+       }
+        if (caplow & CIFS_UNIX_POSIX_ACLS_CAP) {
+               pstrcat(caps, "acls ");
+       }
+        if (caplow & CIFS_UNIX_XATTTR_CAP) {
+               pstrcat(caps, "eas ");
+       }
+        if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+               pstrcat(caps, "pathnames ");
+       }
+        if (caplow & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) {
+               pstrcat(caps, "posix_path_operations ");
+       }
+        if (caplow & CIFS_UNIX_LARGE_READ_CAP) {
+               pstrcat(caps, "large_read ");
+       }
+        if (caplow & CIFS_UNIX_LARGE_WRITE_CAP) {
+               pstrcat(caps, "large_write ");
+       }
+
+       if (strlen(caps) > 0 && caps[strlen(caps)-1] == ' ') {
+               caps[strlen(caps)-1] = '\0';
+       }
+
+       if (!cli_set_unix_extensions_capabilities(cli, major, minor, caplow, caphigh)) {
+               d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n", cli_errstr(cli));
+               return 1;
+       }
+
+       d_printf("Selecting server supported CIFS capabilities %s\n", caps);
+
+       if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+               CLI_DIRSEP_CHAR = '/';
+               *CLI_DIRSEP_STR = '/';
+               pstrcpy(cur_dir, CLI_DIRSEP_STR);
+       }
+
+       return 0;
+}
+
+static int cmd_lock(void)
+{
+       fstring buf;
+       SMB_BIG_UINT start, len;
+       enum brl_type lock_type;
+       int fnum;
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
+               return 1;
+       }
+       fnum = atoi(buf);
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
+               return 1;
+       }
+
+       if (*buf == 'r' || *buf == 'R') {
+               lock_type = READ_LOCK;
+       } else if (*buf == 'w' || *buf == 'W') {
+               lock_type = WRITE_LOCK;
+       } else {
+               d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
+               return 1;
+       }
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
+               return 1;
+       }
+
+       start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
+               return 1;
+       }
+
+       len = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+
+       if (!cli_posix_lock(cli, fnum, start, len, True, lock_type)) {
+               d_printf("lock failed %d: %s\n", fnum, cli_errstr(cli));
+       }
+
+       return 0;
+}
+
+static int cmd_unlock(void)
+{
+       fstring buf;
+       SMB_BIG_UINT start, len;
+       int fnum;
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("unlock <fnum> <hex-start> <hex-len>\n");
+               return 1;
+       }
+       fnum = atoi(buf);
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("unlock <fnum> <hex-start> <hex-len>\n");
+               return 1;
+       }
+
+       start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("unlock <fnum> <hex-start> <hex-len>\n");
+               return 1;
+       }
+
+       len = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+
+       if (!cli_posix_unlock(cli, fnum, start, len)) {
+               d_printf("unlock failed %d: %s\n", fnum, cli_errstr(cli));
+       }
 
        return 0;
 }
@@ -1704,7 +2141,7 @@ static int cmd_rmdir(void)
        }
        pstrcat(mask,buf);
 
-       if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, mask, &targetcli, targetname ) ) {
                d_printf("rmdir %s: %s\n", mask, cli_errstr(cli));
                return 1;
        }
@@ -1740,7 +2177,7 @@ static int cmd_link(void)
        pstrcat(oldname,buf);
        pstrcat(newname,buf2);
 
-       if ( !cli_resolve_path( "", cli, oldname, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, oldname, &targetcli, targetname ) ) {
                d_printf("link %s: %s\n", oldname, cli_errstr(cli));
                return 1;
        }
@@ -1766,6 +2203,8 @@ static int cmd_symlink(void)
 {
        pstring oldname,newname;
        pstring buf,buf2;
+       struct cli_state *targetcli;
+       pstring targetname;
   
        if (!SERVER_HAS_UNIX_CIFS(cli)) {
                d_printf("Server doesn't support UNIX CIFS calls.\n");
@@ -1783,9 +2222,14 @@ static int cmd_symlink(void)
        pstrcpy(oldname,buf);
        pstrcat(newname,buf2);
 
-       if (!cli_unix_symlink(cli, oldname, newname)) {
+       if ( !cli_resolve_path_pstring( "", cli, oldname, &targetcli, targetname ) ) {
+               d_printf("link %s: %s\n", oldname, cli_errstr(cli));
+               return 1;
+       }
+
+       if (!cli_unix_symlink(targetcli, targetname, newname)) {
                d_printf("%s symlinking files (%s -> %s)\n",
-                       cli_errstr(cli), newname, oldname);
+                       cli_errstr(targetcli), newname, targetname);
                return 1;
        } 
 
@@ -1815,7 +2259,7 @@ static int cmd_chmod(void)
        mode = (mode_t)strtol(buf, NULL, 8);
        pstrcat(src,buf2);
 
-       if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, src, &targetcli, targetname ) ) {
                d_printf("chmod %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
@@ -1963,7 +2407,7 @@ static int cmd_getfacl(void)
 
        pstrcat(src,name);
        
-       if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, src, &targetcli, targetname ) ) {
                d_printf("stat %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
@@ -1983,7 +2427,6 @@ static int cmd_getfacl(void)
                return 1;
        }
 
-
        if (!cli_unix_stat(targetcli, targetname, &sbuf)) {
                d_printf("%s getfacl doing a stat on file %s\n",
                        cli_errstr(targetcli), src);
@@ -2111,6 +2554,7 @@ static int cmd_stat(void)
        fstring mode_str;
        SMB_STRUCT_STAT sbuf;
        struct cli_state *targetcli;
+       struct tm *lt;
        pstring targetname;
  
        if (!SERVER_HAS_UNIX_CIFS(cli)) {
@@ -2128,7 +2572,7 @@ static int cmd_stat(void)
        pstrcat(src,name);
 
        
-       if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, src, &targetcli, targetname ) ) {
                d_printf("stat %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
@@ -2165,13 +2609,28 @@ static int cmd_stat(void)
                (unsigned int)sbuf.st_uid, 
                (unsigned int)sbuf.st_gid);
 
-       strftime(mode_str, sizeof(mode_str), "%F %T %z", localtime(&sbuf.st_atime));
+       lt = localtime(&sbuf.st_atime);
+       if (lt) {
+               strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
+       } else {
+               fstrcpy(mode_str, "unknown");
+       }
        d_printf("Access: %s\n", mode_str);
 
-       strftime(mode_str, sizeof(mode_str), "%F %T %z", localtime(&sbuf.st_mtime));
+       lt = localtime(&sbuf.st_mtime);
+       if (lt) {
+               strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
+       } else {
+               fstrcpy(mode_str, "unknown");
+       }
        d_printf("Modify: %s\n", mode_str);
 
-       strftime(mode_str, sizeof(mode_str), "%F %T %z", localtime(&sbuf.st_ctime));
+       lt = localtime(&sbuf.st_ctime);
+       if (lt) {
+               strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
+       } else {
+               fstrcpy(mode_str, "unknown");
+       }
        d_printf("Change: %s\n", mode_str);
        
        return 0;
@@ -2204,12 +2663,11 @@ static int cmd_chown(void)
        gid = (gid_t)atoi(buf2);
        pstrcat(src,buf3);
 
-       if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, src, &targetcli, targetname ) ) {
                d_printf("chown %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
 
-
        if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
                d_printf("Server doesn't support UNIX CIFS calls.\n");
                return 1;
@@ -2232,6 +2690,9 @@ static int cmd_rename(void)
 {
        pstring src,dest;
        pstring buf,buf2;
+       struct cli_state *targetcli;
+       pstring targetsrc;
+       pstring targetdest;
   
        pstrcpy(src,cur_dir);
        pstrcpy(dest,cur_dir);
@@ -2245,8 +2706,21 @@ static int cmd_rename(void)
        pstrcat(src,buf);
        pstrcat(dest,buf2);
 
-       if (!cli_rename(cli, src, dest)) {
-               d_printf("%s renaming files\n",cli_errstr(cli));
+       if ( !cli_resolve_path_pstring( "", cli, src, &targetcli, targetsrc ) ) {
+               d_printf("rename %s: %s\n", src, cli_errstr(cli));
+               return 1;
+       }
+
+       if ( !cli_resolve_path_pstring( "", cli, dest, &targetcli, targetdest ) ) {
+               d_printf("rename %s: %s\n", dest, cli_errstr(cli));
+               return 1;
+       }
+
+       if (!cli_rename(targetcli, targetsrc, targetdest)) {
+               d_printf("%s renaming files %s -> %s \n",
+                       cli_errstr(targetcli),
+                       targetsrc,
+                       targetdest);
                return 1;
        }
        
@@ -2295,7 +2769,7 @@ static int cmd_hardlink(void)
        pstrcat(src,buf);
        pstrcat(dest,buf2);
 
-       if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, src, &targetcli, targetname ) ) {
                d_printf("hardlink %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
@@ -2332,14 +2806,14 @@ static int cmd_prompt(void)
 static int cmd_newer(void)
 {
        pstring buf;
-       BOOL ok;
+       bool ok;
        SMB_STRUCT_STAT sbuf;
 
        ok = next_token_nr(NULL,buf,NULL,sizeof(buf));
        if (ok && (sys_stat(buf,&sbuf) == 0)) {
                newer_than = sbuf.st_mtime;
                DEBUG(1,("Getting files newer than %s",
-                        asctime(localtime(&newer_than))));
+                        time_to_asc(newer_than)));
        } else {
                newer_than = 0;
        }
@@ -2386,7 +2860,7 @@ static int cmd_lowercase(void)
 
 static int cmd_setcase(void)
 {
-       BOOL orig_case_sensitive = cli_set_case_sensitive(cli, False);
+       bool orig_case_sensitive = cli_set_case_sensitive(cli, False);
 
        cli_set_case_sensitive(cli, !orig_case_sensitive);
        DEBUG(2,("filename case sensitivity is now %s\n",!orig_case_sensitive ?
@@ -2395,6 +2869,25 @@ static int cmd_setcase(void)
        return 0;
 }
 
+/****************************************************************************
+ Toggle the showacls flag.
+****************************************************************************/
+
+static int cmd_showacls(void)
+{
+       showacls = !showacls;
+       DEBUG(2,("showacls is now %s\n",showacls?"on":"off"));
+
+       if (!ctx && showacls)
+               ctx = talloc_init("smbclient:showacls");
+               if (!ctx) {
+                       DEBUG( 0, ("cmd_showacls() out of memory.  talloc_init() failed.\n"));
+       }
+
+       return 0;
+}
+
+
 /****************************************************************************
  Toggle the recurse flag.
 ****************************************************************************/
@@ -2447,7 +2940,7 @@ static int cmd_reget(void)
        char *p;
 
        pstrcpy(remote_name, cur_dir);
-       pstrcat(remote_name, "\\");
+       pstrcat(remote_name, CLI_DIRSEP_STR);
        
        p = remote_name + strlen(remote_name);
        
@@ -2456,7 +2949,7 @@ static int cmd_reget(void)
                return 1;
        }
        pstrcpy(local_name, p);
-       dos_clean_name(remote_name);
+       pstring_clean_name(remote_name);
        
        next_token_nr(NULL, local_name, NULL, sizeof(local_name));
        
@@ -2476,7 +2969,7 @@ static int cmd_reput(void)
        SMB_STRUCT_STAT st;
        
        pstrcpy(remote_name, cur_dir);
-       pstrcat(remote_name, "\\");
+       pstrcat(remote_name, CLI_DIRSEP_STR);
   
        if (!next_token_nr(NULL, p, NULL, sizeof(buf))) {
                d_printf("reput <filename>\n");
@@ -2494,7 +2987,7 @@ static int cmd_reput(void)
        else
                pstrcat(remote_name, local_name);
        
-       dos_clean_name(remote_name);
+       pstring_clean_name(remote_name);
 
        return do_put(remote_name, local_name, True);
 }
@@ -2532,7 +3025,7 @@ static void browse_fn(const char *name, uint32 m,
        }
 }
 
-static BOOL browse_host_rpc(BOOL sort)
+static bool browse_host_rpc(bool sort)
 {
        NTSTATUS status;
        struct rpc_pipe_client *pipe_hnd;
@@ -2587,7 +3080,7 @@ static BOOL browse_host_rpc(BOOL sort)
  Try and browse available connections on a host.
 ****************************************************************************/
 
-static BOOL browse_host(BOOL sort)
+static bool browse_host(bool sort)
 {
        int ret;
        if (!grepable) {
@@ -2624,7 +3117,7 @@ static void server_fn(const char *name, uint32 m,
  Try and browse available connections on a host.
 ****************************************************************************/
 
-static BOOL list_servers(const char *wk_grp)
+static bool list_servers(const char *wk_grp)
 {
        fstring state;
 
@@ -2692,10 +3185,10 @@ static int cmd_logon(void)
        else
                pstrcpy(l_password, buf2);
 
-       if (!cli_session_setup(cli, l_username, 
-                              l_password, strlen(l_password),
-                              l_password, strlen(l_password),
-                              lp_workgroup())) {
+       if (!NT_STATUS_IS_OK(cli_session_setup(cli, l_username, 
+                                              l_password, strlen(l_password),
+                                              l_password, strlen(l_password),
+                                              lp_workgroup()))) {
                d_printf("session setup failed: %s\n", cli_errstr(cli));
                return -1;
        }
@@ -2725,7 +3218,7 @@ static int cmd_show_connect( void )
        struct cli_state *targetcli;
        pstring targetpath;
        
-       if ( !cli_resolve_path( "", cli, cur_dir, &targetcli, targetpath ) ) {
+       if ( !cli_resolve_path_pstring( "", cli, cur_dir, &targetcli, targetpath ) ) {
                d_printf("showconnect %s: %s\n", cur_dir, cli_errstr(cli));
                return 1;
        }
@@ -2734,6 +3227,35 @@ static int cmd_show_connect( void )
        return 0;
 }
 
+/****************************************************************************
+ iosize command
+***************************************************************************/
+
+int cmd_iosize(void)
+{
+       fstring buf;
+       int iosize;
+
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               DEBUG(0, ("iosize <n> or iosize 0x<n>. "
+                       "Minimum is 16384 (0x4000), "
+                       "max is 16776960 (0xFFFF00)\n"));
+               return 1;
+       }
+
+       iosize = strtol(buf,NULL,0);
+       if (iosize < 0 || iosize > 0xFFFF00) {
+               DEBUG(0, ("iosize out of range (min = 16384 (0x4000), "
+                       "max = 16776960 (0x0xFFFF00)"));
+               return 1;
+       }
+
+       io_bufsize = iosize;
+       d_printf("iosize is now %d\n", io_bufsize);
+       return 0;
+}
+
+
 /* Some constants for completing filename arguments */
 
 #define COMPL_NONE        0          /* No completions */
@@ -2761,19 +3283,24 @@ static struct
   {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
   {"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}},
   {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}},
+  {"close",cmd_close,"<fid> close a file given a fid",{COMPL_REMOTE,COMPL_REMOTE}},
   {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
   {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
   {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
+  {"echo",cmd_echo,"ping the server",{COMPL_NONE,COMPL_NONE}},
   {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
   {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
   {"getfacl",cmd_getfacl,"<file name> get the POSIX ACL on a file (UNIX extensions only)",{COMPL_REMOTE,COMPL_LOCAL}},
   {"hardlink",cmd_hardlink,"<src> <dest> create a Windows hard link",{COMPL_REMOTE,COMPL_REMOTE}},
   {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
   {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
+  {"iosize",cmd_iosize,"iosize <number> (default 64512)",{COMPL_NONE,COMPL_NONE}},
   {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
   {"link",cmd_link,"<oldname> <newname> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
+  {"lock",cmd_lock,"lock <fnum> [r|w] <hex-start> <hex-len> : set a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
   {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},  
   {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
+  {"l",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
   {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
   {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
   {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
@@ -2782,6 +3309,11 @@ static struct
   {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
   {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
   {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
+  {"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
+  {"posix_open",cmd_posix_open,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
+  {"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
+  {"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
+  {"posix_unlink",cmd_posix_unlink,"<name> removes a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
   {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},  
   {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
@@ -2796,18 +3328,22 @@ static struct
   {"reput",cmd_reput,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}},
   {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
   {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
+  {"showacls",cmd_showacls,"toggle if ACLs are shown or not",{COMPL_NONE,COMPL_NONE}},  
   {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
   {"stat",cmd_stat,"filename Do a UNIX extensions stat call on a file",{COMPL_REMOTE,COMPL_REMOTE}},
   {"symlink",cmd_symlink,"<oldname> <newname> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}},
   {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
   {"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
   {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
+  {"unlock",cmd_unlock,"unlock <fnum> <hex-start> <hex-len> : remove a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
   {"volume",cmd_volume,"print the volume name",{COMPL_NONE,COMPL_NONE}},
   {"vuid",cmd_vuid,"change current vuid",{COMPL_NONE,COMPL_NONE}},
+  {"wdel",cmd_wdel,"<attrib> <mask> wildcard delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
   {"logon",cmd_logon,"establish new logon",{COMPL_NONE,COMPL_NONE}},
   {"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}},
   {"showconnect",cmd_show_connect,"display the current active connection",{COMPL_NONE,COMPL_NONE}},
-  
+  {"..",cmd_cd_oneup,"change the remote directory (up one level)",{COMPL_REMOTE,COMPL_NONE}},
+
   /* Yes, this must be here, see crh's comment above. */
   {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
   {NULL,NULL,NULL,{COMPL_NONE,COMPL_NONE}}
@@ -2881,7 +3417,7 @@ static int process_command_string(char *cmd)
        /* establish the connection if not already */
        
        if (!cli) {
-               cli = cli_cm_open(desthost, service, True);
+               cli = cli_cm_open(talloc_tos(), desthost, service, True);
                if (!cli)
                        return 0;
        }
@@ -2982,10 +3518,17 @@ static char **remote_completion(const char *text, int len)
        if (!info.matches) {
                return NULL;
        }
+
+       /*
+        * We're leaving matches[0] free to fill it later with the text to
+        * display: Either the one single match or the longest common subset
+        * of the matches.
+        */
        info.matches[0] = NULL;
+       info.count = 1;
 
        for (i = len-1; i >= 0; i--) {
-               if ((text[i] == '/') || (text[i] == '\\')) {
+               if ((text[i] == '/') || (text[i] == CLI_DIRSEP_CHAR)) {
                        break;
                }
        }
@@ -3004,15 +3547,36 @@ static char **remote_completion(const char *text, int len)
        if (cli_list(cli, dirmask, aDIR | aSYSTEM | aHIDDEN, completion_remote_filter, &info) < 0)
                goto cleanup;
 
-       if (info.count == 2)
-               info.matches[0] = SMB_STRDUP(info.matches[1]);
-       else {
-               info.matches[0] = SMB_MALLOC(info.samelen+1);
-               if (!info.matches[0])
-                       goto cleanup;
-               strncpy(info.matches[0], info.matches[1], info.samelen);
-               info.matches[0][info.samelen] = 0;
+       if (info.count == 1) {
+
+               /*
+                * No matches at all, NULL indicates there is nothing
+                */
+
+               SAFE_FREE(info.matches[0]);
+               SAFE_FREE(info.matches);
+               return NULL;
+       }
+
+       if (info.count == 2) {
+
+               /*
+                * Exactly one match in matches[1], indicate this is the one
+                * in matches[0].
+                */
+
+               info.matches[0] = info.matches[1];
+               info.matches[1] = NULL;
+               info.count -= 1;
+               return info.matches;
        }
+
+       /*
+        * We got more than one possible match, set the result to the maximum
+        * common subset
+        */
+
+       info.matches[0] = SMB_STRNDUP(info.matches[1], info.samelen);
        info.matches[info.count] = NULL;
        return info.matches;
 
@@ -3039,10 +3603,13 @@ static char **completion_fn(const char *text, int start, int end)
                sp = strchr(buf, ' ');
                if (sp == NULL)
                        return NULL;
-               
-               for (i = 0; commands[i].name; i++)
-                       if ((strncmp(commands[i].name, text, sp - buf) == 0) && (commands[i].name[sp - buf] == 0))
+
+               for (i = 0; commands[i].name; i++) {
+                       if ((strncmp(commands[i].name, buf, sp - buf) == 0) &&
+                           (commands[i].name[sp - buf] == 0)) {
                                break;
+                       }
+               }
                if (commands[i].name == NULL)
                        return NULL;
 
@@ -3091,7 +3658,7 @@ static char **completion_fn(const char *text, int start, int end)
                        matches[0] = SMB_STRDUP(matches[1]);
                        break;
                default:
-                       matches[0] = SMB_MALLOC(samelen+1);
+                       matches[0] = (char *)SMB_MALLOC(samelen+1);
                        if (!matches[0])
                                goto cleanup;
                        strncpy(matches[0], matches[1], samelen);
@@ -3144,7 +3711,7 @@ static void readline_callback(void)
           session keepalives and then drop them here.
        */
        if (FD_ISSET(cli->fd,&fds)) {
-               if (!receive_smb(cli->fd,cli->inbuf,0)) {
+               if (!receive_smb(cli->fd,cli->inbuf,0,&cli->smb_rw_error)) {
                        DEBUG(0, ("Read from server failed, maybe it closed the "
                                "connection\n"));
                        return;
@@ -3156,7 +3723,7 @@ static void readline_callback(void)
        {
                unsigned char garbage[16];
                memset(garbage, 0xf0, sizeof(garbage));
-               cli_echo(cli, garbage, sizeof(garbage));
+               cli_echo(cli, 1, garbage, sizeof(garbage));
        }
 }
 
@@ -3170,29 +3737,37 @@ static int process_stdin(void)
        int rc = 0;
 
        while (1) {
+               TALLOC_CTX *frame = talloc_stackframe();
                pstring tok;
                pstring the_prompt;
                char *cline;
                pstring line;
                int i;
-               
+
                /* display a prompt */
                slprintf(the_prompt, sizeof(the_prompt)-1, "smb: %s> ", cur_dir);
                cline = smb_readline(the_prompt, readline_callback, completion_fn);
-                       
-               if (!cline) break;
-               
+
+               if (!cline) {
+                       TALLOC_FREE(frame);
+                       break;
+               }
+
                pstrcpy(line, cline);
 
                /* special case - first char is ! */
                if (*line == '!') {
                        system(line + 1);
+                       TALLOC_FREE(frame);
                        continue;
                }
-      
+
                /* and get the first part of the command */
                ptr = line;
-               if (!next_token_nr(&ptr,tok,NULL,sizeof(tok))) continue;
+               if (!next_token_nr(&ptr,tok,NULL,sizeof(tok))) {
+                       TALLOC_FREE(frame);
+                       continue;
+               }
 
                if ((i = process_tok(tok)) >= 0) {
                        rc = commands[i].fn();
@@ -3201,6 +3776,7 @@ static int process_stdin(void)
                } else {
                        d_printf("%s: command not found\n",tok);
                }
+               TALLOC_FREE(frame);
        }
        return rc;
 }
@@ -3213,7 +3789,7 @@ static int process(char *base_directory)
 {
        int rc = 0;
 
-       cli = cli_cm_open(desthost, service, True);
+       cli = cli_cm_open(talloc_tos(), desthost, service, True);
        if (!cli) {
                return 1;
        }
@@ -3242,7 +3818,7 @@ static int process(char *base_directory)
 
 static int do_host_query(char *query_host)
 {
-       cli = cli_cm_open(query_host, "IPC$", True);
+       cli = cli_cm_open(talloc_tos(), query_host, "IPC$", True);
        if (!cli)
                return 1;
 
@@ -3255,7 +3831,7 @@ static int do_host_query(char *query_host)
 
                cli_cm_shutdown();
                cli_cm_set_port( 139 );
-               cli = cli_cm_open(query_host, "IPC$", True);
+               cli = cli_cm_open(talloc_tos(), query_host, "IPC$", True);
        }
 
        if (cli == NULL) {
@@ -3280,7 +3856,7 @@ static int do_tar_op(char *base_directory)
 
        /* do we already have a connection? */
        if (!cli) {
-               cli = cli_cm_open(desthost, service, True);
+               cli = cli_cm_open(talloc_tos(), desthost, service, True);
                if (!cli)
                        return 1;
        }
@@ -3308,11 +3884,12 @@ static int do_tar_op(char *base_directory)
 
 static int do_message_op(void)
 {
-       struct in_addr ip;
+       struct sockaddr_storage ss;
        struct nmb_name called, calling;
        fstring server_name;
        char name_type_hex[10];
        int msg_port;
+       NTSTATUS status;
 
        make_nmb_name(&calling, calling_name, 0x0);
        make_nmb_name(&called , desthost, name_type);
@@ -3321,20 +3898,25 @@ static int do_message_op(void)
        snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
        fstrcat(server_name, name_type_hex);
 
-        zero_ip(&ip);
-       if (have_ip) 
-               ip = dest_ip;
+        zero_addr(&ss);
+       if (have_ip)
+               ss = dest_ss;
 
        /* we can only do messages over port 139 (to windows clients at least) */
 
        msg_port = port ? port : 139;
 
-       if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, msg_port) != msg_port) ||
-           !cli_connect(cli, server_name, &ip)) {
+       if (!(cli=cli_initialise()) || (cli_set_port(cli, msg_port) != msg_port)) {
                d_printf("Connection to %s failed\n", desthost);
                return 1;
        }
 
+       status = cli_connect(cli, server_name, &ss);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("Connection to %s failed. Error %s\n", desthost, nt_errstr(status));
+               return 1;
+       }
+
        if (!cli_session_request(cli, &calling, &called)) {
                d_printf("session request failed\n");
                cli_cm_shutdown();
@@ -3355,15 +3937,18 @@ static int do_message_op(void)
  int main(int argc,char *argv[])
 {
        pstring base_directory;
+       int len = 0;
        int opt;
        pstring query_host;
-       BOOL message = False;
+       bool message = False;
        pstring term_code;
        static const char *new_name_resolve_order = NULL;
        poptContext pc;
        char *p;
        int rc = 0;
        fstring new_workgroup;
+       bool tar_opt = False;
+       bool service_opt = False;
        struct poptOption long_options[] = {
                POPT_AUTOHELP
 
@@ -3385,7 +3970,8 @@ static int do_message_op(void)
                POPT_COMMON_CREDENTIALS
                POPT_TABLEEND
        };
-       
+       TALLOC_CTX *frame = talloc_stackframe();
+
        load_case_tables();
 
 #ifdef KANJI
@@ -3406,16 +3992,39 @@ static int do_message_op(void)
         /* set default debug level to 0 regardless of what smb.conf sets */
        setup_logging( "smbclient", True );
        DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
-       dbf = x_stderr;
-       x_setbuf( x_stderr, NULL );
+       if ((dbf = x_fdup(x_stderr))) {
+               x_setbuf( dbf, NULL );
+       }
 
-       pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 
-                               POPT_CONTEXT_KEEP_FIRST);
+       /* skip argv(0) */
+       pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
        poptSetOtherOptionHelp(pc, "service <password>");
 
        in_client = True;   /* Make sure that we tell lp_load we are */
 
        while ((opt = poptGetNextOpt(pc)) != -1) {
+
+               /* if the tar option has been called previouslt, now we need to eat out the leftovers */
+               /* I see no other way to keep things sane --SSS */
+               if (tar_opt == True) {
+                       while (poptPeekArg(pc)) {
+                               poptGetArg(pc);
+                       }
+                       tar_opt = False;
+               }
+
+               /* if the service has not yet been specified lets see if it is available in the popt stack */
+               if (!service_opt && poptPeekArg(pc)) {
+                       pstrcpy(service, poptGetArg(pc));
+                       service_opt = True;
+               }
+
+               /* if the service has already been retrieved then check if we have also a password */
+               if (service_opt && (!cmdline_auth_info.got_pass) && poptPeekArg(pc)) {
+                       pstrcpy(cmdline_auth_info.password, poptGetArg(pc));
+                       cmdline_auth_info.got_pass = True;
+               }
+       
                switch (opt) {
                case 'M':
                        /* Messages are sent to NetBIOS name type 0x3
@@ -3431,15 +4040,18 @@ static int do_message_op(void)
                        break;
                case 'I':
                        {
-                               dest_ip = *interpret_addr2(poptGetOptArg(pc));
-                               if (is_zero_ip(dest_ip))
+                               if (!interpret_string_addr(&dest_ss, poptGetOptArg(pc), 0)) {
                                        exit(1);
+                               }
                                have_ip = True;
 
-                               cli_cm_set_dest_ip( dest_ip );
+                               cli_cm_set_dest_ss(&dest_ss);
                        }
                        break;
                case 'E':
+                       if (dbf) {
+                               x_fclose(dbf);
+                       }
                        dbf = x_stderr;
                        display_set_stderr();
                        break;
@@ -3457,23 +4069,19 @@ static int do_message_op(void)
                        /* We must use old option processing for this. Find the
                         * position of the -T option in the raw argv[]. */
                        {
-                               int i, optnum;
+                               int i;
                                for (i = 1; i < argc; i++) {
                                        if (strncmp("-T", argv[i],2)==0)
                                                break;
                                }
                                i++;
-                               if (!(optnum = tar_parseargs(argc, argv, poptGetOptArg(pc), i))) {
+                               if (!tar_parseargs(argc, argv, poptGetOptArg(pc), i)) {
                                        poptPrintUsage(pc, stderr, 0);
                                        exit(1);
                                }
-                               /* Now we must eat (optnum - i) options - they have
-                                * been processed by tar_parseargs().
-                                */
-                               optnum -= i;
-                               for (i = 0; i < optnum; i++)
-                                       poptGetOptArg(pc);
                        }
+                       /* this must be the last option, mark we have parsed it so that we know we have */
+                       tar_opt = True;
                        break;
                case 'D':
                        pstrcpy(base_directory,poptGetOptArg(pc));
@@ -3484,8 +4092,26 @@ static int do_message_op(void)
                }
        }
 
-       poptGetArg(pc);
+       /* We may still have some leftovers after the last popt option has been called */
+       if (tar_opt == True) {
+               while (poptPeekArg(pc)) {
+                       poptGetArg(pc);
+               }
+               tar_opt = False;
+       }
+
+       /* if the service has not yet been specified lets see if it is available in the popt stack */
+       if (!service_opt && poptPeekArg(pc)) {
+               pstrcpy(service, poptGetArg(pc));
+               service_opt = True;
+       }
 
+       /* if the service has already been retrieved then check if we have also a password */
+       if (service_opt && (!cmdline_auth_info.got_pass) && poptPeekArg(pc)) {
+               pstrcpy(cmdline_auth_info.password, poptGetArg(pc));
+               cmdline_auth_info.got_pass = True;
+       }
+       
        /* check for the -P option */
 
        if ( port != 0 )
@@ -3515,31 +4141,30 @@ static int do_message_op(void)
        }
        
        load_interfaces();
-       
-       if ( strlen(new_workgroup) != 0 )
-               set_global_myworkgroup( new_workgroup );
-
-       if ( strlen(calling_name) != 0 )
-               set_global_myname( calling_name );
-       else
-               pstrcpy( calling_name, global_myname() );
 
-       if(poptPeekArg(pc)) {
-               pstrcpy(service,poptGetArg(pc));  
+       if (service_opt) {
                /* Convert any '/' characters in the service name to '\' characters */
                string_replace(service, '/','\\');
-
                if (count_chars(service,'\\') < 3) {
                        d_printf("\n%s: Not enough '\\' characters in service\n",service);
                        poptPrintUsage(pc, stderr, 0);
                        exit(1);
                }
+               /* Remove trailing slashes */
+               len = strlen(service);
+               while(len > 0 && service[len - 1] == '\\') {
+                       --len;
+                       service[len] = '\0';
+               }
        }
+       
+       if ( strlen(new_workgroup) != 0 )
+               set_global_myworkgroup( new_workgroup );
 
-       if (poptPeekArg(pc) && !cmdline_auth_info.got_pass) { 
-               cmdline_auth_info.got_pass = True;
-               pstrcpy(cmdline_auth_info.password,poptGetArg(pc));  
-       }
+       if ( strlen(calling_name) != 0 )
+               set_global_myname( calling_name );
+       else
+               pstrcpy( calling_name, global_myname() );
 
        init_names();
 
@@ -3591,10 +4216,12 @@ static int do_message_op(void)
        if (message) {
                return do_message_op();
        }
-       
+
        if (process(base_directory)) {
                return 1;
        }
 
+       talloc_destroy( ctx);
+       talloc_destroy(frame);
        return rc;
 }