Add context for libcli_resolve.
[samba-svnmirror.git] / source / client / client.c
index 2de071a195894e46b8c14feb5f4630a98a44036d..98b13aba4c8993d4e5bc816244f3f3681c551ea8 100644 (file)
@@ -8,7 +8,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+/* 
+ * TODO: remove this ... and don't use talloc_append_string()
+ *
+ * NOTE: I'm not changing the code yet, because I assume there're
+ *       some bugs in the existing code and I'm not sure how to fix
+ *      them correctly.
+ */
+#define TALLOC_DEPRECATED 1
+
 #include "includes.h"
 #include "version.h"
 #include "libcli/libcli.h"
 #include "libcli/security/security.h"
 #include "lib/smbreadline/smbreadline.h"
 #include "librpc/gen_ndr/ndr_nbt.h"
-
-static int io_bufsize = 64512;
+#include "param/param.h"
 
 struct smbclient_context {
        char *remote_cur_dir;
        struct smbcli_state *cli;
        char *fileselection;
        time_t newer_than;
-       BOOL prompt;
-       BOOL recurse;
+       bool prompt;
+       bool recurse;
        int archive_level;
-       BOOL lowercase;
+       bool lowercase;
        int printmode;
-       BOOL translation;
+       bool translation;
+       int io_bufsize;
 };
 
 /* timing globals */
@@ -72,7 +80,7 @@ static double dir_total;
 /*******************************************************************
  Reduce a file name, removing .. elements.
 ********************************************************************/
-void dos_clean_name(char *s)
+static void dos_clean_name(char *s)
 {
        char *p=NULL,*r;
 
@@ -96,9 +104,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.
 ****************************************************************************/
-static int writefile(int f, const void *_b, int n, BOOL translation)
+static int writefile(int f, const void *_b, int n, bool translation)
 {
-       const uint8_t *b = _b;
+       const uint8_t *b = (const uint8_t *)_b;
        int i;
 
        if (!translation) {
@@ -124,9 +132,9 @@ static int writefile(int f, const void *_b, int n, BOOL translation)
   read from a file with LF->CR/LF translation if appropriate. return the 
   number read. read approx n bytes.
 ****************************************************************************/
-static int readfile(void *_b, int n, XFILE *f, BOOL translation)
+static int readfile(void *_b, int n, XFILE *f, bool translation)
 {
-       uint8_t *b = _b;
+       uint8_t *b = (uint8_t *)_b;
        int i;
        int c;
 
@@ -281,16 +289,16 @@ static int cmd_cd(struct smbclient_context *ctx, const char **args)
 }
 
 
-BOOL mask_match(struct smbcli_state *c, const char *string, const char *pattern
-               BOOL is_case_sensitive)
+static bool mask_match(struct smbcli_state *c, const char *string
+               const char *pattern, bool is_case_sensitive)
 {
        char *p2, *s2;
-       BOOL ret;
+       bool ret;
 
        if (ISDOTDOT(string))
                string = ".";
        if (ISDOT(pattern))
-               return False;
+               return false;
        
        if (is_case_sensitive)
                return ms_fnmatch(pattern, string, 
@@ -310,27 +318,27 @@ BOOL mask_match(struct smbcli_state *c, const char *string, const char *pattern,
 /*******************************************************************
   decide if a file should be operated on
   ********************************************************************/
-static BOOL do_this_one(struct smbclient_context *ctx, struct clilist_file_info *finfo)
+static bool do_this_one(struct smbclient_context *ctx, struct clilist_file_info *finfo)
 {
-       if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) return(True);
+       if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) return(true);
 
        if (ctx->fileselection && 
-           !mask_match(ctx->cli, finfo->name,ctx->fileselection,False)) {
+           !mask_match(ctx->cli, finfo->name,ctx->fileselection,false)) {
                DEBUG(3,("mask_match %s failed\n", finfo->name));
-               return False;
+               return false;
        }
 
        if (ctx->newer_than && finfo->mtime < ctx->newer_than) {
                DEBUG(3,("newer_than %s failed\n", finfo->name));
-               return(False);
+               return(false);
        }
 
        if ((ctx->archive_level==1 || ctx->archive_level==2) && !(finfo->attrib & FILE_ATTRIBUTE_ARCHIVE)) {
                DEBUG(3,("archive %s failed\n", finfo->name));
-               return(False);
+               return(false);
        }
        
-       return(True);
+       return(true);
 }
 
 /****************************************************************************
@@ -362,8 +370,8 @@ static void do_du(struct smbclient_context *ctx, struct clilist_file_info *finfo
        }
 }
 
-static BOOL do_list_recurse;
-static BOOL do_list_dirs;
+static bool do_list_recurse;
+static bool do_list_dirs;
 static char *do_list_queue = 0;
 static long do_list_queue_size = 0;
 static long do_list_queue_start = 0;
@@ -397,7 +405,7 @@ static void init_do_list_queue(void)
 {
        reset_do_list_queue();
        do_list_queue_size = 1024;
-       do_list_queue = malloc(do_list_queue_size);
+       do_list_queue = malloc_array_p(char, do_list_queue_size);
        if (do_list_queue == 0) { 
                d_printf("malloc fail for size %d\n",
                         (int)do_list_queue_size);
@@ -491,7 +499,7 @@ a helper for do_list
   ****************************************************************************/
 static void do_list_helper(struct clilist_file_info *f, const char *mask, void *state)
 {
-       struct smbclient_context *ctx = state;
+       struct smbclient_context *ctx = (struct smbclient_context *)state;
 
        if (f->attrib & FILE_ATTRIBUTE_DIRECTORY) {
                if (do_list_dirs && do_this_one(ctx, f)) {
@@ -507,7 +515,7 @@ static void do_list_helper(struct clilist_file_info *f, const char *mask, void *
                        p = strrchr_m(mask2,'\\');
                        if (!p) return;
                        p[1] = 0;
-                       mask2 = talloc_asprintf_append(mask2, "%s\\*", f->name);
+                       mask2 = talloc_asprintf_append_buffer(mask2, "%s\\*", f->name);
                        add_to_do_list_queue(mask2);
                }
                return;
@@ -523,7 +531,7 @@ static void do_list_helper(struct clilist_file_info *f, const char *mask, void *
 a wrapper around smbcli_list that adds recursion
   ****************************************************************************/
 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)
+            void (*fn)(struct smbclient_context *, struct clilist_file_info *),bool rec, bool dirs)
 {
        static int in_do_list = 0;
 
@@ -619,7 +627,7 @@ static int cmd_dir(struct smbclient_context *ctx, const char **args)
                }
        }
 
-       do_list(ctx, mask, attribute, display_finfo, ctx->recurse, True);
+       do_list(ctx, mask, attribute, display_finfo, ctx->recurse, true);
 
        rc = do_dskattr(ctx);
 
@@ -650,7 +658,7 @@ static int cmd_du(struct smbclient_context *ctx, const char **args)
                mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir);
        }
 
-       do_list(ctx, mask, attribute, do_du, ctx->recurse, True);
+       do_list(ctx, mask, attribute, do_du, ctx->recurse, true);
 
        talloc_free(mask);
 
@@ -665,13 +673,13 @@ static int cmd_du(struct smbclient_context *ctx, const char **args)
 /****************************************************************************
   get a file from rname to lname
   ****************************************************************************/
-static int do_get(struct smbclient_context *ctx, 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;
+       bool newhandle = false;
        uint8_t *data;
        struct timeval tp_start;
-       int read_size = io_bufsize;
+       int read_size = ctx->io_bufsize;
        uint16_t attr;
        size_t size;
        off_t start = 0;
@@ -706,7 +714,7 @@ static int do_get(struct smbclient_context *ctx, char *rname, const char *lname,
                } else {
                        handle = open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
                }
-               newhandle = True;
+               newhandle = true;
        }
        if (handle < 0) {
                d_printf("Error opening local file %s\n",lname);
@@ -809,24 +817,24 @@ static int cmd_get(struct smbclient_context *ctx, const char **args)
        
        dos_clean_name(rname);
        
-       return do_get(ctx, rname, lname, False);
+       return do_get(ctx, rname, lname, false);
 }
 
 /****************************************************************************
  Put up a yes/no prompt.
 ****************************************************************************/
-static BOOL yesno(char *p)
+static bool yesno(char *p)
 {
        char ans[4];
        printf("%s",p);
 
        if (!fgets(ans,sizeof(ans)-1,stdin))
-               return(False);
+               return(false);
 
        if (*ans == 'y' || *ans == 'Y')
-               return(True);
+               return(true);
 
-       return(False);
+       return(false);
 }
 
 /****************************************************************************
@@ -853,7 +861,7 @@ static void do_mget(struct smbclient_context *ctx, struct clilist_file_info *fin
 
        if (!(finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)) {
                asprintf(&rname, "%s%s",ctx->remote_cur_dir,finfo->name);
-               do_get(ctx, rname, finfo->name, False);
+               do_get(ctx, rname, finfo->name, false);
                SAFE_FREE(rname);
                return;
        }
@@ -861,7 +869,7 @@ static void do_mget(struct smbclient_context *ctx, struct clilist_file_info *fin
        /* handle directories */
        saved_curdir = talloc_strdup(NULL, ctx->remote_cur_dir);
 
-       ctx->remote_cur_dir = talloc_asprintf_append(NULL, "%s\\", finfo->name);
+       ctx->remote_cur_dir = talloc_asprintf_append_buffer(NULL, "%s\\", finfo->name);
 
        string_replace(discard_const_p(char, finfo->name), '\\', '/');
        if (ctx->lowercase) {
@@ -881,7 +889,7 @@ static void do_mget(struct smbclient_context *ctx, struct clilist_file_info *fin
 
        mget_mask = talloc_asprintf(NULL, "%s*", ctx->remote_cur_dir);
        
-       do_list(ctx, 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("..");
        talloc_free(ctx->remote_cur_dir);
 
@@ -917,7 +925,7 @@ static int cmd_more(struct smbclient_context *ctx, const char **args)
        rname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
        dos_clean_name(rname);
 
-       rc = do_get(ctx, rname, lname, False);
+       rc = do_get(ctx, rname, lname, false);
 
        pager=getenv("PAGER");
 
@@ -950,14 +958,14 @@ static int cmd_mget(struct smbclient_context *ctx, const char **args)
                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);
+               do_list(ctx, mget_mask, attribute,do_mget,false,true);
 
                talloc_free(mget_mask);
        }
 
        if (mget_mask == NULL) {
                mget_mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir);
-               do_list(ctx, mget_mask, attribute,do_mget,False,True);
+               do_list(ctx, mget_mask, attribute,do_mget,false,true);
                talloc_free(mget_mask);
        }
        
@@ -1047,7 +1055,7 @@ static int cmd_altname(struct smbclient_context *ctx, const char **args)
        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);
+               return(false);
        }
        d_printf("%s\n", altname);
 
@@ -1058,14 +1066,14 @@ static int cmd_altname(struct smbclient_context *ctx, const char **args)
 /****************************************************************************
   put a single file
   ****************************************************************************/
-static int do_put(struct smbclient_context *ctx, 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;
        uint8_t *buf = NULL;
-       int maxwrite = io_bufsize;
+       int maxwrite = ctx->io_bufsize;
        int rc = 0;
        
        struct timeval tp_start;
@@ -1215,7 +1223,7 @@ static int cmd_put(struct smbclient_context *ctx, const char **args)
                return 1;
        }
 
-       return do_put(ctx, rname, lname, False);
+       return do_put(ctx, rname, lname, false);
 }
 
 /*************************************
@@ -1225,7 +1233,7 @@ static int cmd_put(struct smbclient_context *ctx, const char **args)
 static struct file_list {
        struct file_list *prev, *next;
        char *file_path;
-       BOOL isdir;
+       bool isdir;
 } *file_list;
 
 /****************************************************************************
@@ -1249,17 +1257,17 @@ static void free_file_list (struct file_list * list)
   seek in a directory/file list until you get something that doesn't start with
   the specified name
   ****************************************************************************/
-static BOOL seek_list(struct file_list *list, char *name)
+static bool seek_list(struct file_list *list, char *name)
 {
        while (list) {
                trim_string(list->file_path,"./","\n");
                if (strncmp(list->file_path, name, strlen(name)) != 0) {
-                       return(True);
+                       return(true);
                }
                list = list->next;
        }
       
-       return(False);
+       return(false);
 }
 
 /****************************************************************************
@@ -1312,17 +1320,17 @@ static const char *readdirname(DIR *p)
 
 /****************************************************************************
   Recursive file matching function act as find
-  match must be always set to True when calling this function
+  match must be always set to true when calling this function
 ****************************************************************************/
 static int file_find(struct smbclient_context *ctx, struct file_list **list, const char *directory, 
-                     const char *expression, BOOL match)
+                     const char *expression, bool match)
 {
        DIR *dir;
        struct file_list *entry;
         struct stat statbuf;
         int ret;
         char *path;
-       BOOL isdir;
+       bool isdir;
        const char *dname;
 
         dir = opendir(directory);
@@ -1337,14 +1345,14 @@ static int file_find(struct smbclient_context *ctx, struct file_list **list, con
                        continue;
                }
 
-               isdir = False;
+               isdir = false;
                if (!match || !gen_fnmatch(expression, dname)) {
                        if (ctx->recurse) {
                                ret = stat(path, &statbuf);
                                if (ret == 0) {
                                        if (S_ISDIR(statbuf.st_mode)) {
-                                               isdir = True;
-                                               ret = file_find(ctx, list, path, expression, False);
+                                               isdir = true;
+                                               ret = file_find(ctx, list, path, expression, false);
                                        }
                                } else {
                                        d_printf("file_find: cannot stat file %s\n", path);
@@ -1390,7 +1398,7 @@ static int cmd_mput(struct smbclient_context *ctx, const char **args)
        
                file_list = NULL;
 
-               ret = file_find(ctx, &file_list, ".", args[i], True);
+               ret = file_find(ctx, &file_list, ".", args[i], true);
                if (ret) {
                        free_file_list(file_list);
                        continue;
@@ -1446,7 +1454,7 @@ static int cmd_mput(struct smbclient_context *ctx, const char **args)
 
                        dos_format(rname);
 
-                       do_put(ctx, rname, lname, False);
+                       do_put(ctx, rname, lname, false);
                }
                free_file_list(file_list);
                SAFE_FREE(quest);
@@ -1483,7 +1491,7 @@ static int cmd_print(struct smbclient_context *ctx, const char **args)
                slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)getpid());
        }
 
-       return do_put(ctx, rname, lname, False);
+       return do_put(ctx, rname, lname, false);
 }
 
 
@@ -1726,6 +1734,7 @@ static int cmd_allinfo(struct smbclient_context *ctx, const char **args)
        char *fname;
        union smb_fileinfo finfo;
        NTSTATUS status;
+       int fnum;
 
        if (!args[1]) {
                d_printf("allinfo <filename>\n");
@@ -1809,6 +1818,41 @@ static int cmd_allinfo(struct smbclient_context *ctx, const char **args)
                d_printf("\tcluster_shift   %ld\n", (long)finfo.compression_info.out.cluster_shift);
        }
 
+       /* 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;
 }
 
@@ -2425,7 +2469,7 @@ static int cmd_reget(struct smbclient_context *ctx, const char **args)
        else
                local_name = talloc_strdup(ctx, args[1]);
        
-       return do_get(ctx, remote_name, local_name, True);
+       return do_get(ctx, remote_name, local_name, true);
 }
 
 /****************************************************************************
@@ -2454,7 +2498,7 @@ static int cmd_reput(struct smbclient_context *ctx, const char **args)
        
        dos_clean_name(remote_name);
 
-       return do_put(ctx, remote_name, local_name, True);
+       return do_put(ctx, remote_name, local_name, true);
 }
 
 
@@ -2500,7 +2544,7 @@ static void display_share_result(struct srvsvc_NetShareCtr1 *ctr1)
 /****************************************************************************
 try and browse available shares on a host
 ****************************************************************************/
-static BOOL browse_host(const char *query_host)
+static bool browse_host(struct loadparm_context *lp_ctx, const char *query_host)
 {
        struct dcerpc_pipe *p;
        char *binding;
@@ -2513,13 +2557,14 @@ static BOOL browse_host(const char *query_host)
        binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", query_host);
 
        status = dcerpc_pipe_connect(mem_ctx, &p, binding, 
-                                        &dcerpc_table_srvsvc,
-                                    cmdline_credentials, NULL);
+                                        &ndr_table_srvsvc,
+                                    cmdline_credentials, NULL,
+                                    lp_ctx);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("Failed to connect to %s - %s\n", 
                         binding, nt_errstr(status));
                talloc_free(mem_ctx);
-               return False;
+               return false;
        }
 
        r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
@@ -2549,19 +2594,19 @@ static BOOL browse_host(const char *query_host)
        if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
                d_printf("Failed NetShareEnumAll %s - %s/%s\n", 
                         binding, nt_errstr(status), win_errstr(r.out.result));
-               return False;
+               return false;
        }
 
-       return False;
+       return false;
 }
 
 /****************************************************************************
 try and browse available connections on a host
 ****************************************************************************/
-static BOOL list_servers(const char *wk_grp)
+static bool list_servers(const char *wk_grp)
 {
        d_printf("REWRITE: list servers not implemented\n");
-       return False;
+       return false;
 }
 
 /* Some constants for completing filename arguments */
@@ -2795,7 +2840,7 @@ static char **remote_completion(const char *text, int len)
        if (info.count == 2)
                info.matches[0] = strdup(info.matches[1]);
        else {
-               info.matches[0] = malloc(info.samelen+1);
+               info.matches[0] = malloc_array_p(char, info.samelen+1);
                if (!info.matches[0])
                        goto cleanup;
                strncpy(info.matches[0], info.matches[1], info.samelen);
@@ -2877,7 +2922,7 @@ static char **completion_fn(const char *text, int start, int end)
                        matches[0] = strdup(matches[1]);
                        break;
                default:
-                       matches[0] = malloc(samelen+1);
+                       matches[0] = malloc_array_p(char, samelen+1);
                        if (!matches[0])
                                goto cleanup;
                        strncpy(matches[0], matches[1], samelen);
@@ -2887,9 +2932,10 @@ static char **completion_fn(const char *text, int start, int end)
                return matches;
 
 cleanup:
-               while (i >= 0) {
-                       free(matches[i]);
-                       i--;
+               count--;
+               while (count >= 0) {
+                       free(matches[count]);
+                       count--;
                }
                free(matches);
                return NULL;
@@ -2970,17 +3016,12 @@ static int process_stdin(struct smbclient_context *ctx)
 /***************************************************** 
 return a connection to a server
 *******************************************************/
-static struct smbclient_context *do_connect(TALLOC_CTX *mem_ctx, 
+static bool do_connect(struct smbclient_context *ctx,
                                       const char *specified_server, const char *specified_share, struct cli_credentials *cred)
 {
        NTSTATUS status;
-       struct smbclient_context *ctx = talloc_zero(mem_ctx, struct smbclient_context);
        char *server, *share;
 
-       if (!ctx) {
-               return NULL;
-       }
-
        rl_ctx = ctx; /* Ugly hack */
 
        if (strncmp(specified_share, "\\\\", 2) == 0 ||
@@ -3009,10 +3050,10 @@ static struct smbclient_context *do_connect(TALLOC_CTX *mem_ctx,
 /****************************************************************************
 handle a -L query
 ****************************************************************************/
-static int do_host_query(const char *query_host)
+static int do_host_query(struct loadparm_context *lp_ctx, const char *query_host, const char *workgroup)
 {
-       browse_host(query_host);
-       list_servers(lp_workgroup());
+       browse_host(lp_ctx, query_host);
+       list_servers(workgroup);
        return(0);
 }
 
@@ -3020,19 +3061,19 @@ static int do_host_query(const char *query_host)
 /****************************************************************************
 handle a message operation
 ****************************************************************************/
-static int do_message_op(const char *desthost, const char *destip, int name_type)
+static int do_message_op(const char *netbios_name, const char *desthost, const char *destip, int name_type, struct resolve_context *resolve_ctx, int max_xmit, int max_mux)
 {
        struct nbt_name called, calling;
        const char *server_name;
        struct smbcli_state *cli;
 
-       make_nbt_name_client(&calling, lp_netbios_name());
+       make_nbt_name_client(&calling, netbios_name);
 
        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)) {
+       if (!(cli=smbcli_state_init(NULL)) || !smbcli_socket_connect(cli, server_name, resolve_ctx, max_xmit, max_mux)) {
                d_printf("Connection to %s failed\n", server_name);
                return 1;
        }
@@ -3059,7 +3100,7 @@ static int do_message_op(const char *desthost, const char *destip, int name_type
        const char *dest_ip = NULL;
        int opt;
        const char *query_host = NULL;
-       BOOL message = False;
+       bool message = false;
        const char *desthost = NULL;
 #ifdef KANJI
        const char *term_code = KANJI;
@@ -3101,6 +3142,9 @@ static int do_message_op(const char *desthost, const char *destip, int name_type
                exit(1);
        }
 
+       ctx = talloc(mem_ctx, struct smbclient_context);
+       ctx->io_bufsize = 64512;
+
        pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
        poptSetOtherOptionHelp(pc, "[OPTIONS] service <password>");
 
@@ -3114,7 +3158,7 @@ static int do_message_op(const char *desthost, const char *destip, int name_type
                        name_type = 0x03; 
                        desthost = strdup(poptGetOptArg(pc));
                        if( 0 == port ) port = 139;
-                       message = True;
+                       message = true;
                        break;
                case 'I':
                        dest_ip = poptGetOptArg(pc);
@@ -3129,12 +3173,12 @@ static int do_message_op(const char *desthost, const char *destip, int name_type
                        base_directory = strdup(poptGetOptArg(pc));
                        break;
                case 'b':
-                       io_bufsize = MAX(1, atoi(poptGetOptArg(pc)));
+                       ctx->io_bufsize = MAX(1, atoi(poptGetOptArg(pc)));
                        break;
                }
        }
 
-       gensec_init();
+       gensec_init(cmdline_lp_ctx);
 
        if(poptPeekArg(pc)) {
                char *s = strdup(poptGetArg(pc)); 
@@ -3173,16 +3217,14 @@ static int do_message_op(const char *desthost, const char *destip, int name_type
        }
   
        if (query_host) {
-               return do_host_query(query_host);
+               return do_host_query(cmdline_lp_ctx, query_host, lp_workgroup(cmdline_lp_ctx));
        }
 
        if (message) {
-               return do_message_op(desthost, dest_ip, name_type);
+               return do_message_op(lp_netbios_name(cmdline_lp_ctx), desthost, dest_ip, name_type, lp_resolve_context(cmdline_lp_ctx), lp_max_xmit(cmdline_lp_ctx), lp_maxmux(cmdline_lp_ctx));
        }
        
-
-       ctx = do_connect(mem_ctx, desthost, service, cmdline_credentials);
-       if (!ctx)
+       if (!do_connect(ctx, desthost, service, cmdline_credentials))
                return 1;
 
        if (base_directory)