client/client.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    SMB client
00004    Copyright (C) Andrew Tridgell          1994-1998
00005    Copyright (C) Simo Sorce               2001-2002
00006    Copyright (C) Jelmer Vernooij          2003
00007    Copyright (C) Gerald (Jerry) Carter    2004
00008    
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013    
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018    
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 */
00023 
00024 #include "includes.h"
00025 #include "client/client_proto.h"
00026 #include "include/rpc_client.h"
00027 #ifndef REGISTER
00028 #define REGISTER 0
00029 #endif
00030 
00031 extern BOOL AllowDebugChange;
00032 extern BOOL override_logfile;
00033 extern char tar_type;
00034 extern BOOL in_client;
00035 static int port = 0;
00036 pstring cur_dir = "\\";
00037 static pstring cd_path = "";
00038 static pstring service;
00039 static pstring desthost;
00040 static pstring username;
00041 static pstring calling_name;
00042 static BOOL grepable=False;
00043 static char *cmdstr = NULL;
00044 
00045 static int io_bufsize = 64512;
00046 
00047 static int name_type = 0x20;
00048 extern int max_protocol;
00049 
00050 static int process_tok(pstring tok);
00051 static int cmd_help(void);
00052 
00053 static TALLOC_CTX *ctx;
00054 #define CREATE_ACCESS_READ READ_CONTROL_ACCESS
00055 static pstring cwd;
00056 
00057 /* 30 second timeout on most commands */
00058 #define CLIENT_TIMEOUT (30*1000)
00059 #define SHORT_TIMEOUT (5*1000)
00060 
00061 /* value for unused fid field in trans2 secondary request */
00062 #define FID_UNUSED (0xFFFF)
00063 
00064 time_t newer_than = 0;
00065 static int archive_level = 0;
00066 
00067 static BOOL translation = False;
00068 static BOOL have_ip;
00069 
00070 /* clitar bits insert */
00071 extern int blocksize;
00072 extern BOOL tar_inc;
00073 extern BOOL tar_reset;
00074 /* clitar bits end */
00075  
00076 
00077 static BOOL prompt = True;
00078 
00079 static BOOL recurse = False;
00080 static BOOL showacls = False;
00081 BOOL lowercase = False;
00082 
00083 static struct in_addr dest_ip;
00084 
00085 #define SEPARATORS " \t\n\r"
00086 
00087 static BOOL abort_mget = True;
00088 
00089 static pstring fileselection = "";
00090 
00091 extern file_info def_finfo;
00092 
00093 /* timing globals */
00094 SMB_BIG_UINT get_total_size = 0;
00095 unsigned int get_total_time_ms = 0;
00096 static SMB_BIG_UINT put_total_size = 0;
00097 static unsigned int put_total_time_ms = 0;
00098 
00099 /* totals globals */
00100 static double dir_total;
00101 
00102 /* root cli_state connection */
00103 
00104 struct cli_state *cli;
00105 
00106 static char CLI_DIRSEP_CHAR = '\\';
00107 static char CLI_DIRSEP_STR[] = { '\\', '\0' };
00108 
00109 /****************************************************************************
00110  Write to a local file with CR/LF->LF translation if appropriate. Return the 
00111  number taken from the buffer. This may not equal the number written.
00112 ****************************************************************************/
00113 
00114 static int writefile(int f, char *b, int n)
00115 {
00116         int i;
00117 
00118         if (!translation) {
00119                 return write(f,b,n);
00120         }
00121 
00122         i = 0;
00123         while (i < n) {
00124                 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') {
00125                         b++;i++;
00126                 }
00127                 if (write(f, b, 1) != 1) {
00128                         break;
00129                 }
00130                 b++;
00131                 i++;
00132         }
00133   
00134         return(i);
00135 }
00136 
00137 /****************************************************************************
00138  Read from a file with LF->CR/LF translation if appropriate. Return the 
00139  number read. read approx n bytes.
00140 ****************************************************************************/
00141 
00142 static int readfile(char *b, int n, XFILE *f)
00143 {
00144         int i;
00145         int c;
00146 
00147         if (!translation)
00148                 return x_fread(b,1,n,f);
00149   
00150         i = 0;
00151         while (i < (n - 1) && (i < BUFFER_SIZE)) {
00152                 if ((c = x_getc(f)) == EOF) {
00153                         break;
00154                 }
00155       
00156                 if (c == '\n') { /* change all LFs to CR/LF */
00157                         b[i++] = '\r';
00158                 }
00159       
00160                 b[i++] = c;
00161         }
00162   
00163         return(i);
00164 }
00165  
00166 /****************************************************************************
00167  Send a message.
00168 ****************************************************************************/
00169 
00170 static void send_message(void)
00171 {
00172         int total_len = 0;
00173         int grp_id;
00174 
00175         if (!cli_message_start(cli, desthost, username, &grp_id)) {
00176                 d_printf("message start: %s\n", cli_errstr(cli));
00177                 return;
00178         }
00179 
00180 
00181         d_printf("Connected. Type your message, ending it with a Control-D\n");
00182 
00183         while (!feof(stdin) && total_len < 1600) {
00184                 int maxlen = MIN(1600 - total_len,127);
00185                 pstring msg;
00186                 int l=0;
00187                 int c;
00188 
00189                 ZERO_ARRAY(msg);
00190 
00191                 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++) {
00192                         if (c == '\n')
00193                                 msg[l++] = '\r';
00194                         msg[l] = c;   
00195                 }
00196 
00197                 if ((total_len > 0) && (strlen(msg) == 0)) {
00198                         break;
00199                 }
00200 
00201                 if (!cli_message_text(cli, msg, l, grp_id)) {
00202                         d_printf("SMBsendtxt failed (%s)\n",cli_errstr(cli));
00203                         return;
00204                 }      
00205                 
00206                 total_len += l;
00207         }
00208 
00209         if (total_len >= 1600)
00210                 d_printf("the message was truncated to 1600 bytes\n");
00211         else
00212                 d_printf("sent %d bytes\n",total_len);
00213 
00214         if (!cli_message_end(cli, grp_id)) {
00215                 d_printf("SMBsendend failed (%s)\n",cli_errstr(cli));
00216                 return;
00217         }      
00218 }
00219 
00220 /****************************************************************************
00221  Check the space on a device.
00222 ****************************************************************************/
00223 
00224 static int do_dskattr(void)
00225 {
00226         int total, bsize, avail;
00227         struct cli_state *targetcli;
00228         pstring targetpath;
00229 
00230         if ( !cli_resolve_path( "", cli, cur_dir, &targetcli, targetpath ) ) {
00231                 d_printf("Error in dskattr: %s\n", cli_errstr(cli));
00232                 return 1;
00233         }
00234 
00235         if (!cli_dskattr(targetcli, &bsize, &total, &avail)) {
00236                 d_printf("Error in dskattr: %s\n",cli_errstr(targetcli)); 
00237                 return 1;
00238         }
00239 
00240         d_printf("\n\t\t%d blocks of size %d. %d blocks available\n",
00241                  total, bsize, avail);
00242 
00243         return 0;
00244 }
00245 
00246 /****************************************************************************
00247  Show cd/pwd.
00248 ****************************************************************************/
00249 
00250 static int cmd_pwd(void)
00251 {
00252         d_printf("Current directory is %s",service);
00253         d_printf("%s\n",cur_dir);
00254         return 0;
00255 }
00256 
00257 /****************************************************************************
00258  Change directory - inner section.
00259 ****************************************************************************/
00260 
00261 static int do_cd(char *newdir)
00262 {
00263         char *p = newdir;
00264         pstring saved_dir;
00265         pstring dname;
00266         pstring targetpath;
00267         struct cli_state *targetcli;
00268         SMB_STRUCT_STAT sbuf;
00269         uint32 attributes;
00270         int ret = 1;
00271       
00272         dos_format(newdir);
00273 
00274         /* Save the current directory in case the new directory is invalid */
00275 
00276         pstrcpy(saved_dir, cur_dir);
00277 
00278         if (*p == CLI_DIRSEP_CHAR) {
00279                 pstrcpy(cur_dir,p);
00280         } else {
00281                 pstrcat(cur_dir,p);
00282         }
00283 
00284         /* Ensure cur_dir ends in a DIRSEP */
00285         if ((cur_dir[0] != '\0') && (*(cur_dir+strlen(cur_dir)-1) != CLI_DIRSEP_CHAR)) {
00286                 pstrcat(cur_dir, CLI_DIRSEP_STR);
00287         }
00288         
00289         clean_name(cur_dir);
00290         pstrcpy( dname, cur_dir );
00291         
00292         if ( !cli_resolve_path( "", cli, dname, &targetcli, targetpath ) ) {
00293                 d_printf("cd %s: %s\n", dname, cli_errstr(cli));
00294                 pstrcpy(cur_dir,saved_dir);
00295                 goto out;
00296         }
00297 
00298         if (strequal(targetpath,CLI_DIRSEP_STR )) {
00299                 return 0;
00300         }
00301                 
00302         /* Use a trans2_qpathinfo to test directories for modern servers.
00303            Except Win9x doesn't support the qpathinfo_basic() call..... */ 
00304         
00305         if ( targetcli->protocol >  PROTOCOL_LANMAN2 && !targetcli->win95 ) {
00306                 if ( !cli_qpathinfo_basic( targetcli, targetpath, &sbuf, &attributes ) ) {
00307                         d_printf("cd %s: %s\n", dname, cli_errstr(targetcli));
00308                         pstrcpy(cur_dir,saved_dir);
00309                         goto out;
00310                 }
00311                 
00312                 if ( !(attributes&FILE_ATTRIBUTE_DIRECTORY) ) {
00313                         d_printf("cd %s: not a directory\n", dname);
00314                         pstrcpy(cur_dir,saved_dir);
00315                         goto out;
00316                 }               
00317         } else {
00318                 pstrcat( targetpath, CLI_DIRSEP_STR );
00319                 clean_name( targetpath );
00320                 
00321                 if ( !cli_chkpath(targetcli, targetpath) ) {
00322                         d_printf("cd %s: %s\n", dname, cli_errstr(targetcli));
00323                         pstrcpy(cur_dir,saved_dir);
00324                         goto out;
00325                 }
00326         }
00327 
00328         ret = 0;
00329 
00330 out:
00331         
00332         pstrcpy(cd_path,cur_dir);
00333         return ret;
00334 }
00335 
00336 /****************************************************************************
00337  Change directory.
00338 ****************************************************************************/
00339 
00340 static int cmd_cd(void)
00341 {
00342         pstring buf;
00343         int rc = 0;
00344                 
00345         if (next_token_nr(NULL,buf,NULL,sizeof(buf)))
00346                 rc = do_cd(buf);
00347         else
00348                 d_printf("Current directory is %s\n",cur_dir);
00349 
00350         return rc;
00351 }
00352 
00353 /*******************************************************************
00354  Decide if a file should be operated on.
00355 ********************************************************************/
00356 
00357 static BOOL do_this_one(file_info *finfo)
00358 {
00359         if (finfo->mode & aDIR)
00360                 return(True);
00361 
00362         if (*fileselection && 
00363             !mask_match(finfo->name,fileselection,False)) {
00364                 DEBUG(3,("mask_match %s failed\n", finfo->name));
00365                 return False;
00366         }
00367 
00368         if (newer_than && finfo->mtime_ts.tv_sec < newer_than) {
00369                 DEBUG(3,("newer_than %s failed\n", finfo->name));
00370                 return(False);
00371         }
00372 
00373         if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH)) {
00374                 DEBUG(3,("archive %s failed\n", finfo->name));
00375                 return(False);
00376         }
00377         
00378         return(True);
00379 }
00380 
00381 /****************************************************************************
00382  Display info about a file.
00383 ****************************************************************************/
00384 
00385 static void display_finfo(file_info *finfo)
00386 {
00387         if (do_this_one(finfo)) {
00388                 time_t t = finfo->mtime_ts.tv_sec; /* the time is assumed to be passed as GMT */
00389                 if (!showacls) {
00390                         d_printf("  %-30s%7.7s %8.0f  %s",
00391                                  finfo->name,
00392                                  attrib_string(finfo->mode),
00393                                 (double)finfo->size,
00394                                 time_to_asc(t));
00395                         dir_total += finfo->size;
00396                 } else {
00397                         pstring afname;
00398                         int fnum;
00399 
00400                         /* skip if this is . or .. */
00401                         if ( strequal(finfo->name,"..") || strequal(finfo->name,".") )
00402                                 return;
00403                         /* create absolute filename for cli_nt_create() FIXME */
00404                         pstrcpy( afname, cwd);
00405                         pstrcat( afname, CLI_DIRSEP_STR);
00406                         pstrcat( afname, finfo->name);
00407                         /* print file meta date header */
00408                         d_printf( "FILENAME:%s\n", afname);
00409                         d_printf( "MODE:%s\n", attrib_string(finfo->mode));
00410                         d_printf( "SIZE:%.0f\n", (double)finfo->size);
00411                         d_printf( "MTIME:%s", time_to_asc(t));
00412                         fnum = cli_nt_create(finfo->cli, afname, CREATE_ACCESS_READ);
00413                         if (fnum == -1) {
00414                                 DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
00415                                         afname,
00416                                         cli_errstr( finfo->cli)));
00417                         } else {
00418                                 SEC_DESC *sd = NULL;
00419                                 sd = cli_query_secdesc(finfo->cli, fnum, ctx);
00420                                 if (!sd) {
00421                                         DEBUG( 0, ("display_finfo() failed to "
00422                                                 "get security descriptor: %s",
00423                                                 cli_errstr( finfo->cli)));
00424                                 } else {
00425                                         display_sec_desc(sd);
00426                                 }
00427                         }
00428                 }
00429         }
00430 }
00431 
00432 /****************************************************************************
00433  Accumulate size of a file.
00434 ****************************************************************************/
00435 
00436 static void do_du(file_info *finfo)
00437 {
00438         if (do_this_one(finfo)) {
00439                 dir_total += finfo->size;
00440         }
00441 }
00442 
00443 static BOOL do_list_recurse;
00444 static BOOL do_list_dirs;
00445 static char *do_list_queue = 0;
00446 static long do_list_queue_size = 0;
00447 static long do_list_queue_start = 0;
00448 static long do_list_queue_end = 0;
00449 static void (*do_list_fn)(file_info *);
00450 
00451 /****************************************************************************
00452  Functions for do_list_queue.
00453 ****************************************************************************/
00454 
00455 /*
00456  * The do_list_queue is a NUL-separated list of strings stored in a
00457  * char*.  Since this is a FIFO, we keep track of the beginning and
00458  * ending locations of the data in the queue.  When we overflow, we
00459  * double the size of the char*.  When the start of the data passes
00460  * the midpoint, we move everything back.  This is logically more
00461  * complex than a linked list, but easier from a memory management
00462  * angle.  In any memory error condition, do_list_queue is reset.
00463  * Functions check to ensure that do_list_queue is non-NULL before
00464  * accessing it.
00465  */
00466 
00467 static void reset_do_list_queue(void)
00468 {
00469         SAFE_FREE(do_list_queue);
00470         do_list_queue_size = 0;
00471         do_list_queue_start = 0;
00472         do_list_queue_end = 0;
00473 }
00474 
00475 static void init_do_list_queue(void)
00476 {
00477         reset_do_list_queue();
00478         do_list_queue_size = 1024;
00479         do_list_queue = (char *)SMB_MALLOC(do_list_queue_size);
00480         if (do_list_queue == 0) { 
00481                 d_printf("malloc fail for size %d\n",
00482                          (int)do_list_queue_size);
00483                 reset_do_list_queue();
00484         } else {
00485                 memset(do_list_queue, 0, do_list_queue_size);
00486         }
00487 }
00488 
00489 static void adjust_do_list_queue(void)
00490 {
00491         /*
00492          * If the starting point of the queue is more than half way through,
00493          * move everything toward the beginning.
00494          */
00495 
00496         if (do_list_queue == NULL) {
00497                 DEBUG(4,("do_list_queue is empty\n"));
00498                 do_list_queue_start = do_list_queue_end = 0;
00499                 return;
00500         }
00501                 
00502         if (do_list_queue_start == do_list_queue_end) {
00503                 DEBUG(4,("do_list_queue is empty\n"));
00504                 do_list_queue_start = do_list_queue_end = 0;
00505                 *do_list_queue = '\0';
00506         } else if (do_list_queue_start > (do_list_queue_size / 2)) {
00507                 DEBUG(4,("sliding do_list_queue backward\n"));
00508                 memmove(do_list_queue,
00509                         do_list_queue + do_list_queue_start,
00510                         do_list_queue_end - do_list_queue_start);
00511                 do_list_queue_end -= do_list_queue_start;
00512                 do_list_queue_start = 0;
00513         }
00514 }
00515 
00516 static void add_to_do_list_queue(const char* entry)
00517 {
00518         long new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
00519         while (new_end > do_list_queue_size) {
00520                 do_list_queue_size *= 2;
00521                 DEBUG(4,("enlarging do_list_queue to %d\n",
00522                          (int)do_list_queue_size));
00523                 do_list_queue = (char *)SMB_REALLOC(do_list_queue, do_list_queue_size);
00524                 if (! do_list_queue) {
00525                         d_printf("failure enlarging do_list_queue to %d bytes\n",
00526                                  (int)do_list_queue_size);
00527                         reset_do_list_queue();
00528                 } else {
00529                         memset(do_list_queue + do_list_queue_size / 2,
00530                                0, do_list_queue_size / 2);
00531                 }
00532         }
00533         if (do_list_queue) {
00534                 safe_strcpy_base(do_list_queue + do_list_queue_end, 
00535                                  entry, do_list_queue, do_list_queue_size);
00536                 do_list_queue_end = new_end;
00537                 DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n",
00538                          entry, (int)do_list_queue_start, (int)do_list_queue_end));
00539         }
00540 }
00541 
00542 static char *do_list_queue_head(void)
00543 {
00544         return do_list_queue + do_list_queue_start;
00545 }
00546 
00547 static void remove_do_list_queue_head(void)
00548 {
00549         if (do_list_queue_end > do_list_queue_start) {
00550                 do_list_queue_start += strlen(do_list_queue_head()) + 1;
00551                 adjust_do_list_queue();
00552                 DEBUG(4,("removed head of do_list_queue (start=%d, end=%d)\n",
00553                          (int)do_list_queue_start, (int)do_list_queue_end));
00554         }
00555 }
00556 
00557 static int do_list_queue_empty(void)
00558 {
00559         return (! (do_list_queue && *do_list_queue));
00560 }
00561 
00562 /****************************************************************************
00563  A helper for do_list.
00564 ****************************************************************************/
00565 
00566 static void do_list_helper(const char *mntpoint, file_info *f, const char *mask, void *state)
00567 {
00568         char *dir_end;
00569 
00570         /* save the directory */
00571         pstrcpy( f->dir, mask );
00572         if ( (dir_end = strrchr( f->dir, CLI_DIRSEP_CHAR )) != NULL ) {
00573                 *dir_end = '\0';
00574         }
00575 
00576         if (f->mode & aDIR) {
00577                 if (do_list_dirs && do_this_one(f)) {
00578                         do_list_fn(f);
00579                 }
00580                 if (do_list_recurse && 
00581                     !strequal(f->name,".") && 
00582                     !strequal(f->name,"..")) {
00583                         pstring mask2;
00584                         char *p;
00585 
00586                         if (!f->name[0]) {
00587                                 d_printf("Empty dir name returned. Possible server misconfiguration.\n");
00588                                 return;
00589                         }
00590 
00591                         pstrcpy(mask2, mntpoint);
00592                         pstrcat(mask2, mask);
00593                         p = strrchr_m(mask2,CLI_DIRSEP_CHAR);
00594                         if (!p)
00595                                 return;
00596                         p[1] = 0;
00597                         pstrcat(mask2, f->name);
00598                         pstrcat(mask2,CLI_DIRSEP_STR);
00599                         pstrcat(mask2,"*");
00600                         add_to_do_list_queue(mask2);
00601                 }
00602                 return;
00603         }
00604 
00605         if (do_this_one(f)) {
00606                 do_list_fn(f);
00607         }
00608 }
00609 
00610 /****************************************************************************
00611  A wrapper around cli_list that adds recursion.
00612 ****************************************************************************/
00613 
00614 void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec, BOOL dirs)
00615 {
00616         static int in_do_list = 0;
00617         struct cli_state *targetcli;
00618         pstring targetpath;
00619 
00620         if (in_do_list && rec) {
00621                 fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n");
00622                 exit(1);
00623         }
00624 
00625         in_do_list = 1;
00626 
00627         do_list_recurse = rec;
00628         do_list_dirs = dirs;
00629         do_list_fn = fn;
00630 
00631         if (rec) {
00632                 init_do_list_queue();
00633                 add_to_do_list_queue(mask);
00634                 
00635                 while (! do_list_queue_empty()) {
00636                         /*
00637                          * Need to copy head so that it doesn't become
00638                          * invalid inside the call to cli_list.  This
00639                          * would happen if the list were expanded
00640                          * during the call.
00641                          * Fix from E. Jay Berkenbilt (ejb@ql.org)
00642                          */
00643                         pstring head;
00644                         pstrcpy(head, do_list_queue_head());
00645                         
00646                         /* check for dfs */
00647                         
00648                         if ( !cli_resolve_path( "", cli, head, &targetcli, targetpath ) ) {
00649                                 d_printf("do_list: [%s] %s\n", head, cli_errstr(cli));
00650                                 remove_do_list_queue_head();
00651                                 continue;
00652                         }
00653                         
00654                         cli_list(targetcli, targetpath, attribute, do_list_helper, NULL);
00655                         remove_do_list_queue_head();
00656                         if ((! do_list_queue_empty()) && (fn == display_finfo)) {
00657                                 char* next_file = do_list_queue_head();
00658                                 char* save_ch = 0;
00659                                 if ((strlen(next_file) >= 2) &&
00660                                     (next_file[strlen(next_file) - 1] == '*') &&
00661                                     (next_file[strlen(next_file) - 2] == CLI_DIRSEP_CHAR)) {
00662                                         save_ch = next_file +
00663                                                 strlen(next_file) - 2;
00664                                         *save_ch = '\0';
00665                                         if (showacls) /* cwd is only used if showacls is on */
00666                                                 pstrcpy( cwd, next_file);
00667                                 }
00668                                 if (!showacls) /* don't disturbe the showacls output */
00669                                         d_printf("\n%s\n",next_file);
00670                                 if (save_ch) {
00671                                         *save_ch = CLI_DIRSEP_CHAR;
00672                                 }
00673                         }
00674                 }
00675         } else {
00676                 /* check for dfs */
00677                         
00678                 if ( cli_resolve_path( "", cli, mask, &targetcli, targetpath ) ) {
00679                         if (cli_list(targetcli, targetpath, attribute, do_list_helper, NULL) == -1) 
00680                                 d_printf("%s listing %s\n", cli_errstr(targetcli), targetpath);
00681                 }
00682                 else
00683                         d_printf("do_list: [%s] %s\n", mask, cli_errstr(cli));
00684                 
00685         }
00686 
00687         in_do_list = 0;
00688         reset_do_list_queue();
00689 }
00690 
00691 /****************************************************************************
00692  Get a directory listing.
00693 ****************************************************************************/
00694 
00695 static int cmd_dir(void)
00696 {
00697         uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
00698         pstring mask;
00699         pstring buf;
00700         char *p=buf;
00701         int rc;
00702         
00703         dir_total = 0;
00704         pstrcpy(mask,cur_dir);
00705         
00706         if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
00707                 dos_format(p);
00708                 if (*p == CLI_DIRSEP_CHAR)
00709                         pstrcpy(mask,p);
00710                 else
00711                         pstrcat(mask,p);
00712         } else {
00713                 pstrcat(mask,"*");
00714         }
00715 
00716         if (showacls) {
00717                 /* cwd is only used if showacls is on */
00718                 pstrcpy(cwd, cur_dir);
00719         }
00720 
00721         do_list(mask, attribute, display_finfo, recurse, True);
00722 
00723         rc = do_dskattr();
00724 
00725         DEBUG(3, ("Total bytes listed: %.0f\n", dir_total));
00726 
00727         return rc;
00728 }
00729 
00730 /****************************************************************************
00731  Get a directory listing.
00732 ****************************************************************************/
00733 
00734 static int cmd_du(void)
00735 {
00736         uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
00737         pstring mask;
00738         pstring buf;
00739         char *p=buf;
00740         int rc;
00741         
00742         dir_total = 0;
00743         pstrcpy(mask,cur_dir);
00744 
00745         if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
00746                 dos_format(p);
00747                 if (*p == CLI_DIRSEP_CHAR)
00748                         pstrcpy(mask,p);
00749                 else
00750                         pstrcat(mask,p);
00751         } else {
00752                 pstrcat(mask,"*");
00753         }
00754 
00755         do_list(mask, attribute, do_du, recurse, True);
00756 
00757         rc = do_dskattr();
00758 
00759         d_printf("Total number of bytes: %.0f\n", dir_total);
00760 
00761         return rc;
00762 }
00763 
00764 /****************************************************************************
00765  Get a file from rname to lname
00766 ****************************************************************************/
00767 
00768 static int do_get(char *rname, char *lname, BOOL reget)
00769 {  
00770         int handle = 0, fnum;
00771         BOOL newhandle = False;
00772         char *data;
00773         struct timeval tp_start;
00774         int read_size = io_bufsize;
00775         uint16 attr;
00776         SMB_OFF_T size;
00777         off_t start = 0;
00778         off_t nread = 0;
00779         int rc = 0;
00780         struct cli_state *targetcli;
00781         pstring targetname;
00782 
00783 
00784         if (lowercase) {
00785                 strlower_m(lname);
00786         }
00787 
00788         if ( !cli_resolve_path( "", cli, rname, &targetcli, targetname ) ) {
00789                 d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
00790                 return 1;
00791         }
00792 
00793         GetTimeOfDay(&tp_start);
00794         
00795         fnum = cli_open(targetcli, targetname, O_RDONLY, DENY_NONE);
00796 
00797         if (fnum == -1) {
00798                 d_printf("%s opening remote file %s\n",cli_errstr(cli),rname);
00799                 return 1;
00800         }
00801 
00802         if(!strcmp(lname,"-")) {
00803                 handle = fileno(stdout);
00804         } else {
00805                 if (reget) {
00806                         handle = sys_open(lname, O_WRONLY|O_CREAT, 0644);
00807                         if (handle >= 0) {
00808                                 start = sys_lseek(handle, 0, SEEK_END);
00809                                 if (start == -1) {
00810                                         d_printf("Error seeking local file\n");
00811                                         return 1;
00812                                 }
00813                         }
00814                 } else {
00815                         handle = sys_open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
00816                 }
00817                 newhandle = True;
00818         }
00819         if (handle < 0) {
00820                 d_printf("Error opening local file %s\n",lname);
00821                 return 1;
00822         }
00823 
00824 
00825         if (!cli_qfileinfo(targetcli, fnum, 
00826                            &attr, &size, NULL, NULL, NULL, NULL, NULL) &&
00827             !cli_getattrE(targetcli, fnum, 
00828                           &attr, &size, NULL, NULL, NULL)) {
00829                 d_printf("getattrib: %s\n",cli_errstr(targetcli));
00830                 return 1;
00831         }
00832 
00833         DEBUG(1,("getting file %s of size %.0f as %s ", 
00834                  rname, (double)size, lname));
00835 
00836         if(!(data = (char *)SMB_MALLOC(read_size))) { 
00837                 d_printf("malloc fail for size %d\n", read_size);
00838                 cli_close(targetcli, fnum);
00839                 return 1;
00840         }
00841 
00842         while (1) {
00843                 int n = cli_read(targetcli, fnum, data, nread + start, read_size);
00844 
00845                 if (n <= 0)
00846                         break;
00847  
00848                 if (writefile(handle,data, n) != n) {
00849                         d_printf("Error writing local file\n");
00850                         rc = 1;
00851                         break;
00852                 }
00853       
00854                 nread += n;
00855         }
00856 
00857         if (nread + start < size) {
00858                 DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n",
00859                             rname, (long)nread));
00860 
00861                 rc = 1;
00862         }
00863 
00864         SAFE_FREE(data);
00865         
00866         if (!cli_close(targetcli, fnum)) {
00867                 d_printf("Error %s closing remote file\n",cli_errstr(cli));
00868                 rc = 1;
00869         }
00870 
00871         if (newhandle) {
00872                 close(handle);
00873         }
00874 
00875         if (archive_level >= 2 && (attr & aARCH)) {
00876                 cli_setatr(cli, rname, attr & ~(uint16)aARCH, 0);
00877         }
00878 
00879         {
00880                 struct timeval tp_end;
00881                 int this_time;
00882                 
00883                 GetTimeOfDay(&tp_end);
00884                 this_time = 
00885                         (tp_end.tv_sec - tp_start.tv_sec)*1000 +
00886                         (tp_end.tv_usec - tp_start.tv_usec)/1000;
00887                 get_total_time_ms += this_time;
00888                 get_total_size += nread;
00889                 
00890                 DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
00891                          nread / (1.024*this_time + 1.0e-4),
00892                          get_total_size / (1.024*get_total_time_ms)));
00893         }
00894         
00895         return rc;
00896 }
00897 
00898 /****************************************************************************
00899  Get a file.
00900 ****************************************************************************/
00901 
00902 static int cmd_get(void)
00903 {
00904         pstring lname;
00905         pstring rname;
00906         char *p;
00907 
00908         pstrcpy(rname,cur_dir);
00909         
00910         p = rname + strlen(rname);
00911         
00912         if (!next_token_nr(NULL,p,NULL,sizeof(rname)-strlen(rname))) {
00913                 d_printf("get <filename>\n");
00914                 return 1;
00915         }
00916         pstrcpy(lname,p);
00917         clean_name(rname);
00918         
00919         next_token_nr(NULL,lname,NULL,sizeof(lname));
00920         
00921         return do_get(rname, lname, False);
00922 }
00923 
00924 /****************************************************************************
00925  Do an mget operation on one file.
00926 ****************************************************************************/
00927 
00928 static void do_mget(file_info *finfo)
00929 {
00930         pstring rname;
00931         pstring quest;
00932         pstring saved_curdir;
00933         pstring mget_mask;
00934 
00935         if (strequal(finfo->name,".") || strequal(finfo->name,".."))
00936                 return;
00937 
00938         if (abort_mget) {
00939                 d_printf("mget aborted\n");
00940                 return;
00941         }
00942 
00943         if (finfo->mode & aDIR)
00944                 slprintf(quest,sizeof(pstring)-1,
00945                          "Get directory %s? ",finfo->name);
00946         else
00947                 slprintf(quest,sizeof(pstring)-1,
00948                          "Get file %s? ",finfo->name);
00949 
00950         if (prompt && !yesno(quest))
00951                 return;
00952 
00953         if (!(finfo->mode & aDIR)) {
00954                 pstrcpy(rname,cur_dir);
00955                 pstrcat(rname,finfo->name);
00956                 do_get(rname, finfo->name, False);
00957                 return;
00958         }
00959 
00960         /* handle directories */
00961         pstrcpy(saved_curdir,cur_dir);
00962 
00963         pstrcat(cur_dir,finfo->name);
00964         pstrcat(cur_dir,CLI_DIRSEP_STR);
00965 
00966         unix_format(finfo->name);
00967         if (lowercase)
00968                 strlower_m(finfo->name);
00969         
00970         if (!directory_exist(finfo->name,NULL) && 
00971             mkdir(finfo->name,0777) != 0) {
00972                 d_printf("failed to create directory %s\n",finfo->name);
00973                 pstrcpy(cur_dir,saved_curdir);
00974                 return;
00975         }
00976         
00977         if (chdir(finfo->name) != 0) {
00978                 d_printf("failed to chdir to directory %s\n",finfo->name);
00979                 pstrcpy(cur_dir,saved_curdir);
00980                 return;
00981         }
00982 
00983         pstrcpy(mget_mask,cur_dir);
00984         pstrcat(mget_mask,"*");
00985         
00986         do_list(mget_mask, aSYSTEM | aHIDDEN | aDIR,do_mget,False, True);
00987         chdir("..");
00988         pstrcpy(cur_dir,saved_curdir);
00989 }
00990 
00991 /****************************************************************************
00992  View the file using the pager.
00993 ****************************************************************************/
00994 
00995 static int cmd_more(void)
00996 {
00997         pstring rname,lname,pager_cmd;
00998         char *pager;
00999         int fd;
01000         int rc = 0;
01001 
01002         pstrcpy(rname,cur_dir);
01003         
01004         slprintf(lname,sizeof(lname)-1, "%s/smbmore.XXXXXX",tmpdir());
01005         fd = smb_mkstemp(lname);
01006         if (fd == -1) {
01007                 d_printf("failed to create temporary file for more\n");
01008                 return 1;
01009         }
01010         close(fd);
01011 
01012         if (!next_token_nr(NULL,rname+strlen(rname),NULL,sizeof(rname)-strlen(rname))) {
01013                 d_printf("more <filename>\n");
01014                 unlink(lname);
01015                 return 1;
01016         }
01017         clean_name(rname);
01018 
01019         rc = do_get(rname, lname, False);
01020 
01021         pager=getenv("PAGER");
01022 
01023         slprintf(pager_cmd,sizeof(pager_cmd)-1,
01024                  "%s %s",(pager? pager:PAGER), lname);
01025         system(pager_cmd);
01026         unlink(lname);
01027         
01028         return rc;
01029 }
01030 
01031 /****************************************************************************
01032  Do a mget command.
01033 ****************************************************************************/
01034 
01035 static int cmd_mget(void)
01036 {
01037         uint16 attribute = aSYSTEM | aHIDDEN;
01038         pstring mget_mask;
01039         pstring buf;
01040         char *p=buf;
01041 
01042         *mget_mask = 0;
01043 
01044         if (recurse)
01045                 attribute |= aDIR;
01046         
01047         abort_mget = False;
01048 
01049         while (next_token_nr(NULL,p,NULL,sizeof(buf))) {
01050                 pstrcpy(mget_mask,cur_dir);
01051                 
01052                 if (*p == CLI_DIRSEP_CHAR)
01053                         pstrcpy(mget_mask,p);
01054                 else
01055                         pstrcat(mget_mask,p);
01056                 do_list(mget_mask, attribute,do_mget,False,True);
01057         }
01058 
01059         if (!*mget_mask) {
01060                 pstrcpy(mget_mask,cur_dir);
01061                 pstrcat(mget_mask,"*");
01062                 do_list(mget_mask, attribute,do_mget,False,True);
01063         }
01064         
01065         return 0;
01066 }
01067 
01068 /****************************************************************************
01069  Make a directory of name "name".
01070 ****************************************************************************/
01071 
01072 static BOOL do_mkdir(char *name)
01073 {
01074         struct cli_state *targetcli;
01075         pstring targetname;
01076         
01077         if ( !cli_resolve_path( "", cli, name, &targetcli, targetname ) ) {
01078                 d_printf("mkdir %s: %s\n", name, cli_errstr(cli));
01079                 return False;
01080         }
01081 
01082         if (!cli_mkdir(targetcli, targetname)) {
01083                 d_printf("%s making remote directory %s\n",
01084                          cli_errstr(targetcli),name);
01085                 return(False);
01086         }
01087 
01088         return(True);
01089 }
01090 
01091 /****************************************************************************
01092  Show 8.3 name of a file.
01093 ****************************************************************************/
01094 
01095 static BOOL do_altname(char *name)
01096 {
01097         pstring altname;
01098         if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
01099                 d_printf("%s getting alt name for %s\n",
01100                          cli_errstr(cli),name);
01101                 return(False);
01102         }
01103         d_printf("%s\n", altname);
01104 
01105         return(True);
01106 }
01107 
01108 /****************************************************************************
01109  Exit client.
01110 ****************************************************************************/
01111 
01112 static int cmd_quit(void)
01113 {
01114         cli_cm_shutdown();
01115         talloc_destroy( ctx);
01116         exit(0);
01117         /* NOTREACHED */
01118         return 0;
01119 }
01120 
01121 /****************************************************************************
01122  Make a directory.
01123 ****************************************************************************/
01124 
01125 static int cmd_mkdir(void)
01126 {
01127         pstring mask;
01128         pstring buf;
01129         char *p=buf;
01130   
01131         pstrcpy(mask,cur_dir);
01132 
01133         if (!next_token_nr(NULL,p,NULL,sizeof(buf))) {
01134                 if (!recurse)
01135                         d_printf("mkdir <dirname>\n");
01136                 return 1;
01137         }
01138         pstrcat(mask,p);
01139 
01140         if (recurse) {
01141                 pstring ddir;
01142                 pstring ddir2;
01143                 struct cli_state *targetcli;
01144                 pstring targetname;
01145                 *ddir2 = 0;
01146                 
01147                 if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
01148                         return 1;
01149                 }
01150 
01151                 pstrcpy(ddir,targetname);
01152                 trim_char(ddir,'.','\0');
01153                 p = strtok(ddir,"/\\");
01154                 while (p) {
01155                         pstrcat(ddir2,p);
01156                         if (!cli_chkpath(targetcli, ddir2)) { 
01157                                 do_mkdir(ddir2);
01158                         }
01159                         pstrcat(ddir2,CLI_DIRSEP_STR);
01160                         p = strtok(NULL,"/\\");
01161                 }        
01162         } else {
01163                 do_mkdir(mask);
01164         }
01165         
01166         return 0;
01167 }
01168 
01169 /****************************************************************************
01170  Show alt name.
01171 ****************************************************************************/
01172 
01173 static int cmd_altname(void)
01174 {
01175         pstring name;
01176         pstring buf;
01177         char *p=buf;
01178   
01179         pstrcpy(name,cur_dir);
01180 
01181         if (!next_token_nr(NULL,p,NULL,sizeof(buf))) {
01182                 d_printf("altname <file>\n");
01183                 return 1;
01184         }
01185         pstrcat(name,p);
01186 
01187         do_altname(name);
01188 
01189         return 0;
01190 }
01191 
01192 /****************************************************************************
01193  Put a single file.
01194 ****************************************************************************/
01195 
01196 static int do_put(char *rname, char *lname, BOOL reput)
01197 {
01198         int fnum;
01199         XFILE *f;
01200         SMB_OFF_T start = 0;
01201         off_t nread = 0;
01202         char *buf = NULL;
01203         int maxwrite = io_bufsize;
01204         int rc = 0;
01205         struct timeval tp_start;
01206         struct cli_state *targetcli;
01207         pstring targetname;
01208         
01209         if ( !cli_resolve_path( "", cli, rname, &targetcli, targetname ) ) {
01210                 d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
01211                 return 1;
01212         }
01213         
01214         GetTimeOfDay(&tp_start);
01215 
01216         if (reput) {
01217                 fnum = cli_open(targetcli, targetname, O_RDWR|O_CREAT, DENY_NONE);
01218                 if (fnum >= 0) {
01219                         if (!cli_qfileinfo(targetcli, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL) &&
01220                             !cli_getattrE(targetcli, fnum, NULL, &start, NULL, NULL, NULL)) {
01221                                 d_printf("getattrib: %s\n",cli_errstr(cli));
01222                                 return 1;
01223                         }
01224                 }
01225         } else {
01226                 fnum = cli_open(targetcli, targetname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
01227         }
01228   
01229         if (fnum == -1) {
01230                 d_printf("%s opening remote file %s\n",cli_errstr(targetcli),rname);
01231                 return 1;
01232         }
01233 
01234         /* allow files to be piped into smbclient
01235            jdblair 24.jun.98
01236 
01237            Note that in this case this function will exit(0) rather
01238            than returning. */
01239         if (!strcmp(lname, "-")) {
01240                 f = x_stdin;
01241                 /* size of file is not known */
01242         } else {
01243                 f = x_fopen(lname,O_RDONLY, 0);
01244                 if (f && reput) {
01245                         if (x_tseek(f, start, SEEK_SET) == -1) {
01246                                 d_printf("Error seeking local file\n");
01247                                 return 1;
01248                         }
01249                 }
01250         }
01251 
01252         if (!f) {
01253                 d_printf("Error opening local file %s\n",lname);
01254                 return 1;
01255         }
01256   
01257         DEBUG(1,("putting file %s as %s ",lname,
01258                  rname));
01259   
01260         buf = (char *)SMB_MALLOC(maxwrite);
01261         if (!buf) {
01262                 d_printf("ERROR: Not enough memory!\n");
01263                 return 1;
01264         }
01265         while (!x_feof(f)) {
01266                 int n = maxwrite;
01267                 int ret;
01268 
01269                 if ((n = readfile(buf,n,f)) < 1) {
01270                         if((n == 0) && x_feof(f))
01271                                 break; /* Empty local file. */
01272 
01273                         d_printf("Error reading local file: %s\n", strerror(errno));
01274                         rc = 1;
01275                         break;
01276                 }
01277 
01278                 ret = cli_write(targetcli, fnum, 0, buf, nread + start, n);
01279 
01280                 if (n != ret) {
01281                         d_printf("Error writing file: %s\n", cli_errstr(cli));
01282                         rc = 1;
01283                         break;
01284                 } 
01285 
01286                 nread += n;
01287         }
01288 
01289         if (!cli_close(targetcli, fnum)) {
01290                 d_printf("%s closing remote file %s\n",cli_errstr(cli),rname);
01291                 x_fclose(f);
01292                 SAFE_FREE(buf);
01293                 return 1;
01294         }
01295 
01296         
01297         if (f != x_stdin) {
01298                 x_fclose(f);
01299         }
01300 
01301         SAFE_FREE(buf);
01302 
01303         {
01304                 struct timeval tp_end;
01305                 int this_time;
01306                 
01307                 GetTimeOfDay(&tp_end);
01308                 this_time = 
01309                         (tp_end.tv_sec - tp_start.tv_sec)*1000 +
01310                         (tp_end.tv_usec - tp_start.tv_usec)/1000;
01311                 put_total_time_ms += this_time;
01312                 put_total_size += nread;
01313                 
01314                 DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
01315                          nread / (1.024*this_time + 1.0e-4),
01316                          put_total_size / (1.024*put_total_time_ms)));
01317         }
01318 
01319         if (f == x_stdin) {
01320                 cli_cm_shutdown();
01321                 exit(0);
01322         }
01323         
01324         return rc;
01325 }
01326 
01327 /****************************************************************************
01328  Put a file.
01329 ****************************************************************************/
01330 
01331 static int cmd_put(void)
01332 {
01333         pstring lname;
01334         pstring rname;
01335         pstring buf;
01336         char *p=buf;
01337         
01338         pstrcpy(rname,cur_dir);
01339   
01340         if (!next_token_nr(NULL,p,NULL,sizeof(buf))) {
01341                 d_printf("put <filename>\n");
01342                 return 1;
01343         }
01344         pstrcpy(lname,p);
01345   
01346         if (next_token_nr(NULL,p,NULL,sizeof(buf)))
01347                 pstrcat(rname,p);      
01348         else
01349                 pstrcat(rname,lname);
01350         
01351         clean_name(rname);
01352 
01353         {
01354                 SMB_STRUCT_STAT st;
01355                 /* allow '-' to represent stdin
01356                    jdblair, 24.jun.98 */
01357                 if (!file_exist(lname,&st) &&
01358                     (strcmp(lname,"-"))) {
01359                         d_printf("%s does not exist\n",lname);
01360                         return 1;
01361                 }
01362         }
01363 
01364         return do_put(rname, lname, False);
01365 }
01366 
01367 /*************************************
01368  File list structure.
01369 *************************************/
01370 
01371 static struct file_list {
01372         struct file_list *prev, *next;
01373         char *file_path;
01374         BOOL isdir;
01375 } *file_list;
01376 
01377 /****************************************************************************
01378  Free a file_list structure.
01379 ****************************************************************************/
01380 
01381 static void free_file_list (struct file_list *list_head)
01382 {
01383         struct file_list *list, *next;
01384         
01385         for (list = list_head; list; list = next) {
01386                 next = list->next;
01387                 DLIST_REMOVE(list_head, list);
01388                 SAFE_FREE(list->file_path);
01389                 SAFE_FREE(list);
01390         }
01391 }
01392 
01393 /****************************************************************************
01394  Seek in a directory/file list until you get something that doesn't start with
01395  the specified name.
01396 ****************************************************************************/
01397 
01398 static BOOL seek_list(struct file_list *list, char *name)
01399 {
01400         while (list) {
01401                 trim_string(list->file_path,"./","\n");
01402                 if (strncmp(list->file_path, name, strlen(name)) != 0) {
01403                         return(True);
01404                 }
01405                 list = list->next;
01406         }
01407       
01408         return(False);
01409 }
01410 
01411 /****************************************************************************
01412  Set the file selection mask.
01413 ****************************************************************************/
01414 
01415 static int cmd_select(void)
01416 {
01417         pstrcpy(fileselection,"");
01418         next_token_nr(NULL,fileselection,NULL,sizeof(fileselection));
01419 
01420         return 0;
01421 }
01422 
01423 /****************************************************************************
01424   Recursive file matching function act as find
01425   match must be always set to True when calling this function
01426 ****************************************************************************/
01427 
01428 static int file_find(struct file_list **list, const char *directory, 
01429                       const char *expression, BOOL match)
01430 {
01431         SMB_STRUCT_DIR *dir;
01432         struct file_list *entry;
01433         struct stat statbuf;
01434         int ret;
01435         char *path;
01436         BOOL isdir;
01437         const char *dname;
01438 
01439         dir = sys_opendir(directory);
01440         if (!dir)
01441                 return -1;
01442         
01443         while ((dname = readdirname(dir))) {
01444                 if (!strcmp("..", dname))
01445                         continue;
01446                 if (!strcmp(".", dname))
01447                         continue;
01448                 
01449                 if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
01450                         continue;
01451                 }
01452 
01453                 isdir = False;
01454                 if (!match || !gen_fnmatch(expression, dname)) {
01455                         if (recurse) {
01456                                 ret = stat(path, &statbuf);
01457                                 if (ret == 0) {
01458                                         if (S_ISDIR(statbuf.st_mode)) {
01459                                                 isdir = True;
01460                                                 ret = file_find(list, path, expression, False);
01461                                         }
01462                                 } else {
01463                                         d_printf("file_find: cannot stat file %s\n", path);
01464                                 }
01465                                 
01466                                 if (ret == -1) {
01467                                         SAFE_FREE(path);
01468                                         sys_closedir(dir);
01469                                         return -1;
01470                                 }
01471                         }
01472                         entry = SMB_MALLOC_P(struct file_list);
01473                         if (!entry) {
01474                                 d_printf("Out of memory in file_find\n");
01475                                 sys_closedir(dir);
01476                                 return -1;
01477                         }
01478                         entry->file_path = path;
01479                         entry->isdir = isdir;
01480                         DLIST_ADD(*list, entry);
01481                 } else {
01482                         SAFE_FREE(path);
01483                 }
01484         }
01485 
01486         sys_closedir(dir);
01487         return 0;
01488 }
01489 
01490 /****************************************************************************
01491  mput some files.
01492 ****************************************************************************/
01493 
01494 static int cmd_mput(void)
01495 {
01496         pstring buf;
01497         char *p=buf;
01498         
01499         while (next_token_nr(NULL,p,NULL,sizeof(buf))) {
01500                 int ret;
01501                 struct file_list *temp_list;
01502                 char *quest, *lname, *rname;
01503         
01504                 file_list = NULL;
01505 
01506                 ret = file_find(&file_list, ".", p, True);
01507                 if (ret) {
01508                         free_file_list(file_list);
01509                         continue;
01510                 }
01511                 
01512                 quest = NULL;
01513                 lname = NULL;
01514                 rname = NULL;
01515                                 
01516                 for (temp_list = file_list; temp_list; 
01517                      temp_list = temp_list->next) {
01518 
01519                         SAFE_FREE(lname);
01520                         if (asprintf(&lname, "%s/", temp_list->file_path) <= 0)
01521                                 continue;
01522                         trim_string(lname, "./", "/");
01523                         
01524                         /* check if it's a directory */
01525                         if (temp_list->isdir) {
01526                                 /* if (!recurse) continue; */
01527                                 
01528                                 SAFE_FREE(quest);
01529                                 if (asprintf(&quest, "Put directory %s? ", lname) < 0) break;
01530                                 if (prompt && !yesno(quest)) { /* No */
01531                                         /* Skip the directory */
01532                                         lname[strlen(lname)-1] = '/';
01533                                         if (!seek_list(temp_list, lname))
01534                                                 break;              
01535                                 } else { /* Yes */
01536                                         SAFE_FREE(rname);
01537                                         if(asprintf(&rname, "%s%s", cur_dir, lname) < 0) break;
01538                                         dos_format(rname);
01539                                         if (!cli_chkpath(cli, rname) && 
01540                                             !do_mkdir(rname)) {
01541                                                 DEBUG (0, ("Unable to make dir, skipping..."));
01542                                                 /* Skip the directory */
01543                                                 lname[strlen(lname)-1] = '/';
01544                                                 if (!seek_list(temp_list, lname))
01545                                                         break;
01546                                         }
01547                                 }
01548                                 continue;
01549                         } else {
01550                                 SAFE_FREE(quest);
01551                                 if (asprintf(&quest,"Put file %s? ", lname) < 0) break;
01552                                 if (prompt && !yesno(quest)) /* No */
01553                                         continue;
01554                                 
01555                                 /* Yes */
01556                                 SAFE_FREE(rname);
01557                                 if (asprintf(&rname, "%s%s", cur_dir, lname) < 0) break;
01558                         }
01559 
01560                         dos_format(rname);
01561 
01562                         do_put(rname, lname, False);
01563                 }
01564                 free_file_list(file_list);
01565                 SAFE_FREE(quest);
01566                 SAFE_FREE(lname);
01567                 SAFE_FREE(rname);
01568         }
01569 
01570         return 0;
01571 }
01572 
01573 /****************************************************************************
01574  Cancel a print job.
01575 ****************************************************************************/
01576 
01577 static int do_cancel(int job)
01578 {
01579         if (cli_printjob_del(cli, job)) {
01580                 d_printf("Job %d cancelled\n",job);
01581                 return 0;
01582         } else {
01583                 d_printf("Error cancelling job %d : %s\n",job,cli_errstr(cli));
01584                 return 1;
01585         }
01586 }
01587 
01588 /****************************************************************************
01589  Cancel a print job.
01590 ****************************************************************************/
01591 
01592 static int cmd_cancel(void)
01593 {
01594         pstring buf;
01595         int job; 
01596 
01597         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01598                 d_printf("cancel <jobid> ...\n");
01599                 return 1;
01600         }
01601         do {
01602                 job = atoi(buf);
01603                 do_cancel(job);
01604         } while (next_token_nr(NULL,buf,NULL,sizeof(buf)));
01605         
01606         return 0;
01607 }
01608 
01609 /****************************************************************************
01610  Print a file.
01611 ****************************************************************************/
01612 
01613 static int cmd_print(void)
01614 {
01615         pstring lname;
01616         pstring rname;
01617         char *p;
01618 
01619         if (!next_token_nr(NULL,lname,NULL, sizeof(lname))) {
01620                 d_printf("print <filename>\n");
01621                 return 1;
01622         }
01623 
01624         pstrcpy(rname,lname);
01625         p = strrchr_m(rname,'/');
01626         if (p) {
01627                 slprintf(rname, sizeof(rname)-1, "%s-%d", p+1, (int)sys_getpid());
01628         }
01629 
01630         if (strequal(lname,"-")) {
01631                 slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)sys_getpid());
01632         }
01633 
01634         return do_put(rname, lname, False);
01635 }
01636 
01637 /****************************************************************************
01638  Show a print queue entry.
01639 ****************************************************************************/
01640 
01641 static void queue_fn(struct print_job_info *p)
01642 {
01643         d_printf("%-6d   %-9d    %s\n", (int)p->id, (int)p->size, p->name);
01644 }
01645 
01646 /****************************************************************************
01647  Show a print queue.
01648 ****************************************************************************/
01649 
01650 static int cmd_queue(void)
01651 {
01652         cli_print_queue(cli, queue_fn);
01653         
01654         return 0;
01655 }
01656 
01657 /****************************************************************************
01658  Delete some files.
01659 ****************************************************************************/
01660 
01661 static void do_del(file_info *finfo)
01662 {
01663         pstring mask;
01664 
01665         pstr_sprintf( mask, "%s%c%s", finfo->dir, CLI_DIRSEP_CHAR, finfo->name );
01666 
01667         if (finfo->mode & aDIR) 
01668                 return;
01669 
01670         if (!cli_unlink(finfo->cli, mask)) {
01671                 d_printf("%s deleting remote file %s\n",cli_errstr(finfo->cli),mask);
01672         }
01673 }
01674 
01675 /****************************************************************************
01676  Delete some files.
01677 ****************************************************************************/
01678 
01679 static int cmd_del(void)
01680 {
01681         pstring mask;
01682         pstring buf;
01683         uint16 attribute = aSYSTEM | aHIDDEN;
01684 
01685         if (recurse)
01686                 attribute |= aDIR;
01687         
01688         pstrcpy(mask,cur_dir);
01689         
01690         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01691                 d_printf("del <filename>\n");
01692                 return 1;
01693         }
01694         pstrcat(mask,buf);
01695 
01696         do_list(mask, attribute,do_del,False,False);
01697         
01698         return 0;
01699 }
01700 
01701 /****************************************************************************
01702  Wildcard delete some files.
01703 ****************************************************************************/
01704 
01705 static int cmd_wdel(void)
01706 {
01707         pstring mask;
01708         pstring buf;
01709         uint16 attribute;
01710         struct cli_state *targetcli;
01711         pstring targetname;
01712 
01713         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01714                 d_printf("wdel 0x<attrib> <wcard>\n");
01715                 return 1;
01716         }
01717 
01718         attribute = (uint16)strtol(buf, (char **)NULL, 16);
01719 
01720         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01721                 d_printf("wdel 0x<attrib> <wcard>\n");
01722                 return 1;
01723         }
01724 
01725         pstrcpy(mask,cur_dir);
01726         pstrcat(mask,buf);
01727 
01728         if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
01729                 d_printf("cmd_wdel %s: %s\n", mask, cli_errstr(cli));
01730                 return 1;
01731         }
01732         
01733         if (!cli_unlink_full(targetcli, targetname, attribute)) {
01734                 d_printf("%s deleting remote files %s\n",cli_errstr(targetcli),targetname);
01735         }
01736         return 0;
01737 }
01738 
01739 /****************************************************************************
01740 ****************************************************************************/
01741 
01742 static int cmd_open(void)
01743 {
01744         pstring mask;
01745         pstring buf;
01746         struct cli_state *targetcli;
01747         pstring targetname;
01748         int fnum;
01749 
01750         pstrcpy(mask,cur_dir);
01751         
01752         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01753                 d_printf("open <filename>\n");
01754                 return 1;
01755         }
01756         pstrcat(mask,buf);
01757 
01758         if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
01759                 d_printf("open %s: %s\n", mask, cli_errstr(cli));
01760                 return 1;
01761         }
01762         
01763         fnum = cli_nt_create(targetcli, targetname, FILE_READ_DATA|FILE_WRITE_DATA);
01764         if (fnum == -1) {
01765                 fnum = cli_nt_create(targetcli, targetname, FILE_READ_DATA);
01766                 if (fnum != -1) {
01767                         d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
01768                 } else {
01769                         d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
01770                 }
01771         } else {
01772                 d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
01773         }
01774 
01775         return 0;
01776 }
01777 
01778 /****************************************************************************
01779 ****************************************************************************/
01780 
01781 static int cmd_posix_open(void)
01782 {
01783         pstring mask;
01784         pstring buf;
01785         struct cli_state *targetcli;
01786         pstring targetname;
01787         mode_t mode;
01788         int fnum;
01789 
01790         pstrcpy(mask,cur_dir);
01791         
01792         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01793                 d_printf("posix_open <filename> 0<mode>\n");
01794                 return 1;
01795         }
01796         pstrcat(mask,buf);
01797         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01798                 d_printf("posix_open <filename> 0<mode>\n");
01799                 return 1;
01800         }
01801         mode = (mode_t)strtol(buf, (char **)NULL, 8);
01802 
01803         if (!cli_resolve_path( "", cli, mask, &targetcli, targetname )) {
01804                 d_printf("posix_open %s: %s\n", mask, cli_errstr(cli));
01805                 return 1;
01806         }
01807         
01808         fnum = cli_posix_open(targetcli, targetname, O_CREAT|O_RDWR, mode);
01809         if (fnum == -1) {
01810                 fnum = cli_posix_open(targetcli, targetname, O_CREAT|O_RDONLY, mode);
01811                 if (fnum != -1) {
01812                         d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
01813                 } else {
01814                         d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
01815                 }
01816         } else {
01817                 d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
01818         }
01819 
01820         return 0;
01821 }
01822 
01823 static int cmd_posix_mkdir(void)
01824 {
01825         pstring mask;
01826         pstring buf;
01827         struct cli_state *targetcli;
01828         pstring targetname;
01829         mode_t mode;
01830         int fnum;
01831 
01832         pstrcpy(mask,cur_dir);
01833         
01834         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01835                 d_printf("posix_mkdir <filename> 0<mode>\n");
01836                 return 1;
01837         }
01838         pstrcat(mask,buf);
01839         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01840                 d_printf("posix_mkdir <filename> 0<mode>\n");
01841                 return 1;
01842         }
01843         mode = (mode_t)strtol(buf, (char **)NULL, 8);
01844 
01845         if (!cli_resolve_path( "", cli, mask, &targetcli, targetname )) {
01846                 d_printf("posix_mkdir %s: %s\n", mask, cli_errstr(cli));
01847                 return 1;
01848         }
01849 
01850         fnum = cli_posix_mkdir(targetcli, targetname, mode);
01851         if (fnum == -1) {
01852                 d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
01853         } else {
01854                 d_printf("posix_mkdir created directory %s\n", targetname);
01855         }
01856 
01857         return 0;
01858 }
01859 
01860 static int cmd_posix_unlink(void)
01861 {
01862         pstring mask;
01863         pstring buf;
01864         struct cli_state *targetcli;
01865         pstring targetname;
01866 
01867         pstrcpy(mask,cur_dir);
01868         
01869         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01870                 d_printf("posix_unlink <filename>\n");
01871                 return 1;
01872         }
01873         pstrcat(mask,buf);
01874 
01875         if (!cli_resolve_path( "", cli, mask, &targetcli, targetname )) {
01876                 d_printf("posix_unlink %s: %s\n", mask, cli_errstr(cli));
01877                 return 1;
01878         }
01879         
01880         if (!cli_posix_unlink(targetcli, targetname)) {
01881                 d_printf("Failed to unlink file %s. %s\n", targetname, cli_errstr(cli));
01882         } else {
01883                 d_printf("posix_unlink deleted file %s\n", targetname);
01884         }
01885 
01886         return 0;
01887 }
01888 
01889 static int cmd_posix_rmdir(void)
01890 {
01891         pstring mask;
01892         pstring buf;
01893         struct cli_state *targetcli;
01894         pstring targetname;
01895 
01896         pstrcpy(mask,cur_dir);
01897         
01898         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01899                 d_printf("posix_rmdir <filename>\n");
01900                 return 1;
01901         }
01902         pstrcat(mask,buf);
01903 
01904         if (!cli_resolve_path( "", cli, mask, &targetcli, targetname)) {
01905                 d_printf("posix_rmdir %s: %s\n", mask, cli_errstr(cli));
01906                 return 1;
01907         }
01908         
01909         if (!cli_posix_rmdir(targetcli, targetname)) {
01910                 d_printf("Failed to unlink directory %s. %s\n", targetname, cli_errstr(cli));
01911         } else {
01912                 d_printf("posix_rmdir deleted directory %s\n", targetname);
01913         }
01914 
01915         return 0;
01916 }
01917 
01918 static int cmd_close(void)
01919 {
01920         fstring buf;
01921         int fnum;
01922 
01923         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01924                 d_printf("close <fnum>\n");
01925                 return 1;
01926         }
01927 
01928         fnum = atoi(buf);
01929         /* We really should use the targetcli here.... */
01930         if (!cli_close(cli, fnum)) {
01931                 d_printf("close %d: %s\n", fnum, cli_errstr(cli));
01932                 return 1;
01933         }
01934         return 0;
01935 }
01936 
01937 static int cmd_posix(void)
01938 {
01939         uint16 major, minor;
01940         uint32 caplow, caphigh;
01941         pstring caps;
01942 
01943         if (!SERVER_HAS_UNIX_CIFS(cli)) {
01944                 d_printf("Server doesn't support UNIX CIFS extensions.\n");
01945                 return 1;
01946         }
01947 
01948         if (!cli_unix_extensions_version(cli, &major, &minor, &caplow, &caphigh)) {
01949                 d_printf("Can't get UNIX CIFS extensions version from server.\n");
01950                 return 1;
01951         }
01952 
01953         d_printf("Server supports CIFS extensions %u.%u\n", (unsigned int)major, (unsigned int)minor);
01954 
01955         *caps = '\0';
01956         if (caplow & CIFS_UNIX_FCNTL_LOCKS_CAP) {
01957                 pstrcat(caps, "locks ");
01958         }
01959         if (caplow & CIFS_UNIX_POSIX_ACLS_CAP) {
01960                 pstrcat(caps, "acls ");
01961         }
01962         if (caplow & CIFS_UNIX_XATTTR_CAP) {
01963                 pstrcat(caps, "eas ");
01964         }
01965         if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
01966                 pstrcat(caps, "pathnames ");
01967         }
01968         if (caplow & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) {
01969                 pstrcat(caps, "posix_path_operations ");
01970         }
01971 
01972         if (strlen(caps) > 0 && caps[strlen(caps)-1] == ' ') {
01973                 caps[strlen(caps)-1] = '\0';
01974         }
01975 
01976         if (!cli_set_unix_extensions_capabilities(cli, major, minor, caplow, caphigh)) {
01977                 d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n", cli_errstr(cli));
01978                 return 1;
01979         }
01980 
01981         d_printf("Selecting server supported CIFS capabilities %s\n", caps);
01982 
01983         if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
01984                 CLI_DIRSEP_CHAR = '/';
01985                 *CLI_DIRSEP_STR = '/';
01986                 pstrcpy(cur_dir, CLI_DIRSEP_STR);
01987                 do_cd(cur_dir);
01988         }
01989 
01990         return 0;
01991 }
01992 
01993 static int cmd_lock(void)
01994 {
01995         fstring buf;
01996         SMB_BIG_UINT start, len;
01997         enum brl_type lock_type;
01998         int fnum;
01999 
02000         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02001                 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
02002                 return 1;
02003         }
02004         fnum = atoi(buf);
02005 
02006         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02007                 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
02008                 return 1;
02009         }
02010 
02011         if (*buf == 'r' || *buf == 'R') {
02012                 lock_type = READ_LOCK;
02013         } else if (*buf == 'w' || *buf == 'W') {
02014                 lock_type = WRITE_LOCK;
02015         } else {
02016                 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
02017                 return 1;
02018         }
02019 
02020         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02021                 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
02022                 return 1;
02023         }
02024 
02025         start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
02026 
02027         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02028                 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
02029                 return 1;
02030         }
02031 
02032         len = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
02033 
02034         if (!cli_posix_lock(cli, fnum, start, len, True, lock_type)) {
02035                 d_printf("lock failed %d: %s\n", fnum, cli_errstr(cli));
02036         }
02037 
02038         return 0;
02039 }
02040 
02041 static int cmd_unlock(void)
02042 {
02043         fstring buf;
02044         SMB_BIG_UINT start, len;
02045         int fnum;
02046 
02047         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02048                 d_printf("unlock <fnum> <hex-start> <hex-len>\n");
02049                 return 1;
02050         }
02051         fnum = atoi(buf);
02052 
02053         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02054                 d_printf("unlock <fnum> <hex-start> <hex-len>\n");
02055                 return 1;
02056         }
02057 
02058         start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
02059 
02060         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02061                 d_printf("unlock <fnum> <hex-start> <hex-len>\n");
02062                 return 1;
02063         }
02064 
02065         len = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
02066 
02067         if (!cli_posix_unlock(cli, fnum, start, len)) {
02068                 d_printf("unlock failed %d: %s\n", fnum, cli_errstr(cli));
02069         }
02070 
02071         return 0;
02072 }
02073 
02074 
02075 /****************************************************************************
02076  Remove a directory.
02077 ****************************************************************************/
02078 
02079 static int cmd_rmdir(void)
02080 {
02081         pstring mask;
02082         pstring buf;
02083         struct cli_state *targetcli;
02084         pstring targetname;
02085   
02086         pstrcpy(mask,cur_dir);
02087         
02088         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02089                 d_printf("rmdir <dirname>\n");
02090                 return 1;
02091         }
02092         pstrcat(mask,buf);
02093 
02094         if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
02095                 d_printf("rmdir %s: %s\n", mask, cli_errstr(cli));
02096                 return 1;
02097         }
02098         
02099         if (!cli_rmdir(targetcli, targetname)) {
02100                 d_printf("%s removing remote directory file %s\n",
02101                          cli_errstr(targetcli),mask);
02102         }
02103         
02104         return 0;
02105 }
02106 
02107 /****************************************************************************
02108  UNIX hardlink.
02109 ****************************************************************************/
02110 
02111 static int cmd_link(void)
02112 {
02113         pstring oldname,newname;
02114         pstring buf,buf2;
02115         struct cli_state *targetcli;
02116         pstring targetname;
02117   
02118         pstrcpy(oldname,cur_dir);
02119         pstrcpy(newname,cur_dir);
02120   
02121         if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) || 
02122             !next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
02123                 d_printf("link <oldname> <newname>\n");
02124                 return 1;
02125         }
02126 
02127         pstrcat(oldname,buf);
02128         pstrcat(newname,buf2);
02129 
02130         if ( !cli_resolve_path( "", cli, oldname, &targetcli, targetname ) ) {
02131                 d_printf("link %s: %s\n", oldname, cli_errstr(cli));
02132                 return 1;
02133         }
02134         
02135         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
02136                 d_printf("Server doesn't support UNIX CIFS calls.\n");
02137                 return 1;
02138         }
02139         
02140         if (!cli_unix_hardlink(targetcli, targetname, newname)) {
02141                 d_printf("%s linking files (%s -> %s)\n", cli_errstr(targetcli), newname, oldname);
02142                 return 1;
02143         }  
02144 
02145         return 0;
02146 }
02147 
02148 /****************************************************************************
02149  UNIX symlink.
02150 ****************************************************************************/
02151 
02152 static int cmd_symlink(void)
02153 {
02154         pstring oldname,newname;
02155         pstring buf,buf2;
02156         struct cli_state *targetcli;
02157         pstring targetname;
02158   
02159         if (!SERVER_HAS_UNIX_CIFS(cli)) {
02160                 d_printf("Server doesn't support UNIX CIFS calls.\n");
02161                 return 1;
02162         }
02163 
02164         pstrcpy(newname,cur_dir);
02165         
02166         if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) || 
02167             !next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
02168                 d_printf("symlink <oldname> <newname>\n");
02169                 return 1;
02170         }
02171 
02172         pstrcpy(oldname,buf);
02173         pstrcat(newname,buf2);
02174 
02175         if ( !cli_resolve_path( "", cli, oldname, &targetcli, targetname ) ) {
02176                 d_printf("link %s: %s\n", oldname, cli_errstr(cli));
02177                 return 1;
02178         }
02179 
02180         if (!cli_unix_symlink(targetcli, targetname, newname)) {
02181                 d_printf("%s symlinking files (%s -> %s)\n",
02182                         cli_errstr(targetcli), newname, targetname);
02183                 return 1;
02184         } 
02185 
02186         return 0;
02187 }
02188 
02189 /****************************************************************************
02190  UNIX chmod.
02191 ****************************************************************************/
02192 
02193 static int cmd_chmod(void)
02194 {
02195         pstring src;
02196         mode_t mode;
02197         pstring buf, buf2;
02198         struct cli_state *targetcli;
02199         pstring targetname;
02200   
02201         pstrcpy(src,cur_dir);
02202         
02203         if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) || 
02204             !next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
02205                 d_printf("chmod mode file\n");
02206                 return 1;
02207         }
02208 
02209         mode = (mode_t)strtol(buf, NULL, 8);
02210         pstrcat(src,buf2);
02211 
02212         if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
02213                 d_printf("chmod %s: %s\n", src, cli_errstr(cli));
02214                 return 1;
02215         }
02216         
02217         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
02218                 d_printf("Server doesn't support UNIX CIFS calls.\n");
02219                 return 1;
02220         }
02221         
02222         if (!cli_unix_chmod(targetcli, targetname, mode)) {
02223                 d_printf("%s chmod file %s 0%o\n",
02224                         cli_errstr(targetcli), src, (unsigned int)mode);
02225                 return 1;
02226         } 
02227 
02228         return 0;
02229 }
02230 
02231 static const char *filetype_to_str(mode_t mode)
02232 {
02233         if (S_ISREG(mode)) {
02234                 return "regular file";
02235         } else if (S_ISDIR(mode)) {
02236                 return "directory";
02237         } else 
02238 #ifdef S_ISCHR
02239         if (S_ISCHR(mode)) {
02240                 return "character device";
02241         } else
02242 #endif
02243 #ifdef S_ISBLK
02244         if (S_ISBLK(mode)) {
02245                 return "block device";
02246         } else
02247 #endif
02248 #ifdef S_ISFIFO
02249         if (S_ISFIFO(mode)) {
02250                 return "fifo";
02251         } else
02252 #endif
02253 #ifdef S_ISLNK
02254         if (S_ISLNK(mode)) {
02255                 return "symbolic link";
02256         } else
02257 #endif
02258 #ifdef S_ISSOCK
02259         if (S_ISSOCK(mode)) {
02260                 return "socket";
02261         } else
02262 #endif
02263         return "";
02264 }
02265 
02266 static char rwx_to_str(mode_t m, mode_t bt, char ret)
02267 {
02268         if (m & bt) {
02269                 return ret;
02270         } else {
02271                 return '-';
02272         }
02273 }
02274 
02275 static char *unix_mode_to_str(char *s, mode_t m)
02276 {
02277         char *p = s;
02278         const char *str = filetype_to_str(m);
02279 
02280         switch(str[0]) {
02281                 case 'd':
02282                         *p++ = 'd';
02283                         break;
02284                 case 'c':
02285                         *p++ = 'c';
02286                         break;
02287                 case 'b':
02288                         *p++ = 'b';
02289                         break;
02290                 case 'f':
02291                         *p++ = 'p';
02292                         break;
02293                 case 's':
02294                         *p++ = str[1] == 'y' ? 'l' : 's';
02295                         break;
02296                 case 'r':
02297                 default:
02298                         *p++ = '-';
02299                         break;
02300         }
02301         *p++ = rwx_to_str(m, S_IRUSR, 'r');
02302         *p++ = rwx_to_str(m, S_IWUSR, 'w');
02303         *p++ = rwx_to_str(m, S_IXUSR, 'x');
02304         *p++ = rwx_to_str(m, S_IRGRP, 'r');
02305         *p++ = rwx_to_str(m, S_IWGRP, 'w');
02306         *p++ = rwx_to_str(m, S_IXGRP, 'x');
02307         *p++ = rwx_to_str(m, S_IROTH, 'r');
02308         *p++ = rwx_to_str(m, S_IWOTH, 'w');
02309         *p++ = rwx_to_str(m, S_IXOTH, 'x');
02310         *p++ = '\0';
02311         return s;
02312 }
02313 
02314 /****************************************************************************
02315  Utility function for UNIX getfacl.
02316 ****************************************************************************/
02317 
02318 static char *perms_to_string(fstring permstr, unsigned char perms)
02319 {
02320         fstrcpy(permstr, "---");
02321         if (perms & SMB_POSIX_ACL_READ) {
02322                 permstr[0] = 'r';
02323         }
02324         if (perms & SMB_POSIX_ACL_WRITE) {
02325                 permstr[1] = 'w';
02326         }
02327         if (perms & SMB_POSIX_ACL_EXECUTE) {
02328                 permstr[2] = 'x';
02329         }
02330         return permstr;
02331 }
02332 
02333 /****************************************************************************
02334  UNIX getfacl.
02335 ****************************************************************************/
02336 
02337 static int cmd_getfacl(void)
02338 {
02339         pstring src, name;
02340         uint16 major, minor;
02341         uint32 caplow, caphigh;
02342         char *retbuf = NULL;
02343         size_t rb_size = 0;
02344         SMB_STRUCT_STAT sbuf;
02345         uint16 num_file_acls = 0;
02346         uint16 num_dir_acls = 0;
02347         uint16 i;
02348         struct cli_state *targetcli;
02349         pstring targetname;
02350  
02351         pstrcpy(src,cur_dir);
02352         
02353         if (!next_token_nr(NULL,name,NULL,sizeof(name))) {
02354                 d_printf("stat file\n");
02355                 return 1;
02356         }
02357 
02358         pstrcat(src,name);
02359         
02360         if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
02361                 d_printf("stat %s: %s\n", src, cli_errstr(cli));
02362                 return 1;
02363         }
02364         
02365         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
02366                 d_printf("Server doesn't support UNIX CIFS calls.\n");
02367                 return 1;
02368         }
02369         
02370         if (!cli_unix_extensions_version(targetcli, &major, &minor, &caplow, &caphigh)) {
02371                 d_printf("Can't get UNIX CIFS version from server.\n");
02372                 return 1;
02373         }
02374 
02375         if (!(caplow & CIFS_UNIX_POSIX_ACLS_CAP)) {
02376                 d_printf("This server supports UNIX extensions but doesn't support POSIX ACLs.\n");
02377                 return 1;
02378         }
02379 
02380         if (!cli_unix_stat(targetcli, targetname, &sbuf)) {
02381                 d_printf("%s getfacl doing a stat on file %s\n",
02382                         cli_errstr(targetcli), src);
02383                 return 1;
02384         } 
02385 
02386         if (!cli_unix_getfacl(targetcli, targetname, &rb_size, &retbuf)) {
02387                 d_printf("%s getfacl file %s\n",
02388                         cli_errstr(targetcli), src);
02389                 return 1;
02390         } 
02391 
02392         /* ToDo : Print out the ACL values. */
02393         if (SVAL(retbuf,0) != SMB_POSIX_ACL_VERSION || rb_size < 6) {
02394                 d_printf("getfacl file %s, unknown POSIX acl version %u.\n",
02395                         src, (unsigned int)CVAL(retbuf,0) );
02396                 SAFE_FREE(retbuf);
02397                 return 1;
02398         }
02399 
02400         num_file_acls = SVAL(retbuf,2);
02401         num_dir_acls = SVAL(retbuf,4);
02402         if (rb_size != SMB_POSIX_ACL_HEADER_SIZE + SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls)) {
02403                 d_printf("getfacl file %s, incorrect POSIX acl buffer size (should be %u, was %u).\n",
02404                         src,
02405                         (unsigned int)(SMB_POSIX_ACL_HEADER_SIZE + SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls)),
02406                         (unsigned int)rb_size);
02407 
02408                 SAFE_FREE(retbuf);
02409                 return 1;
02410         }
02411 
02412         d_printf("# file: %s\n", src);
02413         d_printf("# owner: %u\n# group: %u\n", (unsigned int)sbuf.st_uid, (unsigned int)sbuf.st_gid);
02414 
02415         if (num_file_acls == 0 && num_dir_acls == 0) {
02416                 d_printf("No acls found.\n");
02417         }
02418 
02419         for (i = 0; i < num_file_acls; i++) {
02420                 uint32 uorg;
02421                 fstring permstring;
02422                 unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE));
02423                 unsigned char perms = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+1);
02424 
02425                 switch(tagtype) {
02426                         case SMB_POSIX_ACL_USER_OBJ:
02427                                 d_printf("user::");
02428                                 break;
02429                         case SMB_POSIX_ACL_USER:
02430                                 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
02431                                 d_printf("user:%u:", uorg);
02432                                 break;
02433                         case SMB_POSIX_ACL_GROUP_OBJ:
02434                                 d_printf("group::");
02435                                 break;
02436                         case SMB_POSIX_ACL_GROUP:
02437                                 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
02438                                 d_printf("group:%u", uorg);
02439                                 break;
02440                         case SMB_POSIX_ACL_MASK:
02441                                 d_printf("mask::");
02442                                 break;
02443                         case SMB_POSIX_ACL_OTHER:
02444                                 d_printf("other::");
02445                                 break;
02446                         default:
02447                                 d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
02448                                         src, (unsigned int)tagtype );
02449                                 SAFE_FREE(retbuf);
02450                                 return 1;
02451                 }
02452 
02453                 d_printf("%s\n", perms_to_string(permstring, perms));
02454         }
02455 
02456         for (i = 0; i < num_dir_acls; i++) {
02457                 uint32 uorg;
02458                 fstring permstring;
02459                 unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE));
02460                 unsigned char perms = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+1);
02461 
02462                 switch(tagtype) {
02463                         case SMB_POSIX_ACL_USER_OBJ:
02464                                 d_printf("default:user::");
02465                                 break;
02466                         case SMB_POSIX_ACL_USER:
02467                                 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
02468                                 d_printf("default:user:%u:", uorg);
02469                                 break;
02470                         case SMB_POSIX_ACL_GROUP_OBJ:
02471                                 d_printf("default:group::");
02472                                 break;
02473                         case SMB_POSIX_ACL_GROUP:
02474                                 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
02475                                 d_printf("default:group:%u", uorg);
02476                                 break;
02477                         case SMB_POSIX_ACL_MASK:
02478                                 d_printf("default:mask::");
02479                                 break;
02480                         case SMB_POSIX_ACL_OTHER:
02481                                 d_printf("default:other::");
02482                                 break;
02483                         default:
02484                                 d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
02485                                         src, (unsigned int)tagtype );
02486                                 SAFE_FREE(retbuf);
02487                                 return 1;
02488                 }
02489 
02490                 d_printf("%s\n", perms_to_string(permstring, perms));
02491         }
02492 
02493         SAFE_FREE(retbuf);
02494         return 0;
02495 }
02496 
02497 /****************************************************************************
02498  UNIX stat.
02499 ****************************************************************************/
02500 
02501 static int cmd_stat(void)
02502 {
02503         pstring src, name;
02504         fstring mode_str;
02505         SMB_STRUCT_STAT sbuf;
02506         struct cli_state *targetcli;
02507         struct tm *lt;
02508         pstring targetname;
02509  
02510         if (!SERVER_HAS_UNIX_CIFS(cli)) {
02511                 d_printf("Server doesn't support UNIX CIFS calls.\n");
02512                 return 1;
02513         }
02514 
02515         pstrcpy(src,cur_dir);
02516         
02517         if (!next_token_nr(NULL,name,NULL,sizeof(name))) {
02518                 d_printf("stat file\n");
02519                 return 1;
02520         }
02521 
02522         pstrcat(src,name);
02523 
02524         
02525         if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
02526                 d_printf("stat %s: %s\n", src, cli_errstr(cli));
02527                 return 1;
02528         }
02529         
02530         if (!cli_unix_stat(targetcli, targetname, &sbuf)) {
02531                 d_printf("%s stat file %s\n",
02532                         cli_errstr(targetcli), src);
02533                 return 1;
02534         } 
02535 
02536         /* Print out the stat values. */
02537         d_printf("File: %s\n", src);
02538         d_printf("Size: %-12.0f\tBlocks: %u\t%s\n",
02539                 (double)sbuf.st_size,
02540                 (unsigned int)sbuf.st_blocks,
02541                 filetype_to_str(sbuf.st_mode));
02542 
02543 #if defined(S_ISCHR) && defined(S_ISBLK)
02544         if (S_ISCHR(sbuf.st_mode) || S_ISBLK(sbuf.st_mode)) {
02545                 d_printf("Inode: %.0f\tLinks: %u\tDevice type: %u,%u\n",
02546                         (double)sbuf.st_ino,
02547                         (unsigned int)sbuf.st_nlink,
02548                         unix_dev_major(sbuf.st_rdev),
02549                         unix_dev_minor(sbuf.st_rdev));
02550         } else 
02551 #endif
02552                 d_printf("Inode: %.0f\tLinks: %u\n",
02553                         (double)sbuf.st_ino,
02554                         (unsigned int)sbuf.st_nlink);
02555 
02556         d_printf("Access: (0%03o/%s)\tUid: %u\tGid: %u\n",
02557                 ((int)sbuf.st_mode & 0777),
02558                 unix_mode_to_str(mode_str, sbuf.st_mode),
02559                 (unsigned int)sbuf.st_uid, 
02560                 (unsigned int)sbuf.st_gid);
02561 
02562         lt = localtime(&sbuf.st_atime);
02563         if (lt) {
02564                 strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
02565         } else {
02566                 fstrcpy(mode_str, "unknown");
02567         }
02568         d_printf("Access: %s\n", mode_str);
02569 
02570         lt = localtime(&sbuf.st_mtime);
02571         if (lt) {
02572                 strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
02573         } else {
02574                 fstrcpy(mode_str, "unknown");
02575         }
02576         d_printf("Modify: %s\n", mode_str);
02577 
02578         lt = localtime(&sbuf.st_ctime);
02579         if (lt) {
02580                 strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
02581         } else {
02582                 fstrcpy(mode_str, "unknown");
02583         }
02584         d_printf("Change: %s\n", mode_str);
02585         
02586         return 0;
02587 }
02588 
02589 
02590 /****************************************************************************
02591  UNIX chown.
02592 ****************************************************************************/
02593 
02594 static int cmd_chown(void)
02595 {
02596         pstring src;
02597         uid_t uid;
02598         gid_t gid;
02599         pstring buf, buf2, buf3;
02600         struct cli_state *targetcli;
02601         pstring targetname;
02602   
02603         pstrcpy(src,cur_dir);
02604         
02605         if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) || 
02606             !next_token_nr(NULL,buf2,NULL, sizeof(buf2)) ||
02607             !next_token_nr(NULL,buf3,NULL, sizeof(buf3))) {
02608                 d_printf("chown uid gid file\n");
02609                 return 1;
02610         }
02611 
02612         uid = (uid_t)atoi(buf);
02613         gid = (gid_t)atoi(buf2);
02614         pstrcat(src,buf3);
02615 
02616         if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
02617                 d_printf("chown %s: %s\n", src, cli_errstr(cli));
02618                 return 1;
02619         }
02620 
02621         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
02622                 d_printf("Server doesn't support UNIX CIFS calls.\n");
02623                 return 1;
02624         }
02625         
02626         if (!cli_unix_chown(targetcli, targetname, uid, gid)) {
02627                 d_printf("%s chown file %s uid=%d, gid=%d\n",
02628                         cli_errstr(targetcli), src, (int)uid, (int)gid);
02629                 return 1;
02630         } 
02631 
02632         return 0;
02633 }
02634 
02635 /****************************************************************************
02636  Rename some file.
02637 ****************************************************************************/
02638 
02639 static int cmd_rename(void)
02640 {
02641         pstring src,dest;
02642         pstring buf,buf2;
02643         struct cli_state *targetcli;
02644         pstring targetsrc;
02645         pstring targetdest;
02646   
02647         pstrcpy(src,cur_dir);
02648         pstrcpy(dest,cur_dir);
02649         
02650         if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) || 
02651             !next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
02652                 d_printf("rename <src> <dest>\n");
02653                 return 1;
02654         }
02655 
02656         pstrcat(src,buf);
02657         pstrcat(dest,buf2);
02658 
02659         if ( !cli_resolve_path( "", cli, src, &targetcli, targetsrc ) ) {
02660                 d_printf("rename %s: %s\n", src, cli_errstr(cli));
02661                 return 1;
02662         }
02663 
02664         if ( !cli_resolve_path( "", cli, dest, &targetcli, targetdest ) ) {
02665                 d_printf("rename %s: %s\n", dest, cli_errstr(cli));
02666                 return 1;
02667         }
02668 
02669         if (!cli_rename(targetcli, targetsrc, targetdest)) {
02670                 d_printf("%s renaming files %s -> %s \n",
02671                         cli_errstr(targetcli),
02672                         targetsrc,
02673                         targetdest);
02674                 return 1;
02675         }
02676         
02677         return 0;
02678 }
02679 
02680 /****************************************************************************
02681  Print the volume name.
02682 ****************************************************************************/
02683 
02684 static int cmd_volume(void)
02685 {
02686         fstring volname;
02687         uint32 serial_num;
02688         time_t create_date;
02689   
02690         if (!cli_get_fs_volume_info(cli, volname, &serial_num, &create_date)) {
02691                 d_printf("Errr %s getting volume info\n",cli_errstr(cli));
02692                 return 1;
02693         }
02694         
02695         d_printf("Volume: |%s| serial number 0x%x\n", volname, (unsigned int)serial_num);
02696         return 0;
02697 }
02698 
02699 /****************************************************************************
02700  Hard link files using the NT call.
02701 ****************************************************************************/
02702 
02703 static int cmd_hardlink(void)
02704 {
02705         pstring src,dest;
02706         pstring buf,buf2;
02707         struct cli_state *targetcli;
02708         pstring targetname;
02709   
02710         pstrcpy(src,cur_dir);
02711         pstrcpy(dest,cur_dir);
02712         
02713         if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) || 
02714             !next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
02715                 d_printf("hardlink <src> <dest>\n");
02716                 return 1;
02717         }
02718 
02719         pstrcat(src,buf);
02720         pstrcat(dest,buf2);
02721 
02722         if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
02723                 d_printf("hardlink %s: %s\n", src, cli_errstr(cli));
02724                 return 1;
02725         }
02726         
02727         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
02728                 d_printf("Server doesn't support UNIX CIFS calls.\n");
02729                 return 1;
02730         }
02731         
02732         if (!cli_nt_hardlink(targetcli, targetname, dest)) {
02733                 d_printf("%s doing an NT hard link of files\n",cli_errstr(targetcli));
02734                 return 1;
02735         }
02736         
02737         return 0;
02738 }
02739 
02740 /****************************************************************************
02741  Toggle the prompt flag.
02742 ****************************************************************************/
02743 
02744 static int cmd_prompt(void)
02745 {
02746         prompt = !prompt;
02747         DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
02748         
02749         return 1;
02750 }
02751 
02752 /****************************************************************************
02753  Set the newer than time.
02754 ****************************************************************************/
02755 
02756 static int cmd_newer(void)
02757 {
02758         pstring buf;
02759         BOOL ok;
02760         SMB_STRUCT_STAT sbuf;
02761 
02762         ok = next_token_nr(NULL,buf,NULL,sizeof(buf));
02763         if (ok && (sys_stat(buf,&sbuf) == 0)) {
02764                 newer_than = sbuf.st_mtime;
02765                 DEBUG(1,("Getting files newer than %s",
02766                          time_to_asc(newer_than)));
02767         } else {
02768                 newer_than = 0;
02769         }
02770 
02771         if (ok && newer_than == 0) {
02772                 d_printf("Error setting newer-than time\n");
02773                 return 1;
02774         }
02775 
02776         return 0;
02777 }
02778 
02779 /****************************************************************************
02780  Set the archive level.
02781 ****************************************************************************/
02782 
02783 static int cmd_archive(void)
02784 {
02785         pstring buf;
02786 
02787         if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02788                 archive_level = atoi(buf);
02789         } else
02790                 d_printf("Archive level is %d\n",archive_level);
02791 
02792         return 0;
02793 }
02794 
02795 /****************************************************************************
02796  Toggle the lowercaseflag.
02797 ****************************************************************************/
02798 
02799 static int cmd_lowercase(void)
02800 {
02801         lowercase = !lowercase;
02802         DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
02803 
02804         return 0;
02805 }
02806 
02807 /****************************************************************************
02808  Toggle the case sensitive flag.
02809 ****************************************************************************/
02810 
02811 static int cmd_setcase(void)
02812 {
02813         BOOL orig_case_sensitive = cli_set_case_sensitive(cli, False);
02814 
02815         cli_set_case_sensitive(cli, !orig_case_sensitive);
02816         DEBUG(2,("filename case sensitivity is now %s\n",!orig_case_sensitive ?
02817                 "on":"off"));
02818 
02819         return 0;
02820 }
02821 
02822 /****************************************************************************
02823  Toggle the showacls flag.
02824 ****************************************************************************/
02825 
02826 static int cmd_showacls(void)
02827 {
02828         showacls = !showacls;
02829         DEBUG(2,("showacls is now %s\n",showacls?"on":"off"));
02830 
02831         if (!ctx && showacls)
02832                 ctx = talloc_init("smbclient:showacls");
02833                 if (!ctx) {
02834                         DEBUG( 0, ("cmd_showacls() out of memory.  talloc_init() failed.\n"));
02835         }
02836 
02837         return 0;
02838 }
02839 
02840 
02841 /****************************************************************************
02842  Toggle the recurse flag.
02843 ****************************************************************************/
02844 
02845 static int cmd_recurse(void)
02846 {
02847         recurse = !recurse;
02848         DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
02849 
02850         return 0;
02851 }
02852 
02853 /****************************************************************************
02854  Toggle the translate flag.
02855 ****************************************************************************/
02856 
02857 static int cmd_translate(void)
02858 {
02859         translation = !translation;
02860         DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
02861                  translation?"on":"off"));
02862 
02863         return 0;
02864 }
02865 
02866 /****************************************************************************
02867  Do the lcd command.
02868  ****************************************************************************/
02869 
02870 static int cmd_lcd(void)
02871 {
02872         pstring buf;
02873         pstring d;
02874         
02875         if (next_token_nr(NULL,buf,NULL,sizeof(buf)))
02876                 chdir(buf);
02877         DEBUG(2,("the local directory is now %s\n",sys_getwd(d)));
02878 
02879         return 0;
02880 }
02881 
02882 /****************************************************************************
02883  Get a file restarting at end of local file.
02884  ****************************************************************************/
02885 
02886 static int cmd_reget(void)
02887 {
02888         pstring local_name;
02889         pstring remote_name;
02890         char *p;
02891 
02892         pstrcpy(remote_name, cur_dir);
02893         
02894         p = remote_name + strlen(remote_name);
02895         
02896         if (!next_token_nr(NULL, p, NULL, sizeof(remote_name) - strlen(remote_name))) {
02897                 d_printf("reget <filename>\n");
02898                 return 1;
02899         }
02900         pstrcpy(local_name, p);
02901         clean_name(remote_name);
02902         
02903         next_token_nr(NULL, local_name, NULL, sizeof(local_name));
02904         
02905         return do_get(remote_name, local_name, True);
02906 }
02907 
02908 /****************************************************************************
02909  Put a file restarting at end of local file.
02910  ****************************************************************************/
02911 
02912 static int cmd_reput(void)
02913 {
02914         pstring local_name;
02915         pstring remote_name;
02916         pstring buf;
02917         char *p = buf;
02918         SMB_STRUCT_STAT st;
02919         
02920         pstrcpy(remote_name, cur_dir);
02921   
02922         if (!next_token_nr(NULL, p, NULL, sizeof(buf))) {
02923                 d_printf("reput <filename>\n");
02924                 return 1;
02925         }
02926         pstrcpy(local_name, p);
02927   
02928         if (!file_exist(local_name, &st)) {
02929                 d_printf("%s does not exist\n", local_name);
02930                 return 1;
02931         }
02932 
02933         if (next_token_nr(NULL, p, NULL, sizeof(buf)))
02934                 pstrcat(remote_name, p);
02935         else
02936                 pstrcat(remote_name, local_name);
02937         
02938         clean_name(remote_name);
02939 
02940         return do_put(remote_name, local_name, True);
02941 }
02942 
02943 /****************************************************************************
02944  List a share name.
02945  ****************************************************************************/
02946 
02947 static void browse_fn(const char *name, uint32 m, 
02948                       const char *comment, void *state)
02949 {
02950         fstring typestr;
02951 
02952         *typestr=0;
02953 
02954         switch (m & 7)
02955         {
02956           case STYPE_DISKTREE:
02957             fstrcpy(typestr,"Disk"); break;
02958           case STYPE_PRINTQ:
02959             fstrcpy(typestr,"Printer"); break;
02960           case STYPE_DEVICE:
02961             fstrcpy(typestr,"Device"); break;
02962           case STYPE_IPC:
02963             fstrcpy(typestr,"IPC"); break;
02964         }
02965         /* FIXME: If the remote machine returns non-ascii characters
02966            in any of these fields, they can corrupt the output.  We
02967            should remove them. */
02968         if (!grepable) {
02969                 d_printf("\t%-15s %-10.10s%s\n",
02970                         name,typestr,comment);
02971         } else {
02972                 d_printf ("%s|%s|%s\n",typestr,name,comment);
02973         }
02974 }
02975 
02976 static BOOL browse_host_rpc(BOOL sort)
02977 {
02978         NTSTATUS status;
02979         struct rpc_pipe_client *pipe_hnd;
02980         TALLOC_CTX *mem_ctx;
02981         ENUM_HND enum_hnd;
02982         WERROR werr;
02983         SRV_SHARE_INFO_CTR ctr;
02984         int i;
02985 
02986         mem_ctx = talloc_new(NULL);
02987         if (mem_ctx == NULL) {
02988                 DEBUG(0, ("talloc_new failed\n"));
02989                 return False;
02990         }
02991 
02992         init_enum_hnd(&enum_hnd, 0);
02993 
02994         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &status);
02995 
02996         if (pipe_hnd == NULL) {
02997                 DEBUG(10, ("Could not connect to srvsvc pipe: %s\n",
02998                            nt_errstr(status)));
02999                 TALLOC_FREE(mem_ctx);
03000                 return False;
03001         }
03002 
03003         werr = rpccli_srvsvc_net_share_enum(pipe_hnd, mem_ctx, 1, &ctr,
03004                                             0xffffffff, &enum_hnd);
03005 
03006         if (!W_ERROR_IS_OK(werr)) {
03007                 TALLOC_FREE(mem_ctx);
03008                 cli_rpc_pipe_close(pipe_hnd);
03009                 return False;
03010         }
03011 
03012         for (i=0; i<ctr.num_entries; i++) {
03013                 SRV_SHARE_INFO_1 *info = &ctr.share.info1[i];
03014                 char *name, *comment;
03015                 name = rpcstr_pull_unistr2_talloc(
03016                         mem_ctx, &info->info_1_str.uni_netname);
03017                 comment = rpcstr_pull_unistr2_talloc(
03018                         mem_ctx, &info->info_1_str.uni_remark);
03019                 browse_fn(name, info->info_1.type, comment, NULL);
03020         }
03021 
03022         TALLOC_FREE(mem_ctx);
03023         cli_rpc_pipe_close(pipe_hnd);
03024         return True;
03025 }
03026 
03027 /****************************************************************************
03028  Try and browse available connections on a host.
03029 ****************************************************************************/
03030 
03031 static BOOL browse_host(BOOL sort)
03032 {
03033         int ret;
03034         if (!grepable) {
03035                 d_printf("\n\tSharename       Type      Comment\n");
03036                 d_printf("\t---------       ----      -------\n");
03037         }
03038 
03039         if (browse_host_rpc(sort)) {
03040                 return True;
03041         }
03042 
03043         if((ret = cli_RNetShareEnum(cli, browse_fn, NULL)) == -1)
03044                 d_printf("Error returning browse list: %s\n", cli_errstr(cli));
03045 
03046         return (ret != -1);
03047 }
03048 
03049 /****************************************************************************
03050  List a server name.
03051 ****************************************************************************/
03052 
03053 static void server_fn(const char *name, uint32 m, 
03054                       const char *comment, void *state)
03055 {
03056         
03057         if (!grepable){
03058                 d_printf("\t%-16s     %s\n", name, comment);
03059         } else {
03060                 d_printf("%s|%s|%s\n",(char *)state, name, comment);
03061         }
03062 }
03063 
03064 /****************************************************************************
03065  Try and browse available connections on a host.
03066 ****************************************************************************/
03067 
03068 static BOOL list_servers(const char *wk_grp)
03069 {
03070         fstring state;
03071 
03072         if (!cli->server_domain)
03073                 return False;
03074 
03075         if (!grepable) {
03076                 d_printf("\n\tServer               Comment\n");
03077                 d_printf("\t---------            -------\n");
03078         };
03079         fstrcpy( state, "Server" );
03080         cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL, server_fn,
03081                           state);
03082 
03083         if (!grepable) {
03084                 d_printf("\n\tWorkgroup            Master\n");
03085                 d_printf("\t---------            -------\n");
03086         }; 
03087 
03088         fstrcpy( state, "Workgroup" );
03089         cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM,
03090                           server_fn, state);
03091         return True;
03092 }
03093 
03094 /****************************************************************************
03095  Print or set current VUID
03096 ****************************************************************************/
03097 
03098 static int cmd_vuid(void)
03099 {
03100         fstring buf;
03101         
03102         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
03103                 d_printf("Current VUID is %d\n", cli->vuid);
03104                 return 0;
03105         }
03106 
03107         cli->vuid = atoi(buf);
03108         return 0;
03109 }
03110 
03111 /****************************************************************************
03112  Setup a new VUID, by issuing a session setup
03113 ****************************************************************************/
03114 
03115 static int cmd_logon(void)
03116 {
03117         pstring l_username, l_password;
03118         pstring buf,buf2;
03119   
03120         if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
03121                 d_printf("logon <username> [<password>]\n");
03122                 return 0;
03123         }
03124 
03125         pstrcpy(l_username, buf);
03126 
03127         if (!next_token_nr(NULL,buf2,NULL,sizeof(buf))) 
03128         {
03129                 char *pass = getpass("Password: ");
03130                 if (pass) 
03131                         pstrcpy(l_password, pass);
03132         } 
03133         else
03134                 pstrcpy(l_password, buf2);
03135 
03136         if (!NT_STATUS_IS_OK(cli_session_setup(cli, l_username, 
03137                                                l_password, strlen(l_password),
03138                                                l_password, strlen(l_password),
03139                                                lp_workgroup()))) {
03140                 d_printf("session setup failed: %s\n", cli_errstr(cli));
03141                 return -1;
03142         }
03143 
03144         d_printf("Current VUID is %d\n", cli->vuid);
03145         return 0;
03146 }
03147 
03148 
03149 /****************************************************************************
03150  list active connections
03151 ****************************************************************************/
03152 
03153 static int cmd_list_connect(void)
03154 {
03155         cli_cm_display();
03156 
03157         return 0;
03158 }
03159 
03160 /****************************************************************************
03161  display the current active client connection
03162 ****************************************************************************/
03163 
03164 static int cmd_show_connect( void )
03165 {
03166         struct cli_state *targetcli;
03167         pstring targetpath;
03168         
03169         if ( !cli_resolve_path( "", cli, cur_dir, &targetcli, targetpath ) ) {
03170                 d_printf("showconnect %s: %s\n", cur_dir, cli_errstr(cli));
03171                 return 1;
03172         }
03173         
03174         d_printf("//%s/%s\n", targetcli->desthost, targetcli->share);
03175         return 0;
03176 }
03177 
03178 /* Some constants for completing filename arguments */
03179 
03180 #define COMPL_NONE        0          /* No completions */
03181 #define COMPL_REMOTE      1          /* Complete remote filename */
03182 #define COMPL_LOCAL       2          /* Complete local filename */
03183 
03184 /* This defines the commands supported by this client.
03185  * NOTE: The "!" must be the last one in the list because it's fn pointer
03186  *       field is NULL, and NULL in that field is used in process_tok()
03187  *       (below) to indicate the end of the list.  crh
03188  */
03189 static struct
03190 {
03191   const char *name;
03192   int (*fn)(void);
03193   const char *description;
03194   char compl_args[2];      /* Completion argument info */
03195 } commands[] = {
03196   {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
03197   {"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
03198   {"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}},
03199   {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
03200   {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
03201   {"case_sensitive",cmd_setcase,"toggle the case sensitive flag to server",{COMPL_NONE,COMPL_NONE}},
03202   {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
03203   {"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}},
03204   {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}},
03205   {"close",cmd_close,"<fid> close a file given a fid",{COMPL_REMOTE,COMPL_REMOTE}},
03206   {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
03207   {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
03208   {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
03209   {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
03210   {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
03211   {"getfacl",cmd_getfacl,"<file name> get the POSIX ACL on a file (UNIX extensions only)",{COMPL_REMOTE,COMPL_LOCAL}},
03212   {"hardlink",cmd_hardlink,"<src> <dest> create a Windows hard link",{COMPL_REMOTE,COMPL_REMOTE}},
03213   {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
03214   {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
03215   {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
03216   {"link",cmd_link,"<oldname> <newname> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
03217   {"lock",cmd_lock,"lock <fnum> [r|w] <hex-start> <hex-len> : set a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
03218   {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},  
03219   {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
03220   {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
03221   {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
03222   {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
03223   {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
03224   {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},  
03225   {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
03226   {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
03227   {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
03228   {"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
03229   {"posix_open",cmd_posix_open,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
03230   {"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
03231   {"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
03232   {"posix_unlink",cmd_posix_unlink,"<name> removes a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
03233   {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
03234   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},  
03235   {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
03236   {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
03237   {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
03238   {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}},
03239   {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
03240   {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
03241   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},  
03242   {"reget",cmd_reget,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE,COMPL_LOCAL}},
03243   {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
03244   {"reput",cmd_reput,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}},
03245   {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
03246   {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
03247   {"showacls",cmd_showacls,"toggle if ACLs are shown or not",{COMPL_NONE,COMPL_NONE}},  
03248   {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
03249   {"stat",cmd_stat,"filename Do a UNIX extensions stat call on a file",{COMPL_REMOTE,COMPL_REMOTE}},
03250   {"symlink",cmd_symlink,"<oldname> <newname> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}},
03251   {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
03252   {"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
03253   {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
03254   {"unlock",cmd_unlock,"unlock <fnum> <hex-start> <hex-len> : remove a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
03255   {"volume",cmd_volume,"print the volume name",{COMPL_NONE,COMPL_NONE}},
03256   {"vuid",cmd_vuid,"change current vuid",{COMPL_NONE,COMPL_NONE}},
03257   {"wdel",cmd_wdel,"<attrib> <mask> wildcard delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
03258   {"logon",cmd_logon,"establish new logon",{COMPL_NONE,COMPL_NONE}},
03259   {"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}},
03260   {"showconnect",cmd_show_connect,"display the current active connection",{COMPL_NONE,COMPL_NONE}},
03261   
03262   /* Yes, this must be here, see crh's comment above. */
03263   {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
03264   {NULL,NULL,NULL,{COMPL_NONE,COMPL_NONE}}
03265 };
03266 
03267 /*******************************************************************
03268  Lookup a command string in the list of commands, including 
03269  abbreviations.
03270 ******************************************************************/
03271 
03272 static int process_tok(pstring tok)
03273 {
03274         int i = 0, matches = 0;
03275         int cmd=0;
03276         int tok_len = strlen(tok);
03277         
03278         while (commands[i].fn != NULL) {
03279                 if (strequal(commands[i].name,tok)) {
03280                         matches = 1;
03281                         cmd = i;
03282                         break;
03283                 } else if (strnequal(commands[i].name, tok, tok_len)) {
03284                         matches++;
03285                         cmd = i;
03286                 }
03287                 i++;
03288         }
03289   
03290         if (matches == 0)
03291                 return(-1);
03292         else if (matches == 1)
03293                 return(cmd);
03294         else
03295                 return(-2);
03296 }
03297 
03298 /****************************************************************************
03299  Help.
03300 ****************************************************************************/
03301 
03302 static int cmd_help(void)
03303 {
03304         int i=0,j;
03305         pstring buf;
03306         
03307         if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
03308                 if ((i = process_tok(buf)) >= 0)
03309                         d_printf("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description);
03310         } else {
03311                 while (commands[i].description) {
03312                         for (j=0; commands[i].description && (j<5); j++) {
03313                                 d_printf("%-15s",commands[i].name);
03314                                 i++;
03315                         }
03316                         d_printf("\n");
03317                 }
03318         }
03319         return 0;
03320 }
03321 
03322 /****************************************************************************
03323  Process a -c command string.
03324 ****************************************************************************/
03325 
03326 static int process_command_string(char *cmd)
03327 {
03328         pstring line;
03329         const char *ptr;
03330         int rc = 0;
03331 
03332         /* establish the connection if not already */
03333         
03334         if (!cli) {
03335                 cli = cli_cm_open(desthost, service, True);
03336                 if (!cli)
03337                         return 0;
03338         }
03339         
03340         while (cmd[0] != '\0')    {
03341                 char *p;
03342                 pstring tok;
03343                 int i;
03344                 
03345                 if ((p = strchr_m(cmd, ';')) == 0) {
03346                         strncpy(line, cmd, 999);
03347                         line[1000] = '\0';
03348                         cmd += strlen(cmd);
03349                 } else {
03350                         if (p - cmd > 999)
03351                                 p = cmd + 999;
03352                         strncpy(line, cmd, p - cmd);
03353                         line[p - cmd] = '\0';
03354                         cmd = p + 1;
03355                 }
03356                 
03357                 /* and get the first part of the command */
03358                 ptr = line;
03359                 if (!next_token_nr(&ptr,tok,NULL,sizeof(tok))) continue;
03360                 
03361                 if ((i = process_tok(tok)) >= 0) {
03362                         rc = commands[i].fn();
03363                 } else if (i == -2) {
03364                         d_printf("%s: command abbreviation ambiguous\n",tok);
03365                 } else {
03366                         d_printf("%s: command not found\n",tok);
03367                 }
03368         }
03369         
03370         return rc;
03371 }       
03372 
03373 #define MAX_COMPLETIONS 100
03374 
03375 typedef struct {
03376         pstring dirmask;
03377         char **matches;
03378         int count, samelen;
03379         const char *text;
03380         int len;
03381 } completion_remote_t;
03382 
03383 static void completion_remote_filter(const char *mnt, file_info *f, const char *mask, void *state)
03384 {
03385         completion_remote_t *info = (completion_remote_t *)state;
03386 
03387         if ((info->count < MAX_COMPLETIONS - 1) && (strncmp(info->text, f->name, info->len) == 0) && (strcmp(f->name, ".") != 0) && (strcmp(f->name, "..") != 0)) {
03388                 if ((info->dirmask[0] == 0) && !(f->mode & aDIR))
03389                         info->matches[info->count] = SMB_STRDUP(f->name);
03390                 else {
03391                         pstring tmp;
03392 
03393                         if (info->dirmask[0] != 0)
03394                                 pstrcpy(tmp, info->dirmask);
03395                         else
03396                                 tmp[0] = 0;
03397                         pstrcat(tmp, f->name);
03398                         if (f->mode & aDIR)
03399                                 pstrcat(tmp, "/");
03400                         info->matches[info->count] = SMB_STRDUP(tmp);
03401                 }
03402                 if (info->matches[info->count] == NULL)
03403                         return;
03404                 if (f->mode & aDIR)
03405                         smb_readline_ca_char(0);
03406 
03407                 if (info->count == 1)
03408                         info->samelen = strlen(info->matches[info->count]);
03409                 else
03410                         while (strncmp(info->matches[info->count], info->matches[info->count-1], info->samelen) != 0)
03411                                 info->samelen--;
03412                 info->count++;
03413         }
03414 }
03415 
03416 static char **remote_completion(const char *text, int len)
03417 {
03418         pstring dirmask;
03419         int i;
03420         completion_remote_t info = { "", NULL, 1, 0, NULL, 0 };
03421 
03422         /* can't have non-static intialisation on Sun CC, so do it
03423            at run time here */
03424         info.samelen = len;
03425         info.text = text;
03426         info.len = len;
03427                 
03428         if (len >= MIN(PATH_MAX,sizeof(pstring))) {
03429                 return(NULL);
03430         }
03431 
03432         info.matches = SMB_MALLOC_ARRAY(char *,MAX_COMPLETIONS);
03433         if (!info.matches) {
03434                 return NULL;
03435         }
03436 
03437         /*
03438          * We're leaving matches[0] free to fill it later with the text to
03439          * display: Either the one single match or the longest common subset
03440          * of the matches.
03441          */
03442         info.matches[0] = NULL;
03443         info.count = 1;
03444 
03445         for (i = len-1; i >= 0; i--) {
03446                 if ((text[i] == '/') || (text[i] == CLI_DIRSEP_CHAR)) {
03447                         break;
03448                 }
03449         }
03450 
03451         info.text = text+i+1;
03452         info.samelen = info.len = len-i-1;
03453 
03454         if (i > 0) {
03455                 strncpy(info.dirmask, text, i+1);
03456                 info.dirmask[i+1] = 0;
03457                 pstr_sprintf(dirmask, "%s%*s*", cur_dir, i-1, text);
03458         } else {
03459                 pstr_sprintf(dirmask, "%s*", cur_dir);
03460         }
03461 
03462         if (cli_list(cli, dirmask, aDIR | aSYSTEM | aHIDDEN, completion_remote_filter, &info) < 0)
03463                 goto cleanup;
03464 
03465         if (info.count == 1) {
03466 
03467                 /*
03468                  * No matches at all, NULL indicates there is nothing
03469                  */
03470 
03471                 SAFE_FREE(info.matches[0]);
03472                 SAFE_FREE(info.matches);
03473                 return NULL;
03474         }
03475 
03476         if (info.count == 2) {
03477 
03478                 /*
03479                  * Exactly one match in matches[1], indicate this is the one
03480                  * in matches[0].
03481                  */
03482 
03483                 info.matches[0] = info.matches[1];
03484                 info.matches[1] = NULL;
03485                 info.count -= 1;
03486                 return info.matches;
03487         }
03488 
03489         /*
03490          * We got more than one possible match, set the result to the maximum
03491          * common subset
03492          */
03493 
03494         info.matches[0] = SMB_STRNDUP(info.matches[1], info.samelen);
03495         info.matches[info.count] = NULL;
03496         return info.matches;
03497 
03498 cleanup:
03499         for (i = 0; i < info.count; i++)
03500                 free(info.matches[i]);
03501         free(info.matches);
03502         return NULL;
03503 }
03504 
03505 static char **completion_fn(const char *text, int start, int end)
03506 {
03507         smb_readline_ca_char(' ');
03508 
03509         if (start) {
03510                 const char *buf, *sp;
03511                 int i;
03512                 char compl_type;
03513 
03514                 buf = smb_readline_get_line_buffer();
03515                 if (buf == NULL)
03516                         return NULL;
03517                 
03518                 sp = strchr(buf, ' ');
03519                 if (sp == NULL)
03520                         return NULL;
03521 
03522                 for (i = 0; commands[i].name; i++) {
03523                         if ((strncmp(commands[i].name, buf, sp - buf) == 0) &&
03524                             (commands[i].name[sp - buf] == 0)) {
03525                                 break;
03526                         }
03527                 }
03528                 if (commands[i].name == NULL)
03529                         return NULL;
03530 
03531                 while (*sp == ' ')
03532                         sp++;
03533 
03534                 if (sp == (buf + start))
03535                         compl_type = commands[i].compl_args[0];
03536                 else
03537                         compl_type = commands[i].compl_args[1];
03538 
03539                 if (compl_type == COMPL_REMOTE)
03540                         return remote_completion(text, end - start);
03541                 else /* fall back to local filename completion */
03542                         return NULL;
03543         } else {
03544                 char **matches;
03545                 int i, len, samelen = 0, count=1;
03546 
03547                 matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
03548                 if (!matches) {
03549                         return NULL;
03550                 }
03551                 matches[0] = NULL;
03552 
03553                 len = strlen(text);
03554                 for (i=0;commands[i].fn && count < MAX_COMPLETIONS-1;i++) {
03555                         if (strncmp(text, commands[i].name, len) == 0) {
03556                                 matches[count] = SMB_STRDUP(commands[i].name);
03557                                 if (!matches[count])
03558                                         goto cleanup;
03559                                 if (count == 1)
03560                                         samelen = strlen(matches[count]);
03561                                 else
03562                                         while (strncmp(matches[count], matches[count-1], samelen) != 0)
03563                                                 samelen--;
03564                                 count++;
03565                         }
03566                 }
03567 
03568                 switch (count) {
03569                 case 0: /* should never happen */
03570                 case 1:
03571                         goto cleanup;
03572                 case 2:
03573                         matches[0] = SMB_STRDUP(matches[1]);
03574                         break;
03575                 default:
03576                         matches[0] = (char *)SMB_MALLOC(samelen+1);
03577                         if (!matches[0])
03578                                 goto cleanup;
03579                         strncpy(matches[0], matches[1], samelen);
03580                         matches[0][samelen] = 0;
03581                 }
03582                 matches[count] = NULL;
03583                 return matches;
03584 
03585 cleanup:
03586                 for (i = 0; i < count; i++)
03587                         free(matches[i]);
03588 
03589                 free(matches);
03590                 return NULL;
03591         }
03592 }
03593 
03594 /****************************************************************************
03595  Make sure we swallow keepalives during idle time.
03596 ****************************************************************************/
03597 
03598 static void readline_callback(void)
03599 {
03600         fd_set fds;
03601         struct timeval timeout;
03602         static time_t last_t;
03603         time_t t;
03604 
03605         t = time(NULL);
03606 
03607         if (t - last_t < 5)
03608                 return;
03609 
03610         last_t = t;
03611 
03612  again:
03613 
03614         if (cli->fd == -1)
03615                 return;
03616 
03617         FD_ZERO(&fds);
03618         FD_SET(cli->fd,&fds);
03619 
03620         timeout.tv_sec = 0;
03621         timeout.tv_usec = 0;
03622         sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
03623                 
03624         /* We deliberately use receive_smb instead of
03625            client_receive_smb as we want to receive
03626            session keepalives and then drop them here.
03627         */
03628         if (FD_ISSET(cli->fd,&fds)) {
03629                 if (!receive_smb(cli->fd,cli->inbuf,cli->bufsize,0)) {
03630                         DEBUG(0, ("Read from server failed, maybe it closed the "
03631                                 "connection\n"));
03632                         return;
03633                 }
03634                 goto again;
03635         }
03636       
03637         /* Ping the server to keep the connection alive using SMBecho. */
03638         {
03639                 unsigned char garbage[16];
03640                 memset(garbage, 0xf0, sizeof(garbage));
03641                 cli_echo(cli, garbage, sizeof(garbage));
03642         }
03643 }
03644 
03645 /****************************************************************************
03646  Process commands on stdin.
03647 ****************************************************************************/
03648 
03649 static int process_stdin(void)
03650 {
03651         const char *ptr;
03652         int rc = 0;
03653 
03654         while (1) {
03655                 pstring tok;
03656                 pstring the_prompt;
03657                 char *cline;
03658                 pstring line;
03659                 int i;
03660                 
03661                 /* display a prompt */
03662                 slprintf(the_prompt, sizeof(the_prompt)-1, "smb: %s> ", cur_dir);
03663                 cline = smb_readline(the_prompt, readline_callback, completion_fn);
03664                         
03665                 if (!cline) break;
03666                 
03667                 pstrcpy(line, cline);
03668 
03669                 /* special case - first char is ! */
03670                 if (*line == '!') {
03671                         system(line + 1);
03672                         continue;
03673                 }
03674       
03675                 /* and get the first part of the command */
03676                 ptr = line;
03677                 if (!next_token_nr(&ptr,tok,NULL,sizeof(tok))) continue;
03678 
03679                 if ((i = process_tok(tok)) >= 0) {
03680                         rc = commands[i].fn();
03681                 } else if (i == -2) {
03682                         d_printf("%s: command abbreviation ambiguous\n",tok);
03683                 } else {
03684                         d_printf("%s: command not found\n",tok);
03685                 }
03686         }
03687         return rc;
03688 }
03689 
03690 /****************************************************************************
03691  Process commands from the client.
03692 ****************************************************************************/
03693 
03694 static int process(char *base_directory)
03695 {
03696         int rc = 0;
03697 
03698         cli = cli_cm_open(desthost, service, True);
03699         if (!cli) {
03700                 return 1;
03701         }
03702 
03703         if (*base_directory) {
03704                 rc = do_cd(base_directory);
03705                 if (rc) {
03706                         cli_cm_shutdown();
03707                         return rc;
03708                 }
03709         }
03710         
03711         if (cmdstr) {
03712                 rc = process_command_string(cmdstr);
03713         } else {
03714                 process_stdin();
03715         }
03716   
03717         cli_cm_shutdown();
03718         return rc;
03719 }
03720 
03721 /****************************************************************************
03722  Handle a -L query.
03723 ****************************************************************************/
03724 
03725 static int do_host_query(char *query_host)
03726 {
03727         cli = cli_cm_open(query_host, "IPC$", True);
03728         if (!cli)
03729                 return 1;
03730 
03731         browse_host(True);
03732 
03733         if (port != 139) {
03734 
03735                 /* Workgroups simply don't make sense over anything
03736                    else but port 139... */
03737 
03738                 cli_cm_shutdown();
03739                 port = 139;
03740                 cli_cm_set_port( 139 );
03741                 cli = cli_cm_open(query_host, "IPC$", True);
03742         }
03743 
03744         if (cli == NULL) {
03745                 d_printf("NetBIOS over TCP disabled -- no workgroup available\n");
03746                 return 1;
03747         }
03748 
03749         list_servers(lp_workgroup());
03750 
03751         cli_cm_shutdown();
03752         
03753         return(0);
03754 }
03755 
03756 /****************************************************************************
03757  Handle a tar operation.
03758 ****************************************************************************/
03759 
03760 static int do_tar_op(char *base_directory)
03761 {
03762         int ret;
03763 
03764         /* do we already have a connection? */
03765         if (!cli) {
03766                 cli = cli_cm_open(desthost, service, True);
03767                 if (!cli)
03768                         return 1;
03769         }
03770 
03771         recurse=True;
03772 
03773         if (*base_directory)  {
03774                 ret = do_cd(base_directory);
03775                 if (ret) {
03776                         cli_cm_shutdown();
03777                         return ret;
03778                 }
03779         }
03780         
03781         ret=process_tar();
03782 
03783         cli_cm_shutdown();
03784 
03785         return(ret);
03786 }
03787 
03788 /****************************************************************************
03789  Handle a message operation.
03790 ****************************************************************************/
03791 
03792 static int do_message_op(void)
03793 {
03794         struct in_addr ip;
03795         struct nmb_name called, calling;
03796         fstring server_name;
03797         char name_type_hex[10];
03798         int msg_port;
03799         NTSTATUS status;
03800 
03801         make_nmb_name(&calling, calling_name, 0x0);
03802         make_nmb_name(&called , desthost, name_type);
03803 
03804         fstrcpy(server_name, desthost);
03805         snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
03806         fstrcat(server_name, name_type_hex);
03807 
03808         zero_ip(&ip);
03809         if (have_ip) 
03810                 ip = dest_ip;
03811 
03812         /* we can only do messages over port 139 (to windows clients at least) */
03813 
03814         msg_port = port ? port : 139;
03815 
03816         if (!(cli=cli_initialise()) || (cli_set_port(cli, msg_port) != msg_port)) {
03817                 d_printf("Connection to %s failed\n", desthost);
03818                 return 1;
03819         }
03820 
03821         status = cli_connect(cli, server_name, &ip);
03822         if (!NT_STATUS_IS_OK(status)) {
03823                 d_printf("Connection to %s failed. Error %s\n", desthost, nt_errstr(status));
03824                 return 1;
03825         }
03826 
03827         if (!cli_session_request(cli, &calling, &called)) {
03828                 d_printf("session request failed\n");
03829                 cli_cm_shutdown();
03830                 return 1;
03831         }
03832 
03833         send_message();
03834         cli_cm_shutdown();
03835 
03836         return 0;
03837 }
03838 
03839 
03840 /****************************************************************************
03841   main program
03842 ****************************************************************************/
03843 
03844  int main(int argc,char *argv[])
03845 {
03846         pstring base_directory;
03847         int len = 0;
03848         int opt;
03849         pstring query_host;
03850         BOOL message = False;
03851         pstring term_code;
03852         static const char *new_name_resolve_order = NULL;
03853         poptContext pc;
03854         char *p;
03855         int rc = 0;
03856         fstring new_workgroup;
03857         BOOL tar_opt = False;
03858         BOOL service_opt = False;
03859         struct poptOption long_options[] = {
03860                 POPT_AUTOHELP
03861 
03862                 { "name-resolve", 'R', POPT_ARG_STRING, &new_name_resolve_order, 'R', "Use these name resolution services only", "NAME-RESOLVE-ORDER" },
03863                 { "message", 'M', POPT_ARG_STRING, NULL, 'M', "Send message", "HOST" },
03864                 { "ip-address", 'I', POPT_ARG_STRING, NULL, 'I', "Use this IP to connect to", "IP" },
03865                 { "stderr", 'E', POPT_ARG_NONE, NULL, 'E', "Write messages to stderr instead of stdout" },
03866                 { "list", 'L', POPT_ARG_STRING, NULL, 'L', "Get a list of shares available on a host", "HOST" },
03867                 { "terminal", 't', POPT_ARG_STRING, NULL, 't', "Terminal I/O code {sjis|euc|jis7|jis8|junet|hex}", "CODE" },
03868                 { "max-protocol", 'm', POPT_ARG_STRING, NULL, 'm', "Set the max protocol level", "LEVEL" },
03869                 { "tar", 'T', POPT_ARG_STRING, NULL, 'T', "Command line tar", "<c|x>IXFqgbNan" },
03870                 { "directory", 'D', POPT_ARG_STRING, NULL, 'D', "Start from directory", "DIR" },
03871                 { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" }, 
03872                 { "send-buffer", 'b', POPT_ARG_INT, &io_bufsize, 'b', "Changes the transmit/send buffer", "BYTES" },
03873                 { "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" },
03874                 { "grepable", 'g', POPT_ARG_NONE, NULL, 'g', "Produce grepable output" },
03875                 POPT_COMMON_SAMBA
03876                 POPT_COMMON_CONNECTION
03877                 POPT_COMMON_CREDENTIALS
03878                 POPT_TABLEEND
03879         };
03880         
03881         load_case_tables();
03882 
03883 #ifdef KANJI
03884         pstrcpy(term_code, KANJI);
03885 #else /* KANJI */
03886         *term_code = 0;
03887 #endif /* KANJI */
03888 
03889         *query_host = 0;
03890         *base_directory = 0;
03891         
03892         /* initialize the workgroup name so we can determine whether or 
03893            not it was set by a command line option */
03894            
03895         set_global_myworkgroup( "" );
03896         set_global_myname( "" );
03897 
03898         /* set default debug level to 1 regardless of what smb.conf sets */
03899         setup_logging( "smbclient", True );
03900         DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
03901         if ((dbf = x_fdup(x_stderr))) {
03902                 x_setbuf( dbf, NULL );
03903         }
03904 
03905         /* skip argv(0) */
03906         pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
03907         poptSetOtherOptionHelp(pc, "service <password>");
03908 
03909         in_client = True;   /* Make sure that we tell lp_load we are */
03910 
03911         while ((opt = poptGetNextOpt(pc)) != -1) {
03912 
03913                 /* if the tar option has been called previouslt, now we need to eat out the leftovers */
03914                 /* I see no other way to keep things sane --SSS */
03915                 if (tar_opt == True) {
03916                         while (poptPeekArg(pc)) {
03917                                 poptGetArg(pc);
03918                         }
03919                         tar_opt = False;
03920                 }
03921 
03922                 /* if the service has not yet been specified lets see if it is available in the popt stack */
03923                 if (!service_opt && poptPeekArg(pc)) {
03924                         pstrcpy(service, poptGetArg(pc));
03925                         service_opt = True;
03926                 }
03927 
03928                 /* if the service has already been retrieved then check if we have also a password */
03929                 if (service_opt && (!cmdline_auth_info.got_pass) && poptPeekArg(pc)) {
03930                         pstrcpy(cmdline_auth_info.password, poptGetArg(pc));
03931                         cmdline_auth_info.got_pass = True;
03932                 }
03933         
03934                 switch (opt) {
03935                 case 'M':
03936                         /* Messages are sent to NetBIOS name type 0x3
03937                          * (Messenger Service).  Make sure we default
03938                          * to port 139 instead of port 445. srl,crh
03939                          */
03940                         name_type = 0x03; 
03941                         cli_cm_set_dest_name_type( name_type );
03942                         pstrcpy(desthost,poptGetOptArg(pc));
03943                         if ( port != 139 )
03944                                 port = 139;
03945                         cli_cm_set_port ( 138);
03946                         message = True;
03947                         break;
03948                 case 'I':
03949                         {
03950                                 dest_ip = *interpret_addr2(poptGetOptArg(pc));
03951                                 if (is_zero_ip(dest_ip))
03952                                         exit(1);
03953                                 have_ip = True;
03954 
03955                                 cli_cm_set_dest_ip( dest_ip );
03956                         }
03957                         break;
03958                 case 'E':
03959                         if (dbf) {
03960                                 x_fclose(dbf);
03961                         }
03962                         dbf = x_stderr;
03963                         display_set_stderr();
03964                         break;
03965 
03966                 case 'L':
03967                         pstrcpy(query_host, poptGetOptArg(pc));
03968                         break;
03969                 case 't':
03970                         pstrcpy(term_code, poptGetOptArg(pc));
03971                         break;
03972                 case 'm':
03973                         max_protocol = interpret_protocol(poptGetOptArg(pc), max_protocol);
03974                         break;
03975                 case 'T':
03976                         /* We must use old option processing for this. Find the
03977                          * position of the -T option in the raw argv[]. */
03978                         {
03979                                 int i;
03980                                 for (i = 1; i < argc; i++) {
03981                                         if (strncmp("-T", argv[i],2)==0)
03982                                                 break;
03983                                 }
03984                                 i++;
03985                                 if (!tar_parseargs(argc, argv, poptGetOptArg(pc), i)) {
03986                                         poptPrintUsage(pc, stderr, 0);
03987                                         exit(1);
03988                                 }
03989                         }
03990                         /* this must be the last option, mark we have parsed it so that we know we have */
03991                         tar_opt = True;
03992                         break;
03993                 case 'D':
03994                         pstrcpy(base_directory,poptGetOptArg(pc));
03995                         break;
03996                 case 'g':
03997                         grepable=True;
03998                         break;
03999                 }
04000         }
04001 
04002         /* We may still have some leftovers after the last popt option has been called */
04003         if (tar_opt == True) {
04004                 while (poptPeekArg(pc)) {
04005                         poptGetArg(pc);
04006                 }
04007                 tar_opt = False;
04008         }
04009 
04010         /* if the service has not yet been specified lets see if it is available in the popt stack */
04011         if (!service_opt && poptPeekArg(pc)) {
04012                 pstrcpy(service, poptGetArg(pc));
04013                 service_opt = True;
04014         }
04015 
04016         /* if the service has already been retrieved then check if we have also a password */
04017         if (service_opt && (!cmdline_auth_info.got_pass) && poptPeekArg(pc)) {
04018                 pstrcpy(cmdline_auth_info.password, poptGetArg(pc));
04019                 cmdline_auth_info.got_pass = True;
04020         }
04021         
04022         /* check for the -P option */
04023 
04024         if ( port != 0 )
04025                 cli_cm_set_port( port );
04026 
04027         /*
04028          * Don't load debug level from smb.conf. It should be
04029          * set by cmdline arg or remain default (0)
04030          */
04031         AllowDebugChange = False;
04032         
04033         /* save the workgroup...
04034         
04035            FIXME!! do we need to do this for other options as well 
04036            (or maybe a generic way to keep lp_load() from overwriting 
04037            everything)?  */
04038         
04039         fstrcpy( new_workgroup, lp_workgroup() );
04040         pstrcpy( calling_name, global_myname() );
04041         
04042         if ( override_logfile )
04043                 setup_logging( lp_logfile(), False );
04044         
04045         if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) {
04046                 fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n",
04047                         argv[0], dyn_CONFIGFILE);
04048         }
04049         
04050         load_interfaces();
04051 
04052         if (service_opt) {
04053                 /* Convert any '/' characters in the service name to '\' characters */
04054                 string_replace(service, '/','\\');
04055                 if (count_chars(service,'\\') < 3) {
04056                         d_printf("\n%s: Not enough '\\' characters in service\n",service);
04057                         poptPrintUsage(pc, stderr, 0);
04058                         exit(1);
04059                 }
04060                 /* Remove trailing slashes */
04061                 len = strlen(service);
04062                 while(len > 0 && service[len - 1] == '\\') {
04063                         --len;
04064                         service[len] = '\0';
04065                 }
04066         }
04067         
04068         if ( strlen(new_workgroup) != 0 )
04069                 set_global_myworkgroup( new_workgroup );
04070 
04071         if ( strlen(calling_name) != 0 )
04072                 set_global_myname( calling_name );
04073         else
04074                 pstrcpy( calling_name, global_myname() );
04075 
04076         init_names();
04077 
04078         if(new_name_resolve_order)
04079                 lp_set_name_resolve_order(new_name_resolve_order);
04080 
04081         if (!tar_type && !*query_host && !*service && !message) {
04082                 poptPrintUsage(pc, stderr, 0);
04083                 exit(1);
04084         }
04085 
04086         poptFreeContext(pc);
04087 
04088         /* store the username an password for dfs support */
04089 
04090         cli_cm_set_credentials( &cmdline_auth_info );
04091         pstrcpy(username, cmdline_auth_info.username);
04092 
04093         DEBUG(3,("Client started (version %s).\n", SAMBA_VERSION_STRING));
04094 
04095         if (tar_type) {
04096                 if (cmdstr)
04097                         process_command_string(cmdstr);
04098                 return do_tar_op(base_directory);
04099         }
04100 
04101         if (*query_host) {
04102                 char *qhost = query_host;
04103                 char *slash;
04104 
04105                 while (*qhost == '\\' || *qhost == '/')
04106                         qhost++;
04107 
04108                 if ((slash = strchr_m(qhost, '/'))
04109                     || (slash = strchr_m(qhost, '\\'))) {
04110                         *slash = 0;
04111                 }
04112 
04113                 if ((p=strchr_m(qhost, '#'))) {
04114                         *p = 0;
04115                         p++;
04116                         sscanf(p, "%x", &name_type);
04117                         cli_cm_set_dest_name_type( name_type );
04118                 }
04119 
04120                 return do_host_query(qhost);
04121         }
04122 
04123         if (message) {
04124                 return do_message_op();
04125         }
04126         
04127         if (process(base_directory)) {
04128                 return 1;
04129         }
04130 
04131         talloc_destroy( ctx);
04132         return rc;
04133 }

Sambaに対してSat Aug 29 21:22:53 2009に生成されました。  doxygen 1.4.7