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