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