home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / samba.idb / usr / samba / src / source / client.c.z / client.c
Encoding:
C/C++ Source or Header  |  1998-10-28  |  93.4 KB  |  3,913 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    SMB client
  5.    Copyright (C) Andrew Tridgell 1994-1998
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #ifdef SYSLOG
  23. #undef SYSLOG
  24. #endif
  25.  
  26. #include "includes.h"
  27.  
  28. #ifndef REGISTER
  29. #define REGISTER 0
  30. #endif
  31.  
  32. pstring cur_dir = "\\";
  33. pstring cd_path = "";
  34. extern pstring service;
  35. extern pstring desthost;
  36. extern pstring myname;
  37. extern pstring myhostname;
  38. extern pstring password;
  39. extern pstring username;
  40. extern pstring workgroup;
  41. char *cmdstr="";
  42. extern BOOL got_pass;
  43. extern BOOL no_pass;
  44. extern BOOL connect_as_printer;
  45. extern BOOL connect_as_ipc;
  46. extern struct in_addr ipzero;
  47.  
  48. extern BOOL doencrypt;
  49.  
  50. extern pstring user_socket_options;
  51.  
  52. /* 30 second timeout on most commands */
  53. #define CLIENT_TIMEOUT (30*1000)
  54. #define SHORT_TIMEOUT (5*1000)
  55.  
  56. /* value for unused fid field in trans2 secondary request */
  57. #define FID_UNUSED (0xFFFF)
  58.  
  59. extern int name_type;
  60.  
  61. extern int max_protocol;
  62.  
  63.  
  64. time_t newer_than = 0;
  65. int archive_level = 0;
  66.  
  67. extern pstring debugf;
  68. extern int DEBUGLEVEL;
  69.  
  70. BOOL translation = False;
  71.  
  72. extern int cnum;
  73. extern int mid;
  74. extern int pid;
  75. extern int tid;
  76. extern int gid;
  77. extern int uid;
  78.  
  79. extern BOOL have_ip;
  80. extern int max_xmit;
  81.  
  82. static int interpret_long_filename(int level,char *p,file_info *finfo);
  83. static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo);
  84. static int interpret_short_filename(char *p,file_info *finfo);
  85. static BOOL do_this_one(file_info *finfo);
  86.  
  87. /* clitar bits insert */
  88. extern int blocksize;
  89. extern BOOL tar_inc;
  90. extern BOOL tar_reset;
  91. /* clitar bits end */
  92.  
  93.  
  94. int myumask = 0755;
  95.  
  96. extern pstring scope;
  97.  
  98. BOOL prompt = True;
  99.  
  100. int printmode = 1;
  101.  
  102. BOOL recurse = False;
  103. BOOL lowercase = False;
  104.  
  105. struct in_addr dest_ip;
  106.  
  107. #define SEPARATORS " \t\n\r"
  108.  
  109. BOOL abort_mget = True;
  110.  
  111. extern int Protocol;
  112.  
  113. extern BOOL readbraw_supported ;
  114. extern BOOL writebraw_supported;
  115.  
  116. pstring fileselection = "";
  117.  
  118. extern file_info def_finfo;
  119.  
  120. /* timing globals */
  121. int get_total_size = 0;
  122. int get_total_time_ms = 0;
  123. int put_total_size = 0;
  124. int put_total_time_ms = 0;
  125.  
  126. /* totals globals */
  127. int dir_total = 0;
  128.  
  129. extern int Client;
  130.  
  131. #define USENMB
  132.  
  133. #define CNV_LANG(s) dos_to_unix(s,False)
  134. #define CNV_INPUT(s) unix_to_dos(s,True)
  135.  
  136. /****************************************************************************
  137. send an SMBclose on an SMB file handle
  138. ****************************************************************************/
  139. void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
  140. {
  141.   bzero(outbuf,smb_size);
  142.   set_message(outbuf,3,0,True);
  143.  
  144.   CVAL (outbuf,smb_com) = SMBclose;
  145.   SSVAL(outbuf,smb_tid,c_num);
  146.   cli_setup_pkt(outbuf);
  147.   SSVAL (outbuf,smb_vwv0, f_num);
  148.   SIVALS(outbuf,smb_vwv1, -1);
  149.   
  150.   send_smb(clnt_fd, outbuf);
  151.   client_receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
  152. }
  153.  
  154. /****************************************************************************
  155. write to a local file with CR/LF->LF translation if appropriate. return the 
  156. number taken from the buffer. This may not equal the number written.
  157. ****************************************************************************/
  158. static int writefile(int f, char *b, int n)
  159. {
  160.   int i;
  161.  
  162.   if (!translation)
  163.     return(write(f,b,n));
  164.   
  165.   i = 0;
  166.   while (i < n)
  167.     {
  168.       if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
  169.     {
  170.       b++;i++;
  171.     }
  172.       if (write(f, b, 1) != 1)
  173.     {
  174.       break;
  175.     }
  176.       b++;
  177.       i++;
  178.     }
  179.   
  180.   return(i);
  181. }
  182.  
  183. /****************************************************************************
  184.   read from a file with LF->CR/LF translation if appropriate. return the 
  185.   number read. read approx n bytes.
  186. ****************************************************************************/
  187. static int readfile(char *b, int size, int n, FILE *f)
  188. {
  189.   int i;
  190.   int c;
  191.  
  192.   if (!translation || (size != 1))
  193.     return(fread(b,size,n,f));
  194.   
  195.   i = 0;
  196.   while (i < n)
  197.     {
  198.       if ((c = getc(f)) == EOF)
  199.     {
  200.       break;
  201.     }
  202.       
  203.       if (c == '\n') /* change all LFs to CR/LF */
  204.     {
  205.       b[i++] = '\r';
  206.       n++;
  207.     }
  208.       
  209.       if(i < n)
  210.         b[i++] = c;
  211.     }
  212.   
  213.   return(i);
  214. }
  215.  
  216.  
  217. /****************************************************************************
  218. read from a file with print translation. return the number read. read approx n
  219. bytes.
  220. ****************************************************************************/
  221. static int printread(FILE *f,char *b,int n)
  222. {
  223.   int i;
  224.  
  225.   i = readfile(b,1, n-1,f);
  226. #if FORMFEED
  227.   if (feof(f) && i>0)
  228.     b[i++] = '\014';
  229. #endif
  230.  
  231.   return(i);
  232. }
  233.  
  234. /****************************************************************************
  235. check for existance of a dir
  236. ****************************************************************************/
  237. static BOOL chkpath(char *path,BOOL report)
  238. {
  239.   fstring path2;
  240.   pstring inbuf,outbuf;
  241.   char *p;
  242.  
  243.   pstrcpy(path2,path);
  244.   trim_string(path2,NULL,"\\");
  245.   if (!*path2) *path2 = '\\';
  246.  
  247.   bzero(outbuf,smb_size);
  248.   set_message(outbuf,0,4 + strlen(path2),True);
  249.   SCVAL(outbuf,smb_com,SMBchkpth);
  250.   SSVAL(outbuf,smb_tid,cnum);
  251.   cli_setup_pkt(outbuf);
  252.  
  253.   p = smb_buf(outbuf);
  254.   *p++ = 4;
  255.   pstrcpy(p,path2);
  256.  
  257. #if 0
  258.   {
  259.       /* this little bit of code can be used to extract NT error codes.
  260.          Just feed a bunch of "cd foo" commands to smbclient then watch
  261.          in netmon (tridge) */
  262.       static int code=0;
  263.       SIVAL(outbuf, smb_rcls, code | 0xC0000000);
  264.       SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
  265.       code++;
  266.   }
  267. #endif
  268.  
  269.   send_smb(Client,outbuf);
  270.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  271.  
  272.   if (report && CVAL(inbuf,smb_rcls) != 0)
  273.     DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
  274.  
  275.   return(CVAL(inbuf,smb_rcls) == 0);
  276. }
  277.  
  278.  
  279. /****************************************************************************
  280. send a message
  281. ****************************************************************************/
  282. static void send_message(char *inbuf,char *outbuf)
  283. {
  284.   int total_len = 0;
  285.  
  286.   char *p;
  287.   int grp_id;
  288.  
  289.   /* send a SMBsendstrt command */
  290.   bzero(outbuf,smb_size);
  291.   set_message(outbuf,0,0,True);
  292.   CVAL(outbuf,smb_com) = SMBsendstrt;
  293.   SSVAL(outbuf,smb_tid,cnum);
  294.  
  295.   p = smb_buf(outbuf);
  296.   *p++ = 4;
  297.   pstrcpy(p,username);
  298.   p = skip_string(p,1);
  299.   *p++ = 4;
  300.   pstrcpy(p,desthost);
  301.   p = skip_string(p,1);
  302.  
  303.   set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
  304.  
  305.   send_smb(Client,outbuf);
  306.   
  307.  
  308.   if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
  309.     {
  310.       printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
  311.       return;
  312.     }
  313.  
  314.   grp_id = SVAL(inbuf,smb_vwv0);
  315.  
  316.   printf("Connected. Type your message, ending it with a Control-D\n");
  317.  
  318.   while (!feof(stdin) && total_len < 1600)
  319.     {
  320.       int maxlen = MIN(1600 - total_len,127);
  321.       pstring msg;
  322.       int l=0;
  323.       int c;
  324.  
  325.       bzero(msg,smb_size);
  326.  
  327.       for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
  328.     {
  329.       if (c == '\n')
  330.         msg[l++] = '\r';
  331.       msg[l] = c;   
  332.     }
  333.  
  334.       CVAL(outbuf,smb_com) = SMBsendtxt;
  335.  
  336.       set_message(outbuf,1,l+3,True);
  337.  
  338.       SSVAL(outbuf,smb_vwv0,grp_id);
  339.  
  340.       p = smb_buf(outbuf);
  341.       *p = 1;
  342.       SSVAL(p,1,l);
  343.       memcpy(p+3,msg,l);
  344.  
  345.       send_smb(Client,outbuf);
  346.       
  347.  
  348.       if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
  349.     {
  350.       printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
  351.       return;
  352.     }      
  353.  
  354.       total_len += l;
  355.     }
  356.  
  357.   if (total_len >= 1600)
  358.     printf("the message was truncated to 1600 bytes ");
  359.   else
  360.     printf("sent %d bytes ",total_len);
  361.  
  362.   printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
  363.  
  364.   CVAL(outbuf,smb_com) = SMBsendend;
  365.   set_message(outbuf,1,0,False);
  366.   SSVAL(outbuf,smb_vwv0,grp_id);
  367.  
  368.   send_smb(Client,outbuf);
  369.   
  370.  
  371.   if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
  372.     {
  373.       printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
  374.       return;
  375.     }      
  376. }
  377.  
  378.  
  379.  
  380. /****************************************************************************
  381. check the space on a device
  382. ****************************************************************************/
  383. static void do_dskattr(void)
  384. {
  385.   pstring inbuf,outbuf;
  386.  
  387.   bzero(outbuf,smb_size);
  388.   set_message(outbuf,0,0,True);
  389.   CVAL(outbuf,smb_com) = SMBdskattr;
  390.   SSVAL(outbuf,smb_tid,cnum);
  391.   cli_setup_pkt(outbuf);
  392.  
  393.   send_smb(Client,outbuf);
  394.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  395.  
  396.   if (CVAL(inbuf,smb_rcls) != 0) 
  397.     DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));      
  398.  
  399.   DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
  400.     SVAL(inbuf,smb_vwv0),
  401.     SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
  402.     SVAL(inbuf,smb_vwv3)));
  403. }
  404.  
  405. /****************************************************************************
  406. show cd/pwd
  407. ****************************************************************************/
  408. static void cmd_pwd(char *dum_in, char *dum_out)
  409. {
  410.   DEBUG(0,("Current directory is %s",CNV_LANG(service)));
  411.   DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
  412. }
  413.  
  414.  
  415. /****************************************************************************
  416. change directory - inner section
  417. ****************************************************************************/
  418. static void do_cd(char *newdir)
  419. {
  420.   char *p = newdir;
  421.   pstring saved_dir;
  422.   pstring dname;
  423.       
  424.   /* Save the current directory in case the
  425.      new directory is invalid */
  426.   pstrcpy(saved_dir, cur_dir);
  427.   if (*p == '\\')
  428.     pstrcpy(cur_dir,p);
  429.   else
  430.     pstrcat(cur_dir,p);
  431.   if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
  432.     pstrcat(cur_dir, "\\");
  433.   }
  434.   dos_clean_name(cur_dir);
  435.   pstrcpy(dname,cur_dir);
  436.   pstrcat(cur_dir,"\\");
  437.   dos_clean_name(cur_dir);
  438.  
  439.   if (!strequal(cur_dir,"\\"))
  440.     if (!chkpath(dname,True))
  441.       pstrcpy(cur_dir,saved_dir);
  442.  
  443.   pstrcpy(cd_path,cur_dir);
  444. }
  445.  
  446. /****************************************************************************
  447. change directory
  448. ****************************************************************************/
  449. static void cmd_cd(char *inbuf,char *outbuf)
  450. {
  451.   fstring buf;
  452.  
  453.   if (next_token(NULL,buf,NULL))
  454.     do_cd(buf);
  455.   else
  456.     DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
  457. }
  458.  
  459.  
  460. /****************************************************************************
  461.   display info about a file
  462.   ****************************************************************************/
  463. static void display_finfo(file_info *finfo)
  464. {
  465.   if (do_this_one(finfo)) {
  466.     time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
  467.     DEBUG(0,("  %-30s%7.7s%10d  %s",
  468.          CNV_LANG(finfo->name),
  469.        attrib_string(finfo->mode),
  470.        finfo->size,
  471.        asctime(LocalTime(&t))));
  472.     dir_total += finfo->size;
  473.   }
  474. }
  475.  
  476.  
  477. /****************************************************************************
  478.   do a directory listing, calling fn on each file found. Use the TRANSACT2
  479.   call for long filenames
  480.   ****************************************************************************/
  481. static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
  482. {
  483.   int max_matches = 512;
  484.   int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
  485.   char *p;
  486.   pstring mask;
  487.   file_info finfo;
  488.   int i;
  489.   char *dirlist = NULL;
  490.   int dirlist_len = 0;
  491.   int total_received = 0;
  492.   BOOL First = True;
  493.   char *resp_data=NULL;
  494.   char *resp_param=NULL;
  495.   int resp_data_len = 0;
  496.   int resp_param_len=0;
  497.  
  498.   int ff_resume_key = 0;
  499.   int ff_searchcount=0;
  500.   int ff_eos=0;
  501.   int ff_lastname=0;
  502.   int ff_dir_handle=0;
  503.   int loop_count = 0;
  504.  
  505.   uint16 setup;
  506.   pstring param;
  507.  
  508.   pstrcpy(mask,Mask);
  509.  
  510.   while (ff_eos == 0)
  511.     {
  512.       loop_count++;
  513.       if (loop_count > 200)
  514.     {
  515.       DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
  516.       break;
  517.     }
  518.  
  519.       if (First)
  520.     {
  521.       setup = TRANSACT2_FINDFIRST;
  522.       SSVAL(param,0,attribute); /* attribute */
  523.       SSVAL(param,2,max_matches); /* max count */
  524.       SSVAL(param,4,8+4+2);    /* resume required + close on end + continue */
  525.       SSVAL(param,6,info_level); 
  526.       SIVAL(param,8,0);
  527.       pstrcpy(param+12,mask);
  528.     }
  529.       else
  530.     {
  531.       setup = TRANSACT2_FINDNEXT;
  532.       SSVAL(param,0,ff_dir_handle);
  533.       SSVAL(param,2,max_matches); /* max count */
  534.       SSVAL(param,4,info_level); 
  535.       SIVAL(param,6,ff_resume_key); /* ff_resume_key */
  536.       SSVAL(param,10,8+4+2);    /* resume required + close on end + continue */
  537.       pstrcpy(param+12,mask);
  538.  
  539.       DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
  540.            ff_dir_handle,ff_resume_key,ff_lastname,mask));
  541.     }
  542.       /* ??? original code added 1 pad byte after param */
  543.  
  544.       cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
  545.              NULL,param,&setup,
  546.              0,12+strlen(mask)+1,1,
  547.              BUFFER_SIZE,10,0);
  548.  
  549.       if (!cli_receive_trans_response(inbuf,SMBtrans2,
  550.                   &resp_data_len,&resp_param_len,
  551.                       &resp_data,&resp_param))
  552.     {
  553.       DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
  554.       break;
  555.     }
  556.  
  557.       /* parse out some important return info */
  558.       p = resp_param;
  559.       if (First)
  560.     {
  561.       ff_dir_handle = SVAL(p,0);
  562.       ff_searchcount = SVAL(p,2);
  563.       ff_eos = SVAL(p,4);
  564.       ff_lastname = SVAL(p,8);
  565.     }
  566.       else
  567.     {
  568.       ff_searchcount = SVAL(p,0);
  569.       ff_eos = SVAL(p,2);
  570.       ff_lastname = SVAL(p,6);
  571.     }
  572.  
  573.       if (ff_searchcount == 0) 
  574.     break;
  575.  
  576.       /* point to the data bytes */
  577.       p = resp_data;
  578.  
  579.       /* we might need the lastname for continuations */
  580.       if (ff_lastname > 0)
  581.     {
  582.       switch(info_level)
  583.         {
  584.         case 260:
  585.           ff_resume_key =0;
  586.           StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
  587.           /* pstrcpy(mask,p+ff_lastname+94); */
  588.           break;
  589.         case 1:
  590.           pstrcpy(mask,p + ff_lastname + 1);
  591.           ff_resume_key = 0;
  592.           break;
  593.         }
  594.     }
  595.       else
  596.     pstrcpy(mask,"");
  597.   
  598.       /* and add them to the dirlist pool */
  599.       dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
  600.  
  601.       if (!dirlist)
  602.     {
  603.       DEBUG(0,("Failed to expand dirlist\n"));
  604.       break;
  605.     }
  606.  
  607.       /* put in a length for the last entry, to ensure we can chain entries 
  608.      into the next packet */
  609.       {
  610.     char *p2;
  611.     for (p2=p,i=0;i<(ff_searchcount-1);i++)
  612.       p2 += interpret_long_filename(info_level,p2,NULL);
  613.     SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
  614.       }
  615.  
  616.       /* grab the data for later use */
  617.       memcpy(dirlist+dirlist_len,p,resp_data_len);
  618.       dirlist_len += resp_data_len;
  619.  
  620.       total_received += ff_searchcount;
  621.  
  622.       if (resp_data) free(resp_data); resp_data = NULL;
  623.       if (resp_param) free(resp_param); resp_param = NULL;
  624.  
  625.       DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
  626.            ff_searchcount,ff_eos,ff_resume_key));
  627.  
  628.       First = False;
  629.     }
  630.  
  631.   if (!fn)
  632.     for (p=dirlist,i=0;i<total_received;i++)
  633.       {
  634.     p += interpret_long_filename(info_level,p,&finfo);
  635.     display_finfo(&finfo);
  636.       }
  637.  
  638.   for (p=dirlist,i=0;i<total_received;i++)
  639.     {
  640.       p += interpret_long_filename(info_level,p,&finfo);
  641.       dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True, dirstoo);
  642.     }
  643.  
  644.   /* free up the dirlist buffer */
  645.   if (dirlist) free(dirlist);
  646.   return(total_received);
  647. }
  648.  
  649.  
  650. /****************************************************************************
  651.   do a directory listing, calling fn on each file found
  652.   ****************************************************************************/
  653. static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
  654. {
  655.   char *p;
  656.   int received = 0;
  657.   BOOL first = True;
  658.   char status[21];
  659.   int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
  660.   int num_received = 0;
  661.   int i;
  662.   char *dirlist = NULL;
  663.   pstring mask;
  664.   file_info finfo;
  665.  
  666.   finfo = def_finfo;
  667.  
  668.   bzero(status,21);
  669.  
  670.   pstrcpy(mask,Mask);
  671.   
  672.   while (1)
  673.     {
  674.       bzero(outbuf,smb_size);
  675.       if (first)    
  676.     set_message(outbuf,2,5 + strlen(mask),True);
  677.       else
  678.     set_message(outbuf,2,5 + 21,True);
  679.  
  680. #if FFIRST
  681.       if (Protocol >= PROTOCOL_LANMAN1)
  682.     CVAL(outbuf,smb_com) = SMBffirst;
  683.       else
  684. #endif
  685.     CVAL(outbuf,smb_com) = SMBsearch;
  686.  
  687.       SSVAL(outbuf,smb_tid,cnum);
  688.       cli_setup_pkt(outbuf);
  689.  
  690.       SSVAL(outbuf,smb_vwv0,num_asked);
  691.       SSVAL(outbuf,smb_vwv1,attribute);
  692.   
  693.       p = smb_buf(outbuf);
  694.       *p++ = 4;
  695.       
  696.       if (first)
  697.     pstrcpy(p,mask);
  698.       else
  699.     pstrcpy(p,"");
  700.       p += strlen(p) + 1;
  701.       
  702.       *p++ = 5;
  703.       if (first)
  704.     SSVAL(p,0,0);
  705.       else
  706.     {
  707.       SSVAL(p,0,21);
  708.       p += 2;
  709.       memcpy(p,status,21);
  710.     }
  711.  
  712.       send_smb(Client,outbuf);
  713.       client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  714.  
  715.       received = SVAL(inbuf,smb_vwv0);
  716.  
  717.       DEBUG(5,("dir received %d\n",received));
  718.  
  719.       DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
  720.  
  721.       if (received <= 0) break;
  722.  
  723.       first = False;
  724.  
  725.       dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
  726.  
  727.       if (!dirlist) 
  728.     return 0;
  729.  
  730.       p = smb_buf(inbuf) + 3;
  731.  
  732.       memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
  733.          p,received*DIR_STRUCT_SIZE);
  734.  
  735.       memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
  736.  
  737.       num_received += received;
  738.  
  739.       if (CVAL(inbuf,smb_rcls) != 0) break;
  740.     }
  741.  
  742. #if FFIRST
  743.   if (!first && Protocol >= PROTOCOL_LANMAN1)
  744.     {
  745.       bzero(outbuf,smb_size);
  746.       CVAL(outbuf,smb_com) = SMBfclose;
  747.  
  748.       SSVAL(outbuf,smb_tid,cnum);
  749.       cli_setup_pkt(outbuf);
  750.  
  751.       p = smb_buf(outbuf);
  752.       *p++ = 4;
  753.       
  754.       pstrcpy(p,"");
  755.       p += strlen(p) + 1;
  756.       
  757.       *p++ = 5;
  758.       SSVAL(p,0,21);
  759.       p += 2;
  760.       memcpy(p,status,21);
  761.  
  762.       send_smb(Client,outbuf);
  763.       client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  764.  
  765.       if (CVAL(inbuf,smb_rcls) != 0) 
  766.     DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));      
  767.     }
  768. #endif
  769.  
  770.   if (!fn)
  771.     for (p=dirlist,i=0;i<num_received;i++)
  772.       {
  773.     p += interpret_short_filename(p,&finfo);
  774.     display_finfo(&finfo);
  775.       }
  776.  
  777.   for (p=dirlist,i=0;i<num_received;i++)
  778.     {
  779.       p += interpret_short_filename(p,&finfo);
  780.       dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False,dirstoo);
  781.     }
  782.  
  783.   if (dirlist) free(dirlist);
  784.   return(num_received);
  785. }
  786.  
  787.  
  788.  
  789. /****************************************************************************
  790.   do a directory listing, calling fn on each file found
  791.   ****************************************************************************/
  792. void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
  793. {
  794.   DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
  795.   if (Protocol >= PROTOCOL_LANMAN2)
  796.     {
  797.       if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo) > 0)
  798.     return;
  799.     }
  800.  
  801.   expand_mask(Mask,False);
  802.   do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo);
  803.   return;
  804. }
  805.  
  806. /*******************************************************************
  807.   decide if a file should be operated on
  808.   ********************************************************************/
  809. static BOOL do_this_one(file_info *finfo)
  810. {
  811.   if (finfo->mode & aDIR) return(True);
  812.  
  813.   if (newer_than && finfo->mtime < newer_than)
  814.     return(False);
  815.  
  816.   if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
  817.     return(False);
  818.  
  819.   return(True);
  820. }
  821.  
  822.  
  823. /*****************************************************************************
  824.  Convert a character pointer in a cli_call_api() response to a form we can use.
  825.  This function contains code to prevent core dumps if the server returns 
  826.  invalid data.
  827. *****************************************************************************/
  828. static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
  829. {
  830. if( datap == 0 )        /* turn NULL pointers */
  831.   {                /* into zero length strings */
  832.   return "";
  833.   }
  834. else
  835.   {
  836.   unsigned int offset = datap - converter;
  837.  
  838.   if( offset >= rdrcnt )
  839.     {
  840.       DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
  841.     return "<ERROR>";
  842.     }
  843.   else
  844.     {
  845.     return &rdata[offset];
  846.     }
  847.   }
  848. }
  849.  
  850. /****************************************************************************
  851. interpret a short filename structure
  852. The length of the structure is returned
  853. ****************************************************************************/
  854. static int interpret_short_filename(char *p,file_info *finfo)
  855. {
  856.   finfo->mode = CVAL(p,21);
  857.  
  858.   /* this date is converted to GMT by make_unix_date */
  859.   finfo->ctime = make_unix_date(p+22);
  860.   finfo->mtime = finfo->atime = finfo->ctime;
  861.   finfo->size = IVAL(p,26);
  862.   pstrcpy(finfo->name,p+30);
  863.   
  864.   return(DIR_STRUCT_SIZE);
  865. }
  866.  
  867. /****************************************************************************
  868. interpret a long filename structure - this is mostly guesses at the moment
  869. The length of the structure is returned
  870. The structure of a long filename depends on the info level. 260 is used
  871. by NT and 2 is used by OS/2
  872. ****************************************************************************/
  873. static int interpret_long_filename(int level,char *p,file_info *finfo)
  874. {
  875.   if (finfo)
  876.     memcpy(finfo,&def_finfo,sizeof(*finfo));
  877.  
  878.   switch (level)
  879.     {
  880.     case 1: /* OS/2 understands this */
  881.       if (finfo)
  882.     {
  883.       /* these dates are converted to GMT by make_unix_date */
  884.       finfo->ctime = make_unix_date2(p+4);
  885.       finfo->atime = make_unix_date2(p+8);
  886.       finfo->mtime = make_unix_date2(p+12);
  887.       finfo->size = IVAL(p,16);
  888.       finfo->mode = CVAL(p,24);
  889.       pstrcpy(finfo->name,p+27);
  890.     }
  891.       return(28 + CVAL(p,26));
  892.  
  893.     case 2: /* this is what OS/2 uses mostly */
  894.       if (finfo)
  895.     {
  896.       /* these dates are converted to GMT by make_unix_date */
  897.       finfo->ctime = make_unix_date2(p+4);
  898.       finfo->atime = make_unix_date2(p+8);
  899.       finfo->mtime = make_unix_date2(p+12);
  900.       finfo->size = IVAL(p,16);
  901.       finfo->mode = CVAL(p,24);
  902.       pstrcpy(finfo->name,p+31);
  903.     }
  904.       return(32 + CVAL(p,30));
  905.  
  906.       /* levels 3 and 4 are untested */
  907.     case 3:
  908.       if (finfo)
  909.     {
  910.       /* these dates are probably like the other ones */
  911.       finfo->ctime = make_unix_date2(p+8);
  912.       finfo->atime = make_unix_date2(p+12);
  913.       finfo->mtime = make_unix_date2(p+16);
  914.       finfo->size = IVAL(p,20);
  915.       finfo->mode = CVAL(p,28);
  916.       pstrcpy(finfo->name,p+33);
  917.     }
  918.       return(SVAL(p,4)+4);
  919.  
  920.     case 4:
  921.       if (finfo)
  922.     {
  923.       /* these dates are probably like the other ones */
  924.       finfo->ctime = make_unix_date2(p+8);
  925.       finfo->atime = make_unix_date2(p+12);
  926.       finfo->mtime = make_unix_date2(p+16);
  927.       finfo->size = IVAL(p,20);
  928.       finfo->mode = CVAL(p,28);
  929.       pstrcpy(finfo->name,p+37);
  930.     }
  931.       return(SVAL(p,4)+4);
  932.  
  933.     case 260: /* NT uses this, but also accepts 2 */
  934.       if (finfo)
  935.     {
  936.       int ret = SVAL(p,0);
  937.       int namelen;
  938.       p += 4; /* next entry offset */
  939.       p += 4; /* fileindex */
  940.  
  941.       /* these dates appear to arrive in a weird way. It seems to
  942.          be localtime plus the serverzone given in the initial
  943.          connect. This is GMT when DST is not in effect and one
  944.          hour from GMT otherwise. Can this really be right??
  945.  
  946.          I suppose this could be called kludge-GMT. Is is the GMT
  947.          you get by using the current DST setting on a different
  948.          localtime. It will be cheap to calculate, I suppose, as
  949.          no DST tables will be needed */
  950.  
  951.       finfo->ctime = interpret_long_date(p); p += 8;
  952.       finfo->atime = interpret_long_date(p); p += 8;
  953.       finfo->mtime = interpret_long_date(p); p += 8; p += 8;
  954.       finfo->size = IVAL(p,0); p += 8;
  955.       p += 8; /* alloc size */
  956.       finfo->mode = CVAL(p,0); p += 4;
  957.       namelen = IVAL(p,0); p += 4;
  958.       p += 4; /* EA size */
  959.       p += 2; /* short name len? */
  960.       p += 24; /* short name? */      
  961.       StrnCpy(finfo->name,p,namelen);
  962.       return(ret);
  963.     }
  964.       return(SVAL(p,0));
  965.     }
  966.  
  967.   DEBUG(1,("Unknown long filename format %d\n",level));
  968.   return(SVAL(p,0));
  969. }
  970.  
  971.  
  972.  
  973.  
  974. /****************************************************************************
  975.   act on the files in a dir listing
  976.  
  977.   RJS, 4-Apr-1998, dirstoo added to allow caller to indicate that directories
  978.                    should be processed as well.
  979.   ****************************************************************************/
  980. static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo)
  981. {
  982.  
  983.   if (!((finfo->mode & aDIR) == 0 && *fileselection && 
  984.     !mask_match(finfo->name,fileselection,False,False)) &&
  985.       !(recurse_dir && (strequal(finfo->name,".") || 
  986.             strequal(finfo->name,".."))))
  987.     {
  988.       if (recurse_dir && (finfo->mode & aDIR))
  989.     {
  990.       pstring mask2;
  991.       pstring sav_dir;
  992.  
  993.           if (fn && dirstoo && do_this_one(finfo)) { /* Do dirs, RJS */
  994.         fn(finfo);
  995.       }
  996.  
  997.       pstrcpy(sav_dir,cur_dir);
  998.       pstrcat(cur_dir,finfo->name);
  999.       pstrcat(cur_dir,"\\");
  1000.       pstrcpy(mask2,cur_dir);
  1001.  
  1002.       if (!fn)
  1003.         DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
  1004.  
  1005.       pstrcat(mask2,"*");
  1006.  
  1007.       if (longdir)
  1008.         do_long_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);      
  1009.       else
  1010.         do_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
  1011.  
  1012.       pstrcpy(cur_dir,sav_dir);
  1013.     }
  1014.       else
  1015.     {
  1016.       if (fn && do_this_one(finfo))
  1017.         fn(finfo);
  1018.     }
  1019.     }
  1020. }
  1021.  
  1022.  
  1023. /****************************************************************************
  1024.   get a directory listing
  1025.   ****************************************************************************/
  1026. static void cmd_dir(char *inbuf,char *outbuf)
  1027. {
  1028.   int attribute = aDIR | aSYSTEM | aHIDDEN;
  1029.   pstring mask;
  1030.   fstring buf;
  1031.   char *p=buf;
  1032.  
  1033.   dir_total = 0;
  1034.   pstrcpy(mask,cur_dir);
  1035.   if(mask[strlen(mask)-1]!='\\')
  1036.     pstrcat(mask,"\\");
  1037.  
  1038.   if (next_token(NULL,buf,NULL))
  1039.     {
  1040.       if (*p == '\\')
  1041.     pstrcpy(mask,p);
  1042.       else
  1043.     pstrcat(mask,p);
  1044.     }
  1045.   else {
  1046.     pstrcat(mask,"*");
  1047.   }
  1048.  
  1049.   do_dir(inbuf,outbuf,mask,attribute,NULL,recurse,False);
  1050.  
  1051.   do_dskattr();
  1052.  
  1053.   DEBUG(3, ("Total bytes listed: %d\n", dir_total));
  1054. }
  1055.  
  1056.  
  1057.  
  1058. /****************************************************************************
  1059.   get a file from rname to lname
  1060.   ****************************************************************************/
  1061. static void do_get(char *rname,char *lname,file_info *finfo1)
  1062. {  
  1063.   int handle=0,fnum;
  1064.   uint32 nread=0;
  1065.   char *p;
  1066.   BOOL newhandle = False;
  1067.   char *inbuf,*outbuf;
  1068.   file_info finfo;
  1069.   BOOL close_done = False;
  1070.   BOOL ignore_close_error = False;
  1071.   char *dataptr=NULL;
  1072.   int datalen=0;
  1073.  
  1074.   struct timeval tp_start;
  1075.   GetTimeOfDay(&tp_start);
  1076.  
  1077.   if (finfo1) 
  1078.     finfo = *finfo1;
  1079.   else
  1080.     finfo = def_finfo;
  1081.  
  1082.   if (lowercase)
  1083.     strlower(lname);
  1084.  
  1085.  
  1086.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1087.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1088.  
  1089.   if (!inbuf || !outbuf)
  1090.     {
  1091.       DEBUG(0,("out of memory\n"));
  1092.       return;
  1093.     }
  1094.  
  1095.   bzero(outbuf,smb_size);
  1096.   set_message(outbuf,15,1 + strlen(rname),True);
  1097.  
  1098.   CVAL(outbuf,smb_com) = SMBopenX;
  1099.   SSVAL(outbuf,smb_tid,cnum);
  1100.   cli_setup_pkt(outbuf);
  1101.  
  1102.   SSVAL(outbuf,smb_vwv0,0xFF);
  1103.   SSVAL(outbuf,smb_vwv2,1); /* return additional info */
  1104.   SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
  1105.   SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
  1106.   SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
  1107.   SSVAL(outbuf,smb_vwv8,1);
  1108.   SSVAL(outbuf,smb_vwv11,0xffff);
  1109.   SSVAL(outbuf,smb_vwv12,0xffff);
  1110.   
  1111.   p = smb_buf(outbuf);
  1112.   pstrcpy(p,rname);
  1113.   p = skip_string(p,1);
  1114.  
  1115.   /* do a chained openX with a readX? */
  1116. #if 1
  1117.   if (finfo.size > 0)
  1118.     {
  1119.       DEBUG(3,("Chaining readX wth openX\n"));
  1120.       SSVAL(outbuf,smb_vwv0,SMBreadX);
  1121.       SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
  1122.       bzero(p,200);
  1123.       p -= smb_wct;
  1124.       SSVAL(p,smb_wct,10);
  1125.       SSVAL(p,smb_vwv0,0xFF);
  1126.       SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
  1127.       SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
  1128.       smb_setlen(outbuf,smb_len(outbuf)+11*2+1);  
  1129.     }
  1130. #endif
  1131.  
  1132.   if(!strcmp(lname,"-"))
  1133.     handle = fileno(stdout);
  1134.   else 
  1135.     {
  1136.       handle = creat(lname,0644);
  1137.       newhandle = True;
  1138.     }
  1139.   if (handle < 0)
  1140.     {
  1141.       DEBUG(0,("Error opening local file %s\n",lname));
  1142.       free(inbuf);free(outbuf);
  1143.       return;
  1144.     }
  1145.  
  1146.   send_smb(Client,outbuf);
  1147.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1148.  
  1149.   if (CVAL(inbuf,smb_rcls) != 0)
  1150.     {
  1151.       if (CVAL(inbuf,smb_rcls) == ERRSRV &&
  1152.       SVAL(inbuf,smb_err) == ERRnoresource &&
  1153.       cli_reopen_connection(inbuf,outbuf))
  1154.     {
  1155.       do_get(rname,lname,finfo1);
  1156.       return;
  1157.     }
  1158.       DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  1159.       if(newhandle)
  1160.     close(handle);
  1161.       free(inbuf);free(outbuf);
  1162.       return;
  1163.     }
  1164.  
  1165.   pstrcpy(finfo.name,rname);
  1166.  
  1167.   if (!finfo1)
  1168.     {
  1169.       finfo.mode = SVAL(inbuf,smb_vwv3);
  1170.       /* these times arrive as LOCAL time, using the DST offset 
  1171.      corresponding to that time, we convert them to GMT */
  1172.       finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
  1173.       finfo.atime = finfo.ctime = finfo.mtime;
  1174.       finfo.size = IVAL(inbuf,smb_vwv6);
  1175.     }
  1176.  
  1177.   DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
  1178.  
  1179.   fnum = SVAL(inbuf,smb_vwv2);
  1180.  
  1181.   /* we might have got some data from a chained readX */
  1182.   if (SVAL(inbuf,smb_vwv0) == SMBreadX)
  1183.     {
  1184.       p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
  1185.       datalen = SVAL(p,smb_vwv5);
  1186.       dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
  1187.     }
  1188.   else
  1189.     {
  1190.       dataptr = NULL;
  1191.       datalen = 0;
  1192.     }
  1193.  
  1194.  
  1195.   DEBUG(2,("getting file %s of size %d bytes as %s ",
  1196.        CNV_LANG(finfo.name),
  1197.        finfo.size,
  1198.        lname));
  1199.  
  1200.   while (nread < finfo.size && !close_done)
  1201.     {
  1202.       int method = -1;
  1203.       static BOOL can_chain_close = True;
  1204.  
  1205.       p=NULL;
  1206.       
  1207.       DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
  1208.  
  1209.       /* 3 possible read types. readbraw if a large block is required.
  1210.      readX + close if not much left and read if neither is supported */
  1211.  
  1212.       /* we might have already read some data from a chained readX */
  1213.       if (dataptr && datalen>0)
  1214.     method=3;
  1215.  
  1216.       /* if we can finish now then readX+close */
  1217.       if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) && 
  1218.       ((finfo.size - nread) < 
  1219.        (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
  1220.     method = 0;
  1221.  
  1222.       /* if we support readraw then use that */
  1223.       if (method<0 && readbraw_supported)
  1224.     method = 1;
  1225.  
  1226.       /* if we can then use readX */
  1227.       if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
  1228.     method = 2;
  1229.  
  1230.       switch (method)
  1231.     {
  1232.       /* use readX */
  1233.     case 0:
  1234.     case 2:
  1235.       if (method == 0)
  1236.         close_done = True;
  1237.         
  1238.       /* use readX + close */
  1239.       bzero(outbuf,smb_size);
  1240.       set_message(outbuf,10,0,True);
  1241.       CVAL(outbuf,smb_com) = SMBreadX;
  1242.       SSVAL(outbuf,smb_tid,cnum);
  1243.       cli_setup_pkt(outbuf);
  1244.       
  1245.       if (close_done)
  1246.         {
  1247.           CVAL(outbuf,smb_vwv0) = SMBclose;
  1248.           SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
  1249.         }
  1250.       else
  1251.         CVAL(outbuf,smb_vwv0) = 0xFF;          
  1252.       
  1253.       SSVAL(outbuf,smb_vwv2,fnum);
  1254.       SIVAL(outbuf,smb_vwv3,nread);
  1255.       SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
  1256.       SSVAL(outbuf,smb_vwv6,0);
  1257.       SIVAL(outbuf,smb_vwv7,0);
  1258.       SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
  1259.       
  1260.       if (close_done)
  1261.         {
  1262.           p = smb_buf(outbuf);
  1263.           bzero(p,9);
  1264.           
  1265.           CVAL(p,0) = 3;
  1266.           SSVAL(p,1,fnum);
  1267.           SIVALS(p,3,-1);
  1268.           
  1269.           /* now set the total packet length */
  1270.           smb_setlen(outbuf,smb_len(outbuf)+9);
  1271.         }
  1272.       
  1273.       send_smb(Client,outbuf);
  1274.       client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1275.       
  1276.       if (CVAL(inbuf,smb_rcls) != 0)
  1277.         {
  1278.           DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
  1279.           break;
  1280.         }
  1281.       
  1282.       if (close_done &&
  1283.           SVAL(inbuf,smb_vwv0) != SMBclose)
  1284.         {
  1285.           /* NOTE: WfWg sometimes just ignores the chained
  1286.          command! This seems to break the spec? */
  1287.           DEBUG(3,("Rejected chained close?\n"));
  1288.           close_done = False;
  1289.           can_chain_close = False;
  1290.           ignore_close_error = True;
  1291.         }
  1292.       
  1293.       datalen = SVAL(inbuf,smb_vwv5);
  1294.       dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
  1295.       break;
  1296.  
  1297.       /* use readbraw */
  1298.     case 1:
  1299.       {
  1300.         static int readbraw_size = BUFFER_SIZE;
  1301.       
  1302.         extern int Client;
  1303.         bzero(outbuf,smb_size);
  1304.         set_message(outbuf,8,0,True);
  1305.         CVAL(outbuf,smb_com) = SMBreadbraw;
  1306.         SSVAL(outbuf,smb_tid,cnum);
  1307.         cli_setup_pkt(outbuf);
  1308.         SSVAL(outbuf,smb_vwv0,fnum);
  1309.         SIVAL(outbuf,smb_vwv1,nread);
  1310.         SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
  1311.         SSVAL(outbuf,smb_vwv4,0);
  1312.         SIVALS(outbuf,smb_vwv5,-1);
  1313.         send_smb(Client,outbuf);
  1314.  
  1315.         /* Now read the raw data into the buffer and write it */      
  1316.         if(read_smb_length(Client,inbuf,0) == -1) {
  1317.           DEBUG(0,("Failed to read length in readbraw\n"));        
  1318.           exit(1);
  1319.         }
  1320.         
  1321.         /* Even though this is not an smb message, smb_len
  1322.            returns the generic length of an smb message */
  1323.         datalen = smb_len(inbuf);
  1324.  
  1325.         if (datalen == 0)
  1326.           {
  1327.         /* we got a readbraw error */
  1328.         DEBUG(4,("readbraw error - reducing size\n"));
  1329.         readbraw_size = (readbraw_size * 9) / 10;
  1330.         
  1331.         if (readbraw_size < max_xmit)
  1332.           {
  1333.             DEBUG(0,("disabling readbraw\n"));
  1334.             readbraw_supported = False;
  1335.           }
  1336.         
  1337.         dataptr=NULL;
  1338.         continue;
  1339.           }
  1340.  
  1341.         if(read_data(Client,inbuf,datalen) != datalen) {
  1342.           DEBUG(0,("Failed to read data in readbraw\n"));
  1343.           exit(1);
  1344.         }
  1345.         dataptr = inbuf;
  1346.       }
  1347.       break;
  1348.  
  1349.     case 3:
  1350.       /* we've already read some data with a chained readX */
  1351.       break;
  1352.  
  1353.     default:
  1354.       /* use plain read */
  1355.       bzero(outbuf,smb_size);
  1356.       set_message(outbuf,5,0,True);
  1357.       CVAL(outbuf,smb_com) = SMBread;
  1358.       SSVAL(outbuf,smb_tid,cnum);
  1359.       cli_setup_pkt(outbuf);
  1360.  
  1361.       SSVAL(outbuf,smb_vwv0,fnum);
  1362.       SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
  1363.       SIVAL(outbuf,smb_vwv2,nread);
  1364.       SSVAL(outbuf,smb_vwv4,finfo.size - nread);
  1365.  
  1366.       send_smb(Client,outbuf);
  1367.       client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1368.  
  1369.       if (CVAL(inbuf,smb_rcls) != 0)
  1370.         {
  1371.           DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
  1372.           break;
  1373.         }
  1374.  
  1375.       datalen = SVAL(inbuf,smb_vwv0);
  1376.       dataptr = smb_buf(inbuf) + 3;
  1377.       break;
  1378.     }
  1379.  
  1380.       if (writefile(handle,dataptr,datalen) != datalen)
  1381.     {
  1382.       DEBUG(0,("Error writing local file\n"));
  1383.       break;
  1384.     }
  1385.       
  1386.       nread += datalen;
  1387.       if (datalen == 0) 
  1388.     {
  1389.       DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
  1390.       break;
  1391.     }
  1392.  
  1393.       dataptr=NULL;
  1394.       datalen=0;
  1395.     }
  1396.  
  1397.  
  1398.  
  1399.   if (!close_done)
  1400.     {
  1401.       cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
  1402.       
  1403.       if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
  1404.     {
  1405.       DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
  1406.       if(newhandle)
  1407.         close(handle);
  1408.       free(inbuf);free(outbuf);
  1409.       return;
  1410.     }
  1411.     }
  1412.  
  1413.   if(newhandle)
  1414.     close(handle);
  1415.  
  1416.   if (archive_level >= 2 && (finfo.mode & aARCH)) {
  1417.     bzero(outbuf,smb_size);
  1418.     set_message(outbuf,8,strlen(rname)+4,True);
  1419.     CVAL(outbuf,smb_com) = SMBsetatr;
  1420.     SSVAL(outbuf,smb_tid,cnum);
  1421.     cli_setup_pkt(outbuf);
  1422.     SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
  1423.     SIVALS(outbuf,smb_vwv1,0);
  1424.     p = smb_buf(outbuf);
  1425.     *p++ = 4;
  1426.     pstrcpy(p,rname);
  1427.     p += strlen(p)+1;
  1428.     *p++ = 4;
  1429.     *p = 0;
  1430.     send_smb(Client,outbuf);
  1431.     client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1432.   }
  1433.  
  1434.   {
  1435.     struct timeval tp_end;
  1436.     int this_time;
  1437.  
  1438.     GetTimeOfDay(&tp_end);
  1439.     this_time = 
  1440.       (tp_end.tv_sec - tp_start.tv_sec)*1000 +
  1441.     (tp_end.tv_usec - tp_start.tv_usec)/1000;
  1442.     get_total_time_ms += this_time;
  1443.     get_total_size += finfo.size;
  1444.  
  1445.     DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
  1446.          finfo.size / (1.024*this_time + 1.0e-4),
  1447.          get_total_size / (1.024*get_total_time_ms)));
  1448.   }
  1449.  
  1450.   free(inbuf);free(outbuf);
  1451. }
  1452.  
  1453.  
  1454. /****************************************************************************
  1455.   get a file
  1456.   ****************************************************************************/
  1457. static void cmd_get(char *dum_in, char *dum_out)
  1458. {
  1459.   pstring lname;
  1460.   pstring rname;
  1461.   char *p;
  1462.  
  1463.   pstrcpy(rname,cur_dir);
  1464.   pstrcat(rname,"\\");
  1465.  
  1466.   p = rname + strlen(rname);
  1467.  
  1468.   if (!next_token(NULL,p,NULL)) {
  1469.     DEBUG(0,("get <filename>\n"));
  1470.     return;
  1471.   }
  1472.   pstrcpy(lname,p);
  1473.   dos_clean_name(rname);
  1474.     
  1475.   next_token(NULL,lname,NULL);
  1476.  
  1477.   do_get(rname,lname,NULL);
  1478. }
  1479.  
  1480.  
  1481. /****************************************************************************
  1482.   do a mget operation on one file
  1483.   ****************************************************************************/
  1484. static void do_mget(file_info *finfo)
  1485. {
  1486.   pstring rname;
  1487.   pstring quest;
  1488.  
  1489.   if (strequal(finfo->name,".") || strequal(finfo->name,".."))
  1490.     return;
  1491.  
  1492.   if (abort_mget)
  1493.     {
  1494.       DEBUG(0,("mget aborted\n"));
  1495.       return;
  1496.     }
  1497.  
  1498.   if (finfo->mode & aDIR)
  1499.     slprintf(quest,sizeof(pstring)-1,
  1500.          "Get directory %s? ",CNV_LANG(finfo->name));
  1501.   else
  1502.     slprintf(quest,sizeof(pstring)-1,
  1503.          "Get file %s? ",CNV_LANG(finfo->name));
  1504.  
  1505.   if (prompt && !yesno(quest)) return;
  1506.  
  1507.   if (finfo->mode & aDIR)
  1508.     {
  1509.       pstring saved_curdir;
  1510.       pstring mget_mask;
  1511.       char *inbuf,*outbuf;
  1512.  
  1513.       inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1514.       outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1515.  
  1516.       if (!inbuf || !outbuf)
  1517.     {
  1518.       DEBUG(0,("out of memory\n"));
  1519.       return;
  1520.     }
  1521.  
  1522.       pstrcpy(saved_curdir,cur_dir);
  1523.  
  1524.       pstrcat(cur_dir,finfo->name);
  1525.       pstrcat(cur_dir,"\\");
  1526.  
  1527.       unix_format(finfo->name);
  1528.       {
  1529.     if (lowercase)
  1530.       strlower(finfo->name);
  1531.  
  1532.     if (!directory_exist(finfo->name,NULL) && 
  1533.         sys_mkdir(finfo->name,0777) != 0) 
  1534.       {
  1535.         DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
  1536.         pstrcpy(cur_dir,saved_curdir);
  1537.         free(inbuf);free(outbuf);
  1538.         return;
  1539.       }
  1540.  
  1541.     if (sys_chdir(finfo->name) != 0)
  1542.       {
  1543.         DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
  1544.         pstrcpy(cur_dir,saved_curdir);
  1545.         free(inbuf);free(outbuf);
  1546.         return;
  1547.       }
  1548.       }       
  1549.  
  1550.       pstrcpy(mget_mask,cur_dir);
  1551.       pstrcat(mget_mask,"*");
  1552.       
  1553.       do_dir((char *)inbuf,(char *)outbuf,
  1554.          mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False, False);
  1555.       chdir("..");
  1556.       pstrcpy(cur_dir,saved_curdir);
  1557.       free(inbuf);free(outbuf);
  1558.     }
  1559.   else
  1560.     {
  1561.       pstrcpy(rname,cur_dir);
  1562.       pstrcat(rname,finfo->name);
  1563.       do_get(rname,finfo->name,finfo);
  1564.     }
  1565. }
  1566.  
  1567. /****************************************************************************
  1568. view the file using the pager
  1569. ****************************************************************************/
  1570. static void cmd_more(char *dum_in, char *dum_out)
  1571. {
  1572.   fstring rname,lname,tmpname,pager_cmd;
  1573.   char *pager;
  1574.  
  1575.   pstrcpy(rname,cur_dir);
  1576.   pstrcat(rname,"\\");
  1577.   slprintf(tmpname,
  1578.        sizeof(fstring)-1,
  1579.        "%s/smbmore.%d",tmpdir(),(int)getpid());
  1580.   pstrcpy(lname,tmpname);
  1581.  
  1582.   if (!next_token(NULL,rname+strlen(rname),NULL)) {
  1583.     DEBUG(0,("more <filename>\n"));
  1584.     return;
  1585.   }
  1586.   dos_clean_name(rname);
  1587.  
  1588.   do_get(rname,lname,NULL);
  1589.  
  1590.   pager=getenv("PAGER");
  1591.  
  1592.   slprintf(pager_cmd,sizeof(pager_cmd)-1,
  1593.        "%s %s",(pager? pager:PAGER), tmpname);
  1594.   system(pager_cmd);
  1595.   unlink(tmpname);
  1596. }
  1597.  
  1598.  
  1599.  
  1600. /****************************************************************************
  1601. do a mget command
  1602. ****************************************************************************/
  1603. static void cmd_mget(char *inbuf,char *outbuf)
  1604. {
  1605.   int attribute = aSYSTEM | aHIDDEN;
  1606.   pstring mget_mask;
  1607.   fstring buf;
  1608.   char *p=buf;
  1609.  
  1610.   *mget_mask = 0;
  1611.  
  1612.   if (recurse)
  1613.     attribute |= aDIR;
  1614.  
  1615.   abort_mget = False;
  1616.  
  1617.   while (next_token(NULL,p,NULL))
  1618.     {
  1619.       pstrcpy(mget_mask,cur_dir);
  1620.       if(mget_mask[strlen(mget_mask)-1]!='\\')
  1621.     pstrcat(mget_mask,"\\");
  1622.  
  1623.       if (*p == '\\')
  1624.     pstrcpy(mget_mask,p);
  1625.       else
  1626.     pstrcat(mget_mask,p);
  1627.       do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
  1628.     }
  1629.  
  1630.   if (! *mget_mask)
  1631.     {
  1632.       pstrcpy(mget_mask,cur_dir);
  1633.       if(mget_mask[strlen(mget_mask)-1]!='\\')
  1634.     pstrcat(mget_mask,"\\");
  1635.       pstrcat(mget_mask,"*");
  1636.       do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
  1637.     }
  1638. }
  1639.  
  1640. /****************************************************************************
  1641. make a directory of name "name"
  1642. ****************************************************************************/
  1643. static BOOL do_mkdir(char *name)
  1644. {
  1645.   char *p;
  1646.   char *inbuf,*outbuf;
  1647.  
  1648.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1649.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1650.  
  1651.   if (!inbuf || !outbuf)
  1652.     {
  1653.       DEBUG(0,("out of memory\n"));
  1654.       return False;
  1655.     }
  1656.  
  1657.   bzero(outbuf,smb_size);
  1658.   set_message(outbuf,0,2 + strlen(name),True);
  1659.   
  1660.   CVAL(outbuf,smb_com) = SMBmkdir;
  1661.   SSVAL(outbuf,smb_tid,cnum);
  1662.   cli_setup_pkt(outbuf);
  1663.  
  1664.   
  1665.   p = smb_buf(outbuf);
  1666.   *p++ = 4;      
  1667.   pstrcpy(p,name);
  1668.   
  1669.   send_smb(Client,outbuf);
  1670.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1671.   
  1672.   if (CVAL(inbuf,smb_rcls) != 0)
  1673.     {
  1674.       DEBUG(0,("%s making remote directory %s\n",
  1675.            smb_errstr(inbuf),CNV_LANG(name)));
  1676.  
  1677.       free(inbuf);free(outbuf);
  1678.       return(False);
  1679.     }
  1680.  
  1681.   free(inbuf);free(outbuf);
  1682.   return(True);
  1683. }
  1684.  
  1685.  
  1686. /****************************************************************************
  1687.   make a directory
  1688.   ****************************************************************************/
  1689. static void cmd_mkdir(char *inbuf,char *outbuf)
  1690. {
  1691.   pstring mask;
  1692.   fstring buf;
  1693.   char *p=buf;
  1694.   
  1695.   pstrcpy(mask,cur_dir);
  1696.  
  1697.   if (!next_token(NULL,p,NULL))
  1698.     {
  1699.       if (!recurse)
  1700.     DEBUG(0,("mkdir <dirname>\n"));
  1701.       return;
  1702.     }
  1703.   pstrcat(mask,p);
  1704.  
  1705.   if (recurse)
  1706.     {
  1707.       pstring ddir;
  1708.       pstring ddir2;
  1709.       *ddir2 = 0;
  1710.  
  1711.       pstrcpy(ddir,mask);
  1712.       trim_string(ddir,".",NULL);
  1713.       p = strtok(ddir,"/\\");
  1714.       while (p)
  1715.     {
  1716.       pstrcat(ddir2,p);
  1717.       if (!chkpath(ddir2,False))
  1718.         {          
  1719.           do_mkdir(ddir2);
  1720.         }
  1721.       pstrcat(ddir2,"\\");
  1722.       p = strtok(NULL,"/\\");
  1723.     }     
  1724.     }
  1725.   else
  1726.     do_mkdir(mask);
  1727. }
  1728.  
  1729.  
  1730. /*******************************************************************
  1731.   write to a file using writebraw
  1732.   ********************************************************************/
  1733. static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
  1734. {
  1735.   extern int Client;
  1736.   pstring inbuf;
  1737.  
  1738.   bzero(outbuf,smb_size);
  1739.   bzero(inbuf,smb_size);  
  1740.   set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
  1741.  
  1742.   CVAL(outbuf,smb_com) = SMBwritebraw;
  1743.   SSVAL(outbuf,smb_tid,cnum);
  1744.   cli_setup_pkt(outbuf);
  1745.  
  1746.   SSVAL(outbuf,smb_vwv0,fnum);
  1747.   SSVAL(outbuf,smb_vwv1,n);
  1748.   SIVAL(outbuf,smb_vwv3,pos);
  1749.   SSVAL(outbuf,smb_vwv7,1);
  1750.  
  1751.   send_smb(Client,outbuf);
  1752.   
  1753.   if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
  1754.     return(0);
  1755.  
  1756.   _smb_setlen(buf-4,n);        /* HACK! XXXX */
  1757.  
  1758.   if (write_socket(Client,buf-4,n+4) != n+4)
  1759.     return(0);
  1760.  
  1761.   if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
  1762.     DEBUG(0,("Error writing remote file (2)\n"));
  1763.     return(0);
  1764.   }
  1765.   return(SVAL(inbuf,smb_vwv0));
  1766. }
  1767.       
  1768.  
  1769.  
  1770. /*******************************************************************
  1771.   write to a file
  1772.   ********************************************************************/
  1773. static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
  1774. {
  1775.   pstring inbuf;
  1776.  
  1777.   if (writebraw_supported && n > (max_xmit-200)) 
  1778.     return(smb_writeraw(outbuf,fnum,pos,buf,n));
  1779.  
  1780.   bzero(outbuf,smb_size);
  1781.   bzero(inbuf,smb_size);
  1782.   set_message(outbuf,5,n + 3,True);
  1783.  
  1784.   CVAL(outbuf,smb_com) = SMBwrite;
  1785.   SSVAL(outbuf,smb_tid,cnum);
  1786.   cli_setup_pkt(outbuf);
  1787.  
  1788.   SSVAL(outbuf,smb_vwv0,fnum);
  1789.   SSVAL(outbuf,smb_vwv1,n);
  1790.   SIVAL(outbuf,smb_vwv2,pos);
  1791.   SSVAL(outbuf,smb_vwv4,0);
  1792.   CVAL(smb_buf(outbuf),0) = 1;
  1793.   SSVAL(smb_buf(outbuf),1,n);
  1794.  
  1795.   memcpy(smb_buf(outbuf)+3,buf,n);
  1796.  
  1797.   send_smb(Client,outbuf);
  1798.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1799.  
  1800.   if (CVAL(inbuf,smb_rcls) != 0) {
  1801.     DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
  1802.     return(0);
  1803.   }
  1804.   return(SVAL(inbuf,smb_vwv0));
  1805. }
  1806.       
  1807.  
  1808.  
  1809. /****************************************************************************
  1810.   put a single file
  1811.   ****************************************************************************/
  1812. static void do_put(char *rname,char *lname,file_info *finfo)
  1813. {
  1814.   int fnum;
  1815.   FILE *f;
  1816.   int nread=0;
  1817.   char *p;
  1818.   char *inbuf,*outbuf; 
  1819.   time_t close_time = finfo->mtime;
  1820.   char *buf=NULL;
  1821.   static int maxwrite=0;
  1822.  
  1823.   struct timeval tp_start;
  1824.   GetTimeOfDay(&tp_start);
  1825.  
  1826.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1827.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1828.  
  1829.   if (!inbuf || !outbuf)
  1830.     {
  1831.       DEBUG(0,("out of memory\n"));
  1832.       return;
  1833.     }
  1834.  
  1835.   bzero(outbuf,smb_size);
  1836.   set_message(outbuf,3,2 + strlen(rname),True);
  1837.  
  1838.   if (finfo->mtime == 0 || finfo->mtime == -1)
  1839.     finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
  1840.  
  1841.   CVAL(outbuf,smb_com) = SMBcreate;
  1842.   SSVAL(outbuf,smb_tid,cnum);
  1843.   cli_setup_pkt(outbuf);
  1844.  
  1845.   SSVAL(outbuf,smb_vwv0,finfo->mode);
  1846.   put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
  1847.   
  1848.   p = smb_buf(outbuf);
  1849.   *p++ = 4;      
  1850.   pstrcpy(p,rname);
  1851.   
  1852.   send_smb(Client,outbuf);
  1853.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1854.   
  1855.   if (CVAL(inbuf,smb_rcls) != 0)
  1856.     {
  1857.       DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  1858.  
  1859.       free(inbuf);free(outbuf);if (buf) free(buf);
  1860.       return;
  1861.     }
  1862.  
  1863.   /* allow files to be piped into smbclient
  1864.      jdblair 24.jun.98 */
  1865.   if (!strcmp(lname, "-")) {
  1866.     f = stdin;
  1867.     /* size of file is not known */
  1868.     finfo->size = 0;
  1869.   } else {
  1870.     f = fopen(lname,"r");
  1871.   }
  1872.  
  1873.   if (!f)
  1874.     {
  1875.       DEBUG(0,("Error opening local file %s\n",lname));
  1876.       free(inbuf);free(outbuf);
  1877.       return;
  1878.     }
  1879.  
  1880.   
  1881.   fnum = SVAL(inbuf,smb_vwv0);
  1882.   if (finfo->size < 0)
  1883.     finfo->size = file_size(lname);
  1884.   
  1885.   DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
  1886.   
  1887.   if (!maxwrite)
  1888.     maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
  1889.  
  1890.   /* This is a rewrite of the read/write loop that doesn't require the input
  1891.      file to be of a known length.  This allows the stream pointer 'f' to
  1892.      refer to stdin.
  1893.  
  1894.      Rather than reallocing the read buffer every loop to keep it the min
  1895.      necessary length this look uses a fixed length buffer and just tests
  1896.      for eof on the file stream at the top of each loop.
  1897.      jdblair, 24.jun.98 */
  1898.  
  1899.   buf = (char *)malloc(maxwrite+4);
  1900.   while (! feof(f) )
  1901.     {
  1902.       int n = maxwrite;
  1903.       int ret;
  1904.  
  1905.       fseek(f,nread,SEEK_SET);
  1906.       if ((n = readfile(buf+4,1,n,f)) < 1)
  1907.     {
  1908.       DEBUG(0,("Error reading local file\n"));
  1909.       break;
  1910.     }      
  1911.  
  1912.       ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
  1913.  
  1914.       if (n != ret) {
  1915.     if (!maxwrite) {
  1916.       DEBUG(0,("Error writing file\n"));
  1917.       break;
  1918.     } else {
  1919.       maxwrite /= 2;
  1920.       continue;
  1921.     }
  1922.       }
  1923.  
  1924.       nread += n;
  1925.     }
  1926.  
  1927.   bzero(outbuf,smb_size);
  1928.   set_message(outbuf,3,0,True);
  1929.   CVAL(outbuf,smb_com) = SMBclose;
  1930.   SSVAL(outbuf,smb_tid,cnum);
  1931.   cli_setup_pkt(outbuf);
  1932.  
  1933.   SSVAL(outbuf,smb_vwv0,fnum);  
  1934.   put_dos_date3(outbuf,smb_vwv1,close_time);
  1935.  
  1936.   send_smb(Client,outbuf);
  1937.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1938.   
  1939.   if (CVAL(inbuf,smb_rcls) != 0)
  1940.     {
  1941.       DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  1942.       fclose(f);
  1943.       free(inbuf);free(outbuf);
  1944.       if (buf) free(buf);
  1945.       return;
  1946.     }
  1947.  
  1948.   
  1949.   fclose(f);
  1950.   free(inbuf);free(outbuf);
  1951.   if (buf) free(buf);
  1952.  
  1953.   {
  1954.     struct timeval tp_end;
  1955.     int this_time;
  1956.  
  1957.     GetTimeOfDay(&tp_end);
  1958.     this_time = 
  1959.       (tp_end.tv_sec - tp_start.tv_sec)*1000 +
  1960.     (tp_end.tv_usec - tp_start.tv_usec)/1000;
  1961.     put_total_time_ms += this_time;
  1962.     put_total_size += finfo->size;
  1963.  
  1964.     DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
  1965.          finfo->size / (1.024*this_time + 1.0e-4),
  1966.          put_total_size / (1.024*put_total_time_ms)));
  1967.   }
  1968. }
  1969.  
  1970.  
  1971.  
  1972. /****************************************************************************
  1973.   put a file
  1974.   ****************************************************************************/
  1975. static void cmd_put(char *dum_in, char *dum_out)
  1976. {
  1977.   pstring lname;
  1978.   pstring rname;
  1979.   fstring buf;
  1980.   char *p=buf;
  1981.   file_info finfo;
  1982.   finfo = def_finfo;
  1983.   
  1984.   pstrcpy(rname,cur_dir);
  1985.   pstrcat(rname,"\\");
  1986.   
  1987.   
  1988.   if (!next_token(NULL,p,NULL))
  1989.     {
  1990.       DEBUG(0,("put <filename>\n"));
  1991.       return;
  1992.     }
  1993.   pstrcpy(lname,p);
  1994.   
  1995.   if (next_token(NULL,p,NULL))
  1996.     pstrcat(rname,p);      
  1997.   else
  1998.     pstrcat(rname,lname);
  1999.  
  2000.   dos_clean_name(rname);
  2001.  
  2002.   {
  2003.     struct stat st;
  2004.     /* allow '-' to represent stdin
  2005.        jdblair, 24.jun.98 */
  2006.     if (!file_exist(lname,&st) &&
  2007.       (strcmp(lname,"-"))) {
  2008.       DEBUG(0,("%s does not exist\n",lname));
  2009.       return;
  2010.     }
  2011.     finfo.mtime = st.st_mtime;
  2012.   }
  2013.  
  2014.   do_put(rname,lname,&finfo);
  2015. }
  2016.  
  2017. /****************************************************************************
  2018.   seek in a directory/file list until you get something that doesn't start with
  2019.   the specified name
  2020.   ****************************************************************************/
  2021. static BOOL seek_list(FILE *f,char *name)
  2022. {
  2023.   pstring s;
  2024.   while (!feof(f))
  2025.     {
  2026.       if (fscanf(f,"%s",s) != 1) return(False);
  2027.       trim_string(s,"./",NULL);
  2028.       if (strncmp(s,name,strlen(name)) != 0)
  2029.     {
  2030.       pstrcpy(name,s);
  2031.       return(True);
  2032.     }
  2033.     }
  2034.       
  2035.   return(False);
  2036. }
  2037.  
  2038.  
  2039. /****************************************************************************
  2040.   set the file selection mask
  2041.   ****************************************************************************/
  2042. static void cmd_select(char *dum_in, char *dum_out)
  2043. {
  2044.   pstrcpy(fileselection,"");
  2045.   next_token(NULL,fileselection,NULL);
  2046. }
  2047.  
  2048.  
  2049. /****************************************************************************
  2050.   mput some files
  2051.   ****************************************************************************/
  2052. static void cmd_mput(char *dum_in, char *dum_out)
  2053. {
  2054.   pstring lname;
  2055.   pstring rname;
  2056.   file_info finfo;
  2057.   fstring buf;
  2058.   char *p=buf;
  2059.  
  2060.   finfo = def_finfo;
  2061.  
  2062.   
  2063.   while (next_token(NULL,p,NULL))
  2064.     {
  2065.       struct stat st;
  2066.       pstring cmd;
  2067.       pstring tmpname;
  2068.       FILE *f;
  2069.       
  2070.       slprintf(tmpname,sizeof(pstring)-1,
  2071.            "%s/ls.smb.%d",tmpdir(),(int)getpid());
  2072.       if (recurse)
  2073.     slprintf(cmd,sizeof(pstring)-1,
  2074.         "find . -name \"%s\" -print > %s",p,tmpname);
  2075.       else
  2076.     slprintf(cmd,sizeof(pstring)-1,
  2077.          "/bin/ls %s > %s",p,tmpname);
  2078.       system(cmd);
  2079.  
  2080.       f = fopen(tmpname,"r");
  2081.       if (!f) continue;
  2082.  
  2083.       while (!feof(f))
  2084.     {
  2085.       pstring quest;
  2086.  
  2087.       if (fscanf(f,"%s",lname) != 1) break;
  2088.       trim_string(lname,"./",NULL);
  2089.  
  2090.     again1:
  2091.  
  2092.       /* check if it's a directory */
  2093.       if (directory_exist(lname,&st))
  2094.         {
  2095.           if (!recurse) continue;
  2096.           slprintf(quest,sizeof(pstring)-1,
  2097.                "Put directory %s? ",lname);
  2098.           if (prompt && !yesno(quest)) 
  2099.         {
  2100.           pstrcat(lname,"/");
  2101.           if (!seek_list(f,lname))
  2102.             break;
  2103.           goto again1;            
  2104.         }
  2105.           
  2106.           pstrcpy(rname,cur_dir);
  2107.           pstrcat(rname,lname);
  2108.           if (!chkpath(rname,False) && !do_mkdir(rname)) {
  2109.         pstrcat(lname,"/");
  2110.         if (!seek_list(f,lname))
  2111.           break;
  2112.         goto again1;                      
  2113.           }
  2114.  
  2115.           continue;
  2116.         }
  2117.       else
  2118.         {
  2119.           slprintf(quest,sizeof(quest)-1,
  2120.                "Put file %s? ",lname);
  2121.           if (prompt && !yesno(quest)) continue;
  2122.  
  2123.           pstrcpy(rname,cur_dir);
  2124.           pstrcat(rname,lname);
  2125.         }
  2126.       dos_format(rname);
  2127.  
  2128.       /* null size so do_put knows to ignore it */
  2129.       finfo.size = -1;
  2130.  
  2131.       /* set the date on the file */
  2132.       finfo.mtime = st.st_mtime;
  2133.  
  2134.       do_put(rname,lname,&finfo);
  2135.     }
  2136.       fclose(f);
  2137.       unlink(tmpname);
  2138.     }
  2139. }
  2140.  
  2141. /****************************************************************************
  2142.   cancel a print job
  2143.   ****************************************************************************/
  2144. static void do_cancel(int job)
  2145. {
  2146.   char *rparam = NULL;
  2147.   char *rdata = NULL;
  2148.   char *p;
  2149.   int rdrcnt,rprcnt;
  2150.   pstring param;
  2151.  
  2152.   bzero(param,sizeof(param));
  2153.  
  2154.   p = param;
  2155.   SSVAL(p,0,81);        /* DosPrintJobDel() */
  2156.   p += 2;
  2157.   pstrcpy(p,"W");
  2158.   p = skip_string(p,1);
  2159.   pstrcpy(p,"");
  2160.   p = skip_string(p,1);
  2161.   SSVAL(p,0,job);     
  2162.   p += 2;
  2163.  
  2164.   if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
  2165.            6, 1000,
  2166.            &rprcnt,&rdrcnt,
  2167.            param,NULL, NULL,
  2168.            &rparam,&rdata))
  2169.     {
  2170.       int res = SVAL(rparam,0);
  2171.  
  2172.       if (!res)
  2173.     printf("Job %d cancelled\n",job);
  2174.       else
  2175.     printf("Error %d calcelling job %d\n",res,job);
  2176.       return;
  2177.     }
  2178.   else
  2179.   printf("Server refused cancel request\n");
  2180.  
  2181.   if (rparam) free(rparam);
  2182.   if (rdata) free(rdata);
  2183.  
  2184.   return;
  2185. }
  2186.  
  2187.  
  2188. /****************************************************************************
  2189.   cancel a print job
  2190.   ****************************************************************************/
  2191. static void cmd_cancel(char *inbuf,char *outbuf )
  2192. {
  2193.   fstring buf;
  2194.   int job; 
  2195.  
  2196.   if (!connect_as_printer)
  2197.     {
  2198.       DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
  2199.       DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
  2200.     }
  2201.  
  2202.   if (!next_token(NULL,buf,NULL)) {
  2203.     printf("cancel <jobid> ...\n");
  2204.     return;
  2205.   }
  2206.   do {
  2207.     job = atoi(buf);
  2208.     do_cancel(job);
  2209.   } while (next_token(NULL,buf,NULL));
  2210. }
  2211.  
  2212.  
  2213.  
  2214.  
  2215. /****************************************************************************
  2216.   print a file
  2217.   ****************************************************************************/
  2218. static void cmd_print(char *inbuf,char *outbuf )
  2219. {
  2220.   int fnum;
  2221.   FILE *f = NULL;
  2222.   uint32 nread=0;
  2223.   pstring lname;
  2224.   pstring rname;
  2225.   char *p;
  2226.  
  2227.   if (!connect_as_printer)
  2228.     {
  2229.       DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
  2230.       DEBUG(0,("Trying to print without -P may fail\n"));
  2231.     }
  2232.  
  2233.   if (!next_token(NULL,lname,NULL))
  2234.     {
  2235.       DEBUG(0,("print <filename>\n"));
  2236.       return;
  2237.     }
  2238.  
  2239.   pstrcpy(rname,lname);
  2240.   p = strrchr(rname,'/');
  2241.   if (p)
  2242.     {
  2243.       pstring tname;
  2244.       pstrcpy(tname,p+1);
  2245.       pstrcpy(rname,tname);
  2246.     }
  2247.  
  2248.   if ((int)strlen(rname) > 14)
  2249.     rname[14] = 0;
  2250.  
  2251.   if (strequal(lname,"-"))
  2252.     {
  2253.       f = stdin;
  2254.       pstrcpy(rname,"stdin");
  2255.     }
  2256.   
  2257.   dos_clean_name(rname);
  2258.  
  2259.   bzero(outbuf,smb_size);
  2260.   set_message(outbuf,2,2 + strlen(rname),True);
  2261.   
  2262.   CVAL(outbuf,smb_com) = SMBsplopen;
  2263.   SSVAL(outbuf,smb_tid,cnum);
  2264.   cli_setup_pkt(outbuf);
  2265.  
  2266.   SSVAL(outbuf,smb_vwv0,0);
  2267.   SSVAL(outbuf,smb_vwv1,printmode);
  2268.   
  2269.   p = smb_buf(outbuf);
  2270.   *p++ = 4;      
  2271.   pstrcpy(p,rname);
  2272.   
  2273.   send_smb(Client,outbuf);
  2274.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2275.   
  2276.   if (CVAL(inbuf,smb_rcls) != 0)
  2277.     {
  2278.       DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  2279.       return;
  2280.     }
  2281.   
  2282.   if (!f)
  2283.     f = fopen(lname,"r");
  2284.   if (!f)
  2285.     {
  2286.       DEBUG(0,("Error opening local file %s\n",lname));
  2287.       return;
  2288.     }
  2289.  
  2290.   
  2291.   fnum = SVAL(inbuf,smb_vwv0);
  2292.   
  2293.   DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
  2294.   
  2295.   while (!feof(f))
  2296.     {
  2297.       int n;
  2298.   
  2299.       bzero(outbuf,smb_size);
  2300.       set_message(outbuf,1,3,True);
  2301.  
  2302.       /* for some strange reason the OS/2 print server can't handle large
  2303.      packets when printing. weird */
  2304.       n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
  2305.  
  2306.       if (translation)
  2307.     n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
  2308.       else
  2309.     n = readfile(smb_buf(outbuf)+3,1,n,f);
  2310.       if (n <= 0) 
  2311.     {
  2312.       DEBUG(0,("read gave %d\n",n));
  2313.       break;
  2314.     }
  2315.  
  2316.       smb_setlen(outbuf,smb_len(outbuf) + n);
  2317.  
  2318.       CVAL(outbuf,smb_com) = SMBsplwr;
  2319.       SSVAL(outbuf,smb_tid,cnum);
  2320.       cli_setup_pkt(outbuf);
  2321.  
  2322.       SSVAL(outbuf,smb_vwv0,fnum);
  2323.       SSVAL(outbuf,smb_vwv1,n+3);
  2324.       CVAL(smb_buf(outbuf),0) = 1;
  2325.       SSVAL(smb_buf(outbuf),1,n);
  2326.  
  2327.       send_smb(Client,outbuf);
  2328.       client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2329.  
  2330.       if (CVAL(inbuf,smb_rcls) != 0)
  2331.     {
  2332.       DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
  2333.       break;
  2334.     }
  2335.  
  2336.       nread += n;
  2337.     }
  2338.  
  2339.   DEBUG(2,("%d bytes printed\n",nread));
  2340.  
  2341.   bzero(outbuf,smb_size);
  2342.   set_message(outbuf,1,0,True);
  2343.   CVAL(outbuf,smb_com) = SMBsplclose;
  2344.   SSVAL(outbuf,smb_tid,cnum);
  2345.   cli_setup_pkt(outbuf);
  2346.  
  2347.   SSVAL(outbuf,smb_vwv0,fnum);
  2348.  
  2349.   send_smb(Client,outbuf);
  2350.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2351.   
  2352.   if (CVAL(inbuf,smb_rcls) != 0)
  2353.     {
  2354.       DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
  2355.       if (f != stdin)
  2356.     fclose(f);
  2357.       return;
  2358.     }
  2359.  
  2360.   if (f != stdin)
  2361.     fclose(f);
  2362. }
  2363.  
  2364. /****************************************************************************
  2365. show a print queue - this is deprecated as it uses the old smb that
  2366. has limited support - the correct call is the cmd_p_queue_4() after this.
  2367. ****************************************************************************/
  2368. static void cmd_queue(char *inbuf,char *outbuf )
  2369. {
  2370.   int count;
  2371.   char *p;
  2372.  
  2373.   bzero(outbuf,smb_size);
  2374.   set_message(outbuf,2,0,True);
  2375.   
  2376.   CVAL(outbuf,smb_com) = SMBsplretq;
  2377.   SSVAL(outbuf,smb_tid,cnum);
  2378.   cli_setup_pkt(outbuf);
  2379.  
  2380.   SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
  2381.   SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
  2382.   
  2383.   send_smb(Client,outbuf);
  2384.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2385.   
  2386.   if (CVAL(inbuf,smb_rcls) != 0)
  2387.     {
  2388.       DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
  2389.       return;
  2390.     }
  2391.  
  2392.   count = SVAL(inbuf,smb_vwv0);
  2393.   p = smb_buf(inbuf) + 3;
  2394.   if (count <= 0)
  2395.     {
  2396.       DEBUG(0,("No entries in the print queue\n"));
  2397.       return;
  2398.     }  
  2399.  
  2400.   {
  2401.     char status[20];
  2402.  
  2403.     DEBUG(0,("Job      Name              Size         Status\n"));
  2404.  
  2405.     while (count--)
  2406.       {
  2407.     switch (CVAL(p,4))
  2408.       {
  2409.       case 0x01: safe_strcpy(status,"held or stopped",sizeof(status)-1); break;
  2410.       case 0x02: safe_strcpy(status,"printing",sizeof(status)-1); break;
  2411.       case 0x03: safe_strcpy(status,"awaiting print",sizeof(status)-1); break;
  2412.       case 0x04: safe_strcpy(status,"in intercept",sizeof(status)-1); break;
  2413.       case 0x05: safe_strcpy(status,"file had error",sizeof(status)-1); break;
  2414.       case 0x06: safe_strcpy(status,"printer error",sizeof(status)-1); break;
  2415.       default: safe_strcpy(status,"unknown",sizeof(status)-1); break;
  2416.       }
  2417.  
  2418.     DEBUG(0,("%-6d   %-16.16s  %-9d    %s\n",
  2419.          SVAL(p,5),p+12,IVAL(p,7),status));
  2420.     p += 28;
  2421.       }
  2422.   }
  2423.   
  2424. }
  2425.  
  2426.  
  2427. /****************************************************************************
  2428. show information about a print queue
  2429. ****************************************************************************/
  2430. static void cmd_p_queue_4(char *inbuf,char *outbuf )
  2431. {
  2432.   char *rparam = NULL;
  2433.   char *rdata = NULL;
  2434.   char *p;
  2435.   int rdrcnt, rprcnt;
  2436.   pstring param;
  2437.   int result_code=0;
  2438.  
  2439.   if (!connect_as_printer)
  2440.     {
  2441.       DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
  2442.       DEBUG(0,("Trying to print without -P may fail\n"));
  2443.     }
  2444.   
  2445.   bzero(param,sizeof(param));
  2446.  
  2447.   p = param;
  2448.   SSVAL(p,0,76);                        /* API function number 76 (DosPrintJobEnum) */
  2449.   p += 2;
  2450.   pstrcpy(p,"zWrLeh");                   /* parameter description? */
  2451.   p = skip_string(p,1);
  2452.   pstrcpy(p,"WWzWWDDzz");                /* returned data format */
  2453.   p = skip_string(p,1);
  2454.   pstrcpy(p,strrchr(service,'\\')+1);    /* name of queue */
  2455.   p = skip_string(p,1);
  2456.   SSVAL(p,0,2);                 /* API function level 2, PRJINFO_2 data structure */
  2457.   SSVAL(p,2,1000);                      /* size of bytes of returned data buffer */
  2458.   p += 4;
  2459.   pstrcpy(p,"");                         /* subformat */
  2460.   p = skip_string(p,1);
  2461.  
  2462.   DEBUG(1,("Calling DosPrintJobEnum()...\n"));
  2463.   if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
  2464.                10, 4096,
  2465.                &rprcnt, &rdrcnt,
  2466.                param, NULL, NULL,
  2467.                &rparam, &rdata) )
  2468.     {
  2469.       int converter;
  2470.       result_code = SVAL(rparam,0);
  2471.       converter = SVAL(rparam,2);             /* conversion factor */
  2472.  
  2473.       DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
  2474.  
  2475.       if (result_code == 0)                   /* if no error, */
  2476.         {
  2477.           int i;
  2478.           uint16 JobId;
  2479.           uint16 Priority;
  2480.           uint32 Size;
  2481.           char *UserName;
  2482.           char *JobName;
  2483.           char *JobTimeStr;
  2484.           time_t JobTime;
  2485.           char PrinterName[20];
  2486.              
  2487.           safe_strcpy(PrinterName,strrchr(service,'\\')+1,sizeof(PrinterName)-1);       /* name of queue */
  2488.           strlower(PrinterName);                             /* in lower case */
  2489.  
  2490.           p = rdata;                          /* received data */
  2491.           for( i = 0; i < SVAL(rparam,4); ++i)
  2492.             {
  2493.               JobId = SVAL(p,0);
  2494.               Priority = SVAL(p,2);
  2495.               UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
  2496.               strlower(UserName);
  2497.               Priority = SVAL(p,2);
  2498.               JobTime = make_unix_date3( p + 12);
  2499.               JobTimeStr = asctime(LocalTime( &JobTime));
  2500.               Size = IVAL(p,16);
  2501.               JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
  2502.             
  2503.  
  2504.               printf("%s-%u    %s    priority %u   %s    %s   %u bytes\n", 
  2505.         PrinterName, JobId, UserName,
  2506.                 Priority, JobTimeStr, JobName, Size);
  2507.    
  2508. #if 0 /* DEBUG code */
  2509.               printf("Job Id: \"%u\"\n", SVAL(p,0));
  2510.               printf("Priority: \"%u\"\n", SVAL(p,2));
  2511.             
  2512.               printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
  2513.               printf("Position: \"%u\"\n", SVAL(p,8));
  2514.               printf("Status: \"%u\"\n", SVAL(p,10));
  2515.             
  2516.               JobTime = make_unix_date3( p + 12);
  2517.               printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
  2518.               printf("date: \"%u\"\n", SVAL(p,12));
  2519.  
  2520.               printf("Size: \"%u\"\n", SVAL(p,16));
  2521.               printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
  2522.               printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
  2523. #endif /* DEBUG CODE */ 
  2524.               p += 28;
  2525.             }
  2526.         }
  2527.     }
  2528.   else                  /* cli_call_api() failed */
  2529.     {
  2530.       printf("Failed, error = %d\n", result_code);
  2531.     }
  2532.  
  2533.   /* If any parameters or data were returned, free the storage. */
  2534.   if(rparam) free(rparam);
  2535.   if(rdata) free(rdata);
  2536.  
  2537.   return;
  2538. }
  2539.  
  2540. /****************************************************************************
  2541. show information about a print queue
  2542. ****************************************************************************/
  2543. static void cmd_qinfo(char *inbuf,char *outbuf )
  2544. {
  2545.   char *rparam = NULL;
  2546.   char *rdata = NULL;
  2547.   char *p;
  2548.   int rdrcnt, rprcnt;
  2549.   pstring param;
  2550.   int result_code=0;
  2551.   
  2552.   bzero(param,sizeof(param));
  2553.  
  2554.   p = param;
  2555.   SSVAL(p,0,70);             /* API function number 70 (DosPrintQGetInfo) */
  2556.   p += 2;
  2557.   pstrcpy(p,"zWrLh");            /* parameter description? */
  2558.   p = skip_string(p,1);
  2559.   pstrcpy(p,"zWWWWzzzzWWzzl");        /* returned data format */
  2560.   p = skip_string(p,1);
  2561.   pstrcpy(p,strrchr(service,'\\')+1);    /* name of queue */
  2562.   p = skip_string(p,1);
  2563.   SSVAL(p,0,3);                /* API function level 3, just queue info, no job info */
  2564.   SSVAL(p,2,1000);            /* size of bytes of returned data buffer */
  2565.   p += 4;
  2566.   pstrcpy(p,"");                /* subformat */
  2567.   p = skip_string(p,1);
  2568.  
  2569.   DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
  2570.   if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
  2571.            10, 4096,
  2572.            &rprcnt, &rdrcnt,
  2573.            param, NULL, NULL,
  2574.            &rparam, &rdata) )
  2575.     {
  2576.     int converter;
  2577.     result_code = SVAL(rparam,0);
  2578.     converter = SVAL(rparam,2);        /* conversion factor */
  2579.  
  2580.     DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
  2581.  
  2582.     if (result_code == 0)            /* if no error, */
  2583.         {
  2584.         p = rdata;                /* received data */
  2585.  
  2586.         printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
  2587.         printf("Priority: %u\n", SVAL(p,4) );
  2588.         printf("Start time: %u\n", SVAL(p,6) );
  2589.         printf("Until time: %u\n", SVAL(p,8) );
  2590.         printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
  2591.         printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
  2592.         printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
  2593.         printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
  2594.         printf("Status: %u\n", SVAL(p,28) );
  2595.         printf("Jobs: %u\n", SVAL(p,30) );
  2596.         printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
  2597.         printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
  2598.  
  2599.         /* Dump the driver data */
  2600.         {
  2601.         int count, x, y, c;
  2602.         char *ddptr;
  2603.  
  2604.         ddptr = rdata + SVAL(p,40) - converter;
  2605.         if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
  2606.         printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
  2607.  
  2608.         for(x=8; x < count; x+=16)
  2609.         {
  2610.         for(y=0; y < 16; y++)
  2611.             {
  2612.             if( (x+y) < count )
  2613.                 printf("%2.2X ", CVAL(ddptr,(x+y)) );
  2614.             else
  2615.                 fputs("   ", stdout);
  2616.             }
  2617.         for(y=0; y < 16 && (x+y) < count; y++)
  2618.             {
  2619.             c = CVAL(ddptr,(x+y));
  2620.             if(isprint(c))
  2621.                 fputc(c, stdout);
  2622.             else
  2623.                 fputc('.', stdout);
  2624.             }
  2625.         fputc('\n', stdout);
  2626.         }
  2627.         }
  2628.         
  2629.         }
  2630.     }
  2631.   else            /* cli_call_api() failed */
  2632.       {
  2633.       printf("Failed, error = %d\n", result_code);
  2634.       }
  2635.  
  2636.   /* If any parameters or data were returned, free the storage. */
  2637.   if(rparam) free(rparam);
  2638.   if(rdata) free(rdata);
  2639.  
  2640.   return;
  2641. }
  2642.  
  2643. /****************************************************************************
  2644. delete some files
  2645. ****************************************************************************/
  2646. static void do_del(file_info *finfo)
  2647. {
  2648.   char *p;
  2649.   char *inbuf,*outbuf;
  2650.   pstring mask;
  2651.  
  2652.   pstrcpy(mask,cur_dir);
  2653.   pstrcat(mask,finfo->name);
  2654.  
  2655.   if (finfo->mode & aDIR) 
  2656.     return;
  2657.  
  2658.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2659.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2660.   
  2661.   if (!inbuf || !outbuf)
  2662.     {
  2663.       DEBUG(0,("out of memory\n"));
  2664.       return;
  2665.     }
  2666.  
  2667.   bzero(outbuf,smb_size);
  2668.   set_message(outbuf,1,2 + strlen(mask),True);
  2669.   
  2670.   CVAL(outbuf,smb_com) = SMBunlink;
  2671.   SSVAL(outbuf,smb_tid,cnum);
  2672.   cli_setup_pkt(outbuf);
  2673.  
  2674.   SSVAL(outbuf,smb_vwv0,0);
  2675.   
  2676.   p = smb_buf(outbuf);
  2677.   *p++ = 4;      
  2678.   pstrcpy(p,mask);
  2679.   
  2680.   send_smb(Client,outbuf);
  2681.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2682.   
  2683.   if (CVAL(inbuf,smb_rcls) != 0)
  2684.     DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
  2685.  
  2686.   free(inbuf);free(outbuf);
  2687.   
  2688. }
  2689.  
  2690. /****************************************************************************
  2691. delete some files
  2692. ****************************************************************************/
  2693. static void cmd_del(char *inbuf,char *outbuf )
  2694. {
  2695.   pstring mask;
  2696.   fstring buf;
  2697.   int attribute = aSYSTEM | aHIDDEN;
  2698.  
  2699.   if (recurse)
  2700.     attribute |= aDIR;
  2701.   
  2702.   pstrcpy(mask,cur_dir);
  2703.     
  2704.   if (!next_token(NULL,buf,NULL))
  2705.     {
  2706.       DEBUG(0,("del <filename>\n"));
  2707.       return;
  2708.     }
  2709.   pstrcat(mask,buf);
  2710.  
  2711.   do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False,False);
  2712. }
  2713.  
  2714.  
  2715. /****************************************************************************
  2716. remove a directory
  2717. ****************************************************************************/
  2718. static void cmd_rmdir(char *inbuf,char *outbuf )
  2719. {
  2720.   pstring mask;
  2721.   fstring buf;
  2722.   char *p;
  2723.   
  2724.   pstrcpy(mask,cur_dir);
  2725.   
  2726.   if (!next_token(NULL,buf,NULL))
  2727.     {
  2728.       DEBUG(0,("rmdir <dirname>\n"));
  2729.       return;
  2730.     }
  2731.   pstrcat(mask,buf);
  2732.  
  2733.   bzero(outbuf,smb_size);
  2734.   set_message(outbuf,0,2 + strlen(mask),True);
  2735.   
  2736.   CVAL(outbuf,smb_com) = SMBrmdir;
  2737.   SSVAL(outbuf,smb_tid,cnum);
  2738.   cli_setup_pkt(outbuf);
  2739.  
  2740.   
  2741.   p = smb_buf(outbuf);
  2742.   *p++ = 4;      
  2743.   pstrcpy(p,mask);
  2744.   
  2745.   send_smb(Client,outbuf);
  2746.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2747.   
  2748.   if (CVAL(inbuf,smb_rcls) != 0)
  2749.     {
  2750.       DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
  2751.       return;
  2752.     }
  2753.   
  2754. }
  2755.  
  2756. /****************************************************************************
  2757. rename some files
  2758. ****************************************************************************/
  2759. static void cmd_rename(char *inbuf,char *outbuf )
  2760. {
  2761.   pstring src,dest;
  2762.   fstring buf,buf2;
  2763.   char *p;
  2764.   
  2765.   pstrcpy(src,cur_dir);
  2766.   pstrcpy(dest,cur_dir);
  2767.   
  2768.   if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
  2769.     {
  2770.       DEBUG(0,("rename <src> <dest>\n"));
  2771.       return;
  2772.     }
  2773.   pstrcat(src,buf);
  2774.   pstrcat(dest,buf2);
  2775.  
  2776.   bzero(outbuf,smb_size);
  2777.   set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
  2778.   
  2779.   CVAL(outbuf,smb_com) = SMBmv;
  2780.   SSVAL(outbuf,smb_tid,cnum);
  2781.   SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
  2782.   cli_setup_pkt(outbuf);
  2783.   
  2784.   p = smb_buf(outbuf);
  2785.   *p++ = 4;      
  2786.   pstrcpy(p,src);
  2787.   p = skip_string(p,1);
  2788.   *p++ = 4;      
  2789.   pstrcpy(p,dest);
  2790.   
  2791.   send_smb(Client,outbuf);
  2792.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2793.   
  2794.   if (CVAL(inbuf,smb_rcls) != 0)
  2795.     {
  2796.       DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
  2797.       return;
  2798.     }
  2799.   
  2800. }
  2801.  
  2802.  
  2803. /****************************************************************************
  2804. toggle the prompt flag
  2805. ****************************************************************************/
  2806. static void cmd_prompt(char *dum_in, char *dum_out)
  2807. {
  2808.   prompt = !prompt;
  2809.   DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
  2810. }
  2811.  
  2812.  
  2813. /****************************************************************************
  2814. set the newer than time
  2815. ****************************************************************************/
  2816. static void cmd_newer(char *dum_in, char *dum_out)
  2817. {
  2818.   fstring buf;
  2819.   BOOL ok;
  2820.   struct stat sbuf;
  2821.  
  2822.   ok = next_token(NULL,buf,NULL);
  2823.   if (ok && (sys_stat(buf,&sbuf) == 0))
  2824.     {
  2825.       newer_than = sbuf.st_mtime;
  2826.       DEBUG(1,("Getting files newer than %s",
  2827.            asctime(LocalTime(&newer_than))));
  2828.     }
  2829.   else
  2830.     newer_than = 0;
  2831.  
  2832.   if (ok && newer_than == 0)
  2833.     DEBUG(0,("Error setting newer-than time\n"));
  2834. }
  2835.  
  2836. /****************************************************************************
  2837. set the archive level
  2838. ****************************************************************************/
  2839. static void cmd_archive(char *dum_in, char *dum_out)
  2840. {
  2841.   fstring buf;
  2842.  
  2843.   if (next_token(NULL,buf,NULL)) {
  2844.     archive_level = atoi(buf);
  2845.   } else
  2846.     DEBUG(0,("Archive level is %d\n",archive_level));
  2847. }
  2848.  
  2849. /****************************************************************************
  2850. toggle the lowercaseflag
  2851. ****************************************************************************/
  2852. static void cmd_lowercase(char *dum_in, char *dum_out)
  2853. {
  2854.   lowercase = !lowercase;
  2855.   DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
  2856. }
  2857.  
  2858.  
  2859.  
  2860.  
  2861. /****************************************************************************
  2862. toggle the recurse flag
  2863. ****************************************************************************/
  2864. static void cmd_recurse(char *dum_in, char *dum_out)
  2865. {
  2866.   recurse = !recurse;
  2867.   DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
  2868. }
  2869.  
  2870. /****************************************************************************
  2871. toggle the translate flag
  2872. ****************************************************************************/
  2873. static void cmd_translate(char *dum_in, char *dum_out)
  2874. {
  2875.   translation = !translation;
  2876.   DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
  2877.     translation?"on":"off"));
  2878. }
  2879.  
  2880.  
  2881. /****************************************************************************
  2882. do a printmode command
  2883. ****************************************************************************/
  2884. static void cmd_printmode(char *dum_in, char *dum_out)
  2885. {
  2886.   fstring buf;
  2887.   fstring mode;
  2888.  
  2889.   if (next_token(NULL,buf,NULL))
  2890.     {
  2891.       if (strequal(buf,"text"))
  2892.     printmode = 0;      
  2893.       else
  2894.     {
  2895.       if (strequal(buf,"graphics"))
  2896.         printmode = 1;
  2897.       else
  2898.         printmode = atoi(buf);
  2899.     }
  2900.     }
  2901.  
  2902.   switch(printmode)
  2903.     {
  2904.     case 0: 
  2905.       fstrcpy(mode,"text");
  2906.       break;
  2907.     case 1: 
  2908.       fstrcpy(mode,"graphics");
  2909.       break;
  2910.     default: 
  2911.       slprintf(mode,sizeof(mode)-1,"%d",printmode);
  2912.       break;
  2913.     }
  2914.  
  2915.   DEBUG(2,("the printmode is now %s\n",mode));
  2916. }
  2917.  
  2918. /****************************************************************************
  2919. do the lcd command
  2920. ****************************************************************************/
  2921. static void cmd_lcd(char *dum_in, char *dum_out)
  2922. {
  2923.   fstring buf;
  2924.   pstring d;
  2925.  
  2926.   if (next_token(NULL,buf,NULL))
  2927.     sys_chdir(buf);
  2928.   DEBUG(2,("the local directory is now %s\n",GetWd(d)));
  2929. }
  2930.  
  2931.  
  2932. /****************************************************************************
  2933. try and browse available connections on a host
  2934. ****************************************************************************/
  2935. static BOOL browse_host(BOOL sort)
  2936. {
  2937. #ifdef NOSTRCASECMP
  2938. /* If strcasecmp is already defined, remove it. */
  2939. #ifdef strcasecmp
  2940. #undef strcasecmp
  2941. #endif /* strcasecmp */
  2942. #define strcasecmp StrCaseCmp
  2943. #endif /* NOSTRCASECMP */
  2944.  
  2945.   char *rparam = NULL;
  2946.   char *rdata = NULL;
  2947.   char *p;
  2948.   int rdrcnt,rprcnt;
  2949.   pstring param;
  2950.   int count = -1;
  2951.  
  2952.   /* now send a SMBtrans command with api RNetShareEnum */
  2953.   p = param;
  2954.   SSVAL(p,0,0); /* api number */
  2955.   p += 2;
  2956.   pstrcpy(p,"WrLeh");
  2957.   p = skip_string(p,1);
  2958.   pstrcpy(p,"B13BWz");
  2959.   p = skip_string(p,1);
  2960.   SSVAL(p,0,1);
  2961.   SSVAL(p,2,BUFFER_SIZE);
  2962.   p += 4;
  2963.  
  2964.   if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
  2965.              1024, BUFFER_SIZE,
  2966.                &rprcnt,&rdrcnt,
  2967.            param,NULL, NULL,
  2968.            &rparam,&rdata))
  2969.     {
  2970.       int res = SVAL(rparam,0);
  2971.       int converter=SVAL(rparam,2);
  2972.       int i;
  2973.       BOOL long_share_name=False;
  2974.       
  2975.       if (res == 0)
  2976.     {
  2977.       count=SVAL(rparam,4);
  2978.       p = rdata;
  2979.  
  2980.       if (count > 0)
  2981.         {
  2982.           printf("\n\tSharename      Type      Comment\n");
  2983.           printf("\t---------      ----      -------\n");
  2984.         }
  2985.  
  2986.       if (sort)
  2987.         qsort(p,count,20,QSORT_CAST StrCaseCmp);
  2988.  
  2989.       for (i=0;i<count;i++)
  2990.         {
  2991.           char *sname = p;
  2992.           int type = SVAL(p,14);
  2993.           int comment_offset = IVAL(p,16) & 0xFFFF;
  2994.           fstring typestr;
  2995.           *typestr=0;
  2996.  
  2997.           switch (type)
  2998.         {
  2999.         case STYPE_DISKTREE:
  3000.           fstrcpy(typestr,"Disk"); break;
  3001.         case STYPE_PRINTQ:
  3002.           fstrcpy(typestr,"Printer"); break;          
  3003.         case STYPE_DEVICE:
  3004.           fstrcpy(typestr,"Device"); break;
  3005.         case STYPE_IPC:
  3006.           fstrcpy(typestr,"IPC"); break;      
  3007.         }
  3008.  
  3009.           printf("\t%-15.15s%-10.10s%s\n",
  3010.              sname,
  3011.              typestr,
  3012.              comment_offset?rdata+comment_offset-converter:"");
  3013.       
  3014.           if (strlen(sname)>8) long_share_name=True;
  3015.       
  3016.           p += 20;
  3017.         }
  3018.  
  3019.       if (long_share_name) {
  3020.         printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
  3021.       }
  3022.     }
  3023.     }
  3024.   
  3025.   if (rparam) free(rparam);
  3026.   if (rdata) free(rdata);
  3027.  
  3028.   return(count>0);
  3029. }
  3030.  
  3031.  
  3032. /****************************************************************************
  3033. get some server info
  3034. ****************************************************************************/
  3035. static void server_info(void)
  3036. {
  3037.   char *rparam = NULL;
  3038.   char *rdata = NULL;
  3039.   char *p;
  3040.   int rdrcnt,rprcnt;
  3041.   pstring param;
  3042.  
  3043.   bzero(param,sizeof(param));
  3044.  
  3045.   p = param;
  3046.   SSVAL(p,0,63);         /* NetServerGetInfo()? */
  3047.   p += 2;
  3048.   pstrcpy(p,"WrLh");
  3049.   p = skip_string(p,1);
  3050.   pstrcpy(p,"zzzBBzz");
  3051.   p = skip_string(p,1);
  3052.   SSVAL(p,0,10); /* level 10 */
  3053.   SSVAL(p,2,1000);
  3054.   p += 6;
  3055.  
  3056.   if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
  3057.            6, 1000,
  3058.            &rprcnt,&rdrcnt,
  3059.            param,NULL, NULL,
  3060.            &rparam,&rdata))
  3061.     {
  3062.       int res = SVAL(rparam,0);
  3063.       int converter=SVAL(rparam,2);
  3064.  
  3065.       if (res == 0)
  3066.     {
  3067.       p = rdata;
  3068.  
  3069.       printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
  3070.          rdata+SVAL(p,0)-converter,
  3071.          rdata+SVAL(p,4)-converter,
  3072.          rdata+SVAL(p,8)-converter,
  3073.          rdata+SVAL(p,14)-converter);
  3074.     }
  3075.     }
  3076.  
  3077.   if (rparam) free(rparam);
  3078.   if (rdata) free(rdata);
  3079.  
  3080.   return;
  3081. }
  3082.  
  3083.  
  3084. /****************************************************************************
  3085. try and browse available connections on a host
  3086. ****************************************************************************/
  3087. static BOOL list_servers(char *wk_grp)
  3088. {
  3089.   char *rparam = NULL;
  3090.   char *rdata = NULL;
  3091.   int rdrcnt,rprcnt;
  3092.   char *p,*svtype_p;
  3093.   pstring param;
  3094.   int uLevel = 1;
  3095.   int count = 0;
  3096.   BOOL ok = False;
  3097.   BOOL generic_request = False;
  3098.  
  3099.  
  3100.   if (strequal(wk_grp,"WORKGROUP")) {
  3101.     /* we won't specify a workgroup */
  3102.     generic_request = True;
  3103.   } 
  3104.  
  3105.   /* now send a SMBtrans command with api ServerEnum? */
  3106.   p = param;
  3107.   SSVAL(p,0,0x68); /* api number */
  3108.   p += 2;
  3109.  
  3110.   pstrcpy(p,generic_request?"WrLehDO":"WrLehDz");
  3111.   p = skip_string(p,1);
  3112.  
  3113.   pstrcpy(p,"B16BBDz");
  3114.  
  3115.   p = skip_string(p,1);
  3116.   SSVAL(p,0,uLevel);
  3117.   SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
  3118.   p += 4;
  3119.  
  3120.   svtype_p = p;
  3121.   p += 4;
  3122.  
  3123.   if (!generic_request) {
  3124.     pstrcpy(p, wk_grp);
  3125.     p = skip_string(p,1);
  3126.   }
  3127.  
  3128.   /* first ask for a list of servers in this workgroup */
  3129.   SIVAL(svtype_p,0,SV_TYPE_ALL);
  3130.  
  3131.   if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
  3132.            8, BUFFER_SIZE - SAFETY_MARGIN,
  3133.            &rprcnt,&rdrcnt,
  3134.            param,NULL, NULL,
  3135.            &rparam,&rdata))
  3136.     {
  3137.       int res = SVAL(rparam,0);
  3138.       int converter=SVAL(rparam,2);
  3139.       int i;
  3140.  
  3141.       if (res == 0) {    
  3142.     char *p2 = rdata;
  3143.     count=SVAL(rparam,4);
  3144.  
  3145.     if (count > 0) {
  3146.       printf("\n\nThis machine has a browse list:\n");
  3147.       printf("\n\tServer               Comment\n");
  3148.       printf("\t---------            -------\n");
  3149.     }
  3150.     
  3151.     for (i=0;i<count;i++) {
  3152.       char *sname = p2;
  3153.       int comment_offset = IVAL(p2,22) & 0xFFFF;
  3154.       printf("\t%-16.16s     %s\n",
  3155.          sname,
  3156.          comment_offset?rdata+comment_offset-converter:"");
  3157.  
  3158.       ok=True;
  3159.       p2 += 26;
  3160.     }
  3161.       }
  3162.     }
  3163.  
  3164.   if (rparam) {free(rparam); rparam = NULL;}
  3165.   if (rdata) {free(rdata); rdata = NULL;}
  3166.  
  3167.   /* now ask for a list of workgroups */
  3168.   SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
  3169.  
  3170.   if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
  3171.            8, BUFFER_SIZE - SAFETY_MARGIN,
  3172.            &rprcnt,&rdrcnt,
  3173.            param,NULL, NULL,
  3174.            &rparam,&rdata))
  3175.     {
  3176.       int res = SVAL(rparam,0);
  3177.       int converter=SVAL(rparam,2);
  3178.       int i;
  3179.  
  3180.       if (res == 0) {
  3181.     char *p2 = rdata;
  3182.     count=SVAL(rparam,4);
  3183.  
  3184.     if (count > 0) {
  3185.       printf("\n\nThis machine has a workgroup list:\n");
  3186.       printf("\n\tWorkgroup            Master\n");
  3187.       printf("\t---------            -------\n");
  3188.     }
  3189.     
  3190.     for (i=0;i<count;i++) {
  3191.       char *sname = p2;
  3192.       int comment_offset = IVAL(p2,22) & 0xFFFF;
  3193.       printf("\t%-16.16s     %s\n",
  3194.          sname,
  3195.          comment_offset?rdata+comment_offset-converter:"");
  3196.       
  3197.       ok=True;
  3198.       p2 += 26;
  3199.     }
  3200.       }
  3201.     }
  3202.  
  3203.   if (rparam) free(rparam);
  3204.   if (rdata) free(rdata);
  3205.  
  3206.   return(ok);
  3207. }
  3208.  
  3209.  
  3210. /* This defines the commands supported by this client */
  3211. struct
  3212. {
  3213.   char *name;
  3214.   void (*fn)(char *, char *);
  3215.   char *description;
  3216. } commands[] = 
  3217. {
  3218.   {"ls",cmd_dir,"<mask> list the contents of the current directory"},
  3219.   {"dir",cmd_dir,"<mask> list the contents of the current directory"},
  3220.   {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
  3221.   {"cd",cmd_cd,"[directory] change/report the remote directory"},
  3222.   {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
  3223.   {"get",cmd_get,"<remote name> [local name] get a file"},
  3224.   {"mget",cmd_mget,"<mask> get all the matching files"},
  3225.   {"put",cmd_put,"<local name> [remote name] put a file"},
  3226.   {"mput",cmd_mput,"<mask> put all matching files"},
  3227.   {"rename",cmd_rename,"<src> <dest> rename some files"},
  3228.   {"more",cmd_more,"<remote name> view a remote file with your pager"},  
  3229.   {"mask",cmd_select,"<mask> mask all filenames against this"},
  3230.   {"del",cmd_del,"<mask> delete all matching files"},
  3231.   {"rm",cmd_del,"<mask> delete all matching files"},
  3232.   {"mkdir",cmd_mkdir,"<directory> make a directory"},
  3233.   {"md",cmd_mkdir,"<directory> make a directory"},
  3234.   {"rmdir",cmd_rmdir,"<directory> remove a directory"},
  3235.   {"rd",cmd_rmdir,"<directory> remove a directory"},
  3236.   {"pq",cmd_p_queue_4,"enumerate the print queue"},
  3237.   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},  
  3238.   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},  
  3239.   {"translate",cmd_translate,"toggle text translation for printing"},  
  3240.   {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},  
  3241.   {"print",cmd_print,"<file name> print a file"},
  3242.   {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
  3243.   {"queue",cmd_queue,"show the print queue"},
  3244.   {"qinfo",cmd_qinfo,"show print queue information"},
  3245.   {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
  3246.   {"quit",cli_send_logout,"logoff the server"},
  3247.   {"q",cli_send_logout,"logoff the server"},
  3248.   {"exit",cli_send_logout,"logoff the server"},
  3249.   {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
  3250.   {"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"},
  3251.   {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
  3252.   {"blocksize",cmd_block,"blocksize <number> (default 20)" },
  3253.   {"tarmode",cmd_tarmode,
  3254.      "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
  3255.   {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
  3256.   {"help",cmd_help,"[command] give help on a command"},
  3257.   {"?",cmd_help,"[command] give help on a command"},
  3258.   {"!",NULL,"run a shell command on the local system"},
  3259.   {"",NULL,NULL}
  3260. };
  3261.  
  3262.  
  3263. /*******************************************************************
  3264.   lookup a command string in the list of commands, including 
  3265.   abbreviations
  3266.   ******************************************************************/
  3267. static int process_tok(fstring tok)
  3268. {
  3269.   int i = 0, matches = 0;
  3270.   int cmd=0;
  3271.   int tok_len = strlen(tok);
  3272.   
  3273.   while (commands[i].fn != NULL)
  3274.     {
  3275.       if (strequal(commands[i].name,tok))
  3276.     {
  3277.       matches = 1;
  3278.       cmd = i;
  3279.       break;
  3280.     }
  3281.       else if (strnequal(commands[i].name, tok, tok_len))
  3282.     {
  3283.       matches++;
  3284.       cmd = i;
  3285.     }
  3286.       i++;
  3287.     }
  3288.   
  3289.   if (matches == 0)
  3290.     return(-1);
  3291.   else if (matches == 1)
  3292.     return(cmd);
  3293.   else
  3294.     return(-2);
  3295. }
  3296.  
  3297. /****************************************************************************
  3298. help
  3299. ****************************************************************************/
  3300. void cmd_help(char *dum_in, char *dum_out)
  3301. {
  3302.   int i=0,j;
  3303.   fstring buf;
  3304.  
  3305.   if (next_token(NULL,buf,NULL))
  3306.     {
  3307.       if ((i = process_tok(buf)) >= 0)
  3308.     DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));            
  3309.     }
  3310.   else
  3311.     while (commands[i].description)
  3312.       {
  3313.     for (j=0; commands[i].description && (j<5); j++) {
  3314.       DEBUG(0,("%-15s",commands[i].name));
  3315.       i++;
  3316.     }
  3317.     DEBUG(0,("\n"));
  3318.       }
  3319. }
  3320.  
  3321. /****************************************************************************
  3322. wait for keyboard activity, swallowing network packets
  3323. ****************************************************************************/
  3324. #ifdef CLIX
  3325. static char wait_keyboard(char *buffer)
  3326. #else
  3327. static void wait_keyboard(char *buffer)
  3328. #endif
  3329. {
  3330.   fd_set fds;
  3331.   int selrtn;
  3332.   struct timeval timeout;
  3333.   
  3334. #ifdef CLIX
  3335.   int delay = 0;
  3336. #endif
  3337.   
  3338.   while (1) 
  3339.     {
  3340.       extern int Client;
  3341.       FD_ZERO(&fds);
  3342.       FD_SET(Client,&fds);
  3343. #ifndef CLIX
  3344.       FD_SET(fileno(stdin),&fds);
  3345. #endif
  3346.  
  3347.       timeout.tv_sec = 20;
  3348.       timeout.tv_usec = 0;
  3349. #ifdef CLIX
  3350.       timeout.tv_sec = 0;
  3351. #endif
  3352.       selrtn = sys_select(&fds,&timeout);
  3353.       
  3354. #ifndef CLIX
  3355.       if (FD_ISSET(fileno(stdin),&fds))
  3356.       return;
  3357. #else
  3358.       {
  3359.     char ch;
  3360.     int readret;
  3361.  
  3362.     set_blocking(fileno(stdin), False);    
  3363.     readret = read_data( fileno(stdin), &ch, 1);
  3364.     set_blocking(fileno(stdin), True);
  3365.     if (readret == -1)
  3366.       {
  3367.         if (errno != EAGAIN)
  3368.           {
  3369.         /* should crash here */
  3370.         DEBUG(1,("readchar stdin failed\n"));
  3371.           }
  3372.       }
  3373.     else if (readret != 0)
  3374.       {
  3375.         return ch;
  3376.       }
  3377.       }
  3378. #endif
  3379.  
  3380.       /* We deliberately use receive_smb instead of
  3381.          client_receive_smb as we want to receive
  3382.          session keepalives and then drop them here.
  3383.        */
  3384.       if (FD_ISSET(Client,&fds))
  3385.       receive_smb(Client,buffer,0);
  3386.       
  3387. #ifdef CLIX
  3388.       delay++;
  3389.       if (delay > 100000)
  3390.     {
  3391.       delay = 0;
  3392.       chkpath("\\",False);
  3393.     }
  3394. #else
  3395.       chkpath("\\",False);
  3396. #endif
  3397.     }  
  3398. }
  3399.  
  3400.  
  3401. /****************************************************************************
  3402.   process commands from the client
  3403. ****************************************************************************/
  3404. static BOOL process(char *base_directory)
  3405. {
  3406.   extern FILE *dbf;
  3407.   pstring line;
  3408.   char *cmd;
  3409.  
  3410.   char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3411.   char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3412.  
  3413.   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
  3414.     return(False);
  3415.   
  3416.   bzero(OutBuffer,smb_size);
  3417.  
  3418.   if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
  3419.     return(False);
  3420.  
  3421.   if (*base_directory) do_cd(base_directory);
  3422.  
  3423.   cmd = cmdstr;
  3424.   if (cmd[0] != '\0') while (cmd[0] != '\0')
  3425.     {
  3426.       char *p;
  3427.       fstring tok;
  3428.       int i;
  3429.  
  3430.       if ((p = strchr(cmd, ';')) == 0)
  3431.     {
  3432.       strncpy(line, cmd, 999);
  3433.       line[1000] = '\0';
  3434.       cmd += strlen(cmd);
  3435.     }
  3436.       else
  3437.     {
  3438.       if (p - cmd > 999) p = cmd + 999;
  3439.       strncpy(line, cmd, p - cmd);
  3440.       line[p - cmd] = '\0';
  3441.       cmd = p + 1;
  3442.     }
  3443.  
  3444.       /* input language code to internal one */
  3445.       CNV_INPUT (line);
  3446.       
  3447.       /* and get the first part of the command */
  3448.       {
  3449.     char *ptr = line;
  3450.     if (!next_token(&ptr,tok,NULL)) continue;
  3451.       }
  3452.  
  3453.       if ((i = process_tok(tok)) >= 0)
  3454.     commands[i].fn(InBuffer,OutBuffer);
  3455.       else if (i == -2)
  3456.     DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
  3457.       else
  3458.     DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
  3459.     }
  3460.   else while (!feof(stdin))
  3461.     {
  3462.       fstring tok;
  3463.       int i;
  3464.  
  3465.       bzero(OutBuffer,smb_size);
  3466.  
  3467.       /* display a prompt */
  3468.       DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
  3469.       fflush(dbf);
  3470.  
  3471. #ifdef CLIX
  3472.       line[0] = wait_keyboard(InBuffer);
  3473.       /* this might not be such a good idea... */
  3474.       if ( line[0] == EOF)
  3475.     break;
  3476. #else
  3477.       wait_keyboard(InBuffer);
  3478. #endif
  3479.   
  3480.       /* and get a response */
  3481. #ifdef CLIX
  3482.       fgets( &line[1],999, stdin);
  3483. #else
  3484.       if (!fgets(line,1000,stdin))
  3485.     break;
  3486. #endif
  3487.  
  3488.       /* input language code to internal one */
  3489.       CNV_INPUT (line);
  3490.  
  3491.       /* special case - first char is ! */
  3492.       if (*line == '!')
  3493.     {
  3494.       system(line + 1);
  3495.       continue;
  3496.     }
  3497.       
  3498.       /* and get the first part of the command */
  3499.       {
  3500.     char *ptr = line;
  3501.     if (!next_token(&ptr,tok,NULL)) continue;
  3502.       }
  3503.  
  3504.       if ((i = process_tok(tok)) >= 0)
  3505.     commands[i].fn(InBuffer,OutBuffer);
  3506.       else if (i == -2)
  3507.     DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
  3508.       else
  3509.     DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
  3510.     }
  3511.   
  3512.   cli_send_logout(InBuffer,OutBuffer);
  3513.   return(True);
  3514. }
  3515.  
  3516. /****************************************************************************
  3517. usage on the program
  3518. ****************************************************************************/
  3519. static void usage(char *pname)
  3520. {
  3521.   DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
  3522.        pname));
  3523.  
  3524.   DEBUG(0,("\nVersion %s\n",VERSION));
  3525.   DEBUG(0,("\t-p port               connect to the specified port\n"));
  3526.   DEBUG(0,("\t-d debuglevel         set the debuglevel\n"));
  3527.   DEBUG(0,("\t-l log basename.      Basename for log/debug files\n"));
  3528.   DEBUG(0,("\t-n netbios name.      Use this name as my netbios name\n"));
  3529.   DEBUG(0,("\t-N                    don't ask for a password\n"));
  3530.   DEBUG(0,("\t-P                    connect to service as a printer\n"));
  3531.   DEBUG(0,("\t-M host               send a winpopup message to the host\n"));
  3532.   DEBUG(0,("\t-m max protocol       set the max protocol level\n"));
  3533.   DEBUG(0,("\t-L host               get a list of shares available on a host\n"));
  3534.   DEBUG(0,("\t-I dest IP            use this IP to connect to\n"));
  3535.   DEBUG(0,("\t-R name resolve order use these name resolution services only\n"));
  3536.   DEBUG(0,("\t-E                    write messages to stderr instead of stdout\n"));
  3537.   DEBUG(0,("\t-U username           set the network username\n"));
  3538.   DEBUG(0,("\t-W workgroup          set the workgroup name\n"));
  3539.   DEBUG(0,("\t-c command string     execute semicolon separated commands\n"));
  3540.   DEBUG(0,("\t-t terminal code      terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
  3541.   DEBUG(0,("\t-T<c|x>IXgbNa          command line tar\n"));
  3542.   DEBUG(0,("\t-D directory          start from directory\n"));
  3543.   DEBUG(0,("\n"));
  3544. }
  3545.  
  3546. /****************************************************************************
  3547.   main program
  3548. ****************************************************************************/
  3549.  int main(int argc,char *argv[])
  3550. {
  3551.   fstring base_directory;
  3552.   char *pname = argv[0];
  3553.   int port = SMB_PORT;
  3554.   int opt;
  3555.   extern FILE *dbf;
  3556.   extern char *optarg;
  3557.   extern int optind;
  3558.   pstring query_host;
  3559.   BOOL message = False;
  3560.   BOOL nt_domain_logon = False;
  3561.   extern char tar_type;
  3562.   static pstring servicesf = CONFIGFILE;
  3563.   pstring term_code;
  3564.   pstring new_name_resolve_order;
  3565.   char *p;
  3566.   int save_debuglevel = -1;
  3567.   pstring tempworkgroup;
  3568.  
  3569.   *tempworkgroup = '\0';
  3570. #ifdef KANJI
  3571.   pstrcpy(term_code, KANJI);
  3572. #else /* KANJI */
  3573.   *term_code = 0;
  3574. #endif /* KANJI */
  3575.  
  3576.   *query_host = 0;
  3577.   *base_directory = 0;
  3578.  
  3579.   *new_name_resolve_order = 0;
  3580.  
  3581.   DEBUGLEVEL = 2;
  3582.  
  3583.   setup_logging(pname,True);
  3584.  
  3585.   TimeInit();
  3586.   charset_initialise();
  3587.  
  3588.   pid = getpid();
  3589.   uid = getuid();
  3590.   gid = getgid();
  3591.   mid = pid + 100;
  3592.   myumask = umask(0);
  3593.   umask(myumask);
  3594.  
  3595.   if (getenv("USER"))
  3596.   {
  3597.     pstrcpy(username,getenv("USER"));
  3598.  
  3599.     /* modification to support userid%passwd syntax in the USER var
  3600.        25.Aug.97, jdblair@uab.edu */
  3601.  
  3602.     if ((p=strchr(username,'%')))
  3603.     {
  3604.       *p = 0;
  3605.       pstrcpy(password,p+1);
  3606.       got_pass = True;
  3607.       memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
  3608.     }
  3609.     strupper(username);
  3610.   }
  3611.  
  3612.  /* modification to support PASSWD environmental var
  3613.   25.Aug.97, jdblair@uab.edu */
  3614.  
  3615.   if (getenv("PASSWD")) {
  3616.     pstrcpy(password,getenv("PASSWD"));
  3617.     got_pass = True;
  3618.   }
  3619.  
  3620.   if (*username == 0 && getenv("LOGNAME"))
  3621.     {
  3622.       pstrcpy(username,getenv("LOGNAME"));
  3623.       strupper(username);
  3624.     }
  3625.  
  3626.   if (argc < 2)
  3627.     {
  3628.       usage(pname);
  3629.       exit(1);
  3630.     }
  3631.   
  3632.   if (*argv[1] != '-')
  3633.     {
  3634.  
  3635.       pstrcpy(service,argv[1]);  
  3636.       /* Convert any '/' characters in the service name to '\' characters */
  3637.       string_replace( service, '/','\\');
  3638.       argc--;
  3639.       argv++;
  3640.  
  3641.       if (count_chars(service,'\\') < 3)
  3642.     {
  3643.       usage(pname);
  3644.       printf("\n%s: Not enough '\\' characters in service\n",service);
  3645.       exit(1);
  3646.     }
  3647.  
  3648. /*
  3649.       if (count_chars(service,'\\') > 3)
  3650.     {
  3651.       usage(pname);
  3652.       printf("\n%s: Too many '\\' characters in service\n",service);
  3653.       exit(1);
  3654.     }
  3655.     */
  3656.  
  3657.       if (argc > 1 && (*argv[1] != '-'))
  3658.     {
  3659.       got_pass = True;
  3660.       pstrcpy(password,argv[1]);  
  3661.       memset(argv[1],'X',strlen(argv[1]));
  3662.       argc--;
  3663.       argv++;
  3664.     }
  3665.     }
  3666.  
  3667.   while ((opt = 
  3668.       getopt(argc, argv,"s:B:O:R:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
  3669.     switch (opt)
  3670.       {
  3671.       case 'm':
  3672.     max_protocol = interpret_protocol(optarg,max_protocol);
  3673.     break;
  3674.       case 'O':
  3675.     pstrcpy(user_socket_options,optarg);
  3676.     break;    
  3677.       case 'R':
  3678.         pstrcpy(new_name_resolve_order, optarg);
  3679.         break;
  3680.       case 'S':
  3681.     pstrcpy(desthost,optarg);
  3682.     strupper(desthost);
  3683.     nt_domain_logon = True;
  3684.     break;
  3685.       case 'M':
  3686.     name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
  3687.     pstrcpy(desthost,optarg);
  3688.     strupper(desthost);
  3689.     message = True;
  3690.     break;
  3691.       case 'B':
  3692.     iface_set_default(NULL,optarg,NULL);
  3693.     break;
  3694.       case 'D':
  3695.     pstrcpy(base_directory,optarg);
  3696.     break;
  3697.       case 'T':
  3698.     if (!tar_parseargs(argc, argv, optarg, optind)) {
  3699.       usage(pname);
  3700.       exit(1);
  3701.     }
  3702.     break;
  3703.       case 'i':
  3704.     pstrcpy(scope,optarg);
  3705.     break;
  3706.       case 'L':
  3707.     got_pass = True;
  3708.     pstrcpy(query_host,optarg);
  3709.     break;
  3710.       case 'U':
  3711.     {
  3712.       char *lp;
  3713.     pstrcpy(username,optarg);
  3714.     if ((lp=strchr(username,'%')))
  3715.       {
  3716.         *lp = 0;
  3717.         pstrcpy(password,lp+1);
  3718.         got_pass = True;
  3719.         memset(strchr(optarg,'%')+1,'X',strlen(password));
  3720.       }
  3721.     }
  3722.         
  3723.     break;
  3724.       case 'W':
  3725.         pstrcpy(tempworkgroup,optarg);
  3726.     break;
  3727.       case 'E':
  3728.     dbf = stderr;
  3729.     break;
  3730.       case 'I':
  3731.     {
  3732.       dest_ip = *interpret_addr2(optarg);
  3733.       if (zero_ip(dest_ip)) exit(1);
  3734.       have_ip = True;
  3735.     }
  3736.     break;
  3737.       case 'n':
  3738.     pstrcpy(myname,optarg);
  3739.     break;
  3740.       case 'N':
  3741.     got_pass = True;
  3742.     no_pass = True;
  3743.     break;
  3744.       case 'P':
  3745.     connect_as_printer = True;
  3746.     break;
  3747.       case 'd':
  3748.     if (*optarg == 'A')
  3749.       save_debuglevel = DEBUGLEVEL = 10000;
  3750.     else
  3751.       save_debuglevel = DEBUGLEVEL = atoi(optarg);
  3752.     break;
  3753.       case 'l':
  3754.     slprintf(debugf,sizeof(debugf)-1, "%s.client",optarg);
  3755.     break;
  3756.       case 'p':
  3757.     port = atoi(optarg);
  3758.     break;
  3759.       case 'c':
  3760.     cmdstr = optarg;
  3761.     got_pass = True;
  3762.     break;
  3763.       case 'h':
  3764.     usage(pname);
  3765.     exit(0);
  3766.     break;
  3767.       case 's':
  3768.     pstrcpy(servicesf, optarg);
  3769.     break;
  3770.       case 't':
  3771.         pstrcpy(term_code, optarg);
  3772.     break;
  3773.       default:
  3774.     usage(pname);
  3775.     exit(1);
  3776.       }
  3777.  
  3778.   if (!tar_type && !*query_host && !*service && !message)
  3779.     {
  3780.       usage(pname);
  3781.       exit(1);
  3782.     }
  3783.  
  3784.  
  3785.   DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
  3786.  
  3787.   if(!get_myname(myhostname,NULL))
  3788.   {
  3789.     DEBUG(0,("Failed to get my hostname.\n"));
  3790.   }
  3791.  
  3792.   if (!lp_load(servicesf,True)) {
  3793.     fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
  3794.   }
  3795.  
  3796.   /*
  3797.    * We need to reset the global debuglevel here, as
  3798.    * lp_load will reset it from smb.conf.
  3799.    */
  3800.  
  3801.   if(save_debuglevel != -1)
  3802.     DEBUGLEVEL = save_debuglevel;
  3803.  
  3804.   codepage_initialise(lp_client_code_page());
  3805.  
  3806.   interpret_coding_system(term_code);
  3807.  
  3808.   if (*tempworkgroup) {
  3809.     pstrcpy(workgroup,tempworkgroup);
  3810.   } else {
  3811.     pstrcpy(workgroup,lp_workgroup());
  3812.   }
  3813.  
  3814.   load_interfaces();
  3815.   get_myname((*myname)?NULL:myname,NULL);  
  3816.   strupper(myname);
  3817.  
  3818.   if(*new_name_resolve_order)
  3819.     lp_set_name_resolve_order(new_name_resolve_order);
  3820.  
  3821.   if (tar_type) {
  3822.     recurse=True;
  3823.  
  3824.     if (cli_open_sockets(port)) {
  3825.         char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3826.     char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3827.     int ret;
  3828.  
  3829.     if ((InBuffer == NULL) || (OutBuffer == NULL)) 
  3830.       return(1);
  3831.  
  3832.     bzero(OutBuffer,smb_size);
  3833.     if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
  3834.       return(False);
  3835.  
  3836.     if (*base_directory) do_cd(base_directory);
  3837.  
  3838.     ret=process_tar(InBuffer, OutBuffer);
  3839.  
  3840.     cli_send_logout(InBuffer, OutBuffer);
  3841.     close_sockets();
  3842.     return(ret);
  3843.     } else
  3844.       return(1);
  3845.   }
  3846.   
  3847.   if (*query_host && !nt_domain_logon)
  3848.     {
  3849.       int ret = 0;
  3850.       slprintf(service,sizeof(service)-1,
  3851.            "\\\\%s\\IPC$",query_host);
  3852.       strupper(service);
  3853.       connect_as_ipc = True;
  3854.       if (cli_open_sockets(port))
  3855.     {
  3856. #if 0
  3857.       *username = 0;
  3858. #endif
  3859.       if (!cli_send_login(NULL,NULL,True,True,NULL))
  3860.         return(1);
  3861.  
  3862.       server_info();
  3863.       if (!browse_host(True)) {
  3864.         sleep(1);
  3865.         browse_host(True);
  3866.       }
  3867.       if (!list_servers(workgroup)) {
  3868.         sleep(1);
  3869.         list_servers(workgroup);
  3870.       }
  3871.  
  3872.       cli_send_logout(NULL,NULL);
  3873.       close_sockets();
  3874.     }
  3875.  
  3876.       return(ret);
  3877.     }
  3878.  
  3879.   if (message)
  3880.     {
  3881.       int ret = 0;
  3882.       if (cli_open_sockets(port))
  3883.     {
  3884.       pstring inbuf,outbuf;
  3885.       bzero(outbuf,smb_size);
  3886.       if (!cli_send_session_request(inbuf,outbuf))
  3887.         return(1);
  3888.  
  3889.       send_message(inbuf,outbuf);
  3890.  
  3891.       close_sockets();
  3892.     }
  3893.  
  3894.       return(ret);
  3895.     }
  3896.  
  3897.   if (cli_open_sockets(port))
  3898.     {
  3899.       if (!process(base_directory))
  3900.     {
  3901.       close_sockets();
  3902.       return(1);
  3903.     }
  3904.       close_sockets();
  3905.     }
  3906.   else
  3907.     return(1);
  3908.  
  3909.   return(0);
  3910. }
  3911.  
  3912.  
  3913.