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