Make rmdir async.
[nivanova/samba-autobuild/.git] / source3 / client / client.c
index 1c85a6dafc273e3cefc0ad4713d38faac8f4cadd..54ff755ed32b5eb054c560a7e18f20db7a65ef2b 100644 (file)
@@ -33,7 +33,6 @@ extern int do_smb_browse(void); /* mDNS browsing */
 extern bool AllowDebugChange;
 extern bool override_logfile;
 extern char tar_type;
-extern bool in_client;
 
 static int port = 0;
 static char *service;
@@ -41,12 +40,12 @@ static char *desthost;
 static char *calling_name;
 static bool grepable = false;
 static char *cmdstr = NULL;
-static const char *cmd_ptr = NULL;
+const char *cmd_ptr = NULL;
 
-static int io_bufsize = 64512;
+static int io_bufsize = 524288;
 
 static int name_type = 0x20;
-extern int max_protocol;
+static int max_protocol = PROTOCOL_NT1;
 
 static int process_tok(char *tok);
 static int cmd_help(void);
@@ -79,15 +78,16 @@ static bool showacls = false;
 bool lowercase = false;
 
 static struct sockaddr_storage dest_ss;
+static char dest_ss_str[INET6_ADDRSTRLEN];
 
 #define SEPARATORS " \t\n\r"
 
 static bool abort_mget = true;
 
 /* timing globals */
-SMB_BIG_UINT get_total_size = 0;
+uint64_t get_total_size = 0;
 unsigned int get_total_time_ms = 0;
-static SMB_BIG_UINT put_total_size = 0;
+static uint64_t put_total_size = 0;
 static unsigned int put_total_time_ms = 0;
 
 /* totals globals */
@@ -103,6 +103,9 @@ struct cli_state *cli;
 static char CLI_DIRSEP_CHAR = '\\';
 static char CLI_DIRSEP_STR[] = { '\\', '\0' };
 
+/* Authentication for client connections. */
+struct user_auth_info *auth_info;
+
 /* Accessor functions for directory paths. */
 static char *fileselection;
 static const char *client_get_fileselection(void)
@@ -191,7 +194,7 @@ static int writefile(int f, char *b, int n)
  number read. read approx n bytes.
 ****************************************************************************/
 
-static int readfile(char *b, int n, XFILE *f)
+static int readfile(uint8_t *b, int n, XFILE *f)
 {
        int i;
        int c;
@@ -215,17 +218,35 @@ static int readfile(char *b, int n, XFILE *f)
        return(i);
 }
 
+struct push_state {
+       XFILE *f;
+       SMB_OFF_T nread;
+};
+
+static size_t push_source(uint8_t *buf, size_t n, void *priv)
+{
+       struct push_state *state = (struct push_state *)priv;
+       int result;
+
+       if (x_feof(state->f)) {
+               return 0;
+       }
+
+       result = readfile(buf, n, state->f);
+       state->nread += result;
+       return result;
+}
+
 /****************************************************************************
  Send a message.
 ****************************************************************************/
 
-static void send_message(void)
+static void send_message(const char *username)
 {
        int total_len = 0;
        int grp_id;
 
-       if (!cli_message_start(cli, desthost,
-                               get_cmdline_auth_info_username(), &grp_id)) {
+       if (!cli_message_start(cli, desthost, username, &grp_id)) {
                d_printf("message start: %s\n", cli_errstr(cli));
                return;
        }
@@ -281,7 +302,7 @@ static int do_dskattr(void)
        char *targetpath = NULL;
        TALLOC_CTX *ctx = talloc_tos();
 
-       if ( !cli_resolve_path(ctx, "", cli, client_get_cur_dir(), &targetcli, &targetpath)) {
+       if ( !cli_resolve_path(ctx, "", auth_info, cli, client_get_cur_dir(), &targetcli, &targetpath)) {
                d_printf("Error in dskattr: %s\n", cli_errstr(cli));
                return 1;
        }
@@ -308,6 +329,17 @@ static int cmd_pwd(void)
        return 0;
 }
 
+/****************************************************************************
+ Ensure name has correct directory separators.
+****************************************************************************/
+
+static void normalize_name(char *newdir)
+{
+       if (!(cli->posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
+               string_replace(newdir,'/','\\');
+       }
+}
+
 /****************************************************************************
  Change directory - inner section.
 ****************************************************************************/
@@ -329,7 +361,8 @@ static int do_cd(const char *new_dir)
                TALLOC_FREE(ctx);
                return 1;
        }
-       string_replace(newdir,'/','\\');
+
+       normalize_name(newdir);
 
        /* Save the current directory in case the new directory is invalid */
 
@@ -349,22 +382,21 @@ static int do_cd(const char *new_dir)
                if (!new_cd) {
                        goto out;
                }
-               if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) {
-                       new_cd = talloc_asprintf_append(new_cd, CLI_DIRSEP_STR);
-                       if (!new_cd) {
-                               goto out;
-                       }
-               }
-               client_set_cur_dir(new_cd);
        }
-       if (!new_cd) {
-               goto out;
+
+       /* Ensure cur_dir ends in a DIRSEP */
+       if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) {
+               new_cd = talloc_asprintf_append(new_cd, "%s", CLI_DIRSEP_STR);
+               if (!new_cd) {
+                       goto out;
+               }
        }
+       client_set_cur_dir(new_cd);
 
        new_cd = clean_name(ctx, new_cd);
        client_set_cur_dir(new_cd);
 
-       if ( !cli_resolve_path(ctx, "", cli, new_cd, &targetcli, &targetpath)) {
+       if ( !cli_resolve_path(ctx, "", auth_info, cli, new_cd, &targetcli, &targetpath)) {
                d_printf("cd %s: %s\n", new_cd, cli_errstr(cli));
                client_set_cur_dir(saved_dir);
                goto out;
@@ -511,14 +543,14 @@ static void display_finfo(file_info *finfo, const char *dir)
                /* create absolute filename for cli_nt_create() FIXME */
                afname = talloc_asprintf(ctx,
                                        "%s%s%s",
-                                       client_get_cwd(),
+                                       dir,
                                        CLI_DIRSEP_STR,
                                        finfo->name);
                if (!afname) {
                        return;
                }
                /* print file meta date header */
-               d_printf( "FILENAME:%s\n", afname);
+               d_printf( "FILENAME:%s\n", finfo->name);
                d_printf( "MODE:%s\n", attrib_string(finfo->mode));
                d_printf( "SIZE:%.0f\n", (double)finfo->size);
                d_printf( "MTIME:%s", time_to_asc(t));
@@ -718,11 +750,11 @@ static void do_list_helper(const char *mntpoint, file_info *f, const char *mask,
                                return;
                        }
                        p = strrchr_m(mask2,CLI_DIRSEP_CHAR);
-                       if (!p) {
-                               TALLOC_FREE(dir);
-                               return;
+                       if (p) {
+                               p[1] = 0;
+                       } else {
+                               mask2[0] = '\0';
                        }
-                       p[1] = 0;
                        mask2 = talloc_asprintf_append(mask2,
                                        "%s%s*",
                                        f->name,
@@ -790,7 +822,7 @@ void do_list(const char *mask,
 
                        /* check for dfs */
 
-                       if ( !cli_resolve_path(ctx, "", cli, head, &targetcli, &targetpath ) ) {
+                       if ( !cli_resolve_path(ctx, "", auth_info, cli, head, &targetcli, &targetpath ) ) {
                                d_printf("do_list: [%s] %s\n", head, cli_errstr(cli));
                                remove_do_list_queue_head();
                                continue;
@@ -823,7 +855,7 @@ void do_list(const char *mask,
                }
        } else {
                /* check for dfs */
-               if (cli_resolve_path(ctx, "", cli, mask, &targetcli, &targetpath)) {
+               if (cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetpath)) {
                        if (cli_list(targetcli, targetpath, attribute, do_list_helper, NULL) == -1) {
                                d_printf("%s listing %s\n",
                                        cli_errstr(targetcli), targetpath);
@@ -851,28 +883,17 @@ static int cmd_dir(void)
        int rc = 1;
 
        dir_total = 0;
-       if (strcmp(client_get_cur_dir(), CLI_DIRSEP_STR) != 0) {
-               mask = talloc_strdup(ctx, client_get_cur_dir());
-               if (!mask) {
-                       return 1;
-               }
-               if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) {
-                       mask = talloc_asprintf_append(mask, CLI_DIRSEP_STR);
-               }
-       } else {
-               mask = talloc_strdup(ctx, CLI_DIRSEP_STR);
-       }
-
+       mask = talloc_strdup(ctx, client_get_cur_dir());
        if (!mask) {
                return 1;
        }
 
        if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
-               string_replace(buf,'/','\\');
+               normalize_name(buf);
                if (*buf == CLI_DIRSEP_CHAR) {
-                       mask = talloc_strdup(ctx, buf + 1);
+                       mask = talloc_strdup(ctx, buf);
                } else {
-                       mask = talloc_asprintf_append(mask, buf);
+                       mask = talloc_asprintf_append(mask, "%s", buf);
                }
        } else {
                mask = talloc_asprintf_append(mask, "*");
@@ -913,18 +934,18 @@ static int cmd_du(void)
                return 1;
        }
        if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) {
-               mask = talloc_asprintf_append(mask, CLI_DIRSEP_STR);
+               mask = talloc_asprintf_append(mask, "%s", CLI_DIRSEP_STR);
                if (!mask) {
                        return 1;
                }
        }
 
        if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
-               string_replace(buf,'/','\\');
+               normalize_name(buf);
                if (*buf == CLI_DIRSEP_CHAR) {
                        mask = talloc_strdup(ctx, buf);
                } else {
-                       mask = talloc_asprintf_append(mask, buf);
+                       mask = talloc_asprintf_append(mask, "%s", buf);
                }
        } else {
                mask = talloc_strdup(ctx, "*");
@@ -944,6 +965,7 @@ static int cmd_echo(void)
        TALLOC_CTX *ctx = talloc_tos();
        char *num;
        char *data;
+       NTSTATUS status;
 
        if (!next_token_talloc(ctx, &cmd_ptr, &num, NULL)
            || !next_token_talloc(ctx, &cmd_ptr, &data, NULL)) {
@@ -951,9 +973,10 @@ static int cmd_echo(void)
                return 1;
        }
 
-       if (!cli_echo(cli, atoi(num), (uint8 *)data, strlen(data))) {
-               d_printf("echo failed: %s\n",
-                        nt_errstr(cli_get_nt_error(cli)));
+       status = cli_echo(cli, atoi(num), data_blob_const(data, strlen(data)));
+
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("echo failed: %s\n", nt_errstr(status));
                return 1;
        }
 
@@ -964,22 +987,30 @@ static int cmd_echo(void)
  Get a file from rname to lname
 ****************************************************************************/
 
+static NTSTATUS writefile_sink(char *buf, size_t n, void *priv)
+{
+       int *pfd = (int *)priv;
+       if (writefile(*pfd, buf, n) == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+       return NT_STATUS_OK;
+}
+
 static int do_get(const char *rname, const char *lname_in, bool reget)
 {
        TALLOC_CTX *ctx = talloc_tos();
        int handle = 0, fnum;
        bool newhandle = false;
-       char *data = NULL;
        struct timeval tp_start;
-       int read_size = io_bufsize;
        uint16 attr;
        SMB_OFF_T size;
        off_t start = 0;
-       off_t nread = 0;
+       SMB_OFF_T nread = 0;
        int rc = 0;
        struct cli_state *targetcli = NULL;
        char *targetname = NULL;
        char *lname = NULL;
+       NTSTATUS status;
 
        lname = talloc_strdup(ctx, lname_in);
        if (!lname) {
@@ -990,7 +1021,7 @@ static int do_get(const char *rname, const char *lname_in, bool reget)
                strlower_m(lname);
        }
 
-       if (!cli_resolve_path(ctx, "", cli, rname, &targetcli, &targetname ) ) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, rname, &targetcli, &targetname ) ) {
                d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
                return 1;
        }
@@ -1038,36 +1069,15 @@ static int do_get(const char *rname, const char *lname_in, bool reget)
        DEBUG(1,("getting file %s of size %.0f as %s ",
                 rname, (double)size, lname));
 
-       if(!(data = (char *)SMB_MALLOC(read_size))) {
-               d_printf("malloc fail for size %d\n", read_size);
+       status = cli_pull(targetcli, fnum, start, size, io_bufsize,
+                         writefile_sink, (void *)&handle, &nread);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "parallel_read returned %s\n",
+                         nt_errstr(status));
                cli_close(targetcli, fnum);
                return 1;
        }
 
-       while (1) {
-               int n = cli_read(targetcli, fnum, data, nread + start, read_size);
-
-               if (n <= 0)
-                       break;
-
-               if (writefile(handle,data, n) != n) {
-                       d_printf("Error writing local file\n");
-                       rc = 1;
-                       break;
-               }
-
-               nread += n;
-       }
-
-       if (nread + start < size) {
-               DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n",
-                           rname, (long)nread));
-
-               rc = 1;
-       }
-
-       SAFE_FREE(data);
-
        if (!cli_close(targetcli, fnum)) {
                d_printf("Error %s closing remote file\n",cli_errstr(cli));
                rc = 1;
@@ -1092,7 +1102,7 @@ static int do_get(const char *rname, const char *lname_in, bool reget)
                get_total_time_ms += this_time;
                get_total_size += nread;
 
-               DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
+               DEBUG(1,("(%3.1f KiloBytes/sec) (average %3.1f KiloBytes/sec)\n",
                         nread / (1.024*this_time + 1.0e-4),
                         get_total_size / (1.024*get_total_time_ms)));
        }
@@ -1112,10 +1122,7 @@ static int cmd_get(void)
        char *rname = NULL;
        char *fname = NULL;
 
-       rname = talloc_asprintf(ctx,
-                       "%s%s",
-                       client_get_cur_dir(),
-                       CLI_DIRSEP_STR);
+       rname = talloc_strdup(ctx, client_get_cur_dir());
        if (!rname) {
                return 1;
        }
@@ -1124,7 +1131,7 @@ static int cmd_get(void)
                d_printf("get <filename> [localname]\n");
                return 1;
        }
-       rname = talloc_asprintf_append(rname, fname);
+       rname = talloc_asprintf_append(rname, "%s", fname);
        if (!rname) {
                return 1;
        }
@@ -1218,7 +1225,7 @@ static void do_mget(file_info *finfo, const char *dir)
                strlower_m(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);
                client_set_cur_dir(saved_curdir);
@@ -1240,7 +1247,10 @@ static void do_mget(file_info *finfo, const char *dir)
        }
 
        do_list(mget_mask, aSYSTEM | aHIDDEN | aDIR,do_mget,false, true);
-       chdir("..");
+       if (chdir("..") == -1) {
+               d_printf("do_mget: failed to chdir to .. (error %s)\n",
+                       strerror(errno) );
+       }
        client_set_cur_dir(saved_curdir);
        TALLOC_FREE(mget_mask);
        TALLOC_FREE(saved_curdir);
@@ -1262,10 +1272,7 @@ static int cmd_more(void)
        int fd;
        int rc = 0;
 
-       rname = talloc_asprintf(ctx,
-                       "%s%s",
-                       client_get_cur_dir(),
-                       CLI_DIRSEP_STR);
+       rname = talloc_strdup(ctx, client_get_cur_dir());
        if (!rname) {
                return 1;
        }
@@ -1274,7 +1281,7 @@ static int cmd_more(void)
        if (!lname) {
                return 1;
        }
-       fd = smb_mkstemp(lname);
+       fd = mkstemp(lname);
        if (fd == -1) {
                d_printf("failed to create temporary file for more\n");
                return 1;
@@ -1286,7 +1293,7 @@ static int cmd_more(void)
                unlink(lname);
                return 1;
        }
-       rname = talloc_asprintf_append(rname, fname);
+       rname = talloc_asprintf_append(rname, "%s", fname);
        if (!rname) {
                return 1;
        }
@@ -1306,7 +1313,10 @@ static int cmd_more(void)
        if (!pager_cmd) {
                return 1;
        }
-       system(pager_cmd);
+       if (system(pager_cmd) == -1) {
+               d_printf("system command '%s' returned -1\n",
+                       pager_cmd);
+       }
        unlink(lname);
 
        return rc;
@@ -1334,20 +1344,11 @@ static int cmd_mget(void)
                if (!mget_mask) {
                        return 1;
                }
-               if ((mget_mask[0] != '\0') &&
-                               (mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR)) {
-                       mget_mask = talloc_asprintf_append(mget_mask,
-                                                       CLI_DIRSEP_STR);
-                       if (!mget_mask) {
-                               return 1;
-                       }
-               }
-
                if (*buf == CLI_DIRSEP_CHAR) {
                        mget_mask = talloc_strdup(ctx, buf);
                } else {
                        mget_mask = talloc_asprintf_append(mget_mask,
-                                                       buf);
+                                                       "%s", buf);
                }
                if (!mget_mask) {
                        return 1;
@@ -1355,19 +1356,15 @@ static int cmd_mget(void)
                do_list(mget_mask, attribute, do_mget, false, true);
        }
 
+       if (mget_mask == NULL) {
+               d_printf("nothing to mget\n");
+               return 0;
+       }
+
        if (!*mget_mask) {
-               mget_mask = talloc_strdup(ctx, client_get_cur_dir());
-               if (!mget_mask) {
-                       return 1;
-               }
-               if(mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR) {
-                       mget_mask = talloc_asprintf_append(mget_mask,
-                                                       CLI_DIRSEP_STR);
-                       if (!mget_mask) {
-                               return 1;
-                       }
-               }
-               mget_mask = talloc_asprintf_append(mget_mask, "*");
+               mget_mask = talloc_asprintf(ctx,
+                                       "%s*",
+                                       client_get_cur_dir());
                if (!mget_mask) {
                        return 1;
                }
@@ -1387,12 +1384,12 @@ static bool do_mkdir(const char *name)
        struct cli_state *targetcli;
        char *targetname = NULL;
 
-       if (!cli_resolve_path(ctx, "", cli, name, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, name, &targetcli, &targetname)) {
                d_printf("mkdir %s: %s\n", name, cli_errstr(cli));
                return false;
        }
 
-       if (!cli_mkdir(targetcli, targetname)) {
+       if (!NT_STATUS_IS_OK(cli_mkdir(targetcli, targetname))) {
                d_printf("%s making remote directory %s\n",
                         cli_errstr(targetcli),name);
                return false;
@@ -1425,7 +1422,7 @@ static bool do_altname(const char *name)
 
 static int cmd_quit(void)
 {
-       cli_cm_shutdown();
+       cli_shutdown(cli);
        exit(0);
        /* NOTREACHED */
        return 0;
@@ -1452,7 +1449,7 @@ static int cmd_mkdir(void)
                }
                return 1;
        }
-       mask = talloc_asprintf_append(mask, buf);
+       mask = talloc_asprintf_append(mask, "%s", buf);
        if (!mask) {
                return 1;
        }
@@ -1470,7 +1467,7 @@ static int cmd_mkdir(void)
                        return 1;
                }
 
-               if (!cli_resolve_path(ctx, "", cli, mask, &targetcli, &targetname)) {
+               if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
                        return 1;
                }
 
@@ -1481,14 +1478,14 @@ static int cmd_mkdir(void)
                trim_char(ddir,'.','\0');
                p = strtok_r(ddir, "/\\", &saveptr);
                while (p) {
-                       ddir2 = talloc_asprintf_append(ddir2, p);
+                       ddir2 = talloc_asprintf_append(ddir2, "%s", p);
                        if (!ddir2) {
                                return 1;
                        }
                        if (!cli_chkpath(targetcli, ddir2)) {
                                do_mkdir(ddir2);
                        }
-                       ddir2 = talloc_asprintf_append(ddir2, CLI_DIRSEP_STR);
+                       ddir2 = talloc_asprintf_append(ddir2, "%s", CLI_DIRSEP_STR);
                        if (!ddir2) {
                                return 1;
                        }
@@ -1520,7 +1517,7 @@ static int cmd_altname(void)
                d_printf("altname <file>\n");
                return 1;
        }
-       name = talloc_asprintf_append(name, buf);
+       name = talloc_asprintf_append(name, "%s", buf);
        if (!name) {
                return 1;
        }
@@ -1604,7 +1601,7 @@ static int cmd_allinfo(void)
                d_printf("allinfo <file>\n");
                return 1;
        }
-       name = talloc_asprintf_append(name, buf);
+       name = talloc_asprintf_append(name, "%s", buf);
        if (!name) {
                return 1;
        }
@@ -1624,15 +1621,14 @@ static int do_put(const char *rname, const char *lname, bool reput)
        int fnum;
        XFILE *f;
        SMB_OFF_T start = 0;
-       off_t nread = 0;
-       char *buf = NULL;
-       int maxwrite = io_bufsize;
        int rc = 0;
        struct timeval tp_start;
        struct cli_state *targetcli;
        char *targetname = NULL;
+       struct push_state state;
+       NTSTATUS status;
 
-       if (!cli_resolve_path(ctx, "", cli, rname, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, rname, &targetcli, &targetname)) {
                d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
                return 1;
        }
@@ -1683,39 +1679,20 @@ static int do_put(const char *rname, const char *lname, bool reput)
        DEBUG(1,("putting file %s as %s ",lname,
                 rname));
 
-       buf = (char *)SMB_MALLOC(maxwrite);
-       if (!buf) {
-               d_printf("ERROR: Not enough memory!\n");
-               return 1;
-       }
-       while (!x_feof(f)) {
-               int n = maxwrite;
-               int ret;
+       x_setvbuf(f, NULL, X_IOFBF, io_bufsize);
 
-               if ((n = readfile(buf,n,f)) < 1) {
-                       if((n == 0) && x_feof(f))
-                               break; /* Empty local file. */
+       state.f = f;
+       state.nread = 0;
 
-                       d_printf("Error reading local file: %s\n", strerror(errno));
-                       rc = 1;
-                       break;
-               }
-
-               ret = cli_write(targetcli, fnum, 0, buf, nread + start, n);
-
-               if (n != ret) {
-                       d_printf("Error writing file: %s\n", cli_errstr(cli));
-                       rc = 1;
-                       break;
-               }
-
-               nread += n;
+       status = cli_push(targetcli, fnum, 0, 0, io_bufsize, push_source,
+                         &state);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "cli_push returned %s\n", nt_errstr(status));
        }
 
        if (!cli_close(targetcli, fnum)) {
                d_printf("%s closing remote file %s\n",cli_errstr(cli),rname);
                x_fclose(f);
-               SAFE_FREE(buf);
                return 1;
        }
 
@@ -1723,8 +1700,6 @@ static int do_put(const char *rname, const char *lname, bool reput)
                x_fclose(f);
        }
 
-       SAFE_FREE(buf);
-
        {
                struct timeval tp_end;
                int this_time;
@@ -1734,15 +1709,15 @@ static int do_put(const char *rname, const char *lname, bool reput)
                        (tp_end.tv_sec - tp_start.tv_sec)*1000 +
                        (tp_end.tv_usec - tp_start.tv_usec)/1000;
                put_total_time_ms += this_time;
-               put_total_size += nread;
+               put_total_size += state.nread;
 
                DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
-                        nread / (1.024*this_time + 1.0e-4),
+                        state.nread / (1.024*this_time + 1.0e-4),
                         put_total_size / (1.024*put_total_time_ms)));
        }
 
        if (f == x_stdin) {
-               cli_cm_shutdown();
+               cli_shutdown(cli);
                exit(0);
        }
 
@@ -1760,10 +1735,7 @@ static int cmd_put(void)
        char *rname;
        char *buf;
 
-       rname = talloc_asprintf(ctx,
-                       "%s%s",
-                       client_get_cur_dir(),
-                       CLI_DIRSEP_STR);
+       rname = talloc_strdup(ctx, client_get_cur_dir());
        if (!rname) {
                return 1;
        }
@@ -1774,9 +1746,9 @@ static int cmd_put(void)
        }
 
        if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
-               rname = talloc_asprintf_append(rname, buf);
+               rname = talloc_asprintf_append(rname, "%s", buf);
        } else {
-               rname = talloc_asprintf_append(rname, lname);
+               rname = talloc_asprintf_append(rname, "%s", lname);
        }
        if (!rname) {
                return 1;
@@ -1791,7 +1763,7 @@ static int cmd_put(void)
                SMB_STRUCT_STAT st;
                /* allow '-' to represent stdin
                   jdblair, 24.jun.98 */
-               if (!file_exist(lname,&st) &&
+               if (!file_exist_stat(lname,&st) &&
                    (strcmp(lname,"-"))) {
                        d_printf("%s does not exist\n",lname);
                        return 1;
@@ -1815,13 +1787,13 @@ static struct file_list {
  Free a file_list structure.
 ****************************************************************************/
 
-static void free_file_list (struct file_list *list_head)
+static void free_file_list (struct file_list *l_head)
 {
        struct file_list *list, *next;
 
-       for (list = list_head; list; list = next) {
+       for (list = l_head; list; list = next) {
                next = list->next;
-               DLIST_REMOVE(list_head, list);
+               DLIST_REMOVE(l_head, list);
                SAFE_FREE(list->file_path);
                SAFE_FREE(list);
        }
@@ -1980,10 +1952,10 @@ static int cmd_mput(void)
                                                break;
                                } else { /* Yes */
                                        SAFE_FREE(rname);
-                                       if(asprintf(&rname, "%s%s", cur_dir, lname) < 0) {
+                                       if(asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
                                                break;
                                        }
-                                       string_replace(rname,'/','\\');
+                                       normalize_name(rname);
                                        if (!cli_chkpath(cli, rname) &&
                                            !do_mkdir(rname)) {
                                                DEBUG (0, ("Unable to make dir, skipping..."));
@@ -2007,12 +1979,12 @@ static int cmd_mput(void)
 
                                /* Yes */
                                SAFE_FREE(rname);
-                               if (asprintf(&rname, "%s%s", cur_dir, lname) < 0) {
+                               if (asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
                                        break;
                                }
                        }
 
-                       string_replace(rname,'/','\\');
+                       normalize_name(rname);
 
                        do_put(rname, lname, false);
                }
@@ -2173,7 +2145,7 @@ static int cmd_del(void)
                d_printf("del <filename>\n");
                return 1;
        }
-       mask = talloc_asprintf_append(mask, buf);
+       mask = talloc_asprintf_append(mask, "%s", buf);
        if (!mask) {
                return 1;
        }
@@ -2214,7 +2186,7 @@ static int cmd_wdel(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, mask, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
                d_printf("cmd_wdel %s: %s\n", mask, cli_errstr(cli));
                return 1;
        }
@@ -2249,7 +2221,7 @@ static int cmd_open(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, mask, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
                d_printf("open %s: %s\n", mask, cli_errstr(cli));
                return 1;
        }
@@ -2342,7 +2314,7 @@ static int cmd_posix_open(void)
        }
        mode = (mode_t)strtol(buf, (char **)NULL, 8);
 
-       if (!cli_resolve_path(ctx, "", cli, mask, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
                d_printf("posix_open %s: %s\n", mask, cli_errstr(cli));
                return 1;
        }
@@ -2390,7 +2362,7 @@ static int cmd_posix_mkdir(void)
        }
        mode = (mode_t)strtol(buf, (char **)NULL, 8);
 
-       if (!cli_resolve_path(ctx, "", cli, mask, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
                d_printf("posix_mkdir %s: %s\n", mask, cli_errstr(cli));
                return 1;
        }
@@ -2424,7 +2396,7 @@ static int cmd_posix_unlink(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, mask, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
                d_printf("posix_unlink %s: %s\n", mask, cli_errstr(cli));
                return 1;
        }
@@ -2458,7 +2430,7 @@ static int cmd_posix_rmdir(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, mask, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
                d_printf("posix_rmdir %s: %s\n", mask, cli_errstr(cli));
                return 1;
        }
@@ -2594,7 +2566,7 @@ static int cmd_lock(void)
 {
        TALLOC_CTX *ctx = talloc_tos();
        char *buf = NULL;
-       SMB_BIG_UINT start, len;
+       uint64_t start, len;
        enum brl_type lock_type;
        int fnum;
 
@@ -2623,14 +2595,14 @@ static int cmd_lock(void)
                return 1;
        }
 
-       start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+       start = (uint64_t)strtol(buf, (char **)NULL, 16);
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
                return 1;
        }
 
-       len = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+       len = (uint64_t)strtol(buf, (char **)NULL, 16);
 
        if (!cli_posix_lock(cli, fnum, start, len, true, lock_type)) {
                d_printf("lock failed %d: %s\n", fnum, cli_errstr(cli));
@@ -2643,7 +2615,7 @@ static int cmd_unlock(void)
 {
        TALLOC_CTX *ctx = talloc_tos();
        char *buf = NULL;
-       SMB_BIG_UINT start, len;
+       uint64_t start, len;
        int fnum;
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
@@ -2657,14 +2629,14 @@ static int cmd_unlock(void)
                return 1;
        }
 
-       start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+       start = (uint64_t)strtol(buf, (char **)NULL, 16);
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("unlock <fnum> <hex-start> <hex-len>\n");
                return 1;
        }
 
-       len = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+       len = (uint64_t)strtol(buf, (char **)NULL, 16);
 
        if (!cli_posix_unlock(cli, fnum, start, len)) {
                d_printf("unlock failed %d: %s\n", fnum, cli_errstr(cli));
@@ -2698,12 +2670,12 @@ static int cmd_rmdir(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, mask, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
                d_printf("rmdir %s: %s\n", mask, cli_errstr(cli));
                return 1;
        }
 
-       if (!cli_rmdir(targetcli, targetname)) {
+       if (!NT_STATUS_IS_OK(cli_rmdir(targetcli, targetname))) {
                d_printf("%s removing remote directory file %s\n",
                         cli_errstr(targetcli),mask);
        }
@@ -2745,7 +2717,7 @@ static int cmd_link(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, oldname, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, oldname, &targetcli, &targetname)) {
                d_printf("link %s: %s\n", oldname, cli_errstr(cli));
                return 1;
        }
@@ -2796,7 +2768,7 @@ static int cmd_symlink(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, oldname, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, oldname, &targetcli, &targetname)) {
                d_printf("link %s: %s\n", oldname, cli_errstr(cli));
                return 1;
        }
@@ -2844,7 +2816,7 @@ static int cmd_chmod(void)
 
        mode = (mode_t)strtol(buf, NULL, 8);
 
-       if (!cli_resolve_path(ctx, "", cli, src, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
                d_printf("chmod %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
@@ -2997,7 +2969,7 @@ static int cmd_getfacl(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, src, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
                d_printf("stat %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
@@ -3077,7 +3049,7 @@ static int cmd_getfacl(void)
                                break;
                        case SMB_POSIX_ACL_GROUP:
                                uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
-                               d_printf("group:%u", uorg);
+                               d_printf("group:%u:", uorg);
                                break;
                        case SMB_POSIX_ACL_MASK:
                                d_printf("mask::");
@@ -3114,7 +3086,7 @@ static int cmd_getfacl(void)
                                break;
                        case SMB_POSIX_ACL_GROUP:
                                uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
-                               d_printf("default:group:%u", uorg);
+                               d_printf("default:group:%u:", uorg);
                                break;
                        case SMB_POSIX_ACL_MASK:
                                d_printf("default:mask::");
@@ -3163,7 +3135,7 @@ static int cmd_stat(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, src, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
                d_printf("stat %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
@@ -3264,7 +3236,7 @@ static int cmd_chown(void)
        if (!src) {
                return 1;
        }
-       if (!cli_resolve_path(ctx, "", cli, src, &targetcli, &targetname) ) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname) ) {
                d_printf("chown %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
@@ -3318,12 +3290,12 @@ static int cmd_rename(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, src, &targetcli, &targetsrc)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetsrc)) {
                d_printf("rename %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, dest, &targetcli, &targetdest)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, dest, &targetcli, &targetdest)) {
                d_printf("rename %s: %s\n", dest, cli_errstr(cli));
                return 1;
        }
@@ -3393,7 +3365,7 @@ static int cmd_hardlink(void)
                return 1;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, src, &targetcli, &targetname)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
                d_printf("hardlink %s: %s\n", src, cli_errstr(cli));
                return 1;
        }
@@ -3534,7 +3506,10 @@ static int cmd_lcd(void)
        char *d;
 
        if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
-               chdir(buf);
+               if (chdir(buf) == -1) {
+                       d_printf("chdir to %s failed (%s)\n",
+                               buf, strerror(errno));
+               }
        }
        d = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
        if (!d) {
@@ -3556,10 +3531,7 @@ static int cmd_reget(void)
        char *fname = NULL;
        char *p = NULL;
 
-       remote_name = talloc_asprintf(ctx,
-                               "%s%s",
-                               client_get_cur_dir(),
-                               CLI_DIRSEP_STR);
+       remote_name = talloc_strdup(ctx, client_get_cur_dir());
        if (!remote_name) {
                return 1;
        }
@@ -3568,7 +3540,7 @@ static int cmd_reget(void)
                d_printf("reget <filename>\n");
                return 1;
        }
-       remote_name = talloc_asprintf_append(remote_name, fname);
+       remote_name = talloc_asprintf_append(remote_name, "%s", fname);
        if (!remote_name) {
                return 1;
        }
@@ -3598,10 +3570,7 @@ static int cmd_reput(void)
        char *buf;
        SMB_STRUCT_STAT st;
 
-       remote_name = talloc_asprintf(ctx,
-                               "%s%s",
-                               client_get_cur_dir(),
-                               CLI_DIRSEP_STR);
+       remote_name = talloc_strdup(ctx, client_get_cur_dir());
        if (!remote_name) {
                return 1;
        }
@@ -3611,17 +3580,17 @@ static int cmd_reput(void)
                return 1;
        }
 
-       if (!file_exist(local_name, &st)) {
+       if (!file_exist_stat(local_name, &st)) {
                d_printf("%s does not exist\n", local_name);
                return 1;
        }
 
        if (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
                remote_name = talloc_asprintf_append(remote_name,
-                                               buf);
+                                               "%s", buf);
        } else {
                remote_name = talloc_asprintf_append(remote_name,
-                                               local_name);
+                                               "%s", local_name);
        }
        if (!remote_name) {
                return 1;
@@ -3674,42 +3643,49 @@ static bool browse_host_rpc(bool sort)
        NTSTATUS status;
        struct rpc_pipe_client *pipe_hnd;
        TALLOC_CTX *frame = talloc_stackframe();
-       ENUM_HND enum_hnd;
        WERROR werr;
-       SRV_SHARE_INFO_CTR ctr;
+       struct srvsvc_NetShareInfoCtr info_ctr;
+       struct srvsvc_NetShareCtr1 ctr1;
+       uint32_t resume_handle = 0;
+       uint32_t total_entries = 0;
        int i;
 
-       init_enum_hnd(&enum_hnd, 0);
-
-       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &status);
+       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id,
+                                         &pipe_hnd);
 
-       if (pipe_hnd == NULL) {
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("Could not connect to srvsvc pipe: %s\n",
                           nt_errstr(status)));
                TALLOC_FREE(frame);
                return false;
        }
 
-       werr = rpccli_srvsvc_net_share_enum(pipe_hnd, frame, 1, &ctr,
-                                           0xffffffff, &enum_hnd);
+       ZERO_STRUCT(info_ctr);
+       ZERO_STRUCT(ctr1);
+
+       info_ctr.level = 1;
+       info_ctr.ctr.ctr1 = &ctr1;
 
-       if (!W_ERROR_IS_OK(werr)) {
-               cli_rpc_pipe_close(pipe_hnd);
+       status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, frame,
+                                             pipe_hnd->desthost,
+                                             &info_ctr,
+                                             0xffffffff,
+                                             &total_entries,
+                                             &resume_handle,
+                                             &werr);
+
+       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
+               TALLOC_FREE(pipe_hnd);
                TALLOC_FREE(frame);
                return false;
        }
 
-       for (i=0; i<ctr.num_entries; i++) {
-               SRV_SHARE_INFO_1 *info = &ctr.share.info1[i];
-               char *name, *comment;
-               name = rpcstr_pull_unistr2_talloc(
-                       frame, &info->info_1_str.uni_netname);
-               comment = rpcstr_pull_unistr2_talloc(
-                       frame, &info->info_1_str.uni_remark);
-               browse_fn(name, info->info_1.type, comment, NULL);
+       for (i=0; i < info_ctr.ctr.ctr1->count; i++) {
+               struct srvsvc_NetShareInfo1 info = info_ctr.ctr.ctr1->array[i];
+               browse_fn(info.name, info.type, info.comment, NULL);
        }
 
-       cli_rpc_pipe_close(pipe_hnd);
+       TALLOC_FREE(pipe_hnd);
        TALLOC_FREE(frame);
        return true;
 }
@@ -3842,7 +3818,7 @@ static int cmd_logon(void)
 
 static int cmd_list_connect(void)
 {
-       cli_cm_display();
+       cli_cm_display(cli);
        return 0;
 }
 
@@ -3856,7 +3832,7 @@ static int cmd_show_connect( void )
        struct cli_state *targetcli;
        char *targetpath;
 
-       if (!cli_resolve_path(ctx, "", cli, client_get_cur_dir(),
+       if (!cli_resolve_path(ctx, "", auth_info, cli, client_get_cur_dir(),
                                &targetcli, &targetpath ) ) {
                d_printf("showconnect %s: %s\n", cur_dir, cli_errstr(cli));
                return 1;
@@ -4076,8 +4052,11 @@ static int process_command_string(const char *cmd_in)
        /* establish the connection if not already */
 
        if (!cli) {
-               cli = cli_cm_open(talloc_tos(), NULL, desthost,
-                               service, true, smb_encrypt);
+               cli = cli_cm_open(talloc_tos(), NULL,
+                               have_ip ? dest_ss_str : desthost,
+                               service, auth_info,
+                               true, smb_encrypt,
+                               max_protocol, port, name_type);
                if (!cli) {
                        return 1;
                }
@@ -4143,22 +4122,18 @@ static void completion_remote_filter(const char *mnt,
                        TALLOC_CTX *ctx = talloc_stackframe();
                        char *tmp;
 
-                       if (info->dirmask && info->dirmask[0] != 0) {
-                               tmp = talloc_strdup(ctx,info->dirmask);
-                       } else {
-                               tmp = talloc_strdup(ctx,"");
-                       }
+                       tmp = talloc_strdup(ctx,info->dirmask);
                        if (!tmp) {
                                TALLOC_FREE(ctx);
                                return;
                        }
-                       tmp = talloc_asprintf_append(tmp, f->name);
+                       tmp = talloc_asprintf_append(tmp, "%s", f->name);
                        if (!tmp) {
                                TALLOC_FREE(ctx);
                                return;
                        }
                        if (f->mode & aDIR) {
-                               tmp = talloc_asprintf_append(tmp, "/");
+                               tmp = talloc_asprintf_append(tmp, "%s", CLI_DIRSEP_STR);
                        }
                        if (!tmp) {
                                TALLOC_FREE(ctx);
@@ -4249,7 +4224,7 @@ static char **remote_completion(const char *text, int len)
                goto cleanup;
        }
 
-       if (!cli_resolve_path(ctx, "", cli, dirmask, &targetcli, &targetpath)) {
+       if (!cli_resolve_path(ctx, "", auth_info, cli, dirmask, &targetcli, &targetpath)) {
                goto cleanup;
        }
        if (cli_list(targetcli, targetpath, aDIR | aSYSTEM | aHIDDEN,
@@ -4387,6 +4362,8 @@ cleanup:
        }
 }
 
+static bool finished;
+
 /****************************************************************************
  Make sure we swallow keepalives during idle time.
 ****************************************************************************/
@@ -4427,12 +4404,14 @@ static void readline_callback(void)
 
                set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK);
 
-               status = receive_smb_raw(cli->fd, cli->inbuf, 0, 0, &len);
+               status = receive_smb_raw(cli->fd, cli->inbuf, cli->bufsize, 0, 0, &len);
 
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(0, ("Read from server failed, maybe it closed "
                                  "the connection\n"));
 
+                       finished = true;
+                       smb_readline_done();
                        if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
                                set_smb_read_error(&cli->smb_rw_error,
                                                   SMB_READ_EOF);
@@ -4459,9 +4438,17 @@ static void readline_callback(void)
 
        /* Ping the server to keep the connection alive using SMBecho. */
        {
+               NTSTATUS status;
                unsigned char garbage[16];
                memset(garbage, 0xf0, sizeof(garbage));
-               cli_echo(cli, 1, garbage, sizeof(garbage));
+               status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("SMBecho failed. Maybe server has closed "
+                               "the connection\n"));
+                       finished = true;
+                       smb_readline_done();
+               }
        }
 }
 
@@ -4473,7 +4460,7 @@ static int process_stdin(void)
 {
        int rc = 0;
 
-       while (1) {
+       while (!finished) {
                TALLOC_CTX *frame = talloc_stackframe();
                char *tok = NULL;
                char *the_prompt = NULL;
@@ -4494,7 +4481,10 @@ static int process_stdin(void)
 
                /* special case - first char is ! */
                if (*line == '!') {
-                       system(line + 1);
+                       if (system(line + 1) == -1) {
+                               d_printf("system() command %s failed.\n",
+                                       line+1);
+                       }
                        SAFE_FREE(line);
                        TALLOC_FREE(frame);
                        continue;
@@ -4530,7 +4520,9 @@ static int process(const char *base_directory)
        int rc = 0;
 
        cli = cli_cm_open(talloc_tos(), NULL,
-                       desthost, service, true, smb_encrypt);
+                       have_ip ? dest_ss_str : desthost,
+                       service, auth_info, true, smb_encrypt,
+                       max_protocol, port, name_type);
        if (!cli) {
                return 1;
        }
@@ -4538,7 +4530,7 @@ static int process(const char *base_directory)
        if (base_directory && *base_directory) {
                rc = do_cd(base_directory);
                if (rc) {
-                       cli_cm_shutdown();
+                       cli_shutdown(cli);
                        return rc;
                }
        }
@@ -4549,7 +4541,7 @@ static int process(const char *base_directory)
                process_stdin();
        }
 
-       cli_cm_shutdown();
+       cli_shutdown(cli);
        return rc;
 }
 
@@ -4559,22 +4551,31 @@ static int process(const char *base_directory)
 
 static int do_host_query(const char *query_host)
 {
+       struct sockaddr_storage ss;
+
        cli = cli_cm_open(talloc_tos(), NULL,
-                       query_host, "IPC$", true, smb_encrypt);
+                       query_host, "IPC$", auth_info, true, smb_encrypt,
+                       max_protocol, port, name_type);
        if (!cli)
                return 1;
 
        browse_host(true);
 
+       if (interpret_string_addr(&ss, query_host, 0) && (ss.ss_family != AF_INET)) {
+               d_printf("%s is an IPv6 address -- no workgroup available\n",
+                       query_host);
+               return 1;
+       }
+
        if (port != 139) {
 
                /* Workgroups simply don't make sense over anything
                   else but port 139... */
 
-               cli_cm_shutdown();
-               cli_cm_set_port( 139 );
+               cli_shutdown(cli);
                cli = cli_cm_open(talloc_tos(), NULL,
-                               query_host, "IPC$", true, smb_encrypt);
+                               query_host, "IPC$", auth_info, true, smb_encrypt,
+                               max_protocol, 139, name_type);
        }
 
        if (cli == NULL) {
@@ -4584,7 +4585,7 @@ static int do_host_query(const char *query_host)
 
        list_servers(lp_workgroup());
 
-       cli_cm_shutdown();
+       cli_shutdown(cli);
 
        return(0);
 }
@@ -4600,7 +4601,9 @@ static int do_tar_op(const char *base_directory)
        /* do we already have a connection? */
        if (!cli) {
                cli = cli_cm_open(talloc_tos(), NULL,
-                       desthost, service, true, smb_encrypt);
+                       have_ip ? dest_ss_str : desthost,
+                       service, auth_info, true, smb_encrypt,
+                       max_protocol, port, name_type);
                if (!cli)
                        return 1;
        }
@@ -4610,14 +4613,14 @@ static int do_tar_op(const char *base_directory)
        if (base_directory && *base_directory)  {
                ret = do_cd(base_directory);
                if (ret) {
-                       cli_cm_shutdown();
+                       cli_shutdown(cli);
                        return ret;
                }
        }
 
        ret=process_tar();
 
-       cli_cm_shutdown();
+       cli_shutdown(cli);
 
        return(ret);
 }
@@ -4626,7 +4629,7 @@ static int do_tar_op(const char *base_directory)
  Handle a message operation.
 ****************************************************************************/
 
-static int do_message_op(void)
+static int do_message_op(struct user_auth_info *a_info)
 {
        struct sockaddr_storage ss;
        struct nmb_name called, calling;
@@ -4642,7 +4645,7 @@ static int do_message_op(void)
        snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
        fstrcat(server_name, name_type_hex);
 
-        zero_addr(&ss);
+        zero_sockaddr(&ss);
        if (have_ip)
                ss = dest_ss;
 
@@ -4650,10 +4653,11 @@ static int do_message_op(void)
 
        msg_port = port ? port : 139;
 
-       if (!(cli=cli_initialise()) || (cli_set_port(cli, msg_port) != msg_port)) {
+       if (!(cli=cli_initialise())) {
                d_printf("Connection to %s failed\n", desthost);
                return 1;
        }
+       cli_set_port(cli, msg_port);
 
        status = cli_connect(cli, server_name, &ss);
        if (!NT_STATUS_IS_OK(status)) {
@@ -4663,12 +4667,12 @@ static int do_message_op(void)
 
        if (!cli_session_request(cli, &calling, &called)) {
                d_printf("session request failed\n");
-               cli_cm_shutdown();
+               cli_shutdown(cli);
                return 1;
        }
 
-       send_message();
-       cli_cm_shutdown();
+       send_message(get_cmdline_auth_info_username(a_info));
+       cli_shutdown(cli);
 
        return 0;
 }
@@ -4743,11 +4747,17 @@ static int do_message_op(void)
 
        load_case_tables();
 
+       auth_info = user_auth_info_init(frame);
+       if (auth_info == NULL) {
+               exit(1);
+       }
+       popt_common_set_auth_info(auth_info);
+
        /* skip argv(0) */
        pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
        poptSetOtherOptionHelp(pc, "service <password>");
 
-       in_client = true;   /* Make sure that we tell lp_load we are */
+        lp_set_in_client(true); /* Make sure that we tell lp_load we are */
 
        while ((opt = poptGetNextOpt(pc)) != -1) {
 
@@ -4770,8 +4780,11 @@ static int do_message_op(void)
                }
 
                /* if the service has already been retrieved then check if we have also a password */
-               if (service_opt && (!get_cmdline_auth_info_got_pass()) && poptPeekArg(pc)) {
-                       set_cmdline_auth_info_password(poptGetArg(pc));
+               if (service_opt
+                   && (!get_cmdline_auth_info_got_pass(auth_info))
+                   && poptPeekArg(pc)) {
+                       set_cmdline_auth_info_password(auth_info,
+                                                      poptGetArg(pc));
                }
 
                switch (opt) {
@@ -4781,13 +4794,12 @@ static int do_message_op(void)
                         * to port 139 instead of port 445. srl,crh
                         */
                        name_type = 0x03;
-                       cli_cm_set_dest_name_type( name_type );
                        desthost = talloc_strdup(frame,poptGetOptArg(pc));
                        if (!desthost) {
                                exit(ENOMEM);
                        }
                        if( !port )
-                               cli_cm_set_port( 139 );
+                               port = 139;
                        message = true;
                        break;
                case 'I':
@@ -4796,8 +4808,7 @@ static int do_message_op(void)
                                        exit(1);
                                }
                                have_ip = true;
-
-                               cli_cm_set_dest_ss(&dest_ss);
+                               print_sockaddr(dest_ss_str, sizeof(dest_ss_str), &dest_ss);
                        }
                        break;
                case 'E':
@@ -4877,15 +4888,13 @@ static int do_message_op(void)
        }
 
        /* if the service has already been retrieved then check if we have also a password */
-       if (service_opt && !get_cmdline_auth_info_got_pass() && poptPeekArg(pc)) {
-               set_cmdline_auth_info_password(poptGetArg(pc));
+       if (service_opt
+           && !get_cmdline_auth_info_got_pass(auth_info)
+           && poptPeekArg(pc)) {
+               set_cmdline_auth_info_password(auth_info,
+                                              poptGetArg(pc));
        }
 
-       /* check for the -P option */
-
-       if ( port != 0 )
-               cli_cm_set_port( port );
-
        /*
         * Don't load debug level from smb.conf. It should be
         * set by cmdline arg or remain default (0)
@@ -4912,6 +4921,11 @@ static int do_message_op(void)
                        argv[0], get_dyn_CONFIGFILE());
        }
 
+       if (get_cmdline_auth_info_use_machine_account(auth_info) &&
+           !set_cmdline_auth_info_machine_account_creds(auth_info)) {
+               exit(-1);
+       }
+
        load_interfaces();
 
        if (service_opt && service) {
@@ -4943,8 +4957,11 @@ static int do_message_op(void)
                calling_name = talloc_strdup(frame, global_myname() );
        }
 
-       smb_encrypt = get_cmdline_auth_info_smb_encrypt();
-       init_names();
+       smb_encrypt = get_cmdline_auth_info_smb_encrypt(auth_info);
+       if (!init_names()) {
+               fprintf(stderr, "init_names() failed\n");
+               exit(1);
+       }
 
        if(new_name_resolve_order)
                lp_set_name_resolve_order(new_name_resolve_order);
@@ -4956,11 +4973,10 @@ static int do_message_op(void)
 
        poptFreeContext(pc);
 
-       /* Store the username and password for dfs support */
-
-       cli_cm_set_credentials();
+       DEBUG(3,("Client started (version %s).\n", samba_version_string()));
 
-       DEBUG(3,("Client started (version %s).\n", SAMBA_VERSION_STRING));
+       /* Ensure we have a password (or equivalent). */
+       set_cmdline_auth_info_getpass(auth_info);
 
        if (tar_type) {
                if (cmdstr)
@@ -4984,14 +5000,13 @@ static int do_message_op(void)
                        *p = 0;
                        p++;
                        sscanf(p, "%x", &name_type);
-                       cli_cm_set_dest_name_type( name_type );
                }
 
                return do_host_query(qhost);
        }
 
        if (message) {
-               return do_message_op();
+               return do_message_op(auth_info);
        }
 
        if (process(base_directory)) {