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