r25026: Move param/param.h out of includes.h
[kai/samba-autobuild/.git] / source4 / client / client.c
index 82377e82a94a6ed23bd9f8cf44dedf7fa0127f5b..eaa8fe48a0dd5703604320452d4de31b7759d84e 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
    
    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,
    (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
    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 "includes.h"
-#include "dynconfig.h"
-#include "client.h"
+#include "version.h"
+#include "libcli/libcli.h"
 #include "lib/cmdline/popt_common.h"
 #include "lib/cmdline/popt_common.h"
-#include "librpc/gen_ndr/ndr_srvsvc.h"
+#include "librpc/gen_ndr/ndr_srvsvc_c.h"
+#include "librpc/gen_ndr/ndr_lsa.h"
+#include "librpc/gen_ndr/ndr_security.h"
 #include "libcli/raw/libcliraw.h"
 #include "libcli/raw/libcliraw.h"
-#include "system/time.h"
+#include "libcli/util/clilsa.h"
 #include "system/dir.h"
 #include "system/filesys.h"
 #include "system/dir.h"
 #include "system/filesys.h"
-#include "dlinklist.h"
-
-#ifndef REGISTER
-#define REGISTER 0
-#endif
-
-struct smbcli_state *cli;
-extern BOOL in_client;
-static int port = 0;
-pstring cur_dir = "\\";
-static pstring cd_path = "";
-static pstring service;
-static pstring desthost;
-static pstring username;
-static pstring domain;
-static pstring password;
-static char *cmdstr = NULL;
+#include "lib/util/dlinklist.h"
+#include "system/readline.h"
+#include "auth/credentials/credentials.h"
+#include "auth/gensec/gensec.h"
+#include "system/time.h" /* needed by some systems for asctime() */
+#include "libcli/resolve/resolve.h"
+#include "libcli/security/security.h"
+#include "lib/smbreadline/smbreadline.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
+#include "param/param.h"
 
 static int io_bufsize = 64512;
 
 
 static int io_bufsize = 64512;
 
-static int name_type = 0x20;
-
-static int process_tok(fstring tok);
-static int cmd_help(const char **cmd_ptr);
-
-/* 30 second timeout on most commands */
-#define CLIENT_TIMEOUT (30*1000)
-#define SHORT_TIMEOUT (5*1000)
-
-/* value for unused fid field in trans2 secondary request */
-#define FID_UNUSED (0xFFFF)
-
-time_t newer_than = 0;
-static int archive_level = 0;
-
-static BOOL translation = False;
-
-/* clitar bits insert */
-extern int blocksize;
-extern BOOL tar_inc;
-extern BOOL tar_reset;
-/* clitar bits end */
-
-static BOOL prompt = True;
-
-static int printmode = 1;
-
-static BOOL recurse = False;
-BOOL lowercase = False;
-
-static const char *dest_ip;
-
-#define SEPARATORS " \t\n\r"
-
-static BOOL abort_mget = True;
-
-static pstring fileselection = "";
+struct smbclient_context {
+       char *remote_cur_dir;
+       struct smbcli_state *cli;
+       char *fileselection;
+       time_t newer_than;
+       BOOL prompt;
+       BOOL recurse;
+       int archive_level;
+       BOOL lowercase;
+       int printmode;
+       BOOL translation;
+};
 
 /* timing globals */
 
 /* timing globals */
-uint64_t get_total_size = 0;
-uint_t get_total_time_ms = 0;
+static uint64_t get_total_size = 0;
+static uint_t get_total_time_ms = 0;
 static uint64_t put_total_size = 0;
 static uint_t put_total_time_ms = 0;
 
 static uint64_t put_total_size = 0;
 static uint_t put_total_time_ms = 0;
 
+/* Unfortunately, there is no way to pass the a context to the completion function as an argument */
+static struct smbclient_context *rl_ctx; 
+
 /* totals globals */
 static double dir_total;
 
 /* totals globals */
 static double dir_total;
 
-#define USENMB
-
-/* some forward declarations */
-static struct smbcli_state *do_connect(const char *server, const char *share);
-
-
 /*******************************************************************
  Reduce a file name, removing .. elements.
 ********************************************************************/
 void dos_clean_name(char *s)
 {
 /*******************************************************************
  Reduce a file name, removing .. elements.
 ********************************************************************/
 void dos_clean_name(char *s)
 {
-       char *p=NULL;
+       char *p=NULL,*r;
 
        DEBUG(3,("dos_clean_name [%s]\n",s));
 
 
        DEBUG(3,("dos_clean_name [%s]\n",s));
 
@@ -117,17 +82,10 @@ void dos_clean_name(char *s)
        all_string_sub(s, "\\\\", "\\", 0);
 
        while ((p = strstr(s,"\\..\\")) != NULL) {
        all_string_sub(s, "\\\\", "\\", 0);
 
        while ((p = strstr(s,"\\..\\")) != NULL) {
-               pstring s1;
-
-               *p = 0;
-               pstrcpy(s1,p+3);
-
-               if ((p=strrchr_m(s,'\\')) != NULL)
-                       *p = 0;
-               else
-                       *s = 0;
-               pstrcat(s,s1);
-       }  
+               *p = '\0';
+               if ((r = strrchr(s,'\\')) != NULL)
+                       memmove(r,p+3,strlen(p+3)+1);
+       }
 
        trim_string(s,NULL,"\\..");
 
 
        trim_string(s,NULL,"\\..");
 
@@ -138,8 +96,9 @@ void dos_clean_name(char *s)
 write to a local file with CR/LF->LF translation if appropriate. return the 
 number taken from the buffer. This may not equal the number written.
 ****************************************************************************/
 write to a local file with CR/LF->LF translation if appropriate. return the 
 number taken from the buffer. This may not equal the number written.
 ****************************************************************************/
-static int writefile(int f, char *b, int n)
+static int writefile(int f, const void *_b, int n, BOOL translation)
 {
 {
+       const uint8_t *b = _b;
        int i;
 
        if (!translation) {
        int i;
 
        if (!translation) {
@@ -165,8 +124,9 @@ static int writefile(int f, char *b, int n)
   read from a file with LF->CR/LF translation if appropriate. return the 
   number read. read approx n bytes.
 ****************************************************************************/
   read from a file with LF->CR/LF translation if appropriate. return the 
   number read. read approx n bytes.
 ****************************************************************************/
-static int readfile(char *b, int n, XFILE *f)
+static int readfile(void *_b, int n, XFILE *f, BOOL translation)
 {
 {
+       uint8_t *b = _b;
        int i;
        int c;
 
        int i;
        int c;
 
@@ -174,7 +134,7 @@ static int readfile(char *b, int n, XFILE *f)
                return x_fread(b,1,n,f);
   
        i = 0;
                return x_fread(b,1,n,f);
   
        i = 0;
-       while (i < (n - 1) && (i < CLI_BUFFER_SIZE)) {
+       while (i < (n - 1)) {
                if ((c = x_getc(f)) == EOF) {
                        break;
                }
                if ((c = x_getc(f)) == EOF) {
                        break;
                }
@@ -193,12 +153,13 @@ static int readfile(char *b, int n, XFILE *f)
 /****************************************************************************
 send a message
 ****************************************************************************/
 /****************************************************************************
 send a message
 ****************************************************************************/
-static void send_message(void)
+static void send_message(struct smbcli_state *cli, const char *desthost)
 {
 {
+       char msg[1600];
        int total_len = 0;
        int grp_id;
 
        int total_len = 0;
        int grp_id;
 
-       if (!smbcli_message_start(cli->tree, desthost, username, &grp_id)) {
+       if (!smbcli_message_start(cli->tree, desthost, cli_credentials_get_username(cmdline_credentials), &grp_id)) {
                d_printf("message start: %s\n", smbcli_errstr(cli->tree));
                return;
        }
                d_printf("message start: %s\n", smbcli_errstr(cli->tree));
                return;
        }
@@ -208,12 +169,9 @@ static void send_message(void)
 
        while (!feof(stdin) && total_len < 1600) {
                int maxlen = MIN(1600 - total_len,127);
 
        while (!feof(stdin) && total_len < 1600) {
                int maxlen = MIN(1600 - total_len,127);
-               pstring msg;
                int l=0;
                int c;
 
                int l=0;
                int c;
 
-               ZERO_ARRAY(msg);
-
                for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++) {
                        if (c == '\n')
                                msg[l++] = '\r';
                for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++) {
                        if (c == '\n')
                                msg[l++] = '\r';
@@ -244,12 +202,12 @@ static void send_message(void)
 /****************************************************************************
 check the space on a device
 ****************************************************************************/
 /****************************************************************************
 check the space on a device
 ****************************************************************************/
-static int do_dskattr(void)
+static int do_dskattr(struct smbclient_context *ctx)
 {
        int total, bsize, avail;
 
 {
        int total, bsize, avail;
 
-       if (NT_STATUS_IS_ERR(smbcli_dskattr(cli->tree, &bsize, &total, &avail))) {
-               d_printf("Error in dskattr: %s\n",smbcli_errstr(cli->tree)); 
+       if (NT_STATUS_IS_ERR(smbcli_dskattr(ctx->cli->tree, &bsize, &total, &avail))) {
+               d_printf("Error in dskattr: %s\n",smbcli_errstr(ctx->cli->tree)); 
                return 1;
        }
 
                return 1;
        }
 
@@ -262,10 +220,9 @@ static int do_dskattr(void)
 /****************************************************************************
 show cd/pwd
 ****************************************************************************/
 /****************************************************************************
 show cd/pwd
 ****************************************************************************/
-static int cmd_pwd(const char **cmd_ptr)
+static int cmd_pwd(struct smbclient_context *ctx, const char **args)
 {
 {
-       d_printf("Current directory is %s",service);
-       d_printf("%s\n",cur_dir);
+       d_printf("Current directory is %s\n", ctx->remote_cur_dir);
        return 0;
 }
 
        return 0;
 }
 
@@ -280,77 +237,72 @@ static void dos_format(char *s)
 /****************************************************************************
 change directory - inner section
 ****************************************************************************/
 /****************************************************************************
 change directory - inner section
 ****************************************************************************/
-static int do_cd(char *newdir)
+static int do_cd(struct smbclient_context *ctx, const char *newdir)
 {
 {
-       char *p = newdir;
-       pstring saved_dir;
-       pstring dname;
+       char *dname;
       
       
-       dos_format(newdir);
-
        /* Save the current directory in case the
           new directory is invalid */
        /* Save the current directory in case the
           new directory is invalid */
-       pstrcpy(saved_dir, cur_dir);
-       if (*p == '\\')
-               pstrcpy(cur_dir,p);
+       if (newdir[0] == '\\')
+               dname = talloc_strdup(NULL, newdir);
        else
        else
-               pstrcat(cur_dir,p);
-       if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
-               pstrcat(cur_dir, "\\");
-       }
-       dos_clean_name(cur_dir);
-       pstrcpy(dname,cur_dir);
-       pstrcat(cur_dir,"\\");
-       dos_clean_name(cur_dir);
+               dname = talloc_asprintf(NULL, "%s\\%s", ctx->remote_cur_dir, newdir);
+
+       dos_format(dname);
+
+       if (*(dname+strlen(dname)-1) != '\\') {
+               dname = talloc_append_string(NULL, dname, "\\");
+       }
+       dos_clean_name(dname);
        
        
-       if (!strequal(cur_dir,"\\")) {
-               if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, dname))) {
-                       d_printf("cd %s: %s\n", dname, smbcli_errstr(cli->tree));
-                       pstrcpy(cur_dir,saved_dir);
-               }
+       if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, dname))) {
+               d_printf("cd %s: %s\n", dname, smbcli_errstr(ctx->cli->tree));
+               talloc_free(dname);
+       } else {
+               ctx->remote_cur_dir = dname;
        }
        
        }
        
-       pstrcpy(cd_path,cur_dir);
-
        return 0;
 }
 
 /****************************************************************************
 change directory
 ****************************************************************************/
        return 0;
 }
 
 /****************************************************************************
 change directory
 ****************************************************************************/
-static int cmd_cd(const char **cmd_ptr)
+static int cmd_cd(struct smbclient_context *ctx, const char **args)
 {
 {
-       fstring buf;
        int rc = 0;
 
        int rc = 0;
 
-       if (next_token(cmd_ptr,buf,NULL,sizeof(buf)))
-               rc = do_cd(buf);
+       if (args[1]) 
+               rc = do_cd(ctx, args[1]);
        else
        else
-               d_printf("Current directory is %s\n",cur_dir);
+               d_printf("Current directory is %s\n",ctx->remote_cur_dir);
 
        return rc;
 }
 
 
 
        return rc;
 }
 
 
-BOOL mask_match(struct smbcli_state *c, const char *string, char *pattern, 
+BOOL mask_match(struct smbcli_state *c, const char *string, const char *pattern, 
                BOOL is_case_sensitive)
 {
                BOOL is_case_sensitive)
 {
-       fstring p2, s2;
+       char *p2, *s2;
+       BOOL ret;
 
 
-       if (strcmp(string,"..") == 0)
+       if (ISDOTDOT(string))
                string = ".";
                string = ".";
-       if (strcmp(pattern,".") == 0)
+       if (ISDOT(pattern))
                return False;
        
        if (is_case_sensitive)
                return ms_fnmatch(pattern, string, 
                                  c->transport->negotiate.protocol) == 0;
 
                return False;
        
        if (is_case_sensitive)
                return ms_fnmatch(pattern, string, 
                                  c->transport->negotiate.protocol) == 0;
 
-       fstrcpy(p2, pattern);
-       fstrcpy(s2, string);
-       strlower(p2); 
-       strlower(s2);
-       return ms_fnmatch(p2, s2, c->transport->negotiate.protocol) == 0;
+       p2 = strlower_talloc(NULL, pattern);
+       s2 = strlower_talloc(NULL, string);
+       ret = ms_fnmatch(p2, s2, c->transport->negotiate.protocol) == 0;
+       talloc_free(p2);
+       talloc_free(s2);
+
+       return ret;
 }
 
 
 }
 
 
@@ -358,22 +310,22 @@ BOOL mask_match(struct smbcli_state *c, const char *string, char *pattern,
 /*******************************************************************
   decide if a file should be operated on
   ********************************************************************/
 /*******************************************************************
   decide if a file should be operated on
   ********************************************************************/
-static BOOL do_this_one(struct file_info *finfo)
+static BOOL do_this_one(struct smbclient_context *ctx, struct clilist_file_info *finfo)
 {
 {
-       if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) return(True);
+       if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) return(True);
 
 
-       if (*fileselection && 
-           !mask_match(cli, finfo->name,fileselection,False)) {
+       if (ctx->fileselection && 
+           !mask_match(ctx->cli, finfo->name,ctx->fileselection,False)) {
                DEBUG(3,("mask_match %s failed\n", finfo->name));
                return False;
        }
 
                DEBUG(3,("mask_match %s failed\n", finfo->name));
                return False;
        }
 
-       if (newer_than && finfo->mtime < newer_than) {
+       if (ctx->newer_than && finfo->mtime < ctx->newer_than) {
                DEBUG(3,("newer_than %s failed\n", finfo->name));
                return(False);
        }
 
                DEBUG(3,("newer_than %s failed\n", finfo->name));
                return(False);
        }
 
-       if ((archive_level==1 || archive_level==2) && !(finfo->mode & FILE_ATTRIBUTE_ARCHIVE)) {
+       if ((ctx->archive_level==1 || ctx->archive_level==2) && !(finfo->attrib & FILE_ATTRIBUTE_ARCHIVE)) {
                DEBUG(3,("archive %s failed\n", finfo->name));
                return(False);
        }
                DEBUG(3,("archive %s failed\n", finfo->name));
                return(False);
        }
@@ -384,11 +336,11 @@ static BOOL do_this_one(struct file_info *finfo)
 /****************************************************************************
   display info about a file
   ****************************************************************************/
 /****************************************************************************
   display info about a file
   ****************************************************************************/
-static void display_finfo(struct file_info *finfo)
+static void display_finfo(struct smbclient_context *ctx, struct clilist_file_info *finfo)
 {
 {
-       if (do_this_one(finfo)) {
+       if (do_this_one(ctx, finfo)) {
                time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
                time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
-               char *astr = attrib_string(NULL, finfo->mode);
+               char *astr = attrib_string(NULL, finfo->attrib);
                d_printf("  %-30s%7.7s %8.0f  %s",
                         finfo->name,
                         astr,
                d_printf("  %-30s%7.7s %8.0f  %s",
                         finfo->name,
                         astr,
@@ -403,9 +355,9 @@ static void display_finfo(struct file_info *finfo)
 /****************************************************************************
    accumulate size of a file
   ****************************************************************************/
 /****************************************************************************
    accumulate size of a file
   ****************************************************************************/
-static void do_du(struct file_info *finfo)
+static void do_du(struct smbclient_context *ctx, struct clilist_file_info *finfo)
 {
 {
-       if (do_this_one(finfo)) {
+       if (do_this_one(ctx, finfo)) {
                dir_total += finfo->size;
        }
 }
                dir_total += finfo->size;
        }
 }
@@ -416,7 +368,7 @@ static char *do_list_queue = 0;
 static long do_list_queue_size = 0;
 static long do_list_queue_start = 0;
 static long do_list_queue_end = 0;
 static long do_list_queue_size = 0;
 static long do_list_queue_start = 0;
 static long do_list_queue_end = 0;
-static void (*do_list_fn)(struct file_info *);
+static void (*do_list_fn)(struct smbclient_context *, struct clilist_file_info *);
 
 /****************************************************************************
 functions for do_list_queue
 
 /****************************************************************************
 functions for do_list_queue
@@ -457,11 +409,13 @@ static void init_do_list_queue(void)
 
 static void adjust_do_list_queue(void)
 {
 
 static void adjust_do_list_queue(void)
 {
+       if (do_list_queue == NULL) return;
+
        /*
         * If the starting point of the queue is more than half way through,
         * move everything toward the beginning.
         */
        /*
         * 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_start == do_list_queue_end)
        {
                DEBUG(4,("do_list_queue is empty\n"));
                do_list_queue_start = do_list_queue_end = 0;
        {
                DEBUG(4,("do_list_queue is empty\n"));
                do_list_queue_start = do_list_queue_end = 0;
@@ -488,7 +442,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_size *= 2;
                DEBUG(4,("enlarging do_list_queue to %d\n",
                         (int)do_list_queue_size));
-               dlq = Realloc(do_list_queue, do_list_queue_size);
+               dlq = realloc_p(do_list_queue, char, do_list_queue_size);
                if (! dlq) {
                        d_printf("failure enlarging do_list_queue to %d bytes\n",
                                 (int)do_list_queue_size);
                if (! dlq) {
                        d_printf("failure enlarging do_list_queue to %d bytes\n",
                                 (int)do_list_queue_size);
@@ -535,31 +489,32 @@ static int do_list_queue_empty(void)
 /****************************************************************************
 a helper for do_list
   ****************************************************************************/
 /****************************************************************************
 a helper for do_list
   ****************************************************************************/
-static void do_list_helper(struct file_info *f, const char *mask, void *state)
+static void do_list_helper(struct clilist_file_info *f, const char *mask, void *state)
 {
 {
-       if (f->mode & FILE_ATTRIBUTE_DIRECTORY) {
-               if (do_list_dirs && do_this_one(f)) {
-                       do_list_fn(f);
+       struct smbclient_context *ctx = state;
+
+       if (f->attrib & FILE_ATTRIBUTE_DIRECTORY) {
+               if (do_list_dirs && do_this_one(ctx, f)) {
+                       do_list_fn(ctx, f);
                }
                if (do_list_recurse && 
                }
                if (do_list_recurse && 
-                   !strequal(f->name,".") && 
-                   !strequal(f->name,"..")) {
-                       pstring mask2;
+                   !ISDOT(f->name) &&
+                   !ISDOTDOT(f->name)) {
+                       char *mask2;
                        char *p;
 
                        char *p;
 
-                       pstrcpy(mask2, mask);
+                       mask2 = talloc_strdup(NULL, mask);
                        p = strrchr_m(mask2,'\\');
                        if (!p) return;
                        p[1] = 0;
                        p = strrchr_m(mask2,'\\');
                        if (!p) return;
                        p[1] = 0;
-                       pstrcat(mask2, f->name);
-                       pstrcat(mask2,"\\*");
+                       mask2 = talloc_asprintf_append(mask2, "%s\\*", f->name);
                        add_to_do_list_queue(mask2);
                }
                return;
        }
 
                        add_to_do_list_queue(mask2);
                }
                return;
        }
 
-       if (do_this_one(f)) {
-               do_list_fn(f);
+       if (do_this_one(ctx, f)) {
+               do_list_fn(ctx, f);
        }
 }
 
        }
 }
 
@@ -567,7 +522,8 @@ static void do_list_helper(struct file_info *f, const char *mask, void *state)
 /****************************************************************************
 a wrapper around smbcli_list that adds recursion
   ****************************************************************************/
 /****************************************************************************
 a wrapper around smbcli_list that adds recursion
   ****************************************************************************/
-void do_list(const char *mask,uint16_t attribute,void (*fn)(struct file_info *),BOOL rec, BOOL dirs)
+static void do_list(struct smbclient_context *ctx, const char *mask,uint16_t attribute,
+            void (*fn)(struct smbclient_context *, struct clilist_file_info *),BOOL rec, BOOL dirs)
 {
        static int in_do_list = 0;
 
 {
        static int in_do_list = 0;
 
@@ -597,9 +553,9 @@ void do_list(const char *mask,uint16_t attribute,void (*fn)(struct file_info *),
                         * during the call.
                         * Fix from E. Jay Berkenbilt (ejb@ql.org)
                         */
                         * during the call.
                         * Fix from E. Jay Berkenbilt (ejb@ql.org)
                         */
-                       pstring head;
-                       pstrcpy(head, do_list_queue_head());
-                       smbcli_list(cli->tree, head, attribute, do_list_helper, NULL);
+                       char *head;
+                       head = do_list_queue_head();
+                       smbcli_list(ctx->cli->tree, head, attribute, do_list_helper, ctx);
                        remove_do_list_queue_head();
                        if ((! do_list_queue_empty()) && (fn == display_finfo))
                        {
                        remove_do_list_queue_head();
                        if ((! do_list_queue_empty()) && (fn == display_finfo))
                        {
@@ -623,9 +579,9 @@ void do_list(const char *mask,uint16_t attribute,void (*fn)(struct file_info *),
        }
        else
        {
        }
        else
        {
-               if (smbcli_list(cli->tree, mask, attribute, do_list_helper, NULL) == -1)
+               if (smbcli_list(ctx->cli->tree, mask, attribute, do_list_helper, ctx) == -1)
                {
                {
-                       d_printf("%s listing %s\n", smbcli_errstr(cli->tree), mask);
+                       d_printf("%s listing %s\n", smbcli_errstr(ctx->cli->tree), mask);
                }
        }
 
                }
        }
 
@@ -636,38 +592,36 @@ void do_list(const char *mask,uint16_t attribute,void (*fn)(struct file_info *),
 /****************************************************************************
   get a directory listing
   ****************************************************************************/
 /****************************************************************************
   get a directory listing
   ****************************************************************************/
-static int cmd_dir(const char **cmd_ptr)
+static int cmd_dir(struct smbclient_context *ctx, const char **args)
 {
        uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
 {
        uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
-       pstring mask;
-       fstring buf;
-       char *p=buf;
+       char *mask;
        int rc;
        
        dir_total = 0;
        int rc;
        
        dir_total = 0;
-       pstrcpy(mask,cur_dir);
+       
+       mask = talloc_strdup(ctx, ctx->remote_cur_dir);
        if(mask[strlen(mask)-1]!='\\')
        if(mask[strlen(mask)-1]!='\\')
-               pstrcat(mask,"\\");
+               mask = talloc_append_string(ctx, mask,"\\");
        
        
-       if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
-               dos_format(p);
-               if (*p == '\\')
-                       pstrcpy(mask,p);
-               else
-                       pstrcat(mask,p);
+       if (args[1]) {
+               mask = talloc_strdup(ctx, args[1]);
+               if (mask[0] != '\\')
+                       mask = talloc_append_string(ctx, mask, "\\");
+               dos_format(mask);
        }
        else {
        }
        else {
-               if (cli->tree->session->transport->negotiate.protocol <= 
+               if (ctx->cli->tree->session->transport->negotiate.protocol <= 
                    PROTOCOL_LANMAN1) { 
                    PROTOCOL_LANMAN1) { 
-                       pstrcat(mask,"*.*");
+                       mask = talloc_append_string(ctx, mask, "*.*");
                } else {
                } else {
-                       pstrcat(mask,"*");
+                       mask = talloc_append_string(ctx, mask, "*");
                }
        }
 
                }
        }
 
-       do_list(mask, attribute, display_finfo, recurse, True);
+       do_list(ctx, mask, attribute, display_finfo, ctx->recurse, True);
 
 
-       rc = do_dskattr();
+       rc = do_dskattr(ctx);
 
        DEBUG(3, ("Total bytes listed: %.0f\n", dir_total));
 
 
        DEBUG(3, ("Total bytes listed: %.0f\n", dir_total));
 
@@ -678,32 +632,29 @@ static int cmd_dir(const char **cmd_ptr)
 /****************************************************************************
   get a directory listing
   ****************************************************************************/
 /****************************************************************************
   get a directory listing
   ****************************************************************************/
-static int cmd_du(const char **cmd_ptr)
+static int cmd_du(struct smbclient_context *ctx, const char **args)
 {
        uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
 {
        uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
-       pstring mask;
-       fstring buf;
-       char *p=buf;
        int rc;
        int rc;
+       char *mask;
        
        dir_total = 0;
        
        dir_total = 0;
-       pstrcpy(mask,cur_dir);
-       if(mask[strlen(mask)-1]!='\\')
-               pstrcat(mask,"\\");
        
        
-       if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
-               dos_format(p);
-               if (*p == '\\')
-                       pstrcpy(mask,p);
+       if (args[1]) {
+               if (args[1][0] == '\\')
+                       mask = talloc_strdup(ctx, args[1]);
                else
                else
-                       pstrcat(mask,p);
+                       mask = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
+               dos_format(mask);
        } else {
        } else {
-               pstrcat(mask,"\\*");
+               mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir);
        }
 
        }
 
-       do_list(mask, attribute, do_du, recurse, True);
+       do_list(ctx, mask, attribute, do_du, ctx->recurse, True);
 
 
-       rc = do_dskattr();
+       talloc_free(mask);
+
+       rc = do_dskattr(ctx);
 
        d_printf("Total number of bytes: %.0f\n", dir_total);
 
 
        d_printf("Total number of bytes: %.0f\n", dir_total);
 
@@ -714,11 +665,11 @@ static int cmd_du(const char **cmd_ptr)
 /****************************************************************************
   get a file from rname to lname
   ****************************************************************************/
 /****************************************************************************
   get a file from rname to lname
   ****************************************************************************/
-static int do_get(char *rname, const char *lname, BOOL reget)
+static int do_get(struct smbclient_context *ctx, char *rname, const char *lname, BOOL reget)
 {  
        int handle = 0, fnum;
        BOOL newhandle = False;
 {  
        int handle = 0, fnum;
        BOOL newhandle = False;
-       char *data;
+       uint8_t *data;
        struct timeval tp_start;
        int read_size = io_bufsize;
        uint16_t attr;
        struct timeval tp_start;
        int read_size = io_bufsize;
        uint16_t attr;
@@ -729,14 +680,14 @@ static int do_get(char *rname, const char *lname, BOOL reget)
 
        GetTimeOfDay(&tp_start);
 
 
        GetTimeOfDay(&tp_start);
 
-       if (lowercase) {
+       if (ctx->lowercase) {
                strlower(discard_const_p(char, lname));
        }
 
                strlower(discard_const_p(char, lname));
        }
 
-       fnum = smbcli_open(cli->tree, rname, O_RDONLY, DENY_NONE);
+       fnum = smbcli_open(ctx->cli->tree, rname, O_RDONLY, DENY_NONE);
 
        if (fnum == -1) {
 
        if (fnum == -1) {
-               d_printf("%s opening remote file %s\n",smbcli_errstr(cli->tree),rname);
+               d_printf("%s opening remote file %s\n",smbcli_errstr(ctx->cli->tree),rname);
                return 1;
        }
 
                return 1;
        }
 
@@ -763,29 +714,29 @@ static int do_get(char *rname, const char *lname, BOOL reget)
        }
 
 
        }
 
 
-       if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, 
+       if (NT_STATUS_IS_ERR(smbcli_qfileinfo(ctx->cli->tree, fnum, 
                           &attr, &size, NULL, NULL, NULL, NULL, NULL)) &&
                           &attr, &size, NULL, NULL, NULL, NULL, NULL)) &&
-           NT_STATUS_IS_ERR(smbcli_getattrE(cli->tree, fnum, 
+           NT_STATUS_IS_ERR(smbcli_getattrE(ctx->cli->tree, fnum, 
                          &attr, &size, NULL, NULL, NULL))) {
                          &attr, &size, NULL, NULL, NULL))) {
-               d_printf("getattrib: %s\n",smbcli_errstr(cli->tree));
+               d_printf("getattrib: %s\n",smbcli_errstr(ctx->cli->tree));
                return 1;
        }
 
        DEBUG(2,("getting file %s of size %.0f as %s ", 
                 rname, (double)size, lname));
 
                return 1;
        }
 
        DEBUG(2,("getting file %s of size %.0f as %s ", 
                 rname, (double)size, lname));
 
-       if(!(data = (char *)malloc(read_size))) { 
+       if(!(data = (uint8_t *)malloc(read_size))) { 
                d_printf("malloc fail for size %d\n", read_size);
                d_printf("malloc fail for size %d\n", read_size);
-               smbcli_close(cli->tree, fnum);
+               smbcli_close(ctx->cli->tree, fnum);
                return 1;
        }
 
        while (1) {
                return 1;
        }
 
        while (1) {
-               int n = smbcli_read(cli->tree, fnum, data, nread + start, read_size);
+               int n = smbcli_read(ctx->cli->tree, fnum, data, nread + start, read_size);
 
                if (n <= 0) break;
  
 
                if (n <= 0) break;
  
-               if (writefile(handle,data, n) != n) {
+               if (writefile(handle,data, n, ctx->translation) != n) {
                        d_printf("Error writing local file\n");
                        rc = 1;
                        break;
                        d_printf("Error writing local file\n");
                        rc = 1;
                        break;
@@ -803,8 +754,8 @@ static int do_get(char *rname, const char *lname, BOOL reget)
 
        SAFE_FREE(data);
        
 
        SAFE_FREE(data);
        
-       if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
-               d_printf("Error %s closing remote file\n",smbcli_errstr(cli->tree));
+       if (NT_STATUS_IS_ERR(smbcli_close(ctx->cli->tree, fnum))) {
+               d_printf("Error %s closing remote file\n",smbcli_errstr(ctx->cli->tree));
                rc = 1;
        }
 
                rc = 1;
        }
 
@@ -812,8 +763,8 @@ static int do_get(char *rname, const char *lname, BOOL reget)
                close(handle);
        }
 
                close(handle);
        }
 
-       if (archive_level >= 2 && (attr & FILE_ATTRIBUTE_ARCHIVE)) {
-               smbcli_setatr(cli->tree, rname, attr & ~(uint16_t)FILE_ATTRIBUTE_ARCHIVE, 0);
+       if (ctx->archive_level >= 2 && (attr & FILE_ATTRIBUTE_ARCHIVE)) {
+               smbcli_setatr(ctx->cli->tree, rname, attr & ~(uint16_t)FILE_ATTRIBUTE_ARCHIVE, 0);
        }
 
        {
        }
 
        {
@@ -839,27 +790,26 @@ static int do_get(char *rname, const char *lname, BOOL reget)
 /****************************************************************************
   get a file
   ****************************************************************************/
 /****************************************************************************
   get a file
   ****************************************************************************/
-static int cmd_get(const char **cmd_ptr)
+static int cmd_get(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring lname;
-       pstring rname;
-       char *p;
+       const char *lname;
+       char *rname;
 
 
-       pstrcpy(rname,cur_dir);
-       pstrcat(rname,"\\");
-       
-       p = rname + strlen(rname);
-       
-       if (!next_token(cmd_ptr,p,NULL,sizeof(rname)-strlen(rname))) {
+       if (!args[1]) {
                d_printf("get <filename>\n");
                return 1;
        }
                d_printf("get <filename>\n");
                return 1;
        }
-       pstrcpy(lname,p);
-       dos_clean_name(rname);
+
+       rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
+
+       if (args[2]) 
+               lname = args[2];
+       else 
+               lname = args[1];
        
        
-       next_token(cmd_ptr,lname,NULL,sizeof(lname));
+       dos_clean_name(rname);
        
        
-       return do_get(rname, lname, False);
+       return do_get(ctx, rname, lname, False);
 }
 
 /****************************************************************************
 }
 
 /****************************************************************************
@@ -867,7 +817,7 @@ static int cmd_get(const char **cmd_ptr)
 ****************************************************************************/
 static BOOL yesno(char *p)
 {
 ****************************************************************************/
 static BOOL yesno(char *p)
 {
-       pstring ans;
+       char ans[4];
        printf("%s",p);
 
        if (!fgets(ans,sizeof(ans)-1,stdin))
        printf("%s",p);
 
        if (!fgets(ans,sizeof(ans)-1,stdin))
@@ -882,104 +832,96 @@ static BOOL yesno(char *p)
 /****************************************************************************
   do a mget operation on one file
   ****************************************************************************/
 /****************************************************************************
   do a mget operation on one file
   ****************************************************************************/
-static void do_mget(struct file_info *finfo)
+static void do_mget(struct smbclient_context *ctx, struct clilist_file_info *finfo)
 {
 {
-       pstring rname;
-       pstring quest;
-       pstring saved_curdir;
-       pstring mget_mask;
+       char *rname;
+       char *quest;
+       char *mget_mask;
+       char *saved_curdir;
 
 
-       if (strequal(finfo->name,".") || strequal(finfo->name,".."))
+       if (ISDOT(finfo->name) || ISDOTDOT(finfo->name))
                return;
 
                return;
 
-       if (abort_mget) {
-               d_printf("mget aborted\n");
-               return;
-       }
-
-       if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY)
-               slprintf(quest,sizeof(pstring)-1,
-                        "Get directory %s? ",finfo->name);
+       if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)
+               asprintf(&quest, "Get directory %s? ",finfo->name);
        else
        else
-               slprintf(quest,sizeof(pstring)-1,
-                        "Get file %s? ",finfo->name);
+               asprintf(&quest, "Get file %s? ",finfo->name);
 
 
-       if (prompt && !yesno(quest)) return;
+       if (ctx->prompt && !yesno(quest)) return;
 
 
-       if (!(finfo->mode & FILE_ATTRIBUTE_DIRECTORY)) {
-               pstrcpy(rname,cur_dir);
-               pstrcat(rname,finfo->name);
-               do_get(rname, finfo->name, False);
+       SAFE_FREE(quest);
+
+       if (!(finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)) {
+               asprintf(&rname, "%s%s",ctx->remote_cur_dir,finfo->name);
+               do_get(ctx, rname, finfo->name, False);
+               SAFE_FREE(rname);
                return;
        }
 
        /* handle directories */
                return;
        }
 
        /* handle directories */
-       pstrcpy(saved_curdir,cur_dir);
+       saved_curdir = talloc_strdup(NULL, ctx->remote_cur_dir);
 
 
-       pstrcat(cur_dir,finfo->name);
-       pstrcat(cur_dir,"\\");
+       ctx->remote_cur_dir = talloc_asprintf_append(NULL, "%s\\", finfo->name);
 
        string_replace(discard_const_p(char, finfo->name), '\\', '/');
 
        string_replace(discard_const_p(char, finfo->name), '\\', '/');
-       if (lowercase) {
+       if (ctx->lowercase) {
                strlower(discard_const_p(char, finfo->name));
        }
        
                strlower(discard_const_p(char, finfo->name));
        }
        
-       if (!directory_exist(finfo->name,NULL) && 
+       if (!directory_exist(finfo->name) && 
            mkdir(finfo->name,0777) != 0) {
                d_printf("failed to create directory %s\n",finfo->name);
            mkdir(finfo->name,0777) != 0) {
                d_printf("failed to create directory %s\n",finfo->name);
-               pstrcpy(cur_dir,saved_curdir);
                return;
        }
        
        if (chdir(finfo->name) != 0) {
                d_printf("failed to chdir to directory %s\n",finfo->name);
                return;
        }
        
        if (chdir(finfo->name) != 0) {
                d_printf("failed to chdir to directory %s\n",finfo->name);
-               pstrcpy(cur_dir,saved_curdir);
                return;
        }
 
                return;
        }
 
-       pstrcpy(mget_mask,cur_dir);
-       pstrcat(mget_mask,"*");
+       mget_mask = talloc_asprintf(NULL, "%s*", ctx->remote_cur_dir);
        
        
-       do_list(mget_mask, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,do_mget,False, True);
+       do_list(ctx, mget_mask, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,do_mget,False, True);
        chdir("..");
        chdir("..");
-       pstrcpy(cur_dir,saved_curdir);
+       talloc_free(ctx->remote_cur_dir);
+
+       ctx->remote_cur_dir = saved_curdir;
 }
 
 
 /****************************************************************************
 view the file using the pager
 ****************************************************************************/
 }
 
 
 /****************************************************************************
 view the file using the pager
 ****************************************************************************/
-static int cmd_more(const char **cmd_ptr)
+static int cmd_more(struct smbclient_context *ctx, const char **args)
 {
 {
-       fstring rname,lname,pager_cmd;
+       char *rname;
+       char *pager_cmd;
+       char *lname;
        char *pager;
        int fd;
        int rc = 0;
 
        char *pager;
        int fd;
        int rc = 0;
 
-       fstrcpy(rname,cur_dir);
-       fstrcat(rname,"\\");
-       
-       slprintf(lname,sizeof(lname)-1, "%s/smbmore.XXXXXX",tmpdir());
-       fd = smb_mkstemp(lname);
+       lname = talloc_asprintf(ctx, "%s/smbmore.XXXXXX",tmpdir());
+       fd = mkstemp(lname);
        if (fd == -1) {
                d_printf("failed to create temporary file for more\n");
                return 1;
        }
        close(fd);
 
        if (fd == -1) {
                d_printf("failed to create temporary file for more\n");
                return 1;
        }
        close(fd);
 
-       if (!next_token(cmd_ptr,rname+strlen(rname),NULL,sizeof(rname)-strlen(rname))) {
+       if (!args[1]) {
                d_printf("more <filename>\n");
                unlink(lname);
                return 1;
        }
                d_printf("more <filename>\n");
                unlink(lname);
                return 1;
        }
+       rname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
        dos_clean_name(rname);
 
        dos_clean_name(rname);
 
-       rc = do_get(rname, lname, False);
+       rc = do_get(ctx, rname, lname, False);
 
        pager=getenv("PAGER");
 
 
        pager=getenv("PAGER");
 
-       slprintf(pager_cmd,sizeof(pager_cmd)-1,
-                "%s %s",(pager? pager:PAGER), lname);
+       pager_cmd = talloc_asprintf(ctx, "%s %s",(pager? pager:PAGER), lname);
        system(pager_cmd);
        unlink(lname);
        
        system(pager_cmd);
        unlink(lname);
        
@@ -991,38 +933,32 @@ static int cmd_more(const char **cmd_ptr)
 /****************************************************************************
 do a mget command
 ****************************************************************************/
 /****************************************************************************
 do a mget command
 ****************************************************************************/
-static int cmd_mget(const char **cmd_ptr)
+static int cmd_mget(struct smbclient_context *ctx, const char **args)
 {
        uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
 {
        uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
-       pstring mget_mask;
-       fstring buf;
-       char *p=buf;
-
-       *mget_mask = 0;
+       char *mget_mask = NULL;
+       int i;
 
 
-       if (recurse)
+       if (ctx->recurse)
                attribute |= FILE_ATTRIBUTE_DIRECTORY;
        
                attribute |= FILE_ATTRIBUTE_DIRECTORY;
        
-       abort_mget = False;
-
-       while (next_token(cmd_ptr,p,NULL,sizeof(buf))) {
-               pstrcpy(mget_mask,cur_dir);
+       for (i = 1; args[i]; i++) {
+               mget_mask = talloc_strdup(ctx,ctx->remote_cur_dir);
                if(mget_mask[strlen(mget_mask)-1]!='\\')
                if(mget_mask[strlen(mget_mask)-1]!='\\')
-                       pstrcat(mget_mask,"\\");
+                       mget_mask = talloc_append_string(ctx, mget_mask, "\\");
                
                
-               if (*p == '\\')
-                       pstrcpy(mget_mask,p);
-               else
-                       pstrcat(mget_mask,p);
-               do_list(mget_mask, attribute,do_mget,False,True);
+               mget_mask = talloc_strdup(ctx, args[i]);
+               if (mget_mask[0] != '\\')
+                       mget_mask = talloc_append_string(ctx, mget_mask, "\\");
+               do_list(ctx, mget_mask, attribute,do_mget,False,True);
+
+               talloc_free(mget_mask);
        }
 
        }
 
-       if (!*mget_mask) {
-               pstrcpy(mget_mask,cur_dir);
-               if(mget_mask[strlen(mget_mask)-1]!='\\')
-                       pstrcat(mget_mask,"\\");
-               pstrcat(mget_mask,"*");
-               do_list(mget_mask, attribute,do_mget,False,True);
+       if (mget_mask == NULL) {
+               mget_mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir);
+               do_list(ctx, mget_mask, attribute,do_mget,False,True);
+               talloc_free(mget_mask);
        }
        
        return 0;
        }
        
        return 0;
@@ -1032,42 +968,26 @@ static int cmd_mget(const char **cmd_ptr)
 /****************************************************************************
 make a directory of name "name"
 ****************************************************************************/
 /****************************************************************************
 make a directory of name "name"
 ****************************************************************************/
-static NTSTATUS do_mkdir(char *name)
+static NTSTATUS do_mkdir(struct smbclient_context *ctx, char *name)
 {
        NTSTATUS status;
 
 {
        NTSTATUS status;
 
-       if (NT_STATUS_IS_ERR(status = smbcli_mkdir(cli->tree, name))) {
+       if (NT_STATUS_IS_ERR(status = smbcli_mkdir(ctx->cli->tree, name))) {
                d_printf("%s making remote directory %s\n",
                d_printf("%s making remote directory %s\n",
-                        smbcli_errstr(cli->tree),name);
+                        smbcli_errstr(ctx->cli->tree),name);
                return status;
        }
 
        return status;
 }
 
                return status;
        }
 
        return status;
 }
 
-/****************************************************************************
-show 8.3 name of a file
-****************************************************************************/
-static BOOL do_altname(char *name)
-{
-       const char *altname;
-       if (!NT_STATUS_IS_OK(smbcli_qpathinfo_alt_name(cli->tree, name, &altname))) {
-               d_printf("%s getting alt name for %s\n",
-                        smbcli_errstr(cli->tree),name);
-               return(False);
-       }
-       d_printf("%s\n", altname);
-
-       return(True);
-}
-
 
 /****************************************************************************
  Exit client.
 ****************************************************************************/
 
 /****************************************************************************
  Exit client.
 ****************************************************************************/
-static int cmd_quit(const char **cmd_ptr)
+static int cmd_quit(struct smbclient_context *ctx, const char **args)
 {
 {
-       smbcli_shutdown(cli);
+       talloc_free(ctx);
        exit(0);
        /* NOTREACHED */
        return 0;
        exit(0);
        /* NOTREACHED */
        return 0;
@@ -1077,63 +997,59 @@ static int cmd_quit(const char **cmd_ptr)
 /****************************************************************************
   make a directory
   ****************************************************************************/
 /****************************************************************************
   make a directory
   ****************************************************************************/
-static int cmd_mkdir(const char **cmd_ptr)
+static int cmd_mkdir(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring mask;
-       fstring buf;
-       char *p=buf;
+       char *mask, *p;
   
   
-       pstrcpy(mask,cur_dir);
-
-       if (!next_token(cmd_ptr,p,NULL,sizeof(buf))) {
-               if (!recurse)
+       if (!args[1]) {
+               if (!ctx->recurse)
                        d_printf("mkdir <dirname>\n");
                return 1;
        }
                        d_printf("mkdir <dirname>\n");
                return 1;
        }
-       pstrcat(mask,p);
 
 
-       if (recurse) {
-               pstring ddir;
-               pstring ddir2;
-               *ddir2 = 0;
-               
-               pstrcpy(ddir,mask);
-               trim_string(ddir,".",NULL);
-               p = strtok(ddir,"/\\");
-               while (p) {
-                       pstrcat(ddir2,p);
-                       if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, ddir2))) { 
-                               do_mkdir(ddir2);
+       mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir,args[1]);
+
+       if (ctx->recurse) {
+               dos_clean_name(mask);
+
+               trim_string(mask,".",NULL);
+               for (p = strtok(mask,"/\\"); p; p = strtok(p, "/\\")) {
+                       char *parent = talloc_strndup(ctx, mask, PTR_DIFF(p, mask));
+                       
+                       if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, parent))) { 
+                               do_mkdir(ctx, parent);
                        }
                        }
-                       pstrcat(ddir2,"\\");
-                       p = strtok(NULL,"/\\");
+
+                       talloc_free(parent);
                }        
        } else {
                }        
        } else {
-               do_mkdir(mask);
+               do_mkdir(ctx, mask);
        }
        
        return 0;
 }
 
        }
        
        return 0;
 }
 
-
 /****************************************************************************
 /****************************************************************************
-  show alt name
-  ****************************************************************************/
-static int cmd_altname(const char **cmd_ptr)
+show 8.3 name of a file
+****************************************************************************/
+static int cmd_altname(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring name;
-       fstring buf;
-       char *p=buf;
+       const char *altname;
+       char *name;
   
   
-       pstrcpy(name,cur_dir);
-
-       if (!next_token(cmd_ptr,p,NULL,sizeof(buf))) {
+       if (!args[1]) {
                d_printf("altname <file>\n");
                return 1;
        }
                d_printf("altname <file>\n");
                return 1;
        }
-       pstrcat(name,p);
 
 
-       do_altname(name);
+       name = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
+
+       if (!NT_STATUS_IS_OK(smbcli_qpathinfo_alt_name(ctx->cli->tree, name, &altname))) {
+               d_printf("%s getting alt name for %s\n",
+                        smbcli_errstr(ctx->cli->tree),name);
+               return(False);
+       }
+       d_printf("%s\n", altname);
 
        return 0;
 }
 
        return 0;
 }
@@ -1142,13 +1058,13 @@ static int cmd_altname(const char **cmd_ptr)
 /****************************************************************************
   put a single file
   ****************************************************************************/
 /****************************************************************************
   put a single file
   ****************************************************************************/
-static int do_put(char *rname, char *lname, BOOL reput)
+static int do_put(struct smbclient_context *ctx, char *rname, char *lname, BOOL reput)
 {
        int fnum;
        XFILE *f;
        size_t start = 0;
        off_t nread = 0;
 {
        int fnum;
        XFILE *f;
        size_t start = 0;
        off_t nread = 0;
-       char *buf = NULL;
+       uint8_t *buf = NULL;
        int maxwrite = io_bufsize;
        int rc = 0;
        
        int maxwrite = io_bufsize;
        int rc = 0;
        
@@ -1156,21 +1072,21 @@ static int do_put(char *rname, char *lname, BOOL reput)
        GetTimeOfDay(&tp_start);
 
        if (reput) {
        GetTimeOfDay(&tp_start);
 
        if (reput) {
-               fnum = smbcli_open(cli->tree, rname, O_RDWR|O_CREAT, DENY_NONE);
+               fnum = smbcli_open(ctx->cli->tree, rname, O_RDWR|O_CREAT, DENY_NONE);
                if (fnum >= 0) {
                if (fnum >= 0) {
-                       if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL)) &&
-                           NT_STATUS_IS_ERR(smbcli_getattrE(cli->tree, fnum, NULL, &start, NULL, NULL, NULL))) {
-                               d_printf("getattrib: %s\n",smbcli_errstr(cli->tree));
+                       if (NT_STATUS_IS_ERR(smbcli_qfileinfo(ctx->cli->tree, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL)) &&
+                           NT_STATUS_IS_ERR(smbcli_getattrE(ctx->cli->tree, fnum, NULL, &start, NULL, NULL, NULL))) {
+                               d_printf("getattrib: %s\n",smbcli_errstr(ctx->cli->tree));
                                return 1;
                        }
                }
        } else {
                                return 1;
                        }
                }
        } else {
-               fnum = smbcli_open(cli->tree, rname, O_RDWR|O_CREAT|O_TRUNC, 
+               fnum = smbcli_open(ctx->cli->tree, rname, O_RDWR|O_CREAT|O_TRUNC, 
                                DENY_NONE);
        }
   
        if (fnum == -1) {
                                DENY_NONE);
        }
   
        if (fnum == -1) {
-               d_printf("%s opening remote file %s\n",smbcli_errstr(cli->tree),rname);
+               d_printf("%s opening remote file %s\n",smbcli_errstr(ctx->cli->tree),rname);
                return 1;
        }
 
                return 1;
        }
 
@@ -1201,7 +1117,7 @@ static int do_put(char *rname, char *lname, BOOL reput)
        DEBUG(1,("putting file %s as %s ",lname,
                 rname));
   
        DEBUG(1,("putting file %s as %s ",lname,
                 rname));
   
-       buf = (char *)malloc(maxwrite);
+       buf = (uint8_t *)malloc(maxwrite);
        if (!buf) {
                d_printf("ERROR: Not enough memory!\n");
                return 1;
        if (!buf) {
                d_printf("ERROR: Not enough memory!\n");
                return 1;
@@ -1210,7 +1126,7 @@ static int do_put(char *rname, char *lname, BOOL reput)
                int n = maxwrite;
                int ret;
 
                int n = maxwrite;
                int ret;
 
-               if ((n = readfile(buf,n,f)) < 1) {
+               if ((n = readfile(buf,n,f,ctx->translation)) < 1) {
                        if((n == 0) && x_feof(f))
                                break; /* Empty local file. */
 
                        if((n == 0) && x_feof(f))
                                break; /* Empty local file. */
 
@@ -1219,10 +1135,10 @@ static int do_put(char *rname, char *lname, BOOL reput)
                        break;
                }
 
                        break;
                }
 
-               ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
+               ret = smbcli_write(ctx->cli->tree, fnum, 0, buf, nread + start, n);
 
                if (n != ret) {
 
                if (n != ret) {
-                       d_printf("Error writing file: %s\n", smbcli_errstr(cli->tree));
+                       d_printf("Error writing file: %s\n", smbcli_errstr(ctx->cli->tree));
                        rc = 1;
                        break;
                } 
                        rc = 1;
                        break;
                } 
@@ -1230,8 +1146,8 @@ static int do_put(char *rname, char *lname, BOOL reput)
                nread += n;
        }
 
                nread += n;
        }
 
-       if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
-               d_printf("%s closing remote file %s\n",smbcli_errstr(cli->tree),rname);
+       if (NT_STATUS_IS_ERR(smbcli_close(ctx->cli->tree, fnum))) {
+               d_printf("%s closing remote file %s\n",smbcli_errstr(ctx->cli->tree),rname);
                x_fclose(f);
                SAFE_FREE(buf);
                return 1;
                x_fclose(f);
                SAFE_FREE(buf);
                return 1;
@@ -1261,7 +1177,7 @@ static int do_put(char *rname, char *lname, BOOL reput)
        }
 
        if (f == x_stdin) {
        }
 
        if (f == x_stdin) {
-               smbcli_shutdown(cli);
+               talloc_free(ctx);
                exit(0);
        }
        
                exit(0);
        }
        
@@ -1273,41 +1189,33 @@ static int do_put(char *rname, char *lname, BOOL reput)
 /****************************************************************************
   put a file
   ****************************************************************************/
 /****************************************************************************
   put a file
   ****************************************************************************/
-static int cmd_put(const char **cmd_ptr)
+static int cmd_put(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring lname;
-       pstring rname;
-       fstring buf;
-       char *p=buf;
+       char *lname;
+       char *rname;
        
        
-       pstrcpy(rname,cur_dir);
-       pstrcat(rname,"\\");
-  
-       if (!next_token(cmd_ptr,p,NULL,sizeof(buf))) {
-               d_printf("put <filename>\n");
+       if (!args[1]) {
+               d_printf("put <filename> [<remotename>]\n");
                return 1;
        }
                return 1;
        }
-       pstrcpy(lname,p);
+
+       lname = talloc_strdup(ctx, args[1]);
   
   
-       if (next_token(cmd_ptr,p,NULL,sizeof(buf)))
-               pstrcat(rname,p);      
+       if (args[2])
+               rname = talloc_strdup(ctx, args[2]);
        else
        else
-               pstrcat(rname,lname);
+               rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, lname);
        
        dos_clean_name(rname);
 
        
        dos_clean_name(rname);
 
-       {
-               struct stat st;
-               /* allow '-' to represent stdin
-                  jdblair, 24.jun.98 */
-               if (!file_exist(lname,&st) &&
-                   (strcmp(lname,"-"))) {
-                       d_printf("%s does not exist\n",lname);
-                       return 1;
-               }
+       /* allow '-' to represent stdin
+          jdblair, 24.jun.98 */
+       if (!file_exist(lname) && (strcmp(lname,"-"))) {
+               d_printf("%s does not exist\n",lname);
+               return 1;
        }
 
        }
 
-       return do_put(rname, lname, False);
+       return do_put(ctx, rname, lname, False);
 }
 
 /*************************************
 }
 
 /*************************************
@@ -1357,10 +1265,10 @@ static BOOL seek_list(struct file_list *list, char *name)
 /****************************************************************************
   set the file selection mask
   ****************************************************************************/
 /****************************************************************************
   set the file selection mask
   ****************************************************************************/
-static int cmd_select(const char **cmd_ptr)
+static int cmd_select(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstrcpy(fileselection,"");
-       next_token(cmd_ptr,fileselection,NULL,sizeof(fileselection));
+       talloc_free(ctx->fileselection);
+       ctx->fileselection = talloc_strdup(NULL, args[1]);
 
        return 0;
 }
 
        return 0;
 }
@@ -1376,7 +1284,7 @@ static const char *readdirname(DIR *p)
        if (!p)
                return(NULL);
   
        if (!p)
                return(NULL);
   
-       ptr = (struct smb_dirent *)readdir(p);
+       ptr = (struct dirent *)readdir(p);
        if (!ptr)
                return(NULL);
 
        if (!ptr)
                return(NULL);
 
@@ -1393,10 +1301,9 @@ static const char *readdirname(DIR *p)
 #endif
 
        {
 #endif
 
        {
-               static pstring buf;
+               static char *buf;
                int len = NAMLEN(ptr);
                int len = NAMLEN(ptr);
-               memcpy(buf, dname, len);
-               buf[len] = 0;
+               buf = talloc_strndup(NULL, dname, len);
                dname = buf;
        }
 
                dname = buf;
        }
 
@@ -1407,7 +1314,7 @@ static const char *readdirname(DIR *p)
   Recursive file matching function act as find
   match must be always set to True when calling this function
 ****************************************************************************/
   Recursive file matching function act as find
   match must be always set to True when calling this function
 ****************************************************************************/
-static int file_find(struct file_list **list, const char *directory, 
+static int file_find(struct smbclient_context *ctx, struct file_list **list, const char *directory, 
                      const char *expression, BOOL match)
 {
        DIR *dir;
                      const char *expression, BOOL match)
 {
        DIR *dir;
@@ -1422,8 +1329,9 @@ static int file_find(struct file_list **list, const char *directory,
        if (!dir) return -1;
        
         while ((dname = readdirname(dir))) {
        if (!dir) return -1;
        
         while ((dname = readdirname(dir))) {
-               if (!strcmp("..", dname)) continue;
-               if (!strcmp(".", dname)) continue;
+               if (ISDOT(dname) || ISDOTDOT(dname)) {
+                       continue;
+               }
                
                if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
                        continue;
                
                if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
                        continue;
@@ -1431,12 +1339,12 @@ static int file_find(struct file_list **list, const char *directory,
 
                isdir = False;
                if (!match || !gen_fnmatch(expression, dname)) {
 
                isdir = False;
                if (!match || !gen_fnmatch(expression, dname)) {
-                       if (recurse) {
+                       if (ctx->recurse) {
                                ret = stat(path, &statbuf);
                                if (ret == 0) {
                                        if (S_ISDIR(statbuf.st_mode)) {
                                                isdir = True;
                                ret = stat(path, &statbuf);
                                if (ret == 0) {
                                        if (S_ISDIR(statbuf.st_mode)) {
                                                isdir = True;
-                                               ret = file_find(list, path, expression, False);
+                                               ret = file_find(ctx, list, path, expression, False);
                                        }
                                } else {
                                        d_printf("file_find: cannot stat file %s\n", path);
                                        }
                                } else {
                                        d_printf("file_find: cannot stat file %s\n", path);
@@ -1448,7 +1356,7 @@ static int file_find(struct file_list **list, const char *directory,
                                        return -1;
                                }
                        }
                                        return -1;
                                }
                        }
-                       entry = (struct file_list *) malloc(sizeof (struct file_list));
+                       entry = malloc_p(struct file_list);
                        if (!entry) {
                                d_printf("Out of memory in file_find\n");
                                closedir(dir);
                        if (!entry) {
                                d_printf("Out of memory in file_find\n");
                                closedir(dir);
@@ -1469,19 +1377,20 @@ static int file_find(struct file_list **list, const char *directory,
 /****************************************************************************
   mput some files
   ****************************************************************************/
 /****************************************************************************
   mput some files
   ****************************************************************************/
-static int cmd_mput(const char **cmd_ptr)
+static int cmd_mput(struct smbclient_context *ctx, const char **args)
 {
 {
-       fstring buf;
-       char *p=buf;
+       int i;
        
        
-       while (next_token(cmd_ptr,p,NULL,sizeof(buf))) {
+       for (i = 1; args[i]; i++) {
                int ret;
                struct file_list *temp_list;
                char *quest, *lname, *rname;
                int ret;
                struct file_list *temp_list;
                char *quest, *lname, *rname;
+
+               printf("%s\n", args[i]);
        
                file_list = NULL;
 
        
                file_list = NULL;
 
-               ret = file_find(&file_list, ".", p, True);
+               ret = file_find(ctx, &file_list, ".", args[i], True);
                if (ret) {
                        free_file_list(file_list);
                        continue;
                if (ret) {
                        free_file_list(file_list);
                        continue;
@@ -1505,17 +1414,17 @@ static int cmd_mput(const char **cmd_ptr)
                                
                                SAFE_FREE(quest);
                                if (asprintf(&quest, "Put directory %s? ", lname) < 0) break;
                                
                                SAFE_FREE(quest);
                                if (asprintf(&quest, "Put directory %s? ", lname) < 0) break;
-                               if (prompt && !yesno(quest)) { /* No */
+                               if (ctx->prompt && !yesno(quest)) { /* No */
                                        /* Skip the directory */
                                        lname[strlen(lname)-1] = '/';
                                        if (!seek_list(temp_list, lname))
                                                break;              
                                } else { /* Yes */
                                        SAFE_FREE(rname);
                                        /* Skip the directory */
                                        lname[strlen(lname)-1] = '/';
                                        if (!seek_list(temp_list, lname))
                                                break;              
                                } else { /* Yes */
                                        SAFE_FREE(rname);
-                                       if(asprintf(&rname, "%s%s", cur_dir, lname) < 0) break;
+                                       if(asprintf(&rname, "%s%s", ctx->remote_cur_dir, lname) < 0) break;
                                        dos_format(rname);
                                        dos_format(rname);
-                                       if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, rname)) && 
-                                           NT_STATUS_IS_ERR(do_mkdir(rname))) {
+                                       if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, rname)) && 
+                                           NT_STATUS_IS_ERR(do_mkdir(ctx, rname))) {
                                                DEBUG (0, ("Unable to make dir, skipping..."));
                                                /* Skip the directory */
                                                lname[strlen(lname)-1] = '/';
                                                DEBUG (0, ("Unable to make dir, skipping..."));
                                                /* Skip the directory */
                                                lname[strlen(lname)-1] = '/';
@@ -1527,17 +1436,17 @@ static int cmd_mput(const char **cmd_ptr)
                        } else {
                                SAFE_FREE(quest);
                                if (asprintf(&quest,"Put file %s? ", lname) < 0) break;
                        } else {
                                SAFE_FREE(quest);
                                if (asprintf(&quest,"Put file %s? ", lname) < 0) break;
-                               if (prompt && !yesno(quest)) /* No */
+                               if (ctx->prompt && !yesno(quest)) /* No */
                                        continue;
                                
                                /* Yes */
                                SAFE_FREE(rname);
                                        continue;
                                
                                /* Yes */
                                SAFE_FREE(rname);
-                               if (asprintf(&rname, "%s%s", cur_dir, lname) < 0) break;
+                               if (asprintf(&rname, "%s%s", ctx->remote_cur_dir, lname) < 0) break;
                        }
 
                        dos_format(rname);
 
                        }
 
                        dos_format(rname);
 
-                       do_put(rname, lname, False);
+                       do_put(ctx, rname, lname, False);
                }
                free_file_list(file_list);
                SAFE_FREE(quest);
                }
                free_file_list(file_list);
                SAFE_FREE(quest);
@@ -1549,52 +1458,22 @@ static int cmd_mput(const char **cmd_ptr)
 }
 
 
 }
 
 
-/****************************************************************************
-  cancel a print job
-  ****************************************************************************/
-static int do_cancel(int job)
-{
-       d_printf("REWRITE: print job cancel not implemented\n");
-       return 1;
-}
-
-
-/****************************************************************************
-  cancel a print job
-  ****************************************************************************/
-static int cmd_cancel(const char **cmd_ptr)
-{
-       fstring buf;
-       int job; 
-
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
-               d_printf("cancel <jobid> ...\n");
-               return 1;
-       }
-       do {
-               job = atoi(buf);
-               do_cancel(job);
-       } while (next_token(cmd_ptr,buf,NULL,sizeof(buf)));
-       
-       return 0;
-}
-
-
 /****************************************************************************
   print a file
   ****************************************************************************/
 /****************************************************************************
   print a file
   ****************************************************************************/
-static int cmd_print(const char **cmd_ptr)
+static int cmd_print(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring lname;
-       pstring rname;
+       char *lname, *rname;
        char *p;
 
        char *p;
 
-       if (!next_token(cmd_ptr,lname,NULL, sizeof(lname))) {
+       if (!args[1]) {
                d_printf("print <filename>\n");
                return 1;
        }
 
                d_printf("print <filename>\n");
                return 1;
        }
 
-       pstrcpy(rname,lname);
+       lname = talloc_strdup(ctx, args[1]);
+
+       rname = talloc_strdup(ctx, lname);
        p = strrchr_m(rname,'/');
        if (p) {
                slprintf(rname, sizeof(rname)-1, "%s-%d", p+1, (int)getpid());
        p = strrchr_m(rname,'/');
        if (p) {
                slprintf(rname, sizeof(rname)-1, "%s-%d", p+1, (int)getpid());
@@ -1604,16 +1483,13 @@ static int cmd_print(const char **cmd_ptr)
                slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)getpid());
        }
 
                slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)getpid());
        }
 
-       return do_put(rname, lname, False);
+       return do_put(ctx, rname, lname, False);
 }
 
 
 }
 
 
-/****************************************************************************
- show a print queue
-****************************************************************************/
-static int cmd_queue(const char **cmd_ptr)
+static int cmd_rewrite(struct smbclient_context *ctx, const char **args)
 {
 {
-       d_printf("REWRITE: print job queue not implemented\n");
+       d_printf("REWRITE: command not implemented (FIXME!)\n");
        
        return 0;
 }
        
        return 0;
 }
@@ -1621,25 +1497,22 @@ static int cmd_queue(const char **cmd_ptr)
 /****************************************************************************
 delete some files
 ****************************************************************************/
 /****************************************************************************
 delete some files
 ****************************************************************************/
-static int cmd_del(const char **cmd_ptr)
+static int cmd_del(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring mask;
-       fstring buf;
+       char *mask;
        uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
 
        uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
 
-       if (recurse)
+       if (ctx->recurse)
                attribute |= FILE_ATTRIBUTE_DIRECTORY;
        
                attribute |= FILE_ATTRIBUTE_DIRECTORY;
        
-       pstrcpy(mask,cur_dir);
-       
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
+       if (!args[1]) {
                d_printf("del <filename>\n");
                return 1;
        }
                d_printf("del <filename>\n");
                return 1;
        }
-       pstrcat(mask,buf);
+       mask = talloc_asprintf(ctx,"%s%s", ctx->remote_cur_dir, args[1]);
 
 
-       if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, mask))) {
-               d_printf("%s deleting remote file %s\n",smbcli_errstr(cli->tree),mask);
+       if (NT_STATUS_IS_ERR(smbcli_unlink(ctx->cli->tree, mask))) {
+               d_printf("%s deleting remote file %s\n",smbcli_errstr(ctx->cli->tree),mask);
        }
        
        return 0;
        }
        
        return 0;
@@ -1649,24 +1522,22 @@ static int cmd_del(const char **cmd_ptr)
 /****************************************************************************
 delete a whole directory tree
 ****************************************************************************/
 /****************************************************************************
 delete a whole directory tree
 ****************************************************************************/
-static int cmd_deltree(const char **cmd_ptr)
+static int cmd_deltree(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring dname;
-       fstring buf;
+       char *dname;
        int ret;
 
        int ret;
 
-       pstrcpy(dname,cur_dir);
-       
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
+       if (!args[1]) {
                d_printf("deltree <dirname>\n");
                return 1;
        }
                d_printf("deltree <dirname>\n");
                return 1;
        }
-       pstrcat(dname,buf);
 
 
-       ret = smbcli_deltree(cli->tree, dname);
+       dname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
+       
+       ret = smbcli_deltree(ctx->cli->tree, dname);
 
        if (ret == -1) {
 
        if (ret == -1) {
-               printf("Failed to delete tree %s - %s\n", dname, smbcli_errstr(cli->tree));
+               printf("Failed to delete tree %s - %s\n", dname, smbcli_errstr(ctx->cli->tree));
                return -1;
        }
 
                return -1;
        }
 
@@ -1675,43 +1546,207 @@ static int cmd_deltree(const char **cmd_ptr)
        return 0;
 }
 
        return 0;
 }
 
+typedef struct {
+       const char  *level_name;
+       enum smb_fsinfo_level level;
+} fsinfo_level_t;
+
+fsinfo_level_t fsinfo_levels[] = {
+       {"dskattr", RAW_QFS_DSKATTR},
+       {"allocation", RAW_QFS_ALLOCATION},
+       {"volume", RAW_QFS_VOLUME},
+       {"volumeinfo", RAW_QFS_VOLUME_INFO},
+       {"sizeinfo", RAW_QFS_SIZE_INFO},
+       {"deviceinfo", RAW_QFS_DEVICE_INFO},
+       {"attributeinfo", RAW_QFS_ATTRIBUTE_INFO},
+       {"unixinfo", RAW_QFS_UNIX_INFO},
+       {"volume-information", RAW_QFS_VOLUME_INFORMATION},
+       {"size-information", RAW_QFS_SIZE_INFORMATION},
+       {"device-information", RAW_QFS_DEVICE_INFORMATION},
+       {"attribute-information", RAW_QFS_ATTRIBUTE_INFORMATION},
+       {"quota-information", RAW_QFS_QUOTA_INFORMATION},
+       {"fullsize-information", RAW_QFS_FULL_SIZE_INFORMATION},
+       {"objectid", RAW_QFS_OBJECTID_INFORMATION},
+       {NULL, RAW_QFS_GENERIC}
+};
+
+
+static int cmd_fsinfo(struct smbclient_context *ctx, const char **args)
+{
+       union smb_fsinfo fsinfo;
+       NTSTATUS status;
+       fsinfo_level_t *fsinfo_level;
+       
+       if (!args[1]) {
+               d_printf("fsinfo <level>, where level is one of following:\n");
+               fsinfo_level = fsinfo_levels;
+               while(fsinfo_level->level_name) {
+                       d_printf("%s\n", fsinfo_level->level_name);
+                       fsinfo_level++;
+               }
+               return 1;
+       }
+       
+       fsinfo_level = fsinfo_levels;
+       while(fsinfo_level->level_name && !strequal(args[1],fsinfo_level->level_name)) {
+               fsinfo_level++;
+       }
+  
+       if (!fsinfo_level->level_name) {
+               d_printf("wrong level name!\n");
+               return 1;
+       }
+  
+       fsinfo.generic.level = fsinfo_level->level;
+       status = smb_raw_fsinfo(ctx->cli->tree, ctx, &fsinfo);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("fsinfo-level-%s - %s\n", fsinfo_level->level_name, nt_errstr(status));
+               return 1;
+       }
+
+       d_printf("fsinfo-level-%s:\n", fsinfo_level->level_name);
+       switch(fsinfo.generic.level) {
+       case RAW_QFS_DSKATTR:
+               d_printf("\tunits_total:                %hu\n", 
+                        (unsigned short) fsinfo.dskattr.out.units_total);
+               d_printf("\tblocks_per_unit:            %hu\n", 
+                        (unsigned short) fsinfo.dskattr.out.blocks_per_unit);
+               d_printf("\tblocks_size:                %hu\n", 
+                        (unsigned short) fsinfo.dskattr.out.block_size);
+               d_printf("\tunits_free:                 %hu\n", 
+                        (unsigned short) fsinfo.dskattr.out.units_free);
+               break;
+       case RAW_QFS_ALLOCATION:
+               d_printf("\tfs_id:                      %lu\n", 
+                        (unsigned long) fsinfo.allocation.out.fs_id);
+               d_printf("\tsectors_per_unit:           %lu\n", 
+                        (unsigned long) fsinfo.allocation.out.sectors_per_unit);
+               d_printf("\ttotal_alloc_units:          %lu\n", 
+                        (unsigned long) fsinfo.allocation.out.total_alloc_units);
+               d_printf("\tavail_alloc_units:          %lu\n", 
+                        (unsigned long) fsinfo.allocation.out.avail_alloc_units);
+               d_printf("\tbytes_per_sector:           %hu\n", 
+                        (unsigned short) fsinfo.allocation.out.bytes_per_sector);
+               break;
+       case RAW_QFS_VOLUME:
+               d_printf("\tserial_number:              %lu\n", 
+                        (unsigned long) fsinfo.volume.out.serial_number);
+               d_printf("\tvolume_name:                %s\n", fsinfo.volume.out.volume_name.s);
+               break;
+       case RAW_QFS_VOLUME_INFO:
+       case RAW_QFS_VOLUME_INFORMATION:
+               d_printf("\tcreate_time:                %s\n",
+                        nt_time_string(ctx,fsinfo.volume_info.out.create_time));
+               d_printf("\tserial_number:              %lu\n", 
+                        (unsigned long) fsinfo.volume_info.out.serial_number);
+               d_printf("\tvolume_name:                %s\n", fsinfo.volume_info.out.volume_name.s);
+               break;
+       case RAW_QFS_SIZE_INFO:
+       case RAW_QFS_SIZE_INFORMATION:
+               d_printf("\ttotal_alloc_units:          %llu\n", 
+                        (unsigned long long) fsinfo.size_info.out.total_alloc_units);
+               d_printf("\tavail_alloc_units:          %llu\n", 
+                        (unsigned long long) fsinfo.size_info.out.avail_alloc_units);
+               d_printf("\tsectors_per_unit:           %lu\n", 
+                        (unsigned long) fsinfo.size_info.out.sectors_per_unit);
+               d_printf("\tbytes_per_sector:           %lu\n", 
+                        (unsigned long) fsinfo.size_info.out.bytes_per_sector);
+               break;
+       case RAW_QFS_DEVICE_INFO:
+       case RAW_QFS_DEVICE_INFORMATION:
+               d_printf("\tdevice_type:                %lu\n", 
+                        (unsigned long) fsinfo.device_info.out.device_type);
+               d_printf("\tcharacteristics:            0x%lx\n", 
+                        (unsigned long) fsinfo.device_info.out.characteristics);
+               break;
+       case RAW_QFS_ATTRIBUTE_INFORMATION:
+       case RAW_QFS_ATTRIBUTE_INFO:
+               d_printf("\tfs_attr:                    0x%lx\n", 
+                        (unsigned long) fsinfo.attribute_info.out.fs_attr);
+               d_printf("\tmax_file_component_length:  %lu\n", 
+                        (unsigned long) fsinfo.attribute_info.out.max_file_component_length);
+               d_printf("\tfs_type:                    %s\n", fsinfo.attribute_info.out.fs_type.s);
+               break;
+       case RAW_QFS_UNIX_INFO:
+               d_printf("\tmajor_version:              %hu\n", 
+                        (unsigned short) fsinfo.unix_info.out.major_version);
+               d_printf("\tminor_version:              %hu\n", 
+                        (unsigned short) fsinfo.unix_info.out.minor_version);
+               d_printf("\tcapability:                 0x%llx\n", 
+                        (unsigned long long) fsinfo.unix_info.out.capability);
+               break;
+       case RAW_QFS_QUOTA_INFORMATION:
+               d_printf("\tunknown[3]:                 [%llu,%llu,%llu]\n", 
+                        (unsigned long long) fsinfo.quota_information.out.unknown[0],
+                        (unsigned long long) fsinfo.quota_information.out.unknown[1],
+                        (unsigned long long) fsinfo.quota_information.out.unknown[2]);
+               d_printf("\tquota_soft:                 %llu\n", 
+                        (unsigned long long) fsinfo.quota_information.out.quota_soft);
+               d_printf("\tquota_hard:                 %llu\n", 
+                        (unsigned long long) fsinfo.quota_information.out.quota_hard);
+               d_printf("\tquota_flags:                0x%llx\n", 
+                        (unsigned long long) fsinfo.quota_information.out.quota_flags);
+               break;
+       case RAW_QFS_FULL_SIZE_INFORMATION:
+               d_printf("\ttotal_alloc_units:          %llu\n", 
+                        (unsigned long long) fsinfo.full_size_information.out.total_alloc_units);
+               d_printf("\tcall_avail_alloc_units:     %llu\n", 
+                        (unsigned long long) fsinfo.full_size_information.out.call_avail_alloc_units);
+               d_printf("\tactual_avail_alloc_units:   %llu\n", 
+                        (unsigned long long) fsinfo.full_size_information.out.actual_avail_alloc_units);
+               d_printf("\tsectors_per_unit:           %lu\n", 
+                        (unsigned long) fsinfo.full_size_information.out.sectors_per_unit);
+               d_printf("\tbytes_per_sector:           %lu\n", 
+                        (unsigned long) fsinfo.full_size_information.out.bytes_per_sector);
+               break;
+       case RAW_QFS_OBJECTID_INFORMATION:
+               d_printf("\tGUID:                       %s\n", 
+                        GUID_string(ctx,&fsinfo.objectid_information.out.guid));
+               d_printf("\tunknown[6]:                 [%llu,%llu,%llu,%llu,%llu,%llu]\n", 
+                        (unsigned long long) fsinfo.objectid_information.out.unknown[0],
+                        (unsigned long long) fsinfo.objectid_information.out.unknown[1],
+                        (unsigned long long) fsinfo.objectid_information.out.unknown[2],
+                        (unsigned long long) fsinfo.objectid_information.out.unknown[3],
+                        (unsigned long long) fsinfo.objectid_information.out.unknown[4],
+                        (unsigned long long) fsinfo.objectid_information.out.unknown[5] );
+               break;
+       case RAW_QFS_GENERIC:
+               d_printf("\twrong level returned\n");
+               break;
+       }
+  
+       return 0;
+}
 
 /****************************************************************************
 show as much information as possible about a file
 ****************************************************************************/
 
 /****************************************************************************
 show as much information as possible about a file
 ****************************************************************************/
-static int cmd_allinfo(const char **cmd_ptr)
+static int cmd_allinfo(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring fname;
-       fstring buf;
-       int ret = 0;
-       TALLOC_CTX *mem_ctx;
+       char *fname;
        union smb_fileinfo finfo;
        NTSTATUS status;
        union smb_fileinfo finfo;
        NTSTATUS status;
+       int fnum;
 
 
-       pstrcpy(fname,cur_dir);
-       
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
+       if (!args[1]) {
                d_printf("allinfo <filename>\n");
                return 1;
        }
                d_printf("allinfo <filename>\n");
                return 1;
        }
-       pstrcat(fname,buf);
-
-       mem_ctx = talloc_init("%s", fname);
+       fname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
 
        /* first a ALL_INFO QPATHINFO */
        finfo.generic.level = RAW_FILEINFO_ALL_INFO;
 
        /* first a ALL_INFO QPATHINFO */
        finfo.generic.level = RAW_FILEINFO_ALL_INFO;
-       finfo.generic.in.fname = fname;
-       status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
+       finfo.generic.in.file.path = fname;
+       status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("%s - %s\n", fname, nt_errstr(status));
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("%s - %s\n", fname, nt_errstr(status));
-               ret = 1;
-               goto done;
+               return 1;
        }
 
        }
 
-       d_printf("\tcreate_time:    %s\n", nt_time_string(mem_ctx, finfo.all_info.out.create_time));
-       d_printf("\taccess_time:    %s\n", nt_time_string(mem_ctx, finfo.all_info.out.access_time));
-       d_printf("\twrite_time:     %s\n", nt_time_string(mem_ctx, finfo.all_info.out.write_time));
-       d_printf("\tchange_time:    %s\n", nt_time_string(mem_ctx, finfo.all_info.out.change_time));
+       d_printf("\tcreate_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.create_time));
+       d_printf("\taccess_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.access_time));
+       d_printf("\twrite_time:     %s\n", nt_time_string(ctx, finfo.all_info.out.write_time));
+       d_printf("\tchange_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.change_time));
        d_printf("\tattrib:         0x%x\n", finfo.all_info.out.attrib);
        d_printf("\talloc_size:     %lu\n", (unsigned long)finfo.all_info.out.alloc_size);
        d_printf("\tsize:           %lu\n", (unsigned long)finfo.all_info.out.size);
        d_printf("\tattrib:         0x%x\n", finfo.all_info.out.attrib);
        d_printf("\talloc_size:     %lu\n", (unsigned long)finfo.all_info.out.alloc_size);
        d_printf("\tsize:           %lu\n", (unsigned long)finfo.all_info.out.size);
@@ -1723,14 +1758,14 @@ static int cmd_allinfo(const char **cmd_ptr)
 
        /* 8.3 name if any */
        finfo.generic.level = RAW_FILEINFO_ALT_NAME_INFO;
 
        /* 8.3 name if any */
        finfo.generic.level = RAW_FILEINFO_ALT_NAME_INFO;
-       status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
+       status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
        if (NT_STATUS_IS_OK(status)) {
                d_printf("\talt_name:       %s\n", finfo.alt_name_info.out.fname.s);
        }
 
        /* file_id if available */
        finfo.generic.level = RAW_FILEINFO_INTERNAL_INFORMATION;
        if (NT_STATUS_IS_OK(status)) {
                d_printf("\talt_name:       %s\n", finfo.alt_name_info.out.fname.s);
        }
 
        /* file_id if available */
        finfo.generic.level = RAW_FILEINFO_INTERNAL_INFORMATION;
-       status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
+       status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
        if (NT_STATUS_IS_OK(status)) {
                d_printf("\tfile_id         %.0f\n", 
                         (double)finfo.internal_information.out.file_id);
        if (NT_STATUS_IS_OK(status)) {
                d_printf("\tfile_id         %.0f\n", 
                         (double)finfo.internal_information.out.file_id);
@@ -1738,22 +1773,20 @@ static int cmd_allinfo(const char **cmd_ptr)
 
        /* the EAs, if any */
        finfo.generic.level = RAW_FILEINFO_ALL_EAS;
 
        /* the EAs, if any */
        finfo.generic.level = RAW_FILEINFO_ALL_EAS;
-       status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
+       status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
        if (NT_STATUS_IS_OK(status)) {
                int i;
                for (i=0;i<finfo.all_eas.out.num_eas;i++) {
        if (NT_STATUS_IS_OK(status)) {
                int i;
                for (i=0;i<finfo.all_eas.out.num_eas;i++) {
-                       d_printf("\tEA[%d] flags=%d %s=%*.*s\n", i,
+                       d_printf("\tEA[%d] flags=%d len=%d '%s'\n", i,
                                 finfo.all_eas.out.eas[i].flags,
                                 finfo.all_eas.out.eas[i].flags,
-                                finfo.all_eas.out.eas[i].name.s,
-                                finfo.all_eas.out.eas[i].value.length,
-                                finfo.all_eas.out.eas[i].value.length,
-                                finfo.all_eas.out.eas[i].value.data);
+                                (int)finfo.all_eas.out.eas[i].value.length,
+                                finfo.all_eas.out.eas[i].name.s);
                }
        }
 
        /* streams, if available */
        finfo.generic.level = RAW_FILEINFO_STREAM_INFO;
                }
        }
 
        /* streams, if available */
        finfo.generic.level = RAW_FILEINFO_STREAM_INFO;
-       status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
+       status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
        if (NT_STATUS_IS_OK(status)) {
                int i;
                for (i=0;i<finfo.stream_info.out.num_streams;i++) {
        if (NT_STATUS_IS_OK(status)) {
                int i;
                for (i=0;i<finfo.stream_info.out.num_streams;i++) {
@@ -1768,7 +1801,7 @@ static int cmd_allinfo(const char **cmd_ptr)
 
        /* dev/inode if available */
        finfo.generic.level = RAW_FILEINFO_COMPRESSION_INFORMATION;
 
        /* dev/inode if available */
        finfo.generic.level = RAW_FILEINFO_COMPRESSION_INFORMATION;
-       status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
+       status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
        if (NT_STATUS_IS_OK(status)) {
                d_printf("\tcompressed size %ld\n", (long)finfo.compression_info.out.compressed_size);
                d_printf("\tformat          %ld\n", (long)finfo.compression_info.out.format);
        if (NT_STATUS_IS_OK(status)) {
                d_printf("\tcompressed size %ld\n", (long)finfo.compression_info.out.compressed_size);
                d_printf("\tformat          %ld\n", (long)finfo.compression_info.out.format);
@@ -1777,77 +1810,310 @@ static int cmd_allinfo(const char **cmd_ptr)
                d_printf("\tcluster_shift   %ld\n", (long)finfo.compression_info.out.cluster_shift);
        }
 
                d_printf("\tcluster_shift   %ld\n", (long)finfo.compression_info.out.cluster_shift);
        }
 
-       talloc_destroy(mem_ctx);
+       /* shadow copies if available */
+       fnum = smbcli_open(ctx->cli->tree, fname, O_RDONLY, DENY_NONE);
+       if (fnum != -1) {
+               struct smb_shadow_copy info;
+               int i;
+               info.in.file.fnum = fnum;
+               info.in.max_data = ~0;
+               status = smb_raw_shadow_data(ctx->cli->tree, ctx, &info);
+               if (NT_STATUS_IS_OK(status)) {
+                       d_printf("\tshadow_copy: %u volumes  %u names\n",
+                                info.out.num_volumes, info.out.num_names);
+                       for (i=0;i<info.out.num_names;i++) {
+                               d_printf("\t%s\n", info.out.names[i]);
+                               finfo.generic.level = RAW_FILEINFO_ALL_INFO;
+                               finfo.generic.in.file.path = talloc_asprintf(ctx, "%s%s", 
+                                                                            info.out.names[i], fname); 
+                               status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
+                               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
+                                   NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+                                       continue;
+                               }
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       d_printf("%s - %s\n", finfo.generic.in.file.path, 
+                                                nt_errstr(status));
+                                       return 1;
+                               }
+                               
+                               d_printf("\t\tcreate_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.create_time));
+                               d_printf("\t\twrite_time:     %s\n", nt_time_string(ctx, finfo.all_info.out.write_time));
+                               d_printf("\t\tchange_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.change_time));
+                               d_printf("\t\tsize:           %lu\n", (unsigned long)finfo.all_info.out.size);
+                       }
+               }
+       }
+       
+       return 0;
+}
+
 
 
-done:
-       return ret;
+/****************************************************************************
+shows EA contents
+****************************************************************************/
+static int cmd_eainfo(struct smbclient_context *ctx, const char **args)
+{
+       char *fname;
+       union smb_fileinfo finfo;
+       NTSTATUS status;
+       int i;
+
+       if (!args[1]) {
+               d_printf("eainfo <filename>\n");
+               return 1;
+       }
+       fname = talloc_strdup(ctx, args[1]);
+
+       finfo.generic.level = RAW_FILEINFO_ALL_EAS;
+       finfo.generic.in.file.path = fname;
+       status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
+       
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("RAW_FILEINFO_ALL_EAS - %s\n", nt_errstr(status));
+               return 1;
+       }
+
+       d_printf("%s has %d EAs\n", fname, finfo.all_eas.out.num_eas);
+
+       for (i=0;i<finfo.all_eas.out.num_eas;i++) {
+               d_printf("\tEA[%d] flags=%d len=%d '%s'\n", i,
+                        finfo.all_eas.out.eas[i].flags,
+                        (int)finfo.all_eas.out.eas[i].value.length,
+                        finfo.all_eas.out.eas[i].name.s);
+               fflush(stdout);
+               dump_data(0, 
+                         finfo.all_eas.out.eas[i].value.data,
+                         finfo.all_eas.out.eas[i].value.length);
+       }
+
+       return 0;
 }
 
 
 /****************************************************************************
 show any ACL on a file
 ****************************************************************************/
 }
 
 
 /****************************************************************************
 show any ACL on a file
 ****************************************************************************/
-static int cmd_acl(const char **cmd_ptr)
+static int cmd_acl(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring fname;
-       fstring buf;
-       int ret = 0;
-       TALLOC_CTX *mem_ctx;
-       struct smb_query_secdesc query;
+       char *fname;
+       union smb_fileinfo query;
        NTSTATUS status;
        int fnum;
 
        NTSTATUS status;
        int fnum;
 
-       pstrcpy(fname,cur_dir);
-       
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
+       if (!args[1]) {
                d_printf("acl <filename>\n");
                return 1;
        }
                d_printf("acl <filename>\n");
                return 1;
        }
-       pstrcat(fname,buf);
+       fname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
 
 
-       fnum = smbcli_open(cli->tree, fname, O_RDONLY, DENY_NONE);
+       fnum = smbcli_nt_create_full(ctx->cli->tree, fname, 0, 
+                                    SEC_STD_READ_CONTROL,
+                                    0,
+                                    NTCREATEX_SHARE_ACCESS_DELETE|
+                                    NTCREATEX_SHARE_ACCESS_READ|
+                                    NTCREATEX_SHARE_ACCESS_WRITE, 
+                                    NTCREATEX_DISP_OPEN,
+                                    0, 0);
        if (fnum == -1) {
        if (fnum == -1) {
-               d_printf("%s - %s\n", fname, smbcli_errstr(cli->tree));
+               d_printf("%s - %s\n", fname, smbcli_errstr(ctx->cli->tree));
                return -1;
        }
 
                return -1;
        }
 
-       mem_ctx = talloc_init("%s", fname);
+       query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+       query.query_secdesc.in.file.fnum = fnum;
+       query.query_secdesc.in.secinfo_flags = 0x7;
 
 
-       query.in.fnum = fnum;
-       query.in.secinfo_flags = 0x7;
-
-       status = smb_raw_query_secdesc(cli->tree, mem_ctx, &query);
+       status = smb_raw_fileinfo(ctx->cli->tree, ctx, &query);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("%s - %s\n", fname, nt_errstr(status));
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("%s - %s\n", fname, nt_errstr(status));
-               ret = 1;
-               goto done;
+               return 1;
        }
 
        }
 
-       NDR_PRINT_DEBUG(security_descriptor, query.out.sd);
+       NDR_PRINT_DEBUG(security_descriptor, query.query_secdesc.out.sd);
 
 
-       talloc_destroy(mem_ctx);
+       return 0;
+}
 
 
-done:
-       return ret;
+/****************************************************************************
+lookup a name or sid
+****************************************************************************/
+static int cmd_lookup(struct smbclient_context *ctx, const char **args)
+{
+       NTSTATUS status;
+       struct dom_sid *sid;
+
+       if (!args[1]) {
+               d_printf("lookup <sid|name>\n");
+               return 1;
+       }
+
+       sid = dom_sid_parse_talloc(ctx, args[1]);
+       if (sid == NULL) {
+               const char *sidstr;
+               status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sidstr);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
+                       return 1;
+               }
+
+               d_printf("%s\n", sidstr);
+       } else {
+               const char *name;
+               status = smblsa_lookup_sid(ctx->cli, args[1], ctx, &name);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("lsa_LookupSids - %s\n", nt_errstr(status));
+                       return 1;
+               }
+
+               d_printf("%s\n", name);
+       }
+
+       return 0;
+}
+
+/****************************************************************************
+show privileges for a user
+****************************************************************************/
+static int cmd_privileges(struct smbclient_context *ctx, const char **args)
+{
+       NTSTATUS status;
+       struct dom_sid *sid;
+       struct lsa_RightSet rights;
+       unsigned i;
+
+       if (!args[1]) {
+               d_printf("privileges <sid|name>\n");
+               return 1;
+       }
+
+       sid = dom_sid_parse_talloc(ctx, args[1]);
+       if (sid == NULL) {
+               const char *sid_str;
+               status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
+                       return 1;
+               }
+               sid = dom_sid_parse_talloc(ctx, sid_str);
+       }
+
+       status = smblsa_sid_privileges(ctx->cli, sid, ctx, &rights);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("lsa_EnumAccountRights - %s\n", nt_errstr(status));
+               return 1;
+       }
+
+       for (i=0;i<rights.count;i++) {
+               d_printf("\t%s\n", rights.names[i].string);
+       }
+
+       return 0;
 }
 
 
 /****************************************************************************
 }
 
 
 /****************************************************************************
+add privileges for a user
 ****************************************************************************/
 ****************************************************************************/
-static int cmd_open(const char **cmd_ptr)
+static int cmd_addprivileges(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring mask;
-       fstring buf;
-       
-       pstrcpy(mask,cur_dir);
+       NTSTATUS status;
+       struct dom_sid *sid;
+       struct lsa_RightSet rights;
+       int i;
+
+       if (!args[1]) {
+               d_printf("addprivileges <sid|name> <privilege...>\n");
+               return 1;
+       }
+
+       sid = dom_sid_parse_talloc(ctx, args[1]);
+       if (sid == NULL) {
+               const char *sid_str;
+               status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
+                       return 1;
+               }
+               sid = dom_sid_parse_talloc(ctx, sid_str);
+       }
+
+       ZERO_STRUCT(rights);
+       for (i = 2; args[i]; i++) {
+               rights.names = talloc_realloc(ctx, rights.names, 
+                                             struct lsa_StringLarge, rights.count+1);
+               rights.names[rights.count].string = talloc_strdup(ctx, args[i]);
+               rights.count++;
+       }
+
+
+       status = smblsa_sid_add_privileges(ctx->cli, sid, ctx, &rights);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("lsa_AddAccountRights - %s\n", nt_errstr(status));
+               return 1;
+       }
+
+       return 0;
+}
+
+/****************************************************************************
+delete privileges for a user
+****************************************************************************/
+static int cmd_delprivileges(struct smbclient_context *ctx, const char **args)
+{
+       NTSTATUS status;
+       struct dom_sid *sid;
+       struct lsa_RightSet rights;
+       int i;
+
+       if (!args[1]) {
+               d_printf("delprivileges <sid|name> <privilege...>\n");
+               return 1;
+       }
+
+       sid = dom_sid_parse_talloc(ctx, args[1]);
+       if (sid == NULL) {
+               const char *sid_str;
+               status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
+                       return 1;
+               }
+               sid = dom_sid_parse_talloc(ctx, sid_str);
+       }
+
+       ZERO_STRUCT(rights);
+       for (i = 2; args[i]; i++) {
+               rights.names = talloc_realloc(ctx, rights.names, 
+                                             struct lsa_StringLarge, rights.count+1);
+               rights.names[rights.count].string = talloc_strdup(ctx, args[i]);
+               rights.count++;
+       }
+
+
+       status = smblsa_sid_del_privileges(ctx->cli, sid, ctx, &rights);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("lsa_RemoveAccountRights - %s\n", nt_errstr(status));
+               return 1;
+       }
+
+       return 0;
+}
+
+
+/****************************************************************************
+****************************************************************************/
+static int cmd_open(struct smbclient_context *ctx, const char **args)
+{
+       char *mask;
        
        
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
+       if (!args[1]) {
                d_printf("open <filename>\n");
                return 1;
        }
                d_printf("open <filename>\n");
                return 1;
        }
-       pstrcat(mask,buf);
+       mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
 
 
-       smbcli_open(cli->tree, mask, O_RDWR, DENY_ALL);
+       smbcli_open(ctx->cli->tree, mask, O_RDWR, DENY_ALL);
 
        return 0;
 }
 
        return 0;
 }
@@ -1856,22 +2122,19 @@ static int cmd_open(const char **cmd_ptr)
 /****************************************************************************
 remove a directory
 ****************************************************************************/
 /****************************************************************************
 remove a directory
 ****************************************************************************/
-static int cmd_rmdir(const char **cmd_ptr)
+static int cmd_rmdir(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring mask;
-       fstring buf;
+       char *mask;
   
   
-       pstrcpy(mask,cur_dir);
-       
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
+       if (!args[1]) {
                d_printf("rmdir <dirname>\n");
                return 1;
        }
                d_printf("rmdir <dirname>\n");
                return 1;
        }
-       pstrcat(mask,buf);
+       mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
 
 
-       if (NT_STATUS_IS_ERR(smbcli_rmdir(cli->tree, mask))) {
+       if (NT_STATUS_IS_ERR(smbcli_rmdir(ctx->cli->tree, mask))) {
                d_printf("%s removing remote directory file %s\n",
                d_printf("%s removing remote directory file %s\n",
-                        smbcli_errstr(cli->tree),mask);
+                        smbcli_errstr(ctx->cli->tree),mask);
        }
        
        return 0;
        }
        
        return 0;
@@ -1880,30 +2143,26 @@ static int cmd_rmdir(const char **cmd_ptr)
 /****************************************************************************
  UNIX hardlink.
 ****************************************************************************/
 /****************************************************************************
  UNIX hardlink.
 ****************************************************************************/
-static int cmd_link(const char **cmd_ptr)
+static int cmd_link(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring src,dest;
-       fstring buf,buf2;
+       char *src,*dest;
   
   
-       if (!(cli->transport->negotiate.capabilities & CAP_UNIX)) {
+       if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
                d_printf("Server doesn't support UNIX CIFS calls.\n");
                return 1;
        }
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
                return 1;
        }
 
-       pstrcpy(src,cur_dir);
-       pstrcpy(dest,cur_dir);
-  
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf)) || 
-           !next_token(cmd_ptr,buf2,NULL, sizeof(buf2))) {
+       
+       if (!args[1] || !args[2]) {
                d_printf("link <src> <dest>\n");
                return 1;
        }
 
                d_printf("link <src> <dest>\n");
                return 1;
        }
 
-       pstrcat(src,buf);
-       pstrcat(dest,buf2);
+       src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
+       dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
 
 
-       if (NT_STATUS_IS_ERR(smbcli_unix_hardlink(cli->tree, src, dest))) {
-               d_printf("%s linking files (%s -> %s)\n", smbcli_errstr(cli->tree), src, dest);
+       if (NT_STATUS_IS_ERR(smbcli_unix_hardlink(ctx->cli->tree, src, dest))) {
+               d_printf("%s linking files (%s -> %s)\n", smbcli_errstr(ctx->cli->tree), src, dest);
                return 1;
        }  
 
                return 1;
        }  
 
@@ -1914,31 +2173,26 @@ static int cmd_link(const char **cmd_ptr)
  UNIX symlink.
 ****************************************************************************/
 
  UNIX symlink.
 ****************************************************************************/
 
-static int cmd_symlink(const char **cmd_ptr)
+static int cmd_symlink(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring src,dest;
-       fstring buf,buf2;
+       char *src,*dest;
   
   
-       if (!(cli->transport->negotiate.capabilities & CAP_UNIX)) {
+       if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
                d_printf("Server doesn't support UNIX CIFS calls.\n");
                return 1;
        }
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
                return 1;
        }
 
-       pstrcpy(src,cur_dir);
-       pstrcpy(dest,cur_dir);
-       
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf)) || 
-           !next_token(cmd_ptr,buf2,NULL, sizeof(buf2))) {
+       if (!args[1] || !args[2]) {
                d_printf("symlink <src> <dest>\n");
                return 1;
        }
 
                d_printf("symlink <src> <dest>\n");
                return 1;
        }
 
-       pstrcat(src,buf);
-       pstrcat(dest,buf2);
+       src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
+       dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
 
 
-       if (NT_STATUS_IS_ERR(smbcli_unix_symlink(cli->tree, src, dest))) {
+       if (NT_STATUS_IS_ERR(smbcli_unix_symlink(ctx->cli->tree, src, dest))) {
                d_printf("%s symlinking files (%s -> %s)\n",
                d_printf("%s symlinking files (%s -> %s)\n",
-                       smbcli_errstr(cli->tree), src, dest);
+                       smbcli_errstr(ctx->cli->tree), src, dest);
                return 1;
        } 
 
                return 1;
        } 
 
@@ -1949,31 +2203,28 @@ static int cmd_symlink(const char **cmd_ptr)
  UNIX chmod.
 ****************************************************************************/
 
  UNIX chmod.
 ****************************************************************************/
 
-static int cmd_chmod(const char **cmd_ptr)
+static int cmd_chmod(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring src;
+       char *src;
        mode_t mode;
        mode_t mode;
-       fstring buf, buf2;
   
   
-       if (!(cli->transport->negotiate.capabilities & CAP_UNIX)) {
+       if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
                d_printf("Server doesn't support UNIX CIFS calls.\n");
                return 1;
        }
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
                return 1;
        }
 
-       pstrcpy(src,cur_dir);
-       
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf)) || 
-           !next_token(cmd_ptr,buf2,NULL, sizeof(buf2))) {
+       if (!args[1] || !args[2]) {
                d_printf("chmod mode file\n");
                return 1;
        }
 
                d_printf("chmod mode file\n");
                return 1;
        }
 
-       mode = (mode_t)strtol(buf, NULL, 8);
-       pstrcat(src,buf2);
+       src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
+       
+       mode = (mode_t)strtol(args[1], NULL, 8);
 
 
-       if (NT_STATUS_IS_ERR(smbcli_unix_chmod(cli->tree, src, mode))) {
+       if (NT_STATUS_IS_ERR(smbcli_unix_chmod(ctx->cli->tree, src, mode))) {
                d_printf("%s chmod file %s 0%o\n",
                d_printf("%s chmod file %s 0%o\n",
-                       smbcli_errstr(cli->tree), src, (uint_t)mode);
+                       smbcli_errstr(ctx->cli->tree), src, (mode_t)mode);
                return 1;
        } 
 
                return 1;
        } 
 
@@ -1984,34 +2235,29 @@ static int cmd_chmod(const char **cmd_ptr)
  UNIX chown.
 ****************************************************************************/
 
  UNIX chown.
 ****************************************************************************/
 
-static int cmd_chown(const char **cmd_ptr)
+static int cmd_chown(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring src;
+       char *src;
        uid_t uid;
        gid_t gid;
        uid_t uid;
        gid_t gid;
-       fstring buf, buf2, buf3;
   
   
-       if (!(cli->transport->negotiate.capabilities & CAP_UNIX)) {
+       if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
                d_printf("Server doesn't support UNIX CIFS calls.\n");
                return 1;
        }
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
                return 1;
        }
 
-       pstrcpy(src,cur_dir);
-       
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf)) || 
-           !next_token(cmd_ptr,buf2,NULL, sizeof(buf2)) ||
-           !next_token(cmd_ptr,buf3,NULL, sizeof(buf3))) {
+       if (!args[1] || !args[2] || !args[3]) {
                d_printf("chown uid gid file\n");
                return 1;
        }
 
                d_printf("chown uid gid file\n");
                return 1;
        }
 
-       uid = (uid_t)atoi(buf);
-       gid = (gid_t)atoi(buf2);
-       pstrcat(src,buf3);
+       uid = (uid_t)atoi(args[1]);
+       gid = (gid_t)atoi(args[2]);
+       src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[3]);
 
 
-       if (NT_STATUS_IS_ERR(smbcli_unix_chown(cli->tree, src, uid, gid))) {
+       if (NT_STATUS_IS_ERR(smbcli_unix_chown(ctx->cli->tree, src, uid, gid))) {
                d_printf("%s chown file %s uid=%d, gid=%d\n",
                d_printf("%s chown file %s uid=%d, gid=%d\n",
-                       smbcli_errstr(cli->tree), src, (int)uid, (int)gid);
+                       smbcli_errstr(ctx->cli->tree), src, (int)uid, (int)gid);
                return 1;
        } 
 
                return 1;
        } 
 
@@ -2021,25 +2267,20 @@ static int cmd_chown(const char **cmd_ptr)
 /****************************************************************************
 rename some files
 ****************************************************************************/
 /****************************************************************************
 rename some files
 ****************************************************************************/
-static int cmd_rename(const char **cmd_ptr)
+static int cmd_rename(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring src,dest;
-       fstring buf,buf2;
+       char *src,*dest;
   
   
-       pstrcpy(src,cur_dir);
-       pstrcpy(dest,cur_dir);
-       
-       if (!next_token(cmd_ptr,buf,NULL,sizeof(buf)) || 
-           !next_token(cmd_ptr,buf2,NULL, sizeof(buf2))) {
+       if (!args[1] || !args[2]) {
                d_printf("rename <src> <dest>\n");
                return 1;
        }
 
                d_printf("rename <src> <dest>\n");
                return 1;
        }
 
-       pstrcat(src,buf);
-       pstrcat(dest,buf2);
+       src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
+       dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
 
 
-       if (NT_STATUS_IS_ERR(smbcli_rename(cli->tree, src, dest))) {
-               d_printf("%s renaming files\n",smbcli_errstr(cli->tree));
+       if (NT_STATUS_IS_ERR(smbcli_rename(ctx->cli->tree, src, dest))) {
+               d_printf("%s renaming files\n",smbcli_errstr(ctx->cli->tree));
                return 1;
        }
        
                return 1;
        }
        
@@ -2050,10 +2291,10 @@ static int cmd_rename(const char **cmd_ptr)
 /****************************************************************************
 toggle the prompt flag
 ****************************************************************************/
 /****************************************************************************
 toggle the prompt flag
 ****************************************************************************/
-static int cmd_prompt(const char **cmd_ptr)
+static int cmd_prompt(struct smbclient_context *ctx, const char **args)
 {
 {
-       prompt = !prompt;
-       DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
+       ctx->prompt = !ctx->prompt;
+       DEBUG(2,("prompting is now %s\n",ctx->prompt?"on":"off"));
        
        return 1;
 }
        
        return 1;
 }
@@ -2062,22 +2303,19 @@ static int cmd_prompt(const char **cmd_ptr)
 /****************************************************************************
 set the newer than time
 ****************************************************************************/
 /****************************************************************************
 set the newer than time
 ****************************************************************************/
-static int cmd_newer(const char **cmd_ptr)
+static int cmd_newer(struct smbclient_context *ctx, const char **args)
 {
 {
-       fstring buf;
-       BOOL ok;
        struct stat sbuf;
 
        struct stat sbuf;
 
-       ok = next_token(cmd_ptr,buf,NULL,sizeof(buf));
-       if (ok && (stat(buf,&sbuf) == 0)) {
-               newer_than = sbuf.st_mtime;
+       if (args[1] && (stat(args[1],&sbuf) == 0)) {
+               ctx->newer_than = sbuf.st_mtime;
                DEBUG(1,("Getting files newer than %s",
                DEBUG(1,("Getting files newer than %s",
-                        asctime(localtime(&newer_than))));
+                        asctime(localtime(&ctx->newer_than))));
        } else {
        } else {
-               newer_than = 0;
+               ctx->newer_than = 0;
        }
 
        }
 
-       if (ok && newer_than == 0) {
+       if (args[1] && ctx->newer_than == 0) {
                d_printf("Error setting newer-than time\n");
                return 1;
        }
                d_printf("Error setting newer-than time\n");
                return 1;
        }
@@ -2088,14 +2326,12 @@ static int cmd_newer(const char **cmd_ptr)
 /****************************************************************************
 set the archive level
 ****************************************************************************/
 /****************************************************************************
 set the archive level
 ****************************************************************************/
-static int cmd_archive(const char **cmd_ptr)
+static int cmd_archive(struct smbclient_context *ctx, const char **args)
 {
 {
-       fstring buf;
-
-       if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
-               archive_level = atoi(buf);
+       if (args[1]) {
+               ctx->archive_level = atoi(args[1]);
        } else
        } else
-               d_printf("Archive level is %d\n",archive_level);
+               d_printf("Archive level is %d\n",ctx->archive_level);
 
        return 0;
 }
 
        return 0;
 }
@@ -2103,10 +2339,10 @@ static int cmd_archive(const char **cmd_ptr)
 /****************************************************************************
 toggle the lowercaseflag
 ****************************************************************************/
 /****************************************************************************
 toggle the lowercaseflag
 ****************************************************************************/
-static int cmd_lowercase(const char **cmd_ptr)
+static int cmd_lowercase(struct smbclient_context *ctx, const char **args)
 {
 {
-       lowercase = !lowercase;
-       DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
+       ctx->lowercase = !ctx->lowercase;
+       DEBUG(2,("filename lowercasing is now %s\n",ctx->lowercase?"on":"off"));
 
        return 0;
 }
 
        return 0;
 }
@@ -2117,10 +2353,10 @@ static int cmd_lowercase(const char **cmd_ptr)
 /****************************************************************************
 toggle the recurse flag
 ****************************************************************************/
 /****************************************************************************
 toggle the recurse flag
 ****************************************************************************/
-static int cmd_recurse(const char **cmd_ptr)
+static int cmd_recurse(struct smbclient_context *ctx, const char **args)
 {
 {
-       recurse = !recurse;
-       DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
+       ctx->recurse = !ctx->recurse;
+       DEBUG(2,("directory recursion is now %s\n",ctx->recurse?"on":"off"));
 
        return 0;
 }
 
        return 0;
 }
@@ -2128,11 +2364,11 @@ static int cmd_recurse(const char **cmd_ptr)
 /****************************************************************************
 toggle the translate flag
 ****************************************************************************/
 /****************************************************************************
 toggle the translate flag
 ****************************************************************************/
-static int cmd_translate(const char **cmd_ptr)
+static int cmd_translate(struct smbclient_context *ctx, const char **args)
 {
 {
-       translation = !translation;
+       ctx->translation = !ctx->translation;
        DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
        DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
-                translation?"on":"off"));
+                ctx->translation?"on":"off"));
 
        return 0;
 }
 
        return 0;
 }
@@ -2141,51 +2377,66 @@ static int cmd_translate(const char **cmd_ptr)
 /****************************************************************************
 do a printmode command
 ****************************************************************************/
 /****************************************************************************
 do a printmode command
 ****************************************************************************/
-static int cmd_printmode(const char **cmd_ptr)
+static int cmd_printmode(struct smbclient_context *ctx, const char **args)
 {
 {
-       fstring buf;
-       fstring mode;
-
-       if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
-               if (strequal(buf,"text")) {
-                       printmode = 0;      
+       if (args[1]) {
+               if (strequal(args[1],"text")) {
+                       ctx->printmode = 0;      
                } else {
                } else {
-                       if (strequal(buf,"graphics"))
-                               printmode = 1;
+                       if (strequal(args[1],"graphics"))
+                               ctx->printmode = 1;
                        else
                        else
-                               printmode = atoi(buf);
+                               ctx->printmode = atoi(args[1]);
                }
        }
 
                }
        }
 
-       switch(printmode)
-               {
+       switch(ctx->printmode)
+       {
                case 0: 
                case 0: 
-                       fstrcpy(mode,"text");
+                       DEBUG(2,("the printmode is now text\n"));
                        break;
                case 1: 
                        break;
                case 1: 
-                       fstrcpy(mode,"graphics");
+                       DEBUG(2,("the printmode is now graphics\n"));
                        break;
                default: 
                        break;
                default: 
-                       slprintf(mode,sizeof(mode)-1,"%d",printmode);
+                       DEBUG(2,("the printmode is now %d\n", ctx->printmode));
                        break;
                        break;
-               }
+       }
        
        
-       DEBUG(2,("the printmode is now %s\n",mode));
-
        return 0;
 }
 
 /****************************************************************************
  do the lcd command
  ****************************************************************************/
        return 0;
 }
 
 /****************************************************************************
  do the lcd command
  ****************************************************************************/
-static int cmd_lcd(const char **cmd_ptr)
+static int cmd_lcd(struct smbclient_context *ctx, const char **args)
 {
 {
-       fstring buf;
-       pstring d;
+       char d[PATH_MAX];
        
        
-       if (next_token(cmd_ptr,buf,NULL,sizeof(buf)))
-               chdir(buf);
-       DEBUG(2,("the local directory is now %s\n",sys_getwd(d)));
+       if (args[1]) 
+               chdir(args[1]);
+       DEBUG(2,("the local directory is now %s\n",getcwd(d, PATH_MAX)));
+
+       return 0;
+}
+
+/****************************************************************************
+history
+****************************************************************************/
+static int cmd_history(struct smbclient_context *ctx, const char **args)
+{
+#if defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_LIST)
+       HIST_ENTRY **hlist;
+       int i;
+
+       hlist = history_list();
+       
+       for (i = 0; hlist && hlist[i]; i++) {
+               DEBUG(0, ("%d: %s\n", i, hlist[i]->line));
+       }
+#else
+       DEBUG(0,("no history without readline support\n"));
+#endif
 
        return 0;
 }
 
        return 0;
 }
@@ -2193,62 +2444,53 @@ static int cmd_lcd(const char **cmd_ptr)
 /****************************************************************************
  get a file restarting at end of local file
  ****************************************************************************/
 /****************************************************************************
  get a file restarting at end of local file
  ****************************************************************************/
-static int cmd_reget(const char **cmd_ptr)
+static int cmd_reget(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring local_name;
-       pstring remote_name;
-       char *p;
+       char *local_name;
+       char *remote_name;
 
 
-       pstrcpy(remote_name, cur_dir);
-       pstrcat(remote_name, "\\");
-       
-       p = remote_name + strlen(remote_name);
-       
-       if (!next_token(cmd_ptr, p, NULL, sizeof(remote_name) - strlen(remote_name))) {
+       if (!args[1]) {
                d_printf("reget <filename>\n");
                return 1;
        }
                d_printf("reget <filename>\n");
                return 1;
        }
-       pstrcpy(local_name, p);
+       remote_name = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
        dos_clean_name(remote_name);
        
        dos_clean_name(remote_name);
        
-       next_token(cmd_ptr, local_name, NULL, sizeof(local_name));
+       if (args[2]) 
+               local_name = talloc_strdup(ctx, args[2]);
+       else
+               local_name = talloc_strdup(ctx, args[1]);
        
        
-       return do_get(remote_name, local_name, True);
+       return do_get(ctx, remote_name, local_name, True);
 }
 
 /****************************************************************************
  put a file restarting at end of local file
  ****************************************************************************/
 }
 
 /****************************************************************************
  put a file restarting at end of local file
  ****************************************************************************/
-static int cmd_reput(const char **cmd_ptr)
+static int cmd_reput(struct smbclient_context *ctx, const char **args)
 {
 {
-       pstring local_name;
-       pstring remote_name;
-       fstring buf;
-       char *p = buf;
-       struct stat st;
+       char *local_name;
+       char *remote_name;
        
        
-       pstrcpy(remote_name, cur_dir);
-       pstrcat(remote_name, "\\");
-  
-       if (!next_token(cmd_ptr, p, NULL, sizeof(buf))) {
+       if (!args[1]) {
                d_printf("reput <filename>\n");
                return 1;
        }
                d_printf("reput <filename>\n");
                return 1;
        }
-       pstrcpy(local_name, p);
+       local_name = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
   
   
-       if (!file_exist(local_name, &st)) {
+       if (!file_exist(local_name)) {
                d_printf("%s does not exist\n", local_name);
                return 1;
        }
 
                d_printf("%s does not exist\n", local_name);
                return 1;
        }
 
-       if (next_token(cmd_ptr, p, NULL, sizeof(buf)))
-               pstrcat(remote_name, p);
+       if (args[2]) 
+               remote_name = talloc_strdup(ctx, args[2]);
        else
        else
-               pstrcat(remote_name, local_name);
+               remote_name = talloc_strdup(ctx, args[1]);
        
        dos_clean_name(remote_name);
 
        
        dos_clean_name(remote_name);
 
-       return do_put(remote_name, local_name, True);
+       return do_put(ctx, remote_name, local_name, True);
 }
 
 
 }
 
 
@@ -2306,18 +2548,15 @@ static BOOL browse_host(const char *query_host)
 
        binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", query_host);
 
 
        binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", query_host);
 
-       status = dcerpc_pipe_connect(&p, binding, 
-                                    DCERPC_SRVSVC_UUID, 
-                                    DCERPC_SRVSVC_VERSION,
-                                    domain, 
-                                    username, password);
+       status = dcerpc_pipe_connect(mem_ctx, &p, binding, 
+                                        &ndr_table_srvsvc,
+                                    cmdline_credentials, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("Failed to connect to %s - %s\n", 
                         binding, nt_errstr(status));
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("Failed to connect to %s - %s\n", 
                         binding, nt_errstr(status));
-               talloc_destroy(mem_ctx);
+               talloc_free(mem_ctx);
                return False;
        }
                return False;
        }
-       talloc_steal(mem_ctx, p);
 
        r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
        r.in.level = 1;
 
        r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
        r.in.level = 1;
@@ -2341,7 +2580,7 @@ static BOOL browse_host(const char *query_host)
                }
        } while (NT_STATUS_IS_OK(status) && W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
 
                }
        } while (NT_STATUS_IS_OK(status) && W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
 
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
 
        if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
                d_printf("Failed NetShareEnumAll %s - %s/%s\n", 
 
        if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
                d_printf("Failed NetShareEnumAll %s - %s/%s\n", 
@@ -2367,6 +2606,8 @@ static BOOL list_servers(const char *wk_grp)
 #define COMPL_REMOTE      1          /* Complete remote filename */
 #define COMPL_LOCAL       2          /* Complete local filename */
 
 #define COMPL_REMOTE      1          /* Complete remote filename */
 #define COMPL_LOCAL       2          /* Complete local filename */
 
+static int cmd_help(struct smbclient_context *ctx, const char **args);
+
 /* This defines the commands supported by this client.
  * NOTE: The "!" must be the last one in the list because it's fn pointer
  *       field is NULL, and NULL in that field is used in process_tok()
 /* This defines the commands supported by this client.
  * NOTE: The "!" must be the last one in the list because it's fn pointer
  *       field is NULL, and NULL in that field is used in process_tok()
@@ -2375,31 +2616,35 @@ static BOOL list_servers(const char *wk_grp)
 static struct
 {
   const char *name;
 static struct
 {
   const char *name;
-  int (*fn)(const char **cmd_ptr);
+  int (*fn)(struct smbclient_context *ctx, const char **args);
   const char *description;
   char compl_args[2];      /* Completion argument info */
 } commands[] = 
 {
   {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
   const char *description;
   char compl_args[2];      /* Completion argument info */
 } commands[] = 
 {
   {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
+  {"addprivileges",cmd_addprivileges,"<sid|name> <privilege...> add privileges for a user",{COMPL_NONE,COMPL_NONE}},
   {"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
   {"acl",cmd_acl,"<file> show file ACL",{COMPL_NONE,COMPL_NONE}},
   {"allinfo",cmd_allinfo,"<file> show all possible info about a file",{COMPL_NONE,COMPL_NONE}},
   {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
   {"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
   {"acl",cmd_acl,"<file> show file ACL",{COMPL_NONE,COMPL_NONE}},
   {"allinfo",cmd_allinfo,"<file> show all possible info about a file",{COMPL_NONE,COMPL_NONE}},
   {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
-  {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
-  {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
+  {"cancel",cmd_rewrite,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
   {"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}},
   {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
   {"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}},
   {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
+  {"delprivileges",cmd_delprivileges,"<sid|name> <privilege...> remove privileges for a user",{COMPL_NONE,COMPL_NONE}},
   {"deltree",cmd_deltree,"<dir> delete a whole directory tree",{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}},
   {"deltree",cmd_deltree,"<dir> delete a whole directory tree",{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}},
+  {"eainfo",cmd_eainfo,"<file> show EA contents for a file",{COMPL_NONE,COMPL_NONE}},
   {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
   {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
+  {"fsinfo",cmd_fsinfo,"query file system info",{COMPL_NONE,COMPL_NONE}},
   {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
   {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
   {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
   {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
   {"link",cmd_link,"<src> <dest> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
   {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
   {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
   {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
   {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
   {"link",cmd_link,"<src> <dest> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
+  {"lookup",cmd_lookup,"<sid|name> show SID for name or name for SID",{COMPL_NONE,COMPL_NONE}},
   {"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}},
   {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
   {"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}},
   {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
@@ -2410,13 +2655,14 @@ 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}},
   {"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}},
+  {"privileges",cmd_privileges,"<user> show privileges for a user",{COMPL_NONE,COMPL_NONE}},
   {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
   {"printmode",cmd_printmode,"<graphics or text> set the print mode",{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}},
   {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
   {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
   {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
   {"printmode",cmd_printmode,"<graphics or text> set the print mode",{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}},
   {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
   {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
-  {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}},
+  {"queue",cmd_rewrite,"show the print queue",{COMPL_NONE,COMPL_NONE}},
   {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
   {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},  
   {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
   {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},  
@@ -2425,10 +2671,7 @@ 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}},
   {"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}},
-  {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
   {"symlink",cmd_symlink,"<src> <dest> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}},
   {"symlink",cmd_symlink,"<src> <dest> 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}},
   
   /* Yes, this must be here, see crh's comment above. */
   {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
   
   /* Yes, this must be here, see crh's comment above. */
@@ -2441,7 +2684,7 @@ static struct
   lookup a command string in the list of commands, including 
   abbreviations
   ******************************************************************/
   lookup a command string in the list of commands, including 
   abbreviations
   ******************************************************************/
-static int process_tok(fstring tok)
+static int process_tok(const char *tok)
 {
        int i = 0, matches = 0;
        int cmd=0;
 {
        int i = 0, matches = 0;
        int cmd=0;
@@ -2470,13 +2713,12 @@ static int process_tok(fstring tok)
 /****************************************************************************
 help
 ****************************************************************************/
 /****************************************************************************
 help
 ****************************************************************************/
-static int cmd_help(const char **cmd_ptr)
+static int cmd_help(struct smbclient_context *ctx, const char **args)
 {
        int i=0,j;
 {
        int i=0,j;
-       fstring buf;
        
        
-       if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) {
-               if ((i = process_tok(buf)) >= 0)
+       if (args[1]) {
+               if ((i = process_tok(args[1])) >= 0)
                        d_printf("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description);
        } else {
                while (commands[i].description) {
                        d_printf("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description);
        } else {
                while (commands[i].description) {
@@ -2490,87 +2732,56 @@ static int cmd_help(const char **cmd_ptr)
        return 0;
 }
 
        return 0;
 }
 
+static int process_line(struct smbclient_context *ctx, const char *cline);
 /****************************************************************************
 process a -c command string
 ****************************************************************************/
 /****************************************************************************
 process a -c command string
 ****************************************************************************/
-static int process_command_string(char *cmd)
+static int process_command_string(struct smbclient_context *ctx, const char *cmd)
 {
 {
-       pstring line;
-       const char *ptr;
-       int rc = 0;
+       const char **lines;
+       int i, rc = 0;
 
 
-       /* establish the connection if not already */
-       
-       if (!cli) {
-               cli = do_connect(desthost, service);
-               if (!cli)
-                       return 0;
+       lines = str_list_make(NULL, cmd, ";");
+       for (i = 0; lines[i]; i++) {
+               rc |= process_line(ctx, lines[i]);
        }
        }
-       
-       while (cmd[0] != '\0')    {
-               char *p;
-               fstring tok;
-               int i;
-               
-               if ((p = strchr_m(cmd, ';')) == 0) {
-                       strncpy(line, cmd, 999);
-                       line[1000] = '\0';
-                       cmd += strlen(cmd);
-               } else {
-                       if (p - cmd > 999) p = cmd + 999;
-                       strncpy(line, cmd, p - cmd);
-                       line[p - cmd] = '\0';
-                       cmd = p + 1;
-               }
-               
-               /* and get the first part of the command */
-               ptr = line;
-               if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
-               
-               if ((i = process_tok(tok)) >= 0) {
-                       rc = commands[i].fn(&ptr);
-               } else if (i == -2) {
-                       d_printf("%s: command abbreviation ambiguous\n",tok);
-               } else {
-                       d_printf("%s: command not found\n",tok);
-               }
-       }
-       
+       talloc_free(lines);
+
        return rc;
 }      
 
 #define MAX_COMPLETIONS 100
 
 typedef struct {
        return rc;
 }      
 
 #define MAX_COMPLETIONS 100
 
 typedef struct {
-       pstring dirmask;
+       char *dirmask;
        char **matches;
        int count, samelen;
        const char *text;
        int len;
 } completion_remote_t;
 
        char **matches;
        int count, samelen;
        const char *text;
        int len;
 } completion_remote_t;
 
-static void completion_remote_filter(struct file_info *f, const char *mask, void *state)
+static void completion_remote_filter(struct clilist_file_info *f, const char *mask, void *state)
 {
        completion_remote_t *info = (completion_remote_t *)state;
 
 {
        completion_remote_t *info = (completion_remote_t *)state;
 
-       if ((info->count < MAX_COMPLETIONS - 1) && (strncmp(info->text, f->name, info->len) == 0) && (strcmp(f->name, ".") != 0) && (strcmp(f->name, "..") != 0)) {
-               if ((info->dirmask[0] == 0) && !(f->mode & FILE_ATTRIBUTE_DIRECTORY))
+       if ((info->count < MAX_COMPLETIONS - 1) && (strncmp(info->text, f->name, info->len) == 0) && (!ISDOT(f->name)) && (!ISDOTDOT(f->name))) {
+               if ((info->dirmask[0] == 0) && !(f->attrib & FILE_ATTRIBUTE_DIRECTORY))
                        info->matches[info->count] = strdup(f->name);
                else {
                        info->matches[info->count] = strdup(f->name);
                else {
-                       pstring tmp;
+                       char *tmp;
 
                        if (info->dirmask[0] != 0)
 
                        if (info->dirmask[0] != 0)
-                               pstrcpy(tmp, info->dirmask);
+                               tmp = talloc_asprintf(NULL, "%s/%s", info->dirmask, f->name);
                        else
                        else
-                               tmp[0] = 0;
-                       pstrcat(tmp, f->name);
-                       if (f->mode & FILE_ATTRIBUTE_DIRECTORY)
-                               pstrcat(tmp, "/");
-                       info->matches[info->count] = strdup(tmp);
+                               tmp = talloc_strdup(NULL, f->name);
+                       
+                       if (f->attrib & FILE_ATTRIBUTE_DIRECTORY)
+                               tmp = talloc_append_string(NULL, tmp, "/");
+                       info->matches[info->count] = tmp;
                }
                if (info->matches[info->count] == NULL)
                        return;
                }
                if (info->matches[info->count] == NULL)
                        return;
-               if (f->mode & FILE_ATTRIBUTE_DIRECTORY)
+               if (f->attrib & FILE_ATTRIBUTE_DIRECTORY)
                        smb_readline_ca_char(0);
 
                if (info->count == 1)
                        smb_readline_ca_char(0);
 
                if (info->count == 1)
@@ -2584,9 +2795,9 @@ static void completion_remote_filter(struct file_info *f, const char *mask, void
 
 static char **remote_completion(const char *text, int len)
 {
 
 static char **remote_completion(const char *text, int len)
 {
-       pstring dirmask;
+       char *dirmask;
        int i;
        int i;
-       completion_remote_t info = { "", NULL, 1, 0, NULL, 0 };
+       completion_remote_t info;
 
        info.samelen = len;
        info.text = text;
 
        info.samelen = len;
        info.text = text;
@@ -2595,7 +2806,7 @@ static char **remote_completion(const char *text, int len)
        if (len >= PATH_MAX)
                return(NULL);
 
        if (len >= PATH_MAX)
                return(NULL);
 
-       info.matches = (char **)malloc(sizeof(info.matches[0])*MAX_COMPLETIONS);
+       info.matches = malloc_array_p(char *, MAX_COMPLETIONS);
        if (!info.matches) return NULL;
        info.matches[0] = NULL;
 
        if (!info.matches) return NULL;
        info.matches[0] = NULL;
 
@@ -2606,13 +2817,13 @@ static char **remote_completion(const char *text, int len)
        info.samelen = info.len = len-i-1;
 
        if (i > 0) {
        info.samelen = info.len = len-i-1;
 
        if (i > 0) {
-               strncpy(info.dirmask, text, i+1);
+               info.dirmask = talloc_strndup(NULL, text, i+1);
                info.dirmask[i+1] = 0;
                info.dirmask[i+1] = 0;
-               snprintf(dirmask, sizeof(dirmask), "%s%*s*", cur_dir, i-1, text);
+               asprintf(&dirmask, "%s%*s*", rl_ctx->remote_cur_dir, i-1, text);
        } else
        } else
-               snprintf(dirmask, sizeof(dirmask), "%s*", cur_dir);
+               asprintf(&dirmask, "%s*", rl_ctx->remote_cur_dir);
 
 
-       if (smbcli_list(cli->tree, dirmask, 
+       if (smbcli_list(rl_ctx->cli->tree, dirmask, 
                     FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 
                     completion_remote_filter, &info) < 0)
                goto cleanup;
                     FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 
                     completion_remote_filter, &info) < 0)
                goto cleanup;
@@ -2673,9 +2884,9 @@ static char **completion_fn(const char *text, int start, int end)
                        return NULL;
        } else {
                char **matches;
                        return NULL;
        } else {
                char **matches;
-               int i, len, samelen, count=1;
+               int i, len, samelen = 0, count=1;
 
 
-               matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS);
+               matches = malloc_array_p(char *, MAX_COMPLETIONS);
                if (!matches) return NULL;
                matches[0] = NULL;
 
                if (!matches) return NULL;
                matches[0] = NULL;
 
@@ -2712,9 +2923,10 @@ static char **completion_fn(const char *text, int start, int end)
                return matches;
 
 cleanup:
                return matches;
 
 cleanup:
-               while (i >= 0) {
-                       free(matches[i]);
-                       i--;
+               count--;
+               while (count >= 0) {
+                       free(matches[count]);
+                       count--;
                }
                free(matches);
                return NULL;
                }
                free(matches);
                return NULL;
@@ -2735,218 +2947,127 @@ static void readline_callback(void)
 
        last_t = t;
 
 
        last_t = t;
 
-       smbcli_transport_process(cli->transport);
+       smbcli_transport_process(rl_ctx->cli->transport);
 
 
-       if (cli->tree) {
-               smbcli_chkpath(cli->tree, "\\");
+       if (rl_ctx->cli->tree) {
+               smbcli_chkpath(rl_ctx->cli->tree, "\\");
        }
 }
 
        }
 }
 
+static int process_line(struct smbclient_context *ctx, const char *cline)
+{
+       const char **args;
+       int i;
+
+       /* and get the first part of the command */
+       args = str_list_make_shell(ctx, cline, NULL);
+       if (!args || !args[0])
+               return 0;
+
+       if ((i = process_tok(args[0])) >= 0) {
+               i = commands[i].fn(ctx, args);
+       } else if (i == -2) {
+               d_printf("%s: command abbreviation ambiguous\n",args[0]);
+       } else {
+               d_printf("%s: command not found\n",args[0]);
+       }
+
+       talloc_free(args);
+
+       return i;
+}
 
 /****************************************************************************
 process commands on stdin
 ****************************************************************************/
 
 /****************************************************************************
 process commands on stdin
 ****************************************************************************/
-static void process_stdin(void)
+static int process_stdin(struct smbclient_context *ctx)
 {
 {
+       int rc = 0;
        while (1) {
        while (1) {
-               fstring tok;
-               fstring the_prompt;
-               char *cline;
-               pstring line;
-               const char *ptr;
-               int i;
-               
                /* display a prompt */
                /* display a prompt */
-               slprintf(the_prompt, sizeof(the_prompt)-1, "smb: %s> ", cur_dir);
-               cline = smb_readline(the_prompt, readline_callback, completion_fn);
+               char *the_prompt = talloc_asprintf(ctx, "smb: %s> ", ctx->remote_cur_dir);
+               char *cline = smb_readline(the_prompt, readline_callback, completion_fn);
+               talloc_free(the_prompt);
                        
                if (!cline) break;
                
                        
                if (!cline) break;
                
-               pstrcpy(line, cline);
-
                /* special case - first char is ! */
                /* special case - first char is ! */
-               if (*line == '!') {
-                       system(line + 1);
+               if (*cline == '!') {
+                       system(cline + 1);
                        continue;
                }
                        continue;
                }
-      
-               /* and get the first part of the command */
-               ptr = line;
-               if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
-
-               if ((i = process_tok(tok)) >= 0) {
-                       commands[i].fn(&ptr);
-               } else if (i == -2) {
-                       d_printf("%s: command abbreviation ambiguous\n",tok);
-               } else {
-                       d_printf("%s: command not found\n",tok);
-               }
+
+               rc |= process_command_string(ctx, cline); 
        }
        }
+
+       return rc;
 }
 
 
 /***************************************************** 
 return a connection to a server
 *******************************************************/
 }
 
 
 /***************************************************** 
 return a connection to a server
 *******************************************************/
-static struct smbcli_state *do_connect(const char *server, const char *share)
+static struct smbclient_context *do_connect(TALLOC_CTX *mem_ctx, 
+                                      const char *specified_server, const char *specified_share, struct cli_credentials *cred)
 {
 {
-       struct smbcli_state *c;
-       struct nmb_name called, calling;
-       const char *server_n;
-       fstring servicename;
-       char *sharename;
        NTSTATUS status;
        NTSTATUS status;
-       
-       /* make a copy so we don't modify the global string 'service' */
-       fstrcpy(servicename, share);
-       sharename = servicename;
-       if (*sharename == '\\') {
-               server = sharename+2;
-               sharename = strchr_m(server,'\\');
-               if (!sharename) return NULL;
-               *sharename = 0;
-               sharename++;
-       }
-
-       asprintf(&sharename, "\\\\%s\\%s", server, sharename);
+       struct smbclient_context *ctx = talloc_zero(mem_ctx, struct smbclient_context);
+       char *server, *share;
 
 
-       server_n = dest_ip?dest_ip:server;
-       
-       make_nmb_name(&calling, lp_netbios_name(), 0x0);
-       choose_called_name(&called, server, name_type);
-
- again:
-       /* have to open a new connection */
-       if (!(c=smbcli_state_init(NULL)) || !smbcli_socket_connect(c, server_n)) {
-               d_printf("Connection to %s failed\n", server_n);
+       if (!ctx) {
                return NULL;
        }
 
                return NULL;
        }
 
-       if (!smbcli_transport_establish(c, &calling, &called)) {
-               char *p;
-               d_printf("session request to %s failed\n", 
-                        called.name);
-               smbcli_shutdown(c);
-               if ((p=strchr_m(called.name, '.'))) {
-                       *p = 0;
-                       goto again;
-               }
-               if (strcmp(called.name, "*SMBSERVER")) {
-                       make_nmb_name(&called , "*SMBSERVER", 0x20);
-                       goto again;
-               }
-               return NULL;
-       }
-
-       DEBUG(4,(" session request ok\n"));
-
-       if (NT_STATUS_IS_ERR(smbcli_negprot(c))) {
-               d_printf("protocol negotiation failed\n");
-               smbcli_shutdown(c);
-               return NULL;
-       }
+       rl_ctx = ctx; /* Ugly hack */
 
 
-       status = smbcli_session_setup(c, username, password, domain);
-       if (NT_STATUS_IS_ERR(status)) {
-               d_printf("authenticated session setup failed: %s\n", nt_errstr(status));
-               /* if a password was not supplied then try again with a null username */
-               if (password[0] || !username[0]) {
-                       status = smbcli_session_setup(c, "", "", lp_workgroup());
-               }
-               if (NT_STATUS_IS_ERR(status)) {
-                       d_printf("session setup failed: %s\n", nt_errstr(status));
-                       smbcli_shutdown(c);
-                       return NULL;
-               }
-               d_printf("Anonymous login successful\n");
+       if (strncmp(specified_share, "\\\\", 2) == 0 ||
+           strncmp(specified_share, "//", 2) == 0) {
+               smbcli_parse_unc(specified_share, ctx, &server, &share);
+       } else {
+               share = talloc_strdup(ctx, specified_share);
+               server = talloc_strdup(ctx, specified_server);
        }
 
        }
 
-       DEBUG(4,(" session setup ok\n"));
-
-       if (NT_STATUS_IS_ERR(smbcli_send_tconX(c, sharename, "?????", password))) {
-               d_printf("tree connect failed: %s\n", smbcli_errstr(c->tree));
-               smbcli_shutdown(c);
+       ctx->remote_cur_dir = talloc_strdup(ctx, "\\");
+       
+       status = smbcli_full_connection(ctx, &ctx->cli, server,
+                                       share, NULL, cred, 
+                                       cli_credentials_get_event_context(cred));
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("Connection to \\\\%s\\%s failed - %s\n", 
+                        server, share, nt_errstr(status));
+               talloc_free(ctx);
                return NULL;
        }
 
                return NULL;
        }
 
-       DEBUG(4,(" tconx ok\n"));
-
-       return c;
-}
-
-
-/****************************************************************************
-  process commands from the client
-****************************************************************************/
-static int process(char *base_directory)
-{
-       int rc = 0;
-
-       cli = do_connect(desthost, service);
-       if (!cli) {
-               return 1;
-       }
-
-       if (*base_directory) do_cd(base_directory);
-       
-       if (cmdstr) {
-               rc = process_command_string(cmdstr);
-       } else {
-               process_stdin();
-       }
-  
-       smbcli_shutdown(cli);
-       return rc;
+       return ctx;
 }
 
 /****************************************************************************
 handle a -L query
 ****************************************************************************/
 }
 
 /****************************************************************************
 handle a -L query
 ****************************************************************************/
-static int do_host_query(char *query_host)
+static int do_host_query(const char *query_host, const char *workgroup)
 {
        browse_host(query_host);
 {
        browse_host(query_host);
-       list_servers(lp_workgroup());
+       list_servers(workgroup);
        return(0);
 }
 
 
        return(0);
 }
 
 
-/****************************************************************************
-handle a tar operation
-****************************************************************************/
-static int do_tar_op(char *base_directory)
-{
-       int ret;
-
-       /* do we already have a connection? */
-       if (!cli) {
-               cli = do_connect(desthost, service);    
-               if (!cli)
-                       return 1;
-       }
-
-       recurse=True;
-
-       if (*base_directory) do_cd(base_directory);
-       
-       ret=process_tar();
-
-       smbcli_shutdown(cli);
-
-       return(ret);
-}
-
 /****************************************************************************
 handle a message operation
 ****************************************************************************/
 /****************************************************************************
 handle a message operation
 ****************************************************************************/
-static int do_message_op(void)
+static int do_message_op(const char *desthost, const char *destip, int name_type)
 {
 {
-       struct nmb_name called, calling;
+       struct nbt_name called, calling;
        const char *server_name;
        const char *server_name;
+       struct smbcli_state *cli;
 
 
-       make_nmb_name(&calling, lp_netbios_name(), 0x0);
-       choose_called_name(&called, desthost, name_type);
+       make_nbt_name_client(&calling, lp_netbios_name());
 
 
-       server_name = dest_ip ? dest_ip : desthost;
+       nbt_choose_called_name(NULL, &called, desthost, name_type);
+
+       server_name = destip ? destip : desthost;
 
        if (!(cli=smbcli_state_init(NULL)) || !smbcli_socket_connect(cli, server_name)) {
                d_printf("Connection to %s failed\n", server_name);
 
        if (!(cli=smbcli_state_init(NULL)) || !smbcli_socket_connect(cli, server_name)) {
                d_printf("Connection to %s failed\n", server_name);
@@ -2955,53 +3076,43 @@ static int do_message_op(void)
 
        if (!smbcli_transport_establish(cli, &calling, &called)) {
                d_printf("session request failed\n");
 
        if (!smbcli_transport_establish(cli, &calling, &called)) {
                d_printf("session request failed\n");
-               smbcli_shutdown(cli);
+               talloc_free(cli);
                return 1;
        }
 
                return 1;
        }
 
-       send_message();
-       smbcli_shutdown(cli);
+       send_message(cli, desthost);
+       talloc_free(cli);
 
        return 0;
 }
 
 
 
        return 0;
 }
 
 
-/**
- * Process "-L hostname" option.
- *
- * We don't actually do anything yet -- we just stash the name in a
- * global variable and do the query when all options have been read.
- **/
-static void remember_query_host(const char *arg,
-                               pstring query_host)
-{
-       char *slash;
-       
-       while (*arg == '\\' || *arg == '/')
-               arg++;
-       pstrcpy(query_host, arg);
-       if ((slash = strchr(query_host, '/'))
-           || (slash = strchr(query_host, '\\'))) {
-               *slash = 0;
-       }
-}
-
-
 /****************************************************************************
   main program
 ****************************************************************************/
  int main(int argc,char *argv[])
 {
 /****************************************************************************
   main program
 ****************************************************************************/
  int main(int argc,char *argv[])
 {
-       fstring base_directory;
+       const char *base_directory = NULL;
+       const char *dest_ip = NULL;
        int opt;
        int opt;
-       pstring query_host;
+       const char *query_host = NULL;
        BOOL message = False;
        BOOL message = False;
-       extern char tar_type;
-       pstring term_code;
+       const char *desthost = NULL;
+#ifdef KANJI
+       const char *term_code = KANJI;
+#else
+       const char *term_code = "";
+#endif /* KANJI */
        poptContext pc;
        poptContext pc;
+       const char *service = NULL;
+       int port = 0;
        char *p;
        int rc = 0;
        char *p;
        int rc = 0;
+       int name_type = 0x20;
        TALLOC_CTX *mem_ctx;
        TALLOC_CTX *mem_ctx;
+       struct smbclient_context *ctx;
+       const char *cmdstr = NULL;
+
        struct poptOption long_options[] = {
                POPT_AUTOHELP
 
        struct poptOption long_options[] = {
                POPT_AUTOHELP
 
@@ -3010,7 +3121,6 @@ static void remember_query_host(const char *arg,
                { "stderr", 'E', POPT_ARG_NONE, NULL, 'E', "Write messages to stderr instead of stdout" },
                { "list", 'L', POPT_ARG_STRING, NULL, 'L', "Get a list of shares available on a host", "HOST" },
                { "terminal", 't', POPT_ARG_STRING, NULL, 't', "Terminal I/O code {sjis|euc|jis7|jis8|junet|hex}", "CODE" },
                { "stderr", 'E', POPT_ARG_NONE, NULL, 'E', "Write messages to stderr instead of stdout" },
                { "list", 'L', POPT_ARG_STRING, NULL, 'L', "Get a list of shares available on a host", "HOST" },
                { "terminal", 't', POPT_ARG_STRING, NULL, 't', "Terminal I/O code {sjis|euc|jis7|jis8|junet|hex}", "CODE" },
-               { "tar", 'T', POPT_ARG_STRING, NULL, 'T', "Command line tar", "<c|x>IXFqgbNan" },
                { "directory", 'D', POPT_ARG_STRING, NULL, 'D', "Start from directory", "DIR" },
                { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" }, 
                { "send-buffer", 'b', POPT_ARG_INT, NULL, 'b', "Changes the transmit/send buffer", "BYTES" },
                { "directory", 'D', POPT_ARG_STRING, NULL, 'D', "Start from directory", "DIR" },
                { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" }, 
                { "send-buffer", 'b', POPT_ARG_INT, NULL, 'b', "Changes the transmit/send buffer", "BYTES" },
@@ -3019,36 +3129,18 @@ static void remember_query_host(const char *arg,
                POPT_COMMON_CONNECTION
                POPT_COMMON_CREDENTIALS
                POPT_COMMON_VERSION
                POPT_COMMON_CONNECTION
                POPT_COMMON_CREDENTIALS
                POPT_COMMON_VERSION
-               POPT_TABLEEND
+               { NULL }
        };
        
        };
        
-
-#ifdef KANJI
-       pstrcpy(term_code, KANJI);
-#else /* KANJI */
-       *term_code = 0;
-#endif /* KANJI */
-
-       *query_host = 0;
-       *base_directory = 0;
-
-       setup_logging(argv[0],DEBUG_STDOUT);
        mem_ctx = talloc_init("client.c/main");
        if (!mem_ctx) {
                d_printf("\nclient.c: Not enough memory\n");
                exit(1);
        }
 
        mem_ctx = talloc_init("client.c/main");
        if (!mem_ctx) {
                d_printf("\nclient.c: Not enough memory\n");
                exit(1);
        }
 
-       if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
-               fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n",
-                       argv[0], dyn_CONFIGFILE);
-       }
-       
        pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
        poptSetOtherOptionHelp(pc, "[OPTIONS] service <password>");
 
        pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
        poptSetOtherOptionHelp(pc, "[OPTIONS] service <password>");
 
-       in_client = True;   /* Make sure that we tell lp_load we are */
-
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case 'M':
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case 'M':
@@ -3057,31 +3149,21 @@ static void remember_query_host(const char *arg,
                         * to port 139 instead of port 445. srl,crh
                         */
                        name_type = 0x03; 
                         * to port 139 instead of port 445. srl,crh
                         */
                        name_type = 0x03; 
-                       pstrcpy(desthost,poptGetOptArg(pc));
+                       desthost = strdup(poptGetOptArg(pc));
                        if( 0 == port ) port = 139;
                        message = True;
                        break;
                case 'I':
                        dest_ip = poptGetOptArg(pc);
                        break;
                        if( 0 == port ) port = 139;
                        message = True;
                        break;
                case 'I':
                        dest_ip = poptGetOptArg(pc);
                        break;
-               case 'E':
-                       setup_logging("client", DEBUG_STDERR);
-                       break;
-
                case 'L':
                case 'L':
-                       remember_query_host(poptGetOptArg(pc), query_host);
+                       query_host = strdup(poptGetOptArg(pc));
                        break;
                case 't':
                        break;
                case 't':
-                       pstrcpy(term_code, poptGetOptArg(pc));
-                       break;
-               case 'T':
-                       if (!tar_parseargs(argc, argv, poptGetOptArg(pc), optind)) {
-                               poptPrintUsage(pc, stderr, 0);
-                               exit(1);
-                       }
+                       term_code = strdup(poptGetOptArg(pc));
                        break;
                case 'D':
                        break;
                case 'D':
-                       fstrcpy(base_directory,poptGetOptArg(pc));
+                       base_directory = strdup(poptGetOptArg(pc));
                        break;
                case 'b':
                        io_bufsize = MAX(1, atoi(poptGetOptArg(pc)));
                        break;
                case 'b':
                        io_bufsize = MAX(1, atoi(poptGetOptArg(pc)));
@@ -3089,63 +3171,67 @@ static void remember_query_host(const char *arg,
                }
        }
 
                }
        }
 
-       load_interfaces();
+       gensec_init();
 
        if(poptPeekArg(pc)) {
 
        if(poptPeekArg(pc)) {
-               pstrcpy(service,poptGetArg(pc));  
+               char *s = strdup(poptGetArg(pc)); 
+
                /* Convert any '/' characters in the service name to '\' characters */
                /* Convert any '/' characters in the service name to '\' characters */
-               string_replace(service, '/','\\');
+               string_replace(s, '/','\\');
+
+               service = s;
 
 
-               if (count_chars(service,'\\') < 3) {
-                       d_printf("\n%s: Not enough '\\' characters in service\n",service);
+               if (count_chars(s,'\\') < 3) {
+                       d_printf("\n%s: Not enough '\\' characters in service\n",s);
                        poptPrintUsage(pc, stderr, 0);
                        exit(1);
                }
        }
 
        if (poptPeekArg(pc)) { 
                        poptPrintUsage(pc, stderr, 0);
                        exit(1);
                }
        }
 
        if (poptPeekArg(pc)) { 
-               cmdline_set_userpassword(poptGetArg(pc));
+               cli_credentials_set_password(cmdline_credentials, poptGetArg(pc), CRED_SPECIFIED);
        }
 
        /*init_names(); */
 
        }
 
        /*init_names(); */
 
-       if (!tar_type && !*query_host && !*service && !message) {
+       if (!query_host && !service && !message) {
                poptPrintUsage(pc, stderr, 0);
                exit(1);
        }
 
        poptFreeContext(pc);
 
                poptPrintUsage(pc, stderr, 0);
                exit(1);
        }
 
        poptFreeContext(pc);
 
-       pstrcpy(username, cmdline_get_username());
-       pstrcpy(domain, cmdline_get_userdomain());
-       pstrcpy(password, cmdline_get_userpassword());
-
        DEBUG( 3, ( "Client started (version %s).\n", SAMBA_VERSION_STRING ) );
 
        DEBUG( 3, ( "Client started (version %s).\n", SAMBA_VERSION_STRING ) );
 
-       talloc_destroy(mem_ctx);
-       if (tar_type) {
-               if (cmdstr)
-                       process_command_string(cmdstr);
-               return do_tar_op(base_directory);
-       }
-
-       if ((p=strchr_m(query_host,'#'))) {
+       if (query_host && (p=strchr_m(query_host,'#'))) {
                *p = 0;
                p++;
                sscanf(p, "%x", &name_type);
        }
   
                *p = 0;
                p++;
                sscanf(p, "%x", &name_type);
        }
   
-       if (*query_host) {
-               return do_host_query(query_host);
+       if (query_host) {
+               return do_host_query(query_host, lp_workgroup());
        }
 
        if (message) {
        }
 
        if (message) {
-               return do_message_op();
+               return do_message_op(desthost, dest_ip, name_type);
        }
        
        }
        
-       if (process(base_directory)) {
+
+       ctx = do_connect(mem_ctx, desthost, service, cmdline_credentials);
+       if (!ctx)
                return 1;
                return 1;
+
+       if (base_directory) 
+               do_cd(ctx, base_directory);
+       
+       if (cmdstr) {
+               rc = process_command_string(ctx, cmdstr);
+       } else {
+               rc = process_stdin(ctx);
        }
        }
+  
+       talloc_free(mem_ctx);
 
        return rc;
 }
 
        return rc;
 }