s4: popt: Global replace of cmdline_credentials -> popt_get_cmdline_credentials().
[gd/samba-autobuild/.git] / source4 / client / client.c
index a61d1b4ca4ce564226a9a3cf76bb6dd659fcb5fb..9b2115acc31da7230285da616ab5a5dee641100b 100644 (file)
@@ -37,7 +37,6 @@
 #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/util/clilsa.h"
 #include "system/dir.h"
 #include "system/filesys.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 "../libcli/smbreadline/smbreadline.h"
 #include "librpc/gen_ndr/ndr_nbt.h"
 #include "param/param.h"
-#include "librpc/rpc/dcerpc.h"
+#include "libcli/raw/raw_proto.h"
+
+/* the default pager to use for the client "more" command. Users can
+ *    override this with the PAGER environment variable */
+#ifndef DEFAULT_PAGER
+#define DEFAULT_PAGER "more"
+#endif
 
 struct smbclient_context {
        char *remote_cur_dir;
@@ -69,9 +74,9 @@ struct smbclient_context {
 
 /* timing globals */
 static uint64_t get_total_size = 0;
-static uint_t get_total_time_ms = 0;
+static unsigned int get_total_time_ms = 0;
 static uint64_t put_total_size = 0;
-static uint_t put_total_time_ms = 0;
+static unsigned int 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; 
@@ -134,18 +139,18 @@ 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, FILE *f, bool translation)
 {
        uint8_t *b = (uint8_t *)_b;
        int i;
        int c;
 
        if (!translation)
-               return x_fread(b,1,n,f);
+               return fread(b,1,n,f);
   
        i = 0;
        while (i < (n - 1)) {
-               if ((c = x_getc(f)) == EOF) {
+               if ((c = getc(f)) == EOF) {
                        break;
                }
       
@@ -169,7 +174,11 @@ static void send_message(struct smbcli_state *cli, const char *desthost)
        int total_len = 0;
        int grp_id;
 
-       if (!smbcli_message_start(cli->tree, desthost, cli_credentials_get_username(cmdline_credentials), &grp_id)) {
+       if (!smbcli_message_start(cli->tree,
+                       desthost,
+                       cli_credentials_get_username(
+                               popt_get_cmdline_credentials()),
+                       &grp_id)) {
                d_printf("message start: %s\n", smbcli_errstr(cli->tree));
                return;
        }
@@ -257,9 +266,9 @@ static int do_cd(struct smbclient_context *ctx, const char *newdir)
        /* Save the current directory in case the
           new directory is invalid */
        if (newdir[0] == '\\')
-               dname = talloc_strdup(NULL, newdir);
+               dname = talloc_strdup(ctx, newdir);
        else
-               dname = talloc_asprintf(NULL, "%s\\%s", ctx->remote_cur_dir, newdir);
+               dname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, newdir);
 
        dos_format(dname);
 
@@ -297,25 +306,17 @@ static int cmd_cd(struct smbclient_context *ctx, const char **args)
 static bool mask_match(struct smbcli_state *c, const char *string, 
                const char *pattern, bool is_case_sensitive)
 {
-       char *p2, *s2;
-       bool ret;
+       int ret;
 
        if (ISDOTDOT(string))
                string = ".";
        if (ISDOT(pattern))
                return false;
-       
-       if (is_case_sensitive)
-               return ms_fnmatch(pattern, string, 
-                                 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;
+       ret = ms_fnmatch_protocol(pattern, string,
+                                 c->transport->negotiate.protocol,
+                                 is_case_sensitive);
+       return (ret == 0);
 }
 
 
@@ -449,7 +450,13 @@ static void adjust_do_list_queue(void)
 static void add_to_do_list_queue(const char* entry)
 {
        char *dlq;
-       long new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
+       long new_end;
+
+       if (entry == NULL) {
+               entry = "";
+       }
+
+       new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
        while (new_end > do_list_queue_size)
        {
                do_list_queue_size *= 2;
@@ -470,8 +477,8 @@ static void add_to_do_list_queue(const char* entry)
        }
        if (do_list_queue)
        {
-               safe_strcpy(do_list_queue + do_list_queue_end, entry, 
-                           do_list_queue_size - do_list_queue_end - 1);
+               strlcpy(do_list_queue + do_list_queue_end, entry,
+                           do_list_queue_size - do_list_queue_end);
                do_list_queue_end = new_end;
                DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n",
                         entry, (int)do_list_queue_start, (int)do_list_queue_end));
@@ -678,7 +685,7 @@ 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 *p_lname, bool reget)
 {  
        int handle = 0, fnum;
        bool newhandle = false;
@@ -690,11 +697,15 @@ static int do_get(struct smbclient_context *ctx, char *rname, const char *lname,
        off_t start = 0;
        off_t nread = 0;
        int rc = 0;
+       char *lname;
+
 
        GetTimeOfDay(&tp_start);
 
        if (ctx->lowercase) {
-               strlower(discard_const_p(char, lname));
+               lname = strlower_talloc(ctx, p_lname);
+       } else {
+               lname = talloc_strdup(ctx, p_lname);
        }
 
        fnum = smbcli_open(ctx->cli->tree, rname, O_RDONLY, DENY_NONE);
@@ -713,6 +724,7 @@ static int do_get(struct smbclient_context *ctx, char *rname, const char *lname,
                                start = lseek(handle, 0, SEEK_END);
                                if (start == -1) {
                                        d_printf("Error seeking local file\n");
+                                       close(handle);
                                        return 1;
                                }
                        }
@@ -732,6 +744,9 @@ static int do_get(struct smbclient_context *ctx, char *rname, const char *lname,
            NT_STATUS_IS_ERR(smbcli_getattrE(ctx->cli->tree, fnum, 
                          &attr, &size, NULL, NULL, NULL))) {
                d_printf("getattrib: %s\n",smbcli_errstr(ctx->cli->tree));
+               if (newhandle) {
+                       close(handle);
+               }
                return 1;
        }
 
@@ -741,6 +756,9 @@ static int do_get(struct smbclient_context *ctx, char *rname, const char *lname,
        if(!(data = (uint8_t *)malloc(read_size))) { 
                d_printf("malloc fail for size %d\n", read_size);
                smbcli_close(ctx->cli->tree, fnum);
+               if (newhandle) {
+                       close(handle);
+               }
                return 1;
        }
 
@@ -851,51 +869,61 @@ static void do_mget(struct smbclient_context *ctx, struct clilist_file_info *fin
        char *quest;
        char *mget_mask;
        char *saved_curdir;
+       char *l_fname;
+       int ret;
 
        if (ISDOT(finfo->name) || ISDOTDOT(finfo->name))
                return;
 
        if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)
-               asprintf(&quest, "Get directory %s? ",finfo->name);
+               quest = talloc_asprintf(ctx, "Get directory %s? ",finfo->name);
        else
-               asprintf(&quest, "Get file %s? ",finfo->name);
+               quest = talloc_asprintf(ctx, "Get file %s? ",finfo->name);
 
        if (ctx->prompt && !yesno(quest)) return;
 
-       SAFE_FREE(quest);
+       talloc_free(quest);
 
        if (!(finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)) {
-               asprintf(&rname, "%s%s",ctx->remote_cur_dir,finfo->name);
+               rname = talloc_asprintf(ctx, "%s%s",ctx->remote_cur_dir,
+                                       finfo->name);
                do_get(ctx, rname, finfo->name, false);
-               SAFE_FREE(rname);
+               talloc_free(rname);
                return;
        }
 
        /* handle directories */
-       saved_curdir = talloc_strdup(NULL, ctx->remote_cur_dir);
+       saved_curdir = talloc_strdup(ctx, ctx->remote_cur_dir);
 
        ctx->remote_cur_dir = talloc_asprintf_append_buffer(NULL, "%s\\", finfo->name);
 
-       string_replace(discard_const_p(char, finfo->name), '\\', '/');
        if (ctx->lowercase) {
-               strlower(discard_const_p(char, finfo->name));
+               l_fname = strlower_talloc(ctx, finfo->name);
+       } else {
+               l_fname = talloc_strdup(ctx, finfo->name);
        }
        
-       if (!directory_exist(finfo->name) && 
-           mkdir(finfo->name,0777) != 0) {
-               d_printf("failed to create directory %s\n",finfo->name);
+       string_replace(l_fname, '\\', '/');
+
+       if (!directory_exist(l_fname) &&
+           mkdir(l_fname, 0777) != 0) {
+               d_printf("failed to create directory %s\n", l_fname);
                return;
        }
        
-       if (chdir(finfo->name) != 0) {
-               d_printf("failed to chdir to directory %s\n",finfo->name);
+       if (chdir(l_fname) != 0) {
+               d_printf("failed to chdir to directory %s\n", l_fname);
                return;
        }
 
-       mget_mask = talloc_asprintf(NULL, "%s*", ctx->remote_cur_dir);
+       mget_mask = talloc_asprintf(ctx, "%s*", ctx->remote_cur_dir);
        
        do_list(ctx, mget_mask, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,do_mget,false, true);
-       chdir("..");
+       ret = chdir("..");
+       if (ret == -1) {
+               d_printf("failed to chdir to '..': %s\n", strerror(errno));
+               return;
+       }
        talloc_free(ctx->remote_cur_dir);
 
        ctx->remote_cur_dir = saved_curdir;
@@ -913,9 +941,12 @@ static int cmd_more(struct smbclient_context *ctx, const char **args)
        char *pager;
        int fd;
        int rc = 0;
+       mode_t mask;
 
        lname = talloc_asprintf(ctx, "%s/smbmore.XXXXXX",tmpdir());
+       mask = umask(S_IRWXO | S_IRWXG);
        fd = mkstemp(lname);
+       umask(mask);
        if (fd == -1) {
                d_printf("failed to create temporary file for more\n");
                return 1;
@@ -935,7 +966,11 @@ static int cmd_more(struct smbclient_context *ctx, const char **args)
        pager=getenv("PAGER");
 
        pager_cmd = talloc_asprintf(ctx, "%s %s",(pager? pager:DEFAULT_PAGER), lname);
-       system(pager_cmd);
+       rc = system(pager_cmd);
+       if (rc == -1) {
+               d_printf("failed to call pager command\n");
+               return 1;
+       }
        unlink(lname);
        
        return rc;
@@ -956,7 +991,7 @@ static int cmd_mget(struct smbclient_context *ctx, const char **args)
                attribute |= FILE_ATTRIBUTE_DIRECTORY;
        
        for (i = 1; args[i]; i++) {
-               mget_mask = talloc_strdup(ctx,ctx->remote_cur_dir);
+               mget_mask = talloc_strdup(ctx, ctx->remote_cur_dir);
                if(mget_mask[strlen(mget_mask)-1]!='\\')
                        mget_mask = talloc_append_string(ctx, mget_mask, "\\");
                
@@ -1047,7 +1082,8 @@ show 8.3 name of a file
 ****************************************************************************/
 static int cmd_altname(struct smbclient_context *ctx, const char **args)
 {
-       const char *altname;
+       const char *p;
+       char *altname;
        char *name;
   
        if (!args[1]) {
@@ -1057,13 +1093,16 @@ static int cmd_altname(struct smbclient_context *ctx, const char **args)
 
        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))) {
+       if (!NT_STATUS_IS_OK(smbcli_qpathinfo_alt_name(ctx->cli->tree, name, &p))) {
                d_printf("%s getting alt name for %s\n",
                         smbcli_errstr(ctx->cli->tree),name);
                return(false);
        }
+       altname = discard_const_p(char, p);
        d_printf("%s\n", altname);
 
+       SAFE_FREE(altname);
+
        return 0;
 }
 
@@ -1074,7 +1113,7 @@ static int cmd_altname(struct smbclient_context *ctx, const char **args)
 static int do_put(struct smbclient_context *ctx, char *rname, char *lname, bool reput)
 {
        int fnum;
-       XFILE *f;
+       FILE *f;
        size_t start = 0;
        off_t nread = 0;
        uint8_t *buf = NULL;
@@ -1109,13 +1148,14 @@ static int do_put(struct smbclient_context *ctx, char *rname, char *lname, bool
           Note that in this case this function will exit(0) rather
           than returning. */
        if (!strcmp(lname, "-")) {
-               f = x_stdin;
+               f = stdin;
                /* size of file is not known */
        } else {
-               f = x_fopen(lname,O_RDONLY, 0);
+               f = fopen(lname, "r");
                if (f && reput) {
-                       if (x_tseek(f, start, SEEK_SET) == -1) {
+                       if (fseek(f, start, SEEK_SET) == -1) {
                                d_printf("Error seeking local file\n");
+                               fclose(f);
                                return 1;
                        }
                }
@@ -1133,14 +1173,15 @@ static int do_put(struct smbclient_context *ctx, char *rname, char *lname, bool
        buf = (uint8_t *)malloc(maxwrite);
        if (!buf) {
                d_printf("ERROR: Not enough memory!\n");
+               fclose(f);
                return 1;
        }
-       while (!x_feof(f)) {
+       while (!feof(f)) {
                int n = maxwrite;
                int ret;
 
                if ((n = readfile(buf,n,f,ctx->translation)) < 1) {
-                       if((n == 0) && x_feof(f))
+                       if((n == 0) && feof(f))
                                break; /* Empty local file. */
 
                        d_printf("Error reading local file: %s\n", strerror(errno));
@@ -1161,14 +1202,14 @@ static int do_put(struct smbclient_context *ctx, char *rname, char *lname, bool
 
        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);
+               fclose(f);
                SAFE_FREE(buf);
                return 1;
        }
 
        
-       if (f != x_stdin) {
-               x_fclose(f);
+       if (f != stdin) {
+               fclose(f);
        }
 
        SAFE_FREE(buf);
@@ -1189,7 +1230,7 @@ static int do_put(struct smbclient_context *ctx, char *rname, char *lname, bool
                         put_total_size / (1.024*put_total_time_ms)));
        }
 
-       if (f == x_stdin) {
+       if (f == stdin) {
                talloc_free(ctx);
                exit(0);
        }
@@ -1214,10 +1255,14 @@ static int cmd_put(struct smbclient_context *ctx, const char **args)
 
        lname = talloc_strdup(ctx, args[1]);
   
-       if (args[2])
-               rname = talloc_strdup(ctx, args[2]);
-       else
+       if (args[2]) {
+               if (args[2][0]=='\\')
+                       rname = talloc_strdup(ctx, args[2]);
+               else
+                       rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[2]);
+       } else {
                rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, lname);
+       }
        
        dos_clean_name(rname);
 
@@ -1281,7 +1326,7 @@ static bool seek_list(struct file_list *list, char *name)
 static int cmd_select(struct smbclient_context *ctx, const char **args)
 {
        talloc_free(ctx->fileselection);
-       ctx->fileselection = talloc_strdup(NULL, args[1]);
+       ctx->fileselection = talloc_strdup(ctx, args[1]);
 
        return 0;
 }
@@ -1485,15 +1530,26 @@ static int cmd_print(struct smbclient_context *ctx, const char **args)
        }
 
        lname = talloc_strdup(ctx, args[1]);
+       if (lname == NULL) {
+               d_printf("Out of memory in cmd_print\n");
+               return 1;
+       }
 
-       rname = talloc_strdup(ctx, lname);
-       p = strrchr_m(rname,'/');
-       if (p) {
-               slprintf(rname, sizeof(rname)-1, "%s-%d", p+1, (int)getpid());
+       if (strequal(lname, "-")) {
+               rname = talloc_asprintf(ctx, "stdin-%d", (int)getpid());
+       } else {
+               p = strrchr_m(lname, '/');
+               if (p) {
+                       rname = talloc_asprintf(ctx, "%s-%d", p + 1,
+                                               (int)getpid());
+               } else {
+                       rname = talloc_strdup(ctx, lname);
+               }
        }
 
-       if (strequal(lname,"-")) {
-               slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)getpid());
+       if (rname == NULL) {
+               d_printf("Out of memory in cmd_print (stdin)\n");
+               return 1;
        }
 
        return do_put(ctx, rname, lname, false);
@@ -1522,7 +1578,7 @@ static int cmd_del(struct smbclient_context *ctx, const char **args)
                d_printf("del <filename>\n");
                return 1;
        }
-       mask = talloc_asprintf(ctx,"%s%s", ctx->remote_cur_dir, args[1]);
+       mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
 
        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);
@@ -1580,6 +1636,7 @@ fsinfo_level_t fsinfo_levels[] = {
        {"quota-information", RAW_QFS_QUOTA_INFORMATION},
        {"fullsize-information", RAW_QFS_FULL_SIZE_INFORMATION},
        {"objectid", RAW_QFS_OBJECTID_INFORMATION},
+       {"sector-size-info", RAW_QFS_SECTOR_SIZE_INFORMATION},
        {NULL, RAW_QFS_GENERIC}
 };
 
@@ -1723,6 +1780,22 @@ static int cmd_fsinfo(struct smbclient_context *ctx, const char **args)
                         (unsigned long long) fsinfo.objectid_information.out.unknown[4],
                         (unsigned long long) fsinfo.objectid_information.out.unknown[5] );
                break;
+       case RAW_QFS_SECTOR_SIZE_INFORMATION:
+               d_printf("\tlogical_bytes_per_sector:                   %u\n",
+                        (unsigned)fsinfo.sector_size_info.out.logical_bytes_per_sector);
+               d_printf("\tphys_bytes_per_sector_atomic:               %u\n",
+                        (unsigned)fsinfo.sector_size_info.out.phys_bytes_per_sector_atomic);
+               d_printf("\tphys_bytes_per_sector_perf:                 %u\n",
+                        (unsigned)fsinfo.sector_size_info.out.phys_bytes_per_sector_perf);
+               d_printf("\tfs_effective_phys_bytes_per_sector_atomic:  %u\n",
+                        (unsigned)fsinfo.sector_size_info.out.fs_effective_phys_bytes_per_sector_atomic);
+               d_printf("\tflags:                                      0x%x\n",
+                        (unsigned)fsinfo.sector_size_info.out.flags);
+               d_printf("\tbyte_off_sector_align:                      %u\n",
+                        (unsigned)fsinfo.sector_size_info.out.byte_off_sector_align);
+               d_printf("\tbyte_off_partition_align:                   %u\n",
+                        (unsigned)fsinfo.sector_size_info.out.byte_off_partition_align);
+               break;
        case RAW_QFS_GENERIC:
                d_printf("\twrong level returned\n");
                break;
@@ -2115,18 +2188,75 @@ static int cmd_delprivileges(struct smbclient_context *ctx, const char **args)
 
 
 /****************************************************************************
+open a file
 ****************************************************************************/
 static int cmd_open(struct smbclient_context *ctx, const char **args)
 {
-       char *mask;
-       
+       char *filename;
+       union smb_open io;
+       NTSTATUS status;
+       TALLOC_CTX *tmp_ctx;
+
        if (!args[1]) {
                d_printf("open <filename>\n");
                return 1;
        }
-       mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
+       tmp_ctx = talloc_new(ctx);
+
+       filename = talloc_asprintf(tmp_ctx, "%s%s", ctx->remote_cur_dir, args[1]);
+
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid.fnum = 0;
+       io.ntcreatex.in.flags = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = filename;
+
+       status = smb_raw_open(ctx->cli->tree, tmp_ctx, &io);
+       talloc_free(tmp_ctx);
+
+       if (NT_STATUS_IS_OK(status)) {
+               d_printf("Opened file with fnum %u\n", (unsigned)io.ntcreatex.out.file.fnum);
+       } else {
+               d_printf("Opened failed: %s\n", nt_errstr(status));
+       }
+
+       return 0;
+}
 
-       smbcli_open(ctx->cli->tree, mask, O_RDWR, DENY_ALL);
+/****************************************************************************
+close a file
+****************************************************************************/
+static int cmd_close(struct smbclient_context *ctx, const char **args)
+{
+       union smb_close io;
+       NTSTATUS status;
+       uint16_t fnum;
+
+       if (!args[1]) {
+               d_printf("close <fnum>\n");
+               return 1;
+       }
+
+       fnum = atoi(args[1]);
+
+       ZERO_STRUCT(io);
+       io.generic.level = RAW_CLOSE_CLOSE;
+       io.close.in.file.fnum = fnum;
+
+       status = smb_raw_close(ctx->cli->tree, &io);
+
+       if (NT_STATUS_IS_OK(status)) {
+               d_printf("Closed file OK\n");
+       } else {
+               d_printf("Close failed: %s\n", nt_errstr(status));
+       }
 
        return 0;
 }
@@ -2237,7 +2367,7 @@ static int cmd_chmod(struct smbclient_context *ctx, const char **args)
 
        if (NT_STATUS_IS_ERR(smbcli_unix_chmod(ctx->cli->tree, src, mode))) {
                d_printf("%s chmod file %s 0%o\n",
-                       smbcli_errstr(ctx->cli->tree), src, (mode_t)mode);
+                       smbcli_errstr(ctx->cli->tree), src, (unsigned)mode);
                return 1;
        } 
 
@@ -2426,8 +2556,17 @@ static int cmd_lcd(struct smbclient_context *ctx, const char **args)
 {
        char d[PATH_MAX];
        
-       if (args[1]) 
-               chdir(args[1]);
+       if (args[1]) {
+               int ret;
+
+               ret = chdir(args[1]);
+               if (ret == -1) {
+                       d_printf("failed to chdir to dir '%s': %s\n",
+                                args[1], strerror(errno));
+                       return 1;
+               }
+       }
+
        DEBUG(2,("the local directory is now %s\n",getcwd(d, PATH_MAX)));
 
        return 0;
@@ -2550,22 +2689,24 @@ static void display_share_result(struct srvsvc_NetShareCtr1 *ctr1)
 try and browse available shares on a host
 ****************************************************************************/
 static bool browse_host(struct loadparm_context *lp_ctx,
-                       struct event_context *ev_ctx,
+                       struct tevent_context *ev_ctx,
                        const char *query_host)
 {
        struct dcerpc_pipe *p;
        char *binding;
        NTSTATUS status;
        struct srvsvc_NetShareEnumAll r;
+       struct srvsvc_NetShareInfoCtr info_ctr;
        uint32_t resume_handle = 0;
        TALLOC_CTX *mem_ctx = talloc_init("browse_host");
        struct srvsvc_NetShareCtr1 ctr1;
+       uint32_t totalentries = 0;
 
        binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", query_host);
 
        status = dcerpc_pipe_connect(mem_ctx, &p, binding, 
                                         &ndr_table_srvsvc,
-                                    cmdline_credentials, ev_ctx,
+                                    popt_get_cmdline_credentials(), ev_ctx,
                                     lp_ctx);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("Failed to connect to %s - %s\n", 
@@ -2574,25 +2715,30 @@ static bool browse_host(struct loadparm_context *lp_ctx,
                return false;
        }
 
+       info_ctr.level = 1;
+       info_ctr.ctr.ctr1 = &ctr1;
+
        r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
-       r.in.level = 1;
-       r.in.ctr.ctr1 = &ctr1;
+       r.in.info_ctr = &info_ctr;
        r.in.max_buffer = ~0;
        r.in.resume_handle = &resume_handle;
+       r.out.resume_handle = &resume_handle;
+       r.out.totalentries = &totalentries;
+       r.out.info_ctr = &info_ctr;
 
        d_printf("\n\tSharename       Type       Comment\n");
        d_printf("\t---------       ----       -------\n");
 
        do {
                ZERO_STRUCT(ctr1);
-               status = dcerpc_srvsvc_NetShareEnumAll(p, mem_ctx, &r);
+               status = dcerpc_srvsvc_NetShareEnumAll_r(p->binding_handle, mem_ctx, &r);
 
                if (NT_STATUS_IS_OK(status) && 
                    (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA) ||
                     W_ERROR_IS_OK(r.out.result)) &&
-                   r.out.ctr.ctr1) {
-                       display_share_result(r.out.ctr.ctr1);
-                       resume_handle += r.out.ctr.ctr1->count;
+                   r.out.info_ctr->ctr.ctr1) {
+                       display_share_result(r.out.info_ctr->ctr.ctr1);
+                       resume_handle += r.out.info_ctr->ctr.ctr1->count;
                }
        } while (NT_STATUS_IS_OK(status) && W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
 
@@ -2671,6 +2817,7 @@ 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}},
+  {"close",cmd_close,"<fnum> close a file",{COMPL_NONE,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}},
@@ -2812,13 +2959,14 @@ static void completion_remote_filter(struct clilist_file_info *f, const char *ma
 static char **remote_completion(const char *text, int len)
 {
        char *dirmask;
-       int i;
+       int i, ret;
        completion_remote_t info;
 
        info.samelen = len;
        info.text = text;
        info.len = len;
+       info.count = 0;
+
        if (len >= PATH_MAX)
                return(NULL);
 
@@ -2835,9 +2983,14 @@ static char **remote_completion(const char *text, int len)
        if (i > 0) {
                info.dirmask = talloc_strndup(NULL, text, i+1);
                info.dirmask[i+1] = 0;
-               asprintf(&dirmask, "%s%*s*", rl_ctx->remote_cur_dir, i-1, text);
-       } else
-               asprintf(&dirmask, "%s*", rl_ctx->remote_cur_dir);
+               ret = asprintf(&dirmask, "%s%*s*", rl_ctx->remote_cur_dir, i-1,
+                              text);
+       } else {
+               ret = asprintf(&dirmask, "%s*", rl_ctx->remote_cur_dir);
+       }
+       if (ret < 0) {
+               goto cleanup;
+       }
 
        if (smbcli_list(rl_ctx->cli->tree, dirmask, 
                     FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 
@@ -2972,7 +3125,7 @@ static void readline_callback(void)
 
 static int process_line(struct smbclient_context *ctx, const char *cline)
 {
-       const char **args;
+       char **args;
        int i;
 
        /* and get the first part of the command */
@@ -2981,7 +3134,8 @@ static int process_line(struct smbclient_context *ctx, const char *cline)
                return 0;
 
        if ((i = process_tok(args[0])) >= 0) {
-               i = commands[i].fn(ctx, args);
+               const char **a = discard_const_p(const char *, args);
+               i = commands[i].fn(ctx, a);
        } else if (i == -2) {
                d_printf("%s: command abbreviation ambiguous\n",args[0]);
        } else {
@@ -3009,8 +3163,12 @@ static int process_stdin(struct smbclient_context *ctx)
 
                /* special case - first char is ! */
                if (*cline == '!') {
-                       system(cline + 1);
+                       int ret;
+                       ret = system(cline + 1);
                        free(cline);
+                       if (ret == -1) {
+                               rc |= ret;
+                       }
                        continue;
                }
 
@@ -3027,14 +3185,15 @@ static int process_stdin(struct smbclient_context *ctx)
 return a connection to a server
 *******************************************************/
 static bool do_connect(struct smbclient_context *ctx, 
-                      struct event_context *ev_ctx,
+                      struct tevent_context *ev_ctx,
                       struct resolve_context *resolve_ctx,
                       const char *specified_server, const char **ports, 
                       const char *specified_share, 
+                          const char *socket_options,
                       struct cli_credentials *cred, 
                       struct smbcli_options *options,
                       struct smbcli_session_options *session_options,
-                          struct smb_iconv_convenience *iconv_convenience)
+                          struct gensec_settings *gensec_settings)
 {
        NTSTATUS status;
        char *server, *share;
@@ -3043,33 +3202,51 @@ static bool do_connect(struct smbclient_context *ctx,
 
        if (strncmp(specified_share, "\\\\", 2) == 0 ||
            strncmp(specified_share, "//", 2) == 0) {
-               smbcli_parse_unc(specified_share, ctx, &server, &share);
+               bool ok;
+
+               ok = smbcli_parse_unc(specified_share, ctx, &server, &share);
+               if (!ok) {
+                       d_printf("Failed to parse UNC\n");
+                       talloc_free(ctx);
+                       return false;
+               }
        } else {
                share = talloc_strdup(ctx, specified_share);
                server = talloc_strdup(ctx, specified_server);
+               if (share == NULL || server == NULL) {
+                       d_printf("Failed to allocate memory for server and share\n");
+                       talloc_free(ctx);
+                       return false;
+               }
        }
 
        ctx->remote_cur_dir = talloc_strdup(ctx, "\\");
-       
+       if (ctx->remote_cur_dir == NULL) {
+               talloc_free(ctx);
+               return false;
+       }
+
        status = smbcli_full_connection(ctx, &ctx->cli, server, ports,
-                                       share, NULL, cred, resolve_ctx, 
+                                       share, NULL, 
+                                       socket_options,
+                                       cred, resolve_ctx, 
                                        ev_ctx, options, session_options,
-                                       iconv_convenience);
+                                       gensec_settings);
        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 false;
        }
 
-       return ctx;
+       return true;
 }
 
 /****************************************************************************
 handle a -L query
 ****************************************************************************/
 static int do_host_query(struct loadparm_context *lp_ctx,
-                        struct event_context *ev_ctx,
+                        struct tevent_context *ev_ctx,
                         const char *query_host,
                         const char *workgroup)
 {
@@ -3085,14 +3262,15 @@ handle a message operation
 static int do_message_op(const char *netbios_name, const char *desthost,
                         const char **destports, const char *destip,
                         int name_type,
-                        struct event_context *ev_ctx,
+                        struct tevent_context *ev_ctx,
                         struct resolve_context *resolve_ctx,
                         struct smbcli_options *options,
-                        struct smb_iconv_convenience *iconv_convenience)
+             const char *socket_options)
 {
        struct nbt_name called, calling;
        const char *server_name;
        struct smbcli_state *cli;
+       bool ok;
 
        make_nbt_name_client(&calling, netbios_name);
 
@@ -3100,17 +3278,18 @@ static int do_message_op(const char *netbios_name, const char *desthost,
 
        server_name = destip ? destip : desthost;
 
-       if (!(cli = smbcli_state_init(NULL)) ||
-           !smbcli_socket_connect(cli, server_name, destports,
-                                  ev_ctx, resolve_ctx, options,
-                                  iconv_convenience)) {
-               d_printf("Connection to %s failed\n", server_name);
+       cli = smbcli_state_init(NULL);
+       if (cli == NULL) {
+               d_printf("smbcli_state_init() failed\n");
                return 1;
        }
 
-       if (!smbcli_transport_establish(cli, &calling, &called)) {
-               d_printf("session request failed\n");
-               talloc_free(cli);
+       ok = smbcli_socket_connect(cli, server_name, destports,
+                                  ev_ctx, resolve_ctx, options,
+                                  socket_options,
+                                  &calling, &called);
+       if (!ok) {
+               d_printf("Connection to %s failed\n", server_name);
                return 1;
        }
 
@@ -3124,14 +3303,14 @@ static int do_message_op(const char *netbios_name, const char *desthost,
 /****************************************************************************
   main program
 ****************************************************************************/
- int main(int argc,char *argv[])
+ int main(int argc, const char *argv[])
 {
-       const char *base_directory = NULL;
+       char *base_directory = NULL;
        const char *dest_ip = NULL;
        int opt;
        const char *query_host = NULL;
        bool message = false;
-       const char *desthost = NULL;
+       char *desthost = NULL;
        poptContext pc;
        const char *service = NULL;
        int port = 0;
@@ -3139,7 +3318,7 @@ static int do_message_op(const char *netbios_name, const char *desthost,
        int rc = 0;
        int name_type = 0x20;
        TALLOC_CTX *mem_ctx;
-       struct event_context *ev_ctx;
+       struct tevent_context *ev_ctx;
        struct smbclient_context *ctx;
        const char *cmdstr = NULL;
        struct smbcli_options smb_options;
@@ -3169,10 +3348,10 @@ static int do_message_op(const char *netbios_name, const char *desthost,
                exit(1);
        }
 
-       ctx = talloc(mem_ctx, struct smbclient_context);
+       ctx = talloc_zero(mem_ctx, struct smbclient_context);
        ctx->io_bufsize = 64512;
 
-       pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
+       pc = poptGetContext("smbclient", argc, argv, long_options, 0);
        poptSetOtherOptionHelp(pc, "[OPTIONS] service <password>");
 
        while ((opt = poptGetNextOpt(pc)) != -1) {
@@ -3202,7 +3381,7 @@ static int do_message_op(const char *netbios_name, const char *desthost,
                }
        }
 
-       gensec_init(cmdline_lp_ctx);
+       gensec_init();
 
        if(poptPeekArg(pc)) {
                char *s = strdup(poptGetArg(pc)); 
@@ -3220,7 +3399,8 @@ static int do_message_op(const char *netbios_name, const char *desthost,
        }
 
        if (poptPeekArg(pc)) { 
-               cli_credentials_set_password(cmdline_credentials, poptGetArg(pc), CRED_SPECIFIED);
+               cli_credentials_set_password(popt_get_cmdline_credentials(),
+                       poptGetArg(pc), CRED_SPECIFIED);
        }
 
        /*init_names(); */
@@ -3232,8 +3412,8 @@ static int do_message_op(const char *netbios_name, const char *desthost,
 
        poptFreeContext(pc);
 
-       lp_smbcli_options(cmdline_lp_ctx, &smb_options);
-       lp_smbcli_session_options(cmdline_lp_ctx, &smb_session_options);
+       lpcfg_smbcli_options(cmdline_lp_ctx, &smb_options);
+       lpcfg_smbcli_session_options(cmdline_lp_ctx, &smb_session_options);
 
        ev_ctx = s4_event_context_init(talloc_autofree_context());
 
@@ -3247,34 +3427,40 @@ static int do_message_op(const char *netbios_name, const char *desthost,
   
        if (query_host) {
                rc = do_host_query(cmdline_lp_ctx, ev_ctx, query_host,
-                                  lp_workgroup(cmdline_lp_ctx));
+                                  lpcfg_workgroup(cmdline_lp_ctx));
                return rc;
        }
 
        if (message) {
-               rc = do_message_op(lp_netbios_name(cmdline_lp_ctx), desthost,
-                                  lp_smb_ports(cmdline_lp_ctx), dest_ip,
+               rc = do_message_op(lpcfg_netbios_name(cmdline_lp_ctx), desthost,
+                                  lpcfg_smb_ports(cmdline_lp_ctx), dest_ip,
                                   name_type, ev_ctx,
-                                  lp_resolve_context(cmdline_lp_ctx),
-                                  &smb_options, lp_iconv_convenience(cmdline_lp_ctx));
+                                  lpcfg_resolve_context(cmdline_lp_ctx),
+                                  &smb_options, 
+                   lpcfg_socket_options(cmdline_lp_ctx));
                return rc;
        }
        
-       if (!do_connect(ctx, ev_ctx, lp_resolve_context(cmdline_lp_ctx),
-                       desthost, lp_smb_ports(cmdline_lp_ctx), service,
-                       cmdline_credentials, &smb_options, &smb_session_options,
-                       lp_iconv_convenience(cmdline_lp_ctx)))
+       if (!do_connect(ctx, ev_ctx, lpcfg_resolve_context(cmdline_lp_ctx),
+                       desthost, lpcfg_smb_ports(cmdline_lp_ctx), service,
+                       lpcfg_socket_options(cmdline_lp_ctx),
+                       popt_get_cmdline_credentials(),
+                       &smb_options, &smb_session_options,
+                       lpcfg_gensec_settings(ctx, cmdline_lp_ctx)))
                return 1;
 
-       if (base_directory) 
+       if (base_directory) {
                do_cd(ctx, base_directory);
+               free(base_directory);
+       }
        
        if (cmdstr) {
                rc = process_command_string(ctx, cmdstr);
        } else {
                rc = process_stdin(ctx);
        }
-  
+
+       free(desthost);
        talloc_free(mem_ctx);
 
        return rc;