X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source%2Fclient%2Fclient.c;h=077ca351c1fa89711dbed0a55b0456b6cbba127f;hb=531995000df77a54a4f2d7734e1ad33cd7cda37a;hp=dce99a7833997ce9a74480c81d717663fc6e7c1e;hpb=5921587ec26e4892efc678421277e4969417d7f5;p=jelmer%2Fsamba4-debian.git diff --git a/source/client/client.c b/source/client/client.c index dce99a783..077ca351c 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -22,84 +22,52 @@ */ #include "includes.h" -#ifndef REGISTER -#define REGISTER 0 -#endif - -struct smbcli_state *cli; -extern BOOL in_client; -static int port = 0; -pstring cur_dir = "\\"; -static pstring cd_path = ""; -static pstring service; -static pstring desthost; -static pstring username; -static pstring domain; -static pstring password; -static char *cmdstr = NULL; +#include "version.h" +#include "libcli/libcli.h" +#include "lib/cmdline/popt_common.h" +#include "librpc/gen_ndr/ndr_srvsvc.h" +#include "librpc/gen_ndr/ndr_lsa.h" +#include "libcli/raw/libcliraw.h" +#include "system/dir.h" +#include "system/filesys.h" +#include "dlinklist.h" +#include "system/readline.h" +#include "auth/gensec/gensec.h" +#include "system/time.h" /* needed by some systems for asctime() */ static int io_bufsize = 64512; -static int name_type = 0x20; - -static int process_tok(fstring tok); -static int cmd_help(const char **cmd_ptr); - -/* 30 second timeout on most commands */ -#define CLIENT_TIMEOUT (30*1000) -#define SHORT_TIMEOUT (5*1000) - -/* value for unused fid field in trans2 secondary request */ -#define FID_UNUSED (0xFFFF) - -time_t newer_than = 0; -static int archive_level = 0; - -static BOOL translation = False; - -/* clitar bits insert */ -extern int blocksize; -extern BOOL tar_inc; -extern BOOL tar_reset; -/* clitar bits end */ - - -static BOOL prompt = True; - -static int printmode = 1; - -static BOOL recurse = False; -BOOL lowercase = False; - -static const char *dest_ip; - -#define SEPARATORS " \t\n\r" - -static BOOL abort_mget = True; - -static pstring fileselection = ""; +struct smbclient_context { + char *remote_cur_dir; + struct smbcli_state *cli; + char *fileselection; + time_t newer_than; + BOOL prompt; + BOOL recurse; + int archive_level; + BOOL lowercase; + int printmode; + BOOL translation; +}; /* timing globals */ -uint64_t get_total_size = 0; -uint_t get_total_time_ms = 0; +static uint64_t get_total_size = 0; +static uint_t get_total_time_ms = 0; static uint64_t put_total_size = 0; static uint_t put_total_time_ms = 0; +/* Unfortunately, there is no way to pass the a context to the completion function as an argument */ +static struct smbclient_context *rl_ctx; + /* totals globals */ static double dir_total; -#define USENMB - -/* some forward declarations */ -static struct smbcli_state *do_connect(const char *server, const char *share); - - /******************************************************************* Reduce a file name, removing .. elements. ********************************************************************/ void dos_clean_name(char *s) { - char *p=NULL; + char *p=NULL,*r; DEBUG(3,("dos_clean_name [%s]\n",s)); @@ -107,17 +75,10 @@ void dos_clean_name(char *s) all_string_sub(s, "\\\\", "\\", 0); while ((p = strstr(s,"\\..\\")) != NULL) { - pstring s1; - - *p = 0; - pstrcpy(s1,p+3); - - if ((p=strrchr_m(s,'\\')) != NULL) - *p = 0; - else - *s = 0; - pstrcat(s,s1); - } + *p = '\0'; + if ((r = strrchr(s,'\\')) != NULL) + memmove(r,p+3,strlen(p+3)+1); + } trim_string(s,NULL,"\\.."); @@ -128,8 +89,9 @@ void dos_clean_name(char *s) write to a local file with CR/LF->LF translation if appropriate. return the number taken from the buffer. This may not equal the number written. ****************************************************************************/ -static int writefile(int f, char *b, int n) +static int writefile(int f, const void *_b, int n, BOOL translation) { + const uint8_t *b = _b; int i; if (!translation) { @@ -155,8 +117,9 @@ static int writefile(int f, char *b, int n) read from a file with LF->CR/LF translation if appropriate. return the number read. read approx n bytes. ****************************************************************************/ -static int readfile(char *b, int n, XFILE *f) +static int readfile(void *_b, int n, XFILE *f, BOOL translation) { + uint8_t *b = _b; int i; int c; @@ -164,7 +127,7 @@ static int readfile(char *b, int n, XFILE *f) return x_fread(b,1,n,f); i = 0; - while (i < (n - 1) && (i < CLI_BUFFER_SIZE)) { + while (i < (n - 1)) { if ((c = x_getc(f)) == EOF) { break; } @@ -183,12 +146,13 @@ static int readfile(char *b, int n, XFILE *f) /**************************************************************************** send a message ****************************************************************************/ -static void send_message(void) +static void send_message(struct smbcli_state *cli, const char *desthost) { + char msg[1600]; int total_len = 0; int grp_id; - if (!smbcli_message_start(cli->tree, desthost, username, &grp_id)) { + if (!smbcli_message_start(cli->tree, desthost, cli_credentials_get_username(cmdline_credentials), &grp_id)) { d_printf("message start: %s\n", smbcli_errstr(cli->tree)); return; } @@ -198,12 +162,9 @@ static void send_message(void) while (!feof(stdin) && total_len < 1600) { int maxlen = MIN(1600 - total_len,127); - pstring msg; int l=0; int c; - ZERO_ARRAY(msg); - for (l=0;ltree, &bsize, &total, &avail))) { - d_printf("Error in dskattr: %s\n",smbcli_errstr(cli->tree)); + if (NT_STATUS_IS_ERR(smbcli_dskattr(ctx->cli->tree, &bsize, &total, &avail))) { + d_printf("Error in dskattr: %s\n",smbcli_errstr(ctx->cli->tree)); return 1; } @@ -252,10 +213,9 @@ static int do_dskattr(void) /**************************************************************************** show cd/pwd ****************************************************************************/ -static int cmd_pwd(const char **cmd_ptr) +static int cmd_pwd(struct smbclient_context *ctx, const char **args) { - d_printf("Current directory is %s",service); - d_printf("%s\n",cur_dir); + d_printf("Current directory is %s\n", ctx->remote_cur_dir); return 0; } @@ -270,77 +230,95 @@ static void dos_format(char *s) /**************************************************************************** change directory - inner section ****************************************************************************/ -static int do_cd(char *newdir) +static int do_cd(struct smbclient_context *ctx, const char *newdir) { - char *p = newdir; - pstring saved_dir; - pstring dname; + char *dname; - dos_format(newdir); - /* Save the current directory in case the new directory is invalid */ - pstrcpy(saved_dir, cur_dir); - if (*p == '\\') - pstrcpy(cur_dir,p); + if (newdir[0] == '\\') + dname = talloc_strdup(NULL, newdir); else - pstrcat(cur_dir,p); - if (*(cur_dir+strlen(cur_dir)-1) != '\\') { - pstrcat(cur_dir, "\\"); - } - dos_clean_name(cur_dir); - pstrcpy(dname,cur_dir); - pstrcat(cur_dir,"\\"); - dos_clean_name(cur_dir); + dname = talloc_asprintf(NULL, "%s\\%s", ctx->remote_cur_dir, newdir); + + dos_format(dname); + + if (*(dname+strlen(dname)-1) != '\\') { + dname = talloc_append_string(NULL, dname, "\\"); + } + dos_clean_name(dname); - if (!strequal(cur_dir,"\\")) { - if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, dname))) { - d_printf("cd %s: %s\n", dname, smbcli_errstr(cli->tree)); - pstrcpy(cur_dir,saved_dir); - } + if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, dname))) { + d_printf("cd %s: %s\n", dname, smbcli_errstr(ctx->cli->tree)); + talloc_free(dname); + } else { + ctx->remote_cur_dir = dname; } - pstrcpy(cd_path,cur_dir); - return 0; } /**************************************************************************** change directory ****************************************************************************/ -static int cmd_cd(const char **cmd_ptr) +static int cmd_cd(struct smbclient_context *ctx, const char **args) { - fstring buf; int rc = 0; - if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) - rc = do_cd(buf); + if (args[1]) + rc = do_cd(ctx, args[1]); else - d_printf("Current directory is %s\n",cur_dir); + d_printf("Current directory is %s\n",ctx->remote_cur_dir); return rc; } +BOOL mask_match(struct smbcli_state *c, const char *string, const char *pattern, + BOOL is_case_sensitive) +{ + char *p2, *s2; + BOOL ret; + + if (strcmp(string,"..") == 0) + string = "."; + if (strcmp(pattern,".") == 0) + 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; +} + + + /******************************************************************* decide if a file should be operated on ********************************************************************/ -static BOOL do_this_one(file_info *finfo) +static BOOL do_this_one(struct smbclient_context *ctx, struct clilist_file_info *finfo) { - if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) return(True); + if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) return(True); - if (*fileselection && - !mask_match(cli, finfo->name,fileselection,False)) { + if (ctx->fileselection && + !mask_match(ctx->cli, finfo->name,ctx->fileselection,False)) { DEBUG(3,("mask_match %s failed\n", finfo->name)); return False; } - if (newer_than && finfo->mtime < newer_than) { + if (ctx->newer_than && finfo->mtime < ctx->newer_than) { DEBUG(3,("newer_than %s failed\n", finfo->name)); return(False); } - if ((archive_level==1 || archive_level==2) && !(finfo->mode & FILE_ATTRIBUTE_ARCHIVE)) { + if ((ctx->archive_level==1 || ctx->archive_level==2) && !(finfo->attrib & FILE_ATTRIBUTE_ARCHIVE)) { DEBUG(3,("archive %s failed\n", finfo->name)); return(False); } @@ -351,11 +329,11 @@ static BOOL do_this_one(file_info *finfo) /**************************************************************************** display info about a file ****************************************************************************/ -static void display_finfo(file_info *finfo) +static void display_finfo(struct smbclient_context *ctx, struct clilist_file_info *finfo) { - if (do_this_one(finfo)) { + if (do_this_one(ctx, finfo)) { time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */ - char *astr = attrib_string(NULL, finfo->mode); + char *astr = attrib_string(NULL, finfo->attrib); d_printf(" %-30s%7.7s %8.0f %s", finfo->name, astr, @@ -370,9 +348,9 @@ static void display_finfo(file_info *finfo) /**************************************************************************** accumulate size of a file ****************************************************************************/ -static void do_du(file_info *finfo) +static void do_du(struct smbclient_context *ctx, struct clilist_file_info *finfo) { - if (do_this_one(finfo)) { + if (do_this_one(ctx, finfo)) { dir_total += finfo->size; } } @@ -383,7 +361,7 @@ static char *do_list_queue = 0; static long do_list_queue_size = 0; static long do_list_queue_start = 0; static long do_list_queue_end = 0; -static void (*do_list_fn)(file_info *); +static void (*do_list_fn)(struct smbclient_context *, struct clilist_file_info *); /**************************************************************************** functions for do_list_queue @@ -455,7 +433,7 @@ static void add_to_do_list_queue(const char* entry) do_list_queue_size *= 2; DEBUG(4,("enlarging do_list_queue to %d\n", (int)do_list_queue_size)); - dlq = Realloc(do_list_queue, do_list_queue_size); + dlq = realloc_p(do_list_queue, char, do_list_queue_size); if (! dlq) { d_printf("failure enlarging do_list_queue to %d bytes\n", (int)do_list_queue_size); @@ -502,31 +480,32 @@ static int do_list_queue_empty(void) /**************************************************************************** a helper for do_list ****************************************************************************/ -static void do_list_helper(file_info *f, const char *mask, void *state) +static void do_list_helper(struct clilist_file_info *f, const char *mask, void *state) { - if (f->mode & FILE_ATTRIBUTE_DIRECTORY) { - if (do_list_dirs && do_this_one(f)) { - do_list_fn(f); + struct smbclient_context *ctx = state; + + if (f->attrib & FILE_ATTRIBUTE_DIRECTORY) { + if (do_list_dirs && do_this_one(ctx, f)) { + do_list_fn(ctx, f); } if (do_list_recurse && !strequal(f->name,".") && !strequal(f->name,"..")) { - pstring mask2; + char *mask2; char *p; - pstrcpy(mask2, mask); + mask2 = talloc_strdup(NULL, mask); p = strrchr_m(mask2,'\\'); if (!p) return; p[1] = 0; - pstrcat(mask2, f->name); - pstrcat(mask2,"\\*"); + mask2 = talloc_asprintf_append(mask2, "%s\\*", f->name); add_to_do_list_queue(mask2); } return; } - if (do_this_one(f)) { - do_list_fn(f); + if (do_this_one(ctx, f)) { + do_list_fn(ctx, f); } } @@ -534,7 +513,8 @@ static void do_list_helper(file_info *f, const char *mask, void *state) /**************************************************************************** a wrapper around smbcli_list that adds recursion ****************************************************************************/ -void do_list(const char *mask,uint16_t attribute,void (*fn)(file_info *),BOOL rec, BOOL dirs) +static void do_list(struct smbclient_context *ctx, const char *mask,uint16_t attribute, + void (*fn)(struct smbclient_context *, struct clilist_file_info *),BOOL rec, BOOL dirs) { static int in_do_list = 0; @@ -564,9 +544,9 @@ void do_list(const char *mask,uint16_t attribute,void (*fn)(file_info *),BOOL re * during the call. * Fix from E. Jay Berkenbilt (ejb@ql.org) */ - pstring head; - pstrcpy(head, do_list_queue_head()); - smbcli_list(cli->tree, head, attribute, do_list_helper, NULL); + char *head; + head = do_list_queue_head(); + smbcli_list(ctx->cli->tree, head, attribute, do_list_helper, ctx); remove_do_list_queue_head(); if ((! do_list_queue_empty()) && (fn == display_finfo)) { @@ -590,9 +570,9 @@ void do_list(const char *mask,uint16_t attribute,void (*fn)(file_info *),BOOL re } else { - if (smbcli_list(cli->tree, mask, attribute, do_list_helper, NULL) == -1) + if (smbcli_list(ctx->cli->tree, mask, attribute, do_list_helper, ctx) == -1) { - d_printf("%s listing %s\n", smbcli_errstr(cli->tree), mask); + d_printf("%s listing %s\n", smbcli_errstr(ctx->cli->tree), mask); } } @@ -603,38 +583,36 @@ void do_list(const char *mask,uint16_t attribute,void (*fn)(file_info *),BOOL re /**************************************************************************** get a directory listing ****************************************************************************/ -static int cmd_dir(const char **cmd_ptr) +static int cmd_dir(struct smbclient_context *ctx, const char **args) { uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN; - pstring mask; - fstring buf; - char *p=buf; + char *mask; int rc; dir_total = 0; - pstrcpy(mask,cur_dir); + + mask = talloc_strdup(ctx, ctx->remote_cur_dir); if(mask[strlen(mask)-1]!='\\') - pstrcat(mask,"\\"); + mask = talloc_append_string(ctx, mask,"\\"); - if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) { - dos_format(p); - if (*p == '\\') - pstrcpy(mask,p); - else - pstrcat(mask,p); + if (args[1]) { + mask = talloc_strdup(ctx, args[1]); + if (mask[0] != '\\') + mask = talloc_append_string(ctx, mask, "\\"); + dos_format(mask); } else { - if (cli->tree->session->transport->negotiate.protocol <= + if (ctx->cli->tree->session->transport->negotiate.protocol <= PROTOCOL_LANMAN1) { - pstrcat(mask,"*.*"); + mask = talloc_append_string(ctx, mask, "*.*"); } else { - pstrcat(mask,"*"); + mask = talloc_append_string(ctx, mask, "*"); } } - do_list(mask, attribute, display_finfo, recurse, True); + do_list(ctx, mask, attribute, display_finfo, ctx->recurse, True); - rc = do_dskattr(); + rc = do_dskattr(ctx); DEBUG(3, ("Total bytes listed: %.0f\n", dir_total)); @@ -645,32 +623,29 @@ static int cmd_dir(const char **cmd_ptr) /**************************************************************************** get a directory listing ****************************************************************************/ -static int cmd_du(const char **cmd_ptr) +static int cmd_du(struct smbclient_context *ctx, const char **args) { uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN; - pstring mask; - fstring buf; - char *p=buf; int rc; + char *mask; dir_total = 0; - pstrcpy(mask,cur_dir); - if(mask[strlen(mask)-1]!='\\') - pstrcat(mask,"\\"); - if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) { - dos_format(p); - if (*p == '\\') - pstrcpy(mask,p); + if (args[1]) { + if (args[1][0] == '\\') + mask = talloc_strdup(ctx, args[1]); else - pstrcat(mask,p); + mask = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]); + dos_format(mask); } else { - pstrcat(mask,"\\*"); + mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir); } - do_list(mask, attribute, do_du, recurse, True); + do_list(ctx, mask, attribute, do_du, ctx->recurse, True); + + talloc_free(mask); - rc = do_dskattr(); + rc = do_dskattr(ctx); d_printf("Total number of bytes: %.0f\n", dir_total); @@ -681,11 +656,11 @@ static int cmd_du(const char **cmd_ptr) /**************************************************************************** get a file from rname to lname ****************************************************************************/ -static int do_get(char *rname, const char *lname, BOOL reget) +static int do_get(struct smbclient_context *ctx, char *rname, const char *lname, BOOL reget) { int handle = 0, fnum; BOOL newhandle = False; - char *data; + uint8_t *data; struct timeval tp_start; int read_size = io_bufsize; uint16_t attr; @@ -696,14 +671,14 @@ static int do_get(char *rname, const char *lname, BOOL reget) GetTimeOfDay(&tp_start); - if (lowercase) { + if (ctx->lowercase) { strlower(discard_const_p(char, lname)); } - fnum = smbcli_open(cli->tree, rname, O_RDONLY, DENY_NONE); + fnum = smbcli_open(ctx->cli->tree, rname, O_RDONLY, DENY_NONE); if (fnum == -1) { - d_printf("%s opening remote file %s\n",smbcli_errstr(cli->tree),rname); + d_printf("%s opening remote file %s\n",smbcli_errstr(ctx->cli->tree),rname); return 1; } @@ -711,16 +686,16 @@ static int do_get(char *rname, const char *lname, BOOL reget) handle = fileno(stdout); } else { if (reget) { - handle = sys_open(lname, O_WRONLY|O_CREAT, 0644); + handle = open(lname, O_WRONLY|O_CREAT, 0644); if (handle >= 0) { - start = sys_lseek(handle, 0, SEEK_END); + start = lseek(handle, 0, SEEK_END); if (start == -1) { d_printf("Error seeking local file\n"); return 1; } } } else { - handle = sys_open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644); + handle = open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644); } newhandle = True; } @@ -730,29 +705,29 @@ static int do_get(char *rname, const char *lname, BOOL reget) } - if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, + if (NT_STATUS_IS_ERR(smbcli_qfileinfo(ctx->cli->tree, fnum, &attr, &size, NULL, NULL, NULL, NULL, NULL)) && - NT_STATUS_IS_ERR(smbcli_getattrE(cli->tree, fnum, + NT_STATUS_IS_ERR(smbcli_getattrE(ctx->cli->tree, fnum, &attr, &size, NULL, NULL, NULL))) { - d_printf("getattrib: %s\n",smbcli_errstr(cli->tree)); + d_printf("getattrib: %s\n",smbcli_errstr(ctx->cli->tree)); return 1; } DEBUG(2,("getting file %s of size %.0f as %s ", rname, (double)size, lname)); - if(!(data = (char *)malloc(read_size))) { + if(!(data = (uint8_t *)malloc(read_size))) { d_printf("malloc fail for size %d\n", read_size); - smbcli_close(cli->tree, fnum); + smbcli_close(ctx->cli->tree, fnum); return 1; } while (1) { - int n = smbcli_read(cli->tree, fnum, data, nread + start, read_size); + int n = smbcli_read(ctx->cli->tree, fnum, data, nread + start, read_size); if (n <= 0) break; - if (writefile(handle,data, n) != n) { + if (writefile(handle,data, n, ctx->translation) != n) { d_printf("Error writing local file\n"); rc = 1; break; @@ -770,8 +745,8 @@ static int do_get(char *rname, const char *lname, BOOL reget) SAFE_FREE(data); - if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) { - d_printf("Error %s closing remote file\n",smbcli_errstr(cli->tree)); + if (NT_STATUS_IS_ERR(smbcli_close(ctx->cli->tree, fnum))) { + d_printf("Error %s closing remote file\n",smbcli_errstr(ctx->cli->tree)); rc = 1; } @@ -779,8 +754,8 @@ static int do_get(char *rname, const char *lname, BOOL reget) close(handle); } - if (archive_level >= 2 && (attr & FILE_ATTRIBUTE_ARCHIVE)) { - smbcli_setatr(cli->tree, rname, attr & ~(uint16_t)FILE_ATTRIBUTE_ARCHIVE, 0); + if (ctx->archive_level >= 2 && (attr & FILE_ATTRIBUTE_ARCHIVE)) { + smbcli_setatr(ctx->cli->tree, rname, attr & ~(uint16_t)FILE_ATTRIBUTE_ARCHIVE, 0); } { @@ -806,131 +781,138 @@ static int do_get(char *rname, const char *lname, BOOL reget) /**************************************************************************** get a file ****************************************************************************/ -static int cmd_get(const char **cmd_ptr) +static int cmd_get(struct smbclient_context *ctx, const char **args) { - pstring lname; - pstring rname; - char *p; + const char *lname; + char *rname; - pstrcpy(rname,cur_dir); - pstrcat(rname,"\\"); - - p = rname + strlen(rname); - - if (!next_token(cmd_ptr,p,NULL,sizeof(rname)-strlen(rname))) { + if (!args[1]) { d_printf("get \n"); return 1; } - pstrcpy(lname,p); - dos_clean_name(rname); + + rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]); + + if (args[2]) + lname = args[2]; + else + lname = args[1]; - next_token(cmd_ptr,lname,NULL,sizeof(lname)); + dos_clean_name(rname); - return do_get(rname, lname, False); + return do_get(ctx, rname, lname, False); } +/**************************************************************************** + Put up a yes/no prompt. +****************************************************************************/ +static BOOL yesno(char *p) +{ + char ans[4]; + printf("%s",p); + + if (!fgets(ans,sizeof(ans)-1,stdin)) + return(False); + + if (*ans == 'y' || *ans == 'Y') + return(True); + + return(False); +} /**************************************************************************** do a mget operation on one file ****************************************************************************/ -static void do_mget(file_info *finfo) +static void do_mget(struct smbclient_context *ctx, struct clilist_file_info *finfo) { - pstring rname; - pstring quest; - pstring saved_curdir; - pstring mget_mask; + char *rname; + char *quest; + char *mget_mask; + char *saved_curdir; if (strequal(finfo->name,".") || strequal(finfo->name,"..")) return; - if (abort_mget) { - d_printf("mget aborted\n"); - return; - } - - if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) - slprintf(quest,sizeof(pstring)-1, - "Get directory %s? ",finfo->name); + if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) + asprintf(&quest, "Get directory %s? ",finfo->name); else - slprintf(quest,sizeof(pstring)-1, - "Get file %s? ",finfo->name); + asprintf(&quest, "Get file %s? ",finfo->name); - if (prompt && !yesno(quest)) return; + if (ctx->prompt && !yesno(quest)) return; - if (!(finfo->mode & FILE_ATTRIBUTE_DIRECTORY)) { - pstrcpy(rname,cur_dir); - pstrcat(rname,finfo->name); - do_get(rname, finfo->name, False); + SAFE_FREE(quest); + + if (!(finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)) { + asprintf(&rname, "%s%s",ctx->remote_cur_dir,finfo->name); + do_get(ctx, rname, finfo->name, False); + SAFE_FREE(rname); return; } /* handle directories */ - pstrcpy(saved_curdir,cur_dir); + saved_curdir = talloc_strdup(NULL, ctx->remote_cur_dir); - pstrcat(cur_dir,finfo->name); - pstrcat(cur_dir,"\\"); + ctx->remote_cur_dir = talloc_asprintf_append(NULL, "%s\\", finfo->name); string_replace(discard_const_p(char, finfo->name), '\\', '/'); - if (lowercase) { + if (ctx->lowercase) { strlower(discard_const_p(char, finfo->name)); } - if (!directory_exist(finfo->name,NULL) && + if (!directory_exist(finfo->name) && mkdir(finfo->name,0777) != 0) { d_printf("failed to create directory %s\n",finfo->name); - pstrcpy(cur_dir,saved_curdir); return; } if (chdir(finfo->name) != 0) { d_printf("failed to chdir to directory %s\n",finfo->name); - pstrcpy(cur_dir,saved_curdir); return; } - pstrcpy(mget_mask,cur_dir); - pstrcat(mget_mask,"*"); + mget_mask = talloc_asprintf(NULL, "%s*", ctx->remote_cur_dir); - do_list(mget_mask, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,do_mget,False, True); + do_list(ctx, mget_mask, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,do_mget,False, True); chdir(".."); - pstrcpy(cur_dir,saved_curdir); + talloc_free(ctx->remote_cur_dir); + + ctx->remote_cur_dir = saved_curdir; } /**************************************************************************** view the file using the pager ****************************************************************************/ -static int cmd_more(const char **cmd_ptr) +static int cmd_more(struct smbclient_context *ctx, const char **args) { - fstring rname,lname,pager_cmd; + char *rname; + char *pager_cmd; + char *lname; char *pager; int fd; int rc = 0; - fstrcpy(rname,cur_dir); - fstrcat(rname,"\\"); - - slprintf(lname,sizeof(lname)-1, "%s/smbmore.XXXXXX",tmpdir()); - fd = smb_mkstemp(lname); + lname = talloc_asprintf(ctx, "%s/smbmore.XXXXXX",tmpdir()); + fd = mkstemp(lname); if (fd == -1) { d_printf("failed to create temporary file for more\n"); return 1; } close(fd); - if (!next_token(cmd_ptr,rname+strlen(rname),NULL,sizeof(rname)-strlen(rname))) { + if (!args[1]) { d_printf("more \n"); unlink(lname); return 1; } + rname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]); dos_clean_name(rname); - rc = do_get(rname, lname, False); + rc = do_get(ctx, rname, lname, False); pager=getenv("PAGER"); - slprintf(pager_cmd,sizeof(pager_cmd)-1, - "%s %s",(pager? pager:PAGER), lname); + pager_cmd = talloc_asprintf(ctx, "%s %s",(pager? pager:PAGER), lname); system(pager_cmd); unlink(lname); @@ -942,39 +924,32 @@ static int cmd_more(const char **cmd_ptr) /**************************************************************************** do a mget command ****************************************************************************/ -static int cmd_mget(const char **cmd_ptr) +static int cmd_mget(struct smbclient_context *ctx, const char **args) { uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN; - pstring mget_mask; - fstring buf; - char *p=buf; - - *mget_mask = 0; + char *mget_mask; + int i; - if (recurse) + if (ctx->recurse) attribute |= FILE_ATTRIBUTE_DIRECTORY; - abort_mget = False; - - while (next_token(cmd_ptr,p,NULL,sizeof(buf))) { - pstrcpy(mget_mask,cur_dir); + for (i = 1; args[i]; i++) { + mget_mask = talloc_strdup(ctx,ctx->remote_cur_dir); if(mget_mask[strlen(mget_mask)-1]!='\\') - pstrcat(mget_mask,"\\"); + mget_mask = talloc_append_string(ctx, mget_mask, "\\"); - if (*p == '\\') - pstrcpy(mget_mask,p); - else - pstrcat(mget_mask,p); - do_list(mget_mask, attribute,do_mget,False,True); + mget_mask = talloc_strdup(ctx, args[i]); + if (mget_mask[0] != '\\') + mget_mask = talloc_append_string(ctx, mget_mask, "\\"); + do_list(ctx, mget_mask, attribute,do_mget,False,True); } if (!*mget_mask) { - pstrcpy(mget_mask,cur_dir); - if(mget_mask[strlen(mget_mask)-1]!='\\') - pstrcat(mget_mask,"\\"); - pstrcat(mget_mask,"*"); - do_list(mget_mask, attribute,do_mget,False,True); + mget_mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir); + do_list(ctx, mget_mask, attribute,do_mget,False,True); } + + talloc_free(mget_mask); return 0; } @@ -983,42 +958,26 @@ static int cmd_mget(const char **cmd_ptr) /**************************************************************************** make a directory of name "name" ****************************************************************************/ -static NTSTATUS do_mkdir(char *name) +static NTSTATUS do_mkdir(struct smbclient_context *ctx, char *name) { NTSTATUS status; - if (NT_STATUS_IS_ERR(status = smbcli_mkdir(cli->tree, name))) { + if (NT_STATUS_IS_ERR(status = smbcli_mkdir(ctx->cli->tree, name))) { d_printf("%s making remote directory %s\n", - smbcli_errstr(cli->tree),name); + smbcli_errstr(ctx->cli->tree),name); return status; } return status; } -/**************************************************************************** -show 8.3 name of a file -****************************************************************************/ -static BOOL do_altname(char *name) -{ - const char *altname; - if (!NT_STATUS_IS_OK(smbcli_qpathinfo_alt_name(cli->tree, name, &altname))) { - d_printf("%s getting alt name for %s\n", - smbcli_errstr(cli->tree),name); - return(False); - } - d_printf("%s\n", altname); - - return(True); -} - /**************************************************************************** Exit client. ****************************************************************************/ -static int cmd_quit(const char **cmd_ptr) +static int cmd_quit(struct smbclient_context *ctx, const char **args) { - smbcli_shutdown(cli); + talloc_free(ctx); exit(0); /* NOTREACHED */ return 0; @@ -1028,63 +987,59 @@ static int cmd_quit(const char **cmd_ptr) /**************************************************************************** make a directory ****************************************************************************/ -static int cmd_mkdir(const char **cmd_ptr) +static int cmd_mkdir(struct smbclient_context *ctx, const char **args) { - pstring mask; - fstring buf; - char *p=buf; + char *mask, *p; - pstrcpy(mask,cur_dir); - - if (!next_token(cmd_ptr,p,NULL,sizeof(buf))) { - if (!recurse) + if (!args[1]) { + if (!ctx->recurse) d_printf("mkdir \n"); return 1; } - pstrcat(mask,p); - if (recurse) { - pstring ddir; - pstring ddir2; - *ddir2 = 0; - - pstrcpy(ddir,mask); - trim_string(ddir,".",NULL); - p = strtok(ddir,"/\\"); - while (p) { - pstrcat(ddir2,p); - if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, ddir2))) { - do_mkdir(ddir2); + mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir,args[1]); + + if (ctx->recurse) { + dos_clean_name(mask); + + trim_string(mask,".",NULL); + for (p = strtok(mask,"/\\"); p; p = strtok(p, "/\\")) { + char *parent = talloc_strndup(ctx, mask, PTR_DIFF(p, mask)); + + if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, parent))) { + do_mkdir(ctx, parent); } - pstrcat(ddir2,"\\"); - p = strtok(NULL,"/\\"); + + talloc_free(parent); } } else { - do_mkdir(mask); + do_mkdir(ctx, mask); } return 0; } - /**************************************************************************** - show alt name - ****************************************************************************/ -static int cmd_altname(const char **cmd_ptr) +show 8.3 name of a file +****************************************************************************/ +static int cmd_altname(struct smbclient_context *ctx, const char **args) { - pstring name; - fstring buf; - char *p=buf; + const char *altname; + char *name; - pstrcpy(name,cur_dir); - - if (!next_token(cmd_ptr,p,NULL,sizeof(buf))) { + if (!args[1]) { d_printf("altname \n"); return 1; } - pstrcat(name,p); - do_altname(name); + name = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]); + + if (!NT_STATUS_IS_OK(smbcli_qpathinfo_alt_name(ctx->cli->tree, name, &altname))) { + d_printf("%s getting alt name for %s\n", + smbcli_errstr(ctx->cli->tree),name); + return(False); + } + d_printf("%s\n", altname); return 0; } @@ -1093,13 +1048,13 @@ static int cmd_altname(const char **cmd_ptr) /**************************************************************************** put a single file ****************************************************************************/ -static int do_put(char *rname, char *lname, BOOL reput) +static int do_put(struct smbclient_context *ctx, char *rname, char *lname, BOOL reput) { int fnum; XFILE *f; size_t start = 0; off_t nread = 0; - char *buf = NULL; + uint8_t *buf = NULL; int maxwrite = io_bufsize; int rc = 0; @@ -1107,21 +1062,21 @@ static int do_put(char *rname, char *lname, BOOL reput) GetTimeOfDay(&tp_start); if (reput) { - fnum = smbcli_open(cli->tree, rname, O_RDWR|O_CREAT, DENY_NONE); + fnum = smbcli_open(ctx->cli->tree, rname, O_RDWR|O_CREAT, DENY_NONE); if (fnum >= 0) { - if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL)) && - NT_STATUS_IS_ERR(smbcli_getattrE(cli->tree, fnum, NULL, &start, NULL, NULL, NULL))) { - d_printf("getattrib: %s\n",smbcli_errstr(cli->tree)); + if (NT_STATUS_IS_ERR(smbcli_qfileinfo(ctx->cli->tree, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL)) && + NT_STATUS_IS_ERR(smbcli_getattrE(ctx->cli->tree, fnum, NULL, &start, NULL, NULL, NULL))) { + d_printf("getattrib: %s\n",smbcli_errstr(ctx->cli->tree)); return 1; } } } else { - fnum = smbcli_open(cli->tree, rname, O_RDWR|O_CREAT|O_TRUNC, + fnum = smbcli_open(ctx->cli->tree, rname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE); } if (fnum == -1) { - d_printf("%s opening remote file %s\n",smbcli_errstr(cli->tree),rname); + d_printf("%s opening remote file %s\n",smbcli_errstr(ctx->cli->tree),rname); return 1; } @@ -1152,7 +1107,7 @@ static int do_put(char *rname, char *lname, BOOL reput) DEBUG(1,("putting file %s as %s ",lname, rname)); - buf = (char *)malloc(maxwrite); + buf = (uint8_t *)malloc(maxwrite); if (!buf) { d_printf("ERROR: Not enough memory!\n"); return 1; @@ -1161,7 +1116,7 @@ static int do_put(char *rname, char *lname, BOOL reput) int n = maxwrite; int ret; - if ((n = readfile(buf,n,f)) < 1) { + if ((n = readfile(buf,n,f,ctx->translation)) < 1) { if((n == 0) && x_feof(f)) break; /* Empty local file. */ @@ -1170,10 +1125,10 @@ static int do_put(char *rname, char *lname, BOOL reput) break; } - ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n); + ret = smbcli_write(ctx->cli->tree, fnum, 0, buf, nread + start, n); if (n != ret) { - d_printf("Error writing file: %s\n", smbcli_errstr(cli->tree)); + d_printf("Error writing file: %s\n", smbcli_errstr(ctx->cli->tree)); rc = 1; break; } @@ -1181,8 +1136,8 @@ static int do_put(char *rname, char *lname, BOOL reput) nread += n; } - if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) { - d_printf("%s closing remote file %s\n",smbcli_errstr(cli->tree),rname); + if (NT_STATUS_IS_ERR(smbcli_close(ctx->cli->tree, fnum))) { + d_printf("%s closing remote file %s\n",smbcli_errstr(ctx->cli->tree),rname); x_fclose(f); SAFE_FREE(buf); return 1; @@ -1212,7 +1167,7 @@ static int do_put(char *rname, char *lname, BOOL reput) } if (f == x_stdin) { - smbcli_shutdown(cli); + talloc_free(ctx); exit(0); } @@ -1224,41 +1179,33 @@ static int do_put(char *rname, char *lname, BOOL reput) /**************************************************************************** put a file ****************************************************************************/ -static int cmd_put(const char **cmd_ptr) +static int cmd_put(struct smbclient_context *ctx, const char **args) { - pstring lname; - pstring rname; - fstring buf; - char *p=buf; + char *lname; + char *rname; - pstrcpy(rname,cur_dir); - pstrcat(rname,"\\"); - - if (!next_token(cmd_ptr,p,NULL,sizeof(buf))) { + if (!args[1]) { d_printf("put \n"); return 1; } - pstrcpy(lname,p); + + lname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]); - if (next_token(cmd_ptr,p,NULL,sizeof(buf))) - pstrcat(rname,p); + if (args[2]) + rname = talloc_strdup(ctx, args[2]); else - pstrcat(rname,lname); + rname = talloc_strdup(ctx, lname); dos_clean_name(rname); - { - SMB_STRUCT_STAT st; - /* allow '-' to represent stdin - jdblair, 24.jun.98 */ - if (!file_exist(lname,&st) && - (strcmp(lname,"-"))) { - d_printf("%s does not exist\n",lname); - return 1; - } + /* allow '-' to represent stdin + jdblair, 24.jun.98 */ + if (!file_exist(lname) && (strcmp(lname,"-"))) { + d_printf("%s does not exist\n",lname); + return 1; } - return do_put(rname, lname, False); + return do_put(ctx, rname, lname, False); } /************************************* @@ -1308,19 +1255,56 @@ static BOOL seek_list(struct file_list *list, char *name) /**************************************************************************** set the file selection mask ****************************************************************************/ -static int cmd_select(const char **cmd_ptr) +static int cmd_select(struct smbclient_context *ctx, const char **args) { - pstrcpy(fileselection,""); - next_token(cmd_ptr,fileselection,NULL,sizeof(fileselection)); + talloc_free(ctx->fileselection); + ctx->fileselection = talloc_strdup(NULL, args[1]); return 0; } +/******************************************************************* + A readdir wrapper which just returns the file name. + ********************************************************************/ +static const char *readdirname(DIR *p) +{ + struct dirent *ptr; + char *dname; + + if (!p) + return(NULL); + + ptr = (struct dirent *)readdir(p); + if (!ptr) + return(NULL); + + dname = ptr->d_name; + +#ifdef NEXT2 + if (telldir(p) < 0) + return(NULL); +#endif + +#ifdef HAVE_BROKEN_READDIR + /* using /usr/ucb/cc is BAD */ + dname = dname - 2; +#endif + + { + static char *buf; + int len = NAMLEN(ptr); + buf = talloc_strndup(NULL, dname, len); + dname = buf; + } + + return(dname); +} + /**************************************************************************** Recursive file matching function act as find match must be always set to True when calling this function ****************************************************************************/ -static int file_find(struct file_list **list, const char *directory, +static int file_find(struct smbclient_context *ctx, struct file_list **list, const char *directory, const char *expression, BOOL match) { DIR *dir; @@ -1344,12 +1328,12 @@ static int file_find(struct file_list **list, const char *directory, isdir = False; if (!match || !gen_fnmatch(expression, dname)) { - if (recurse) { + if (ctx->recurse) { ret = stat(path, &statbuf); if (ret == 0) { if (S_ISDIR(statbuf.st_mode)) { isdir = True; - ret = file_find(list, path, expression, False); + ret = file_find(ctx, list, path, expression, False); } } else { d_printf("file_find: cannot stat file %s\n", path); @@ -1361,7 +1345,7 @@ static int file_find(struct file_list **list, const char *directory, return -1; } } - entry = (struct file_list *) malloc(sizeof (struct file_list)); + entry = malloc_p(struct file_list); if (!entry) { d_printf("Out of memory in file_find\n"); closedir(dir); @@ -1382,19 +1366,20 @@ static int file_find(struct file_list **list, const char *directory, /**************************************************************************** mput some files ****************************************************************************/ -static int cmd_mput(const char **cmd_ptr) +static int cmd_mput(struct smbclient_context *ctx, const char **args) { - fstring buf; - char *p=buf; + int i; - while (next_token(cmd_ptr,p,NULL,sizeof(buf))) { + for (i = 1; args[i]; i++) { int ret; struct file_list *temp_list; char *quest, *lname, *rname; + + printf("%s\n", args[i]); file_list = NULL; - ret = file_find(&file_list, ".", p, True); + ret = file_find(ctx, &file_list, ".", args[i], True); if (ret) { free_file_list(file_list); continue; @@ -1418,17 +1403,17 @@ static int cmd_mput(const char **cmd_ptr) SAFE_FREE(quest); if (asprintf(&quest, "Put directory %s? ", lname) < 0) break; - if (prompt && !yesno(quest)) { /* No */ + if (ctx->prompt && !yesno(quest)) { /* No */ /* Skip the directory */ lname[strlen(lname)-1] = '/'; if (!seek_list(temp_list, lname)) break; } else { /* Yes */ SAFE_FREE(rname); - if(asprintf(&rname, "%s%s", cur_dir, lname) < 0) break; + if(asprintf(&rname, "%s%s", ctx->remote_cur_dir, lname) < 0) break; dos_format(rname); - if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, rname)) && - NT_STATUS_IS_ERR(do_mkdir(rname))) { + if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, rname)) && + NT_STATUS_IS_ERR(do_mkdir(ctx, rname))) { DEBUG (0, ("Unable to make dir, skipping...")); /* Skip the directory */ lname[strlen(lname)-1] = '/'; @@ -1440,17 +1425,17 @@ static int cmd_mput(const char **cmd_ptr) } else { SAFE_FREE(quest); if (asprintf(&quest,"Put file %s? ", lname) < 0) break; - if (prompt && !yesno(quest)) /* No */ + if (ctx->prompt && !yesno(quest)) /* No */ continue; /* Yes */ SAFE_FREE(rname); - if (asprintf(&rname, "%s%s", cur_dir, lname) < 0) break; + if (asprintf(&rname, "%s%s", ctx->remote_cur_dir, lname) < 0) break; } dos_format(rname); - do_put(rname, lname, False); + do_put(ctx, rname, lname, False); } free_file_list(file_list); SAFE_FREE(quest); @@ -1462,52 +1447,22 @@ static int cmd_mput(const char **cmd_ptr) } -/**************************************************************************** - cancel a print job - ****************************************************************************/ -static int do_cancel(int job) -{ - d_printf("REWRITE: print job cancel not implemented\n"); - return 1; -} - - -/**************************************************************************** - cancel a print job - ****************************************************************************/ -static int cmd_cancel(const char **cmd_ptr) -{ - fstring buf; - int job; - - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) { - d_printf("cancel ...\n"); - return 1; - } - do { - job = atoi(buf); - do_cancel(job); - } while (next_token(cmd_ptr,buf,NULL,sizeof(buf))); - - return 0; -} - - /**************************************************************************** print a file ****************************************************************************/ -static int cmd_print(const char **cmd_ptr) +static int cmd_print(struct smbclient_context *ctx, const char **args) { - pstring lname; - pstring rname; + char *lname, *rname; char *p; - if (!next_token(cmd_ptr,lname,NULL, sizeof(lname))) { + if (!args[1]) { d_printf("print \n"); return 1; } - pstrcpy(rname,lname); + lname = talloc_strdup(ctx, args[1]); + + rname = talloc_strdup(ctx, lname); p = strrchr_m(rname,'/'); if (p) { slprintf(rname, sizeof(rname)-1, "%s-%d", p+1, (int)getpid()); @@ -1517,16 +1472,13 @@ static int cmd_print(const char **cmd_ptr) slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)getpid()); } - return do_put(rname, lname, False); + return do_put(ctx, rname, lname, False); } -/**************************************************************************** - show a print queue -****************************************************************************/ -static int cmd_queue(const char **cmd_ptr) +static int cmd_rewrite(struct smbclient_context *ctx, const char **args) { - d_printf("REWRITE: print job queue not implemented\n"); + d_printf("REWRITE: command not implemented (FIXME!)\n"); return 0; } @@ -1534,25 +1486,22 @@ static int cmd_queue(const char **cmd_ptr) /**************************************************************************** delete some files ****************************************************************************/ -static int cmd_del(const char **cmd_ptr) +static int cmd_del(struct smbclient_context *ctx, const char **args) { - pstring mask; - fstring buf; + char *mask; uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN; - if (recurse) + if (ctx->recurse) attribute |= FILE_ATTRIBUTE_DIRECTORY; - pstrcpy(mask,cur_dir); - - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) { + if (!args[1]) { d_printf("del \n"); return 1; } - pstrcat(mask,buf); + mask = talloc_asprintf(ctx,"%s%s", ctx->remote_cur_dir, args[1]); - if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, mask))) { - d_printf("%s deleting remote file %s\n",smbcli_errstr(cli->tree),mask); + if (NT_STATUS_IS_ERR(smbcli_unlink(ctx->cli->tree, mask))) { + d_printf("%s deleting remote file %s\n",smbcli_errstr(ctx->cli->tree),mask); } return 0; @@ -1562,24 +1511,22 @@ static int cmd_del(const char **cmd_ptr) /**************************************************************************** delete a whole directory tree ****************************************************************************/ -static int cmd_deltree(const char **cmd_ptr) +static int cmd_deltree(struct smbclient_context *ctx, const char **args) { - pstring dname; - fstring buf; + char *dname; int ret; - pstrcpy(dname,cur_dir); - - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) { + if (!args[1]) { d_printf("deltree \n"); return 1; } - pstrcat(dname,buf); - ret = smbcli_deltree(cli->tree, dname); + dname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]); + + ret = smbcli_deltree(ctx->cli->tree, dname); if (ret == -1) { - printf("Failed to delete tree %s - %s\n", dname, smbcli_errstr(cli->tree)); + printf("Failed to delete tree %s - %s\n", dname, smbcli_errstr(ctx->cli->tree)); return -1; } @@ -1588,43 +1535,206 @@ static int cmd_deltree(const char **cmd_ptr) return 0; } +typedef struct { + const char *level_name; + enum smb_fsinfo_level level; +} fsinfo_level_t; + +fsinfo_level_t fsinfo_levels[] = { + {"dskattr", RAW_QFS_DSKATTR}, + {"allocation", RAW_QFS_ALLOCATION}, + {"volume", RAW_QFS_VOLUME}, + {"volumeinfo", RAW_QFS_VOLUME_INFO}, + {"sizeinfo", RAW_QFS_SIZE_INFO}, + {"deviceinfo", RAW_QFS_DEVICE_INFO}, + {"attributeinfo", RAW_QFS_ATTRIBUTE_INFO}, + {"unixinfo", RAW_QFS_UNIX_INFO}, + {"volume-information", RAW_QFS_VOLUME_INFORMATION}, + {"size-information", RAW_QFS_SIZE_INFORMATION}, + {"device-information", RAW_QFS_DEVICE_INFORMATION}, + {"attribute-information", RAW_QFS_ATTRIBUTE_INFORMATION}, + {"quota-information", RAW_QFS_QUOTA_INFORMATION}, + {"fullsize-information", RAW_QFS_FULL_SIZE_INFORMATION}, + {"objectid", RAW_QFS_OBJECTID_INFORMATION}, + {NULL, RAW_QFS_GENERIC} +}; + + +static int cmd_fsinfo(struct smbclient_context *ctx, const char **args) +{ + union smb_fsinfo fsinfo; + NTSTATUS status; + fsinfo_level_t *fsinfo_level; + + if (!args[1]) { + d_printf("fsinfo , where level is one of following:\n"); + fsinfo_level = fsinfo_levels; + while(fsinfo_level->level_name) { + d_printf("%s\n", fsinfo_level->level_name); + fsinfo_level++; + } + return 1; + } + + fsinfo_level = fsinfo_levels; + while(fsinfo_level->level_name && !strequal(args[1],fsinfo_level->level_name)) { + fsinfo_level++; + } + + if (!fsinfo_level->level_name) { + d_printf("wrong level name!\n"); + return 1; + } + + fsinfo.generic.level = fsinfo_level->level; + status = smb_raw_fsinfo(ctx->cli->tree, ctx, &fsinfo); + if (!NT_STATUS_IS_OK(status)) { + d_printf("fsinfo-level-%s - %s\n", fsinfo_level->level_name, nt_errstr(status)); + return 1; + } + + d_printf("fsinfo-level-%s:\n", fsinfo_level->level_name); + switch(fsinfo.generic.level) { + case RAW_QFS_DSKATTR: + d_printf("\tunits_total: %hu\n", + (unsigned short) fsinfo.dskattr.out.units_total); + d_printf("\tblocks_per_unit: %hu\n", + (unsigned short) fsinfo.dskattr.out.blocks_per_unit); + d_printf("\tblocks_size: %hu\n", + (unsigned short) fsinfo.dskattr.out.block_size); + d_printf("\tunits_free: %hu\n", + (unsigned short) fsinfo.dskattr.out.units_free); + break; + case RAW_QFS_ALLOCATION: + d_printf("\tfs_id: %lu\n", + (unsigned long) fsinfo.allocation.out.fs_id); + d_printf("\tsectors_per_unit: %lu\n", + (unsigned long) fsinfo.allocation.out.sectors_per_unit); + d_printf("\ttotal_alloc_units: %lu\n", + (unsigned long) fsinfo.allocation.out.total_alloc_units); + d_printf("\tavail_alloc_units: %lu\n", + (unsigned long) fsinfo.allocation.out.avail_alloc_units); + d_printf("\tbytes_per_sector: %hu\n", + (unsigned short) fsinfo.allocation.out.bytes_per_sector); + break; + case RAW_QFS_VOLUME: + d_printf("\tserial_number: %lu\n", + (unsigned long) fsinfo.volume.out.serial_number); + d_printf("\tvolume_name: %s\n", fsinfo.volume.out.volume_name.s); + break; + case RAW_QFS_VOLUME_INFO: + case RAW_QFS_VOLUME_INFORMATION: + d_printf("\tcreate_time: %s\n", + nt_time_string(ctx,fsinfo.volume_info.out.create_time)); + d_printf("\tserial_number: %lu\n", + (unsigned long) fsinfo.volume_info.out.serial_number); + d_printf("\tvolume_name: %s\n", fsinfo.volume_info.out.volume_name.s); + break; + case RAW_QFS_SIZE_INFO: + case RAW_QFS_SIZE_INFORMATION: + d_printf("\ttotal_alloc_units: %llu\n", + (unsigned long long) fsinfo.size_info.out.total_alloc_units); + d_printf("\tavail_alloc_units: %llu\n", + (unsigned long long) fsinfo.size_info.out.avail_alloc_units); + d_printf("\tsectors_per_unit: %lu\n", + (unsigned long) fsinfo.size_info.out.sectors_per_unit); + d_printf("\tbytes_per_sector: %lu\n", + (unsigned long) fsinfo.size_info.out.bytes_per_sector); + break; + case RAW_QFS_DEVICE_INFO: + case RAW_QFS_DEVICE_INFORMATION: + d_printf("\tdevice_type: %lu\n", + (unsigned long) fsinfo.device_info.out.device_type); + d_printf("\tcharacteristics: 0x%lx\n", + (unsigned long) fsinfo.device_info.out.characteristics); + break; + case RAW_QFS_ATTRIBUTE_INFORMATION: + case RAW_QFS_ATTRIBUTE_INFO: + d_printf("\tfs_attr: 0x%lx\n", + (unsigned long) fsinfo.attribute_info.out.fs_attr); + d_printf("\tmax_file_component_length: %lu\n", + (unsigned long) fsinfo.attribute_info.out.max_file_component_length); + d_printf("\tfs_type: %s\n", fsinfo.attribute_info.out.fs_type.s); + break; + case RAW_QFS_UNIX_INFO: + d_printf("\tmajor_version: %hu\n", + (unsigned short) fsinfo.unix_info.out.major_version); + d_printf("\tminor_version: %hu\n", + (unsigned short) fsinfo.unix_info.out.minor_version); + d_printf("\tcapability: 0x%llx\n", + (unsigned long long) fsinfo.unix_info.out.capability); + break; + case RAW_QFS_QUOTA_INFORMATION: + d_printf("\tunknown[3]: [%llu,%llu,%llu]\n", + (unsigned long long) fsinfo.quota_information.out.unknown[0], + (unsigned long long) fsinfo.quota_information.out.unknown[1], + (unsigned long long) fsinfo.quota_information.out.unknown[2]); + d_printf("\tquota_soft: %llu\n", + (unsigned long long) fsinfo.quota_information.out.quota_soft); + d_printf("\tquota_hard: %llu\n", + (unsigned long long) fsinfo.quota_information.out.quota_hard); + d_printf("\tquota_flags: 0x%llx\n", + (unsigned long long) fsinfo.quota_information.out.quota_flags); + break; + case RAW_QFS_FULL_SIZE_INFORMATION: + d_printf("\ttotal_alloc_units: %llu\n", + (unsigned long long) fsinfo.full_size_information.out.total_alloc_units); + d_printf("\tcall_avail_alloc_units: %llu\n", + (unsigned long long) fsinfo.full_size_information.out.call_avail_alloc_units); + d_printf("\tactual_avail_alloc_units: %llu\n", + (unsigned long long) fsinfo.full_size_information.out.actual_avail_alloc_units); + d_printf("\tsectors_per_unit: %lu\n", + (unsigned long) fsinfo.full_size_information.out.sectors_per_unit); + d_printf("\tbytes_per_sector: %lu\n", + (unsigned long) fsinfo.full_size_information.out.bytes_per_sector); + break; + case RAW_QFS_OBJECTID_INFORMATION: + d_printf("\tGUID: %s\n", + GUID_string(ctx,&fsinfo.objectid_information.out.guid)); + d_printf("\tunknown[6]: [%llu,%llu,%llu,%llu,%llu,%llu]\n", + (unsigned long long) fsinfo.objectid_information.out.unknown[0], + (unsigned long long) fsinfo.objectid_information.out.unknown[2], + (unsigned long long) fsinfo.objectid_information.out.unknown[3], + (unsigned long long) fsinfo.objectid_information.out.unknown[4], + (unsigned long long) fsinfo.objectid_information.out.unknown[5], + (unsigned long long) fsinfo.objectid_information.out.unknown[6] ); + break; + case RAW_QFS_GENERIC: + d_printf("\twrong level returned\n"); + break; + } + + return 0; +} /**************************************************************************** show as much information as possible about a file ****************************************************************************/ -static int cmd_allinfo(const char **cmd_ptr) +static int cmd_allinfo(struct smbclient_context *ctx, const char **args) { - pstring fname; - fstring buf; - int ret = 0; - TALLOC_CTX *mem_ctx; + char *fname; union smb_fileinfo finfo; NTSTATUS status; - pstrcpy(fname,cur_dir); - - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) { + if (!args[1]) { d_printf("allinfo \n"); return 1; } - pstrcat(fname,buf); - - mem_ctx = talloc_init("%s", fname); + fname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]); /* first a ALL_INFO QPATHINFO */ finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.fname = fname; - status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); + status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo); if (!NT_STATUS_IS_OK(status)) { d_printf("%s - %s\n", fname, nt_errstr(status)); - ret = 1; - goto done; + return 1; } - d_printf("\tcreate_time: %s\n", nt_time_string(mem_ctx, finfo.all_info.out.create_time)); - d_printf("\taccess_time: %s\n", nt_time_string(mem_ctx, finfo.all_info.out.access_time)); - d_printf("\twrite_time: %s\n", nt_time_string(mem_ctx, finfo.all_info.out.write_time)); - d_printf("\tchange_time: %s\n", nt_time_string(mem_ctx, finfo.all_info.out.change_time)); + d_printf("\tcreate_time: %s\n", nt_time_string(ctx, finfo.all_info.out.create_time)); + d_printf("\taccess_time: %s\n", nt_time_string(ctx, finfo.all_info.out.access_time)); + d_printf("\twrite_time: %s\n", nt_time_string(ctx, finfo.all_info.out.write_time)); + d_printf("\tchange_time: %s\n", nt_time_string(ctx, finfo.all_info.out.change_time)); d_printf("\tattrib: 0x%x\n", finfo.all_info.out.attrib); d_printf("\talloc_size: %lu\n", (unsigned long)finfo.all_info.out.alloc_size); d_printf("\tsize: %lu\n", (unsigned long)finfo.all_info.out.size); @@ -1636,14 +1746,14 @@ static int cmd_allinfo(const char **cmd_ptr) /* 8.3 name if any */ finfo.generic.level = RAW_FILEINFO_ALT_NAME_INFO; - status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); + status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo); if (NT_STATUS_IS_OK(status)) { d_printf("\talt_name: %s\n", finfo.alt_name_info.out.fname.s); } /* file_id if available */ finfo.generic.level = RAW_FILEINFO_INTERNAL_INFORMATION; - status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); + status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo); if (NT_STATUS_IS_OK(status)) { d_printf("\tfile_id %.0f\n", (double)finfo.internal_information.out.file_id); @@ -1651,22 +1761,20 @@ static int cmd_allinfo(const char **cmd_ptr) /* the EAs, if any */ finfo.generic.level = RAW_FILEINFO_ALL_EAS; - status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); + status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo); if (NT_STATUS_IS_OK(status)) { int i; for (i=0;itree, mem_ctx, &finfo); + status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo); if (NT_STATUS_IS_OK(status)) { int i; for (i=0;itree, mem_ctx, &finfo); + status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo); if (NT_STATUS_IS_OK(status)) { d_printf("\tcompressed size %ld\n", (long)finfo.compression_info.out.compressed_size); d_printf("\tformat %ld\n", (long)finfo.compression_info.out.format); @@ -1690,77 +1798,275 @@ static int cmd_allinfo(const char **cmd_ptr) d_printf("\tcluster_shift %ld\n", (long)finfo.compression_info.out.cluster_shift); } - talloc_destroy(mem_ctx); + return 0; +} -done: - return ret; + +/**************************************************************************** +shows EA contents +****************************************************************************/ +static int cmd_eainfo(struct smbclient_context *ctx, const char **args) +{ + char *fname; + union smb_fileinfo finfo; + NTSTATUS status; + int i; + + if (!args[1]) { + d_printf("eainfo \n"); + return 1; + } + fname = talloc_strdup(ctx, args[1]); + + finfo.generic.in.fname = fname; + finfo.generic.level = RAW_FILEINFO_ALL_EAS; + status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo); + + if (!NT_STATUS_IS_OK(status)) { + d_printf("RAW_FILEINFO_ALL_EAS - %s\n", nt_errstr(status)); + return 1; + } + + d_printf("%s has %d EAs\n", fname, finfo.all_eas.out.num_eas); + + for (i=0;i\n"); return 1; } - pstrcat(fname,buf); + fname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]); - fnum = smbcli_open(cli->tree, fname, O_RDONLY, DENY_NONE); + fnum = smbcli_nt_create_full(ctx->cli->tree, fname, 0, + SEC_STD_READ_CONTROL, + 0, + NTCREATEX_SHARE_ACCESS_DELETE| + NTCREATEX_SHARE_ACCESS_READ| + NTCREATEX_SHARE_ACCESS_WRITE, + NTCREATEX_DISP_OPEN, + 0, 0); if (fnum == -1) { - d_printf("%s - %s\n", fname, smbcli_errstr(cli->tree)); + d_printf("%s - %s\n", fname, smbcli_errstr(ctx->cli->tree)); return -1; } - mem_ctx = talloc_init("%s", fname); - - query.in.fnum = fnum; - query.in.secinfo_flags = 0x7; + query.query_secdesc.level = RAW_FILEINFO_SEC_DESC; + query.query_secdesc.in.fnum = fnum; + query.query_secdesc.secinfo_flags = 0x7; - status = smb_raw_query_secdesc(cli->tree, mem_ctx, &query); + status = smb_raw_fileinfo(ctx->cli->tree, ctx, &query); if (!NT_STATUS_IS_OK(status)) { d_printf("%s - %s\n", fname, nt_errstr(status)); - ret = 1; - goto done; + return 1; } - NDR_PRINT_DEBUG(security_descriptor, query.out.sd); + NDR_PRINT_DEBUG(security_descriptor, query.query_secdesc.out.sd); - talloc_destroy(mem_ctx); + return 0; +} -done: - return ret; +/**************************************************************************** +lookup a name or sid +****************************************************************************/ +static int cmd_lookup(struct smbclient_context *ctx, const char **args) +{ + NTSTATUS status; + struct dom_sid *sid; + + if (!args[1]) { + d_printf("lookup \n"); + return 1; + } + + sid = dom_sid_parse_talloc(ctx, args[1]); + if (sid == NULL) { + const char *sidstr; + status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sidstr); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_LookupNames - %s\n", nt_errstr(status)); + return 1; + } + + d_printf("%s\n", sidstr); + } else { + const char *name; + status = smblsa_lookup_sid(ctx->cli, args[1], ctx, &name); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_LookupSids - %s\n", nt_errstr(status)); + return 1; + } + + d_printf("%s\n", name); + } + + return 0; +} + +/**************************************************************************** +show privileges for a user +****************************************************************************/ +static int cmd_privileges(struct smbclient_context *ctx, const char **args) +{ + NTSTATUS status; + struct dom_sid *sid; + struct lsa_RightSet rights; + unsigned i; + + if (!args[1]) { + d_printf("privileges \n"); + return 1; + } + + sid = dom_sid_parse_talloc(ctx, args[1]); + if (sid == NULL) { + const char *sid_str; + status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_LookupNames - %s\n", nt_errstr(status)); + return 1; + } + sid = dom_sid_parse_talloc(ctx, sid_str); + } + + status = smblsa_sid_privileges(ctx->cli, sid, ctx, &rights); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_EnumAccountRights - %s\n", nt_errstr(status)); + return 1; + } + + for (i=0;i \n"); + return 1; + } + + sid = dom_sid_parse_talloc(ctx, args[1]); + if (sid == NULL) { + const char *sid_str; + status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_LookupNames - %s\n", nt_errstr(status)); + return 1; + } + sid = dom_sid_parse_talloc(ctx, sid_str); + } + + ZERO_STRUCT(rights); + for (i = 2; args[i]; i++) { + rights.names = talloc_realloc(ctx, rights.names, + struct lsa_StringLarge, rights.count+1); + rights.names[rights.count].string = talloc_strdup(ctx, args[i]); + rights.count++; + } + + + status = smblsa_sid_add_privileges(ctx->cli, sid, ctx, &rights); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_AddAccountRights - %s\n", nt_errstr(status)); + return 1; + } + + return 0; +} + +/**************************************************************************** +delete privileges for a user +****************************************************************************/ +static int cmd_delprivileges(struct smbclient_context *ctx, const char **args) +{ + NTSTATUS status; + struct dom_sid *sid; + struct lsa_RightSet rights; + int i; + + if (!args[1]) { + d_printf("delprivileges \n"); + return 1; + } + + sid = dom_sid_parse_talloc(ctx, args[1]); + if (sid == NULL) { + const char *sid_str; + status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_LookupNames - %s\n", nt_errstr(status)); + return 1; + } + sid = dom_sid_parse_talloc(ctx, sid_str); + } + + ZERO_STRUCT(rights); + for (i = 2; args[i]; i++) { + rights.names = talloc_realloc(ctx, rights.names, + struct lsa_StringLarge, rights.count+1); + rights.names[rights.count].string = talloc_strdup(ctx, args[i]); + rights.count++; + } + + + status = smblsa_sid_del_privileges(ctx->cli, sid, ctx, &rights); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_RemoveAccountRights - %s\n", nt_errstr(status)); + return 1; + } + + return 0; +} + + +/**************************************************************************** +****************************************************************************/ +static int cmd_open(struct smbclient_context *ctx, const char **args) +{ + char *mask; - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) { + if (!args[1]) { d_printf("open \n"); return 1; } - pstrcat(mask,buf); + mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]); - smbcli_open(cli->tree, mask, O_RDWR, DENY_ALL); + smbcli_open(ctx->cli->tree, mask, O_RDWR, DENY_ALL); return 0; } @@ -1769,22 +2075,19 @@ static int cmd_open(const char **cmd_ptr) /**************************************************************************** remove a directory ****************************************************************************/ -static int cmd_rmdir(const char **cmd_ptr) +static int cmd_rmdir(struct smbclient_context *ctx, const char **args) { - pstring mask; - fstring buf; + char *mask; - pstrcpy(mask,cur_dir); - - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) { + if (!args[1]) { d_printf("rmdir \n"); return 1; } - pstrcat(mask,buf); + mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]); - if (NT_STATUS_IS_ERR(smbcli_rmdir(cli->tree, mask))) { + if (NT_STATUS_IS_ERR(smbcli_rmdir(ctx->cli->tree, mask))) { d_printf("%s removing remote directory file %s\n", - smbcli_errstr(cli->tree),mask); + smbcli_errstr(ctx->cli->tree),mask); } return 0; @@ -1793,30 +2096,26 @@ static int cmd_rmdir(const char **cmd_ptr) /**************************************************************************** UNIX hardlink. ****************************************************************************/ -static int cmd_link(const char **cmd_ptr) +static int cmd_link(struct smbclient_context *ctx, const char **args) { - pstring src,dest; - fstring buf,buf2; + char *src,*dest; - if (!(cli->transport->negotiate.capabilities & CAP_UNIX)) { + if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) { d_printf("Server doesn't support UNIX CIFS calls.\n"); return 1; } - pstrcpy(src,cur_dir); - pstrcpy(dest,cur_dir); - - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf)) || - !next_token(cmd_ptr,buf2,NULL, sizeof(buf2))) { + + if (!args[1] || !args[2]) { d_printf("link \n"); return 1; } - pstrcat(src,buf); - pstrcat(dest,buf2); + src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]); + dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]); - if (NT_STATUS_IS_ERR(smbcli_unix_hardlink(cli->tree, src, dest))) { - d_printf("%s linking files (%s -> %s)\n", smbcli_errstr(cli->tree), src, dest); + if (NT_STATUS_IS_ERR(smbcli_unix_hardlink(ctx->cli->tree, src, dest))) { + d_printf("%s linking files (%s -> %s)\n", smbcli_errstr(ctx->cli->tree), src, dest); return 1; } @@ -1827,31 +2126,26 @@ static int cmd_link(const char **cmd_ptr) UNIX symlink. ****************************************************************************/ -static int cmd_symlink(const char **cmd_ptr) +static int cmd_symlink(struct smbclient_context *ctx, const char **args) { - pstring src,dest; - fstring buf,buf2; + char *src,*dest; - if (!(cli->transport->negotiate.capabilities & CAP_UNIX)) { + if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) { d_printf("Server doesn't support UNIX CIFS calls.\n"); return 1; } - pstrcpy(src,cur_dir); - pstrcpy(dest,cur_dir); - - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf)) || - !next_token(cmd_ptr,buf2,NULL, sizeof(buf2))) { + if (!args[1] || !args[2]) { d_printf("symlink \n"); return 1; } - pstrcat(src,buf); - pstrcat(dest,buf2); + src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]); + dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]); - if (NT_STATUS_IS_ERR(smbcli_unix_symlink(cli->tree, src, dest))) { + if (NT_STATUS_IS_ERR(smbcli_unix_symlink(ctx->cli->tree, src, dest))) { d_printf("%s symlinking files (%s -> %s)\n", - smbcli_errstr(cli->tree), src, dest); + smbcli_errstr(ctx->cli->tree), src, dest); return 1; } @@ -1862,31 +2156,28 @@ static int cmd_symlink(const char **cmd_ptr) UNIX chmod. ****************************************************************************/ -static int cmd_chmod(const char **cmd_ptr) +static int cmd_chmod(struct smbclient_context *ctx, const char **args) { - pstring src; + char *src; mode_t mode; - fstring buf, buf2; - if (!(cli->transport->negotiate.capabilities & CAP_UNIX)) { + if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) { d_printf("Server doesn't support UNIX CIFS calls.\n"); return 1; } - pstrcpy(src,cur_dir); - - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf)) || - !next_token(cmd_ptr,buf2,NULL, sizeof(buf2))) { + if (!args[1] || !args[2]) { d_printf("chmod mode file\n"); return 1; } - mode = (mode_t)strtol(buf, NULL, 8); - pstrcat(src,buf2); + src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]); + + mode = (mode_t)strtol(args[1], NULL, 8); - if (NT_STATUS_IS_ERR(smbcli_unix_chmod(cli->tree, src, mode))) { + if (NT_STATUS_IS_ERR(smbcli_unix_chmod(ctx->cli->tree, src, mode))) { d_printf("%s chmod file %s 0%o\n", - smbcli_errstr(cli->tree), src, (uint_t)mode); + smbcli_errstr(ctx->cli->tree), src, (uint_t)mode); return 1; } @@ -1897,34 +2188,29 @@ static int cmd_chmod(const char **cmd_ptr) UNIX chown. ****************************************************************************/ -static int cmd_chown(const char **cmd_ptr) +static int cmd_chown(struct smbclient_context *ctx, const char **args) { - pstring src; + char *src; uid_t uid; gid_t gid; - fstring buf, buf2, buf3; - if (!(cli->transport->negotiate.capabilities & CAP_UNIX)) { + if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) { d_printf("Server doesn't support UNIX CIFS calls.\n"); return 1; } - pstrcpy(src,cur_dir); - - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf)) || - !next_token(cmd_ptr,buf2,NULL, sizeof(buf2)) || - !next_token(cmd_ptr,buf3,NULL, sizeof(buf3))) { + if (!args[1] || !args[2] || !args[3]) { d_printf("chown uid gid file\n"); return 1; } - uid = (uid_t)atoi(buf); - gid = (gid_t)atoi(buf2); - pstrcat(src,buf3); + uid = (uid_t)atoi(args[1]); + gid = (gid_t)atoi(args[2]); + src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[3]); - if (NT_STATUS_IS_ERR(smbcli_unix_chown(cli->tree, src, uid, gid))) { + if (NT_STATUS_IS_ERR(smbcli_unix_chown(ctx->cli->tree, src, uid, gid))) { d_printf("%s chown file %s uid=%d, gid=%d\n", - smbcli_errstr(cli->tree), src, (int)uid, (int)gid); + smbcli_errstr(ctx->cli->tree), src, (int)uid, (int)gid); return 1; } @@ -1934,25 +2220,20 @@ static int cmd_chown(const char **cmd_ptr) /**************************************************************************** rename some files ****************************************************************************/ -static int cmd_rename(const char **cmd_ptr) +static int cmd_rename(struct smbclient_context *ctx, const char **args) { - pstring src,dest; - fstring buf,buf2; + char *src,*dest; - pstrcpy(src,cur_dir); - pstrcpy(dest,cur_dir); - - if (!next_token(cmd_ptr,buf,NULL,sizeof(buf)) || - !next_token(cmd_ptr,buf2,NULL, sizeof(buf2))) { + if (!args[1] || !args[2]) { d_printf("rename \n"); return 1; } - pstrcat(src,buf); - pstrcat(dest,buf2); + src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]); + dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]); - if (NT_STATUS_IS_ERR(smbcli_rename(cli->tree, src, dest))) { - d_printf("%s renaming files\n",smbcli_errstr(cli->tree)); + if (NT_STATUS_IS_ERR(smbcli_rename(ctx->cli->tree, src, dest))) { + d_printf("%s renaming files\n",smbcli_errstr(ctx->cli->tree)); return 1; } @@ -1963,10 +2244,10 @@ static int cmd_rename(const char **cmd_ptr) /**************************************************************************** toggle the prompt flag ****************************************************************************/ -static int cmd_prompt(const char **cmd_ptr) +static int cmd_prompt(struct smbclient_context *ctx, const char **args) { - prompt = !prompt; - DEBUG(2,("prompting is now %s\n",prompt?"on":"off")); + ctx->prompt = !ctx->prompt; + DEBUG(2,("prompting is now %s\n",ctx->prompt?"on":"off")); return 1; } @@ -1975,22 +2256,19 @@ static int cmd_prompt(const char **cmd_ptr) /**************************************************************************** set the newer than time ****************************************************************************/ -static int cmd_newer(const char **cmd_ptr) +static int cmd_newer(struct smbclient_context *ctx, const char **args) { - fstring buf; - BOOL ok; - SMB_STRUCT_STAT sbuf; + struct stat sbuf; - ok = next_token(cmd_ptr,buf,NULL,sizeof(buf)); - if (ok && (sys_stat(buf,&sbuf) == 0)) { - newer_than = sbuf.st_mtime; + if (args[1] && (stat(args[1],&sbuf) == 0)) { + ctx->newer_than = sbuf.st_mtime; DEBUG(1,("Getting files newer than %s", - asctime(localtime(&newer_than)))); + asctime(localtime(&ctx->newer_than)))); } else { - newer_than = 0; + ctx->newer_than = 0; } - if (ok && newer_than == 0) { + if (args[1] && ctx->newer_than == 0) { d_printf("Error setting newer-than time\n"); return 1; } @@ -2001,14 +2279,12 @@ static int cmd_newer(const char **cmd_ptr) /**************************************************************************** set the archive level ****************************************************************************/ -static int cmd_archive(const char **cmd_ptr) +static int cmd_archive(struct smbclient_context *ctx, const char **args) { - fstring buf; - - if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) { - archive_level = atoi(buf); + if (args[1]) { + ctx->archive_level = atoi(args[1]); } else - d_printf("Archive level is %d\n",archive_level); + d_printf("Archive level is %d\n",ctx->archive_level); return 0; } @@ -2016,10 +2292,10 @@ static int cmd_archive(const char **cmd_ptr) /**************************************************************************** toggle the lowercaseflag ****************************************************************************/ -static int cmd_lowercase(const char **cmd_ptr) +static int cmd_lowercase(struct smbclient_context *ctx, const char **args) { - lowercase = !lowercase; - DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off")); + ctx->lowercase = !ctx->lowercase; + DEBUG(2,("filename lowercasing is now %s\n",ctx->lowercase?"on":"off")); return 0; } @@ -2030,10 +2306,10 @@ static int cmd_lowercase(const char **cmd_ptr) /**************************************************************************** toggle the recurse flag ****************************************************************************/ -static int cmd_recurse(const char **cmd_ptr) +static int cmd_recurse(struct smbclient_context *ctx, const char **args) { - recurse = !recurse; - DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off")); + ctx->recurse = !ctx->recurse; + DEBUG(2,("directory recursion is now %s\n",ctx->recurse?"on":"off")); return 0; } @@ -2041,11 +2317,11 @@ static int cmd_recurse(const char **cmd_ptr) /**************************************************************************** toggle the translate flag ****************************************************************************/ -static int cmd_translate(const char **cmd_ptr) +static int cmd_translate(struct smbclient_context *ctx, const char **args) { - translation = !translation; + ctx->translation = !ctx->translation; DEBUG(2,("CR/LF<->LF and print text translation now %s\n", - translation?"on":"off")); + ctx->translation?"on":"off")); return 0; } @@ -2054,51 +2330,66 @@ static int cmd_translate(const char **cmd_ptr) /**************************************************************************** do a printmode command ****************************************************************************/ -static int cmd_printmode(const char **cmd_ptr) +static int cmd_printmode(struct smbclient_context *ctx, const char **args) { - fstring buf; - fstring mode; - - if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) { - if (strequal(buf,"text")) { - printmode = 0; + if (args[1]) { + if (strequal(args[1],"text")) { + ctx->printmode = 0; } else { - if (strequal(buf,"graphics")) - printmode = 1; + if (strequal(args[1],"graphics")) + ctx->printmode = 1; else - printmode = atoi(buf); + ctx->printmode = atoi(args[1]); } } - switch(printmode) - { + switch(ctx->printmode) + { case 0: - fstrcpy(mode,"text"); + DEBUG(2,("the printmode is now text\n")); break; case 1: - fstrcpy(mode,"graphics"); + DEBUG(2,("the printmode is now graphics\n")); break; default: - slprintf(mode,sizeof(mode)-1,"%d",printmode); + DEBUG(2,("the printmode is now %d\n", ctx->printmode)); break; - } + } - DEBUG(2,("the printmode is now %s\n",mode)); - return 0; } /**************************************************************************** do the lcd command ****************************************************************************/ -static int cmd_lcd(const char **cmd_ptr) +static int cmd_lcd(struct smbclient_context *ctx, const char **args) +{ + char d[PATH_MAX]; + + if (args[1]) + chdir(args[1]); + DEBUG(2,("the local directory is now %s\n",getcwd(d, PATH_MAX))); + + return 0; +} + +/**************************************************************************** +history +****************************************************************************/ +static int cmd_history(struct smbclient_context *ctx, const char **args) { - fstring buf; - pstring d; +#if defined(HAVE_LIBREADLINE) + HIST_ENTRY **hlist; + int i; + + hlist = history_list(); - if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) - chdir(buf); - DEBUG(2,("the local directory is now %s\n",sys_getwd(d))); + for (i = 0; hlist && hlist[i]; i++) { + DEBUG(0, ("%d: %s\n", i, hlist[i]->line)); + } +#else + DEBUG(0,("no history without readline support\n")); +#endif return 0; } @@ -2106,62 +2397,53 @@ static int cmd_lcd(const char **cmd_ptr) /**************************************************************************** get a file restarting at end of local file ****************************************************************************/ -static int cmd_reget(const char **cmd_ptr) +static int cmd_reget(struct smbclient_context *ctx, const char **args) { - pstring local_name; - pstring remote_name; - char *p; + char *local_name; + char *remote_name; - pstrcpy(remote_name, cur_dir); - pstrcat(remote_name, "\\"); - - p = remote_name + strlen(remote_name); - - if (!next_token(cmd_ptr, p, NULL, sizeof(remote_name) - strlen(remote_name))) { + if (!args[1]) { d_printf("reget \n"); return 1; } - pstrcpy(local_name, p); + remote_name = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]); dos_clean_name(remote_name); - next_token(cmd_ptr, local_name, NULL, sizeof(local_name)); + if (args[2]) + local_name = talloc_strdup(ctx, args[2]); + else + local_name = talloc_strdup(ctx, args[1]); - return do_get(remote_name, local_name, True); + return do_get(ctx, remote_name, local_name, True); } /**************************************************************************** put a file restarting at end of local file ****************************************************************************/ -static int cmd_reput(const char **cmd_ptr) +static int cmd_reput(struct smbclient_context *ctx, const char **args) { - pstring local_name; - pstring remote_name; - fstring buf; - char *p = buf; - SMB_STRUCT_STAT st; + char *local_name; + char *remote_name; - pstrcpy(remote_name, cur_dir); - pstrcat(remote_name, "\\"); - - if (!next_token(cmd_ptr, p, NULL, sizeof(buf))) { + if (!args[1]) { d_printf("reput \n"); return 1; } - pstrcpy(local_name, p); + local_name = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]); - if (!file_exist(local_name, &st)) { + if (!file_exist(local_name)) { d_printf("%s does not exist\n", local_name); return 1; } - if (next_token(cmd_ptr, p, NULL, sizeof(buf))) - pstrcat(remote_name, p); + if (args[2]) + remote_name = talloc_strdup(ctx, args[2]); else - pstrcat(remote_name, local_name); + remote_name = talloc_strdup(ctx, args[1]); dos_clean_name(remote_name); - return do_put(remote_name, local_name, True); + return do_put(ctx, remote_name, local_name, True); } @@ -2219,18 +2501,15 @@ static BOOL browse_host(const char *query_host) binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", query_host); - status = dcerpc_pipe_connect(&p, binding, - DCERPC_SRVSVC_UUID, - DCERPC_SRVSVC_VERSION, - domain, - username, password); + status = dcerpc_pipe_connect(mem_ctx, &p, binding, + &dcerpc_table_srvsvc, + cmdline_credentials, NULL); if (!NT_STATUS_IS_OK(status)) { d_printf("Failed to connect to %s - %s\n", binding, nt_errstr(status)); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return False; } - talloc_steal(mem_ctx, p); r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p)); r.in.level = 1; @@ -2254,7 +2533,7 @@ static BOOL browse_host(const char *query_host) } } while (NT_STATUS_IS_OK(status) && W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) { d_printf("Failed NetShareEnumAll %s - %s/%s\n", @@ -2280,6 +2559,8 @@ static BOOL list_servers(const char *wk_grp) #define COMPL_REMOTE 1 /* Complete remote filename */ #define COMPL_LOCAL 2 /* Complete local filename */ +static int cmd_help(struct smbclient_context *ctx, const char **args); + /* This defines the commands supported by this client. * NOTE: The "!" must be the last one in the list because it's fn pointer * field is NULL, and NULL in that field is used in process_tok() @@ -2288,31 +2569,35 @@ static BOOL list_servers(const char *wk_grp) static struct { const char *name; - int (*fn)(const char **cmd_ptr); + int (*fn)(struct smbclient_context *ctx, const char **args); const char *description; char compl_args[2]; /* Completion argument info */ } commands[] = { {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}}, + {"addprivileges",cmd_addprivileges," add privileges for a user",{COMPL_NONE,COMPL_NONE}}, {"altname",cmd_altname," show alt name",{COMPL_NONE,COMPL_NONE}}, {"acl",cmd_acl," show file ACL",{COMPL_NONE,COMPL_NONE}}, {"allinfo",cmd_allinfo," show all possible info about a file",{COMPL_NONE,COMPL_NONE}}, {"archive",cmd_archive,"\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}}, - {"blocksize",cmd_block,"blocksize (default 20)",{COMPL_NONE,COMPL_NONE}}, - {"cancel",cmd_cancel," cancel a print queue entry",{COMPL_NONE,COMPL_NONE}}, + {"cancel",cmd_rewrite," cancel a print queue entry",{COMPL_NONE,COMPL_NONE}}, {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}}, {"chmod",cmd_chmod," chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}}, {"chown",cmd_chown," chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}}, {"del",cmd_del," delete all matching files",{COMPL_REMOTE,COMPL_NONE}}, + {"delprivileges",cmd_delprivileges," remove privileges for a user",{COMPL_NONE,COMPL_NONE}}, {"deltree",cmd_deltree," delete a whole directory tree",{COMPL_REMOTE,COMPL_NONE}}, {"dir",cmd_dir," list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}}, {"du",cmd_du," computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}}, + {"eainfo",cmd_eainfo," show EA contents for a file",{COMPL_NONE,COMPL_NONE}}, {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}}, + {"fsinfo",cmd_fsinfo,"query file system info",{COMPL_NONE,COMPL_NONE}}, {"get",cmd_get," [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}}, {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}}, {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}}, {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}}, {"link",cmd_link," create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}}, + {"lookup",cmd_lookup," show SID for name or name for SID",{COMPL_NONE,COMPL_NONE}}, {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}}, {"ls",cmd_dir," list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}}, {"mask",cmd_select," mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}}, @@ -2323,13 +2608,14 @@ static struct {"mput",cmd_mput," put all matching files",{COMPL_REMOTE,COMPL_NONE}}, {"newer",cmd_newer," only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}}, {"open",cmd_open," open a file",{COMPL_REMOTE,COMPL_NONE}}, + {"privileges",cmd_privileges," show privileges for a user",{COMPL_NONE,COMPL_NONE}}, {"print",cmd_print," print a file",{COMPL_NONE,COMPL_NONE}}, {"printmode",cmd_printmode," set the print mode",{COMPL_NONE,COMPL_NONE}}, {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}}, {"put",cmd_put," [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}}, {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}}, {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}}, - {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}}, + {"queue",cmd_rewrite,"show the print queue",{COMPL_NONE,COMPL_NONE}}, {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}}, {"rd",cmd_rmdir," remove a directory",{COMPL_NONE,COMPL_NONE}}, {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}}, @@ -2338,10 +2624,7 @@ static struct {"reput",cmd_reput," [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}}, {"rm",cmd_del," delete all matching files",{COMPL_REMOTE,COMPL_NONE}}, {"rmdir",cmd_rmdir," remove a directory",{COMPL_NONE,COMPL_NONE}}, - {"setmode",cmd_setmode,"filename change modes of file",{COMPL_REMOTE,COMPL_NONE}}, {"symlink",cmd_symlink," create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}}, - {"tar",cmd_tar,"tar [IXFqbgNan] current directory to/from ",{COMPL_NONE,COMPL_NONE}}, - {"tarmode",cmd_tarmode," tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}}, {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}}, /* Yes, this must be here, see crh's comment above. */ @@ -2354,7 +2637,7 @@ static struct lookup a command string in the list of commands, including abbreviations ******************************************************************/ -static int process_tok(fstring tok) +static int process_tok(const char *tok) { int i = 0, matches = 0; int cmd=0; @@ -2383,13 +2666,12 @@ static int process_tok(fstring tok) /**************************************************************************** help ****************************************************************************/ -static int cmd_help(const char **cmd_ptr) +static int cmd_help(struct smbclient_context *ctx, const char **args) { int i=0,j; - fstring buf; - if (next_token(cmd_ptr,buf,NULL,sizeof(buf))) { - if ((i = process_tok(buf)) >= 0) + if (args[1]) { + if ((i = process_tok(args[1])) >= 0) d_printf("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description); } else { while (commands[i].description) { @@ -2403,87 +2685,56 @@ static int cmd_help(const char **cmd_ptr) return 0; } +static int process_line(struct smbclient_context *ctx, const char *cline); /**************************************************************************** process a -c command string ****************************************************************************/ -static int process_command_string(char *cmd) +static int process_command_string(struct smbclient_context *ctx, const char *cmd) { - pstring line; - const char *ptr; - int rc = 0; + const char **lines; + int i, rc = 0; - /* establish the connection if not already */ - - if (!cli) { - cli = do_connect(desthost, service); - if (!cli) - return 0; + lines = str_list_make(NULL, cmd, ";"); + for (i = 0; lines[i]; i++) { + rc |= process_line(ctx, lines[i]); } - - while (cmd[0] != '\0') { - char *p; - fstring tok; - int i; - - if ((p = strchr_m(cmd, ';')) == 0) { - strncpy(line, cmd, 999); - line[1000] = '\0'; - cmd += strlen(cmd); - } else { - if (p - cmd > 999) p = cmd + 999; - strncpy(line, cmd, p - cmd); - line[p - cmd] = '\0'; - cmd = p + 1; - } - - /* and get the first part of the command */ - ptr = line; - if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue; - - if ((i = process_tok(tok)) >= 0) { - rc = commands[i].fn(&ptr); - } else if (i == -2) { - d_printf("%s: command abbreviation ambiguous\n",tok); - } else { - d_printf("%s: command not found\n",tok); - } - } - + talloc_free(lines); + return rc; } #define MAX_COMPLETIONS 100 typedef struct { - pstring dirmask; + char *dirmask; char **matches; int count, samelen; const char *text; int len; } completion_remote_t; -static void completion_remote_filter(file_info *f, const char *mask, void *state) +static void completion_remote_filter(struct clilist_file_info *f, const char *mask, void *state) { completion_remote_t *info = (completion_remote_t *)state; if ((info->count < MAX_COMPLETIONS - 1) && (strncmp(info->text, f->name, info->len) == 0) && (strcmp(f->name, ".") != 0) && (strcmp(f->name, "..") != 0)) { - if ((info->dirmask[0] == 0) && !(f->mode & FILE_ATTRIBUTE_DIRECTORY)) + if ((info->dirmask[0] == 0) && !(f->attrib & FILE_ATTRIBUTE_DIRECTORY)) info->matches[info->count] = strdup(f->name); else { - pstring tmp; + char *tmp; if (info->dirmask[0] != 0) - pstrcpy(tmp, info->dirmask); + tmp = talloc_asprintf(NULL, "%s/%s", info->dirmask, f->name); else - tmp[0] = 0; - pstrcat(tmp, f->name); - if (f->mode & FILE_ATTRIBUTE_DIRECTORY) - pstrcat(tmp, "/"); - info->matches[info->count] = strdup(tmp); + tmp = talloc_strdup(NULL, f->name); + + if (f->attrib & FILE_ATTRIBUTE_DIRECTORY) + tmp = talloc_append_string(NULL, tmp, "/"); + info->matches[info->count] = tmp; } if (info->matches[info->count] == NULL) return; - if (f->mode & FILE_ATTRIBUTE_DIRECTORY) + if (f->attrib & FILE_ATTRIBUTE_DIRECTORY) smb_readline_ca_char(0); if (info->count == 1) @@ -2497,9 +2748,9 @@ static void completion_remote_filter(file_info *f, const char *mask, void *state static char **remote_completion(const char *text, int len) { - pstring dirmask; + char *dirmask; int i; - completion_remote_t info = { "", NULL, 1, 0, NULL, 0 }; + completion_remote_t info; info.samelen = len; info.text = text; @@ -2508,7 +2759,7 @@ static char **remote_completion(const char *text, int len) if (len >= PATH_MAX) return(NULL); - info.matches = (char **)malloc(sizeof(info.matches[0])*MAX_COMPLETIONS); + info.matches = malloc_array_p(char *, MAX_COMPLETIONS); if (!info.matches) return NULL; info.matches[0] = NULL; @@ -2519,13 +2770,13 @@ static char **remote_completion(const char *text, int len) info.samelen = info.len = len-i-1; if (i > 0) { - strncpy(info.dirmask, text, i+1); + info.dirmask = talloc_strndup(NULL, text, i+1); info.dirmask[i+1] = 0; - snprintf(dirmask, sizeof(dirmask), "%s%*s*", cur_dir, i-1, text); + asprintf(&dirmask, "%s%*s*", rl_ctx->remote_cur_dir, i-1, text); } else - snprintf(dirmask, sizeof(dirmask), "%s*", cur_dir); + asprintf(&dirmask, "%s*", rl_ctx->remote_cur_dir); - if (smbcli_list(cli->tree, dirmask, + if (smbcli_list(rl_ctx->cli->tree, dirmask, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, completion_remote_filter, &info) < 0) goto cleanup; @@ -2586,9 +2837,9 @@ static char **completion_fn(const char *text, int start, int end) return NULL; } else { char **matches; - int i, len, samelen, count=1; + int i, len, samelen = 0, count=1; - matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS); + matches = malloc_array_p(char *, MAX_COMPLETIONS); if (!matches) return NULL; matches[0] = NULL; @@ -2648,174 +2899,100 @@ static void readline_callback(void) last_t = t; - smbcli_transport_process(cli->transport); + smbcli_transport_process(rl_ctx->cli->transport); - if (cli->tree) { - smbcli_chkpath(cli->tree, "\\"); + if (rl_ctx->cli->tree) { + smbcli_chkpath(rl_ctx->cli->tree, "\\"); } } +static int process_line(struct smbclient_context *ctx, const char *cline) +{ + const char **args; + int i; + + /* and get the first part of the command */ + args = str_list_make_shell(ctx, cline, NULL); + if (!args || !args[0]) + return 0; + + if ((i = process_tok(args[0])) >= 0) { + i = commands[i].fn(ctx, args); + } else if (i == -2) { + d_printf("%s: command abbreviation ambiguous\n",args[0]); + } else { + d_printf("%s: command not found\n",args[0]); + } + + talloc_free(args); + + return i; +} /**************************************************************************** process commands on stdin ****************************************************************************/ -static void process_stdin(void) +static int process_stdin(struct smbclient_context *ctx) { + int rc = 0; while (1) { - fstring tok; - fstring the_prompt; - char *cline; - pstring line; - const char *ptr; - int i; - /* display a prompt */ - slprintf(the_prompt, sizeof(the_prompt)-1, "smb: %s> ", cur_dir); - cline = smb_readline(the_prompt, readline_callback, completion_fn); + char *the_prompt = talloc_asprintf(ctx, "smb: %s> ", ctx->remote_cur_dir); + char *cline = smb_readline(the_prompt, readline_callback, completion_fn); + talloc_free(the_prompt); if (!cline) break; - pstrcpy(line, cline); - /* special case - first char is ! */ - if (*line == '!') { - system(line + 1); + if (*cline == '!') { + system(cline + 1); continue; } - - /* and get the first part of the command */ - ptr = line; - if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue; - - if ((i = process_tok(tok)) >= 0) { - commands[i].fn(&ptr); - } else if (i == -2) { - d_printf("%s: command abbreviation ambiguous\n",tok); - } else { - d_printf("%s: command not found\n",tok); - } + + rc |= process_command_string(ctx, cline); } + + return rc; } /***************************************************** return a connection to a server *******************************************************/ -static struct smbcli_state *do_connect(const char *server, const char *share) +static struct smbclient_context *do_connect(TALLOC_CTX *mem_ctx, + const char *server, const char *share, struct cli_credentials *cred) { - struct smbcli_state *c; - struct nmb_name called, calling; - const char *server_n; - fstring servicename; - char *sharename; NTSTATUS status; - - /* make a copy so we don't modify the global string 'service' */ - fstrcpy(servicename, share); - sharename = servicename; - if (*sharename == '\\') { - server = sharename+2; - sharename = strchr_m(server,'\\'); - if (!sharename) return NULL; - *sharename = 0; - sharename++; - } - - asprintf(&sharename, "\\\\%s\\%s", server, sharename); - - server_n = dest_ip?dest_ip:server; - - make_nmb_name(&calling, lp_netbios_name(), 0x0); - choose_called_name(&called, server, name_type); - - again: - /* have to open a new connection */ - if (!(c=smbcli_state_init(NULL)) || !smbcli_socket_connect(c, server_n)) { - d_printf("Connection to %s failed\n", server_n); - return NULL; - } - - if (!smbcli_transport_establish(c, &calling, &called)) { - char *p; - d_printf("session request to %s failed\n", - called.name); - smbcli_shutdown(c); - if ((p=strchr_m(called.name, '.'))) { - *p = 0; - goto again; - } - if (strcmp(called.name, "*SMBSERVER")) { - make_nmb_name(&called , "*SMBSERVER", 0x20); - goto again; - } + struct smbclient_context *ctx = talloc_zero(mem_ctx, struct smbclient_context); + if (!ctx) { return NULL; } - DEBUG(4,(" session request ok\n")); - - if (NT_STATUS_IS_ERR(smbcli_negprot(c))) { - d_printf("protocol negotiation failed\n"); - smbcli_shutdown(c); - return NULL; - } + rl_ctx = ctx; /* Ugly hack */ - status = smbcli_session_setup(c, username, password, domain); - if (NT_STATUS_IS_ERR(status)) { - d_printf("authenticated session setup failed: %s\n", nt_errstr(status)); - /* if a password was not supplied then try again with a null username */ - if (password[0] || !username[0]) { - status = smbcli_session_setup(c, "", "", lp_workgroup()); - } - if (NT_STATUS_IS_ERR(status)) { - d_printf("session setup failed: %s\n", nt_errstr(status)); - smbcli_shutdown(c); - return NULL; - } - d_printf("Anonymous login successful\n"); + if (strncmp(share, "\\\\", 2) == 0 || + strncmp(share, "//", 2) == 0) { + smbcli_parse_unc(share, ctx, &server, &share); } - DEBUG(4,(" session setup ok\n")); - - if (NT_STATUS_IS_ERR(smbcli_send_tconX(c, sharename, "?????", password))) { - d_printf("tree connect failed: %s\n", smbcli_errstr(c->tree)); - smbcli_shutdown(c); + ctx->remote_cur_dir = talloc_strdup(ctx, "\\"); + + status = smbcli_full_connection(ctx, &ctx->cli, server, + share, NULL, cred, NULL); + 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; } - DEBUG(4,(" tconx ok\n")); - - return c; -} - - -/**************************************************************************** - process commands from the client -****************************************************************************/ -static int process(char *base_directory) -{ - int rc = 0; - - cli = do_connect(desthost, service); - if (!cli) { - return 1; - } - - if (*base_directory) do_cd(base_directory); - - if (cmdstr) { - rc = process_command_string(cmdstr); - } else { - process_stdin(); - } - - smbcli_shutdown(cli); - return rc; + return ctx; } /**************************************************************************** handle a -L query ****************************************************************************/ -static int do_host_query(char *query_host) +static int do_host_query(const char *query_host) { browse_host(query_host); list_servers(lp_workgroup()); @@ -2823,43 +3000,20 @@ static int do_host_query(char *query_host) } -/**************************************************************************** -handle a tar operation -****************************************************************************/ -static int do_tar_op(char *base_directory) -{ - int ret; - - /* do we already have a connection? */ - if (!cli) { - cli = do_connect(desthost, service); - if (!cli) - return 1; - } - - recurse=True; - - if (*base_directory) do_cd(base_directory); - - ret=process_tar(); - - smbcli_shutdown(cli); - - return(ret); -} - /**************************************************************************** handle a message operation ****************************************************************************/ -static int do_message_op(void) +static int do_message_op(const char *desthost, const char *destip, int name_type) { - struct nmb_name called, calling; + struct nbt_name called, calling; const char *server_name; + struct smbcli_state *cli; - make_nmb_name(&calling, lp_netbios_name(), 0x0); - choose_called_name(&called, desthost, name_type); + make_nbt_name_client(&calling, lp_netbios_name()); - server_name = dest_ip ? dest_ip : desthost; + nbt_choose_called_name(NULL, &called, desthost, name_type); + + server_name = destip ? destip : desthost; if (!(cli=smbcli_state_init(NULL)) || !smbcli_socket_connect(cli, server_name)) { d_printf("Connection to %s failed\n", server_name); @@ -2868,53 +3022,43 @@ static int do_message_op(void) if (!smbcli_transport_establish(cli, &calling, &called)) { d_printf("session request failed\n"); - smbcli_shutdown(cli); + talloc_free(cli); return 1; } - send_message(); - smbcli_shutdown(cli); + send_message(cli, desthost); + talloc_free(cli); return 0; } -/** - * Process "-L hostname" option. - * - * We don't actually do anything yet -- we just stash the name in a - * global variable and do the query when all options have been read. - **/ -static void remember_query_host(const char *arg, - pstring query_host) -{ - char *slash; - - while (*arg == '\\' || *arg == '/') - arg++; - pstrcpy(query_host, arg); - if ((slash = strchr(query_host, '/')) - || (slash = strchr(query_host, '\\'))) { - *slash = 0; - } -} - - /**************************************************************************** main program ****************************************************************************/ int main(int argc,char *argv[]) { - fstring base_directory; + const char *base_directory = NULL; + const char *dest_ip; int opt; - pstring query_host; + const char *query_host = NULL; BOOL message = False; - extern char tar_type; - pstring term_code; + const char *desthost; +#ifdef KANJI + const char *term_code = KANJI; +#else + const char *term_code = ""; +#endif /* KANJI */ poptContext pc; + const char *service = NULL; + int port = 0; char *p; int rc = 0; + int name_type = 0x20; TALLOC_CTX *mem_ctx; + struct smbclient_context *ctx; + const char *cmdstr = NULL; + struct poptOption long_options[] = { POPT_AUTOHELP @@ -2923,7 +3067,6 @@ static void remember_query_host(const char *arg, { "stderr", 'E', POPT_ARG_NONE, NULL, 'E', "Write messages to stderr instead of stdout" }, { "list", 'L', POPT_ARG_STRING, NULL, 'L', "Get a list of shares available on a host", "HOST" }, { "terminal", 't', POPT_ARG_STRING, NULL, 't', "Terminal I/O code {sjis|euc|jis7|jis8|junet|hex}", "CODE" }, - { "tar", 'T', POPT_ARG_STRING, NULL, 'T', "Command line tar", "IXFqgbNan" }, { "directory", 'D', POPT_ARG_STRING, NULL, 'D', "Start from directory", "DIR" }, { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" }, { "send-buffer", 'b', POPT_ARG_INT, NULL, 'b', "Changes the transmit/send buffer", "BYTES" }, @@ -2935,33 +3078,15 @@ static void remember_query_host(const char *arg, POPT_TABLEEND }; - -#ifdef KANJI - pstrcpy(term_code, KANJI); -#else /* KANJI */ - *term_code = 0; -#endif /* KANJI */ - - *query_host = 0; - *base_directory = 0; - - setup_logging(argv[0],DEBUG_STDOUT); mem_ctx = talloc_init("client.c/main"); if (!mem_ctx) { d_printf("\nclient.c: Not enough memory\n"); exit(1); } - if (!lp_load(dyn_CONFIGFILE,True,False,False)) { - fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n", - argv[0], dyn_CONFIGFILE); - } - pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0); poptSetOtherOptionHelp(pc, "[OPTIONS] service "); - in_client = True; /* Make sure that we tell lp_load we are */ - while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case 'M': @@ -2970,31 +3095,21 @@ static void remember_query_host(const char *arg, * to port 139 instead of port 445. srl,crh */ name_type = 0x03; - pstrcpy(desthost,poptGetOptArg(pc)); + desthost = strdup(poptGetOptArg(pc)); if( 0 == port ) port = 139; message = True; break; case 'I': dest_ip = poptGetOptArg(pc); break; - case 'E': - setup_logging("client", DEBUG_STDERR); - break; - case 'L': - remember_query_host(poptGetOptArg(pc), query_host); + query_host = strdup(poptGetOptArg(pc)); break; case 't': - pstrcpy(term_code, poptGetOptArg(pc)); - break; - case 'T': - if (!tar_parseargs(argc, argv, poptGetOptArg(pc), optind)) { - poptPrintUsage(pc, stderr, 0); - exit(1); - } + term_code = strdup(poptGetOptArg(pc)); break; case 'D': - fstrcpy(base_directory,poptGetOptArg(pc)); + base_directory = strdup(poptGetOptArg(pc)); break; case 'b': io_bufsize = MAX(1, atoi(poptGetOptArg(pc))); @@ -3002,63 +3117,67 @@ static void remember_query_host(const char *arg, } } - load_interfaces(); + gensec_init(); if(poptPeekArg(pc)) { - pstrcpy(service,poptGetArg(pc)); + char *s = strdup(poptGetArg(pc)); + /* Convert any '/' characters in the service name to '\' characters */ - string_replace(service, '/','\\'); + string_replace(s, '/','\\'); - if (count_chars(service,'\\') < 3) { - d_printf("\n%s: Not enough '\\' characters in service\n",service); + service = s; + + if (count_chars(s,'\\') < 3) { + d_printf("\n%s: Not enough '\\' characters in service\n",s); poptPrintUsage(pc, stderr, 0); exit(1); } } if (poptPeekArg(pc)) { - cmdline_set_userpassword(poptGetArg(pc)); + cli_credentials_set_password(cmdline_credentials, poptGetArg(pc), CRED_SPECIFIED); } /*init_names(); */ - if (!tar_type && !*query_host && !*service && !message) { + if (!query_host && !service && !message) { poptPrintUsage(pc, stderr, 0); exit(1); } poptFreeContext(pc); - pstrcpy(username, cmdline_get_username()); - pstrcpy(domain, cmdline_get_userdomain()); - pstrcpy(password, cmdline_get_userpassword()); - DEBUG( 3, ( "Client started (version %s).\n", SAMBA_VERSION_STRING ) ); - talloc_destroy(mem_ctx); - if (tar_type) { - if (cmdstr) - process_command_string(cmdstr); - return do_tar_op(base_directory); - } - - if ((p=strchr_m(query_host,'#'))) { + if (query_host && (p=strchr_m(query_host,'#'))) { *p = 0; p++; sscanf(p, "%x", &name_type); } - if (*query_host) { + if (query_host) { return do_host_query(query_host); } if (message) { - return do_message_op(); + return do_message_op(desthost, dest_ip, name_type); } - if (process(base_directory)) { + + ctx = do_connect(mem_ctx, desthost, service, cmdline_credentials); + if (!ctx) return 1; + + if (base_directory) + do_cd(ctx, base_directory); + + if (cmdstr) { + rc = process_command_string(ctx, cmdstr); + } else { + rc = process_stdin(ctx); } + + talloc_free(mem_ctx); return rc; }