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