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