home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / contrib / samba / samba-1.8 / samba-1 / samba-1.8.05 / client.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  82.6 KB  |  3,547 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.8.
  4.    Copyright (C) Andrew Tridgell 1994
  5.    
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.    
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #include "includes.h"
  22.  
  23. /* default to using LANMAN1 */
  24. #ifndef LANMAN1
  25. #define LANMAN1 1
  26. #endif
  27.  
  28. /* default to using LANMAN2 */
  29. #ifndef LANMAN2
  30. #define LANMAN2 1
  31. #endif
  32.  
  33. #ifndef REGISTER
  34. #define REGISTER 0
  35. #endif
  36.  
  37. pstring cur_dir = "\\";
  38. pstring cd_path = "";
  39. pstring service="";
  40. pstring desthost="";
  41. pstring myname = "";
  42. pstring password = "";
  43. pstring username="";
  44. BOOL got_pass = False;
  45. BOOL connect_as_printer = False;
  46. BOOL connect_as_ipc = False;
  47.  
  48. time_t newer_than = 0;
  49.  
  50. extern struct in_addr myip;
  51.  
  52. extern pstring debugf;
  53. extern int DEBUGLEVEL;
  54.  
  55. BOOL translation = False;
  56.  
  57.  
  58. int cnum = 0;
  59. int pid = 0;
  60. int gid = 0;
  61. int uid = 0;
  62. int mid = 0;
  63. int myumask = 0755;
  64.  
  65. int max_xmit = BUFFER_SIZE;
  66.  
  67. extern BOOL NeedSwap;
  68. extern pstring scope;
  69.  
  70. BOOL prompt = True;
  71.  
  72. int printmode = 1;
  73.  
  74. BOOL recurse = False;
  75. BOOL lowercase = False;
  76.  
  77. BOOL have_ip = False;
  78.  
  79. struct in_addr dest_ip;
  80.  
  81. #define SEPARATORS " \t\n\r"
  82.  
  83. BOOL abort_mget = True;
  84.  
  85. extern int Protocol;
  86.  
  87. BOOL readbraw_supported = False;
  88. BOOL writebraw_supported = False;
  89.  
  90. time_t servertime = 0;
  91.  
  92. pstring fileselection = "";
  93.  
  94. extern file_info def_finfo;
  95.  
  96. /* timing globals */
  97. int get_total_size = 0;
  98. int get_total_time_ms = 0;
  99. int put_total_size = 0;
  100. int put_total_time_ms = 0;
  101.  
  102. #ifdef KANJI
  103. int term_code = SJIS_CODE;
  104. #define CNV_LANG(s) (term_code == EUC_CODE?sj_to_euc(s):s)
  105. #define CNV_INPUT(s) (term_code == EUC_CODE?euc_to_sj(s):s)
  106. #else
  107. #define CNV_LANG(s) s
  108. #define CNV_INPUT(s) s
  109. #endif
  110.  
  111.  
  112. /****************************************************************************
  113. setup basics in a outgoing packet
  114. ****************************************************************************/
  115. void setup_pkt(char *outbuf)
  116. {
  117.   SSVAL(outbuf,smb_pid,pid);
  118.   SSVAL(outbuf,smb_uid,uid);
  119.   SSVAL(outbuf,smb_mid,mid);
  120.   if (Protocol > PROTOCOL_CORE)
  121.     {
  122.       CVAL(outbuf,smb_flg) = 0x8;
  123.       SSVAL(outbuf,smb_flg2,0x3);
  124.     }
  125. }
  126.  
  127. /****************************************************************************
  128. write to a local file with CR/LF->LF translation if appropriate. return the 
  129. number taken from the buffer. This may not equal the number written.
  130. ****************************************************************************/
  131. int writefile(int f, char *b, int n)
  132. {
  133.   int i;
  134.  
  135.   if (!translation)
  136.     return(write(f,b,n));
  137.   
  138.   i = 0;
  139.   while (i < n)
  140.     {
  141.       if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
  142.     {
  143.       b++;i++;
  144.     }
  145.       if (write(f, b, 1) != 1)
  146.     {
  147.       break;
  148.     }
  149.       b++;
  150.       i++;
  151.     }
  152.   
  153.   return(i);
  154. }
  155.  
  156. /****************************************************************************
  157.   read from a file with LF->CR/LF translation if appropriate. return the 
  158.   number read. read approx n bytes.
  159. ****************************************************************************/
  160. int readfile(char *b, int size, int n, FILE *f)
  161. {
  162.   int i;
  163.   char c;
  164.  
  165.   if (!translation || (size != 1))
  166.     return(fread(b,size,n,f));
  167.   
  168.   i = 0;
  169.   while (i < n)
  170.     {
  171.       if ((c = getc(f)) == EOF)
  172.     {
  173.       break;
  174.     }
  175.       
  176.       if (c == '\n') /* change all LFs to CR/LF */
  177.     {
  178.       b[i++] = '\r';
  179.     }
  180.       
  181.       b[i++] = c;
  182.     }
  183.   
  184.   return(i);
  185. }
  186.  
  187.  
  188. /****************************************************************************
  189. read from a file with print translation. return the number read. read approx n
  190. bytes.
  191. ****************************************************************************/
  192. int printread(FILE *f,char *b,int n)
  193. {
  194.   int i;
  195.  
  196.   i = readfile(b,1, n-1,f);
  197.   if (feof(f) && i>0)
  198.     b[i++] = '\014';
  199.  
  200.   return(i);
  201. }
  202.  
  203. /****************************************************************************
  204.   show an finfo struct
  205. ****************************************************************************/
  206. void show_finfo(file_info *finfo)
  207. {
  208.   DEBUG(3,("name=%s\nmode=0x%x\nsize=%d\n",
  209.        CNV_LANG(finfo->name),
  210.        finfo->mode,
  211.        finfo->size));
  212.  
  213.   DEBUG(3,("mtime=%s",asctime(LocalTime(&finfo->mtime,LOCAL_TO_GMT))));
  214.   DEBUG(3,("atime=%s",asctime(LocalTime(&finfo->atime,LOCAL_TO_GMT))));
  215.   DEBUG(3,("ctime=%s",asctime(LocalTime(&finfo->ctime,LOCAL_TO_GMT))));
  216.  
  217.   DEBUG(3,("%x %x %x\n",finfo->mtime,finfo->atime,finfo->ctime));
  218. }
  219.  
  220. /****************************************************************************
  221. check for existance of a dir
  222. ****************************************************************************/
  223. void test_getattr(char *path)
  224. {
  225.   pstring inbuf,outbuf;
  226.   char *p;
  227.  
  228.   memset(outbuf,0,smb_size);
  229.   set_message(outbuf,0,2 + strlen(path),True);
  230.   CVAL(outbuf,smb_com) = SMBgetatr;
  231.   SSVAL(outbuf,smb_tid,cnum);
  232.   setup_pkt(outbuf);
  233.  
  234.   p = smb_buf(outbuf);
  235.   *p++ = 4;
  236.   strcpy(p,path);
  237.  
  238.   send_smb(outbuf);
  239.   receive_smb(inbuf,0);
  240.  
  241.   if (CVAL(inbuf,smb_rcls) != 0)
  242.     DEBUG(2,("getatr: %s\n",smb_errstr(inbuf)));
  243.   else
  244.     {
  245.       DEBUG(0,("attr 0x%X  time %d  size %d\n",
  246.            (int)CVAL(inbuf,smb_vwv0),
  247.            SVAL(inbuf,smb_vwv1),
  248.            SVAL(inbuf,smb_vwv3)));
  249.     }
  250.   
  251. }
  252.  
  253. /****************************************************************************
  254. check for existance of a dir
  255. ****************************************************************************/
  256. BOOL chkpath(char *path,BOOL report)
  257. {
  258.   pstring inbuf,outbuf;
  259.   char *p;
  260.  
  261.   memset(outbuf,0,smb_size);
  262.   set_message(outbuf,0,4 + strlen(path),True);
  263.   CVAL(outbuf,smb_com) = SMBchkpth;
  264.   SSVAL(outbuf,smb_tid,cnum);
  265.   setup_pkt(outbuf);
  266.  
  267.   p = smb_buf(outbuf);
  268.   *p++ = 4;
  269.   strcpy(p,path);
  270.  
  271.   send_smb(outbuf);
  272.   receive_smb(inbuf,0);
  273.  
  274.   if (report && CVAL(inbuf,smb_rcls) != 0)
  275.     DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
  276.  
  277.   return(CVAL(inbuf,smb_rcls) == 0);
  278. }
  279.  
  280.  
  281. /****************************************************************************
  282. check the space on a device
  283. ****************************************************************************/
  284. void do_dskattr(void)
  285. {
  286.   pstring inbuf,outbuf;
  287.  
  288.   memset(outbuf,0,smb_size);
  289.   set_message(outbuf,0,0,True);
  290.   CVAL(outbuf,smb_com) = SMBdskattr;
  291.   SSVAL(outbuf,smb_tid,cnum);
  292.   setup_pkt(outbuf);
  293.  
  294.   send_smb(outbuf);
  295.   receive_smb(inbuf,0);
  296.  
  297.   DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
  298.     SVAL(inbuf,smb_vwv0),
  299.     SVAL(inbuf,smb_vwv2),
  300.     SVAL(inbuf,smb_vwv3)));
  301. }
  302.  
  303.  
  304. /****************************************************************************
  305. change directory
  306. ****************************************************************************/
  307. void cmd_cd(char *inbuf,char *outbuf )
  308. {
  309.   char *p;
  310.   pstring saved_dir;
  311.  
  312.   p = strtok(NULL,SEPARATORS);
  313.   if (p)
  314.     {
  315.       pstring dname;
  316.       
  317.       /* Save the current directory in case the
  318.      new directory is invalid */
  319.       strcpy(saved_dir, cur_dir);
  320.       if (*p == '\\')
  321.     strcpy(cur_dir,p);
  322.       else
  323.     strcat(cur_dir,p);
  324.       dos_clean_name(cur_dir);
  325.       strcpy(dname,cur_dir);
  326.       strcat(cur_dir,"\\");
  327.       dos_clean_name(cur_dir);
  328.  
  329.       if (!strequal(cur_dir,"\\"))
  330.     if (!chkpath(dname,True))
  331.       strcpy(cur_dir,saved_dir);
  332.     }
  333.   else
  334.     DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
  335.   strcpy(cd_path,cur_dir);
  336. }
  337.  
  338.  
  339. /****************************************************************************
  340. display info about a file
  341. ****************************************************************************/
  342. void display_finfo(file_info *finfo)
  343. {
  344.   DEBUG(0,("  %-30s%7.7s%10d  %s",
  345.        CNV_LANG(finfo->name),
  346.        attrib_string(finfo->mode),
  347.        finfo->size,
  348.        asctime(LocalTime(&finfo->mtime,0))));
  349. }
  350.  
  351.  
  352. /****************************************************************************
  353. act on the files in a dir listing
  354. ****************************************************************************/
  355. void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
  356. {
  357.  
  358.   if (!((finfo->mode & aDIR) == 0 && *fileselection && 
  359.     !mask_match(finfo->name,fileselection,False,False,True)) &&
  360.       !(recurse_dir && (strequal(finfo->name,".") || 
  361.             strequal(finfo->name,".."))))
  362.     {
  363.       if (recurse_dir && (finfo->mode & aDIR))
  364.     {
  365.       pstring mask2;
  366.       pstring sav_dir;
  367.       strcpy(sav_dir,cur_dir);
  368.       strcat(cur_dir,finfo->name);
  369.       strcat(cur_dir,"\\");
  370.       strcpy(mask2,cur_dir);
  371.  
  372.       if (!fn)
  373.         DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
  374.  
  375.       if (longdir)
  376.         {
  377.           strcat(mask2,"*");
  378.           do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);      
  379.         }
  380.       else
  381.         {
  382.           strcat(mask2,"*.*");
  383.           do_dir(inbuf,outbuf,mask2,attribute,fn,True);
  384.         }
  385.       strcpy(cur_dir,sav_dir);
  386.     }
  387.       else
  388.     {
  389.       if (fn && (newer_than==0 || 
  390.              finfo->mtime >= newer_than ||
  391.              finfo->mode & aDIR))
  392.         fn(finfo);
  393.     }
  394.     }
  395. }
  396.  
  397. /****************************************************************************
  398. do a directory listing, calling fn on each file found
  399. ****************************************************************************/
  400. void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
  401. {
  402.   if (Protocol >= PROTOCOL_LANMAN2)
  403.     {
  404.       if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
  405.     return;
  406.     }
  407.  
  408.   expand_mask(Mask,False);
  409.   do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
  410.   return;
  411. }
  412.  
  413.  
  414.  
  415. /****************************************************************************
  416. do a directory listing, calling fn on each file found
  417. ****************************************************************************/
  418. int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
  419. {
  420.   char *p;
  421.   int received = 0;
  422.   BOOL first = True;
  423.   char status[21];
  424.   int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
  425.   int num_received = 0;
  426.   int i;
  427.   char *dirlist = NULL;
  428.   pstring mask;
  429.   file_info finfo = def_finfo;
  430.  
  431.   strcpy(mask,Mask);
  432.   
  433.   while (1)
  434.     {
  435.       memset(outbuf,0,smb_size);
  436.       if (first)    
  437.     set_message(outbuf,2,5 + strlen(mask),True);
  438.       else
  439.     set_message(outbuf,2,5 + 21,True);
  440.  
  441. #if FFIRST
  442.       if (Protocol >= PROTOCOL_LANMAN1)
  443.     CVAL(outbuf,smb_com) = SMBffirst;
  444.       else
  445. #endif
  446.     CVAL(outbuf,smb_com) = SMBsearch;
  447.  
  448.       SSVAL(outbuf,smb_tid,cnum);
  449.       setup_pkt(outbuf);
  450.  
  451.       SSVAL(outbuf,smb_vwv0,num_asked);
  452.       SSVAL(outbuf,smb_vwv1,attribute);
  453.   
  454.       p = smb_buf(outbuf);
  455.       *p++ = 4;
  456.       
  457.       if (first)
  458.     strcpy(p,mask);
  459.       else
  460.     strcpy(p,"");
  461.       p += strlen(p) + 1;
  462.       
  463.       *p++ = 5;
  464.       if (first)
  465.     SSVAL(p,0,0);
  466.       else
  467.     {
  468.       SSVAL(p,0,21);
  469.       p += 2;
  470.       memcpy(p,status,21);
  471.     }
  472.  
  473.       send_smb(outbuf);
  474.       receive_smb(inbuf,0);
  475.  
  476.       received = SVAL(inbuf,smb_vwv0);
  477.  
  478.       DEBUG(5,("dir received %d\n",received));
  479.  
  480.       DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
  481.  
  482.       if (received <= 0) break;
  483.  
  484.       first = False;
  485.  
  486.       dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
  487.  
  488.       if (!dirlist) 
  489.     return 0;
  490.  
  491.       p = smb_buf(inbuf) + 3;
  492.  
  493.       memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
  494.          p,received*DIR_STRUCT_SIZE);
  495.  
  496.       memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
  497.  
  498.       num_received += received;
  499.  
  500.       if (CVAL(inbuf,smb_rcls) != 0) break;
  501.     }
  502.  
  503. #if FFIRST
  504.   if (!first && Protocol >= PROTOCOL_LANMAN1)
  505.     {
  506.       memset(outbuf,0,smb_size);
  507.       CVAL(outbuf,smb_com) = SMBfclose;
  508.  
  509.       SSVAL(outbuf,smb_tid,cnum);
  510.       setup_pkt(outbuf);
  511.  
  512.       p = smb_buf(outbuf);
  513.       *p++ = 4;
  514.       
  515.       strcpy(p,"");
  516.       p += strlen(p) + 1;
  517.       
  518.       *p++ = 5;
  519.       SSVAL(p,0,21);
  520.       p += 2;
  521.       memcpy(p,status,21);
  522.  
  523.       send_smb(outbuf);
  524.       receive_smb(inbuf,0);
  525.  
  526.       if (CVAL(inbuf,smb_rcls) != 0) 
  527.     DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));      
  528.     }
  529. #endif
  530.  
  531.   if (!fn)
  532.     for (p=dirlist,i=0;i<num_received;i++)
  533.       {
  534.     p += interpret_short_filename(p,&finfo);
  535.     display_finfo(&finfo);
  536.       }
  537.  
  538.   for (p=dirlist,i=0;i<num_received;i++)
  539.     {
  540.       p += interpret_short_filename(p,&finfo);
  541.       dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
  542.     }
  543.  
  544.   if (dirlist) free(dirlist);
  545.   return(num_received);
  546. }
  547.  
  548. /****************************************************************************
  549. receive a SMB trans2 response allocating the necessary memory
  550. ****************************************************************************/
  551. BOOL receive_trans2_response(char *inbuf,int *data_len,int *param_len,
  552.                  char **data,char **param)
  553. {
  554.   int total_data=0;
  555.   int total_param=0;
  556.  
  557.   *data_len = *param_len = 0;
  558.  
  559.   receive_smb(inbuf,0);
  560.   if (CVAL(inbuf,smb_rcls) != 0)
  561.     return(False);
  562.  
  563.   /* parse out the lengths */
  564.   total_data = SVAL(inbuf,smb_tdrcnt);
  565.   total_param = SVAL(inbuf,smb_tprcnt);
  566.  
  567.   /* allocate it */
  568.   *data = Realloc(*data,total_data);
  569.   *param = Realloc(*param,total_param);
  570.  
  571.   while (1)
  572.     {
  573.       memcpy(*data + *data_len,smb_base(inbuf) + SVAL(inbuf,smb_droff),
  574.          SVAL(inbuf,smb_drcnt));
  575.       memcpy(*param + *param_len,smb_base(inbuf) + SVAL(inbuf,smb_proff),
  576.          SVAL(inbuf,smb_prcnt));
  577.       *data_len += SVAL(inbuf,smb_drcnt);
  578.       *param_len += SVAL(inbuf,smb_prcnt);
  579.  
  580.       /* parse out the total lengths again - they can shrink! */
  581.       total_data = SVAL(inbuf,smb_tdrcnt);
  582.       total_param = SVAL(inbuf,smb_tprcnt);
  583.  
  584.       if (total_data <= *data_len && total_param <= *param_len)
  585.     break;
  586.       receive_smb(inbuf,0);
  587.     }
  588.   
  589.   return(True);
  590. }
  591.  
  592. /****************************************************************************
  593. do a directory listing, calling fn on each file found. Use the TRANSACT2
  594. call for long filenames
  595. ****************************************************************************/
  596. int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
  597. {
  598.   int max_matches = 512;
  599.   int info_level = 1; /* NT uses 260, OS/2 uses 2. Both accept 1. */
  600.   char *p;
  601.   pstring mask;
  602.   file_info finfo;
  603.   int i;
  604.   char *dirlist = NULL;
  605.   int dirlist_len = 0;
  606.   int total_received = 0;
  607.   BOOL First = True;
  608.   char *resp_data=NULL;
  609.   char *resp_param=NULL;
  610.   int resp_data_len = 0;
  611.   int resp_param_len=0;
  612.  
  613.   int ff_resume_key = 0;
  614.   int ff_searchcount=0;
  615.   int ff_eos=0;
  616.   int ff_lastname=0;
  617.   int ff_dir_handle=0;
  618.   int loop_count = 0;
  619.  
  620.   strcpy(mask,Mask);
  621.  
  622.   while (ff_eos == 0)
  623.     {
  624.       loop_count++;
  625.       if (loop_count > 200)
  626.     {
  627.       DEBUG(0,("ERROR: Looping in FIND_NEXT??\n"));
  628.       break;
  629.     }
  630.  
  631.       memset(outbuf,0,smb_setup);
  632.       set_message(outbuf,15,5 + 12 + strlen(mask)+1,True);
  633.       CVAL(outbuf,smb_com) = SMBtrans2;
  634.       SSVAL(outbuf,smb_tid,cnum);
  635.       setup_pkt(outbuf);
  636.   
  637.       SSVAL(outbuf,smb_tpscnt,12 + strlen(mask)+1);
  638.       SSVAL(outbuf,smb_tdscnt,0);
  639.       SSVAL(outbuf,smb_mprcnt,10); 
  640.       SSVAL(outbuf,smb_mdrcnt,0xFFFF);
  641.       SSVAL(outbuf,smb_msrcnt,0);
  642.       SSVAL(outbuf,smb_flags,0); 
  643.       SIVAL(outbuf,smb_timeout,0);
  644.       SSVAL(outbuf,smb_pscnt,SVAL(outbuf,smb_tpscnt));
  645.       SSVAL(outbuf,smb_psoff,((smb_buf(outbuf)+3) - outbuf)-4);
  646.       SSVAL(outbuf,smb_dscnt,0);
  647.       SSVAL(outbuf,smb_dsoff,0);
  648.       SSVAL(outbuf,smb_suwcnt,1);
  649.  
  650.       if (First)
  651.     SSVAL(outbuf,smb_setup0,TRANSACT2_FINDFIRST);
  652.       else
  653.     SSVAL(outbuf,smb_setup0,TRANSACT2_FINDNEXT);
  654.  
  655.       p = smb_buf(outbuf);
  656.       *p++ = 0; /* put in a null smb_name */
  657.       *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */
  658.  
  659.       if (First)
  660.     {
  661.       SSVAL(p,0,attribute); /* attribute */
  662.       SSVAL(p,2,max_matches); /* max count */
  663.       SSVAL(p,4,8+4+2); /* resume required + close on end + continue */
  664.       SSVAL(p,6,info_level); 
  665.       SIVAL(p,8,0);
  666.       p += 12;
  667.       strcpy(p,mask);
  668.       p += strlen(mask);
  669.       *p++ = 0; *p++ = 0;
  670.     }
  671.       else
  672.     {
  673.       DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
  674.         ff_dir_handle,ff_resume_key,ff_lastname,mask));
  675.       SSVAL(p,0,ff_dir_handle);
  676.       SSVAL(p,2,max_matches); /* max count */
  677.       SSVAL(p,4,info_level); 
  678.       SIVAL(p,6,ff_resume_key); /* ff_resume_key */
  679.       SSVAL(p,10,12); /* resume required + close on end + continue */
  680.       p += 12;
  681.       strcpy(p,mask);
  682.       *p++ = 0; *p++ = 0;
  683.     }
  684.  
  685.       send_smb(outbuf);
  686.  
  687.       receive_trans2_response(inbuf,
  688.                   &resp_data_len,&resp_param_len,
  689.                   &resp_data,&resp_param);
  690.  
  691.       if (CVAL(inbuf,smb_rcls) != 0)
  692.     {
  693.       DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
  694.       break;
  695.     }
  696.  
  697.       /* parse out some important return info */
  698.       p = resp_param;
  699.       if (First)
  700.     {
  701.       ff_dir_handle = SVAL(p,0);
  702.       ff_searchcount = SVAL(p,2);
  703.       ff_eos = SVAL(p,4);
  704.       ff_lastname = SVAL(p,8);
  705.     }
  706.       else
  707.     {
  708.       ff_searchcount = SVAL(p,0);
  709.       ff_eos = SVAL(p,2);
  710.       ff_lastname = SVAL(p,6);
  711.     }
  712.  
  713.       if (ff_searchcount == 0) 
  714.     break;
  715.  
  716.       /* point to the data bytes */
  717.       p = resp_data;
  718.  
  719.       /* we might need the lastname for continuations */
  720.       if (ff_lastname > 0)
  721.     {
  722.       switch(info_level)
  723.         {
  724.         case 260:
  725.           ff_resume_key =0;
  726.           strcpy(mask,p+ff_lastname+94);
  727.           break;
  728.         case 1:
  729.           strcpy(mask,p + ff_lastname + 1);
  730.           ff_resume_key = 0;
  731.           break;
  732.         }
  733.     }
  734.       else
  735.     strcpy(mask,"");
  736.   
  737.       /* and add them to the dirlist pool */
  738.       dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
  739.  
  740.       if (!dirlist)
  741.     {
  742.       DEBUG(0,("Failed to expand dirlist\n"));
  743.       break;
  744.     }
  745.  
  746.       /* put in a length for the last entry, to ensure we can chain entries 
  747.        into the next packet */
  748.       {
  749.     char *p2;
  750.     for (p2=p,i=0;i<(ff_searchcount-1);i++)
  751.       p2 += interpret_long_filename(info_level,p2,NULL);
  752.     SSVAL(p2,0,resp_data_len - (int)(p2 - p));
  753.       }
  754.  
  755.       /* grab the data for later use */
  756.       memcpy(dirlist+dirlist_len,p,resp_data_len);
  757.       dirlist_len += resp_data_len;
  758.  
  759.       total_received += ff_searchcount;
  760.  
  761.       if (resp_data) free(resp_data); resp_data = NULL;
  762.       if (resp_param) free(resp_param); resp_param = NULL;
  763.  
  764.       DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
  765.         ff_searchcount,ff_eos,ff_resume_key));
  766.  
  767.       First = False;
  768.     }
  769.  
  770.   if (!fn)
  771.     for (p=dirlist,i=0;i<total_received;i++)
  772.       {
  773.     p += interpret_long_filename(info_level,p,&finfo);
  774.     display_finfo(&finfo);
  775.       }
  776.  
  777.   for (p=dirlist,i=0;i<total_received;i++)
  778.     {
  779.       p += interpret_long_filename(info_level,p,&finfo);
  780.       dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
  781.     }
  782.  
  783.   /* free up the dirlist buffer */
  784.   if (dirlist) free(dirlist);
  785.   return(total_received);
  786. }
  787.  
  788.  
  789. /****************************************************************************
  790. get a directory listing
  791. ****************************************************************************/
  792. void cmd_dir(char *inbuf,char *outbuf)
  793. {
  794.   int attribute = aDIR | aSYSTEM | aHIDDEN;
  795.   pstring mask;
  796.   char *p;
  797.  
  798.   strcpy(mask,cur_dir);
  799.   if(mask[strlen(mask)-1]!='\\')
  800.     strcat(mask,"\\");
  801.  
  802.   p = strtok(NULL,SEPARATORS);
  803.   if (p)
  804.     {
  805.       if (*p == '\\')
  806.     strcpy(mask,p);
  807.       else
  808.     strcat(mask,p);
  809.     }
  810.   else
  811.     strcat(mask,"*.*");
  812.  
  813.   if (Protocol < PROTOCOL_LANMAN2)
  814.     expand_mask(mask,True);
  815.  
  816.   do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
  817.  
  818.   do_dskattr();
  819. }
  820.  
  821.  
  822. /****************************************************************************
  823. list lots of info about a file
  824. ****************************************************************************/
  825. void do_ldir(file_info *finfo)
  826. {
  827.   char *inbuf,*outbuf;
  828.   char *p;
  829.   pstring rname;
  830.   pstring SMB_NAME="";
  831.  
  832.   if (Protocol < PROTOCOL_LANMAN2)
  833.     {
  834.       DEBUG(0,("%20.20s mode=0x%x uid=%d gid=%d size=%10d  %s %s %s",
  835.            CNV_LANG(finfo->name),
  836.            finfo->mode,
  837.            finfo->uid,
  838.            finfo->gid,
  839.            finfo->size,
  840.            asctime(LocalTime(&finfo->ctime,LOCAL_TO_GMT)),
  841.            asctime(LocalTime(&finfo->atime,LOCAL_TO_GMT)),
  842.            asctime(LocalTime(&finfo->mtime,LOCAL_TO_GMT))));
  843.       return;
  844.     }
  845.  
  846.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  847.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  848.  
  849.   if (!inbuf || !outbuf)
  850.     {
  851.       DEBUG(0,("out of memory\n"));
  852.       return;
  853.     }
  854.  
  855.   strcpy(rname,cur_dir);
  856.   strcat(rname,finfo->name);
  857.  
  858.   memset(outbuf,0,smb_setup);
  859.   set_message(outbuf,15,6 + strlen(rname)+1+strlen(SMB_NAME)+1,True);
  860.   CVAL(outbuf,smb_com) = SMBtrans2;
  861.   SSVAL(outbuf,smb_tid,cnum);
  862.   setup_pkt(outbuf);
  863.  
  864.   SSVAL(outbuf,smb_tpscnt,6+strlen(rname)+1);
  865.   SSVAL(outbuf,smb_tdscnt,0);
  866.   SSVAL(outbuf,smb_mprcnt,1024); /* XXXXX need to get this right */
  867.   SSVAL(outbuf,smb_mdrcnt,1024); /* XXXXX need to get this right */
  868.   SSVAL(outbuf,smb_msrcnt,0);
  869.   SSVAL(outbuf,smb_flags,0);
  870.   SIVAL(outbuf,smb_timeout,0);
  871.   SSVAL(outbuf,smb_pscnt,SVAL(outbuf,smb_tpscnt));
  872.   SSVAL(outbuf,smb_psoff,((smb_buf(outbuf)+strlen(SMB_NAME)+1) - outbuf)-4);
  873.   SSVAL(outbuf,smb_dscnt,0);
  874.   SSVAL(outbuf,smb_dsoff,SVAL(outbuf,smb_psoff) + SVAL(outbuf,smb_pscnt));
  875.   SSVAL(outbuf,smb_suwcnt,1);
  876.   SSVAL(outbuf,smb_setup0,TRANSACT2_QPATHINFO);
  877.  
  878.   /* what the hell is smb_name ?? */
  879.   strcpy(smb_buf(outbuf),SMB_NAME);
  880.  
  881.   p = smb_buf(outbuf)+strlen(SMB_NAME)+1;
  882.  
  883.   {
  884.     int i;
  885.     for (i=2;i<3;i++)
  886.       {
  887.     SSVAL(p,0,i); /* is 3 the right level?? */
  888.     strcpy(p+6,rname);
  889.     send_smb(outbuf);
  890.     receive_smb(inbuf,0);
  891.  
  892.     DEBUG(3,("qpath: prcnt=%d drcnt=%d\n",
  893.           SVAL(inbuf,smb_prcnt),SVAL(inbuf,smb_drcnt)));
  894.       }
  895.   }
  896.  
  897.   if (CVAL(inbuf,smb_rcls) != 0) 
  898.     DEBUG(0,("Qpathinfo failed %s\n",
  899.       smb_errstr(inbuf)));
  900.   else
  901.     DEBUG(3,("Qpathinfo succeeded\n"));
  902.  
  903.   free(inbuf);free(outbuf);
  904. }
  905.  
  906.  
  907. /****************************************************************************
  908. get a file from rname to lname
  909. ****************************************************************************/
  910. void do_get(char *rname,char *lname,file_info *finfo1)
  911. {
  912.   int handle=0,fnum;
  913.   uint32 nread=0;
  914.   char *p;
  915.   BOOL newhandle = False;
  916.   char *inbuf,*outbuf;
  917.   file_info finfo;
  918.   BOOL close_done = False;
  919.  
  920.   struct timeval tp_start;
  921.   gettimeofday(&tp_start,NULL);
  922.  
  923.   if (finfo1) 
  924.     finfo = *finfo1;
  925.   else
  926.     finfo = def_finfo;
  927.  
  928.   if (lowercase)
  929.     strlower(lname);
  930.  
  931.  
  932.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  933.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  934.  
  935.   if (!inbuf || !outbuf)
  936.     {
  937.       DEBUG(0,("out of memory\n"));
  938.       return;
  939.     }
  940.  
  941.   memset(outbuf,0,smb_size);
  942.   set_message(outbuf,2,2 + strlen(rname),True);
  943.  
  944.   CVAL(outbuf,smb_com) = SMBopen;
  945.   SSVAL(outbuf,smb_tid,cnum);
  946.   setup_pkt(outbuf);
  947.  
  948.   SSVAL(outbuf,smb_vwv0,0);
  949.   SSVAL(outbuf,smb_vwv1,aSYSTEM | aHIDDEN);
  950.   
  951.   p = smb_buf(outbuf);
  952.   *p++ = 4;      
  953.   strcpy(p,rname);
  954.   dos_clean_name(rname);
  955.  
  956.       if(!strcmp(lname,"-"))
  957.     handle = fileno(stdout);
  958.       else 
  959.     {
  960.       handle = creat(lname,0644);
  961.       newhandle = True;
  962.     }
  963.       if (handle < 0)
  964.     {
  965.       DEBUG(0,("Error opening local file %s\n",lname));
  966.       free(inbuf);free(outbuf);
  967.       return;
  968.     }
  969.  
  970.   send_smb(outbuf);
  971.   receive_smb(inbuf,0);
  972.  
  973.   if (CVAL(inbuf,smb_rcls) != 0)
  974.     {
  975.       DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  976.       if(newhandle)
  977.     close(handle);
  978.       free(inbuf);free(outbuf);
  979.       return;
  980.     }
  981.  
  982.   strcpy(finfo.name,rname);
  983.   if (!finfo1)
  984.     {
  985.       finfo.mode = SVAL(inbuf,smb_vwv1);
  986.       finfo.size = IVAL(inbuf,smb_vwv4);
  987.       finfo.mtime = IVAL(inbuf,smb_vwv2);
  988.       finfo.atime = finfo.ctime = finfo.mtime;
  989.     }
  990.  
  991.   DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
  992.  
  993.   fnum = SVAL(inbuf,smb_vwv0);
  994.  
  995.     DEBUG(2,("getting file %s of size %d bytes as %s ",
  996.          CNV_LANG(finfo.name),
  997.          finfo.size,
  998.          lname));
  999.  
  1000.  
  1001.   while (nread < finfo.size && !close_done)
  1002.     {
  1003.       char *dataptr;
  1004.       int datalen;
  1005.       
  1006.       DEBUG(3,("nread=%d\n",nread));
  1007.  
  1008.       /* 3 possible read types. readbraw if a large block is required.
  1009.      readX + close if not much left and read if neither is supported */
  1010.  
  1011.       if (Protocol >= PROTOCOL_LANMAN1)
  1012.     {
  1013.       char *p=NULL;
  1014.  
  1015.       if ((finfo.size - nread) < 
  1016.           (max_xmit - (2*smb_size + 13*sizeof(WORD) + 300)))
  1017.         close_done = True;
  1018.  
  1019.       DEBUG(4,("Using readX+close\n"));
  1020.  
  1021.       /* use readX + close */
  1022.       memset(outbuf,0,smb_size);
  1023.       set_message(outbuf,10,0,True);
  1024.       CVAL(outbuf,smb_com) = SMBreadX;
  1025.       SSVAL(outbuf,smb_tid,cnum);
  1026.       setup_pkt(outbuf);
  1027.  
  1028.       if (close_done)
  1029.         {
  1030.           CVAL(outbuf,smb_vwv0) = SMBclose;
  1031.           SSVAL(outbuf,smb_vwv1,PTR_DIFF(smb_buf(outbuf),outbuf) - 4);
  1032.         }
  1033.       else
  1034.         CVAL(outbuf,smb_vwv0) = 0xFF;          
  1035.  
  1036.       SSVAL(outbuf,smb_vwv2,fnum);
  1037.       SIVAL(outbuf,smb_vwv3,nread);
  1038.       SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
  1039.       SSVAL(outbuf,smb_vwv6,0);
  1040.       SIVAL(outbuf,smb_vwv7,0);
  1041.       SSVAL(outbuf,smb_vwv9,MIN(0xFFFF,finfo.size-nread));
  1042.  
  1043.       if (close_done)
  1044.         {
  1045.           p = smb_buf(outbuf);
  1046.           memset(p,0,9);
  1047.  
  1048.           CVAL(p,0) = 3;
  1049.           SSVAL(p,1,fnum);
  1050.           SIVAL(p,3,finfo.mtime);
  1051.  
  1052.           /* now set the total packet length */
  1053.           smb_setlen(outbuf,smb_len(outbuf)+9);
  1054.         }
  1055.       
  1056.       send_smb(outbuf);
  1057.       receive_smb(inbuf,0);
  1058.  
  1059.       if (CVAL(inbuf,smb_rcls) != 0)
  1060.         {
  1061.           DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
  1062.           break;
  1063.         }
  1064.  
  1065.       if (Protocol < PROTOCOL_LANMAN2 &&
  1066.           SVAL(inbuf,smb_vwv0) != SMBclose)
  1067.         {
  1068.           /* NOTE: WfWg sometimes just ignores the chained
  1069.          command! This seems to break the spec? */
  1070.           DEBUG(3,("Rejected chained close?\n"));
  1071.           close_done = False;
  1072.         }
  1073.  
  1074.       datalen = SVAL(inbuf,smb_vwv5);
  1075.       dataptr = inbuf + 4 + SVAL(inbuf,smb_vwv6);
  1076.     }
  1077.       else if (readbraw_supported)
  1078.     {
  1079.       static int readbraw_size = 0xFFFF;
  1080.       
  1081.       extern int Client;
  1082.       memset(outbuf,0,smb_size);
  1083.       set_message(outbuf,8,0,True);
  1084.       CVAL(outbuf,smb_com) = SMBreadbraw;
  1085.       SSVAL(outbuf,smb_tid,cnum);
  1086.       setup_pkt(outbuf);
  1087.         
  1088.       SSVAL(outbuf,smb_vwv0,fnum);
  1089.       SIVAL(outbuf,smb_vwv1,nread);
  1090.       SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
  1091.       SSVAL(outbuf,smb_vwv4,0);
  1092.       SIVALS(outbuf,smb_vwv5,-1);
  1093.       send_smb(outbuf);
  1094.  
  1095.       /* Now read the raw data into the buffer and write it */      
  1096.       if(read_smb_length(Client,inbuf,0) == -1) {
  1097.         DEBUG(0,("Failed to read length in readbraw\n"));        
  1098.         exit(1);
  1099.       }
  1100.  
  1101.       log_in(inbuf,4);
  1102.  
  1103.       /* Even though this is not an smb message, smb_len
  1104.          returns the generic length of an smb message */
  1105.       datalen = smb_len(inbuf);
  1106.  
  1107.       if (datalen == 0)
  1108.         {
  1109.           /* we got a readbraw error */
  1110.           DEBUG(4,("readbraw error - reducing size\n"));
  1111.           readbraw_size = (readbraw_size * 9) / 10;
  1112.  
  1113.           if (readbraw_size < max_xmit)
  1114.         {
  1115.           DEBUG(0,("disabling readbraw\n"));
  1116.           readbraw_supported = False;
  1117.         }
  1118.  
  1119.           continue;
  1120.         }
  1121.  
  1122.       if(!read_data(Client,inbuf,datalen)) {
  1123.         DEBUG(0,("Failed to read data in readbraw\n"));
  1124.         exit(1);
  1125.       }
  1126.       log_in(inbuf,datalen);
  1127.  
  1128.       dataptr = inbuf;
  1129.       
  1130.     }
  1131.       else
  1132.     {
  1133.       /* use plain read */
  1134.       memset(outbuf,0,smb_size);
  1135.       set_message(outbuf,5,0,True);
  1136.       CVAL(outbuf,smb_com) = SMBread;
  1137.       SSVAL(outbuf,smb_tid,cnum);
  1138.       setup_pkt(outbuf);
  1139.  
  1140.       SSVAL(outbuf,smb_vwv0,fnum);
  1141.       SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
  1142.       SIVAL(outbuf,smb_vwv2,nread);
  1143.       SSVAL(outbuf,smb_vwv4,finfo.size - nread);
  1144.  
  1145.       send_smb(outbuf);
  1146.       receive_smb(inbuf,0);
  1147.  
  1148.       if (CVAL(inbuf,smb_rcls) != 0)
  1149.         {
  1150.           DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
  1151.           break;
  1152.         }
  1153.  
  1154.       datalen = SVAL(inbuf,smb_vwv0);
  1155.       dataptr = smb_buf(inbuf) + 3;
  1156.     }
  1157.  
  1158.     if (writefile(handle,dataptr,datalen) != datalen)
  1159.       {
  1160.         DEBUG(0,("Error writing local file\n"));
  1161.         break;
  1162.       }
  1163.       
  1164.       nread += datalen;
  1165.       if (nread == 0) 
  1166.     {
  1167.       DEBUG(0,("Error reading file %s. Got 0 bytes\n",CNV_LANG(rname)));
  1168.       break;
  1169.     }
  1170.     }
  1171.  
  1172.  
  1173.  
  1174.   if (!close_done)
  1175.     {
  1176.       memset(outbuf,0,smb_size);
  1177.       set_message(outbuf,3,0,True);
  1178.       CVAL(outbuf,smb_com) = SMBclose;
  1179.       SSVAL(outbuf,smb_tid,cnum);
  1180.       setup_pkt(outbuf);
  1181.       
  1182.       SSVAL(outbuf,smb_vwv0,fnum);
  1183.       SIVAL(outbuf,smb_vwv1,finfo.mtime);
  1184.       
  1185.       send_smb(outbuf);
  1186.       receive_smb(inbuf,0);
  1187.       
  1188.       if (CVAL(inbuf,smb_rcls) != 0)
  1189.     {
  1190.       DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
  1191.       if(newhandle)
  1192.         close(handle);
  1193.       free(inbuf);free(outbuf);
  1194.       return;
  1195.     }
  1196.     }
  1197.  
  1198.   if(newhandle)
  1199.     close(handle);
  1200.  
  1201.   {
  1202.     struct timeval tp_end;
  1203.     int this_time;
  1204.  
  1205.     gettimeofday(&tp_end,NULL);
  1206.     this_time = 
  1207.       (tp_end.tv_sec - tp_start.tv_sec)*1000 +
  1208.     (tp_end.tv_usec - tp_start.tv_usec)/1000;
  1209.     get_total_time_ms += this_time;
  1210.     get_total_size += finfo.size;
  1211.  
  1212.     DEBUG(2,("(%g kb/s) (average %g kb/s)\n",
  1213.          finfo.size / (1.024*this_time),
  1214.          get_total_size / (1.024*get_total_time_ms)));
  1215.   }
  1216.  
  1217.   free(inbuf);free(outbuf);
  1218. }
  1219.  
  1220.  
  1221. /****************************************************************************
  1222. get a file
  1223. ****************************************************************************/
  1224. void cmd_get(void)
  1225. {
  1226.   pstring lname;
  1227.   pstring rname;
  1228.   char *p;
  1229.  
  1230.   strcpy(rname,cur_dir);
  1231.   strcat(rname,"\\");
  1232.  
  1233.   p = strtok(NULL,SEPARATORS);
  1234.   if (!p)
  1235.     {
  1236.       DEBUG(0,("get <filename>\n"));
  1237.       return;
  1238.     }
  1239.   strcat(rname,p); 
  1240.   dos_clean_name(rname);
  1241.   strcpy(lname,p);
  1242.  
  1243.   p = strtok(NULL,SEPARATORS);
  1244.   if (p)
  1245.     strcpy(lname,p);      
  1246.  
  1247.   do_get(rname,lname,NULL);
  1248. }
  1249.  
  1250.  
  1251. /****************************************************************************
  1252. do a mget operation on one file
  1253. ****************************************************************************/
  1254. void do_mget(file_info *finfo)
  1255. {
  1256.   pstring rname;
  1257.   pstring quest;
  1258.  
  1259.   if (strequal(finfo->name,".") || strequal(finfo->name,".."))
  1260.     return;
  1261.  
  1262.   if (abort_mget)
  1263.     {
  1264.       DEBUG(0,("mget aborted\n"));
  1265.       return;
  1266.     }
  1267.  
  1268.   if (finfo->mode & aDIR)
  1269.     sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
  1270.   else
  1271.     sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
  1272.  
  1273.   if (prompt && !yesno(quest)) return;
  1274.  
  1275.   if (finfo->mode & aDIR)
  1276.     {
  1277.       pstring saved_curdir;
  1278.       pstring mget_mask;
  1279.       char *inbuf,*outbuf;
  1280.  
  1281.       inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1282.       outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1283.  
  1284.       if (!inbuf || !outbuf)
  1285.     {
  1286.       DEBUG(0,("out of memory\n"));
  1287.       return;
  1288.     }
  1289.  
  1290.       strcpy(saved_curdir,cur_dir);
  1291.  
  1292.       strcat(cur_dir,finfo->name);
  1293.       strcat(cur_dir,"\\");
  1294.  
  1295.       unix_format(finfo->name);
  1296.     {
  1297.       if (lowercase)
  1298.         strlower(finfo->name);
  1299.  
  1300.       if (!directory_exist(finfo->name) && mkdir(finfo->name,0777) != 0) 
  1301.         {
  1302.           DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
  1303.           strcpy(cur_dir,saved_curdir);
  1304.           free(inbuf);free(outbuf);
  1305.           return;
  1306.         }
  1307.  
  1308.       if (chdir(finfo->name) != 0)
  1309.         {
  1310.           DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
  1311.           strcpy(cur_dir,saved_curdir);
  1312.           free(inbuf);free(outbuf);
  1313.           return;
  1314.         }
  1315.     }       
  1316.  
  1317.       strcpy(mget_mask,cur_dir);
  1318.       strcat(mget_mask,"*.*");
  1319.       
  1320.       do_dir((char *)inbuf,(char *)outbuf,
  1321.          mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
  1322.     chdir("..");
  1323.       strcpy(cur_dir,saved_curdir);
  1324.       free(inbuf);free(outbuf);
  1325.     }
  1326.   else
  1327.     {
  1328.       strcpy(rname,cur_dir);
  1329.       strcat(rname,finfo->name);
  1330.       do_get(rname,finfo->name,finfo);
  1331.     }
  1332. }
  1333.  
  1334.  
  1335. /****************************************************************************
  1336. do a mget command
  1337. ****************************************************************************/
  1338. void cmd_mget(char *inbuf,char *outbuf)
  1339. {
  1340.   int attribute = aSYSTEM | aHIDDEN;
  1341.   pstring mget_mask="";
  1342.   char *p;
  1343.  
  1344.   if (recurse)
  1345.     attribute |= aDIR;
  1346.  
  1347.   abort_mget = False;
  1348.  
  1349.   while ((p = strtok(NULL,SEPARATORS)))
  1350.     {
  1351.       strcpy(mget_mask,cur_dir);
  1352.       if(mget_mask[strlen(mget_mask)-1]!='\\')
  1353.     strcat(mget_mask,"\\");
  1354.  
  1355.       if (*p == '\\')
  1356.     strcpy(mget_mask,p);
  1357.       else
  1358.     strcat(mget_mask,p);
  1359.     }
  1360.  
  1361.   do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
  1362. }
  1363.  
  1364. /****************************************************************************
  1365. make a directory of name "name"
  1366. ****************************************************************************/
  1367. BOOL do_mkdir(char *name)
  1368. {
  1369.   char *p;
  1370.   char *inbuf,*outbuf;
  1371.  
  1372.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1373.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1374.  
  1375.   if (!inbuf || !outbuf)
  1376.     {
  1377.       DEBUG(0,("out of memory\n"));
  1378.       return False;
  1379.     }
  1380.  
  1381.   memset(outbuf,0,smb_size);
  1382.   set_message(outbuf,0,2 + strlen(name),True);
  1383.   
  1384.   CVAL(outbuf,smb_com) = SMBmkdir;
  1385.   SSVAL(outbuf,smb_tid,cnum);
  1386.   setup_pkt(outbuf);
  1387.  
  1388.   
  1389.   p = smb_buf(outbuf);
  1390.   *p++ = 4;      
  1391.   strcpy(p,name);
  1392.   
  1393.   send_smb(outbuf);
  1394.   receive_smb(inbuf,0);
  1395.   
  1396.   if (CVAL(inbuf,smb_rcls) != 0)
  1397.     {
  1398.       DEBUG(0,("%s making remote directory %s\n",
  1399.            smb_errstr(inbuf),CNV_LANG(name)));
  1400.  
  1401.       free(inbuf);free(outbuf);
  1402.       return(False);
  1403.     }
  1404.  
  1405.   free(inbuf);free(outbuf);
  1406.   return(True);
  1407. }
  1408.  
  1409.  
  1410. /****************************************************************************
  1411. set the attributes and date of a file
  1412. ****************************************************************************/
  1413. BOOL do_setattr(file_info *finfo)
  1414. {
  1415.   char *p;
  1416.   char *inbuf,*outbuf;
  1417.   pstring name;
  1418.  
  1419.   strcpy(name,finfo->name);
  1420.   strcpy(finfo->name,"\\");
  1421.   strcat(finfo->name,name);
  1422.  
  1423.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1424.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1425.  
  1426.   if (!inbuf || !outbuf)
  1427.     {
  1428.       DEBUG(0,("out of memory\n"));
  1429.       return False;
  1430.     }
  1431.  
  1432.   memset(outbuf,0,smb_size);
  1433.   set_message(outbuf,8,4 + strlen(finfo->name),True);
  1434.   CVAL(outbuf,smb_com) = SMBsetatr;
  1435.   SSVAL(outbuf,smb_tid,cnum);
  1436.   setup_pkt(outbuf);
  1437.  
  1438.   SSVAL(outbuf,smb_vwv0,finfo->mode);
  1439.   SIVAL(outbuf,smb_vwv1,finfo->mtime); 
  1440.   
  1441.   p = smb_buf(outbuf);
  1442.   *p++ = 4;      
  1443.   strcpy(p,finfo->name);
  1444.   p += (strlen(finfo->name)+1);
  1445.   
  1446.   *p++ = 4;
  1447.   *p++ = 0;
  1448.  
  1449.   send_smb(outbuf);
  1450.   receive_smb(inbuf,0);
  1451.   
  1452.   if (CVAL(inbuf,smb_rcls) != 0)
  1453.     {
  1454.       DEBUG(0,("%s setting attributes on file %s\n",
  1455.         smb_errstr(inbuf),CNV_LANG(finfo->name)));
  1456.       free(inbuf);free(outbuf);
  1457.       return(False);
  1458.     }
  1459.  
  1460.   free(inbuf);free(outbuf);
  1461.   return(True);
  1462. }
  1463.  
  1464.  
  1465. /****************************************************************************
  1466. make a directory
  1467. ****************************************************************************/
  1468. void cmd_mkdir(char *inbuf,char *outbuf)
  1469. {
  1470.   pstring mask;
  1471.   char *p;
  1472.   
  1473.   strcpy(mask,cur_dir);
  1474.  
  1475.   p = strtok(NULL,SEPARATORS);
  1476.   if (!p)
  1477.     {
  1478.       if (!recurse)
  1479.     DEBUG(0,("mkdir <dirname>\n"));
  1480.       return;
  1481.     }
  1482.   strcat(mask,p);
  1483.  
  1484.   if (recurse)
  1485.     {
  1486.       pstring ddir;
  1487.       pstring ddir2 = "";
  1488.       strcpy(ddir,mask);
  1489.       trim_string(ddir,".",NULL);
  1490.       p = strtok(ddir,"/\\");
  1491.       while (p)
  1492.     {
  1493.       strcat(ddir2,p);
  1494.       if (!chkpath(ddir2,False))
  1495.         {          
  1496.           do_mkdir(ddir2);
  1497.         }
  1498.       strcat(ddir2,"\\");
  1499.       p = strtok(NULL,"/\\");
  1500.     }     
  1501.     }
  1502.   else
  1503.     do_mkdir(mask);
  1504. }
  1505.  
  1506. /****************************************************************************
  1507. put a single file
  1508. ****************************************************************************/
  1509. void do_put(char *rname,char *lname,file_info *finfo)
  1510. {
  1511.   int fnum;
  1512.   FILE *f;
  1513.   int nread=0;
  1514.   char *p;
  1515.   char *inbuf,*outbuf; 
  1516.   time_t close_time = finfo->mtime - TimeDiff();
  1517.  
  1518.   struct timeval tp_start;
  1519.   gettimeofday(&tp_start,NULL);
  1520.  
  1521.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1522.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1523.  
  1524.   if (!inbuf || !outbuf)
  1525.     {
  1526.       DEBUG(0,("out of memory\n"));
  1527.       return;
  1528.     }
  1529.  
  1530.   
  1531.   memset(outbuf,0,smb_size);
  1532.   set_message(outbuf,3,2 + strlen(rname),True);
  1533.  
  1534.   if (finfo->mtime == 0 || finfo->mtime == -1)
  1535.     {
  1536.       finfo->mtime = finfo->atime = finfo->ctime = 
  1537.     time(NULL) + GMT_TO_LOCAL*TimeDiff();
  1538.     }
  1539.   
  1540.   CVAL(outbuf,smb_com) = SMBcreate;
  1541.   SSVAL(outbuf,smb_tid,cnum);
  1542.   setup_pkt(outbuf);
  1543.  
  1544.   SSVAL(outbuf,smb_vwv0,finfo->mode);
  1545.   SIVAL(outbuf,smb_vwv1,finfo->mtime);
  1546.   
  1547.   p = smb_buf(outbuf);
  1548.   *p++ = 4;      
  1549.   strcpy(p,rname);
  1550.   
  1551.   send_smb(outbuf);
  1552.   receive_smb(inbuf,0);
  1553.   
  1554.   if (CVAL(inbuf,smb_rcls) != 0)
  1555.     {
  1556.       DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  1557.  
  1558.       free(inbuf);free(outbuf);
  1559.       return;
  1560.     }
  1561.  
  1562.     f = fopen(lname,"r");
  1563.  
  1564.   if (!f)
  1565.     {
  1566.       DEBUG(0,("Error opening local file %s\n",lname));
  1567.       free(inbuf);free(outbuf);
  1568.       return;
  1569.     }
  1570.  
  1571.   
  1572.   fnum = SVAL(inbuf,smb_vwv0);
  1573.   if (finfo->size < 0)
  1574.     finfo->size = file_size(lname);
  1575.   
  1576.   DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
  1577.   
  1578.   while (nread < finfo->size)
  1579.     {
  1580.       int n = (max_xmit-200);
  1581.  
  1582.       n = MIN(n,finfo->size - nread);
  1583.  
  1584.       memset(outbuf,0,smb_size);
  1585.       set_message(outbuf,5,n + 3,True);
  1586.   
  1587.       if ((n = readfile(smb_buf(outbuf)+3,1,n,f)) < 1)
  1588.     {
  1589.       DEBUG(0,("Error reading local file\n"));
  1590.       break;
  1591.     }      
  1592.  
  1593.       set_message(outbuf,5,n + 3,False);
  1594.       CVAL(outbuf,smb_com) = SMBwrite;
  1595.       SSVAL(outbuf,smb_tid,cnum);
  1596.       setup_pkt(outbuf);
  1597.  
  1598.       SSVAL(outbuf,smb_vwv0,fnum);
  1599.       SSVAL(outbuf,smb_vwv1,n);
  1600.       SIVAL(outbuf,smb_vwv2,nread);
  1601.       SSVAL(outbuf,smb_vwv4,finfo->size - nread);
  1602.       CVAL(smb_buf(outbuf),0) = 1;
  1603.       SSVAL(smb_buf(outbuf),1,n);
  1604.  
  1605.       send_smb(outbuf);
  1606.       receive_smb(inbuf,0);
  1607.  
  1608.       if (CVAL(inbuf,smb_rcls) != 0)
  1609.     {
  1610.       DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
  1611.       break;
  1612.     }
  1613.  
  1614.       
  1615.       if (n != SVAL(inbuf,smb_vwv0))
  1616.     {
  1617.       DEBUG(0,("Error: only wrote %d bytes\n",nread + SVAL(inbuf,smb_vwv0)));
  1618.       break;
  1619.     }
  1620.  
  1621.       nread += n;
  1622.     }
  1623.  
  1624.  
  1625.  
  1626.   memset(outbuf,0,smb_size);
  1627.   set_message(outbuf,3,0,True);
  1628.   CVAL(outbuf,smb_com) = SMBclose;
  1629.   SSVAL(outbuf,smb_tid,cnum);
  1630.   setup_pkt(outbuf);
  1631.  
  1632.   SSVAL(outbuf,smb_vwv0,fnum);
  1633.   SIVAL(outbuf,smb_vwv1,close_time);
  1634.  
  1635.   DEBUG(3,("Setting date to %s (0x%X)",
  1636.     asctime(LocalTime(&finfo->mtime,LOCAL_TO_GMT)),
  1637.     finfo->mtime));
  1638.  
  1639.   send_smb(outbuf);
  1640.   receive_smb(inbuf,0);
  1641.   
  1642.   if (CVAL(inbuf,smb_rcls) != 0)
  1643.     {
  1644.       DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  1645.     fclose(f);
  1646.       free(inbuf);free(outbuf);
  1647.       return;
  1648.     }
  1649.  
  1650.   
  1651.     fclose(f);
  1652.   free(inbuf);free(outbuf);
  1653.  
  1654.   {
  1655.     struct timeval tp_end;
  1656.     int this_time;
  1657.  
  1658.     gettimeofday(&tp_end,NULL);
  1659.     this_time = 
  1660.       (tp_end.tv_sec - tp_start.tv_sec)*1000 +
  1661.     (tp_end.tv_usec - tp_start.tv_usec)/1000;
  1662.     put_total_time_ms += this_time;
  1663.     put_total_size += finfo->size;
  1664.  
  1665.     DEBUG(2,("(%g kb/s) (average %g kb/s)\n",
  1666.          finfo->size / (1.024*this_time),
  1667.          put_total_size / (1.024*put_total_time_ms)));
  1668.   }
  1669. }
  1670.  
  1671.  
  1672. /****************************************************************************
  1673.   fudge a single file
  1674. ****************************************************************************/
  1675. void do_fudge(file_info *finfo)
  1676. {
  1677.   int fnum;
  1678.   char *p;
  1679.   char *inbuf,*outbuf;
  1680.   time_t old_mtime;
  1681.   static time_t sane_date = 0;
  1682.   
  1683.   {
  1684.     pstring n2;
  1685.     strcpy(n2,finfo->name);
  1686.     strcpy(finfo->name,cur_dir);
  1687.     strcat(finfo->name,n2);
  1688.   }
  1689.   
  1690.   if (sane_date == 0)
  1691.     {
  1692.       sane_date = start_of_month();
  1693.     }
  1694.   
  1695.   if (sane_unix_date(finfo->mtime))
  1696.     return;
  1697.   
  1698.   DEBUG(2,("Fixing insane date on file %s %s",CNV_LANG(finfo->name),
  1699.      asctime(LocalTime(&finfo->mtime,LOCAL_TO_GMT))));
  1700.  
  1701.   finfo->mtime = sane_date;
  1702.   
  1703.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1704.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1705.   
  1706.   if (!inbuf || !outbuf)
  1707.     {
  1708.       DEBUG(0,("out of memory\n"));
  1709.       return;
  1710.     }
  1711.   
  1712.   memset(outbuf,0,smb_size);
  1713.   set_message(outbuf,2,2 + strlen(finfo->name),True);
  1714.   
  1715.   CVAL(outbuf,smb_com) = SMBopen;
  1716.   SSVAL(outbuf,smb_tid,cnum);
  1717.   setup_pkt(outbuf);
  1718.   
  1719.   SSVAL(outbuf,smb_vwv0,0);
  1720.   SSVAL(outbuf,smb_vwv1,0);
  1721.   
  1722.   p = smb_buf(outbuf);
  1723.   *p++ = 4;      
  1724.   strcpy(p,finfo->name);
  1725.   dos_clean_name(finfo->name);
  1726.   
  1727.   send_smb(outbuf);
  1728.   receive_smb(inbuf,0);
  1729.   
  1730.   if (CVAL(inbuf,smb_rcls) != 0)
  1731.     {
  1732.       DEBUG(0,("Error %s opening remote file %s\n",smb_errstr(inbuf),
  1733.          CNV_LANG(finfo->name)));
  1734.       free(inbuf);free(outbuf);
  1735.       return;
  1736.     }
  1737.   
  1738.   fnum = SVAL(inbuf,smb_vwv0);
  1739.   old_mtime = IVAL(inbuf,smb_vwv2);
  1740.   
  1741.   if (sane_unix_date(old_mtime))
  1742.     {
  1743.       finfo->mtime = old_mtime;
  1744.       DEBUG(2,("Already sane date on file %s %s",CNV_LANG(finfo->name),
  1745.          asctime(LocalTime(&finfo->mtime,LOCAL_TO_GMT))));
  1746.     }
  1747.   
  1748.   memset(outbuf,0,smb_size);
  1749.   set_message(outbuf,3,0,True);
  1750.   CVAL(outbuf,smb_com) = SMBclose;
  1751.   SSVAL(outbuf,smb_tid,cnum);
  1752.   setup_pkt(outbuf);
  1753.   
  1754.   SSVAL(outbuf,smb_vwv0,fnum);
  1755.   SIVAL(outbuf,smb_vwv1,finfo->mtime);
  1756.   
  1757.   send_smb(outbuf);
  1758.   receive_smb(inbuf,0);
  1759.   
  1760.   if (CVAL(inbuf,smb_rcls) != 0)
  1761.     {
  1762.       DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
  1763.       free(inbuf);free(outbuf);
  1764.       return;
  1765.     }
  1766.   
  1767.   free(inbuf);free(outbuf);
  1768. }
  1769.  
  1770. /****************************************************************************
  1771.   fudge dates
  1772.   ****************************************************************************/
  1773. void cmd_fudge(char *inbuf,char *outbuf)
  1774. {
  1775.   int attribute = aDIR | aSYSTEM | aHIDDEN;
  1776.   pstring mask;
  1777.   char *p;
  1778.   
  1779.   strcpy(mask,cur_dir);
  1780.   if(mask[strlen(mask)-1]!='\\')
  1781.     strcat(mask,"\\");
  1782.   
  1783.   p = strtok(NULL,SEPARATORS);
  1784.   if (p)
  1785.     {
  1786.       if (*p == '\\')
  1787.      strcpy(mask,p);
  1788.       else
  1789.      strcat(mask,p);
  1790.     }
  1791.   else
  1792.     strcat(mask,"*.*");
  1793.   
  1794.   do_dir(inbuf,outbuf,mask,attribute,do_fudge,recurse);
  1795. }
  1796.  
  1797.  
  1798.  
  1799. /****************************************************************************
  1800. put a file
  1801. ****************************************************************************/
  1802. void cmd_put(void)
  1803. {
  1804.   pstring lname;
  1805.   pstring rname;
  1806.   char *p;
  1807.   file_info finfo = def_finfo;
  1808.   
  1809.   strcpy(rname,cur_dir);
  1810.   strcat(rname,"\\");
  1811.   
  1812.   p = strtok(NULL,SEPARATORS);
  1813.   if (!p)
  1814.     {
  1815.       DEBUG(0,("put <filename>\n"));
  1816.       return;
  1817.     }
  1818.   strcpy(lname,p);
  1819.   
  1820.   p = strtok(NULL,SEPARATORS);
  1821.   if (p)
  1822.     strcat(rname,p);      
  1823.   else
  1824.     strcat(rname,lname);
  1825.  
  1826.   dos_clean_name(rname);
  1827.  
  1828.   /* let the remote side decide the date */
  1829.   finfo.mtime = -1;
  1830.  
  1831.   do_put(rname,lname,&finfo);
  1832. }
  1833.  
  1834. /****************************************************************************
  1835. seek in a directory/file list until you get something that doesn't start with
  1836. the specified name
  1837. ****************************************************************************/
  1838. BOOL seek_list(FILE *f,char *name)
  1839. {
  1840.   pstring s;
  1841.   while (!feof(f))
  1842.     {
  1843.       if (fscanf(f,"%s",s) != 1) return(False);
  1844.       trim_string(s,"./",NULL);
  1845.       if (strncmp(s,name,strlen(name)) != 0)
  1846.     {
  1847.       strcpy(name,s);
  1848.       return(True);
  1849.     }
  1850.     }
  1851.       
  1852.   return(False);
  1853. }
  1854.  
  1855.  
  1856. /****************************************************************************
  1857. set the file selection mask
  1858. ****************************************************************************/
  1859. void cmd_select(void)
  1860. {
  1861.   char *p = strtok(NULL,SEPARATORS);
  1862.   if (p)
  1863.     strcpy(fileselection,p);
  1864.   else
  1865.     strcpy(fileselection,"");
  1866. }
  1867.  
  1868.  
  1869. /****************************************************************************
  1870. mput some files
  1871. ****************************************************************************/
  1872. void cmd_mput(void)
  1873. {
  1874.   pstring lname;
  1875.   pstring rname;
  1876.   file_info finfo = def_finfo;
  1877.  
  1878.   char *p;
  1879.   
  1880.   while ((p = strtok(NULL,SEPARATORS)))
  1881.     {
  1882.       pstring cmd;
  1883.       pstring tmpnam;
  1884.       FILE *f;
  1885.       
  1886.       sprintf(tmpnam,"/tmp/ls.smb.%d",getpid());
  1887.       if (recurse)
  1888.     sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpnam);
  1889.       else
  1890.     sprintf(cmd,"/bin/ls %s > %s",p,tmpnam);
  1891.       system(cmd);
  1892.  
  1893.       f = fopen(tmpnam,"r");
  1894.       if (!f) continue;
  1895.  
  1896.       while (!feof(f))
  1897.     {
  1898.       pstring quest;
  1899.  
  1900.       if (fscanf(f,"%s",lname) != 1) break;
  1901.       trim_string(lname,"./",NULL);
  1902.  
  1903.     again:
  1904.  
  1905.       /* check if it's a directory */
  1906.       if (directory_exist(lname))
  1907.         {
  1908.           if (!recurse) continue;
  1909.           sprintf(quest,"Put directory %s? ",lname);
  1910.           if (prompt && !yesno(quest)) 
  1911.         {
  1912.           strcat(lname,"/");
  1913.           if (!seek_list(f,lname))
  1914.             break;
  1915.           goto again;            
  1916.         }
  1917.           
  1918.           strcpy(rname,cur_dir);
  1919.           strcat(rname,lname);
  1920.           if (!do_mkdir(rname))
  1921.         {
  1922.           strcat(lname,"/");
  1923.           if (!seek_list(f,lname))
  1924.             break;
  1925.           goto again;                      
  1926.         }
  1927.  
  1928.           continue;
  1929.         }
  1930.       else
  1931.         {
  1932.           sprintf(quest,"Put file %s? ",lname);
  1933.           if (prompt && !yesno(quest)) continue;
  1934.  
  1935.           strcpy(rname,cur_dir);
  1936.           strcat(rname,lname);
  1937.         }
  1938.       dos_format(rname);
  1939.  
  1940.       /* null size so do_put knows to ignore it */
  1941.       finfo.size = -1;
  1942.  
  1943.       /* let the remote side decide the date */
  1944.       finfo.mtime = -1;
  1945.  
  1946.       do_put(rname,lname,&finfo);
  1947.     }
  1948.       fclose(f);
  1949.       unlink(tmpnam);
  1950.     }
  1951. }
  1952.  
  1953. /****************************************************************************
  1954. print a file
  1955. ****************************************************************************/
  1956. void cmd_print(char *inbuf,char *outbuf )
  1957. {
  1958.   int fnum;
  1959.   FILE *f = NULL;
  1960.   uint32 nread=0;
  1961.   pstring lname;
  1962.   pstring rname;
  1963.   char *p;
  1964.  
  1965.   p = strtok(NULL,SEPARATORS);
  1966.   if (!p)
  1967.     {
  1968.       DEBUG(0,("print <filename>\n"));
  1969.       return;
  1970.     }
  1971.   strcpy(lname,p);
  1972.  
  1973.   strcpy(rname,lname);
  1974.   p = strrchr(rname,'/');
  1975.   if (p)
  1976.     {
  1977.       pstring tname;
  1978.       strcpy(tname,p+1);
  1979.       strcpy(rname,tname);
  1980.     }
  1981.  
  1982.   if (strlen(rname) > 14)
  1983.     rname[14] = 0;
  1984.  
  1985.   if (strequal(lname,"-"))
  1986.     {
  1987.       f = stdin;
  1988.       strcpy(rname,"stdin");
  1989.     }
  1990.   
  1991.   dos_clean_name(rname);
  1992.  
  1993.   memset(outbuf,0,smb_size);
  1994.   set_message(outbuf,2,2 + strlen(rname),True);
  1995.   
  1996.   CVAL(outbuf,smb_com) = SMBsplopen;
  1997.   SSVAL(outbuf,smb_tid,cnum);
  1998.   setup_pkt(outbuf);
  1999.  
  2000.   SSVAL(outbuf,smb_vwv0,0);
  2001.   SSVAL(outbuf,smb_vwv1,printmode);
  2002.   
  2003.   p = smb_buf(outbuf);
  2004.   *p++ = 4;      
  2005.   strcpy(p,rname);
  2006.   
  2007.   send_smb(outbuf);
  2008.   receive_smb(inbuf,0);
  2009.   
  2010.   if (CVAL(inbuf,smb_rcls) != 0)
  2011.     {
  2012.       DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  2013.       return;
  2014.     }
  2015.   
  2016.   if (!f)
  2017.     f = fopen(lname,"r");
  2018.   if (!f)
  2019.     {
  2020.       DEBUG(0,("Error opening local file %s\n",lname));
  2021.       return;
  2022.     }
  2023.  
  2024.   
  2025.   fnum = SVAL(inbuf,smb_vwv0);
  2026.   
  2027.   DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
  2028.   
  2029.   while (!feof(f))
  2030.     {
  2031.       int n;
  2032.   
  2033.       memset(outbuf,0,smb_size);
  2034.       set_message(outbuf,1,3,True);
  2035.  
  2036.       /* for some strange reason the OS/2 print server can't handle large
  2037.      packets when printing. weird */
  2038.       n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
  2039.  
  2040. #if 0
  2041.       if (first)
  2042.     {
  2043.       n = 0;
  2044.       first = False;
  2045.     }
  2046.       else
  2047. #endif
  2048.     {
  2049.       if (translation)
  2050.         n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
  2051.       else
  2052.         n = readfile(smb_buf(outbuf)+3,1,n,f);
  2053.       if (n <= 0) 
  2054.         {
  2055.           DEBUG(0,("read gave %d\n",n));
  2056.           break;
  2057.         }
  2058.     }
  2059.  
  2060.       smb_setlen(outbuf,smb_len(outbuf) + n);
  2061.  
  2062.       CVAL(outbuf,smb_com) = SMBsplwr;
  2063.       SSVAL(outbuf,smb_tid,cnum);
  2064.       setup_pkt(outbuf);
  2065.  
  2066.       SSVAL(outbuf,smb_vwv0,fnum);
  2067.       SSVAL(outbuf,smb_vwv1,n+3);
  2068.       CVAL(smb_buf(outbuf),0) = 1;
  2069.       SSVAL(smb_buf(outbuf),1,n);
  2070.  
  2071.       send_smb(outbuf);
  2072.       receive_smb(inbuf,0);
  2073.  
  2074.       if (CVAL(inbuf,smb_rcls) != 0)
  2075.     {
  2076.       DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
  2077.       break;
  2078.     }
  2079.  
  2080.       nread += n;
  2081.     }
  2082.  
  2083.   DEBUG(2,("%d bytes printed\n",nread));
  2084.  
  2085.   memset(outbuf,0,smb_size);
  2086.   set_message(outbuf,1,0,True);
  2087.   CVAL(outbuf,smb_com) = SMBsplclose;
  2088.   SSVAL(outbuf,smb_tid,cnum);
  2089.   setup_pkt(outbuf);
  2090.  
  2091.   SSVAL(outbuf,smb_vwv0,fnum);
  2092.  
  2093.   send_smb(outbuf);
  2094.   receive_smb(inbuf,0);
  2095.   
  2096.   if (CVAL(inbuf,smb_rcls) != 0)
  2097.     {
  2098.       DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
  2099.       if (f != stdin)
  2100.     fclose(f);
  2101.       return;
  2102.     }
  2103.  
  2104.   if (f != stdin)
  2105.     fclose(f);
  2106. }
  2107.  
  2108. /****************************************************************************
  2109. print a file
  2110. ****************************************************************************/
  2111. void cmd_queue(char *inbuf,char *outbuf )
  2112. {
  2113.   int count;
  2114.   char *p;
  2115.  
  2116.   memset(outbuf,0,smb_size);
  2117.   set_message(outbuf,2,0,True);
  2118.   
  2119.   CVAL(outbuf,smb_com) = SMBsplretq;
  2120.   SSVAL(outbuf,smb_tid,cnum);
  2121.   setup_pkt(outbuf);
  2122.  
  2123.   SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
  2124.   SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
  2125.   
  2126.   send_smb(outbuf);
  2127.   receive_smb(inbuf,0);
  2128.   
  2129.   if (CVAL(inbuf,smb_rcls) != 0)
  2130.     {
  2131.       DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
  2132.       return;
  2133.     }
  2134.  
  2135.   count = SVAL(inbuf,smb_vwv0);
  2136.   p = smb_buf(inbuf) + 3;
  2137.   if (count <= 0)
  2138.     {
  2139.       DEBUG(0,("No entries in the print queue\n"));
  2140.       return;
  2141.     }  
  2142.  
  2143.   {
  2144.     char status[20];
  2145.  
  2146.     DEBUG(0,("Job      Name              Size         Status\n"));
  2147.  
  2148.     while (count--)
  2149.       {
  2150.     switch (CVAL(p,4))
  2151.       {
  2152.       case 0x01: sprintf(status,"held or stopped"); break;
  2153.       case 0x02: sprintf(status,"printing"); break;
  2154.       case 0x03: sprintf(status,"awaiting print"); break;
  2155.       case 0x04: sprintf(status,"in intercept"); break;
  2156.       case 0x05: sprintf(status,"file had error"); break;
  2157.       case 0x06: sprintf(status,"printer error"); break;
  2158.       default: sprintf(status,"unknown"); break;
  2159.       }
  2160.  
  2161.     DEBUG(0,("%-6d   %-16.16s  %-9d    %s\n",
  2162.          SVAL(p,5),p+12,IVAL(p,7),status));
  2163.     p += 28;
  2164.       }
  2165.   }
  2166.   
  2167. }
  2168.  
  2169.  
  2170. /****************************************************************************
  2171. delete some files
  2172. ****************************************************************************/
  2173. void do_del(file_info *finfo)
  2174. {
  2175.   char *p;
  2176.   char *inbuf,*outbuf;
  2177.   pstring mask;
  2178.  
  2179.   strcpy(mask,cur_dir);
  2180.   strcat(mask,finfo->name);
  2181.  
  2182.   if (finfo->mode & aDIR) 
  2183.     return;
  2184.  
  2185.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2186.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2187.   
  2188.   if (!inbuf || !outbuf)
  2189.     {
  2190.       DEBUG(0,("out of memory\n"));
  2191.       return;
  2192.     }
  2193.  
  2194.   memset(outbuf,0,smb_size);
  2195.   set_message(outbuf,1,2 + strlen(mask),True);
  2196.   
  2197.   CVAL(outbuf,smb_com) = SMBunlink;
  2198.   SSVAL(outbuf,smb_tid,cnum);
  2199.   setup_pkt(outbuf);
  2200.  
  2201.   SSVAL(outbuf,smb_vwv0,0);
  2202.   
  2203.   p = smb_buf(outbuf);
  2204.   *p++ = 4;      
  2205.   strcpy(p,mask);
  2206.   
  2207.   send_smb(outbuf);
  2208.   receive_smb(inbuf,0);
  2209.   
  2210.   if (CVAL(inbuf,smb_rcls) != 0)
  2211.     DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
  2212.  
  2213.   free(inbuf);free(outbuf);
  2214.   
  2215. }
  2216.  
  2217. /****************************************************************************
  2218. delete some files
  2219. ****************************************************************************/
  2220. void cmd_del(char *inbuf,char *outbuf )
  2221. {
  2222.   pstring mask;
  2223.   char *p;
  2224.   int attribute = aSYSTEM | aHIDDEN;
  2225.  
  2226.   if (recurse)
  2227.     attribute |= aDIR;
  2228.   
  2229.   strcpy(mask,cur_dir);
  2230.   
  2231.   p = strtok(NULL,SEPARATORS);
  2232.   if (!p)
  2233.     {
  2234.       DEBUG(0,("del <filename>\n"));
  2235.       return;
  2236.     }
  2237.   strcat(mask,p);
  2238.  
  2239.   do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
  2240. }
  2241.  
  2242.  
  2243. /****************************************************************************
  2244. remove a directory
  2245. ****************************************************************************/
  2246. void cmd_rmdir(char *inbuf,char *outbuf )
  2247. {
  2248.   pstring mask;
  2249.   char *p;
  2250.   
  2251.   strcpy(mask,cur_dir);
  2252.   
  2253.   p = strtok(NULL,SEPARATORS);
  2254.   if (!p)
  2255.     {
  2256.       DEBUG(0,("rmdir <dirname>\n"));
  2257.       return;
  2258.     }
  2259.   strcat(mask,p);
  2260.  
  2261.  
  2262.   memset(outbuf,0,smb_size);
  2263.   set_message(outbuf,0,2 + strlen(mask),True);
  2264.   
  2265.   CVAL(outbuf,smb_com) = SMBrmdir;
  2266.   SSVAL(outbuf,smb_tid,cnum);
  2267.   setup_pkt(outbuf);
  2268.  
  2269.   
  2270.   p = smb_buf(outbuf);
  2271.   *p++ = 4;      
  2272.   strcpy(p,mask);
  2273.   
  2274.   send_smb(outbuf);
  2275.   receive_smb(inbuf,0);
  2276.   
  2277.   if (CVAL(inbuf,smb_rcls) != 0)
  2278.     {
  2279.       DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
  2280.       return;
  2281.     }
  2282.   
  2283. }
  2284.  
  2285. /****************************************************************************
  2286. toggle the prompt flag
  2287. ****************************************************************************/
  2288. void cmd_prompt(void)
  2289. {
  2290.   prompt = !prompt;
  2291.   DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
  2292. }
  2293.  
  2294.  
  2295. /****************************************************************************
  2296. set the newer than time
  2297. ****************************************************************************/
  2298. void cmd_newer(void)
  2299. {
  2300.   char *p = strtok(NULL,SEPARATORS);
  2301.   struct stat sbuf;
  2302.  
  2303.   if (p && (stat(p,&sbuf) == 0))
  2304.     {
  2305.       newer_than = sbuf.st_mtime + GMT_TO_LOCAL*TimeDiff();
  2306.       DEBUG(1,("Getting files newer than %s",asctime(LocalTime(&newer_than,0))));
  2307.     }
  2308.   else
  2309.     newer_than = 0;
  2310.  
  2311.   if (p && newer_than == 0)
  2312.     DEBUG(0,("Error setting newer-than time\n"));
  2313. }
  2314.  
  2315. /****************************************************************************
  2316. toggle the lowercaseflag
  2317. ****************************************************************************/
  2318. void cmd_lowercase(void)
  2319. {
  2320.   lowercase = !lowercase;
  2321.   DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
  2322. }
  2323.  
  2324.  
  2325.  
  2326.  
  2327. /****************************************************************************
  2328. toggle the recurse flag
  2329. ****************************************************************************/
  2330. void cmd_recurse(void)
  2331. {
  2332.   recurse = !recurse;
  2333.   DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
  2334. }
  2335.  
  2336. /****************************************************************************
  2337. toggle the translate flag
  2338. ****************************************************************************/
  2339. void cmd_translate(void)
  2340. {
  2341.   translation = !translation;
  2342.   DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
  2343.     translation?"on":"off"));
  2344. }
  2345.  
  2346.  
  2347. /****************************************************************************
  2348. do a printmode command
  2349. ****************************************************************************/
  2350. void cmd_printmode(void)
  2351. {
  2352.   char *p;
  2353.   pstring mode;
  2354.  
  2355.   p = strtok(NULL,SEPARATORS);
  2356.   if (p)
  2357.     {
  2358.       if (strequal(p,"text"))
  2359.     printmode = 0;      
  2360.       else
  2361.     {
  2362.       if (strequal(p,"graphics"))
  2363.         printmode = 1;
  2364.       else
  2365.         printmode = atoi(p);
  2366.     }
  2367.     }
  2368.  
  2369.   switch(printmode)
  2370.     {
  2371.     case 0: 
  2372.       strcpy(mode,"text");
  2373.       break;
  2374.     case 1: 
  2375.       strcpy(mode,"graphics");
  2376.       break;
  2377.     default: 
  2378.       sprintf(mode,"%d",printmode);
  2379.       break;
  2380.     }
  2381.  
  2382.   DEBUG(2,("the printmode is now %s\n",mode));
  2383. }
  2384.  
  2385. /****************************************************************************
  2386. do the lcd command
  2387. ****************************************************************************/
  2388. void cmd_lcd(void)
  2389. {
  2390.   char *p;
  2391.   pstring d;
  2392.  
  2393.   p = strtok(NULL,SEPARATORS);
  2394.   if (p)
  2395.     chdir(p);
  2396.   DEBUG(2,("the local directory is now %s\n",GetWd(d)));
  2397. }
  2398.  
  2399.  
  2400. /****************************************************************************
  2401. send a login command
  2402. ****************************************************************************/
  2403. BOOL send_login(char *inbuf,char *outbuf,BOOL use_setup)
  2404. {
  2405.   int sesskey=0;
  2406.   struct {
  2407.     int prot;
  2408.     char *name;
  2409.   }
  2410.   prots[] = 
  2411.     {
  2412.       {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
  2413.       {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
  2414. #if LANMAN1
  2415.       {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
  2416.       {PROTOCOL_LANMAN1,"LANMAN1.0"},
  2417. #endif
  2418. #if LANMAN2
  2419.       {PROTOCOL_LANMAN2,"LM1.2X002"},
  2420. #endif
  2421.       {-1,NULL}
  2422.     };
  2423.   char *pass = NULL;  
  2424.   pstring dev = "A:";
  2425.   char *p;
  2426.   int len = 4;
  2427.   int numprots;
  2428.  
  2429.   if (connect_as_printer)
  2430.     strcpy(dev,"LPT1:");
  2431.   if (connect_as_ipc)
  2432.     strcpy(dev,"IPC");
  2433.  
  2434.   /* send a session request (RFC 8002) */
  2435.   CVAL(outbuf,0) = 0x81;
  2436.  
  2437.   /* put in the destination name */
  2438.   p = outbuf+len;
  2439.   name_mangle(desthost,p);
  2440.   len += name_len(p);
  2441.  
  2442.   /* and my name */
  2443.   p = outbuf+len;
  2444.   name_mangle(myname,p);
  2445.   len += name_len(p);
  2446.  
  2447.   /* setup the packet length */
  2448.   /* We can't use smb_setlen here as it assumes a data
  2449.      packet and will trample over the name data we have copied
  2450.      in (by adding 0xFF 'S' 'M' 'B' at offsets 4 - 7 */
  2451.  
  2452.   SSVAL(outbuf,2,len);
  2453.   BSWP(outbuf+2,2);
  2454.  
  2455.   if (len >= (1 << 16))
  2456.     CVAL(outbuf,1) |= 1;
  2457.  
  2458.   send_smb(outbuf);
  2459.   DEBUG(5,("Sent session request\n"));
  2460.  
  2461.   receive_smb(inbuf,0);
  2462.  
  2463.   if (CVAL(inbuf,0) != 0x82)
  2464.     {
  2465.       int ecode = CVAL(inbuf,4);
  2466.       DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
  2467.         CVAL(inbuf,0),ecode,myname,desthost));
  2468.       switch (ecode)
  2469.     {
  2470.     case 0x80: 
  2471.       DEBUG(0,("Not listening on called name\n")); 
  2472.       DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
  2473.       DEBUG(0,("You may find the -I option useful for this\n"));
  2474.       break;
  2475.     case 0x81: 
  2476.       DEBUG(0,("Not listening for calling name\n")); 
  2477.       DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
  2478.       DEBUG(0,("You may find the -n option useful for this\n"));
  2479.       break;
  2480.     case 0x82: 
  2481.       DEBUG(0,("Called name not present\n")); 
  2482.       DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
  2483.       DEBUG(0,("You may find the -I option useful for this\n"));
  2484.       break;
  2485.     case 0x83: 
  2486.       DEBUG(0,("Called name present, but insufficient resources\n")); 
  2487.       DEBUG(0,("Perhaps you should try again later?\n")); 
  2488.       break;
  2489.     case 0x8F:
  2490.       DEBUG(0,("Unspecified error 0x%X\n",ecode)); 
  2491.       DEBUG(0,("Your server software is being unfriendly\n"));
  2492.       break;      
  2493.     }
  2494.       return(False);
  2495.     }      
  2496.  
  2497.   memset(outbuf,0,smb_size);
  2498.  
  2499.   /* setup the protocol strings */
  2500.   {
  2501.     int plength;
  2502.     char *p;
  2503.  
  2504.     for (numprots=0,plength=0;prots[numprots].name;numprots++)
  2505.       plength += strlen(prots[numprots].name)+2;
  2506.     
  2507.     set_message(outbuf,0,plength,True);
  2508.  
  2509.     p = smb_buf(outbuf);
  2510.     for (numprots=0;prots[numprots].name;numprots++)
  2511.       {
  2512.     *p++ = 2;
  2513.     strcpy(p,prots[numprots].name);
  2514.     p += strlen(p) + 1;
  2515.       }
  2516.   }
  2517.  
  2518.   CVAL(outbuf,smb_com) = SMBnegprot;
  2519.   setup_pkt(outbuf);
  2520.  
  2521.   CVAL(smb_buf(outbuf),0) = 2;
  2522.  
  2523.   send_smb(outbuf);
  2524.   receive_smb(inbuf,0);
  2525.  
  2526.   if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
  2527.     {
  2528.       DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
  2529.         myname,desthost,smb_errstr(inbuf)));
  2530.       return(False);
  2531.     }
  2532.  
  2533.   max_xmit = MIN(max_xmit,(int)SVAL(inbuf,smb_vwv2));
  2534.  
  2535.   DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
  2536.   DEBUG(3,("max xmt %d\n",SVAL(inbuf,smb_vwv2)));
  2537.   DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
  2538.   DEBUG(3,("max vcs %d\n",SVAL(inbuf,smb_vwv4)));
  2539.   DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
  2540.   DEBUG(3,("time zone %d\n",SVAL(inbuf,smb_vwv10)));
  2541.  
  2542.   sesskey = IVAL(inbuf,smb_vwv6);
  2543.  
  2544.   servertime = make_unix_date(inbuf+smb_vwv8);
  2545.  
  2546.   DEBUG(3,("Got %d byte crypt key\n",strlen(smb_buf(inbuf))));
  2547.  
  2548.   DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
  2549.   Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
  2550.   if (Protocol >= PROTOCOL_COREPLUS)
  2551.     {
  2552.       readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
  2553.       writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
  2554.     }
  2555.  
  2556.   if (Protocol >= PROTOCOL_LANMAN1)
  2557.     {
  2558.       DEBUG(1,("Server time is %sTimezone is UTC%+d\n",
  2559.            asctime(LocalTime(&servertime,0)),
  2560.            -(int16)SVAL(inbuf,smb_vwv10)/60));
  2561.     }
  2562.  
  2563.   if (got_pass)
  2564.     pass = password;
  2565.   else
  2566.     pass = (char *)getpass("Password: ");
  2567.  
  2568.   if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
  2569.     {
  2570.       /* send a session setup command */
  2571.       memset(outbuf,0,smb_size);
  2572.       set_message(outbuf,10,2 + strlen(username) + strlen(pass),True);
  2573.       CVAL(outbuf,smb_com) = SMBsesssetupX;
  2574.       setup_pkt(outbuf);
  2575.  
  2576.       CVAL(outbuf,smb_vwv0) = 0xFF;
  2577.       SSVAL(outbuf,smb_vwv2,max_xmit);
  2578.       SSVAL(outbuf,smb_vwv3,2);
  2579.       SSVAL(outbuf,smb_vwv4,getpid());
  2580.       SIVAL(outbuf,smb_vwv5,sesskey);
  2581.       SSVAL(outbuf,smb_vwv7,strlen(pass)+1);
  2582.       p = smb_buf(outbuf);
  2583.       strcpy(p,pass);
  2584.       p += strlen(pass)+1;
  2585.       strcpy(p,username);
  2586.  
  2587.       send_smb(outbuf);
  2588.       receive_smb(inbuf,0);      
  2589.  
  2590.       if (CVAL(inbuf,smb_rcls) != 0)
  2591.     {
  2592.       DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s   %s\n",
  2593.         username,myname,desthost,smb_errstr(inbuf)));
  2594.       DEBUG(0,("You might find the -U or -n options useful\n"));
  2595.       DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
  2596.       DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
  2597.       return(False);
  2598.     }
  2599.  
  2600.       /* use the returned uid from now on */
  2601.       if (SVAL(inbuf,smb_uid) != uid)
  2602.     DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
  2603.           SVAL(inbuf,smb_uid),uid));
  2604.       uid = SVAL(inbuf,smb_uid);
  2605.     }
  2606.  
  2607.   /* now we've got a connection - send a tcon message */
  2608.   memset(outbuf,0,smb_size);
  2609. #if 0
  2610.   if (Protocol >= PROTOCOL_LANMAN1)
  2611.     strcpy(pass,"");
  2612. #endif
  2613.  
  2614.   if (strncmp(service,"\\\\",2) != 0)
  2615.     {
  2616.       DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
  2617.       DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
  2618.     }
  2619.  
  2620.  
  2621.  again:
  2622.   set_message(outbuf,0,6 + strlen(service) + strlen(pass) + strlen(dev),True);
  2623.   CVAL(outbuf,smb_com) = SMBtcon;
  2624.   setup_pkt(outbuf);
  2625.  
  2626.   p = smb_buf(outbuf);
  2627.   *p++ = 4;
  2628.   strcpy(p,service);
  2629.   p += strlen(p) + 1;
  2630.   *p++ = 4;
  2631.   strcpy(p,pass);
  2632.   p += strlen(p) + 1;
  2633.   *p++ = 4;
  2634.   strcpy(p,dev);
  2635.  
  2636.   send_smb(outbuf);
  2637.   receive_smb(inbuf,0);
  2638.  
  2639.   /* trying again with a blank password */
  2640.   if (CVAL(inbuf,smb_rcls) != 0 && 
  2641.       strlen(pass) > 0 && 
  2642.       Protocol >= PROTOCOL_LANMAN1)
  2643.     {
  2644.       DEBUG(0,("first SMBtcon failed, trying again. %s\n",smb_errstr(inbuf)));
  2645.       strcpy(pass,"");
  2646.       goto again;
  2647.     }  
  2648.  
  2649.   if (CVAL(inbuf,smb_rcls) != 0)
  2650.     {
  2651.       DEBUG(0,("SMBtcon failed. %s\n",smb_errstr(inbuf)));
  2652.       DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
  2653.       DEBUG(0,("Some servers insist that these be in uppercase\n"));
  2654.       return(False);
  2655.     }
  2656.   
  2657.  
  2658.   max_xmit = SVAL(inbuf,smb_vwv0);
  2659.   max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
  2660.   if (max_xmit <= 0)
  2661.     max_xmit = BUFFER_SIZE - 4;
  2662.  
  2663.   cnum = SVAL(inbuf,smb_vwv1);
  2664.  
  2665.   DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
  2666.  
  2667.   /* wipe out the password from memory */
  2668.   if (got_pass)
  2669.     memset(password,0,strlen(password));
  2670.  
  2671.   return True;
  2672.  
  2673. }
  2674.  
  2675.  
  2676. /****************************************************************************
  2677. send a logout command
  2678. ****************************************************************************/
  2679. void send_logout(char *inbuf,char *outbuf )
  2680. {
  2681.   set_message(outbuf,0,0,True);
  2682.   CVAL(outbuf,smb_com) = SMBtdis;
  2683.   SSVAL(outbuf,smb_tid,cnum);
  2684.   setup_pkt(outbuf);
  2685.  
  2686.   send_smb(outbuf);
  2687.   receive_smb(inbuf,0);
  2688.  
  2689.   if (CVAL(inbuf,smb_rcls) != 0)
  2690.     {
  2691.       DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
  2692.     }
  2693. #if 0
  2694.   set_message(outbuf,0,0,True);
  2695.   CVAL(outbuf,smb_com) = SMBexit;
  2696.   setup_pkt(outbuf);
  2697.  
  2698.   send_smb(outbuf);
  2699.   receive_smb(inbuf,0);
  2700.  
  2701.   if (CVAL(inbuf,smb_rcls) != 0)
  2702.     {
  2703.       DEBUG(0,("SMBexit failed %s\n",smb_errstr(inbuf)));
  2704.     }
  2705. #endif
  2706.  
  2707.   
  2708. #ifdef STATS
  2709.   stats_report();
  2710. #endif
  2711.   exit(0);
  2712. }
  2713.  
  2714.  
  2715. /****************************************************************************
  2716. try and browse available connections on a host
  2717. ****************************************************************************/
  2718. void browse_host()
  2719. {
  2720.   char *p;
  2721.   char *params;
  2722.   char *inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2723.   char *outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2724.   if ((inbuf == NULL) || (outbuf == NULL)) 
  2725.     return;
  2726.   
  2727.   memset(outbuf,0,smb_size);
  2728.  
  2729.   if (!send_login(inbuf,outbuf,True))
  2730.     return;
  2731.  
  2732.   /* now send a SMBtrans command with api RNetShareEnum */
  2733.   memset(outbuf,0,smb_size);
  2734.   set_message(outbuf,14,0,True);
  2735.   CVAL(outbuf,smb_com) = SMBtrans;
  2736.   SSVAL(outbuf,smb_tid,cnum);
  2737.   setup_pkt(outbuf);
  2738.  
  2739.   SSVAL(outbuf,smb_vwv1,0); /* data count */
  2740.   SSVAL(outbuf,smb_vwv2,1024); /* mprcnt */
  2741.   SSVAL(outbuf,smb_vwv3,4096); /* mdrcnt */
  2742.   SSVAL(outbuf,smb_vwv4,10); /* msrcnt */
  2743.   SSVAL(outbuf,smb_vwv5,0); /* flags */
  2744.   SSVAL(outbuf,smb_vwv11,0); /* dscnt */
  2745.   SSVAL(outbuf,smb_vwv12,0); /* dsoff */
  2746.   CVAL(outbuf,smb_vwv13) = 0; /* suwcnt */
  2747.  
  2748.   p = smb_buf(outbuf);
  2749.  
  2750.   strcpy(p,"\\PIPE\\LANMAN");
  2751.  
  2752.   params = skip_string(p,1);
  2753.  
  2754.   SSVAL(params,0,0); /* RNetShareEnum */
  2755.   
  2756.   p = params+2;
  2757.  
  2758.   strcpy(p,"WrLeh");
  2759.   p = skip_string(p,1);
  2760.   strcpy(p,"B13BWz");
  2761.   p = skip_string(p,1);
  2762.   SSVAL(p,0,1);
  2763.   SSVAL(p,2,SVAL(outbuf,smb_vwv3));
  2764.  
  2765.   p += 4;
  2766.  
  2767.  
  2768.   set_message(outbuf,14,PTR_DIFF(p,smb_buf(outbuf)),False);
  2769.  
  2770.   SSVAL(outbuf,smb_vwv0,PTR_DIFF(p,params)); /* param count */
  2771.   SSVAL(outbuf,smb_vwv9,SVAL(outbuf,smb_vwv0)); /* pscnt */
  2772.   SSVAL(outbuf,smb_vwv10,PTR_DIFF(params,outbuf)-4); /* psoff */
  2773.  
  2774.   send_smb(outbuf);
  2775.   receive_smb(inbuf,0);
  2776.  
  2777.   if (CVAL(inbuf,smb_rcls) == 0)
  2778.     {
  2779.       int ofs_param = SVAL(inbuf,smb_vwv4);
  2780.       int ofs_data = SVAL(inbuf,smb_vwv7);
  2781.       char *param = inbuf+4 + ofs_param;
  2782.       char *data = inbuf+4 + ofs_data;
  2783.       int count=SVAL(param,4);
  2784.       int converter=SVAL(param,2);
  2785.       int i;
  2786.  
  2787.       p = data;
  2788.  
  2789.       if (count > 0)
  2790.     {
  2791.       printf("\n\tSharename      Type      Comment\n");
  2792.       printf("\t---------      ----      -------\n");
  2793.     }
  2794.  
  2795.       for (i=0;i<count;i++)
  2796.     {
  2797.       char *sname = p;
  2798.       int type = SVAL(p,14);
  2799.       int comment_offset = IVAL(p,16) & 0xFFFF;
  2800.       fstring typestr="";
  2801.  
  2802.       switch (type)
  2803.         {
  2804.         case 0:
  2805.           strcpy(typestr,"Disk"); break;
  2806.         case 1:
  2807.           strcpy(typestr,"Printer"); break;          
  2808.         case 2:
  2809.           strcpy(typestr,"Device"); break;
  2810.         case 3:
  2811.           strcpy(typestr,"IPC"); break;      
  2812.         }
  2813.  
  2814.       printf("\t%-15.15s%-10.10s%s\n",
  2815.          sname,
  2816.          typestr,
  2817.          comment_offset?data+comment_offset-converter:"");
  2818.       
  2819.       p += 20;
  2820.     }
  2821.     }
  2822.   send_logout(inbuf,outbuf);
  2823. }
  2824.  
  2825.  
  2826. void cmd_help();
  2827.  
  2828. /* This defines the commands supported by this client */
  2829. struct
  2830. {
  2831.   char *name;
  2832.   void (*fn)();
  2833.   char *description;
  2834. } commands[] = 
  2835. {
  2836.   {"ls",cmd_dir,"<mask> list the contents of the current directory"},
  2837.   {"dir",cmd_dir,"<mask> list the contents of the current directory"},
  2838.   {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
  2839.   {"cd",cmd_cd,"[directory] change/report the remote directory"},
  2840.   {"get",cmd_get,"<remote name> [local name] get a file"},
  2841.   {"mget",cmd_mget,"<mask> get all the matching files"},
  2842.   {"put",cmd_put,"<local name> [remote name] put a file"},
  2843.   {"mput",cmd_mput,"<mask> put all matching files"},
  2844.   {"mask",cmd_select,"<mask> mask all filenames against this"},
  2845.   {"del",cmd_del,"<mask> delete all matching files"},
  2846.   {"rm",cmd_del,"<mask> delete all matching files"},
  2847.   {"mkdir",cmd_mkdir,"<directory> make a directory"},
  2848.   {"md",cmd_mkdir,"<directory> make a directory"},
  2849.   {"rmdir",cmd_rmdir,"<directory> remove a directory"},
  2850.   {"rd",cmd_rmdir,"<directory> remove a directory"},
  2851.   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},  
  2852.   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},  
  2853.   {"translate",cmd_translate,"toggle text translation for printing"},  
  2854.   {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},  
  2855.   {"print",cmd_print,"<file name> print a file"},
  2856.   {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
  2857.   {"queue",cmd_queue,"show the print queue"},
  2858.   {"quit",send_logout,"logoff the server"},
  2859.   {"exit",send_logout,"logoff the server"},
  2860.   {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
  2861.   {"help",cmd_help,"[command] give help on a command"},
  2862.   {"?",cmd_help,"[command] give help on a command"},
  2863.   {"!",NULL,"run a shell command on the local system"},
  2864.   {"",NULL,NULL}
  2865. };
  2866.  
  2867. /****************************************************************************
  2868. help
  2869. ****************************************************************************/
  2870. void cmd_help(void)
  2871. {
  2872.   int i=0;
  2873.   char *p;
  2874.  
  2875.   p = strtok(NULL,SEPARATORS);
  2876.   if (p)
  2877.     {
  2878.       while (commands[i].description)
  2879.     {
  2880.       if (strequal(commands[i].name,p))      
  2881.         DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
  2882.       i++;
  2883.     }
  2884.     }
  2885.   else
  2886.     while (commands[i].description)
  2887.       {
  2888.     DEBUG(0,("%s\n",commands[i].name));
  2889.     i++;
  2890.       }
  2891. }
  2892.  
  2893. /****************************************************************************
  2894. open the client sockets
  2895. ****************************************************************************/
  2896. BOOL open_sockets(int port )
  2897. {
  2898.   char *host;
  2899.   pstring service2;
  2900.   extern int Client;
  2901.  
  2902.   strupper(service);
  2903.  
  2904.   strcpy(service2,service);
  2905.   host = strtok(service2,"\\/");
  2906.   strcpy(desthost,host);
  2907.  
  2908.   DEBUG(3,("Opening sockets\n"));
  2909.  
  2910.   if (*myname == 0)
  2911.     {
  2912.       get_myname(myname,NULL);
  2913.       strupper(myname);
  2914.     }
  2915.  
  2916.   if (!have_ip)
  2917.     {
  2918.       struct hostent *hp;
  2919.  
  2920.       if ((hp = Get_Hostbyname(host)) == 0) 
  2921.     {
  2922.       DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
  2923.       return False;
  2924.     }
  2925.  
  2926.       memcpy((char *)&dest_ip,(char *)hp->h_addr,4);
  2927.     }
  2928.  
  2929.   Client = open_socket_out(&dest_ip, port);
  2930.   if (Client == -1)
  2931.     return False;
  2932.  
  2933.   DEBUG(3,("Connected\n"));
  2934.  
  2935.   {
  2936.     int one=1;
  2937.     setsockopt(Client,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one));
  2938.   }
  2939.  
  2940.   DEBUG(3,("Sockets open\n"));
  2941.  
  2942.   return True;
  2943. }
  2944.  
  2945. /****************************************************************************
  2946. wait for keyboard activity, swallowing network packets
  2947. ****************************************************************************/
  2948. #ifdef CLIX
  2949. char wait_keyboard(char *buffer)
  2950. #else
  2951. void wait_keyboard(char *buffer)
  2952. #endif
  2953. {
  2954.   fd_set fds;
  2955.   int selrtn;
  2956.   struct timeval timeout;
  2957.   
  2958. #ifdef CLIX
  2959.   int delay = 0;
  2960. #endif
  2961.   
  2962.   while (1) 
  2963.     {
  2964.       extern int Client;
  2965.       FD_ZERO(&fds);
  2966.       FD_SET(Client,&fds);
  2967. #ifndef CLIX
  2968.       FD_SET(fileno(stdin),&fds);
  2969. #endif
  2970.       do 
  2971.       {
  2972. #ifdef CLIX
  2973.       timeout.tv_sec = 0;
  2974. #else
  2975.         timeout.tv_sec = 20;
  2976. #endif
  2977.         timeout.tv_usec = 0;
  2978.         selrtn = select(255,SELECT_CAST &fds,NULL,NULL,&timeout);
  2979.       }
  2980.       while(selrtn < 0 && errno == EINTR);
  2981.       
  2982. #ifndef CLIX
  2983.       if (FD_ISSET(fileno(stdin),&fds))
  2984.       return;
  2985. #else
  2986.       {
  2987.     char ch;
  2988.     int f_flags;
  2989.     int readret;
  2990.     
  2991.     f_flags = fcntl(fileno(stdin), F_GETFL, 0);
  2992.     fcntl( fileno(stdin), F_SETFL, f_flags | O_NONBLOCK);
  2993.     readret = read( fileno(stdin), &ch, 1);
  2994.     fcntl(fileno(stdin), F_SETFL, f_flags);
  2995.     if (readret == -1)
  2996.       {
  2997.         if (errno != EAGAIN)
  2998.           {
  2999.         /* should crash here */
  3000.         DEBUG(1,("readchar stdin failed\n"));
  3001.           }
  3002.       }
  3003.     else if (readret != 0)
  3004.       {
  3005.         return ch;
  3006.       }
  3007.       }
  3008. #endif
  3009.       if (FD_ISSET(Client,&fds))
  3010.       receive_smb(buffer,0);
  3011.       
  3012. #ifdef CLIX
  3013.       delay++;
  3014.       if (delay > 100000)
  3015.     {
  3016.       delay = 0;
  3017.       chkpath("\\",False);
  3018.     }
  3019. #else
  3020.       chkpath("\\",False);
  3021. #endif
  3022.     }  
  3023. }
  3024.  
  3025. #if 0
  3026. /****************************************************************************
  3027. wait for keyboard activity, swallowing network packets
  3028. ****************************************************************************/
  3029. void wait_keyboard(char *buffer)
  3030. {
  3031.   fd_set fds;
  3032.   int selrtn;
  3033.   struct timeval timeout;
  3034.  
  3035.   while (1) 
  3036.     {
  3037.       extern int Client;
  3038.       FD_ZERO(&fds);
  3039.       FD_SET(Client,&fds);
  3040.       FD_SET(fileno(stdin),&fds);
  3041.  
  3042.       do 
  3043.     {
  3044.       timeout.tv_sec = 20;
  3045.       timeout.tv_usec = 0;
  3046.       selrtn = select(255,SELECT_CAST &fds,NULL,NULL,&timeout);
  3047.     }
  3048.       while(selrtn < 0 && errno == EINTR);
  3049.  
  3050.       if (FD_ISSET(fileno(stdin),&fds))
  3051.     return;
  3052.  
  3053.       if (FD_ISSET(Client,&fds))
  3054.     receive_smb(buffer,0);
  3055.  
  3056.       chkpath("\\",False);
  3057.     }
  3058.  
  3059. }
  3060. #endif
  3061.  
  3062.  
  3063. /****************************************************************************
  3064. try and register my own netbios name with a unicast
  3065. ****************************************************************************/
  3066. void register_myname(void)
  3067. {
  3068.   name_struct name;
  3069.  
  3070.   name.valid = True;
  3071.   strcpy(name.name,myname);
  3072.   strupper(name.name);
  3073.   strcpy(name.flags,"");
  3074.   name.ip = myip;
  3075.   name.ttl = 0;
  3076.   name.nb_flags = 0;
  3077.  
  3078.   register_name(&name,&dest_ip,NULL);
  3079. }
  3080.  
  3081.  
  3082. /****************************************************************************
  3083.   process commands from the client
  3084. ****************************************************************************/
  3085. void process(void )
  3086. {
  3087.   pstring line;
  3088.  
  3089.   char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3090.   char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3091.  
  3092.   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
  3093.     return;
  3094.   
  3095.   memset(OutBuffer,0,smb_size);
  3096.  
  3097. #if REGISTER
  3098.   register_myname();
  3099. #endif
  3100.  
  3101.   if (!send_login(InBuffer,OutBuffer,True))
  3102.     return;
  3103.  
  3104.   while (!feof(stdin))
  3105.     {
  3106.       char *tok;
  3107.       int i;
  3108.       BOOL found = False;
  3109.  
  3110.       memset(OutBuffer,0,smb_size);
  3111.  
  3112.       /* display a prompt */
  3113.       DEBUG(1,("smb: %s> ", CNV_LANG(cur_dir)));
  3114.  
  3115. #ifdef CLIX
  3116.       line[0] = wait_keyboard(InBuffer);
  3117.       /* this might not be such a good idea... */
  3118.       if ( line[0] == EOF)
  3119.     break;
  3120. #else
  3121.       wait_keyboard(InBuffer);
  3122. #endif
  3123.   
  3124.       /* and get a response */
  3125. #ifdef CLIX
  3126.       fgets( &line[1],999, stdin);
  3127. #else
  3128.       if (!fgets(line,1000,stdin))
  3129. #endif
  3130.     break;
  3131.  
  3132.       {
  3133.     pstring line2;
  3134.     strcpy (line2, CNV_INPUT(line));
  3135.     strcpy (line, line2);
  3136.       }
  3137.  
  3138.       /* special case - first char is ! */
  3139.       if (*line == '!')
  3140.     {
  3141.       system(line + 1);
  3142.       continue;
  3143.     }
  3144.       
  3145.       /* and get the first part of the command */
  3146.       tok = strtok(line,SEPARATORS);
  3147.       
  3148.       i = 0;
  3149.       while (commands[i].fn != NULL)
  3150.     {
  3151.       if (strequal(commands[i].name,tok))
  3152.         {
  3153.           found = True;
  3154.           commands[i].fn(InBuffer,OutBuffer);
  3155.         }
  3156.       i++;
  3157.     }
  3158.       if (!found && tok)
  3159.     DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
  3160.     }
  3161.   
  3162.   memset(OutBuffer,0,smb_size);
  3163.   send_logout(InBuffer,OutBuffer);
  3164. }
  3165.  
  3166.  
  3167. /****************************************************************************
  3168. usage on the program
  3169. ****************************************************************************/
  3170. void usage(char *pname)
  3171. {
  3172. #ifdef KANJI
  3173.   DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] [-e]\n",
  3174.        pname));
  3175. #else
  3176.   DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log]\n",pname));
  3177. #endif /* KANJI */
  3178.   DEBUG(0,("Version %s\n",VERSION));
  3179.   DEBUG(0,("\t-p port               listen on the specified port\n"));
  3180.   DEBUG(0,("\t-d debuglevel         set the debuglevel\n"));
  3181.   DEBUG(0,("\t-l log basename.      Basename for log/debug files\n"));
  3182.   DEBUG(0,("\t-n netbios name.      Use this name as my netbios name\n"));
  3183.   DEBUG(0,("\t-N                    don't ask for a password\n"));
  3184.   DEBUG(0,("\t-P                    connect to service as a printer\n"));
  3185.   DEBUG(0,("\t-L host               get a list of shares available on a host\n"));
  3186.   DEBUG(0,("\t-I dest IP            use this IP to connect to\n"));
  3187.   DEBUG(0,("\t-E                    write messages to stderr instead of stdout\n"));
  3188.   DEBUG(0,("\t-U username           set the network username\n"));
  3189. #ifdef KANJI
  3190.   DEBUG(0,("\t-e                    terminal output code to EUC\n"));
  3191. #endif /* KANJI */
  3192.   DEBUG(0,("\n"));
  3193. }
  3194.  
  3195.  
  3196.  
  3197. /****************************************************************************
  3198.   main program
  3199. ****************************************************************************/
  3200. int main(int argc,char *argv[])
  3201. {
  3202.   char *pname = argv[0];
  3203.   int port = 139;
  3204.   int opt;
  3205.   extern FILE *dbf;
  3206.   extern char *optarg;
  3207.   pstring query_host="";
  3208.  
  3209.   DEBUGLEVEL = 2;
  3210.   dbf = stdout;
  3211.  
  3212.   pid = getpid();
  3213.   uid = getuid();
  3214.   gid = getgid();
  3215.   mid = pid + 100;
  3216.   myumask = umask(0);
  3217.   umask(myumask);
  3218.  
  3219.   if (getenv("USER"))
  3220.     {
  3221.       strcpy(username,getenv("USER"));
  3222.       strupper(username);
  3223.     }
  3224.  
  3225.   if (*username == 0 && getenv("LOGNAME"))
  3226.     {
  3227.       strcpy(username,getenv("LOGNAME"));
  3228.       strupper(username);
  3229.     }
  3230.  
  3231.   if (argc < 2)
  3232.     {
  3233.       usage(pname);
  3234.       exit(0);
  3235.     }
  3236.   
  3237.   if (*argv[1] != '-')
  3238.     {
  3239.  
  3240.       strcpy(service,argv[1]);  
  3241.       argc--;
  3242.       argv++;
  3243.  
  3244.       if (count_chars(service,'\\') < 3)
  3245.     {
  3246.       usage(pname);
  3247.       printf("\n%s: Not enough '\\' characters in service\n",service);
  3248.       exit(0);
  3249.     }
  3250.  
  3251.       if (count_chars(service,'\\') > 3)
  3252.     {
  3253.       usage(pname);
  3254.       printf("\n%s: Too many '\\' characters in service\n",service);
  3255.       exit(0);
  3256.     }
  3257.   
  3258.  
  3259.       if (argc > 1 && (*argv[1] != '-'))
  3260.     {
  3261.       got_pass = True;
  3262.       strcpy(password,argv[1]);  
  3263.       memset(argv[1],'X',strlen(argv[1]));
  3264.       argc--;
  3265.       argv++;
  3266.     }
  3267.     }
  3268.  
  3269. #ifdef KANJI
  3270.   while ((opt = getopt (argc, argv, "i:Nn:d:Pp:l:hI:EeB:U:L:")) != EOF)
  3271. #else
  3272.   while ((opt = getopt (argc, argv, "i:Nn:d:Pp:l:hI:EB:U:L:")) != EOF)
  3273. #endif /* KANJI */
  3274.     switch (opt)
  3275.       {
  3276.       case 'i':
  3277.     strcpy(scope,optarg);
  3278.     break;
  3279.       case 'L':
  3280.     got_pass = True;
  3281.     strcpy(query_host,optarg);
  3282.     break;
  3283.       case 'U':
  3284.     {
  3285.       char *p;
  3286.     strcpy(username,optarg);
  3287.     if ((p=strchr(username,'%')))
  3288.       {
  3289.         *p = 0;
  3290.         strcpy(password,p+1);
  3291.         got_pass = True;
  3292.         memset(strchr(optarg,'%')+1,'X',strlen(password));
  3293.       }
  3294.     }
  3295.         
  3296.     break;
  3297.       case 'E':
  3298.     dbf = stderr;
  3299.     break;
  3300.       case 'I':
  3301.     {
  3302.       unsigned long a = interpret_addr(optarg);
  3303.       memcpy((char *)&dest_ip,(char *)&a,sizeof(a));
  3304.       have_ip = True;
  3305.     }
  3306.     break;
  3307.       case 'n':
  3308.     strcpy(myname,optarg);
  3309.     break;
  3310.       case 'N':
  3311.     got_pass = True;
  3312.     break;
  3313.       case 'P':
  3314.     connect_as_printer = True;
  3315.     break;
  3316.       case 'd':
  3317.     if (*optarg == 'A')
  3318.       DEBUGLEVEL = 10000;
  3319.     else
  3320.       DEBUGLEVEL = atoi(optarg);
  3321.     break;
  3322.       case 'l':
  3323.     sprintf(debugf,"%s.client",optarg);
  3324.     break;
  3325.       case 'p':
  3326.     port = atoi(optarg);
  3327.     break;
  3328.       case 'h':
  3329.     usage(pname);
  3330.     exit(0);
  3331.     break;
  3332. #ifdef KANJI
  3333.       case 'e':
  3334.     term_code = EUC_CODE;
  3335.     break;
  3336. #endif /* KANJI */
  3337.       default:
  3338.     usage(pname);
  3339.     exit(1);
  3340.       }
  3341.  
  3342.   if (!*query_host && !*service)
  3343.     {
  3344.       usage(pname);
  3345.       exit(1);
  3346.     }
  3347.  
  3348.  
  3349.   NeedSwap = big_endian();
  3350.   
  3351.   DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
  3352.  
  3353.   if (DEBUGLEVEL > 100)
  3354.     {
  3355.       extern FILE *login,*logout;
  3356.       pstring fname;
  3357.       sprintf(fname,"%s.in",debugf);
  3358.       login = fopen(fname,"w"); 
  3359.       if (login) chmod(fname,0600);
  3360.       sprintf(fname,"%s.out",debugf);
  3361.       logout = fopen(fname,"w");
  3362.       if (logout) chmod(fname,0600);
  3363.     }
  3364.  
  3365.   get_machine_info();
  3366.  
  3367. #if 0
  3368.   /* Read the broadcast address from the interface */
  3369.   get_broadcast(&myip,&bcast_ip,&Netmask);
  3370. #endif
  3371.  
  3372.   get_myname(*myname?NULL:myname,&myip);  
  3373.   strupper(myname);
  3374.   
  3375.   if (*query_host)
  3376.     {
  3377.       sprintf(service,"\\\\%s\\IPC$",query_host);
  3378.       strupper(service);
  3379.       connect_as_ipc = True;
  3380.       if (open_sockets(port))
  3381.     browse_host();
  3382.       close_sockets();
  3383.       return(0);
  3384.     }
  3385.  
  3386.   if (open_sockets(port))
  3387.     {
  3388.       process();
  3389.       close_sockets();
  3390.     }
  3391.   return(0);
  3392. }
  3393.  
  3394.  
  3395. /* error code stuff - put together by Merik Karman
  3396.    merik@blackadder.dsh.oz.au */
  3397.  
  3398. typedef struct
  3399. {
  3400.   char *name;
  3401.   int code;
  3402.   char *message;
  3403. } err_code_struct;
  3404.  
  3405. /* Dos Error Messages */
  3406. err_code_struct dos_msgs[] = {
  3407.   {"ERRbadfunc",1,"Invalid function."},
  3408.   {"ERRbadfile",2,"File not found."},
  3409.   {"ERRbadpath",3,"Directory invalid."},
  3410.   {"ERRnofids",4,"No file descriptors available"},
  3411.   {"ERRnoaccess",5,"Access denied."},
  3412.   {"ERRbadfid",6,"Invalid file handle."},
  3413.   {"ERRbadmcb",7,"Memory control blocks destroyed."},
  3414.   {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
  3415.   {"ERRbadmem",9,"Invalid memory block address."},
  3416.   {"ERRbadenv",10,"Invalid environment."},
  3417.   {"ERRbadformat",11,"Invalid format."},
  3418.   {"ERRbadaccess",12,"Invalid open mode."},
  3419.   {"ERRbaddata",13,"Invalid data."},
  3420.   {"ERR",14,"reserved."},
  3421.   {"ERRbaddrive",15,"Invalid drive specified."},
  3422.   {"ERRremcd",16,"A Delete Directory request attempted  to  remove  the  server's  current directory."},
  3423.   {"ERRdiffdevice",17,"Not same device."},
  3424.   {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
  3425.   {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing  FIDs  on the file."},
  3426.   {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an  invalid mode,  or an Unlock requested attempted to remove a lock held by another process."},
  3427.   {"ERRfilexists",80,"The file named in a Create Directory, Make  New  File  or  Link  request already exists."},
  3428.   {"ERRbadpipe",230,"Pipe invalid."},
  3429.   {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
  3430.   {"ERRpipeclosing",232,"Pipe close in progress."},
  3431.   {"ERRnotconnected",233,"No process on other end of pipe."},
  3432.   {"ERRmoredata",234,"There is more data to be returned."},
  3433.   {NULL,-1,NULL}};
  3434.  
  3435. /* Server Error Messages */
  3436. err_code_struct server_msgs[] = {
  3437.   {"ERRerror",1,"Non-specific error code."},
  3438.   {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
  3439.   {"ERRbadtype",3,"reserved."},
  3440.   {"ERRaccess",4,"The requester does not have  the  necessary  access  rights  within  the specified  context for the requested function. The context is defined by the TID or the UID."},
  3441.   {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
  3442.   {"ERRinvnetname",6,"Invalid network name in tree connect."},
  3443.   {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection."},
  3444.   {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
  3445.   {"ERRqtoobig",50,"Print queue full -- no space."},
  3446.   {"ERRqeof",51,"EOF on print queue dump."},
  3447.   {"ERRinvpfid",52,"Invalid print file FID."},
  3448.   {"ERRsmbcmd",64,"The server did not recognize the command received."},
  3449.   {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
  3450.   {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid  combination of values."},
  3451.   {"ERRreserved",68,"reserved."},
  3452.   {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute."},
  3453.   {"ERRreserved",70,"reserved."},
  3454.   {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
  3455.   {"ERRpaused",81,"Server is paused. (reserved for messaging)"},
  3456.   {"ERRmsgoff",82,"Not receiving messages. (reserved for messaging)."},
  3457.   {"ERRnoroom",83,"No room to buffer message. (reserved for messaging)."},
  3458.   {"ERRrmuns",87,"Too many remote user names. (reserved for messaging)."},
  3459.   {"ERRtimeout",88,"Operation timed out."},
  3460.   {"ERRnoresource",89,"No resources currently available for request."},
  3461.   {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
  3462.   {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
  3463.   {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
  3464.   {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
  3465.   {"ERRcontmpx",252,"Continue in MPX mode."},
  3466.   {"ERRreserved",253,"reserved."},
  3467.   {"ERRreserved",254,"reserved."},
  3468.   {"ERRnosupport",0xFFFF,"Function not supported."},
  3469.   {NULL,-1,NULL}};
  3470.  
  3471. /* Hard Error Messages */
  3472. err_code_struct hard_msgs[] = {
  3473.   {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
  3474.   {"ERRbadunit",20,"Unknown unit."},
  3475.   {"ERRnotready",21,"Drive not ready."},
  3476.   {"ERRbadcmd",22,"Unknown command."},
  3477.   {"ERRdata",23,"Data error (CRC)."},
  3478.   {"ERRbadreq",24,"Bad request structure length."},
  3479.   {"ERRseek",25 ,"Seek error."},
  3480.   {"ERRbadmedia",26,"Unknown media type."},
  3481.   {"ERRbadsector",27,"Sector not found."},
  3482.   {"ERRnopaper",28,"Printer out of paper."},
  3483.   {"ERRwrite",29,"Write fault."},
  3484.   {"ERRread",30,"Read fault."},
  3485.   {"ERRgeneral",31,"General failure."},
  3486.   {"ERRbadshare",32,"A open conflicts with an existing open."},
  3487.   {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
  3488.   {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
  3489.   {"ERRFCBUnavail",35,"No FCBs are available to process request."},
  3490.   {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
  3491.   {NULL,-1,NULL}};
  3492.  
  3493.  
  3494. struct
  3495. {
  3496.   int code;
  3497.   char *class;
  3498.   err_code_struct *err_msgs;
  3499. } err_classes[] = { 
  3500.   {0,"SUCCESS",NULL},
  3501.   {0x01,"ERRDOS",dos_msgs},
  3502.   {0x02,"ERRSRV",server_msgs},
  3503.   {0x03,"ERRHRD",hard_msgs},
  3504.   {0x04,"ERRXOS",NULL},
  3505.   {0xE1,"ERRRMX1",NULL},
  3506.   {0xE2,"ERRRMX2",NULL},
  3507.   {0xE3,"ERRRMX3",NULL},
  3508.   {0xFF,"ERRCMD",NULL},
  3509.   {-1,NULL,NULL}};
  3510.  
  3511.  
  3512. /****************************************************************************
  3513. return a SMB error string from a SMB buffer
  3514. ****************************************************************************/
  3515. char *smb_errstr(char *inbuf)
  3516. {
  3517.   static pstring ret;
  3518.   int class = CVAL(inbuf,smb_rcls);
  3519.   int num = SVAL(inbuf,smb_err);
  3520.   int i,j;
  3521.  
  3522.   for (i=0;err_classes[i].class;i++)
  3523.     if (err_classes[i].code == class)
  3524.       {
  3525.     if (err_classes[i].err_msgs)
  3526.       {
  3527.         err_code_struct *err = err_classes[i].err_msgs;
  3528.         for (j=0;err[j].name;j++)
  3529.           if (num == err[j].code)
  3530.         {
  3531.           if (DEBUGLEVEL > 0)
  3532.             sprintf(ret,"%s - %s (%s)",err_classes[i].class,
  3533.                 err[j].name,err[j].message);
  3534.           else
  3535.             sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
  3536.           return ret;
  3537.         }
  3538.       }
  3539.  
  3540.     sprintf(ret,"%s - %d",err_classes[i].class,num);
  3541.     return ret;
  3542.       }
  3543.   
  3544.   sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num);
  3545.   return(ret);
  3546. }
  3547.