LCOV - code coverage report
Current view: top level - source4/client - client.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 654 1625 40.2 %
Date: 2024-05-31 13:13:24 Functions: 46 90 51.1 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB client
       4             :    Copyright (C) Andrew Tridgell 1994-1998
       5             :    Copyright (C) Simo Sorce 2001-2002
       6             :    Copyright (C) Jelmer Vernooij 2003-2004
       7             :    Copyright (C) James J Myers   2003 <myersjj@samba.org>
       8             :    
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             :    
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             :    
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : /* 
      24             :  * TODO: remove this ... and don't use talloc_append_string()
      25             :  *
      26             :  * NOTE: I'm not changing the code yet, because I assume there're
      27             :  *       some bugs in the existing code and I'm not sure how to fix
      28             :  *       them correctly.
      29             :  */
      30             : #define TALLOC_DEPRECATED 1
      31             : 
      32             : #include "includes.h"
      33             : #include "version.h"
      34             : #include "libcli/libcli.h"
      35             : #include "lib/events/events.h"
      36             : #include "lib/cmdline/cmdline.h"
      37             : #include "librpc/gen_ndr/ndr_srvsvc_c.h"
      38             : #include "librpc/gen_ndr/ndr_lsa.h"
      39             : #include "librpc/gen_ndr/ndr_security.h"
      40             : #include "libcli/util/clilsa.h"
      41             : #include "system/dir.h"
      42             : #include "system/filesys.h"
      43             : #include "../lib/util/dlinklist.h"
      44             : #include "system/readline.h"
      45             : #include "auth/credentials/credentials.h"
      46             : #include "auth/gensec/gensec.h"
      47             : #include "system/time.h" /* needed by some systems for asctime() */
      48             : #include "libcli/resolve/resolve.h"
      49             : #include "libcli/security/security.h"
      50             : #include "../libcli/smbreadline/smbreadline.h"
      51             : #include "librpc/gen_ndr/ndr_nbt.h"
      52             : #include "param/param.h"
      53             : #include "libcli/raw/raw_proto.h"
      54             : 
      55             : /* the default pager to use for the client "more" command. Users can
      56             :  *    override this with the PAGER environment variable */
      57             : #ifndef DEFAULT_PAGER
      58             : #define DEFAULT_PAGER "more"
      59             : #endif
      60             : 
      61             : #undef strncasecmp
      62             : 
      63             : struct smbclient_context {
      64             :         char *remote_cur_dir;
      65             :         struct smbcli_state *cli;
      66             :         char *fileselection;
      67             :         time_t newer_than;
      68             :         bool prompt;
      69             :         bool recurse;
      70             :         int archive_level;
      71             :         bool lowercase;
      72             :         int printmode;
      73             :         bool translation;
      74             :         int io_bufsize;
      75             : };
      76             : 
      77             : /* timing globals */
      78             : static uint64_t get_total_size = 0;
      79             : static unsigned int get_total_time_ms = 0;
      80             : static uint64_t put_total_size = 0;
      81             : static unsigned int put_total_time_ms = 0;
      82             : 
      83             : /* Unfortunately, there is no way to pass a context to the completion function as an argument */
      84             : static struct smbclient_context *rl_ctx; 
      85             : 
      86             : /* totals globals */
      87             : static double dir_total;
      88             : 
      89             : /*******************************************************************
      90             :  Reduce a file name, removing .. elements.
      91             : ********************************************************************/
      92          12 : static void dos_clean_name(char *s)
      93             : {
      94          12 :         char *p=NULL,*r;
      95             : 
      96          12 :         DEBUG(3,("dos_clean_name [%s]\n",s));
      97             : 
      98             :         /* remove any double slashes */
      99          12 :         all_string_sub(s, "\\\\", "\\", 0);
     100             : 
     101          20 :         while ((p = strstr(s,"\\..\\")) != NULL) {
     102           2 :                 *p = '\0';
     103           2 :                 if ((r = strrchr(s,'\\')) != NULL)
     104           2 :                         memmove(r,p+3,strlen(p+3)+1);
     105             :         }
     106             : 
     107          12 :         trim_string(s,NULL,"\\..");
     108             : 
     109          12 :         all_string_sub(s, "\\.\\", "\\", 0);
     110          12 : }
     111             : 
     112             : /****************************************************************************
     113             : write to a local file with CR/LF->LF translation if appropriate. return the 
     114             : number taken from the buffer. This may not equal the number written.
     115             : ****************************************************************************/
     116          30 : static int writefile(int f, const void *_b, int n, bool translation)
     117             : {
     118          30 :         const uint8_t *b = (const uint8_t *)_b;
     119             :         int i;
     120             : 
     121          30 :         if (!translation) {
     122          30 :                 return write(f,b,n);
     123             :         }
     124             : 
     125           0 :         i = 0;
     126           0 :         while (i < n) {
     127           0 :                 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') {
     128           0 :                         b++;i++;
     129             :                 }
     130           0 :                 if (write(f, b, 1) != 1) {
     131           0 :                         break;
     132             :                 }
     133           0 :                 b++;
     134           0 :                 i++;
     135             :         }
     136             :   
     137           0 :         return(i);
     138             : }
     139             : 
     140             : /****************************************************************************
     141             :   read from a file with LF->CR/LF translation if appropriate. return the 
     142             :   number read. read approx n bytes.
     143             : ****************************************************************************/
     144          30 : static int readfile(void *_b, int n, FILE *f, bool translation)
     145             : {
     146          30 :         uint8_t *b = (uint8_t *)_b;
     147             :         int i;
     148             :         int c;
     149             : 
     150          30 :         if (!translation)
     151          30 :                 return fread(b,1,n,f);
     152             :   
     153           0 :         i = 0;
     154           0 :         while (i < (n - 1)) {
     155           0 :                 if ((c = getc(f)) == EOF) {
     156           0 :                         break;
     157             :                 }
     158             :       
     159           0 :                 if (c == '\n') { /* change all LFs to CR/LF */
     160           0 :                         b[i++] = '\r';
     161             :                 }
     162             :       
     163           0 :                 b[i++] = c;
     164             :         }
     165             :   
     166           0 :         return(i);
     167             : }
     168             :  
     169             : 
     170             : /****************************************************************************
     171             : send a message
     172             : ****************************************************************************/
     173           0 : static void send_message(struct smbcli_state *cli, const char *desthost)
     174             : {
     175             :         char msg[1600];
     176           0 :         int total_len = 0;
     177             :         int grp_id;
     178           0 :         struct cli_credentials *creds = samba_cmdline_get_creds();
     179             : 
     180           0 :         if (!smbcli_message_start(cli->tree,
     181             :                         desthost,
     182             :                         cli_credentials_get_username(creds),
     183             :                         &grp_id)) {
     184           0 :                 d_printf("message start: %s\n", smbcli_errstr(cli->tree));
     185           0 :                 return;
     186             :         }
     187             : 
     188             : 
     189           0 :         d_printf("Connected. Type your message, ending it with a Control-D\n");
     190             : 
     191           0 :         while (!feof(stdin) && total_len < 1600) {
     192           0 :                 int maxlen = MIN(1600 - total_len,127);
     193           0 :                 int l=0;
     194             :                 int c;
     195             : 
     196           0 :                 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++) {
     197           0 :                         if (c == '\n')
     198           0 :                                 msg[l++] = '\r';
     199           0 :                         msg[l] = c;   
     200             :                 }
     201             : 
     202           0 :                 if (!smbcli_message_text(cli->tree, msg, l, grp_id)) {
     203           0 :                         d_printf("SMBsendtxt failed (%s)\n",smbcli_errstr(cli->tree));
     204           0 :                         return;
     205             :                 }      
     206             :                 
     207           0 :                 total_len += l;
     208             :         }
     209             : 
     210           0 :         if (total_len >= 1600)
     211           0 :                 d_printf("the message was truncated to 1600 bytes\n");
     212             :         else
     213           0 :                 d_printf("sent %d bytes\n",total_len);
     214             : 
     215           0 :         if (!smbcli_message_end(cli->tree, grp_id)) {
     216           0 :                 d_printf("SMBsendend failed (%s)\n",smbcli_errstr(cli->tree));
     217           0 :                 return;
     218             :         }      
     219             : }
     220             : 
     221             : 
     222             : 
     223             : /****************************************************************************
     224             : check the space on a device
     225             : ****************************************************************************/
     226          10 : static int do_dskattr(struct smbclient_context *ctx)
     227             : {
     228             :         uint32_t bsize;
     229             :         uint64_t total, avail;
     230             : 
     231          10 :         if (NT_STATUS_IS_ERR(smbcli_dskattr(ctx->cli->tree, &bsize, &total, &avail))) {
     232           0 :                 d_printf("Error in dskattr: %s\n",smbcli_errstr(ctx->cli->tree)); 
     233           0 :                 return 1;
     234             :         }
     235             : 
     236          10 :         d_printf("\n\t\t%llu blocks of size %u. %llu blocks available\n",
     237             :                  (unsigned long long)total, 
     238             :                  (unsigned)bsize, 
     239             :                  (unsigned long long)avail);
     240             : 
     241          10 :         return 0;
     242             : }
     243             : 
     244             : /****************************************************************************
     245             : show cd/pwd
     246             : ****************************************************************************/
     247           2 : static int cmd_pwd(struct smbclient_context *ctx, const char **args)
     248             : {
     249           2 :         d_printf("Current directory is %s\n", ctx->remote_cur_dir);
     250           2 :         return 0;
     251             : }
     252             : 
     253             : /*
     254             :   convert a string to dos format
     255             : */
     256           6 : static void dos_format(char *s)
     257             : {
     258           6 :         string_replace(s, '/', '\\');
     259           6 : }
     260             : 
     261             : /****************************************************************************
     262             : change directory - inner section
     263             : ****************************************************************************/
     264           4 : static int do_cd(struct smbclient_context *ctx, const char *newdir)
     265             : {
     266             :         char *dname;
     267             :       
     268             :         /* Save the current directory in case the
     269             :            new directory is invalid */
     270           4 :         if (newdir[0] == '\\')
     271           0 :                 dname = talloc_strdup(ctx, newdir);
     272             :         else
     273           4 :                 dname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, newdir);
     274             : 
     275           4 :         dos_format(dname);
     276             : 
     277           4 :         if (*(dname+strlen(dname)-1) != '\\') {
     278           4 :                 dname = talloc_append_string(NULL, dname, "\\");
     279             :         }
     280           4 :         dos_clean_name(dname);
     281             :         
     282           4 :         if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, dname))) {
     283           0 :                 d_printf("cd %s: %s\n", dname, smbcli_errstr(ctx->cli->tree));
     284           0 :                 talloc_free(dname);
     285             :         } else {
     286           4 :                 ctx->remote_cur_dir = dname;
     287             :         }
     288             :         
     289           4 :         return 0;
     290             : }
     291             : 
     292             : /****************************************************************************
     293             : change directory
     294             : ****************************************************************************/
     295           4 : static int cmd_cd(struct smbclient_context *ctx, const char **args)
     296             : {
     297           4 :         int rc = 0;
     298             : 
     299           4 :         if (args[1]) 
     300           4 :                 rc = do_cd(ctx, args[1]);
     301             :         else
     302           0 :                 d_printf("Current directory is %s\n",ctx->remote_cur_dir);
     303             : 
     304           4 :         return rc;
     305             : }
     306             : 
     307             : 
     308           0 : static bool mask_match(struct smbcli_state *c, const char *string, 
     309             :                 const char *pattern, bool is_case_sensitive)
     310             : {
     311             :         int ret;
     312             : 
     313           0 :         if (ISDOTDOT(string))
     314           0 :                 string = ".";
     315           0 :         if (ISDOT(pattern))
     316           0 :                 return false;
     317             : 
     318           0 :         ret = ms_fnmatch_protocol(pattern, string,
     319           0 :                                   c->transport->negotiate.protocol,
     320             :                                   is_case_sensitive);
     321           0 :         return (ret == 0);
     322             : }
     323             : 
     324             : 
     325             : 
     326             : /*******************************************************************
     327             :   decide if a file should be operated on
     328             :   ********************************************************************/
     329         274 : static bool do_this_one(struct smbclient_context *ctx, struct clilist_file_info *finfo)
     330             : {
     331         274 :         if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) return(true);
     332             : 
     333         102 :         if (ctx->fileselection && 
     334           0 :             !mask_match(ctx->cli, finfo->name,ctx->fileselection,false)) {
     335           0 :                 DEBUG(3,("mask_match %s failed\n", finfo->name));
     336           0 :                 return false;
     337             :         }
     338             : 
     339         102 :         if (ctx->newer_than && finfo->mtime < ctx->newer_than) {
     340           0 :                 DEBUG(3,("newer_than %s failed\n", finfo->name));
     341           0 :                 return(false);
     342             :         }
     343             : 
     344         102 :         if ((ctx->archive_level==1 || ctx->archive_level==2) && !(finfo->attrib & FILE_ATTRIBUTE_ARCHIVE)) {
     345           0 :                 DEBUG(3,("archive %s failed\n", finfo->name));
     346           0 :                 return(false);
     347             :         }
     348             :         
     349         102 :         return(true);
     350             : }
     351             : 
     352             : /****************************************************************************
     353             :   display info about a file
     354             :   ****************************************************************************/
     355         136 : static void display_finfo(struct smbclient_context *ctx, struct clilist_file_info *finfo)
     356             : {
     357         136 :         if (do_this_one(ctx, finfo)) {
     358         136 :                 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
     359         136 :                 char *astr = attrib_string(NULL, finfo->attrib);
     360         136 :                 d_printf("  %-30s%7.7s %8.0f  %s",
     361             :                          finfo->name,
     362             :                          astr,
     363         136 :                          (double)finfo->size,
     364         136 :                          asctime(localtime(&t)));
     365         136 :                 dir_total += finfo->size;
     366         136 :                 talloc_free(astr);
     367             :         }
     368         136 : }
     369             : 
     370             : 
     371             : /****************************************************************************
     372             :    accumulate size of a file
     373             :   ****************************************************************************/
     374           0 : static void do_du(struct smbclient_context *ctx, struct clilist_file_info *finfo)
     375             : {
     376           0 :         if (do_this_one(ctx, finfo)) {
     377           0 :                 dir_total += finfo->size;
     378             :         }
     379           0 : }
     380             : 
     381             : static bool do_list_recurse;
     382             : static bool do_list_dirs;
     383             : static char *do_list_queue = 0;
     384             : static long do_list_queue_size = 0;
     385             : static long do_list_queue_start = 0;
     386             : static long do_list_queue_end = 0;
     387             : static void (*do_list_fn)(struct smbclient_context *, struct clilist_file_info *);
     388             : 
     389             : /****************************************************************************
     390             : functions for do_list_queue
     391             :   ****************************************************************************/
     392             : 
     393             : /*
     394             :  * The do_list_queue is a NUL-separated list of strings stored in a
     395             :  * char*.  Since this is a FIFO, we keep track of the beginning and
     396             :  * ending locations of the data in the queue.  When we overflow, we
     397             :  * double the size of the char*.  When the start of the data passes
     398             :  * the midpoint, we move everything back.  This is logically more
     399             :  * complex than a linked list, but easier from a memory management
     400             :  * angle.  In any memory error condition, do_list_queue is reset.
     401             :  * Functions check to ensure that do_list_queue is non-NULL before
     402             :  * accessing it.
     403             :  */
     404          12 : static void reset_do_list_queue(void)
     405             : {
     406          12 :         SAFE_FREE(do_list_queue);
     407          12 :         do_list_queue_size = 0;
     408          12 :         do_list_queue_start = 0;
     409          12 :         do_list_queue_end = 0;
     410          12 : }
     411             : 
     412           0 : static void init_do_list_queue(void)
     413             : {
     414           0 :         reset_do_list_queue();
     415           0 :         do_list_queue_size = 1024;
     416           0 :         do_list_queue = malloc_array_p(char, do_list_queue_size);
     417           0 :         if (do_list_queue == 0) { 
     418           0 :                 d_printf("malloc fail for size %d\n",
     419             :                          (int)do_list_queue_size);
     420           0 :                 reset_do_list_queue();
     421             :         } else {
     422           0 :                 memset(do_list_queue, 0, do_list_queue_size);
     423             :         }
     424           0 : }
     425             : 
     426           0 : static void adjust_do_list_queue(void)
     427             : {
     428           0 :         if (do_list_queue == NULL) return;
     429             : 
     430             :         /*
     431             :          * If the starting point of the queue is more than half way through,
     432             :          * move everything toward the beginning.
     433             :          */
     434           0 :         if (do_list_queue_start == do_list_queue_end)
     435             :         {
     436           0 :                 DEBUG(4,("do_list_queue is empty\n"));
     437           0 :                 do_list_queue_start = do_list_queue_end = 0;
     438           0 :                 *do_list_queue = '\0';
     439             :         }
     440           0 :         else if (do_list_queue_start > (do_list_queue_size / 2))
     441             :         {
     442           0 :                 DEBUG(4,("sliding do_list_queue backward\n"));
     443           0 :                 memmove(do_list_queue,
     444           0 :                         do_list_queue + do_list_queue_start,
     445           0 :                         do_list_queue_end - do_list_queue_start);
     446           0 :                 do_list_queue_end -= do_list_queue_start;
     447           0 :                 do_list_queue_start = 0;
     448             :         }
     449             :            
     450             : }
     451             : 
     452           0 : static void add_to_do_list_queue(const char* entry)
     453             : {
     454             :         char *dlq;
     455             :         long new_end;
     456             : 
     457           0 :         if (entry == NULL) {
     458           0 :                 entry = "";
     459             :         }
     460             : 
     461           0 :         new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
     462           0 :         while (new_end > do_list_queue_size)
     463             :         {
     464           0 :                 do_list_queue_size *= 2;
     465           0 :                 DEBUG(4,("enlarging do_list_queue to %d\n",
     466             :                          (int)do_list_queue_size));
     467           0 :                 dlq = realloc_p(do_list_queue, char, do_list_queue_size);
     468           0 :                 if (! dlq) {
     469           0 :                         d_printf("failure enlarging do_list_queue to %d bytes\n",
     470             :                                  (int)do_list_queue_size);
     471           0 :                         reset_do_list_queue();
     472             :                 }
     473             :                 else
     474             :                 {
     475           0 :                         do_list_queue = dlq;
     476           0 :                         memset(do_list_queue + do_list_queue_size / 2,
     477           0 :                                0, do_list_queue_size / 2);
     478             :                 }
     479             :         }
     480           0 :         if (do_list_queue)
     481             :         {
     482           0 :                 strlcpy(do_list_queue + do_list_queue_end, entry,
     483           0 :                             do_list_queue_size - do_list_queue_end);
     484           0 :                 do_list_queue_end = new_end;
     485           0 :                 DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n",
     486             :                          entry, (int)do_list_queue_start, (int)do_list_queue_end));
     487             :         }
     488           0 : }
     489             : 
     490           0 : static char *do_list_queue_head(void)
     491             : {
     492           0 :         return do_list_queue + do_list_queue_start;
     493             : }
     494             : 
     495           0 : static void remove_do_list_queue_head(void)
     496             : {
     497           0 :         if (do_list_queue_end > do_list_queue_start)
     498             :         {
     499           0 :                 do_list_queue_start += strlen(do_list_queue_head()) + 1;
     500           0 :                 adjust_do_list_queue();
     501           0 :                 DEBUG(4,("removed head of do_list_queue (start=%d, end=%d)\n",
     502             :                          (int)do_list_queue_start, (int)do_list_queue_end));
     503             :         }
     504           0 : }
     505             : 
     506           0 : static int do_list_queue_empty(void)
     507             : {
     508           0 :         return (! (do_list_queue && *do_list_queue));
     509             : }
     510             : 
     511             : /****************************************************************************
     512             : a helper for do_list
     513             :   ****************************************************************************/
     514         138 : static void do_list_helper(struct clilist_file_info *f, const char *mask, void *state)
     515             : {
     516         138 :         struct smbclient_context *ctx = (struct smbclient_context *)state;
     517             : 
     518         138 :         if (f->attrib & FILE_ATTRIBUTE_DIRECTORY) {
     519          86 :                 if (do_list_dirs && do_this_one(ctx, f)) {
     520          86 :                         do_list_fn(ctx, f);
     521             :                 }
     522          86 :                 if (do_list_recurse && 
     523           0 :                     !ISDOT(f->name) &&
     524           0 :                     !ISDOTDOT(f->name)) {
     525             :                         char *mask2;
     526             :                         char *p;
     527             : 
     528           0 :                         mask2 = talloc_strdup(NULL, mask);
     529           0 :                         p = strrchr_m(mask2,'\\');
     530           0 :                         if (!p) return;
     531           0 :                         p[1] = 0;
     532           0 :                         mask2 = talloc_asprintf_append_buffer(mask2, "%s\\*", f->name);
     533           0 :                         add_to_do_list_queue(mask2);
     534             :                 }
     535          86 :                 return;
     536             :         }
     537             : 
     538          52 :         if (do_this_one(ctx, f)) {
     539          52 :                 do_list_fn(ctx, f);
     540             :         }
     541             : }
     542             : 
     543             : 
     544             : /****************************************************************************
     545             : a wrapper around smbcli_list that adds recursion
     546             :   ****************************************************************************/
     547          12 : static void do_list(struct smbclient_context *ctx, const char *mask,uint16_t attribute,
     548             :              void (*fn)(struct smbclient_context *, struct clilist_file_info *),bool rec, bool dirs)
     549             : {
     550             :         static int in_do_list = 0;
     551             : 
     552          12 :         if (in_do_list && rec)
     553             :         {
     554           0 :                 fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n");
     555           0 :                 exit(1);
     556             :         }
     557             : 
     558          12 :         in_do_list = 1;
     559             : 
     560          12 :         do_list_recurse = rec;
     561          12 :         do_list_dirs = dirs;
     562          12 :         do_list_fn = fn;
     563             : 
     564          12 :         if (rec)
     565             :         {
     566           0 :                 init_do_list_queue();
     567           0 :                 add_to_do_list_queue(mask);
     568             :                 
     569           0 :                 while (! do_list_queue_empty())
     570             :                 {
     571             :                         /*
     572             :                          * Need to copy head so that it doesn't become
     573             :                          * invalid inside the call to smbcli_list.  This
     574             :                          * would happen if the list were expanded
     575             :                          * during the call.
     576             :                          * Fix from E. Jay Berkenbilt (ejb@ql.org)
     577             :                          */
     578             :                         char *head;
     579           0 :                         head = do_list_queue_head();
     580           0 :                         smbcli_list(ctx->cli->tree, head, attribute, do_list_helper, ctx);
     581           0 :                         remove_do_list_queue_head();
     582           0 :                         if ((! do_list_queue_empty()) && (fn == display_finfo))
     583             :                         {
     584           0 :                                 char* next_file = do_list_queue_head();
     585           0 :                                 char* save_ch = 0;
     586           0 :                                 if ((strlen(next_file) >= 2) &&
     587           0 :                                     (next_file[strlen(next_file) - 1] == '*') &&
     588           0 :                                     (next_file[strlen(next_file) - 2] == '\\'))
     589             :                                 {
     590           0 :                                         save_ch = next_file +
     591           0 :                                                 strlen(next_file) - 2;
     592           0 :                                         *save_ch = '\0';
     593             :                                 }
     594           0 :                                 d_printf("\n%s\n",next_file);
     595           0 :                                 if (save_ch)
     596             :                                 {
     597           0 :                                         *save_ch = '\\';
     598             :                                 }
     599             :                         }
     600             :                 }
     601             :         }
     602             :         else
     603             :         {
     604          12 :                 if (smbcli_list(ctx->cli->tree, mask, attribute, do_list_helper, ctx) == -1)
     605             :                 {
     606           0 :                         d_printf("%s listing %s\n", smbcli_errstr(ctx->cli->tree), mask);
     607             :                 }
     608             :         }
     609             : 
     610          12 :         in_do_list = 0;
     611          12 :         reset_do_list_queue();
     612          12 : }
     613             : 
     614             : /****************************************************************************
     615             :   get a directory listing
     616             :   ****************************************************************************/
     617          10 : static int cmd_dir(struct smbclient_context *ctx, const char **args)
     618             : {
     619          10 :         uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
     620             :         char *mask;
     621             :         int rc;
     622             :         
     623          10 :         dir_total = 0;
     624             :         
     625          10 :         mask = talloc_strdup(ctx, ctx->remote_cur_dir);
     626          10 :         if(mask[strlen(mask)-1]!='\\')
     627           0 :                 mask = talloc_append_string(ctx, mask,"\\");
     628             :         
     629          10 :         if (args[1]) {
     630           0 :                 mask = talloc_strdup(ctx, args[1]);
     631           0 :                 if (mask[0] != '\\')
     632           0 :                         mask = talloc_append_string(ctx, mask, "\\");
     633           0 :                 dos_format(mask);
     634             :         }
     635             :         else {
     636          10 :                 if (ctx->cli->tree->session->transport->negotiate.protocol <= 
     637             :                     PROTOCOL_LANMAN1) { 
     638           0 :                         mask = talloc_append_string(ctx, mask, "*.*");
     639             :                 } else {
     640          10 :                         mask = talloc_append_string(ctx, mask, "*");
     641             :                 }
     642             :         }
     643             : 
     644          10 :         do_list(ctx, mask, attribute, display_finfo, ctx->recurse, true);
     645             : 
     646          10 :         rc = do_dskattr(ctx);
     647             : 
     648          10 :         DEBUG(3, ("Total bytes listed: %.0f\n", dir_total));
     649             : 
     650          10 :         return rc;
     651             : }
     652             : 
     653             : 
     654             : /****************************************************************************
     655             :   get a directory listing
     656             :   ****************************************************************************/
     657           0 : static int cmd_du(struct smbclient_context *ctx, const char **args)
     658             : {
     659           0 :         uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
     660             :         int rc;
     661             :         char *mask;
     662             :         
     663           0 :         dir_total = 0;
     664             :         
     665           0 :         if (args[1]) {
     666           0 :                 if (args[1][0] == '\\')
     667           0 :                         mask = talloc_strdup(ctx, args[1]);
     668             :                 else
     669           0 :                         mask = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
     670           0 :                 dos_format(mask);
     671             :         } else {
     672           0 :                 mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir);
     673             :         }
     674             : 
     675           0 :         do_list(ctx, mask, attribute, do_du, ctx->recurse, true);
     676             : 
     677           0 :         talloc_free(mask);
     678             : 
     679           0 :         rc = do_dskattr(ctx);
     680             : 
     681           0 :         d_printf("Total number of bytes: %.0f\n", dir_total);
     682             : 
     683           0 :         return rc;
     684             : }
     685             : 
     686             : 
     687             : /****************************************************************************
     688             :   get a file from rname to lname
     689             :   ****************************************************************************/
     690           6 : static int do_get(struct smbclient_context *ctx, char *rname, const char *p_lname, bool reget)
     691             : {  
     692           6 :         int handle = 0, fnum;
     693           6 :         bool newhandle = false;
     694             :         uint8_t *data;
     695             :         struct timeval tp_start;
     696           6 :         int read_size = ctx->io_bufsize;
     697             :         uint16_t attr;
     698             :         size_t size;
     699           6 :         off_t start = 0;
     700           6 :         off_t nread = 0;
     701           6 :         int rc = 0;
     702             :         char *lname;
     703             : 
     704             : 
     705           6 :         GetTimeOfDay(&tp_start);
     706             : 
     707           6 :         if (ctx->lowercase) {
     708           0 :                 lname = strlower_talloc(ctx, p_lname);
     709             :         } else {
     710           6 :                 lname = talloc_strdup(ctx, p_lname);
     711             :         }
     712             : 
     713           6 :         fnum = smbcli_open(ctx->cli->tree, rname, O_RDONLY, DENY_NONE);
     714             : 
     715           6 :         if (fnum == -1) {
     716           0 :                 d_printf("%s opening remote file %s\n",smbcli_errstr(ctx->cli->tree),rname);
     717           0 :                 return 1;
     718             :         }
     719             : 
     720           6 :         if(!strcmp(lname,"-")) {
     721           0 :                 handle = fileno(stdout);
     722             :         } else {
     723           6 :                 if (reget) {
     724           0 :                         handle = open(lname, O_WRONLY|O_CREAT, 0644);
     725           0 :                         if (handle >= 0) {
     726           0 :                                 start = lseek(handle, 0, SEEK_END);
     727           0 :                                 if (start == -1) {
     728           0 :                                         d_printf("Error seeking local file\n");
     729           0 :                                         close(handle);
     730           0 :                                         return 1;
     731             :                                 }
     732             :                         }
     733             :                 } else {
     734           6 :                         handle = open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
     735             :                 }
     736           6 :                 newhandle = true;
     737             :         }
     738           6 :         if (handle < 0) {
     739           0 :                 d_printf("Error opening local file %s\n",lname);
     740           0 :                 return 1;
     741             :         }
     742             : 
     743             : 
     744           6 :         if (NT_STATUS_IS_ERR(smbcli_qfileinfo(ctx->cli->tree, fnum, 
     745           0 :                            &attr, &size, NULL, NULL, NULL, NULL, NULL)) &&
     746           0 :             NT_STATUS_IS_ERR(smbcli_getattrE(ctx->cli->tree, fnum, 
     747             :                           &attr, &size, NULL, NULL, NULL))) {
     748           0 :                 d_printf("getattrib: %s\n",smbcli_errstr(ctx->cli->tree));
     749           0 :                 if (newhandle) {
     750           0 :                         close(handle);
     751             :                 }
     752           0 :                 return 1;
     753             :         }
     754             : 
     755           6 :         DEBUG(2,("getting file %s of size %.0f as %s ", 
     756             :                  rname, (double)size, lname));
     757             : 
     758           6 :         if(!(data = (uint8_t *)malloc(read_size))) { 
     759           0 :                 d_printf("malloc fail for size %d\n", read_size);
     760           0 :                 smbcli_close(ctx->cli->tree, fnum);
     761           0 :                 if (newhandle) {
     762           0 :                         close(handle);
     763             :                 }
     764           0 :                 return 1;
     765             :         }
     766             : 
     767          30 :         while (1) {
     768          36 :                 int n = smbcli_read(ctx->cli->tree, fnum, data, nread + start, read_size);
     769             : 
     770          36 :                 if (n <= 0) break;
     771             :  
     772          30 :                 if (writefile(handle,data, n, ctx->translation) != n) {
     773           0 :                         d_printf("Error writing local file\n");
     774           0 :                         rc = 1;
     775           0 :                         break;
     776             :                 }
     777             :       
     778          30 :                 nread += n;
     779             :         }
     780             : 
     781           6 :         if (nread + start < size) {
     782           0 :                 DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n",
     783             :                             rname, (long)nread));
     784             : 
     785           0 :                 rc = 1;
     786             :         }
     787             : 
     788           6 :         SAFE_FREE(data);
     789             :         
     790           6 :         if (NT_STATUS_IS_ERR(smbcli_close(ctx->cli->tree, fnum))) {
     791           0 :                 d_printf("Error %s closing remote file\n",smbcli_errstr(ctx->cli->tree));
     792           0 :                 rc = 1;
     793             :         }
     794             : 
     795           6 :         if (newhandle) {
     796           6 :                 close(handle);
     797             :         }
     798             : 
     799           6 :         if (ctx->archive_level >= 2 && (attr & FILE_ATTRIBUTE_ARCHIVE)) {
     800           0 :                 smbcli_setatr(ctx->cli->tree, rname, attr & ~(uint16_t)FILE_ATTRIBUTE_ARCHIVE, 0);
     801             :         }
     802             : 
     803             :         {
     804             :                 struct timeval tp_end;
     805             :                 int this_time;
     806             :                 
     807           6 :                 GetTimeOfDay(&tp_end);
     808           6 :                 this_time = 
     809           6 :                         (tp_end.tv_sec - tp_start.tv_sec)*1000 +
     810           6 :                         (tp_end.tv_usec - tp_start.tv_usec)/1000;
     811           6 :                 get_total_time_ms += this_time;
     812           6 :                 get_total_size += nread;
     813             :                 
     814           6 :                 DEBUG(2,("(%3.1f kb/s) (average %3.1f kb/s)\n",
     815             :                          nread / (1.024*this_time + 1.0e-4),
     816             :                          get_total_size / (1.024*get_total_time_ms)));
     817             :         }
     818             :         
     819           6 :         return rc;
     820             : }
     821             : 
     822             : 
     823             : /****************************************************************************
     824             :   get a file
     825             :   ****************************************************************************/
     826           4 : static int cmd_get(struct smbclient_context *ctx, const char **args)
     827             : {
     828             :         const char *lname;
     829             :         char *rname;
     830             : 
     831           4 :         if (!args[1]) {
     832           0 :                 d_printf("get <filename>\n");
     833           0 :                 return 1;
     834             :         }
     835             : 
     836           4 :         rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
     837             : 
     838           4 :         if (args[2]) 
     839           0 :                 lname = args[2];
     840             :         else 
     841           4 :                 lname = args[1];
     842             :         
     843           4 :         dos_clean_name(rname);
     844             :         
     845           4 :         return do_get(ctx, rname, lname, false);
     846             : }
     847             : 
     848             : /****************************************************************************
     849             :  Put up a yes/no prompt.
     850             : ****************************************************************************/
     851           0 : static bool yesno(char *p)
     852             : {
     853             :         char ans[4];
     854           0 :         printf("%s",p);
     855             : 
     856           0 :         if (!fgets(ans,sizeof(ans)-1,stdin))
     857           0 :                 return(false);
     858             : 
     859           0 :         if (*ans == 'y' || *ans == 'Y')
     860           0 :                 return(true);
     861             : 
     862           0 :         return(false);
     863             : }
     864             : 
     865             : /****************************************************************************
     866             :   do a mget operation on one file
     867             :   ****************************************************************************/
     868           2 : static void do_mget(struct smbclient_context *ctx, struct clilist_file_info *finfo)
     869             : {
     870             :         char *rname;
     871             :         char *quest;
     872             :         char *mget_mask;
     873             :         char *saved_curdir;
     874             :         char *l_fname;
     875             :         int ret;
     876             : 
     877           2 :         if (ISDOT(finfo->name) || ISDOTDOT(finfo->name))
     878           0 :                 return;
     879             : 
     880           2 :         if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)
     881           0 :                 quest = talloc_asprintf(ctx, "Get directory %s? ",finfo->name);
     882             :         else
     883           2 :                 quest = talloc_asprintf(ctx, "Get file %s? ",finfo->name);
     884             : 
     885           2 :         if (ctx->prompt && !yesno(quest)) return;
     886             : 
     887           2 :         talloc_free(quest);
     888             : 
     889           2 :         if (!(finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)) {
     890           2 :                 rname = talloc_asprintf(ctx, "%s%s",ctx->remote_cur_dir,
     891             :                                         finfo->name);
     892           2 :                 do_get(ctx, rname, finfo->name, false);
     893           2 :                 talloc_free(rname);
     894           2 :                 return;
     895             :         }
     896             : 
     897             :         /* handle directories */
     898           0 :         saved_curdir = talloc_strdup(ctx, ctx->remote_cur_dir);
     899             : 
     900           0 :         ctx->remote_cur_dir = talloc_asprintf_append_buffer(NULL, "%s\\", finfo->name);
     901             : 
     902           0 :         if (ctx->lowercase) {
     903           0 :                 l_fname = strlower_talloc(ctx, finfo->name);
     904             :         } else {
     905           0 :                 l_fname = talloc_strdup(ctx, finfo->name);
     906             :         }
     907             :         
     908           0 :         string_replace(l_fname, '\\', '/');
     909             : 
     910           0 :         if (!directory_exist(l_fname) &&
     911           0 :             mkdir(l_fname, 0777) != 0) {
     912           0 :                 d_printf("failed to create directory %s\n", l_fname);
     913           0 :                 return;
     914             :         }
     915             :         
     916           0 :         if (chdir(l_fname) != 0) {
     917           0 :                 d_printf("failed to chdir to directory %s\n", l_fname);
     918           0 :                 return;
     919             :         }
     920             : 
     921           0 :         mget_mask = talloc_asprintf(ctx, "%s*", ctx->remote_cur_dir);
     922             :         
     923           0 :         do_list(ctx, mget_mask, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,do_mget,false, true);
     924           0 :         ret = chdir("..");
     925           0 :         if (ret == -1) {
     926           0 :                 d_printf("failed to chdir to '..': %s\n", strerror(errno));
     927           0 :                 return;
     928             :         }
     929           0 :         talloc_free(ctx->remote_cur_dir);
     930             : 
     931           0 :         ctx->remote_cur_dir = saved_curdir;
     932             : }
     933             : 
     934             : 
     935             : /****************************************************************************
     936             : view the file using the pager
     937             : ****************************************************************************/
     938           0 : static int cmd_more(struct smbclient_context *ctx, const char **args)
     939             : {
     940             :         char *rname;
     941             :         char *pager_cmd;
     942             :         char *lname;
     943             :         char *pager;
     944             :         int fd;
     945           0 :         int rc = 0;
     946             :         mode_t mask;
     947             : 
     948           0 :         lname = talloc_asprintf(ctx, "%s/smbmore.XXXXXX",tmpdir());
     949           0 :         mask = umask(S_IRWXO | S_IRWXG);
     950           0 :         fd = mkstemp(lname);
     951           0 :         umask(mask);
     952           0 :         if (fd == -1) {
     953           0 :                 d_printf("failed to create temporary file for more\n");
     954           0 :                 return 1;
     955             :         }
     956           0 :         close(fd);
     957             : 
     958           0 :         if (!args[1]) {
     959           0 :                 d_printf("more <filename>\n");
     960           0 :                 unlink(lname);
     961           0 :                 return 1;
     962             :         }
     963           0 :         rname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
     964           0 :         dos_clean_name(rname);
     965             : 
     966           0 :         rc = do_get(ctx, rname, lname, false);
     967             : 
     968           0 :         pager=getenv("PAGER");
     969             : 
     970           0 :         pager_cmd = talloc_asprintf(ctx, "%s %s",(pager? pager:DEFAULT_PAGER), lname);
     971           0 :         rc = system(pager_cmd);
     972           0 :         if (rc == -1) {
     973           0 :                 d_printf("failed to call pager command\n");
     974           0 :                 return 1;
     975             :         }
     976           0 :         unlink(lname);
     977             :         
     978           0 :         return rc;
     979             : }
     980             : 
     981             : 
     982             : 
     983             : /****************************************************************************
     984             : do a mget command
     985             : ****************************************************************************/
     986           2 : static int cmd_mget(struct smbclient_context *ctx, const char **args)
     987             : {
     988           2 :         uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
     989           2 :         char *mget_mask = NULL;
     990             :         int i;
     991             : 
     992           2 :         if (ctx->recurse)
     993           0 :                 attribute |= FILE_ATTRIBUTE_DIRECTORY;
     994             :         
     995           4 :         for (i = 1; args[i]; i++) {
     996           2 :                 mget_mask = talloc_strdup(ctx, ctx->remote_cur_dir);
     997           2 :                 if(mget_mask[strlen(mget_mask)-1]!='\\')
     998           0 :                         mget_mask = talloc_append_string(ctx, mget_mask, "\\");
     999             :                 
    1000           2 :                 mget_mask = talloc_strdup(ctx, args[i]);
    1001           2 :                 if (mget_mask[0] != '\\')
    1002           2 :                         mget_mask = talloc_append_string(ctx, mget_mask, "\\");
    1003           2 :                 do_list(ctx, mget_mask, attribute,do_mget,false,true);
    1004             : 
    1005           2 :                 talloc_free(mget_mask);
    1006             :         }
    1007             : 
    1008           2 :         if (mget_mask == NULL) {
    1009           0 :                 mget_mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir);
    1010           0 :                 do_list(ctx, mget_mask, attribute,do_mget,false,true);
    1011           0 :                 talloc_free(mget_mask);
    1012             :         }
    1013             :         
    1014           2 :         return 0;
    1015             : }
    1016             : 
    1017             : 
    1018             : /****************************************************************************
    1019             : make a directory of name "name"
    1020             : ****************************************************************************/
    1021           6 : static NTSTATUS do_mkdir(struct smbclient_context *ctx, char *name)
    1022             : {
    1023             :         NTSTATUS status;
    1024             : 
    1025           6 :         if (NT_STATUS_IS_ERR(status = smbcli_mkdir(ctx->cli->tree, name))) {
    1026           2 :                 d_printf("%s making remote directory %s\n",
    1027           2 :                          smbcli_errstr(ctx->cli->tree),name);
    1028           2 :                 return status;
    1029             :         }
    1030             : 
    1031           4 :         return status;
    1032             : }
    1033             : 
    1034             : 
    1035             : /****************************************************************************
    1036             :  Exit client.
    1037             : ****************************************************************************/
    1038           0 : static int cmd_quit(struct smbclient_context *ctx, const char **args)
    1039             : {
    1040           0 :         talloc_free(ctx);
    1041           0 :         exit(0);
    1042             :         /* NOTREACHED */
    1043             :         return 0;
    1044             : }
    1045             : 
    1046             : 
    1047             : /****************************************************************************
    1048             :   make a directory
    1049             :   ****************************************************************************/
    1050           6 : static int cmd_mkdir(struct smbclient_context *ctx, const char **args)
    1051             : {
    1052             :         char *mask, *p;
    1053             :   
    1054           6 :         if (!args[1]) {
    1055           0 :                 if (!ctx->recurse)
    1056           0 :                         d_printf("mkdir <dirname>\n");
    1057           0 :                 return 1;
    1058             :         }
    1059             : 
    1060           6 :         mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir,args[1]);
    1061             : 
    1062           6 :         if (ctx->recurse) {
    1063           0 :                 dos_clean_name(mask);
    1064             : 
    1065           0 :                 trim_string(mask,".",NULL);
    1066           0 :                 for (p = strtok(mask,"/\\"); p; p = strtok(p, "/\\")) {
    1067           0 :                         char *parent = talloc_strndup(ctx, mask, PTR_DIFF(p, mask));
    1068             :                         
    1069           0 :                         if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, parent))) { 
    1070           0 :                                 do_mkdir(ctx, parent);
    1071             :                         }
    1072             : 
    1073           0 :                         talloc_free(parent);
    1074             :                 }        
    1075             :         } else {
    1076           6 :                 do_mkdir(ctx, mask);
    1077             :         }
    1078             :         
    1079           6 :         return 0;
    1080             : }
    1081             : 
    1082             : /****************************************************************************
    1083             : show 8.3 name of a file
    1084             : ****************************************************************************/
    1085           2 : static int cmd_altname(struct smbclient_context *ctx, const char **args)
    1086             : {
    1087             :         const char *p;
    1088             :         char *altname;
    1089             :         char *name;
    1090             :   
    1091           2 :         if (!args[1]) {
    1092           0 :                 d_printf("altname <file>\n");
    1093           0 :                 return 1;
    1094             :         }
    1095             : 
    1096           2 :         name = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
    1097             : 
    1098           2 :         if (!NT_STATUS_IS_OK(smbcli_qpathinfo_alt_name(ctx->cli->tree, name, &p))) {
    1099           0 :                 d_printf("%s getting alt name for %s\n",
    1100           0 :                          smbcli_errstr(ctx->cli->tree),name);
    1101           0 :                 return(false);
    1102             :         }
    1103           2 :         altname = discard_const_p(char, p);
    1104           2 :         d_printf("%s\n", altname);
    1105             : 
    1106           2 :         SAFE_FREE(altname);
    1107             : 
    1108           2 :         return 0;
    1109             : }
    1110             : 
    1111             : 
    1112             : /****************************************************************************
    1113             :   put a single file
    1114             :   ****************************************************************************/
    1115           6 : static int do_put(struct smbclient_context *ctx, char *rname, char *lname, bool reput)
    1116             : {
    1117             :         int fnum;
    1118             :         FILE *f;
    1119           6 :         size_t start = 0;
    1120           6 :         off_t nread = 0;
    1121           6 :         uint8_t *buf = NULL;
    1122           6 :         int maxwrite = ctx->io_bufsize;
    1123           6 :         int rc = 0;
    1124             :         
    1125             :         struct timeval tp_start;
    1126           6 :         GetTimeOfDay(&tp_start);
    1127             : 
    1128           6 :         if (reput) {
    1129           0 :                 fnum = smbcli_open(ctx->cli->tree, rname, O_RDWR|O_CREAT, DENY_NONE);
    1130           0 :                 if (fnum >= 0) {
    1131           0 :                         if (NT_STATUS_IS_ERR(smbcli_qfileinfo(ctx->cli->tree, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL)) &&
    1132           0 :                             NT_STATUS_IS_ERR(smbcli_getattrE(ctx->cli->tree, fnum, NULL, &start, NULL, NULL, NULL))) {
    1133           0 :                                 d_printf("getattrib: %s\n",smbcli_errstr(ctx->cli->tree));
    1134           0 :                                 return 1;
    1135             :                         }
    1136             :                 }
    1137             :         } else {
    1138           6 :                 fnum = smbcli_open(ctx->cli->tree, rname, O_RDWR|O_CREAT|O_TRUNC, 
    1139             :                                 DENY_NONE);
    1140             :         }
    1141             :   
    1142           6 :         if (fnum == -1) {
    1143           0 :                 d_printf("%s opening remote file %s\n",smbcli_errstr(ctx->cli->tree),rname);
    1144           0 :                 return 1;
    1145             :         }
    1146             : 
    1147             :         /* allow files to be piped into smbclient
    1148             :            jdblair 24.jun.98
    1149             : 
    1150             :            Note that in this case this function will exit(0) rather
    1151             :            than returning. */
    1152           6 :         if (!strcmp(lname, "-")) {
    1153           0 :                 f = stdin;
    1154             :                 /* size of file is not known */
    1155             :         } else {
    1156           6 :                 f = fopen(lname, "r");
    1157           6 :                 if (f && reput) {
    1158           0 :                         if (fseek(f, start, SEEK_SET) == -1) {
    1159           0 :                                 d_printf("Error seeking local file\n");
    1160           0 :                                 fclose(f);
    1161           0 :                                 return 1;
    1162             :                         }
    1163             :                 }
    1164             :         }
    1165             : 
    1166           6 :         if (!f) {
    1167           0 :                 d_printf("Error opening local file %s\n",lname);
    1168           0 :                 return 1;
    1169             :         }
    1170             : 
    1171             :   
    1172           6 :         DEBUG(1,("putting file %s as %s ",lname,
    1173             :                  rname));
    1174             :   
    1175           6 :         buf = (uint8_t *)malloc(maxwrite);
    1176           6 :         if (!buf) {
    1177           0 :                 d_printf("ERROR: Not enough memory!\n");
    1178           0 :                 fclose(f);
    1179           0 :                 return 1;
    1180             :         }
    1181          36 :         while (!feof(f)) {
    1182          30 :                 int n = maxwrite;
    1183             :                 int ret;
    1184             : 
    1185          30 :                 if ((n = readfile(buf,n,f,ctx->translation)) < 1) {
    1186           0 :                         if((n == 0) && feof(f))
    1187           0 :                                 break; /* Empty local file. */
    1188             : 
    1189           0 :                         d_printf("Error reading local file: %s\n", strerror(errno));
    1190           0 :                         rc = 1;
    1191           0 :                         break;
    1192             :                 }
    1193             : 
    1194          30 :                 ret = smbcli_write(ctx->cli->tree, fnum, 0, buf, nread + start, n);
    1195             : 
    1196          30 :                 if (n != ret) {
    1197           0 :                         d_printf("Error writing file: %s\n", smbcli_errstr(ctx->cli->tree));
    1198           0 :                         rc = 1;
    1199           0 :                         break;
    1200             :                 } 
    1201             : 
    1202          30 :                 nread += n;
    1203             :         }
    1204             : 
    1205           6 :         if (NT_STATUS_IS_ERR(smbcli_close(ctx->cli->tree, fnum))) {
    1206           0 :                 d_printf("%s closing remote file %s\n",smbcli_errstr(ctx->cli->tree),rname);
    1207           0 :                 fclose(f);
    1208           0 :                 SAFE_FREE(buf);
    1209           0 :                 return 1;
    1210             :         }
    1211             : 
    1212             :         
    1213           6 :         if (f != stdin) {
    1214           6 :                 fclose(f);
    1215             :         }
    1216             : 
    1217           6 :         SAFE_FREE(buf);
    1218             : 
    1219             :         {
    1220             :                 struct timeval tp_end;
    1221             :                 int this_time;
    1222             :                 
    1223           6 :                 GetTimeOfDay(&tp_end);
    1224           6 :                 this_time = 
    1225           6 :                         (tp_end.tv_sec - tp_start.tv_sec)*1000 +
    1226           6 :                         (tp_end.tv_usec - tp_start.tv_usec)/1000;
    1227           6 :                 put_total_time_ms += this_time;
    1228           6 :                 put_total_size += nread;
    1229             :                 
    1230           6 :                 DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
    1231             :                          nread / (1.024*this_time + 1.0e-4),
    1232             :                          put_total_size / (1.024*put_total_time_ms)));
    1233             :         }
    1234             : 
    1235           6 :         if (f == stdin) {
    1236           0 :                 talloc_free(ctx);
    1237           0 :                 exit(0);
    1238             :         }
    1239             :         
    1240           6 :         return rc;
    1241             : }
    1242             : 
    1243             :  
    1244             : 
    1245             : /****************************************************************************
    1246             :   put a file
    1247             :   ****************************************************************************/
    1248           4 : static int cmd_put(struct smbclient_context *ctx, const char **args)
    1249             : {
    1250             :         char *lname;
    1251             :         char *rname;
    1252             :         
    1253           4 :         if (!args[1]) {
    1254           0 :                 d_printf("put <filename> [<remotename>]\n");
    1255           0 :                 return 1;
    1256             :         }
    1257             : 
    1258           4 :         lname = talloc_strdup(ctx, args[1]);
    1259             :   
    1260           4 :         if (args[2]) {
    1261           2 :                 if (args[2][0]=='\\')
    1262           0 :                         rname = talloc_strdup(ctx, args[2]);
    1263             :                 else
    1264           2 :                         rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[2]);
    1265             :         } else {
    1266           2 :                 rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, lname);
    1267             :         }
    1268             :         
    1269           4 :         dos_clean_name(rname);
    1270             : 
    1271             :         /* allow '-' to represent stdin
    1272             :            jdblair, 24.jun.98 */
    1273           4 :         if (!file_exist(lname) && (strcmp(lname,"-"))) {
    1274           0 :                 d_printf("%s does not exist\n",lname);
    1275           0 :                 return 1;
    1276             :         }
    1277             : 
    1278           4 :         return do_put(ctx, rname, lname, false);
    1279             : }
    1280             : 
    1281             : /*************************************
    1282             :   File list structure
    1283             : *************************************/
    1284             : 
    1285             : static struct file_list {
    1286             :         struct file_list *prev, *next;
    1287             :         char *file_path;
    1288             :         bool isdir;
    1289             : } *file_list;
    1290             : 
    1291             : /****************************************************************************
    1292             :   Free a file_list structure
    1293             : ****************************************************************************/
    1294             : 
    1295           2 : static void free_file_list (struct file_list * list)
    1296             : {
    1297             :         struct file_list *tmp;
    1298             :         
    1299           4 :         while (list)
    1300             :         {
    1301           2 :                 tmp = list;
    1302           2 :                 DLIST_REMOVE(list, list);
    1303           2 :                 SAFE_FREE(tmp->file_path);
    1304           2 :                 SAFE_FREE(tmp);
    1305             :         }
    1306           2 : }
    1307             : 
    1308             : /****************************************************************************
    1309             :   seek in a directory/file list until you get something that doesn't start with
    1310             :   the specified name
    1311             :   ****************************************************************************/
    1312           0 : static bool seek_list(struct file_list *list, char *name)
    1313             : {
    1314           0 :         while (list) {
    1315           0 :                 trim_string(list->file_path,"./","\n");
    1316           0 :                 if (strncmp(list->file_path, name, strlen(name)) != 0) {
    1317           0 :                         return(true);
    1318             :                 }
    1319           0 :                 list = list->next;
    1320             :         }
    1321             :       
    1322           0 :         return(false);
    1323             : }
    1324             : 
    1325             : /****************************************************************************
    1326             :   set the file selection mask
    1327             :   ****************************************************************************/
    1328           0 : static int cmd_select(struct smbclient_context *ctx, const char **args)
    1329             : {
    1330           0 :         talloc_free(ctx->fileselection);
    1331           0 :         ctx->fileselection = talloc_strdup(ctx, args[1]);
    1332             : 
    1333           0 :         return 0;
    1334             : }
    1335             : 
    1336             : /*******************************************************************
    1337             :   A readdir wrapper which just returns the file name.
    1338             :  ********************************************************************/
    1339          37 : static const char *readdirname(DIR *p)
    1340             : {
    1341             :         struct dirent *ptr;
    1342             :         char *dname;
    1343             : 
    1344          37 :         if (!p)
    1345           0 :                 return(NULL);
    1346             :   
    1347          37 :         ptr = (struct dirent *)readdir(p);
    1348          37 :         if (!ptr)
    1349           2 :                 return(NULL);
    1350             : 
    1351          35 :         dname = ptr->d_name;
    1352             : 
    1353             : #ifdef HAVE_BROKEN_READDIR
    1354             :         /* using /usr/ucb/cc is BAD */
    1355             :         dname = dname - 2;
    1356             : #endif
    1357             : 
    1358             :         {
    1359             :                 static char *buf;
    1360          35 :                 int len = NAMLEN(ptr);
    1361          35 :                 buf = talloc_strndup(NULL, dname, len);
    1362          35 :                 dname = buf;
    1363             :         }
    1364             : 
    1365          35 :         return(dname);
    1366             : }
    1367             : 
    1368             : /****************************************************************************
    1369             :   Recursive file matching function act as find
    1370             :   match must be always set to true when calling this function
    1371             : ****************************************************************************/
    1372           2 : static int file_find(struct smbclient_context *ctx, struct file_list **list, const char *directory, 
    1373             :                       const char *expression, bool match)
    1374             : {
    1375             :         DIR *dir;
    1376             :         struct file_list *entry;
    1377             :         struct stat statbuf;
    1378             :         int ret;
    1379             :         char *path;
    1380             :         bool isdir;
    1381             :         const char *dname;
    1382             : 
    1383           2 :         dir = opendir(directory);
    1384           2 :         if (!dir) return -1;
    1385             :         
    1386          37 :         while ((dname = readdirname(dir))) {
    1387          35 :                 if (ISDOT(dname) || ISDOTDOT(dname)) {
    1388           4 :                         continue;
    1389             :                 }
    1390             :                 
    1391          31 :                 if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
    1392           0 :                         continue;
    1393             :                 }
    1394             : 
    1395          31 :                 isdir = false;
    1396          31 :                 if (!match || !gen_fnmatch(expression, dname)) {
    1397           2 :                         if (ctx->recurse) {
    1398           0 :                                 ret = stat(path, &statbuf);
    1399           0 :                                 if (ret == 0) {
    1400           0 :                                         if (S_ISDIR(statbuf.st_mode)) {
    1401           0 :                                                 isdir = true;
    1402           0 :                                                 ret = file_find(ctx, list, path, expression, false);
    1403             :                                         }
    1404             :                                 } else {
    1405           0 :                                         d_printf("file_find: cannot stat file %s\n", path);
    1406             :                                 }
    1407             :                                 
    1408           0 :                                 if (ret == -1) {
    1409           0 :                                         SAFE_FREE(path);
    1410           0 :                                         closedir(dir);
    1411           0 :                                         return -1;
    1412             :                                 }
    1413             :                         }
    1414           2 :                         entry = malloc_p(struct file_list);
    1415           2 :                         if (!entry) {
    1416           0 :                                 d_printf("Out of memory in file_find\n");
    1417           0 :                                 closedir(dir);
    1418           0 :                                 return -1;
    1419             :                         }
    1420           2 :                         entry->file_path = path;
    1421           2 :                         entry->isdir = isdir;
    1422           2 :                         DLIST_ADD(*list, entry);
    1423             :                 } else {
    1424          29 :                         SAFE_FREE(path);
    1425             :                 }
    1426             :         }
    1427             : 
    1428           2 :         closedir(dir);
    1429           2 :         return 0;
    1430             : }
    1431             : 
    1432             : /****************************************************************************
    1433             :   mput some files
    1434             :   ****************************************************************************/
    1435           2 : static int cmd_mput(struct smbclient_context *ctx, const char **args)
    1436             : {
    1437             :         int i;
    1438             :         
    1439           4 :         for (i = 1; args[i]; i++) {
    1440             :                 int ret;
    1441             :                 struct file_list *temp_list;
    1442             :                 char *quest, *lname, *rname;
    1443             : 
    1444           2 :                 printf("%s\n", args[i]);
    1445             :         
    1446           2 :                 file_list = NULL;
    1447             : 
    1448           2 :                 ret = file_find(ctx, &file_list, ".", args[i], true);
    1449           2 :                 if (ret) {
    1450           0 :                         free_file_list(file_list);
    1451           0 :                         continue;
    1452             :                 }
    1453             :                 
    1454           2 :                 quest = NULL;
    1455           2 :                 lname = NULL;
    1456           2 :                 rname = NULL;
    1457             :                                 
    1458           4 :                 for (temp_list = file_list; temp_list; 
    1459           2 :                      temp_list = temp_list->next) {
    1460             : 
    1461           2 :                         SAFE_FREE(lname);
    1462           2 :                         if (asprintf(&lname, "%s/", temp_list->file_path) <= 0)
    1463           0 :                                 continue;
    1464           2 :                         trim_string(lname, "./", "/");
    1465             :                         
    1466             :                         /* check if it's a directory */
    1467           2 :                         if (temp_list->isdir) {
    1468             :                                 /* if (!recurse) continue; */
    1469             :                                 
    1470           0 :                                 SAFE_FREE(quest);
    1471           0 :                                 if (asprintf(&quest, "Put directory %s? ", lname) < 0) break;
    1472           0 :                                 if (ctx->prompt && !yesno(quest)) { /* No */
    1473             :                                         /* Skip the directory */
    1474           0 :                                         lname[strlen(lname)-1] = '/';
    1475           0 :                                         if (!seek_list(temp_list, lname))
    1476           0 :                                                 break;              
    1477             :                                 } else { /* Yes */
    1478           0 :                                         SAFE_FREE(rname);
    1479           0 :                                         if(asprintf(&rname, "%s%s", ctx->remote_cur_dir, lname) < 0) break;
    1480           0 :                                         dos_format(rname);
    1481           0 :                                         if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, rname)) && 
    1482           0 :                                             NT_STATUS_IS_ERR(do_mkdir(ctx, rname))) {
    1483           0 :                                                 DEBUG (0, ("Unable to make dir, skipping...\n"));
    1484             :                                                 /* Skip the directory */
    1485           0 :                                                 lname[strlen(lname)-1] = '/';
    1486           0 :                                                 if (!seek_list(temp_list, lname))
    1487           0 :                                                         break;
    1488             :                                         }
    1489             :                                 }
    1490           0 :                                 continue;
    1491             :                         } else {
    1492           2 :                                 SAFE_FREE(quest);
    1493           2 :                                 if (asprintf(&quest,"Put file %s? ", lname) < 0) break;
    1494           2 :                                 if (ctx->prompt && !yesno(quest)) /* No */
    1495           0 :                                         continue;
    1496             :                                 
    1497             :                                 /* Yes */
    1498           2 :                                 SAFE_FREE(rname);
    1499           2 :                                 if (asprintf(&rname, "%s%s", ctx->remote_cur_dir, lname) < 0) break;
    1500             :                         }
    1501             : 
    1502           2 :                         dos_format(rname);
    1503             : 
    1504           2 :                         do_put(ctx, rname, lname, false);
    1505             :                 }
    1506           2 :                 free_file_list(file_list);
    1507           2 :                 SAFE_FREE(quest);
    1508           2 :                 SAFE_FREE(lname);
    1509           2 :                 SAFE_FREE(rname);
    1510             :         }
    1511             : 
    1512           2 :         return 0;
    1513             : }
    1514             : 
    1515             : 
    1516             : /****************************************************************************
    1517             :   print a file
    1518             :   ****************************************************************************/
    1519           0 : static int cmd_print(struct smbclient_context *ctx, const char **args)
    1520             : {
    1521             :         char *lname, *rname;
    1522             :         char *p;
    1523             : 
    1524           0 :         if (!args[1]) {
    1525           0 :                 d_printf("print <filename>\n");
    1526           0 :                 return 1;
    1527             :         }
    1528             : 
    1529           0 :         lname = talloc_strdup(ctx, args[1]);
    1530           0 :         if (lname == NULL) {
    1531           0 :                 d_printf("Out of memory in cmd_print\n");
    1532           0 :                 return 1;
    1533             :         }
    1534             : 
    1535           0 :         if (strequal(lname, "-")) {
    1536           0 :                 rname = talloc_asprintf(ctx, "stdin-%d", (int)getpid());
    1537             :         } else {
    1538           0 :                 p = strrchr_m(lname, '/');
    1539           0 :                 if (p) {
    1540           0 :                         rname = talloc_asprintf(ctx, "%s-%d", p + 1,
    1541           0 :                                                 (int)getpid());
    1542             :                 } else {
    1543           0 :                         rname = talloc_strdup(ctx, lname);
    1544             :                 }
    1545             :         }
    1546             : 
    1547           0 :         if (rname == NULL) {
    1548           0 :                 d_printf("Out of memory in cmd_print (stdin)\n");
    1549           0 :                 return 1;
    1550             :         }
    1551             : 
    1552           0 :         return do_put(ctx, rname, lname, false);
    1553             : }
    1554             : 
    1555             : 
    1556           0 : static int cmd_rewrite(struct smbclient_context *ctx, const char **args)
    1557             : {
    1558           0 :         d_printf("REWRITE: command not implemented (FIXME!)\n");
    1559             :         
    1560           0 :         return 0;
    1561             : }
    1562             : 
    1563             : /****************************************************************************
    1564             : delete some files
    1565             : ****************************************************************************/
    1566           6 : static int cmd_del(struct smbclient_context *ctx, const char **args)
    1567             : {
    1568             :         char *mask;
    1569             :         
    1570           6 :         if (!args[1]) {
    1571           0 :                 d_printf("del <filename>\n");
    1572           0 :                 return 1;
    1573             :         }
    1574           6 :         mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
    1575             : 
    1576           6 :         if (NT_STATUS_IS_ERR(smbcli_unlink(ctx->cli->tree, mask))) {
    1577           0 :                 d_printf("%s deleting remote file %s\n",smbcli_errstr(ctx->cli->tree),mask);
    1578             :         }
    1579             :         
    1580           6 :         return 0;
    1581             : }
    1582             : 
    1583             : 
    1584             : /****************************************************************************
    1585             : delete a whole directory tree
    1586             : ****************************************************************************/
    1587           2 : static int cmd_deltree(struct smbclient_context *ctx, const char **args)
    1588             : {
    1589             :         char *dname;
    1590             :         int ret;
    1591             : 
    1592           2 :         if (!args[1]) {
    1593           0 :                 d_printf("deltree <dirname>\n");
    1594           0 :                 return 1;
    1595             :         }
    1596             : 
    1597           2 :         dname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
    1598             :         
    1599           2 :         ret = smbcli_deltree(ctx->cli->tree, dname);
    1600             : 
    1601           2 :         if (ret == -1) {
    1602           0 :                 printf("Failed to delete tree %s - %s\n", dname, smbcli_errstr(ctx->cli->tree));
    1603           0 :                 return -1;
    1604             :         }
    1605             : 
    1606           2 :         printf("Deleted %d files in %s\n", ret, dname);
    1607             :         
    1608           2 :         return 0;
    1609             : }
    1610             : 
    1611             : typedef struct {
    1612             :         const char  *level_name;
    1613             :         enum smb_fsinfo_level level;
    1614             : } fsinfo_level_t;
    1615             : 
    1616             : fsinfo_level_t fsinfo_levels[] = {
    1617             :         {"dskattr", RAW_QFS_DSKATTR},
    1618             :         {"allocation", RAW_QFS_ALLOCATION},
    1619             :         {"volume", RAW_QFS_VOLUME},
    1620             :         {"volumeinfo", RAW_QFS_VOLUME_INFO},
    1621             :         {"sizeinfo", RAW_QFS_SIZE_INFO},
    1622             :         {"deviceinfo", RAW_QFS_DEVICE_INFO},
    1623             :         {"attributeinfo", RAW_QFS_ATTRIBUTE_INFO},
    1624             :         {"unixinfo", RAW_QFS_UNIX_INFO},
    1625             :         {"volume-information", RAW_QFS_VOLUME_INFORMATION},
    1626             :         {"size-information", RAW_QFS_SIZE_INFORMATION},
    1627             :         {"device-information", RAW_QFS_DEVICE_INFORMATION},
    1628             :         {"attribute-information", RAW_QFS_ATTRIBUTE_INFORMATION},
    1629             :         {"quota-information", RAW_QFS_QUOTA_INFORMATION},
    1630             :         {"fullsize-information", RAW_QFS_FULL_SIZE_INFORMATION},
    1631             :         {"objectid", RAW_QFS_OBJECTID_INFORMATION},
    1632             :         {"sector-size-info", RAW_QFS_SECTOR_SIZE_INFORMATION},
    1633             :         {NULL, RAW_QFS_GENERIC}
    1634             : };
    1635             : 
    1636             : 
    1637          26 : static int cmd_fsinfo(struct smbclient_context *ctx, const char **args)
    1638             : {
    1639             :         union smb_fsinfo fsinfo;
    1640             :         NTSTATUS status;
    1641             :         fsinfo_level_t *fsinfo_level;
    1642             :         
    1643          26 :         if (!args[1]) {
    1644           0 :                 d_printf("fsinfo <level>, where level is one of following:\n");
    1645           0 :                 fsinfo_level = fsinfo_levels;
    1646           0 :                 while(fsinfo_level->level_name) {
    1647           0 :                         d_printf("%s\n", fsinfo_level->level_name);
    1648           0 :                         fsinfo_level++;
    1649             :                 }
    1650           0 :                 return 1;
    1651             :         }
    1652             :         
    1653          26 :         fsinfo_level = fsinfo_levels;
    1654         222 :         while(fsinfo_level->level_name && !strequal(args[1],fsinfo_level->level_name)) {
    1655         196 :                 fsinfo_level++;
    1656             :         }
    1657             :   
    1658          26 :         if (!fsinfo_level->level_name) {
    1659           0 :                 d_printf("wrong level name!\n");
    1660           0 :                 return 1;
    1661             :         }
    1662             :   
    1663          26 :         fsinfo.generic.level = fsinfo_level->level;
    1664          26 :         status = smb_raw_fsinfo(ctx->cli->tree, ctx, &fsinfo);
    1665          26 :         if (!NT_STATUS_IS_OK(status)) {
    1666           0 :                 d_printf("fsinfo-level-%s - %s\n", fsinfo_level->level_name, nt_errstr(status));
    1667           0 :                 return 1;
    1668             :         }
    1669             : 
    1670          26 :         d_printf("fsinfo-level-%s:\n", fsinfo_level->level_name);
    1671          26 :         switch(fsinfo.generic.level) {
    1672           0 :         case RAW_QFS_DSKATTR:
    1673           0 :                 d_printf("\tunits_total:                %hu\n", 
    1674           0 :                          (unsigned short) fsinfo.dskattr.out.units_total);
    1675           0 :                 d_printf("\tblocks_per_unit:            %hu\n", 
    1676           0 :                          (unsigned short) fsinfo.dskattr.out.blocks_per_unit);
    1677           0 :                 d_printf("\tblocks_size:                %hu\n", 
    1678           0 :                          (unsigned short) fsinfo.dskattr.out.block_size);
    1679           0 :                 d_printf("\tunits_free:                 %hu\n", 
    1680           0 :                          (unsigned short) fsinfo.dskattr.out.units_free);
    1681           0 :                 break;
    1682           2 :         case RAW_QFS_ALLOCATION:
    1683           2 :                 d_printf("\tfs_id:                      %lu\n", 
    1684           2 :                          (unsigned long) fsinfo.allocation.out.fs_id);
    1685           2 :                 d_printf("\tsectors_per_unit:           %lu\n", 
    1686           2 :                          (unsigned long) fsinfo.allocation.out.sectors_per_unit);
    1687           2 :                 d_printf("\ttotal_alloc_units:          %lu\n", 
    1688           2 :                          (unsigned long) fsinfo.allocation.out.total_alloc_units);
    1689           2 :                 d_printf("\tavail_alloc_units:          %lu\n", 
    1690           2 :                          (unsigned long) fsinfo.allocation.out.avail_alloc_units);
    1691           2 :                 d_printf("\tbytes_per_sector:           %hu\n", 
    1692           2 :                          (unsigned short) fsinfo.allocation.out.bytes_per_sector);
    1693           2 :                 break;
    1694           2 :         case RAW_QFS_VOLUME:
    1695           2 :                 d_printf("\tserial_number:              %lu\n", 
    1696           2 :                          (unsigned long) fsinfo.volume.out.serial_number);
    1697           2 :                 d_printf("\tvolume_name:                %s\n", fsinfo.volume.out.volume_name.s);
    1698           2 :                 break;
    1699           4 :         case RAW_QFS_VOLUME_INFO:
    1700             :         case RAW_QFS_VOLUME_INFORMATION:
    1701           4 :                 d_printf("\tcreate_time:                %s\n",
    1702             :                          nt_time_string(ctx,fsinfo.volume_info.out.create_time));
    1703           4 :                 d_printf("\tserial_number:              %lu\n", 
    1704           4 :                          (unsigned long) fsinfo.volume_info.out.serial_number);
    1705           4 :                 d_printf("\tvolume_name:                %s\n", fsinfo.volume_info.out.volume_name.s);
    1706           4 :                 break;
    1707           4 :         case RAW_QFS_SIZE_INFO:
    1708             :         case RAW_QFS_SIZE_INFORMATION:
    1709           4 :                 d_printf("\ttotal_alloc_units:          %llu\n", 
    1710           4 :                          (unsigned long long) fsinfo.size_info.out.total_alloc_units);
    1711           4 :                 d_printf("\tavail_alloc_units:          %llu\n", 
    1712           4 :                          (unsigned long long) fsinfo.size_info.out.avail_alloc_units);
    1713           4 :                 d_printf("\tsectors_per_unit:           %lu\n", 
    1714           4 :                          (unsigned long) fsinfo.size_info.out.sectors_per_unit);
    1715           4 :                 d_printf("\tbytes_per_sector:           %lu\n", 
    1716           4 :                          (unsigned long) fsinfo.size_info.out.bytes_per_sector);
    1717           4 :                 break;
    1718           4 :         case RAW_QFS_DEVICE_INFO:
    1719             :         case RAW_QFS_DEVICE_INFORMATION:
    1720           4 :                 d_printf("\tdevice_type:                %lu\n", 
    1721           4 :                          (unsigned long) fsinfo.device_info.out.device_type);
    1722           4 :                 d_printf("\tcharacteristics:            0x%lx\n", 
    1723           4 :                          (unsigned long) fsinfo.device_info.out.characteristics);
    1724           4 :                 break;
    1725           4 :         case RAW_QFS_ATTRIBUTE_INFORMATION:
    1726             :         case RAW_QFS_ATTRIBUTE_INFO:
    1727           4 :                 d_printf("\tfs_attr:                    0x%lx\n", 
    1728           4 :                          (unsigned long) fsinfo.attribute_info.out.fs_attr);
    1729           4 :                 d_printf("\tmax_file_component_length:  %lu\n", 
    1730           4 :                          (unsigned long) fsinfo.attribute_info.out.max_file_component_length);
    1731           4 :                 d_printf("\tfs_type:                    %s\n", fsinfo.attribute_info.out.fs_type.s);
    1732           4 :                 break;
    1733           0 :         case RAW_QFS_UNIX_INFO:
    1734           0 :                 d_printf("\tmajor_version:              %hu\n", 
    1735           0 :                          (unsigned short) fsinfo.unix_info.out.major_version);
    1736           0 :                 d_printf("\tminor_version:              %hu\n", 
    1737           0 :                          (unsigned short) fsinfo.unix_info.out.minor_version);
    1738           0 :                 d_printf("\tcapability:                 0x%llx\n", 
    1739           0 :                          (unsigned long long) fsinfo.unix_info.out.capability);
    1740           0 :                 break;
    1741           2 :         case RAW_QFS_QUOTA_INFORMATION:
    1742           2 :                 d_printf("\tunknown[3]:                 [%llu,%llu,%llu]\n", 
    1743           2 :                          (unsigned long long) fsinfo.quota_information.out.unknown[0],
    1744           2 :                          (unsigned long long) fsinfo.quota_information.out.unknown[1],
    1745           2 :                          (unsigned long long) fsinfo.quota_information.out.unknown[2]);
    1746           2 :                 d_printf("\tquota_soft:                 %llu\n", 
    1747           2 :                          (unsigned long long) fsinfo.quota_information.out.quota_soft);
    1748           2 :                 d_printf("\tquota_hard:                 %llu\n", 
    1749           2 :                          (unsigned long long) fsinfo.quota_information.out.quota_hard);
    1750           2 :                 d_printf("\tquota_flags:                0x%llx\n", 
    1751           2 :                          (unsigned long long) fsinfo.quota_information.out.quota_flags);
    1752           2 :                 break;
    1753           2 :         case RAW_QFS_FULL_SIZE_INFORMATION:
    1754           2 :                 d_printf("\ttotal_alloc_units:          %llu\n", 
    1755           2 :                          (unsigned long long) fsinfo.full_size_information.out.total_alloc_units);
    1756           2 :                 d_printf("\tcall_avail_alloc_units:     %llu\n", 
    1757           2 :                          (unsigned long long) fsinfo.full_size_information.out.call_avail_alloc_units);
    1758           2 :                 d_printf("\tactual_avail_alloc_units:   %llu\n", 
    1759           2 :                          (unsigned long long) fsinfo.full_size_information.out.actual_avail_alloc_units);
    1760           2 :                 d_printf("\tsectors_per_unit:           %lu\n", 
    1761           2 :                          (unsigned long) fsinfo.full_size_information.out.sectors_per_unit);
    1762           2 :                 d_printf("\tbytes_per_sector:           %lu\n", 
    1763           2 :                          (unsigned long) fsinfo.full_size_information.out.bytes_per_sector);
    1764           2 :                 break;
    1765           2 :         case RAW_QFS_OBJECTID_INFORMATION:
    1766           2 :                 d_printf("\tGUID:                       %s\n", 
    1767             :                          GUID_string(ctx,&fsinfo.objectid_information.out.guid));
    1768           2 :                 d_printf("\tunknown[6]:                 [%llu,%llu,%llu,%llu,%llu,%llu]\n", 
    1769           2 :                          (unsigned long long) fsinfo.objectid_information.out.unknown[0],
    1770           2 :                          (unsigned long long) fsinfo.objectid_information.out.unknown[1],
    1771           2 :                          (unsigned long long) fsinfo.objectid_information.out.unknown[2],
    1772           2 :                          (unsigned long long) fsinfo.objectid_information.out.unknown[3],
    1773           2 :                          (unsigned long long) fsinfo.objectid_information.out.unknown[4],
    1774           2 :                          (unsigned long long) fsinfo.objectid_information.out.unknown[5] );
    1775           2 :                 break;
    1776           0 :         case RAW_QFS_SECTOR_SIZE_INFORMATION:
    1777           0 :                 d_printf("\tlogical_bytes_per_sector:                      %u\n",
    1778           0 :                          (unsigned)fsinfo.sector_size_info.out.logical_bytes_per_sector);
    1779           0 :                 d_printf("\tphys_bytes_per_sector_atomic:          %u\n",
    1780           0 :                          (unsigned)fsinfo.sector_size_info.out.phys_bytes_per_sector_atomic);
    1781           0 :                 d_printf("\tphys_bytes_per_sector_perf:                    %u\n",
    1782           0 :                          (unsigned)fsinfo.sector_size_info.out.phys_bytes_per_sector_perf);
    1783           0 :                 d_printf("\tfs_effective_phys_bytes_per_sector_atomic:     %u\n",
    1784           0 :                          (unsigned)fsinfo.sector_size_info.out.fs_effective_phys_bytes_per_sector_atomic);
    1785           0 :                 d_printf("\tflags:                                 0x%x\n",
    1786           0 :                          (unsigned)fsinfo.sector_size_info.out.flags);
    1787           0 :                 d_printf("\tbyte_off_sector_align:                 %u\n",
    1788           0 :                          (unsigned)fsinfo.sector_size_info.out.byte_off_sector_align);
    1789           0 :                 d_printf("\tbyte_off_partition_align:                      %u\n",
    1790           0 :                          (unsigned)fsinfo.sector_size_info.out.byte_off_partition_align);
    1791           0 :                 break;
    1792           0 :         case RAW_QFS_GENERIC:
    1793           0 :                 d_printf("\twrong level returned\n");
    1794           0 :                 break;
    1795             :         }
    1796             :   
    1797          26 :         return 0;
    1798             : }
    1799             : 
    1800             : /****************************************************************************
    1801             : show as much information as possible about a file
    1802             : ****************************************************************************/
    1803           2 : static int cmd_allinfo(struct smbclient_context *ctx, const char **args)
    1804             : {
    1805             :         char *fname;
    1806             :         union smb_fileinfo finfo;
    1807             :         NTSTATUS status;
    1808             :         int fnum;
    1809             : 
    1810           2 :         if (!args[1]) {
    1811           0 :                 d_printf("allinfo <filename>\n");
    1812           0 :                 return 1;
    1813             :         }
    1814           2 :         fname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
    1815             : 
    1816             :         /* first a ALL_INFO QPATHINFO */
    1817           2 :         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
    1818           2 :         finfo.generic.in.file.path = fname;
    1819           2 :         status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
    1820           2 :         if (!NT_STATUS_IS_OK(status)) {
    1821           0 :                 d_printf("%s - %s\n", fname, nt_errstr(status));
    1822           0 :                 return 1;
    1823             :         }
    1824             : 
    1825           2 :         d_printf("\tcreate_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.create_time));
    1826           2 :         d_printf("\taccess_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.access_time));
    1827           2 :         d_printf("\twrite_time:     %s\n", nt_time_string(ctx, finfo.all_info.out.write_time));
    1828           2 :         d_printf("\tchange_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.change_time));
    1829           2 :         d_printf("\tattrib:         0x%x\n", finfo.all_info.out.attrib);
    1830           2 :         d_printf("\talloc_size:     %lu\n", (unsigned long)finfo.all_info.out.alloc_size);
    1831           2 :         d_printf("\tsize:           %lu\n", (unsigned long)finfo.all_info.out.size);
    1832           2 :         d_printf("\tnlink:          %u\n", finfo.all_info.out.nlink);
    1833           2 :         d_printf("\tdelete_pending: %u\n", finfo.all_info.out.delete_pending);
    1834           2 :         d_printf("\tdirectory:      %u\n", finfo.all_info.out.directory);
    1835           2 :         d_printf("\tea_size:        %u\n", finfo.all_info.out.ea_size);
    1836           2 :         d_printf("\tfname:          '%s'\n", finfo.all_info.out.fname.s);
    1837             : 
    1838             :         /* 8.3 name if any */
    1839           2 :         finfo.generic.level = RAW_FILEINFO_ALT_NAME_INFO;
    1840           2 :         status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
    1841           2 :         if (NT_STATUS_IS_OK(status)) {
    1842           2 :                 d_printf("\talt_name:       %s\n", finfo.alt_name_info.out.fname.s);
    1843             :         }
    1844             : 
    1845             :         /* file_id if available */
    1846           2 :         finfo.generic.level = RAW_FILEINFO_INTERNAL_INFORMATION;
    1847           2 :         status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
    1848           2 :         if (NT_STATUS_IS_OK(status)) {
    1849           2 :                 d_printf("\tfile_id         %.0f\n", 
    1850           2 :                          (double)finfo.internal_information.out.file_id);
    1851             :         }
    1852             : 
    1853             :         /* the EAs, if any */
    1854           2 :         finfo.generic.level = RAW_FILEINFO_ALL_EAS;
    1855           2 :         status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
    1856           2 :         if (NT_STATUS_IS_OK(status)) {
    1857             :                 int i;
    1858           2 :                 for (i=0;i<finfo.all_eas.out.num_eas;i++) {
    1859           0 :                         d_printf("\tEA[%d] flags=%d len=%d '%s'\n", i,
    1860           0 :                                  finfo.all_eas.out.eas[i].flags,
    1861           0 :                                  (int)finfo.all_eas.out.eas[i].value.length,
    1862           0 :                                  finfo.all_eas.out.eas[i].name.s);
    1863             :                 }
    1864             :         }
    1865             : 
    1866             :         /* streams, if available */
    1867           2 :         finfo.generic.level = RAW_FILEINFO_STREAM_INFO;
    1868           2 :         status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
    1869           2 :         if (NT_STATUS_IS_OK(status)) {
    1870             :                 int i;
    1871           4 :                 for (i=0;i<finfo.stream_info.out.num_streams;i++) {
    1872           2 :                         d_printf("\tstream %d:\n", i);
    1873           2 :                         d_printf("\t\tsize       %ld\n", 
    1874           2 :                                  (long)finfo.stream_info.out.streams[i].size);
    1875           2 :                         d_printf("\t\talloc size %ld\n", 
    1876           2 :                                  (long)finfo.stream_info.out.streams[i].alloc_size);
    1877           2 :                         d_printf("\t\tname       %s\n", finfo.stream_info.out.streams[i].stream_name.s);
    1878             :                 }
    1879             :         }       
    1880             : 
    1881             :         /* dev/inode if available */
    1882           2 :         finfo.generic.level = RAW_FILEINFO_COMPRESSION_INFORMATION;
    1883           2 :         status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
    1884           2 :         if (NT_STATUS_IS_OK(status)) {
    1885           2 :                 d_printf("\tcompressed size %ld\n", (long)finfo.compression_info.out.compressed_size);
    1886           2 :                 d_printf("\tformat          %ld\n", (long)finfo.compression_info.out.format);
    1887           2 :                 d_printf("\tunit_shift      %ld\n", (long)finfo.compression_info.out.unit_shift);
    1888           2 :                 d_printf("\tchunk_shift     %ld\n", (long)finfo.compression_info.out.chunk_shift);
    1889           2 :                 d_printf("\tcluster_shift   %ld\n", (long)finfo.compression_info.out.cluster_shift);
    1890             :         }
    1891             : 
    1892             :         /* shadow copies if available */
    1893           2 :         fnum = smbcli_open(ctx->cli->tree, fname, O_RDONLY, DENY_NONE);
    1894           2 :         if (fnum != -1) {
    1895             :                 struct smb_shadow_copy info;
    1896             :                 int i;
    1897           2 :                 info.in.file.fnum = fnum;
    1898           2 :                 info.in.max_data = ~0;
    1899           2 :                 status = smb_raw_shadow_data(ctx->cli->tree, ctx, &info);
    1900           2 :                 if (NT_STATUS_IS_OK(status)) {
    1901           0 :                         d_printf("\tshadow_copy: %u volumes  %u names\n",
    1902             :                                  info.out.num_volumes, info.out.num_names);
    1903           0 :                         for (i=0;i<info.out.num_names;i++) {
    1904           0 :                                 d_printf("\t%s\n", info.out.names[i]);
    1905           0 :                                 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
    1906           0 :                                 finfo.generic.in.file.path = talloc_asprintf(ctx, "%s%s", 
    1907           0 :                                                                              info.out.names[i], fname); 
    1908           0 :                                 status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
    1909           0 :                                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
    1910           0 :                                     NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    1911           0 :                                         continue;
    1912             :                                 }
    1913           0 :                                 if (!NT_STATUS_IS_OK(status)) {
    1914           0 :                                         d_printf("%s - %s\n", finfo.generic.in.file.path, 
    1915             :                                                  nt_errstr(status));
    1916           0 :                                         return 1;
    1917             :                                 }
    1918             :                                 
    1919           0 :                                 d_printf("\t\tcreate_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.create_time));
    1920           0 :                                 d_printf("\t\twrite_time:     %s\n", nt_time_string(ctx, finfo.all_info.out.write_time));
    1921           0 :                                 d_printf("\t\tchange_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.change_time));
    1922           0 :                                 d_printf("\t\tsize:           %lu\n", (unsigned long)finfo.all_info.out.size);
    1923             :                         }
    1924             :                 }
    1925             :         }
    1926             :         
    1927           2 :         return 0;
    1928             : }
    1929             : 
    1930             : 
    1931             : /****************************************************************************
    1932             : shows EA contents
    1933             : ****************************************************************************/
    1934           2 : static int cmd_eainfo(struct smbclient_context *ctx, const char **args)
    1935             : {
    1936             :         char *fname;
    1937             :         union smb_fileinfo finfo;
    1938             :         NTSTATUS status;
    1939             :         int i;
    1940             : 
    1941           2 :         if (!args[1]) {
    1942           0 :                 d_printf("eainfo <filename>\n");
    1943           0 :                 return 1;
    1944             :         }
    1945           2 :         fname = talloc_strdup(ctx, args[1]);
    1946             : 
    1947           2 :         finfo.generic.level = RAW_FILEINFO_ALL_EAS;
    1948           2 :         finfo.generic.in.file.path = fname;
    1949           2 :         status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
    1950             :         
    1951           2 :         if (!NT_STATUS_IS_OK(status)) {
    1952           0 :                 d_printf("RAW_FILEINFO_ALL_EAS - %s\n", nt_errstr(status));
    1953           0 :                 return 1;
    1954             :         }
    1955             : 
    1956           2 :         d_printf("%s has %d EAs\n", fname, finfo.all_eas.out.num_eas);
    1957             : 
    1958           2 :         for (i=0;i<finfo.all_eas.out.num_eas;i++) {
    1959           0 :                 d_printf("\tEA[%d] flags=%d len=%d '%s'\n", i,
    1960           0 :                          finfo.all_eas.out.eas[i].flags,
    1961           0 :                          (int)finfo.all_eas.out.eas[i].value.length,
    1962           0 :                          finfo.all_eas.out.eas[i].name.s);
    1963           0 :                 fflush(stdout);
    1964           0 :                 dump_data(0, 
    1965           0 :                           finfo.all_eas.out.eas[i].value.data,
    1966           0 :                           finfo.all_eas.out.eas[i].value.length);
    1967             :         }
    1968             : 
    1969           2 :         return 0;
    1970             : }
    1971             : 
    1972             : 
    1973             : /****************************************************************************
    1974             : show any ACL on a file
    1975             : ****************************************************************************/
    1976           0 : static int cmd_acl(struct smbclient_context *ctx, const char **args)
    1977             : {
    1978             :         char *fname;
    1979             :         union smb_fileinfo query;
    1980             :         NTSTATUS status;
    1981             :         int fnum;
    1982             : 
    1983           0 :         if (!args[1]) {
    1984           0 :                 d_printf("acl <filename>\n");
    1985           0 :                 return 1;
    1986             :         }
    1987           0 :         fname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
    1988             : 
    1989           0 :         fnum = smbcli_nt_create_full(ctx->cli->tree, fname, 0, 
    1990             :                                      SEC_STD_READ_CONTROL,
    1991             :                                      0,
    1992             :                                      NTCREATEX_SHARE_ACCESS_DELETE|
    1993             :                                      NTCREATEX_SHARE_ACCESS_READ|
    1994             :                                      NTCREATEX_SHARE_ACCESS_WRITE, 
    1995             :                                      NTCREATEX_DISP_OPEN,
    1996             :                                      0, 0);
    1997           0 :         if (fnum == -1) {
    1998           0 :                 d_printf("%s - %s\n", fname, smbcli_errstr(ctx->cli->tree));
    1999           0 :                 return -1;
    2000             :         }
    2001             : 
    2002           0 :         query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    2003           0 :         query.query_secdesc.in.file.fnum = fnum;
    2004           0 :         query.query_secdesc.in.secinfo_flags = 0x7;
    2005             : 
    2006           0 :         status = smb_raw_fileinfo(ctx->cli->tree, ctx, &query);
    2007           0 :         if (!NT_STATUS_IS_OK(status)) {
    2008           0 :                 d_printf("%s - %s\n", fname, nt_errstr(status));
    2009           0 :                 return 1;
    2010             :         }
    2011             : 
    2012           0 :         NDR_PRINT_DEBUG(security_descriptor, query.query_secdesc.out.sd);
    2013             : 
    2014           0 :         return 0;
    2015             : }
    2016             : 
    2017             : /****************************************************************************
    2018             : lookup a name or sid
    2019             : ****************************************************************************/
    2020           2 : static int cmd_lookup(struct smbclient_context *ctx, const char **args)
    2021             : {
    2022             :         NTSTATUS status;
    2023             :         struct dom_sid *sid;
    2024             : 
    2025           2 :         if (!args[1]) {
    2026           0 :                 d_printf("lookup <sid|name>\n");
    2027           0 :                 return 1;
    2028             :         }
    2029             : 
    2030           2 :         sid = dom_sid_parse_talloc(ctx, args[1]);
    2031           2 :         if (sid == NULL) {
    2032             :                 const char *sidstr;
    2033           2 :                 status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sidstr);
    2034           2 :                 if (!NT_STATUS_IS_OK(status)) {
    2035           0 :                         d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
    2036           0 :                         return 1;
    2037             :                 }
    2038             : 
    2039           2 :                 d_printf("%s\n", sidstr);
    2040             :         } else {
    2041             :                 const char *name;
    2042           0 :                 status = smblsa_lookup_sid(ctx->cli, args[1], ctx, &name);
    2043           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2044           0 :                         d_printf("lsa_LookupSids - %s\n", nt_errstr(status));
    2045           0 :                         return 1;
    2046             :                 }
    2047             : 
    2048           0 :                 d_printf("%s\n", name);
    2049             :         }
    2050             : 
    2051           2 :         return 0;
    2052             : }
    2053             : 
    2054             : /****************************************************************************
    2055             : show privileges for a user
    2056             : ****************************************************************************/
    2057           0 : static int cmd_privileges(struct smbclient_context *ctx, const char **args)
    2058             : {
    2059             :         NTSTATUS status;
    2060             :         struct dom_sid *sid;
    2061             :         struct lsa_RightSet rights;
    2062             :         unsigned i;
    2063             : 
    2064           0 :         if (!args[1]) {
    2065           0 :                 d_printf("privileges <sid|name>\n");
    2066           0 :                 return 1;
    2067             :         }
    2068             : 
    2069           0 :         sid = dom_sid_parse_talloc(ctx, args[1]);
    2070           0 :         if (sid == NULL) {
    2071             :                 const char *sid_str;
    2072           0 :                 status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str);
    2073           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2074           0 :                         d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
    2075           0 :                         return 1;
    2076             :                 }
    2077           0 :                 sid = dom_sid_parse_talloc(ctx, sid_str);
    2078             :         }
    2079             : 
    2080           0 :         status = smblsa_sid_privileges(ctx->cli, sid, ctx, &rights);
    2081           0 :         if (!NT_STATUS_IS_OK(status)) {
    2082           0 :                 d_printf("lsa_EnumAccountRights - %s\n", nt_errstr(status));
    2083           0 :                 return 1;
    2084             :         }
    2085             : 
    2086           0 :         for (i=0;i<rights.count;i++) {
    2087           0 :                 d_printf("\t%s\n", rights.names[i].string);
    2088             :         }
    2089             : 
    2090           0 :         return 0;
    2091             : }
    2092             : 
    2093             : 
    2094             : /****************************************************************************
    2095             : add privileges for a user
    2096             : ****************************************************************************/
    2097           0 : static int cmd_addprivileges(struct smbclient_context *ctx, const char **args)
    2098             : {
    2099             :         NTSTATUS status;
    2100             :         struct dom_sid *sid;
    2101             :         struct lsa_RightSet rights;
    2102             :         int i;
    2103             : 
    2104           0 :         if (!args[1]) {
    2105           0 :                 d_printf("addprivileges <sid|name> <privilege...>\n");
    2106           0 :                 return 1;
    2107             :         }
    2108             : 
    2109           0 :         sid = dom_sid_parse_talloc(ctx, args[1]);
    2110           0 :         if (sid == NULL) {
    2111             :                 const char *sid_str;
    2112           0 :                 status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str);
    2113           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2114           0 :                         d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
    2115           0 :                         return 1;
    2116             :                 }
    2117           0 :                 sid = dom_sid_parse_talloc(ctx, sid_str);
    2118             :         }
    2119             : 
    2120           0 :         ZERO_STRUCT(rights);
    2121           0 :         for (i = 2; args[i]; i++) {
    2122           0 :                 rights.names = talloc_realloc(ctx, rights.names, 
    2123             :                                               struct lsa_StringLarge, rights.count+1);
    2124           0 :                 rights.names[rights.count].string = talloc_strdup(ctx, args[i]);
    2125           0 :                 rights.count++;
    2126             :         }
    2127             : 
    2128             : 
    2129           0 :         status = smblsa_sid_add_privileges(ctx->cli, sid, ctx, &rights);
    2130           0 :         if (!NT_STATUS_IS_OK(status)) {
    2131           0 :                 d_printf("lsa_AddAccountRights - %s\n", nt_errstr(status));
    2132           0 :                 return 1;
    2133             :         }
    2134             : 
    2135           0 :         return 0;
    2136             : }
    2137             : 
    2138             : /****************************************************************************
    2139             : delete privileges for a user
    2140             : ****************************************************************************/
    2141           0 : static int cmd_delprivileges(struct smbclient_context *ctx, const char **args)
    2142             : {
    2143             :         NTSTATUS status;
    2144             :         struct dom_sid *sid;
    2145             :         struct lsa_RightSet rights;
    2146             :         int i;
    2147             : 
    2148           0 :         if (!args[1]) {
    2149           0 :                 d_printf("delprivileges <sid|name> <privilege...>\n");
    2150           0 :                 return 1;
    2151             :         }
    2152             : 
    2153           0 :         sid = dom_sid_parse_talloc(ctx, args[1]);
    2154           0 :         if (sid == NULL) {
    2155             :                 const char *sid_str;
    2156           0 :                 status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str);
    2157           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2158           0 :                         d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
    2159           0 :                         return 1;
    2160             :                 }
    2161           0 :                 sid = dom_sid_parse_talloc(ctx, sid_str);
    2162             :         }
    2163             : 
    2164           0 :         ZERO_STRUCT(rights);
    2165           0 :         for (i = 2; args[i]; i++) {
    2166           0 :                 rights.names = talloc_realloc(ctx, rights.names, 
    2167             :                                               struct lsa_StringLarge, rights.count+1);
    2168           0 :                 rights.names[rights.count].string = talloc_strdup(ctx, args[i]);
    2169           0 :                 rights.count++;
    2170             :         }
    2171             : 
    2172             : 
    2173           0 :         status = smblsa_sid_del_privileges(ctx->cli, sid, ctx, &rights);
    2174           0 :         if (!NT_STATUS_IS_OK(status)) {
    2175           0 :                 d_printf("lsa_RemoveAccountRights - %s\n", nt_errstr(status));
    2176           0 :                 return 1;
    2177             :         }
    2178             : 
    2179           0 :         return 0;
    2180             : }
    2181             : 
    2182             : 
    2183             : /****************************************************************************
    2184             : open a file
    2185             : ****************************************************************************/
    2186           0 : static int cmd_open(struct smbclient_context *ctx, const char **args)
    2187             : {
    2188             :         char *filename;
    2189             :         union smb_open io;
    2190             :         NTSTATUS status;
    2191             :         TALLOC_CTX *tmp_ctx;
    2192             : 
    2193           0 :         if (!args[1]) {
    2194           0 :                 d_printf("open <filename>\n");
    2195           0 :                 return 1;
    2196             :         }
    2197           0 :         tmp_ctx = talloc_new(ctx);
    2198             : 
    2199           0 :         filename = talloc_asprintf(tmp_ctx, "%s%s", ctx->remote_cur_dir, args[1]);
    2200             : 
    2201           0 :         io.generic.level = RAW_OPEN_NTCREATEX;
    2202           0 :         io.ntcreatex.in.root_fid.fnum = 0;
    2203           0 :         io.ntcreatex.in.flags = 0;
    2204           0 :         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
    2205           0 :         io.ntcreatex.in.create_options = 0;
    2206           0 :         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
    2207           0 :         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
    2208           0 :         io.ntcreatex.in.alloc_size = 0;
    2209           0 :         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
    2210           0 :         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
    2211           0 :         io.ntcreatex.in.security_flags = 0;
    2212           0 :         io.ntcreatex.in.fname = filename;
    2213             : 
    2214           0 :         status = smb_raw_open(ctx->cli->tree, tmp_ctx, &io);
    2215           0 :         talloc_free(tmp_ctx);
    2216             : 
    2217           0 :         if (NT_STATUS_IS_OK(status)) {
    2218           0 :                 d_printf("Opened file with fnum %u\n", (unsigned)io.ntcreatex.out.file.fnum);
    2219             :         } else {
    2220           0 :                 d_printf("Opened failed: %s\n", nt_errstr(status));
    2221             :         }
    2222             : 
    2223           0 :         return 0;
    2224             : }
    2225             : 
    2226             : /****************************************************************************
    2227             : close a file
    2228             : ****************************************************************************/
    2229           0 : static int cmd_close(struct smbclient_context *ctx, const char **args)
    2230             : {
    2231             :         union smb_close io;
    2232             :         NTSTATUS status;
    2233             :         uint16_t fnum;
    2234             : 
    2235           0 :         if (!args[1]) {
    2236           0 :                 d_printf("close <fnum>\n");
    2237           0 :                 return 1;
    2238             :         }
    2239             : 
    2240           0 :         fnum = atoi(args[1]);
    2241             : 
    2242           0 :         ZERO_STRUCT(io);
    2243           0 :         io.generic.level = RAW_CLOSE_CLOSE;
    2244           0 :         io.close.in.file.fnum = fnum;
    2245             : 
    2246           0 :         status = smb_raw_close(ctx->cli->tree, &io);
    2247             : 
    2248           0 :         if (NT_STATUS_IS_OK(status)) {
    2249           0 :                 d_printf("Closed file OK\n");
    2250             :         } else {
    2251           0 :                 d_printf("Close failed: %s\n", nt_errstr(status));
    2252             :         }
    2253             : 
    2254           0 :         return 0;
    2255             : }
    2256             : 
    2257             : 
    2258             : /****************************************************************************
    2259             : remove a directory
    2260             : ****************************************************************************/
    2261           6 : static int cmd_rmdir(struct smbclient_context *ctx, const char **args)
    2262             : {
    2263             :         char *mask;
    2264             :   
    2265           6 :         if (!args[1]) {
    2266           0 :                 d_printf("rmdir <dirname>\n");
    2267           0 :                 return 1;
    2268             :         }
    2269           6 :         mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
    2270             : 
    2271           6 :         if (NT_STATUS_IS_ERR(smbcli_rmdir(ctx->cli->tree, mask))) {
    2272           4 :                 d_printf("%s removing remote directory file %s\n",
    2273           4 :                          smbcli_errstr(ctx->cli->tree),mask);
    2274             :         }
    2275             :         
    2276           6 :         return 0;
    2277             : }
    2278             : 
    2279             : /****************************************************************************
    2280             :  UNIX hardlink.
    2281             : ****************************************************************************/
    2282           0 : static int cmd_link(struct smbclient_context *ctx, const char **args)
    2283             : {
    2284             :         char *src,*dest;
    2285             :   
    2286           0 :         if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
    2287           0 :                 d_printf("Server doesn't support UNIX CIFS calls.\n");
    2288           0 :                 return 1;
    2289             :         }
    2290             : 
    2291             :         
    2292           0 :         if (!args[1] || !args[2]) {
    2293           0 :                 d_printf("link <src> <dest>\n");
    2294           0 :                 return 1;
    2295             :         }
    2296             : 
    2297           0 :         src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
    2298           0 :         dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
    2299             : 
    2300           0 :         if (NT_STATUS_IS_ERR(smbcli_unix_hardlink(ctx->cli->tree, src, dest))) {
    2301           0 :                 d_printf("%s linking files (%s -> %s)\n", smbcli_errstr(ctx->cli->tree), src, dest);
    2302           0 :                 return 1;
    2303             :         }  
    2304             : 
    2305           0 :         return 0;
    2306             : }
    2307             : 
    2308             : /****************************************************************************
    2309             :  UNIX symlink.
    2310             : ****************************************************************************/
    2311             : 
    2312           0 : static int cmd_symlink(struct smbclient_context *ctx, const char **args)
    2313             : {
    2314             :         char *src,*dest;
    2315             :   
    2316           0 :         if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
    2317           0 :                 d_printf("Server doesn't support UNIX CIFS calls.\n");
    2318           0 :                 return 1;
    2319             :         }
    2320             : 
    2321           0 :         if (!args[1] || !args[2]) {
    2322           0 :                 d_printf("symlink <src> <dest>\n");
    2323           0 :                 return 1;
    2324             :         }
    2325             : 
    2326           0 :         src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
    2327           0 :         dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
    2328             : 
    2329           0 :         if (NT_STATUS_IS_ERR(smbcli_unix_symlink(ctx->cli->tree, src, dest))) {
    2330           0 :                 d_printf("%s symlinking files (%s -> %s)\n",
    2331           0 :                         smbcli_errstr(ctx->cli->tree), src, dest);
    2332           0 :                 return 1;
    2333             :         } 
    2334             : 
    2335           0 :         return 0;
    2336             : }
    2337             : 
    2338             : /****************************************************************************
    2339             :  UNIX chmod.
    2340             : ****************************************************************************/
    2341             : 
    2342           0 : static int cmd_chmod(struct smbclient_context *ctx, const char **args)
    2343             : {
    2344             :         char *src;
    2345             :         mode_t mode;
    2346             :   
    2347           0 :         if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
    2348           0 :                 d_printf("Server doesn't support UNIX CIFS calls.\n");
    2349           0 :                 return 1;
    2350             :         }
    2351             : 
    2352           0 :         if (!args[1] || !args[2]) {
    2353           0 :                 d_printf("chmod mode file\n");
    2354           0 :                 return 1;
    2355             :         }
    2356             : 
    2357           0 :         src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
    2358             :         
    2359           0 :         mode = (mode_t)strtol(args[1], NULL, 8);
    2360             : 
    2361           0 :         if (NT_STATUS_IS_ERR(smbcli_unix_chmod(ctx->cli->tree, src, mode))) {
    2362           0 :                 d_printf("%s chmod file %s 0%o\n",
    2363           0 :                         smbcli_errstr(ctx->cli->tree), src, (unsigned)mode);
    2364           0 :                 return 1;
    2365             :         } 
    2366             : 
    2367           0 :         return 0;
    2368             : }
    2369             : 
    2370             : /****************************************************************************
    2371             :  UNIX chown.
    2372             : ****************************************************************************/
    2373             : 
    2374           0 : static int cmd_chown(struct smbclient_context *ctx, const char **args)
    2375             : {
    2376             :         char *src;
    2377             :         uid_t uid;
    2378             :         gid_t gid;
    2379             :   
    2380           0 :         if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
    2381           0 :                 d_printf("Server doesn't support UNIX CIFS calls.\n");
    2382           0 :                 return 1;
    2383             :         }
    2384             : 
    2385           0 :         if (!args[1] || !args[2] || !args[3]) {
    2386           0 :                 d_printf("chown uid gid file\n");
    2387           0 :                 return 1;
    2388             :         }
    2389             : 
    2390           0 :         uid = (uid_t)atoi(args[1]);
    2391           0 :         gid = (gid_t)atoi(args[2]);
    2392           0 :         src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[3]);
    2393             : 
    2394           0 :         if (NT_STATUS_IS_ERR(smbcli_unix_chown(ctx->cli->tree, src, uid, gid))) {
    2395           0 :                 d_printf("%s chown file %s uid=%d, gid=%d\n",
    2396           0 :                         smbcli_errstr(ctx->cli->tree), src, (int)uid, (int)gid);
    2397           0 :                 return 1;
    2398             :         } 
    2399             : 
    2400           0 :         return 0;
    2401             : }
    2402             : 
    2403             : /****************************************************************************
    2404             : rename some files
    2405             : ****************************************************************************/
    2406           2 : static int cmd_rename(struct smbclient_context *ctx, const char **args)
    2407             : {
    2408             :         char *src,*dest;
    2409             :   
    2410           2 :         if (!args[1] || !args[2]) {
    2411           0 :                 d_printf("rename <src> <dest>\n");
    2412           0 :                 return 1;
    2413             :         }
    2414             : 
    2415           2 :         src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
    2416           2 :         dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
    2417             : 
    2418           2 :         if (NT_STATUS_IS_ERR(smbcli_rename(ctx->cli->tree, src, dest))) {
    2419           0 :                 d_printf("%s renaming files\n",smbcli_errstr(ctx->cli->tree));
    2420           0 :                 return 1;
    2421             :         }
    2422             :         
    2423           2 :         return 0;
    2424             : }
    2425             : 
    2426             : 
    2427             : /****************************************************************************
    2428             : toggle the prompt flag
    2429             : ****************************************************************************/
    2430           0 : static int cmd_prompt(struct smbclient_context *ctx, const char **args)
    2431             : {
    2432           0 :         ctx->prompt = !ctx->prompt;
    2433           0 :         DEBUG(2,("prompting is now %s\n",ctx->prompt?"on":"off"));
    2434             :         
    2435           0 :         return 1;
    2436             : }
    2437             : 
    2438             : 
    2439             : /****************************************************************************
    2440             : set the newer than time
    2441             : ****************************************************************************/
    2442           0 : static int cmd_newer(struct smbclient_context *ctx, const char **args)
    2443             : {
    2444             :         struct stat sbuf;
    2445             : 
    2446           0 :         if (args[1] && (stat(args[1],&sbuf) == 0)) {
    2447           0 :                 ctx->newer_than = sbuf.st_mtime;
    2448           0 :                 DEBUG(1,("Getting files newer than %s",
    2449             :                          asctime(localtime(&ctx->newer_than))));
    2450             :         } else {
    2451           0 :                 ctx->newer_than = 0;
    2452             :         }
    2453             : 
    2454           0 :         if (args[1] && ctx->newer_than == 0) {
    2455           0 :                 d_printf("Error setting newer-than time\n");
    2456           0 :                 return 1;
    2457             :         }
    2458             : 
    2459           0 :         return 0;
    2460             : }
    2461             : 
    2462             : /****************************************************************************
    2463             : set the archive level
    2464             : ****************************************************************************/
    2465           0 : static int cmd_archive(struct smbclient_context *ctx, const char **args)
    2466             : {
    2467           0 :         if (args[1]) {
    2468           0 :                 ctx->archive_level = atoi(args[1]);
    2469             :         } else
    2470           0 :                 d_printf("Archive level is %d\n",ctx->archive_level);
    2471             : 
    2472           0 :         return 0;
    2473             : }
    2474             : 
    2475             : /****************************************************************************
    2476             : toggle the lowercaseflag
    2477             : ****************************************************************************/
    2478           0 : static int cmd_lowercase(struct smbclient_context *ctx, const char **args)
    2479             : {
    2480           0 :         ctx->lowercase = !ctx->lowercase;
    2481           0 :         DEBUG(2,("filename lowercasing is now %s\n",ctx->lowercase?"on":"off"));
    2482             : 
    2483           0 :         return 0;
    2484             : }
    2485             : 
    2486             : 
    2487             : 
    2488             : 
    2489             : /****************************************************************************
    2490             : toggle the recurse flag
    2491             : ****************************************************************************/
    2492           0 : static int cmd_recurse(struct smbclient_context *ctx, const char **args)
    2493             : {
    2494           0 :         ctx->recurse = !ctx->recurse;
    2495           0 :         DEBUG(2,("directory recursion is now %s\n",ctx->recurse?"on":"off"));
    2496             : 
    2497           0 :         return 0;
    2498             : }
    2499             : 
    2500             : /****************************************************************************
    2501             : toggle the translate flag
    2502             : ****************************************************************************/
    2503           0 : static int cmd_translate(struct smbclient_context *ctx, const char **args)
    2504             : {
    2505           0 :         ctx->translation = !ctx->translation;
    2506           0 :         DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
    2507             :                  ctx->translation?"on":"off"));
    2508             : 
    2509           0 :         return 0;
    2510             : }
    2511             : 
    2512             : 
    2513             : /****************************************************************************
    2514             : do a printmode command
    2515             : ****************************************************************************/
    2516           0 : static int cmd_printmode(struct smbclient_context *ctx, const char **args)
    2517             : {
    2518           0 :         if (args[1]) {
    2519           0 :                 if (strequal(args[1],"text")) {
    2520           0 :                         ctx->printmode = 0;      
    2521             :                 } else {
    2522           0 :                         if (strequal(args[1],"graphics"))
    2523           0 :                                 ctx->printmode = 1;
    2524             :                         else
    2525           0 :                                 ctx->printmode = atoi(args[1]);
    2526             :                 }
    2527             :         }
    2528             : 
    2529           0 :         switch(ctx->printmode)
    2530             :         {
    2531           0 :                 case 0: 
    2532           0 :                         DEBUG(2,("the printmode is now text\n"));
    2533           0 :                         break;
    2534           0 :                 case 1: 
    2535           0 :                         DEBUG(2,("the printmode is now graphics\n"));
    2536           0 :                         break;
    2537           0 :                 default: 
    2538           0 :                         DEBUG(2,("the printmode is now %d\n", ctx->printmode));
    2539           0 :                         break;
    2540             :         }
    2541             :         
    2542           0 :         return 0;
    2543             : }
    2544             : 
    2545             : /****************************************************************************
    2546             :  do the lcd command
    2547             :  ****************************************************************************/
    2548          12 : static int cmd_lcd(struct smbclient_context *ctx, const char **args)
    2549             : {
    2550             :         char d[PATH_MAX];
    2551             :         
    2552          12 :         if (args[1]) {
    2553             :                 int ret;
    2554             : 
    2555          12 :                 ret = chdir(args[1]);
    2556          12 :                 if (ret == -1) {
    2557           0 :                         d_printf("failed to chdir to dir '%s': %s\n",
    2558           0 :                                  args[1], strerror(errno));
    2559           0 :                         return 1;
    2560             :                 }
    2561             :         }
    2562             : 
    2563          12 :         DEBUG(2,("the local directory is now %s\n",getcwd(d, PATH_MAX)));
    2564             : 
    2565          12 :         return 0;
    2566             : }
    2567             : 
    2568             : /****************************************************************************
    2569             : history
    2570             : ****************************************************************************/
    2571           0 : static int cmd_history(struct smbclient_context *ctx, const char **args)
    2572             : {
    2573             : #if defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_LIST)
    2574             :         HIST_ENTRY **hlist;
    2575             :         int i;
    2576             : 
    2577           0 :         hlist = history_list();
    2578             :         
    2579           0 :         for (i = 0; hlist && hlist[i]; i++) {
    2580           0 :                 DEBUG(0, ("%d: %s\n", i, hlist[i]->line));
    2581             :         }
    2582             : #else
    2583             :         DEBUG(0,("no history without readline support\n"));
    2584             : #endif
    2585             : 
    2586           0 :         return 0;
    2587             : }
    2588             : 
    2589             : /****************************************************************************
    2590             :  get a file restarting at end of local file
    2591             :  ****************************************************************************/
    2592           0 : static int cmd_reget(struct smbclient_context *ctx, const char **args)
    2593             : {
    2594             :         char *local_name;
    2595             :         char *remote_name;
    2596             : 
    2597           0 :         if (!args[1]) {
    2598           0 :                 d_printf("reget <filename>\n");
    2599           0 :                 return 1;
    2600             :         }
    2601           0 :         remote_name = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
    2602           0 :         dos_clean_name(remote_name);
    2603             :         
    2604           0 :         if (args[2]) 
    2605           0 :                 local_name = talloc_strdup(ctx, args[2]);
    2606             :         else
    2607           0 :                 local_name = talloc_strdup(ctx, args[1]);
    2608             :         
    2609           0 :         return do_get(ctx, remote_name, local_name, true);
    2610             : }
    2611             : 
    2612             : /****************************************************************************
    2613             :  put a file restarting at end of local file
    2614             :  ****************************************************************************/
    2615           0 : static int cmd_reput(struct smbclient_context *ctx, const char **args)
    2616             : {
    2617             :         char *local_name;
    2618             :         char *remote_name;
    2619             :         
    2620           0 :         if (!args[1]) {
    2621           0 :                 d_printf("reput <filename>\n");
    2622           0 :                 return 1;
    2623             :         }
    2624           0 :         local_name = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
    2625             :   
    2626           0 :         if (!file_exist(local_name)) {
    2627           0 :                 d_printf("%s does not exist\n", local_name);
    2628           0 :                 return 1;
    2629             :         }
    2630             : 
    2631           0 :         if (args[2]) 
    2632           0 :                 remote_name = talloc_strdup(ctx, args[2]);
    2633             :         else
    2634           0 :                 remote_name = talloc_strdup(ctx, args[1]);
    2635             :         
    2636           0 :         dos_clean_name(remote_name);
    2637             : 
    2638           0 :         return do_put(ctx, remote_name, local_name, true);
    2639             : }
    2640             : 
    2641             : 
    2642             : /*
    2643             :   return a string representing a share type
    2644             : */
    2645          26 : static const char *share_type_str(uint32_t type)
    2646             : {
    2647          26 :         switch (type & 0xF) {
    2648          24 :         case STYPE_DISKTREE: 
    2649          24 :                 return "Disk";
    2650           0 :         case STYPE_PRINTQ: 
    2651           0 :                 return "Printer";
    2652           0 :         case STYPE_DEVICE: 
    2653           0 :                 return "Device";
    2654           2 :         case STYPE_IPC: 
    2655           2 :                 return "IPC";
    2656           0 :         default:
    2657           0 :                 return "Unknown";
    2658             :         }
    2659             : }
    2660             : 
    2661             : 
    2662             : /*
    2663             :   display a list of shares from a level 1 share enum
    2664             : */
    2665           2 : static void display_share_result(struct srvsvc_NetShareCtr1 *ctr1)
    2666             : {
    2667             :         int i;
    2668             : 
    2669          28 :         for (i=0;i<ctr1->count;i++) {
    2670          26 :                 struct srvsvc_NetShareInfo1 *info = ctr1->array+i;
    2671             : 
    2672          26 :                 printf("\t%-15s %-10.10s %s\n", 
    2673             :                        info->name, 
    2674          26 :                        share_type_str(info->type), 
    2675             :                        info->comment);
    2676             :         }
    2677           2 : }
    2678             : 
    2679             : 
    2680             : 
    2681             : /****************************************************************************
    2682             : try and browse available shares on a host
    2683             : ****************************************************************************/
    2684           4 : static bool browse_host(struct loadparm_context *lp_ctx,
    2685             :                         struct tevent_context *ev_ctx,
    2686             :                         const char *query_host)
    2687             : {
    2688             :         struct dcerpc_pipe *p;
    2689             :         char *binding;
    2690             :         NTSTATUS status;
    2691             :         struct srvsvc_NetShareEnumAll r;
    2692             :         struct srvsvc_NetShareInfoCtr info_ctr;
    2693           4 :         uint32_t resume_handle = 0;
    2694           4 :         TALLOC_CTX *mem_ctx = talloc_init("browse_host");
    2695             :         struct srvsvc_NetShareCtr1 ctr1;
    2696           4 :         uint32_t totalentries = 0;
    2697           4 :         struct cli_credentials *creds = samba_cmdline_get_creds();
    2698             : 
    2699           4 :         binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", query_host);
    2700             : 
    2701           4 :         status = dcerpc_pipe_connect(mem_ctx, &p, binding, 
    2702             :                                          &ndr_table_srvsvc,
    2703             :                                          creds,
    2704             :                                          ev_ctx,
    2705             :                                      lp_ctx);
    2706           4 :         if (!NT_STATUS_IS_OK(status)) {
    2707           2 :                 d_printf("Failed to connect to %s - %s\n", 
    2708             :                          binding, nt_errstr(status));
    2709           2 :                 talloc_free(mem_ctx);
    2710           2 :                 return false;
    2711             :         }
    2712             : 
    2713           2 :         info_ctr.level = 1;
    2714           2 :         info_ctr.ctr.ctr1 = &ctr1;
    2715             : 
    2716           2 :         r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
    2717           2 :         r.in.info_ctr = &info_ctr;
    2718           2 :         r.in.max_buffer = ~0;
    2719           2 :         r.in.resume_handle = &resume_handle;
    2720           2 :         r.out.resume_handle = &resume_handle;
    2721           2 :         r.out.totalentries = &totalentries;
    2722           2 :         r.out.info_ctr = &info_ctr;
    2723             : 
    2724           2 :         d_printf("\n\tSharename       Type       Comment\n");
    2725           2 :         d_printf("\t---------       ----       -------\n");
    2726             : 
    2727             :         do {
    2728           2 :                 ZERO_STRUCT(ctr1);
    2729           2 :                 status = dcerpc_srvsvc_NetShareEnumAll_r(p->binding_handle, mem_ctx, &r);
    2730             : 
    2731           2 :                 if (NT_STATUS_IS_OK(status) && 
    2732           2 :                     (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA) ||
    2733           2 :                      W_ERROR_IS_OK(r.out.result)) &&
    2734           2 :                     r.out.info_ctr->ctr.ctr1) {
    2735           2 :                         display_share_result(r.out.info_ctr->ctr.ctr1);
    2736           2 :                         resume_handle += r.out.info_ctr->ctr.ctr1->count;
    2737             :                 }
    2738           2 :         } while (NT_STATUS_IS_OK(status) && W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
    2739             : 
    2740           2 :         talloc_free(mem_ctx);
    2741             : 
    2742           2 :         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
    2743           0 :                 d_printf("Failed NetShareEnumAll %s - %s/%s\n", 
    2744             :                          binding, nt_errstr(status), win_errstr(r.out.result));
    2745           0 :                 return false;
    2746             :         }
    2747             : 
    2748           2 :         return false;
    2749             : }
    2750             : 
    2751             : /****************************************************************************
    2752             : try and browse available connections on a host
    2753             : ****************************************************************************/
    2754           4 : static bool list_servers(const char *wk_grp)
    2755             : {
    2756           4 :         d_printf("REWRITE: list servers not implemented\n");
    2757           4 :         return false;
    2758             : }
    2759             : 
    2760             : /* Some constants for completing filename arguments */
    2761             : 
    2762             : #define COMPL_NONE        0          /* No completions */
    2763             : #define COMPL_REMOTE      1          /* Complete remote filename */
    2764             : #define COMPL_LOCAL       2          /* Complete local filename */
    2765             : 
    2766             : static int cmd_help(struct smbclient_context *ctx, const char **args);
    2767             : 
    2768             : /* This defines the commands supported by this client.
    2769             :  * NOTE: The "!" must be the last one in the list because it's fn pointer
    2770             :  *       field is NULL, and NULL in that field is used in process_tok()
    2771             :  *       (below) to indicate the end of the list.  crh
    2772             :  */
    2773             : static struct
    2774             : {
    2775             :   const char *name;
    2776             :   int (*fn)(struct smbclient_context *ctx, const char **args);
    2777             :   const char *description;
    2778             :   char compl_args[2];      /* Completion argument info */
    2779             : } commands[] = 
    2780             : {
    2781             :   {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
    2782             :   {"addprivileges",cmd_addprivileges,"<sid|name> <privilege...> add privileges for a user",{COMPL_NONE,COMPL_NONE}},
    2783             :   {"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
    2784             :   {"acl",cmd_acl,"<file> show file ACL",{COMPL_NONE,COMPL_NONE}},
    2785             :   {"allinfo",cmd_allinfo,"<file> show all possible info about a file",{COMPL_NONE,COMPL_NONE}},
    2786             :   {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
    2787             :   {"cancel",cmd_rewrite,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
    2788             :   {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
    2789             :   {"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}},
    2790             :   {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}},
    2791             :   {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
    2792             :   {"delprivileges",cmd_delprivileges,"<sid|name> <privilege...> remove privileges for a user",{COMPL_NONE,COMPL_NONE}},
    2793             :   {"deltree",cmd_deltree,"<dir> delete a whole directory tree",{COMPL_REMOTE,COMPL_NONE}},
    2794             :   {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
    2795             :   {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
    2796             :   {"eainfo",cmd_eainfo,"<file> show EA contents for a file",{COMPL_NONE,COMPL_NONE}},
    2797             :   {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
    2798             :   {"fsinfo",cmd_fsinfo,"query file system info",{COMPL_NONE,COMPL_NONE}},
    2799             :   {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
    2800             :   {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
    2801             :   {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
    2802             :   {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
    2803             :   {"link",cmd_link,"<src> <dest> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
    2804             :   {"lookup",cmd_lookup,"<sid|name> show SID for name or name for SID",{COMPL_NONE,COMPL_NONE}},
    2805             :   {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},  
    2806             :   {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
    2807             :   {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
    2808             :   {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
    2809             :   {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
    2810             :   {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
    2811             :   {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},  
    2812             :   {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
    2813             :   {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
    2814             :   {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
    2815             :   {"close",cmd_close,"<fnum> close a file",{COMPL_NONE,COMPL_NONE}},
    2816             :   {"privileges",cmd_privileges,"<user> show privileges for a user",{COMPL_NONE,COMPL_NONE}},
    2817             :   {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
    2818             :   {"printmode",cmd_printmode,"<graphics or text> set the print mode",{COMPL_NONE,COMPL_NONE}},
    2819             :   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},  
    2820             :   {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
    2821             :   {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
    2822             :   {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
    2823             :   {"queue",cmd_rewrite,"show the print queue",{COMPL_NONE,COMPL_NONE}},
    2824             :   {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
    2825             :   {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
    2826             :   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},  
    2827             :   {"reget",cmd_reget,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE,COMPL_LOCAL}},
    2828             :   {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
    2829             :   {"reput",cmd_reput,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}},
    2830             :   {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
    2831             :   {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
    2832             :   {"symlink",cmd_symlink,"<src> <dest> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}},
    2833             :   {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
    2834             :   
    2835             :   /* Yes, this must be here, see crh's comment above. */
    2836             :   {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
    2837             :   {NULL,NULL,NULL,{COMPL_NONE,COMPL_NONE}}
    2838             : };
    2839             : 
    2840             : 
    2841             : /*******************************************************************
    2842             :   lookup a command string in the list of commands, including 
    2843             :   abbreviations
    2844             :   ******************************************************************/
    2845          96 : static int process_tok(const char *tok)
    2846             : {
    2847          96 :         size_t i = 0, matches = 0;
    2848          96 :         size_t cmd=0;
    2849          96 :         size_t tok_len = strlen(tok);
    2850             : 
    2851        2468 :         while (commands[i].fn != NULL) {
    2852        2468 :                 if (strequal(commands[i].name,tok)) {
    2853          96 :                         matches = 1;
    2854          96 :                         cmd = i;
    2855          96 :                         break;
    2856        2372 :                 } else if (strncasecmp(commands[i].name, tok, tok_len) == 0) {
    2857           0 :                         matches++;
    2858           0 :                         cmd = i;
    2859             :                 }
    2860        2372 :                 i++;
    2861             :         }
    2862             :   
    2863          96 :         if (matches == 0)
    2864           0 :                 return(-1);
    2865          96 :         else if (matches == 1)
    2866          96 :                 return(cmd);
    2867             :         else
    2868           0 :                 return(-2);
    2869             : }
    2870             : 
    2871             : /****************************************************************************
    2872             : help
    2873             : ****************************************************************************/
    2874           0 : static int cmd_help(struct smbclient_context *ctx, const char **args)
    2875             : {
    2876           0 :         int i=0,j;
    2877             :         
    2878           0 :         if (args[1]) {
    2879           0 :                 if ((i = process_tok(args[1])) >= 0)
    2880           0 :                         d_printf("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description);
    2881             :         } else {
    2882           0 :                 while (commands[i].description) {
    2883           0 :                         for (j=0; commands[i].description && (j<5); j++) {
    2884           0 :                                 d_printf("%-15s",commands[i].name);
    2885           0 :                                 i++;
    2886             :                         }
    2887           0 :                         d_printf("\n");
    2888             :                 }
    2889             :         }
    2890           0 :         return 0;
    2891             : }
    2892             : 
    2893             : static int process_line(struct smbclient_context *ctx, const char *cline);
    2894             : /****************************************************************************
    2895             : process a -c command string
    2896             : ****************************************************************************/
    2897          78 : static int process_command_string(struct smbclient_context *ctx, const char *cmd)
    2898             : {
    2899             :         char **lines;
    2900          78 :         int i, rc = 0;
    2901             : 
    2902          78 :         lines = str_list_make(NULL, cmd, ";");
    2903         174 :         for (i = 0; lines[i]; i++) {
    2904          96 :                 rc |= process_line(ctx, lines[i]);
    2905             :         }
    2906          78 :         talloc_free(lines);
    2907             : 
    2908          78 :         return rc;
    2909             : }       
    2910             : 
    2911             : #define MAX_COMPLETIONS 100
    2912             : 
    2913             : typedef struct {
    2914             :         char *dirmask;
    2915             :         char **matches;
    2916             :         int count, samelen;
    2917             :         const char *text;
    2918             :         int len;
    2919             : } completion_remote_t;
    2920             : 
    2921           0 : static void completion_remote_filter(struct clilist_file_info *f, const char *mask, void *state)
    2922             : {
    2923           0 :         completion_remote_t *info = (completion_remote_t *)state;
    2924             : 
    2925           0 :         if ((info->count < MAX_COMPLETIONS - 1) && (strncmp(info->text, f->name, info->len) == 0) && (!ISDOT(f->name)) && (!ISDOTDOT(f->name))) {
    2926           0 :                 if ((info->dirmask[0] == 0) && !(f->attrib & FILE_ATTRIBUTE_DIRECTORY))
    2927           0 :                         info->matches[info->count] = strdup(f->name);
    2928             :                 else {
    2929             :                         char *tmp;
    2930             : 
    2931           0 :                         if (info->dirmask[0] != 0)
    2932           0 :                                 tmp = talloc_asprintf(NULL, "%s/%s", info->dirmask, f->name);
    2933             :                         else
    2934           0 :                                 tmp = talloc_strdup(NULL, f->name);
    2935             :                         
    2936           0 :                         if (f->attrib & FILE_ATTRIBUTE_DIRECTORY)
    2937           0 :                                 tmp = talloc_append_string(NULL, tmp, "/");
    2938           0 :                         info->matches[info->count] = tmp;
    2939             :                 }
    2940           0 :                 if (info->matches[info->count] == NULL)
    2941           0 :                         return;
    2942           0 :                 if (f->attrib & FILE_ATTRIBUTE_DIRECTORY)
    2943           0 :                         smb_readline_ca_char(0);
    2944             : 
    2945           0 :                 if (info->count == 1)
    2946           0 :                         info->samelen = strlen(info->matches[info->count]);
    2947             :                 else
    2948           0 :                         while (strncmp(info->matches[info->count], info->matches[info->count-1], info->samelen) != 0)
    2949           0 :                                 info->samelen--;
    2950           0 :                 info->count++;
    2951             :         }
    2952             : }
    2953             : 
    2954           0 : static char **remote_completion(const char *text, int len)
    2955             : {
    2956             :         char *dirmask;
    2957             :         int i, ret;
    2958             :         completion_remote_t info;
    2959             : 
    2960           0 :         info.samelen = len;
    2961           0 :         info.text = text;
    2962           0 :         info.len = len;
    2963           0 :         info.count = 0;
    2964             : 
    2965           0 :         if (len >= PATH_MAX)
    2966           0 :                 return(NULL);
    2967             : 
    2968           0 :         info.matches = malloc_array_p(char *, MAX_COMPLETIONS);
    2969           0 :         if (!info.matches) return NULL;
    2970           0 :         info.matches[0] = NULL;
    2971             : 
    2972           0 :         for (i = len-1; i >= 0; i--)
    2973           0 :                 if ((text[i] == '/') || (text[i] == '\\'))
    2974             :                         break;
    2975           0 :         info.text = text+i+1;
    2976           0 :         info.samelen = info.len = len-i-1;
    2977             : 
    2978           0 :         if (i > 0) {
    2979           0 :                 info.dirmask = talloc_strndup(NULL, text, i+1);
    2980           0 :                 info.dirmask[i+1] = 0;
    2981           0 :                 ret = asprintf(&dirmask, "%s%*s*", rl_ctx->remote_cur_dir, i-1,
    2982             :                                text);
    2983             :         } else {
    2984           0 :                 ret = asprintf(&dirmask, "%s*", rl_ctx->remote_cur_dir);
    2985             :         }
    2986           0 :         if (ret < 0) {
    2987           0 :                 goto cleanup;
    2988             :         }
    2989             : 
    2990           0 :         if (smbcli_list(rl_ctx->cli->tree, dirmask, 
    2991             :                      FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 
    2992             :                      completion_remote_filter, &info) < 0)
    2993           0 :                 goto cleanup;
    2994             : 
    2995           0 :         if (info.count == 2)
    2996           0 :                 info.matches[0] = strdup(info.matches[1]);
    2997             :         else {
    2998           0 :                 info.matches[0] = malloc_array_p(char, info.samelen+1);
    2999           0 :                 if (!info.matches[0])
    3000           0 :                         goto cleanup;
    3001           0 :                 strncpy(info.matches[0], info.matches[1], info.samelen);
    3002           0 :                 info.matches[0][info.samelen] = 0;
    3003             :         }
    3004           0 :         info.matches[info.count] = NULL;
    3005           0 :         return info.matches;
    3006             : 
    3007           0 : cleanup:
    3008           0 :         for (i = 0; i < info.count; i++)
    3009           0 :                 free(info.matches[i]);
    3010           0 :         free(info.matches);
    3011           0 :         return NULL;
    3012             : }
    3013             : 
    3014           0 : static char **completion_fn(const char *text, int start, int end)
    3015             : {
    3016           0 :         smb_readline_ca_char(' ');
    3017             : 
    3018           0 :         if (start) {
    3019             :                 const char *buf, *sp;
    3020             :                 int i;
    3021             :                 char compl_type;
    3022             : 
    3023           0 :                 buf = smb_readline_get_line_buffer();
    3024           0 :                 if (buf == NULL)
    3025           0 :                         return NULL;
    3026             :                 
    3027           0 :                 sp = strchr(buf, ' ');
    3028           0 :                 if (sp == NULL)
    3029           0 :                         return NULL;
    3030             :                 
    3031           0 :                 for (i = 0; commands[i].name; i++)
    3032           0 :                         if ((strncmp(commands[i].name, text, sp - buf) == 0) && (commands[i].name[sp - buf] == 0))
    3033           0 :                                 break;
    3034           0 :                 if (commands[i].name == NULL)
    3035           0 :                         return NULL;
    3036             : 
    3037           0 :                 while (*sp == ' ')
    3038           0 :                         sp++;
    3039             : 
    3040           0 :                 if (sp == (buf + start))
    3041           0 :                         compl_type = commands[i].compl_args[0];
    3042             :                 else
    3043           0 :                         compl_type = commands[i].compl_args[1];
    3044             : 
    3045           0 :                 if (compl_type == COMPL_REMOTE)
    3046           0 :                         return remote_completion(text, end - start);
    3047             :                 else /* fall back to local filename completion */
    3048           0 :                         return NULL;
    3049             :         } else {
    3050             :                 char **matches;
    3051           0 :                 size_t i, len, samelen = 0, count=1;
    3052             : 
    3053           0 :                 matches = malloc_array_p(char *, MAX_COMPLETIONS);
    3054           0 :                 if (!matches) return NULL;
    3055           0 :                 matches[0] = NULL;
    3056             : 
    3057           0 :                 len = strlen(text);
    3058           0 :                 for (i=0;commands[i].fn && count < MAX_COMPLETIONS-1;i++) {
    3059           0 :                         if (strncmp(text, commands[i].name, len) == 0) {
    3060           0 :                                 matches[count] = strdup(commands[i].name);
    3061           0 :                                 if (!matches[count])
    3062           0 :                                         goto cleanup;
    3063           0 :                                 if (count == 1)
    3064           0 :                                         samelen = strlen(matches[count]);
    3065             :                                 else
    3066           0 :                                         while (strncmp(matches[count], matches[count-1], samelen) != 0)
    3067           0 :                                                 samelen--;
    3068           0 :                                 count++;
    3069             :                         }
    3070             :                 }
    3071             : 
    3072           0 :                 switch (count) {
    3073           0 :                 case 0: /* should never happen */
    3074             :                 case 1:
    3075           0 :                         goto cleanup;
    3076           0 :                 case 2:
    3077           0 :                         matches[0] = strdup(matches[1]);
    3078           0 :                         break;
    3079           0 :                 default:
    3080           0 :                         matches[0] = malloc_array_p(char, samelen+1);
    3081           0 :                         if (!matches[0])
    3082           0 :                                 goto cleanup;
    3083           0 :                         strncpy(matches[0], matches[1], samelen);
    3084           0 :                         matches[0][samelen] = 0;
    3085             :                 }
    3086           0 :                 matches[count] = NULL;
    3087           0 :                 return matches;
    3088             : 
    3089           0 : cleanup:
    3090           0 :                 for (i = 0; i < count; i++) {
    3091           0 :                         free(matches[i]);
    3092             :                 }
    3093           0 :                 free(matches);
    3094           0 :                 return NULL;
    3095             :         }
    3096             : }
    3097             : 
    3098             : /****************************************************************************
    3099             : make sure we swallow keepalives during idle time
    3100             : ****************************************************************************/
    3101           0 : static void readline_callback(void)
    3102             : {
    3103             :         static time_t last_t;
    3104             :         time_t t;
    3105             : 
    3106           0 :         t = time(NULL);
    3107             : 
    3108           0 :         if (t - last_t < 5) return;
    3109             : 
    3110           0 :         last_t = t;
    3111             : 
    3112           0 :         smbcli_transport_process(rl_ctx->cli->transport);
    3113             : 
    3114           0 :         if (rl_ctx->cli->tree) {
    3115           0 :                 smbcli_chkpath(rl_ctx->cli->tree, "\\");
    3116             :         }
    3117             : }
    3118             : 
    3119          96 : static int process_line(struct smbclient_context *ctx, const char *cline)
    3120             : {
    3121             :         char **args;
    3122             :         int i;
    3123             : 
    3124             :         /* and get the first part of the command */
    3125          96 :         args = str_list_make_shell(ctx, cline, NULL);
    3126          96 :         if (!args || !args[0])
    3127           0 :                 return 0;
    3128             : 
    3129          96 :         if ((i = process_tok(args[0])) >= 0) {
    3130          96 :                 const char **a = discard_const_p(const char *, args);
    3131          96 :                 i = commands[i].fn(ctx, a);
    3132           0 :         } else if (i == -2) {
    3133           0 :                 d_printf("%s: command abbreviation ambiguous\n",args[0]);
    3134             :         } else {
    3135           0 :                 d_printf("%s: command not found\n",args[0]);
    3136             :         }
    3137             : 
    3138          96 :         talloc_free(args);
    3139             : 
    3140          96 :         return i;
    3141             : }
    3142             : 
    3143             : /****************************************************************************
    3144             : process commands on stdin
    3145             : ****************************************************************************/
    3146           0 : static int process_stdin(struct smbclient_context *ctx)
    3147             : {
    3148           0 :         int rc = 0;
    3149           0 :         while (1) {
    3150             :                 /* display a prompt */
    3151           0 :                 char *the_prompt = talloc_asprintf(ctx, "smb: %s> ", ctx->remote_cur_dir);
    3152           0 :                 char *cline = smb_readline(the_prompt, readline_callback, completion_fn);
    3153           0 :                 talloc_free(the_prompt);
    3154             : 
    3155           0 :                 if (!cline) break;
    3156             : 
    3157             :                 /* special case - first char is ! */
    3158           0 :                 if (*cline == '!') {
    3159             :                         int ret;
    3160           0 :                         ret = system(cline + 1);
    3161           0 :                         free(cline);
    3162           0 :                         if (ret == -1) {
    3163           0 :                                 rc |= ret;
    3164             :                         }
    3165           0 :                         continue;
    3166             :                 }
    3167             : 
    3168           0 :                 rc |= process_command_string(ctx, cline);
    3169           0 :                 free(cline);
    3170             : 
    3171             :         }
    3172             : 
    3173           0 :         return rc;
    3174             : }
    3175             : 
    3176             : 
    3177             : /***************************************************** 
    3178             : return a connection to a server
    3179             : *******************************************************/
    3180          94 : static bool do_connect(struct smbclient_context *ctx, 
    3181             :                        struct tevent_context *ev_ctx,
    3182             :                        struct resolve_context *resolve_ctx,
    3183             :                        const char *specified_server, const char **ports, 
    3184             :                        const char *specified_share, 
    3185             :                            const char *socket_options,
    3186             :                        struct cli_credentials *cred, 
    3187             :                        struct smbcli_options *options,
    3188             :                        struct smbcli_session_options *session_options,
    3189             :                            struct gensec_settings *gensec_settings)
    3190             : {
    3191             :         NTSTATUS status;
    3192             :         char *server, *share;
    3193             : 
    3194          94 :         rl_ctx = ctx; /* Ugly hack */
    3195             : 
    3196          94 :         if (strncmp(specified_share, "\\\\", 2) == 0 ||
    3197          94 :             strncmp(specified_share, "//", 2) == 0) {
    3198             :                 bool ok;
    3199             : 
    3200          94 :                 ok = smbcli_parse_unc(specified_share, ctx, &server, &share);
    3201          94 :                 if (!ok) {
    3202           0 :                         d_printf("Failed to parse UNC\n");
    3203           0 :                         talloc_free(ctx);
    3204           0 :                         return false;
    3205             :                 }
    3206             :         } else {
    3207           0 :                 share = talloc_strdup(ctx, specified_share);
    3208           0 :                 server = talloc_strdup(ctx, specified_server);
    3209           0 :                 if (share == NULL || server == NULL) {
    3210           0 :                         d_printf("Failed to allocate memory for server and share\n");
    3211           0 :                         talloc_free(ctx);
    3212           0 :                         return false;
    3213             :                 }
    3214             :         }
    3215             : 
    3216          94 :         ctx->remote_cur_dir = talloc_strdup(ctx, "\\");
    3217          94 :         if (ctx->remote_cur_dir == NULL) {
    3218           0 :                 talloc_free(ctx);
    3219           0 :                 return false;
    3220             :         }
    3221             : 
    3222          94 :         status = smbcli_full_connection(ctx, &ctx->cli, server, ports,
    3223             :                                         share, NULL, 
    3224             :                                         socket_options,
    3225             :                                         cred, resolve_ctx, 
    3226             :                                         ev_ctx, options, session_options,
    3227             :                                         gensec_settings);
    3228          94 :         if (!NT_STATUS_IS_OK(status)) {
    3229          16 :                 d_printf("Connection to \\\\%s\\%s failed - %s\n", 
    3230             :                          server, share, nt_errstr(status));
    3231          16 :                 talloc_free(ctx);
    3232          16 :                 return false;
    3233             :         }
    3234             : 
    3235          78 :         return true;
    3236             : }
    3237             : 
    3238             : /****************************************************************************
    3239             : handle a -L query
    3240             : ****************************************************************************/
    3241           4 : static int do_host_query(struct loadparm_context *lp_ctx,
    3242             :                          struct tevent_context *ev_ctx,
    3243             :                          const char *query_host,
    3244             :                          const char *workgroup)
    3245             : {
    3246           4 :         browse_host(lp_ctx, ev_ctx, query_host);
    3247           4 :         list_servers(workgroup);
    3248           4 :         return(0);
    3249             : }
    3250             : 
    3251             : 
    3252             : /****************************************************************************
    3253             : handle a message operation
    3254             : ****************************************************************************/
    3255           0 : static int do_message_op(const char *netbios_name, const char *desthost,
    3256             :                          const char **destports, const char *destip,
    3257             :                          int name_type,
    3258             :                          struct tevent_context *ev_ctx,
    3259             :                          struct resolve_context *resolve_ctx,
    3260             :                          struct smbcli_options *options,
    3261             :              const char *socket_options)
    3262             : {
    3263             :         struct nbt_name called, calling;
    3264             :         const char *server_name;
    3265             :         struct smbcli_state *cli;
    3266             :         bool ok;
    3267             : 
    3268           0 :         make_nbt_name_client(&calling, netbios_name);
    3269             : 
    3270           0 :         nbt_choose_called_name(NULL, &called, desthost, name_type);
    3271             : 
    3272           0 :         server_name = destip ? destip : desthost;
    3273             : 
    3274           0 :         cli = smbcli_state_init(NULL);
    3275           0 :         if (cli == NULL) {
    3276           0 :                 d_printf("smbcli_state_init() failed\n");
    3277           0 :                 return 1;
    3278             :         }
    3279             : 
    3280           0 :         ok = smbcli_socket_connect(cli, server_name, destports,
    3281             :                                    ev_ctx, resolve_ctx, options,
    3282             :                                    socket_options,
    3283             :                                    &calling, &called);
    3284           0 :         if (!ok) {
    3285           0 :                 d_printf("Connection to %s failed\n", server_name);
    3286           0 :                 return 1;
    3287             :         }
    3288             : 
    3289           0 :         send_message(cli, desthost);
    3290           0 :         talloc_free(cli);
    3291             : 
    3292           0 :         return 0;
    3293             : }
    3294             : 
    3295             : 
    3296             : /****************************************************************************
    3297             :   main program
    3298             : ****************************************************************************/
    3299          98 : int main(int argc, char *argv[])
    3300             : {
    3301          98 :         const char **const_argv = discard_const_p(const char *, argv);
    3302          98 :         char *base_directory = NULL;
    3303          98 :         const char *dest_ip = NULL;
    3304             :         int opt;
    3305          98 :         const char *query_host = NULL;
    3306          98 :         bool message = false;
    3307          98 :         char *desthost = NULL;
    3308             :         poptContext pc;
    3309          98 :         const char *service = NULL;
    3310          98 :         int port = 0;
    3311             :         char *p;
    3312          98 :         int rc = 0;
    3313          98 :         int name_type = 0x20;
    3314             :         TALLOC_CTX *mem_ctx;
    3315             :         struct tevent_context *ev_ctx;
    3316             :         struct smbclient_context *ctx;
    3317          98 :         const char *cmdstr = NULL;
    3318             :         struct smbcli_options smb_options;
    3319             :         struct smbcli_session_options smb_session_options;
    3320          98 :         struct cli_credentials *creds = NULL;
    3321          98 :         struct loadparm_context *lp_ctx = NULL;
    3322             :         bool ok;
    3323             : 
    3324         588 :         struct poptOption long_options[] = {
    3325             :                 POPT_AUTOHELP
    3326             : 
    3327             :                 {
    3328             :                         .longName   = "message",
    3329             :                         .shortName  = 'M',
    3330             :                         .argInfo    = POPT_ARG_STRING,
    3331             :                         .arg        = NULL,
    3332             :                         .val        = 'M',
    3333             :                         .descrip    = "Send message",
    3334             :                         .argDescrip = "HOST",
    3335             :                 },
    3336             :                 {
    3337             :                         .longName   = "ip-address",
    3338             :                         .shortName  = 'I',
    3339             :                         .argInfo    = POPT_ARG_STRING,
    3340             :                         .arg        = NULL,
    3341             :                         .val        = 'I',
    3342             :                         .descrip    = "Use this IP to connect to",
    3343             :                         .argDescrip = "IP",
    3344             :                 },
    3345             :                 {
    3346             :                         .longName   = "stderr",
    3347             :                         .shortName  = 'E',
    3348             :                         .argInfo    = POPT_ARG_NONE,
    3349             :                         .arg        = NULL,
    3350             :                         .val        = 'E',
    3351             :                         .descrip    = "Write messages to stderr instead of stdout",
    3352             :                 },
    3353             :                 {
    3354             :                         .longName   = "list",
    3355             :                         .shortName  = 'L',
    3356             :                         .argInfo    = POPT_ARG_STRING,
    3357             :                         .arg        = NULL,
    3358             :                         .val        = 'L',
    3359             :                         .descrip    = "Get a list of shares available on a host",
    3360             :                         .argDescrip = "HOST",
    3361             :                 },
    3362             :                 {
    3363             :                         .longName   = "directory",
    3364             :                         .shortName  = 'D',
    3365             :                         .argInfo    = POPT_ARG_STRING,
    3366             :                         .arg        = NULL,
    3367             :                         .val        = 'D',
    3368             :                         .descrip    = "Start from directory",
    3369             :                         .argDescrip = "DIR",
    3370             :                 },
    3371             :                 {
    3372             :                         .longName   = "command",
    3373             :                         .shortName  = 'c',
    3374             :                         .argInfo    = POPT_ARG_STRING,
    3375             :                         .arg        = &cmdstr,
    3376             :                         .val        = 'c',
    3377             :                         .descrip    = "Execute semicolon separated commands",
    3378             :                 },
    3379             :                 {
    3380             :                         .longName   = "send-buffer",
    3381             :                         .shortName  = 'b',
    3382             :                         .argInfo    = POPT_ARG_INT,
    3383             :                         .arg        = NULL,
    3384             :                         .val        = 'b',
    3385             :                         .descrip    = "Changes the transmit/send buffer",
    3386             :                         .argDescrip = "BYTES",
    3387             :                 },
    3388             :                 {
    3389             :                         .longName   = "port",
    3390             :                         .shortName  = 'p',
    3391             :                         .argInfo    = POPT_ARG_INT,
    3392             :                         .arg        = &port,
    3393             :                         .val        = 'p',
    3394             :                         .descrip    = "Port to connect to",
    3395             :                         .argDescrip = "PORT",
    3396             :                 },
    3397          98 :                 POPT_COMMON_SAMBA
    3398          98 :                 POPT_COMMON_CONNECTION
    3399          98 :                 POPT_COMMON_CREDENTIALS
    3400          98 :                 POPT_LEGACY_S4
    3401          98 :                 POPT_COMMON_VERSION
    3402             :                 POPT_TABLEEND
    3403             :         };
    3404             :         
    3405          98 :         mem_ctx = talloc_init("client.c/main");
    3406          98 :         if (!mem_ctx) {
    3407           0 :                 d_printf("\nclient.c: Not enough memory\n");
    3408           0 :                 exit(1);
    3409             :         }
    3410             : 
    3411          98 :         ctx = talloc_zero(mem_ctx, struct smbclient_context);
    3412          98 :         ctx->io_bufsize = 64512;
    3413             : 
    3414          98 :         ok = samba_cmdline_init(mem_ctx,
    3415             :                                 SAMBA_CMDLINE_CONFIG_CLIENT,
    3416             :                                 false /* require_smbconf */);
    3417          98 :         if (!ok) {
    3418           0 :                 DBG_ERR("Failed to init cmdline parser!\n");
    3419           0 :                 TALLOC_FREE(ctx);
    3420           0 :                 exit(1);
    3421             :         }
    3422             : 
    3423          98 :         pc = samba_popt_get_context(getprogname(),
    3424             :                                     argc,
    3425             :                                     const_argv,
    3426             :                                     long_options,
    3427             :                                     0);
    3428          98 :         if (pc == NULL) {
    3429           0 :                 DBG_ERR("Failed to setup popt context!\n");
    3430           0 :                 TALLOC_FREE(ctx);
    3431           0 :                 exit(1);
    3432             :         }
    3433          98 :         poptSetOtherOptionHelp(pc, "[OPTIONS] service <password>");
    3434             : 
    3435         243 :         while ((opt = poptGetNextOpt(pc)) != -1) {
    3436          98 :                 switch (opt) {
    3437           0 :                 case 'M':
    3438             :                         /* Messages are sent to NetBIOS name type 0x3
    3439             :                          * (Messenger Service).  Make sure we default
    3440             :                          * to port 139 instead of port 445. srl,crh
    3441             :                          */
    3442           0 :                         name_type = 0x03; 
    3443           0 :                         desthost = strdup(poptGetOptArg(pc));
    3444           0 :                         if( 0 == port ) port = 139;
    3445           0 :                         message = true;
    3446           0 :                         break;
    3447           0 :                 case 'I':
    3448           0 :                         dest_ip = poptGetOptArg(pc);
    3449           0 :                         break;
    3450           4 :                 case 'L':
    3451           4 :                         query_host = strdup(poptGetOptArg(pc));
    3452           4 :                         break;
    3453           0 :                 case 'D':
    3454           0 :                         base_directory = strdup(poptGetOptArg(pc));
    3455           0 :                         break;
    3456           0 :                 case 'b':
    3457           0 :                         ctx->io_bufsize = MAX(1, atoi(poptGetOptArg(pc)));
    3458           0 :                         break;
    3459           0 :                 case POPT_ERROR_BADOPT:
    3460           0 :                         fprintf(stderr, "\nInvalid option %s: %s\n\n",
    3461             :                                 poptBadOption(pc, 0), poptStrerror(opt));
    3462           0 :                         poptPrintUsage(pc, stderr, 0);
    3463           0 :                         exit(1);
    3464             :                 }
    3465             :         }
    3466             : 
    3467          98 :         gensec_init();
    3468             : 
    3469          98 :         if(poptPeekArg(pc)) {
    3470          94 :                 char *s = strdup(poptGetArg(pc)); 
    3471             : 
    3472             :                 /* Convert any '/' characters in the service name to '\' characters */
    3473          94 :                 string_replace(s, '/','\\');
    3474             : 
    3475          94 :                 service = s;
    3476             : 
    3477          94 :                 if (count_chars(s,'\\') < 3) {
    3478           0 :                         d_printf("\n%s: Not enough '\\' characters in service\n",s);
    3479           0 :                         poptPrintUsage(pc, stderr, 0);
    3480           0 :                         exit(1);
    3481             :                 }
    3482             :         }
    3483             : 
    3484          98 :         creds = samba_cmdline_get_creds();
    3485          98 :         lp_ctx = samba_cmdline_get_lp_ctx();
    3486             : 
    3487          98 :         if (poptPeekArg(pc)) { 
    3488           0 :                 cli_credentials_set_password(creds,
    3489             :                         poptGetArg(pc), CRED_SPECIFIED);
    3490             :         }
    3491             : 
    3492          98 :         if (!query_host && !service && !message) {
    3493           0 :                 poptPrintUsage(pc, stderr, 0);
    3494           0 :                 exit(1);
    3495             :         }
    3496             : 
    3497          98 :         poptFreeContext(pc);
    3498          98 :         samba_cmdline_burn(argc, argv);
    3499             : 
    3500          98 :         lpcfg_smbcli_options(lp_ctx, &smb_options);
    3501          98 :         lpcfg_smbcli_session_options(lp_ctx, &smb_session_options);
    3502             : 
    3503          98 :         ev_ctx = s4_event_context_init(ctx);
    3504             : 
    3505          98 :         DEBUG( 3, ( "Client started (version %s).\n", SAMBA_VERSION_STRING ) );
    3506             : 
    3507          98 :         if (query_host && (p=strchr_m(query_host,'#'))) {
    3508           0 :                 *p = 0;
    3509           0 :                 p++;
    3510           0 :                 sscanf(p, "%x", &name_type);
    3511             :         }
    3512             :   
    3513          98 :         if (query_host) {
    3514           4 :                 rc = do_host_query(lp_ctx, ev_ctx, query_host,
    3515             :                                    lpcfg_workgroup(lp_ctx));
    3516           4 :                 return rc;
    3517             :         }
    3518             : 
    3519          94 :         if (message) {
    3520           0 :                 rc = do_message_op(lpcfg_netbios_name(lp_ctx), desthost,
    3521             :                                    lpcfg_smb_ports(lp_ctx), dest_ip,
    3522             :                                    name_type, ev_ctx,
    3523             :                                    lpcfg_resolve_context(lp_ctx),
    3524             :                                    &smb_options, 
    3525             :                    lpcfg_socket_options(lp_ctx));
    3526           0 :                 return rc;
    3527             :         }
    3528             :         
    3529          94 :         if (!do_connect(ctx, ev_ctx, lpcfg_resolve_context(lp_ctx),
    3530             :                         desthost, lpcfg_smb_ports(lp_ctx), service,
    3531             :                         lpcfg_socket_options(lp_ctx),
    3532             :                         creds,
    3533             :                         &smb_options, &smb_session_options,
    3534             :                         lpcfg_gensec_settings(ctx, lp_ctx)))
    3535          16 :                 return 1;
    3536             : 
    3537          78 :         if (base_directory) {
    3538           0 :                 do_cd(ctx, base_directory);
    3539           0 :                 free(base_directory);
    3540             :         }
    3541             :         
    3542          78 :         if (cmdstr) {
    3543          78 :                 rc = process_command_string(ctx, cmdstr);
    3544             :         } else {
    3545           0 :                 rc = process_stdin(ctx);
    3546             :         }
    3547             : 
    3548          78 :         free(desthost);
    3549          78 :         talloc_free(mem_ctx);
    3550             : 
    3551          78 :         return rc;
    3552             : }

Generated by: LCOV version 1.14