client.c: Made sure myhostname was initialised before substitutions.
[samba.git] / source3 / client / client.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB client
5    Copyright (C) Andrew Tridgell 1994-1997
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifdef SYSLOG
23 #undef SYSLOG
24 #endif
25
26 #include "includes.h"
27
28 #ifndef REGISTER
29 #define REGISTER 0
30 #endif
31
32 pstring cur_dir = "\\";
33 pstring cd_path = "";
34 pstring service="";
35 pstring desthost="";
36 extern pstring myname;
37 extern pstring myhostname;
38 pstring password = "";
39 pstring username="";
40 pstring workgroup="";
41 char *cmdstr="";
42 BOOL got_pass = False;
43 BOOL connect_as_printer = False;
44 BOOL connect_as_ipc = False;
45 extern struct in_addr ipzero;
46
47 char cryptkey[8];
48 BOOL doencrypt=False;
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 int name_type = 0x20;
60
61 int max_protocol = PROTOCOL_NT1;
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
73 static BOOL send_trans_request(char *outbuf,int trans,
74                                char *name,int fid,int flags,
75                                char *data,char *param,uint16 *setup,
76                                int ldata,int lparam,int lsetup,
77                                int mdata,int mparam,int msetup);
78 static BOOL receive_trans_response(char *inbuf,int trans,
79                                    int *data_len,int *param_len,
80                                    char **data,char **param);
81 static int interpret_long_filename(int level,char *p,file_info *finfo);
82 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir);
83 static int interpret_short_filename(char *p,file_info *finfo);
84 static BOOL call_api(int prcnt,int drcnt,
85                      int mprcnt,int mdrcnt,
86                      int *rprcnt,int *rdrcnt,
87                      char *param,char *data,
88                      char **rparam,char **rdata);
89 static BOOL do_this_one(file_info *finfo);
90
91 /* clitar bits insert */
92 extern int blocksize;
93 extern BOOL tar_inc;
94 extern BOOL tar_reset;
95 /* clitar bits end */
96  
97
98 int cnum = 0;
99 int pid = 0;
100 int gid = 0;
101 int uid = 0;
102 int mid = 0;
103 int myumask = 0755;
104
105 int max_xmit = BUFFER_SIZE;
106
107 extern pstring scope;
108
109 BOOL prompt = True;
110
111 int printmode = 1;
112
113 BOOL recurse = False;
114 BOOL lowercase = False;
115
116 BOOL have_ip = False;
117
118 struct in_addr dest_ip;
119
120 #define SEPARATORS " \t\n\r"
121
122 BOOL abort_mget = True;
123
124 extern int Protocol;
125
126 BOOL readbraw_supported = False;
127 BOOL writebraw_supported = False;
128
129 pstring fileselection = "";
130
131 extern file_info def_finfo;
132
133 /* timing globals */
134 int get_total_size = 0;
135 int get_total_time_ms = 0;
136 int put_total_size = 0;
137 int put_total_time_ms = 0;
138
139 /* totals globals */
140 int dir_total = 0;
141
142 extern int Client;
143
144 #define USENMB
145
146 #ifdef KANJI
147 extern int coding_system;
148 #define CNV_LANG(s) (coding_system == DOSV_CODE?s:dos_to_unix(s, False))
149 #define CNV_INPUT(s) (coding_system == DOSV_CODE?s:unix_to_dos(s, True))
150 static BOOL
151 setup_term_code (char *code)
152 {
153     int new;
154     new = interpret_coding_system (code, UNKNOWN_CODE);
155     if (new != UNKNOWN_CODE) {
156         coding_system = new;
157         return True;
158     }
159     return False;
160 }
161 #else
162 #define CNV_LANG(s) dos2unix_format(s,False)
163 #define CNV_INPUT(s) unix2dos_format(s,True)
164 #endif
165
166 /****************************************************************************
167 setup basics in a outgoing packet
168 ****************************************************************************/
169 void setup_pkt(char *outbuf)
170 {
171   SSVAL(outbuf,smb_pid,pid);
172   SSVAL(outbuf,smb_uid,uid);
173   SSVAL(outbuf,smb_mid,mid);
174   if (Protocol > PROTOCOL_COREPLUS)
175     {
176       SCVAL(outbuf,smb_flg,0x8);
177       SSVAL(outbuf,smb_flg2,0x1);
178     }
179 }
180
181 /****************************************************************************
182 write to a local file with CR/LF->LF translation if appropriate. return the 
183 number taken from the buffer. This may not equal the number written.
184 ****************************************************************************/
185 static int writefile(int f, char *b, int n)
186 {
187   int i;
188
189   if (!translation)
190     return(write(f,b,n));
191   
192   i = 0;
193   while (i < n)
194     {
195       if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
196         {
197           b++;i++;
198         }
199       if (write(f, b, 1) != 1)
200         {
201           break;
202         }
203       b++;
204       i++;
205     }
206   
207   return(i);
208 }
209
210 /****************************************************************************
211   read from a file with LF->CR/LF translation if appropriate. return the 
212   number read. read approx n bytes.
213 ****************************************************************************/
214 static int readfile(char *b, int size, int n, FILE *f)
215 {
216   int i;
217   int c;
218
219   if (!translation || (size != 1))
220     return(fread(b,size,n,f));
221   
222   i = 0;
223   while (i < n)
224     {
225       if ((c = getc(f)) == EOF)
226         {
227           break;
228         }
229       
230       if (c == '\n') /* change all LFs to CR/LF */
231         {
232           b[i++] = '\r';
233           n++;
234         }
235       
236       if(i < n)
237         b[i++] = c;
238     }
239   
240   return(i);
241 }
242  
243
244 /****************************************************************************
245 read from a file with print translation. return the number read. read approx n
246 bytes.
247 ****************************************************************************/
248 static int printread(FILE *f,char *b,int n)
249 {
250   int i;
251
252   i = readfile(b,1, n-1,f);
253 #if FORMFEED
254   if (feof(f) && i>0)
255     b[i++] = '\014';
256 #endif
257
258   return(i);
259 }
260
261 /****************************************************************************
262 check for existance of a dir
263 ****************************************************************************/
264 static BOOL chkpath(char *path,BOOL report)
265 {
266   fstring path2;
267   pstring inbuf,outbuf;
268   char *p;
269
270   strcpy(path2,path);
271   trim_string(path2,NULL,"\\");
272   if (!*path2) *path2 = '\\';
273
274   bzero(outbuf,smb_size);
275   set_message(outbuf,0,4 + strlen(path2),True);
276   SCVAL(outbuf,smb_com,SMBchkpth);
277   SSVAL(outbuf,smb_tid,cnum);
278   setup_pkt(outbuf);
279
280   p = smb_buf(outbuf);
281   *p++ = 4;
282   strcpy(p,path2);
283
284   send_smb(Client,outbuf);
285   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
286
287   if (report && CVAL(inbuf,smb_rcls) != 0)
288     DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
289
290   return(CVAL(inbuf,smb_rcls) == 0);
291 }
292
293
294 /****************************************************************************
295 send a message
296 ****************************************************************************/
297 static void send_message(char *inbuf,char *outbuf)
298 {
299   int total_len = 0;
300
301   char *p;
302   int grp_id;
303
304   /* send a SMBsendstrt command */
305   bzero(outbuf,smb_size);
306   set_message(outbuf,0,0,True);
307   CVAL(outbuf,smb_com) = SMBsendstrt;
308   SSVAL(outbuf,smb_tid,cnum);
309
310   p = smb_buf(outbuf);
311   *p++ = 4;
312   strcpy(p,username);
313   p = skip_string(p,1);
314   *p++ = 4;
315   strcpy(p,desthost);
316   p = skip_string(p,1);
317
318   set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
319
320   send_smb(Client,outbuf);
321   
322
323   if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
324     {
325       printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
326       return;
327     }
328
329   grp_id = SVAL(inbuf,smb_vwv0);
330
331   printf("Connected. Type your message, ending it with a Control-D\n");
332
333   while (!feof(stdin) && total_len < 1600)
334     {
335       int maxlen = MIN(1600 - total_len,127);
336       pstring msg;
337       int l=0;
338       int c;
339
340       bzero(msg,smb_size);
341
342       for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
343         {
344           if (c == '\n')
345             msg[l++] = '\r';
346           msg[l] = c;   
347         }
348
349       CVAL(outbuf,smb_com) = SMBsendtxt;
350
351       set_message(outbuf,1,l+3,True);
352
353       SSVAL(outbuf,smb_vwv0,grp_id);
354
355       p = smb_buf(outbuf);
356       *p = 1;
357       SSVAL(p,1,l);
358       memcpy(p+3,msg,l);
359
360       send_smb(Client,outbuf);
361       
362
363       if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
364         {
365           printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
366           return;
367         }      
368
369       total_len += l;
370     }
371
372   if (total_len >= 1600)
373     printf("the message was truncated to 1600 bytes ");
374   else
375     printf("sent %d bytes ",total_len);
376
377   printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
378
379   CVAL(outbuf,smb_com) = SMBsendend;
380   set_message(outbuf,1,0,False);
381   SSVAL(outbuf,smb_vwv0,grp_id);
382
383   send_smb(Client,outbuf);
384   
385
386   if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
387     {
388       printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
389       return;
390     }      
391 }
392
393
394
395 /****************************************************************************
396 check the space on a device
397 ****************************************************************************/
398 static void do_dskattr(void)
399 {
400   pstring inbuf,outbuf;
401
402   bzero(outbuf,smb_size);
403   set_message(outbuf,0,0,True);
404   CVAL(outbuf,smb_com) = SMBdskattr;
405   SSVAL(outbuf,smb_tid,cnum);
406   setup_pkt(outbuf);
407
408   send_smb(Client,outbuf);
409   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
410
411   if (CVAL(inbuf,smb_rcls) != 0) 
412     DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));      
413
414   DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
415         SVAL(inbuf,smb_vwv0),
416         SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
417         SVAL(inbuf,smb_vwv3)));
418 }
419
420 /****************************************************************************
421 show cd/pwd
422 ****************************************************************************/
423 static void cmd_pwd(void)
424 {
425   DEBUG(0,("Current directory is %s",CNV_LANG(service)));
426   DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
427 }
428
429
430 /****************************************************************************
431 change directory - inner section
432 ****************************************************************************/
433 static void do_cd(char *newdir)
434 {
435   char *p = newdir;
436   pstring saved_dir;
437   pstring dname;
438       
439   /* Save the current directory in case the
440      new directory is invalid */
441   strcpy(saved_dir, cur_dir);
442   if (*p == '\\')
443     strcpy(cur_dir,p);
444   else
445     strcat(cur_dir,p);
446   if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
447     strcat(cur_dir, "\\");
448   }
449   dos_clean_name(cur_dir);
450   strcpy(dname,cur_dir);
451   strcat(cur_dir,"\\");
452   dos_clean_name(cur_dir);
453
454   if (!strequal(cur_dir,"\\"))
455     if (!chkpath(dname,True))
456       strcpy(cur_dir,saved_dir);
457
458   strcpy(cd_path,cur_dir);
459 }
460
461 /****************************************************************************
462 change directory
463 ****************************************************************************/
464 static void cmd_cd(char *inbuf,char *outbuf)
465 {
466   fstring buf;
467
468   if (next_token(NULL,buf,NULL))
469     do_cd(buf);
470   else
471     DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
472 }
473
474
475 /****************************************************************************
476   display info about a file
477   ****************************************************************************/
478 static void display_finfo(file_info *finfo)
479 {
480   if (do_this_one(finfo)) {
481     time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
482     DEBUG(0,("  %-30s%7.7s%10d  %s",
483            CNV_LANG(finfo->name),
484            attrib_string(finfo->mode),
485            finfo->size,
486            asctime(LocalTime(&t))));
487     dir_total += finfo->size;
488   }
489 }
490
491
492 /****************************************************************************
493   do a directory listing, calling fn on each file found. Use the TRANSACT2
494   call for long filenames
495   ****************************************************************************/
496 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
497 {
498   int max_matches = 512;
499   int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
500   char *p;
501   pstring mask;
502   file_info finfo;
503   int i;
504   char *dirlist = NULL;
505   int dirlist_len = 0;
506   int total_received = 0;
507   BOOL First = True;
508   char *resp_data=NULL;
509   char *resp_param=NULL;
510   int resp_data_len = 0;
511   int resp_param_len=0;
512
513   int ff_resume_key = 0;
514   int ff_searchcount=0;
515   int ff_eos=0;
516   int ff_lastname=0;
517   int ff_dir_handle=0;
518   int loop_count = 0;
519
520   uint16 setup;
521   pstring param;
522
523   strcpy(mask,Mask);
524
525   while (ff_eos == 0)
526     {
527       loop_count++;
528       if (loop_count > 200)
529         {
530           DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
531           break;
532         }
533
534       if (First)
535         {
536           setup = TRANSACT2_FINDFIRST;
537           SSVAL(param,0,attribute); /* attribute */
538           SSVAL(param,2,max_matches); /* max count */
539           SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
540           SSVAL(param,6,info_level); 
541           SIVAL(param,8,0);
542           strcpy(param+12,mask);
543         }
544       else
545         {
546           setup = TRANSACT2_FINDNEXT;
547           SSVAL(param,0,ff_dir_handle);
548           SSVAL(param,2,max_matches); /* max count */
549           SSVAL(param,4,info_level); 
550           SIVAL(param,6,ff_resume_key); /* ff_resume_key */
551           SSVAL(param,10,8+4+2);        /* resume required + close on end + continue */
552           strcpy(param+12,mask);
553
554           DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
555                    ff_dir_handle,ff_resume_key,ff_lastname,mask));
556         }
557       /* ??? original code added 1 pad byte after param */
558
559       send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
560                          NULL,param,&setup,
561                          0,12+strlen(mask)+1,1,
562                          BUFFER_SIZE,10,0);
563
564       if (!receive_trans_response(inbuf,SMBtrans2,
565                               &resp_data_len,&resp_param_len,
566                                   &resp_data,&resp_param))
567         {
568           DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
569           break;
570         }
571
572       /* parse out some important return info */
573       p = resp_param;
574       if (First)
575         {
576           ff_dir_handle = SVAL(p,0);
577           ff_searchcount = SVAL(p,2);
578           ff_eos = SVAL(p,4);
579           ff_lastname = SVAL(p,8);
580         }
581       else
582         {
583           ff_searchcount = SVAL(p,0);
584           ff_eos = SVAL(p,2);
585           ff_lastname = SVAL(p,6);
586         }
587
588       if (ff_searchcount == 0) 
589         break;
590
591       /* point to the data bytes */
592       p = resp_data;
593
594       /* we might need the lastname for continuations */
595       if (ff_lastname > 0)
596         {
597           switch(info_level)
598             {
599             case 260:
600               ff_resume_key =0;
601               StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
602               /* strcpy(mask,p+ff_lastname+94); */
603               break;
604             case 1:
605               strcpy(mask,p + ff_lastname + 1);
606               ff_resume_key = 0;
607               break;
608             }
609         }
610       else
611         strcpy(mask,"");
612   
613       /* and add them to the dirlist pool */
614       dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
615
616       if (!dirlist)
617         {
618           DEBUG(0,("Failed to expand dirlist\n"));
619           break;
620         }
621
622       /* put in a length for the last entry, to ensure we can chain entries 
623          into the next packet */
624       {
625         char *p2;
626         for (p2=p,i=0;i<(ff_searchcount-1);i++)
627           p2 += interpret_long_filename(info_level,p2,NULL);
628         SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
629       }
630
631       /* grab the data for later use */
632       memcpy(dirlist+dirlist_len,p,resp_data_len);
633       dirlist_len += resp_data_len;
634
635       total_received += ff_searchcount;
636
637       if (resp_data) free(resp_data); resp_data = NULL;
638       if (resp_param) free(resp_param); resp_param = NULL;
639
640       DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
641                ff_searchcount,ff_eos,ff_resume_key));
642
643       First = False;
644     }
645
646   if (!fn)
647     for (p=dirlist,i=0;i<total_received;i++)
648       {
649         p += interpret_long_filename(info_level,p,&finfo);
650         display_finfo(&finfo);
651       }
652
653   for (p=dirlist,i=0;i<total_received;i++)
654     {
655       p += interpret_long_filename(info_level,p,&finfo);
656       dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
657     }
658
659   /* free up the dirlist buffer */
660   if (dirlist) free(dirlist);
661   return(total_received);
662 }
663
664
665 /****************************************************************************
666   do a directory listing, calling fn on each file found
667   ****************************************************************************/
668 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
669 {
670   char *p;
671   int received = 0;
672   BOOL first = True;
673   char status[21];
674   int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
675   int num_received = 0;
676   int i;
677   char *dirlist = NULL;
678   pstring mask;
679   file_info finfo;
680
681   finfo = def_finfo;
682
683   bzero(status,21);
684
685   strcpy(mask,Mask);
686   
687   while (1)
688     {
689       bzero(outbuf,smb_size);
690       if (first)        
691         set_message(outbuf,2,5 + strlen(mask),True);
692       else
693         set_message(outbuf,2,5 + 21,True);
694
695 #if FFIRST
696       if (Protocol >= PROTOCOL_LANMAN1)
697         CVAL(outbuf,smb_com) = SMBffirst;
698       else
699 #endif
700         CVAL(outbuf,smb_com) = SMBsearch;
701
702       SSVAL(outbuf,smb_tid,cnum);
703       setup_pkt(outbuf);
704
705       SSVAL(outbuf,smb_vwv0,num_asked);
706       SSVAL(outbuf,smb_vwv1,attribute);
707   
708       p = smb_buf(outbuf);
709       *p++ = 4;
710       
711       if (first)
712         strcpy(p,mask);
713       else
714         strcpy(p,"");
715       p += strlen(p) + 1;
716       
717       *p++ = 5;
718       if (first)
719         SSVAL(p,0,0);
720       else
721         {
722           SSVAL(p,0,21);
723           p += 2;
724           memcpy(p,status,21);
725         }
726
727       send_smb(Client,outbuf);
728       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
729
730       received = SVAL(inbuf,smb_vwv0);
731
732       DEBUG(5,("dir received %d\n",received));
733
734       DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
735
736       if (received <= 0) break;
737
738       first = False;
739
740       dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
741
742       if (!dirlist) 
743         return 0;
744
745       p = smb_buf(inbuf) + 3;
746
747       memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
748              p,received*DIR_STRUCT_SIZE);
749
750       memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
751
752       num_received += received;
753
754       if (CVAL(inbuf,smb_rcls) != 0) break;
755     }
756
757 #if FFIRST
758   if (!first && Protocol >= PROTOCOL_LANMAN1)
759     {
760       bzero(outbuf,smb_size);
761       CVAL(outbuf,smb_com) = SMBfclose;
762
763       SSVAL(outbuf,smb_tid,cnum);
764       setup_pkt(outbuf);
765
766       p = smb_buf(outbuf);
767       *p++ = 4;
768       
769       strcpy(p,"");
770       p += strlen(p) + 1;
771       
772       *p++ = 5;
773       SSVAL(p,0,21);
774       p += 2;
775       memcpy(p,status,21);
776
777       send_smb(Client,outbuf);
778       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
779
780       if (CVAL(inbuf,smb_rcls) != 0) 
781         DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));      
782     }
783 #endif
784
785   if (!fn)
786     for (p=dirlist,i=0;i<num_received;i++)
787       {
788         p += interpret_short_filename(p,&finfo);
789         display_finfo(&finfo);
790       }
791
792   for (p=dirlist,i=0;i<num_received;i++)
793     {
794       p += interpret_short_filename(p,&finfo);
795       dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
796     }
797
798   if (dirlist) free(dirlist);
799   return(num_received);
800 }
801
802
803
804 /****************************************************************************
805   do a directory listing, calling fn on each file found
806   ****************************************************************************/
807 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
808 {
809   DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
810   if (Protocol >= PROTOCOL_LANMAN2)
811     {
812       if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
813         return;
814     }
815
816   expand_mask(Mask,False);
817   do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
818   return;
819 }
820
821 /*******************************************************************
822   decide if a file should be operated on
823   ********************************************************************/
824 static BOOL do_this_one(file_info *finfo)
825 {
826   if (finfo->mode & aDIR) return(True);
827
828   if (newer_than && finfo->mtime < newer_than)
829     return(False);
830
831   if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
832     return(False);
833
834   return(True);
835 }
836
837
838 /*****************************************************************************
839  Convert a character pointer in a call_api() response to a form we can use.
840  This function contains code to prevent core dumps if the server returns 
841  invalid data.
842 *****************************************************************************/
843 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
844 {
845 if( datap == 0 )                /* turn NULL pointers */
846   {                             /* into zero length strings */
847   return "";
848   }
849 else
850   {
851   unsigned int offset = datap - converter;
852
853   if( offset >= rdrcnt )
854     {
855       DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
856     return "<ERROR>";
857     }
858   else
859     {
860     return &rdata[offset];
861     }
862   }
863 }
864
865 /****************************************************************************
866 interpret a short filename structure
867 The length of the structure is returned
868 ****************************************************************************/
869 static int interpret_short_filename(char *p,file_info *finfo)
870 {
871   finfo->mode = CVAL(p,21);
872
873   /* this date is converted to GMT by make_unix_date */
874   finfo->ctime = make_unix_date(p+22);
875   finfo->mtime = finfo->atime = finfo->ctime;
876   finfo->size = IVAL(p,26);
877   strcpy(finfo->name,p+30);
878   
879   return(DIR_STRUCT_SIZE);
880 }
881
882 /****************************************************************************
883 interpret a long filename structure - this is mostly guesses at the moment
884 The length of the structure is returned
885 The structure of a long filename depends on the info level. 260 is used
886 by NT and 2 is used by OS/2
887 ****************************************************************************/
888 static int interpret_long_filename(int level,char *p,file_info *finfo)
889 {
890   if (finfo)
891     memcpy(finfo,&def_finfo,sizeof(*finfo));
892
893   switch (level)
894     {
895     case 1: /* OS/2 understands this */
896       if (finfo)
897         {
898           /* these dates are converted to GMT by make_unix_date */
899           finfo->ctime = make_unix_date2(p+4);
900           finfo->atime = make_unix_date2(p+8);
901           finfo->mtime = make_unix_date2(p+12);
902           finfo->size = IVAL(p,16);
903           finfo->mode = CVAL(p,24);
904           strcpy(finfo->name,p+27);
905         }
906       return(28 + CVAL(p,26));
907
908     case 2: /* this is what OS/2 uses mostly */
909       if (finfo)
910         {
911           /* these dates are converted to GMT by make_unix_date */
912           finfo->ctime = make_unix_date2(p+4);
913           finfo->atime = make_unix_date2(p+8);
914           finfo->mtime = make_unix_date2(p+12);
915           finfo->size = IVAL(p,16);
916           finfo->mode = CVAL(p,24);
917           strcpy(finfo->name,p+31);
918         }
919       return(32 + CVAL(p,30));
920
921       /* levels 3 and 4 are untested */
922     case 3:
923       if (finfo)
924         {
925           /* these dates are probably like the other ones */
926           finfo->ctime = make_unix_date2(p+8);
927           finfo->atime = make_unix_date2(p+12);
928           finfo->mtime = make_unix_date2(p+16);
929           finfo->size = IVAL(p,20);
930           finfo->mode = CVAL(p,28);
931           strcpy(finfo->name,p+33);
932         }
933       return(SVAL(p,4)+4);
934
935     case 4:
936       if (finfo)
937         {
938           /* these dates are probably like the other ones */
939           finfo->ctime = make_unix_date2(p+8);
940           finfo->atime = make_unix_date2(p+12);
941           finfo->mtime = make_unix_date2(p+16);
942           finfo->size = IVAL(p,20);
943           finfo->mode = CVAL(p,28);
944           strcpy(finfo->name,p+37);
945         }
946       return(SVAL(p,4)+4);
947
948     case 260: /* NT uses this, but also accepts 2 */
949       if (finfo)
950         {
951           int ret = SVAL(p,0);
952           int namelen;
953           p += 4; /* next entry offset */
954           p += 4; /* fileindex */
955
956           /* these dates appear to arrive in a weird way. It seems to
957              be localtime plus the serverzone given in the initial
958              connect. This is GMT when DST is not in effect and one
959              hour from GMT otherwise. Can this really be right??
960
961              I suppose this could be called kludge-GMT. Is is the GMT
962              you get by using the current DST setting on a different
963              localtime. It will be cheap to calculate, I suppose, as
964              no DST tables will be needed */
965
966           finfo->ctime = interpret_long_date(p); p += 8;
967           finfo->atime = interpret_long_date(p); p += 8;
968           finfo->mtime = interpret_long_date(p); p += 8; p += 8;
969           finfo->size = IVAL(p,0); p += 8;
970           p += 8; /* alloc size */
971           finfo->mode = CVAL(p,0); p += 4;
972           namelen = IVAL(p,0); p += 4;
973           p += 4; /* EA size */
974           p += 2; /* short name len? */
975           p += 24; /* short name? */      
976           StrnCpy(finfo->name,p,namelen);
977           return(ret);
978         }
979       return(SVAL(p,0));
980     }
981
982   DEBUG(1,("Unknown long filename format %d\n",level));
983   return(SVAL(p,0));
984 }
985
986
987
988
989 /****************************************************************************
990   act on the files in a dir listing
991   ****************************************************************************/
992 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
993 {
994
995   if (!((finfo->mode & aDIR) == 0 && *fileselection && 
996         !mask_match(finfo->name,fileselection,False,False)) &&
997       !(recurse_dir && (strequal(finfo->name,".") || 
998                         strequal(finfo->name,".."))))
999     {
1000       if (recurse_dir && (finfo->mode & aDIR))
1001         {
1002           pstring mask2;
1003           pstring sav_dir;
1004           strcpy(sav_dir,cur_dir);
1005           strcat(cur_dir,finfo->name);
1006           strcat(cur_dir,"\\");
1007           strcpy(mask2,cur_dir);
1008
1009           if (!fn)
1010             DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1011
1012           strcat(mask2,"*");
1013
1014           if (longdir)
1015             do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);      
1016           else
1017             do_dir(inbuf,outbuf,mask2,attribute,fn,True);
1018
1019           strcpy(cur_dir,sav_dir);
1020         }
1021       else
1022         {
1023           if (fn && do_this_one(finfo))
1024             fn(finfo);
1025         }
1026     }
1027 }
1028
1029
1030 /****************************************************************************
1031   receive a SMB trans or trans2 response allocating the necessary memory
1032   ****************************************************************************/
1033 static BOOL receive_trans_response(char *inbuf,int trans,
1034                                    int *data_len,int *param_len,
1035                                    char **data,char **param)
1036 {
1037   int total_data=0;
1038   int total_param=0;
1039   int this_data,this_param;
1040
1041   *data_len = *param_len = 0;
1042
1043   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1044   show_msg(inbuf);
1045
1046   /* sanity check */
1047   if (CVAL(inbuf,smb_com) != trans)
1048     {
1049       DEBUG(0,("Expected %s response, got command 0x%02x\n",
1050                trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
1051       return(False);
1052     }
1053   if (CVAL(inbuf,smb_rcls) != 0)
1054     return(False);
1055
1056   /* parse out the lengths */
1057   total_data = SVAL(inbuf,smb_tdrcnt);
1058   total_param = SVAL(inbuf,smb_tprcnt);
1059
1060   /* allocate it */
1061   *data = Realloc(*data,total_data);
1062   *param = Realloc(*param,total_param);
1063
1064   while (1)
1065     {
1066       this_data = SVAL(inbuf,smb_drcnt);
1067       this_param = SVAL(inbuf,smb_prcnt);
1068       if (this_data)
1069         memcpy(*data + SVAL(inbuf,smb_drdisp),
1070                smb_base(inbuf) + SVAL(inbuf,smb_droff),
1071                this_data);
1072       if (this_param)
1073         memcpy(*param + SVAL(inbuf,smb_prdisp),
1074                smb_base(inbuf) + SVAL(inbuf,smb_proff),
1075                this_param);
1076       *data_len += this_data;
1077       *param_len += this_param;
1078
1079       /* parse out the total lengths again - they can shrink! */
1080       total_data = SVAL(inbuf,smb_tdrcnt);
1081       total_param = SVAL(inbuf,smb_tprcnt);
1082
1083       if (total_data <= *data_len && total_param <= *param_len)
1084         break;
1085
1086       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1087       show_msg(inbuf);
1088
1089       /* sanity check */
1090       if (CVAL(inbuf,smb_com) != trans)
1091         {
1092           DEBUG(0,("Expected %s response, got command 0x%02x\n",
1093                    trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
1094           return(False);
1095         }
1096       if (CVAL(inbuf,smb_rcls) != 0)
1097           return(False);
1098     }
1099   
1100   return(True);
1101 }
1102
1103
1104 /****************************************************************************
1105   get a directory listing
1106   ****************************************************************************/
1107 static void cmd_dir(char *inbuf,char *outbuf)
1108 {
1109   int attribute = aDIR | aSYSTEM | aHIDDEN;
1110   pstring mask;
1111   fstring buf;
1112   char *p=buf;
1113
1114   dir_total = 0;
1115   strcpy(mask,cur_dir);
1116   if(mask[strlen(mask)-1]!='\\')
1117     strcat(mask,"\\");
1118
1119   if (next_token(NULL,buf,NULL))
1120     {
1121       if (*p == '\\')
1122         strcpy(mask,p);
1123       else
1124         strcat(mask,p);
1125     }
1126   else {
1127     strcat(mask,"*");
1128   }
1129
1130   do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1131
1132   do_dskattr();
1133
1134   DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1135 }
1136
1137
1138
1139 /****************************************************************************
1140   get a file from rname to lname
1141   ****************************************************************************/
1142 static void do_get(char *rname,char *lname,file_info *finfo1)
1143 {  
1144   int handle=0,fnum;
1145   uint32 nread=0;
1146   char *p;
1147   BOOL newhandle = False;
1148   char *inbuf,*outbuf;
1149   file_info finfo;
1150   BOOL close_done = False;
1151   BOOL ignore_close_error = False;
1152   char *dataptr=NULL;
1153   int datalen=0;
1154
1155   struct timeval tp_start;
1156   GetTimeOfDay(&tp_start);
1157
1158   if (finfo1) 
1159     finfo = *finfo1;
1160   else
1161     finfo = def_finfo;
1162
1163   if (lowercase)
1164     strlower(lname);
1165
1166
1167   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1168   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1169
1170   if (!inbuf || !outbuf)
1171     {
1172       DEBUG(0,("out of memory\n"));
1173       return;
1174     }
1175
1176   bzero(outbuf,smb_size);
1177   set_message(outbuf,15,1 + strlen(rname),True);
1178
1179   CVAL(outbuf,smb_com) = SMBopenX;
1180   SSVAL(outbuf,smb_tid,cnum);
1181   setup_pkt(outbuf);
1182
1183   SSVAL(outbuf,smb_vwv0,0xFF);
1184   SSVAL(outbuf,smb_vwv2,1);
1185   SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1186   SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1187   SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1188   SSVAL(outbuf,smb_vwv8,1);
1189   
1190   p = smb_buf(outbuf);
1191   strcpy(p,rname);
1192   p = skip_string(p,1);
1193
1194   /* do a chained openX with a readX? */
1195 #if 1
1196   if (finfo.size > 0)
1197     {
1198       DEBUG(3,("Chaining readX wth openX\n"));
1199       SSVAL(outbuf,smb_vwv0,SMBreadX);
1200       SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1201       bzero(p,200);
1202       p -= smb_wct;
1203       SSVAL(p,smb_wct,10);
1204       SSVAL(p,smb_vwv0,0xFF);
1205       SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1206       SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1207       smb_setlen(outbuf,smb_len(outbuf)+11*2+1);  
1208     }
1209 #endif
1210
1211   if(!strcmp(lname,"-"))
1212     handle = fileno(stdout);
1213   else 
1214     {
1215       handle = creat(lname,0644);
1216       newhandle = True;
1217     }
1218   if (handle < 0)
1219     {
1220       DEBUG(0,("Error opening local file %s\n",lname));
1221       free(inbuf);free(outbuf);
1222       return;
1223     }
1224
1225   send_smb(Client,outbuf);
1226   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1227
1228   if (CVAL(inbuf,smb_rcls) != 0)
1229     {
1230       if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1231           SVAL(inbuf,smb_err) == ERRnoresource &&
1232           reopen_connection(inbuf,outbuf))
1233         {
1234           do_get(rname,lname,finfo1);
1235           return;
1236         }
1237       DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1238       if(newhandle)
1239         close(handle);
1240       free(inbuf);free(outbuf);
1241       return;
1242     }
1243
1244   strcpy(finfo.name,rname);
1245
1246   if (!finfo1)
1247     {
1248       finfo.mode = SVAL(inbuf,smb_vwv3);
1249       /* these times arrive as LOCAL time, using the DST offset 
1250          corresponding to that time, we convert them to GMT */
1251       finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1252       finfo.atime = finfo.ctime = finfo.mtime;
1253       finfo.size = IVAL(inbuf,smb_vwv6);
1254     }
1255
1256   DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1257
1258   fnum = SVAL(inbuf,smb_vwv2);
1259
1260   /* we might have got some data from a chained readX */
1261   if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1262     {
1263       p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1264       datalen = SVAL(p,smb_vwv5);
1265       dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1266     }
1267   else
1268     {
1269       dataptr = NULL;
1270       datalen = 0;
1271     }
1272
1273
1274   DEBUG(2,("getting file %s of size %d bytes as %s ",
1275            CNV_LANG(finfo.name),
1276            finfo.size,
1277            lname));
1278
1279   while (nread < finfo.size && !close_done)
1280     {
1281       int method = -1;
1282       static BOOL can_chain_close = True;
1283
1284       p=NULL;
1285       
1286       DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1287
1288       /* 3 possible read types. readbraw if a large block is required.
1289          readX + close if not much left and read if neither is supported */
1290
1291       /* we might have already read some data from a chained readX */
1292       if (dataptr && datalen>0)
1293         method=3;
1294
1295       /* if we can finish now then readX+close */
1296       if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) && 
1297           ((finfo.size - nread) < 
1298            (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1299         method = 0;
1300
1301       /* if we support readraw then use that */
1302       if (method<0 && readbraw_supported)
1303         method = 1;
1304
1305       /* if we can then use readX */
1306       if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1307         method = 2;
1308
1309       switch (method)
1310         {
1311           /* use readX */
1312         case 0:
1313         case 2:
1314           if (method == 0)
1315             close_done = True;
1316             
1317           /* use readX + close */
1318           bzero(outbuf,smb_size);
1319           set_message(outbuf,10,0,True);
1320           CVAL(outbuf,smb_com) = SMBreadX;
1321           SSVAL(outbuf,smb_tid,cnum);
1322           setup_pkt(outbuf);
1323           
1324           if (close_done)
1325             {
1326               CVAL(outbuf,smb_vwv0) = SMBclose;
1327               SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1328             }
1329           else
1330             CVAL(outbuf,smb_vwv0) = 0xFF;             
1331           
1332           SSVAL(outbuf,smb_vwv2,fnum);
1333           SIVAL(outbuf,smb_vwv3,nread);
1334           SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1335           SSVAL(outbuf,smb_vwv6,0);
1336           SIVAL(outbuf,smb_vwv7,0);
1337           SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1338           
1339           if (close_done)
1340             {
1341               p = smb_buf(outbuf);
1342               bzero(p,9);
1343               
1344               CVAL(p,0) = 3;
1345               SSVAL(p,1,fnum);
1346               SIVALS(p,3,-1);
1347               
1348               /* now set the total packet length */
1349               smb_setlen(outbuf,smb_len(outbuf)+9);
1350             }
1351           
1352           send_smb(Client,outbuf);
1353           receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1354           
1355           if (CVAL(inbuf,smb_rcls) != 0)
1356             {
1357               DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1358               break;
1359             }
1360           
1361           if (close_done &&
1362               SVAL(inbuf,smb_vwv0) != SMBclose)
1363             {
1364               /* NOTE: WfWg sometimes just ignores the chained
1365                  command! This seems to break the spec? */
1366               DEBUG(3,("Rejected chained close?\n"));
1367               close_done = False;
1368               can_chain_close = False;
1369               ignore_close_error = True;
1370             }
1371           
1372           datalen = SVAL(inbuf,smb_vwv5);
1373           dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1374           break;
1375
1376           /* use readbraw */
1377         case 1:
1378           {
1379             static int readbraw_size = BUFFER_SIZE;
1380           
1381             extern int Client;
1382             bzero(outbuf,smb_size);
1383             set_message(outbuf,8,0,True);
1384             CVAL(outbuf,smb_com) = SMBreadbraw;
1385             SSVAL(outbuf,smb_tid,cnum);
1386             setup_pkt(outbuf);
1387             SSVAL(outbuf,smb_vwv0,fnum);
1388             SIVAL(outbuf,smb_vwv1,nread);
1389             SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1390             SSVAL(outbuf,smb_vwv4,0);
1391             SIVALS(outbuf,smb_vwv5,-1);
1392             send_smb(Client,outbuf);
1393
1394             /* Now read the raw data into the buffer and write it */      
1395             if(read_smb_length(Client,inbuf,0) == -1) {
1396               DEBUG(0,("Failed to read length in readbraw\n"));     
1397               exit(1);
1398             }
1399             
1400             /* Even though this is not an smb message, smb_len
1401                returns the generic length of an smb message */
1402             datalen = smb_len(inbuf);
1403
1404             if (datalen == 0)
1405               {
1406                 /* we got a readbraw error */
1407                 DEBUG(4,("readbraw error - reducing size\n"));
1408                 readbraw_size = (readbraw_size * 9) / 10;
1409                 
1410                 if (readbraw_size < max_xmit)
1411                   {
1412                     DEBUG(0,("disabling readbraw\n"));
1413                     readbraw_supported = False;
1414                   }
1415                 
1416                 dataptr=NULL;
1417                 continue;
1418               }
1419
1420             if(read_data(Client,inbuf,datalen) != datalen) {
1421               DEBUG(0,("Failed to read data in readbraw\n"));
1422               exit(1);
1423             }
1424             dataptr = inbuf;
1425           }
1426           break;
1427
1428         case 3:
1429           /* we've already read some data with a chained readX */
1430           break;
1431
1432         default:
1433           /* use plain read */
1434           bzero(outbuf,smb_size);
1435           set_message(outbuf,5,0,True);
1436           CVAL(outbuf,smb_com) = SMBread;
1437           SSVAL(outbuf,smb_tid,cnum);
1438           setup_pkt(outbuf);
1439
1440           SSVAL(outbuf,smb_vwv0,fnum);
1441           SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1442           SIVAL(outbuf,smb_vwv2,nread);
1443           SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1444
1445           send_smb(Client,outbuf);
1446           receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1447
1448           if (CVAL(inbuf,smb_rcls) != 0)
1449             {
1450               DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1451               break;
1452             }
1453
1454           datalen = SVAL(inbuf,smb_vwv0);
1455           dataptr = smb_buf(inbuf) + 3;
1456           break;
1457         }
1458  
1459       if (writefile(handle,dataptr,datalen) != datalen)
1460         {
1461           DEBUG(0,("Error writing local file\n"));
1462           break;
1463         }
1464       
1465       nread += datalen;
1466       if (datalen == 0) 
1467         {
1468           DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1469           break;
1470         }
1471
1472       dataptr=NULL;
1473       datalen=0;
1474     }
1475
1476
1477
1478   if (!close_done)
1479     {
1480       bzero(outbuf,smb_size);
1481       set_message(outbuf,3,0,True);
1482       CVAL(outbuf,smb_com) = SMBclose;
1483       SSVAL(outbuf,smb_tid,cnum);
1484       setup_pkt(outbuf);
1485       
1486       SSVAL(outbuf,smb_vwv0,fnum);
1487       SIVALS(outbuf,smb_vwv1,-1);
1488       
1489       send_smb(Client,outbuf);
1490       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1491       
1492       if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1493         {
1494           DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1495           if(newhandle)
1496             close(handle);
1497           free(inbuf);free(outbuf);
1498           return;
1499         }
1500     }
1501
1502   if(newhandle)
1503     close(handle);
1504
1505   if (archive_level >= 2 && (finfo.mode & aARCH)) {
1506     bzero(outbuf,smb_size);
1507     set_message(outbuf,8,strlen(rname)+4,True);
1508     CVAL(outbuf,smb_com) = SMBsetatr;
1509     SSVAL(outbuf,smb_tid,cnum);
1510     setup_pkt(outbuf);
1511     SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1512     SIVALS(outbuf,smb_vwv1,0);
1513     p = smb_buf(outbuf);
1514     *p++ = 4;
1515     strcpy(p,rname);
1516     p += strlen(p)+1;
1517     *p++ = 4;
1518     *p = 0;
1519     send_smb(Client,outbuf);
1520     receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1521   }
1522
1523   {
1524     struct timeval tp_end;
1525     int this_time;
1526
1527     GetTimeOfDay(&tp_end);
1528     this_time = 
1529       (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1530         (tp_end.tv_usec - tp_start.tv_usec)/1000;
1531     get_total_time_ms += this_time;
1532     get_total_size += finfo.size;
1533
1534     DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1535              finfo.size / (1.024*this_time + 1.0e-4),
1536              get_total_size / (1.024*get_total_time_ms)));
1537   }
1538
1539   free(inbuf);free(outbuf);
1540 }
1541
1542
1543 /****************************************************************************
1544   get a file
1545   ****************************************************************************/
1546 static void cmd_get(void)
1547 {
1548   pstring lname;
1549   pstring rname;
1550   char *p;
1551
1552   strcpy(rname,cur_dir);
1553   strcat(rname,"\\");
1554
1555   p = rname + strlen(rname);
1556
1557   if (!next_token(NULL,p,NULL)) {
1558     DEBUG(0,("get <filename>\n"));
1559     return;
1560   }
1561   strcpy(lname,p);
1562   dos_clean_name(rname);
1563     
1564   next_token(NULL,lname,NULL);
1565
1566   do_get(rname,lname,NULL);
1567 }
1568
1569
1570 /****************************************************************************
1571   do a mget operation on one file
1572   ****************************************************************************/
1573 static void do_mget(file_info *finfo)
1574 {
1575   pstring rname;
1576   pstring quest;
1577
1578   if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1579     return;
1580
1581   if (abort_mget)
1582     {
1583       DEBUG(0,("mget aborted\n"));
1584       return;
1585     }
1586
1587   if (finfo->mode & aDIR)
1588     sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1589   else
1590     sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1591
1592   if (prompt && !yesno(quest)) return;
1593
1594   if (finfo->mode & aDIR)
1595     {
1596       pstring saved_curdir;
1597       pstring mget_mask;
1598       char *inbuf,*outbuf;
1599
1600       inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1601       outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1602
1603       if (!inbuf || !outbuf)
1604         {
1605           DEBUG(0,("out of memory\n"));
1606           return;
1607         }
1608
1609       strcpy(saved_curdir,cur_dir);
1610
1611       strcat(cur_dir,finfo->name);
1612       strcat(cur_dir,"\\");
1613
1614       unix_format(finfo->name);
1615       {
1616         if (lowercase)
1617           strlower(finfo->name);
1618
1619         if (!directory_exist(finfo->name,NULL) && 
1620             sys_mkdir(finfo->name,0777) != 0) 
1621           {
1622             DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1623             strcpy(cur_dir,saved_curdir);
1624             free(inbuf);free(outbuf);
1625             return;
1626           }
1627
1628         if (sys_chdir(finfo->name) != 0)
1629           {
1630             DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1631             strcpy(cur_dir,saved_curdir);
1632             free(inbuf);free(outbuf);
1633             return;
1634           }
1635       }       
1636
1637       strcpy(mget_mask,cur_dir);
1638       strcat(mget_mask,"*");
1639       
1640       do_dir((char *)inbuf,(char *)outbuf,
1641              mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1642       chdir("..");
1643       strcpy(cur_dir,saved_curdir);
1644       free(inbuf);free(outbuf);
1645     }
1646   else
1647     {
1648       strcpy(rname,cur_dir);
1649       strcat(rname,finfo->name);
1650       do_get(rname,finfo->name,finfo);
1651     }
1652 }
1653
1654 /****************************************************************************
1655 view the file using the pager
1656 ****************************************************************************/
1657 static void cmd_more(void)
1658 {
1659   fstring rname,lname,tmpname,pager_cmd;
1660   char *pager;
1661
1662   strcpy(rname,cur_dir);
1663   strcat(rname,"\\");
1664   sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1665   strcpy(lname,tmpname);
1666
1667   if (!next_token(NULL,rname+strlen(rname),NULL)) {
1668     DEBUG(0,("more <filename>\n"));
1669     return;
1670   }
1671   dos_clean_name(rname);
1672
1673   do_get(rname,lname,NULL);
1674
1675   pager=getenv("PAGER");
1676   sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1677   system(pager_cmd);
1678   unlink(tmpname);
1679 }
1680
1681
1682
1683 /****************************************************************************
1684 do a mget command
1685 ****************************************************************************/
1686 static void cmd_mget(char *inbuf,char *outbuf)
1687 {
1688   int attribute = aSYSTEM | aHIDDEN;
1689   pstring mget_mask;
1690   fstring buf;
1691   char *p=buf;
1692
1693   *mget_mask = 0;
1694
1695   if (recurse)
1696     attribute |= aDIR;
1697
1698   abort_mget = False;
1699
1700   while (next_token(NULL,p,NULL))
1701     {
1702       strcpy(mget_mask,cur_dir);
1703       if(mget_mask[strlen(mget_mask)-1]!='\\')
1704         strcat(mget_mask,"\\");
1705
1706       if (*p == '\\')
1707         strcpy(mget_mask,p);
1708       else
1709         strcat(mget_mask,p);
1710       do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1711     }
1712
1713   if (! *mget_mask)
1714     {
1715       strcpy(mget_mask,cur_dir);
1716       if(mget_mask[strlen(mget_mask)-1]!='\\')
1717         strcat(mget_mask,"\\");
1718       strcat(mget_mask,"*");
1719       do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1720     }
1721 }
1722
1723 /****************************************************************************
1724 make a directory of name "name"
1725 ****************************************************************************/
1726 static BOOL do_mkdir(char *name)
1727 {
1728   char *p;
1729   char *inbuf,*outbuf;
1730
1731   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1732   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1733
1734   if (!inbuf || !outbuf)
1735     {
1736       DEBUG(0,("out of memory\n"));
1737       return False;
1738     }
1739
1740   bzero(outbuf,smb_size);
1741   set_message(outbuf,0,2 + strlen(name),True);
1742   
1743   CVAL(outbuf,smb_com) = SMBmkdir;
1744   SSVAL(outbuf,smb_tid,cnum);
1745   setup_pkt(outbuf);
1746
1747   
1748   p = smb_buf(outbuf);
1749   *p++ = 4;      
1750   strcpy(p,name);
1751   
1752   send_smb(Client,outbuf);
1753   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1754   
1755   if (CVAL(inbuf,smb_rcls) != 0)
1756     {
1757       DEBUG(0,("%s making remote directory %s\n",
1758                smb_errstr(inbuf),CNV_LANG(name)));
1759
1760       free(inbuf);free(outbuf);
1761       return(False);
1762     }
1763
1764   free(inbuf);free(outbuf);
1765   return(True);
1766 }
1767
1768
1769 /****************************************************************************
1770   make a directory
1771   ****************************************************************************/
1772 static void cmd_mkdir(char *inbuf,char *outbuf)
1773 {
1774   pstring mask;
1775   fstring buf;
1776   char *p=buf;
1777   
1778   strcpy(mask,cur_dir);
1779
1780   if (!next_token(NULL,p,NULL))
1781     {
1782       if (!recurse)
1783         DEBUG(0,("mkdir <dirname>\n"));
1784       return;
1785     }
1786   strcat(mask,p);
1787
1788   if (recurse)
1789     {
1790       pstring ddir;
1791       pstring ddir2;
1792       *ddir2 = 0;
1793
1794       strcpy(ddir,mask);
1795       trim_string(ddir,".",NULL);
1796       p = strtok(ddir,"/\\");
1797       while (p)
1798         {
1799           strcat(ddir2,p);
1800           if (!chkpath(ddir2,False))
1801             {             
1802               do_mkdir(ddir2);
1803             }
1804           strcat(ddir2,"\\");
1805           p = strtok(NULL,"/\\");
1806         }        
1807     }
1808   else
1809     do_mkdir(mask);
1810 }
1811
1812
1813 /*******************************************************************
1814   write to a file using writebraw
1815   ********************************************************************/
1816 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1817 {
1818   extern int Client;
1819   pstring inbuf;
1820
1821   bzero(outbuf,smb_size);
1822   bzero(inbuf,smb_size);  
1823   set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1824
1825   CVAL(outbuf,smb_com) = SMBwritebraw;
1826   SSVAL(outbuf,smb_tid,cnum);
1827   setup_pkt(outbuf);
1828
1829   SSVAL(outbuf,smb_vwv0,fnum);
1830   SSVAL(outbuf,smb_vwv1,n);
1831   SIVAL(outbuf,smb_vwv3,pos);
1832   SSVAL(outbuf,smb_vwv7,1);
1833
1834   send_smb(Client,outbuf);
1835   
1836   if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1837     return(0);
1838
1839   _smb_setlen(buf-4,n);         /* HACK! XXXX */
1840
1841   if (write_socket(Client,buf-4,n+4) != n+4)
1842     return(0);
1843
1844   if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1845     DEBUG(0,("Error writing remote file (2)\n"));
1846     return(0);
1847   }
1848   return(SVAL(inbuf,smb_vwv0));
1849 }
1850       
1851
1852
1853 /*******************************************************************
1854   write to a file
1855   ********************************************************************/
1856 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1857 {
1858   pstring inbuf;
1859
1860   if (writebraw_supported && n > (max_xmit-200)) 
1861     return(smb_writeraw(outbuf,fnum,pos,buf,n));
1862
1863   bzero(outbuf,smb_size);
1864   bzero(inbuf,smb_size);
1865   set_message(outbuf,5,n + 3,True);
1866
1867   CVAL(outbuf,smb_com) = SMBwrite;
1868   SSVAL(outbuf,smb_tid,cnum);
1869   setup_pkt(outbuf);
1870
1871   SSVAL(outbuf,smb_vwv0,fnum);
1872   SSVAL(outbuf,smb_vwv1,n);
1873   SIVAL(outbuf,smb_vwv2,pos);
1874   SSVAL(outbuf,smb_vwv4,0);
1875   CVAL(smb_buf(outbuf),0) = 1;
1876   SSVAL(smb_buf(outbuf),1,n);
1877
1878   memcpy(smb_buf(outbuf)+3,buf,n);
1879
1880   send_smb(Client,outbuf);
1881   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1882
1883   if (CVAL(inbuf,smb_rcls) != 0) {
1884     DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1885     return(0);
1886   }
1887   return(SVAL(inbuf,smb_vwv0));
1888 }
1889       
1890
1891
1892 /****************************************************************************
1893   put a single file
1894   ****************************************************************************/
1895 static void do_put(char *rname,char *lname,file_info *finfo)
1896 {
1897   int fnum;
1898   FILE *f;
1899   int nread=0;
1900   char *p;
1901   char *inbuf,*outbuf; 
1902   time_t close_time = finfo->mtime;
1903   char *buf=NULL;
1904   static int maxwrite=0;
1905
1906   struct timeval tp_start;
1907   GetTimeOfDay(&tp_start);
1908
1909   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1910   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1911
1912   if (!inbuf || !outbuf)
1913     {
1914       DEBUG(0,("out of memory\n"));
1915       return;
1916     }
1917
1918   bzero(outbuf,smb_size);
1919   set_message(outbuf,3,2 + strlen(rname),True);
1920
1921   if (finfo->mtime == 0 || finfo->mtime == -1)
1922     finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1923
1924   CVAL(outbuf,smb_com) = SMBcreate;
1925   SSVAL(outbuf,smb_tid,cnum);
1926   setup_pkt(outbuf);
1927
1928   SSVAL(outbuf,smb_vwv0,finfo->mode);
1929   put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1930   
1931   p = smb_buf(outbuf);
1932   *p++ = 4;      
1933   strcpy(p,rname);
1934   
1935   send_smb(Client,outbuf);
1936   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1937   
1938   if (CVAL(inbuf,smb_rcls) != 0)
1939     {
1940       DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1941
1942       free(inbuf);free(outbuf);if (buf) free(buf);
1943       return;
1944     }
1945
1946   f = fopen(lname,"r");
1947
1948   if (!f)
1949     {
1950       DEBUG(0,("Error opening local file %s\n",lname));
1951       free(inbuf);free(outbuf);
1952       return;
1953     }
1954
1955   
1956   fnum = SVAL(inbuf,smb_vwv0);
1957   if (finfo->size < 0)
1958     finfo->size = file_size(lname);
1959   
1960   DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1961   
1962   if (!maxwrite)
1963     maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1964
1965   while (nread < finfo->size)
1966     {
1967       int n = maxwrite;
1968       int ret;
1969
1970       n = MIN(n,finfo->size - nread);
1971
1972       buf = (char *)Realloc(buf,n+4);
1973   
1974       fseek(f,nread,SEEK_SET);
1975       if ((n = readfile(buf+4,1,n,f)) < 1)
1976         {
1977           DEBUG(0,("Error reading local file\n"));
1978           break;
1979         }         
1980
1981       ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1982
1983       if (n != ret) {
1984         if (!maxwrite) {
1985           DEBUG(0,("Error writing file\n"));
1986           break;
1987         } else {
1988           maxwrite /= 2;
1989           continue;
1990         }
1991       }
1992
1993       nread += n;
1994     }
1995
1996
1997
1998   bzero(outbuf,smb_size);
1999   set_message(outbuf,3,0,True);
2000   CVAL(outbuf,smb_com) = SMBclose;
2001   SSVAL(outbuf,smb_tid,cnum);
2002   setup_pkt(outbuf);
2003
2004   SSVAL(outbuf,smb_vwv0,fnum);  
2005   put_dos_date3(outbuf,smb_vwv1,close_time);
2006
2007   send_smb(Client,outbuf);
2008   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2009   
2010   if (CVAL(inbuf,smb_rcls) != 0)
2011     {
2012       DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2013       fclose(f);
2014       free(inbuf);free(outbuf);
2015       if (buf) free(buf);
2016       return;
2017     }
2018
2019   
2020   fclose(f);
2021   free(inbuf);free(outbuf);
2022   if (buf) free(buf);
2023
2024   {
2025     struct timeval tp_end;
2026     int this_time;
2027
2028     GetTimeOfDay(&tp_end);
2029     this_time = 
2030       (tp_end.tv_sec - tp_start.tv_sec)*1000 +
2031         (tp_end.tv_usec - tp_start.tv_usec)/1000;
2032     put_total_time_ms += this_time;
2033     put_total_size += finfo->size;
2034
2035     DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
2036              finfo->size / (1.024*this_time + 1.0e-4),
2037              put_total_size / (1.024*put_total_time_ms)));
2038   }
2039
2040
2041  
2042
2043 /****************************************************************************
2044   put a file
2045   ****************************************************************************/
2046 static void cmd_put(void)
2047 {
2048   pstring lname;
2049   pstring rname;
2050   fstring buf;
2051   char *p=buf;
2052   file_info finfo;
2053   finfo = def_finfo;
2054   
2055   strcpy(rname,cur_dir);
2056   strcat(rname,"\\");
2057   
2058   
2059   if (!next_token(NULL,p,NULL))
2060     {
2061       DEBUG(0,("put <filename>\n"));
2062       return;
2063     }
2064   strcpy(lname,p);
2065   
2066   if (next_token(NULL,p,NULL))
2067     strcat(rname,p);      
2068   else
2069     strcat(rname,lname);
2070
2071   dos_clean_name(rname);
2072
2073   {
2074     struct stat st;
2075     if (!file_exist(lname,&st)) {
2076       DEBUG(0,("%s does not exist\n",lname));
2077       return;
2078     }
2079     finfo.mtime = st.st_mtime;
2080   }
2081
2082   do_put(rname,lname,&finfo);
2083 }
2084
2085 /****************************************************************************
2086   seek in a directory/file list until you get something that doesn't start with
2087   the specified name
2088   ****************************************************************************/
2089 static BOOL seek_list(FILE *f,char *name)
2090 {
2091   pstring s;
2092   while (!feof(f))
2093     {
2094       if (fscanf(f,"%s",s) != 1) return(False);
2095       trim_string(s,"./",NULL);
2096       if (strncmp(s,name,strlen(name)) != 0)
2097         {
2098           strcpy(name,s);
2099           return(True);
2100         }
2101     }
2102       
2103   return(False);
2104 }
2105
2106
2107 /****************************************************************************
2108   set the file selection mask
2109   ****************************************************************************/
2110 static void cmd_select(void)
2111 {
2112   strcpy(fileselection,"");
2113   next_token(NULL,fileselection,NULL);
2114 }
2115
2116
2117 /****************************************************************************
2118   mput some files
2119   ****************************************************************************/
2120 static void cmd_mput(void)
2121 {
2122   pstring lname;
2123   pstring rname;
2124   file_info finfo;
2125   fstring buf;
2126   char *p=buf;
2127
2128   finfo = def_finfo;
2129
2130   
2131   while (next_token(NULL,p,NULL))
2132     {
2133       struct stat st;
2134       pstring cmd;
2135       pstring tmpname;
2136       FILE *f;
2137       
2138       sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2139       if (recurse)
2140         sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2141       else
2142         sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2143       system(cmd);
2144
2145       f = fopen(tmpname,"r");
2146       if (!f) continue;
2147
2148       while (!feof(f))
2149         {
2150           pstring quest;
2151
2152           if (fscanf(f,"%s",lname) != 1) break;
2153           trim_string(lname,"./",NULL);
2154
2155         again1:
2156
2157           /* check if it's a directory */
2158           if (directory_exist(lname,&st))
2159             {
2160               if (!recurse) continue;
2161               sprintf(quest,"Put directory %s? ",lname);
2162               if (prompt && !yesno(quest)) 
2163                 {
2164                   strcat(lname,"/");
2165                   if (!seek_list(f,lname))
2166                     break;
2167                   goto again1;              
2168                 }
2169               
2170               strcpy(rname,cur_dir);
2171               strcat(rname,lname);
2172               if (!chkpath(rname,False) && !do_mkdir(rname)) {
2173                 strcat(lname,"/");
2174                 if (!seek_list(f,lname))
2175                   break;
2176                 goto again1;                              
2177               }
2178
2179               continue;
2180             }
2181           else
2182             {
2183               sprintf(quest,"Put file %s? ",lname);
2184               if (prompt && !yesno(quest)) continue;
2185
2186               strcpy(rname,cur_dir);
2187               strcat(rname,lname);
2188             }
2189           dos_format(rname);
2190
2191           /* null size so do_put knows to ignore it */
2192           finfo.size = -1;
2193
2194           /* set the date on the file */
2195           finfo.mtime = st.st_mtime;
2196
2197           do_put(rname,lname,&finfo);
2198         }
2199       fclose(f);
2200       unlink(tmpname);
2201     }
2202 }
2203
2204 /****************************************************************************
2205   cancel a print job
2206   ****************************************************************************/
2207 static void do_cancel(int job)
2208 {
2209   char *rparam = NULL;
2210   char *rdata = NULL;
2211   char *p;
2212   int rdrcnt,rprcnt;
2213   pstring param;
2214
2215   bzero(param,sizeof(param));
2216
2217   p = param;
2218   SSVAL(p,0,81);                /* DosPrintJobDel() */
2219   p += 2;
2220   strcpy(p,"W");
2221   p = skip_string(p,1);
2222   strcpy(p,"");
2223   p = skip_string(p,1);
2224   SSVAL(p,0,job);     
2225   p += 2;
2226
2227   if (call_api(PTR_DIFF(p,param),0,
2228                6,1000,
2229                &rprcnt,&rdrcnt,
2230                param,NULL,
2231                &rparam,&rdata))
2232     {
2233       int res = SVAL(rparam,0);
2234
2235       if (!res)
2236         printf("Job %d cancelled\n",job);
2237       else
2238         printf("Error %d calcelling job %d\n",res,job);
2239       return;
2240     }
2241   else
2242   printf("Server refused cancel request\n");
2243
2244   if (rparam) free(rparam);
2245   if (rdata) free(rdata);
2246
2247   return;
2248 }
2249
2250
2251 /****************************************************************************
2252   cancel a print job
2253   ****************************************************************************/
2254 static void cmd_cancel(char *inbuf,char *outbuf )
2255 {
2256   fstring buf;
2257   int job; 
2258
2259   if (!connect_as_printer)
2260     {
2261       DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2262       DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2263     }
2264
2265   if (!next_token(NULL,buf,NULL)) {
2266     printf("cancel <jobid> ...\n");
2267     return;
2268   }
2269   do {
2270     job = atoi(buf);
2271     do_cancel(job);
2272   } while (next_token(NULL,buf,NULL));
2273 }
2274
2275
2276 /****************************************************************************
2277   get info on a file
2278   ****************************************************************************/
2279 static void cmd_stat(char *inbuf,char *outbuf)
2280 {
2281   fstring buf;
2282   pstring param;
2283   char *resp_data=NULL;
2284   char *resp_param=NULL;
2285   int resp_data_len = 0;
2286   int resp_param_len=0;
2287   char *p;
2288   uint16 setup = TRANSACT2_QPATHINFO;
2289
2290   if (!next_token(NULL,buf,NULL)) {
2291     printf("stat <file>\n");
2292     return;
2293   }
2294
2295   bzero(param,6);
2296   SSVAL(param,0,4); /* level */
2297   p = param+6;
2298   strcpy(p,cur_dir);
2299   strcat(p,buf);
2300
2301   send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
2302                      NULL,param,&setup,
2303                      0,6 + strlen(p)+1,1,
2304                      BUFFER_SIZE,2,0);
2305
2306   receive_trans_response(inbuf,SMBtrans2,
2307                           &resp_data_len,&resp_param_len,
2308                           &resp_data,&resp_param);
2309
2310   if (resp_data) free(resp_data); resp_data = NULL;
2311   if (resp_param) free(resp_param); resp_param = NULL;
2312 }
2313
2314
2315 /****************************************************************************
2316   print a file
2317   ****************************************************************************/
2318 static void cmd_print(char *inbuf,char *outbuf )
2319 {
2320   int fnum;
2321   FILE *f = NULL;
2322   uint32 nread=0;
2323   pstring lname;
2324   pstring rname;
2325   char *p;
2326
2327   if (!connect_as_printer)
2328     {
2329       DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2330       DEBUG(0,("Trying to print without -P may fail\n"));
2331     }
2332
2333   if (!next_token(NULL,lname,NULL))
2334     {
2335       DEBUG(0,("print <filename>\n"));
2336       return;
2337     }
2338
2339   strcpy(rname,lname);
2340   p = strrchr(rname,'/');
2341   if (p)
2342     {
2343       pstring tname;
2344       strcpy(tname,p+1);
2345       strcpy(rname,tname);
2346     }
2347
2348   if ((int)strlen(rname) > 14)
2349     rname[14] = 0;
2350
2351   if (strequal(lname,"-"))
2352     {
2353       f = stdin;
2354       strcpy(rname,"stdin");
2355     }
2356   
2357   dos_clean_name(rname);
2358
2359   bzero(outbuf,smb_size);
2360   set_message(outbuf,2,2 + strlen(rname),True);
2361   
2362   CVAL(outbuf,smb_com) = SMBsplopen;
2363   SSVAL(outbuf,smb_tid,cnum);
2364   setup_pkt(outbuf);
2365
2366   SSVAL(outbuf,smb_vwv0,0);
2367   SSVAL(outbuf,smb_vwv1,printmode);
2368   
2369   p = smb_buf(outbuf);
2370   *p++ = 4;      
2371   strcpy(p,rname);
2372   
2373   send_smb(Client,outbuf);
2374   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2375   
2376   if (CVAL(inbuf,smb_rcls) != 0)
2377     {
2378       DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2379       return;
2380     }
2381   
2382   if (!f)
2383     f = fopen(lname,"r");
2384   if (!f)
2385     {
2386       DEBUG(0,("Error opening local file %s\n",lname));
2387       return;
2388     }
2389
2390   
2391   fnum = SVAL(inbuf,smb_vwv0);
2392   
2393   DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2394   
2395   while (!feof(f))
2396     {
2397       int n;
2398   
2399       bzero(outbuf,smb_size);
2400       set_message(outbuf,1,3,True);
2401
2402       /* for some strange reason the OS/2 print server can't handle large
2403          packets when printing. weird */
2404       n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2405
2406       if (translation)
2407         n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2408       else
2409         n = readfile(smb_buf(outbuf)+3,1,n,f);
2410       if (n <= 0) 
2411         {
2412           DEBUG(0,("read gave %d\n",n));
2413           break;
2414         }
2415
2416       smb_setlen(outbuf,smb_len(outbuf) + n);
2417
2418       CVAL(outbuf,smb_com) = SMBsplwr;
2419       SSVAL(outbuf,smb_tid,cnum);
2420       setup_pkt(outbuf);
2421
2422       SSVAL(outbuf,smb_vwv0,fnum);
2423       SSVAL(outbuf,smb_vwv1,n+3);
2424       CVAL(smb_buf(outbuf),0) = 1;
2425       SSVAL(smb_buf(outbuf),1,n);
2426
2427       send_smb(Client,outbuf);
2428       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2429
2430       if (CVAL(inbuf,smb_rcls) != 0)
2431         {
2432           DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2433           break;
2434         }
2435
2436       nread += n;
2437     }
2438
2439   DEBUG(2,("%d bytes printed\n",nread));
2440
2441   bzero(outbuf,smb_size);
2442   set_message(outbuf,1,0,True);
2443   CVAL(outbuf,smb_com) = SMBsplclose;
2444   SSVAL(outbuf,smb_tid,cnum);
2445   setup_pkt(outbuf);
2446
2447   SSVAL(outbuf,smb_vwv0,fnum);
2448
2449   send_smb(Client,outbuf);
2450   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2451   
2452   if (CVAL(inbuf,smb_rcls) != 0)
2453     {
2454       DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2455       if (f != stdin)
2456         fclose(f);
2457       return;
2458     }
2459
2460   if (f != stdin)
2461     fclose(f);
2462 }
2463
2464 /****************************************************************************
2465 show a print queue - this is deprecated as it uses the old smb that
2466 has limited support - the correct call is the cmd_p_queue_4() after this.
2467 ****************************************************************************/
2468 static void cmd_queue(char *inbuf,char *outbuf )
2469 {
2470   int count;
2471   char *p;
2472
2473   bzero(outbuf,smb_size);
2474   set_message(outbuf,2,0,True);
2475   
2476   CVAL(outbuf,smb_com) = SMBsplretq;
2477   SSVAL(outbuf,smb_tid,cnum);
2478   setup_pkt(outbuf);
2479
2480   SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2481   SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2482   
2483   send_smb(Client,outbuf);
2484   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2485   
2486   if (CVAL(inbuf,smb_rcls) != 0)
2487     {
2488       DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2489       return;
2490     }
2491
2492   count = SVAL(inbuf,smb_vwv0);
2493   p = smb_buf(inbuf) + 3;
2494   if (count <= 0)
2495     {
2496       DEBUG(0,("No entries in the print queue\n"));
2497       return;
2498     }  
2499
2500   {
2501     char status[20];
2502
2503     DEBUG(0,("Job      Name              Size         Status\n"));
2504
2505     while (count--)
2506       {
2507         switch (CVAL(p,4))
2508           {
2509           case 0x01: sprintf(status,"held or stopped"); break;
2510           case 0x02: sprintf(status,"printing"); break;
2511           case 0x03: sprintf(status,"awaiting print"); break;
2512           case 0x04: sprintf(status,"in intercept"); break;
2513           case 0x05: sprintf(status,"file had error"); break;
2514           case 0x06: sprintf(status,"printer error"); break;
2515           default: sprintf(status,"unknown"); break;
2516           }
2517
2518         DEBUG(0,("%-6d   %-16.16s  %-9d    %s\n",
2519                  SVAL(p,5),p+12,IVAL(p,7),status));
2520         p += 28;
2521       }
2522   }
2523   
2524 }
2525
2526
2527 /****************************************************************************
2528 show information about a print queue
2529 ****************************************************************************/
2530 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2531 {
2532   char *rparam = NULL;
2533   char *rdata = NULL;
2534   char *p;
2535   int rdrcnt, rprcnt;
2536   pstring param;
2537   int result_code=0;
2538
2539   if (!connect_as_printer)
2540     {
2541       DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2542       DEBUG(0,("Trying to print without -P may fail\n"));
2543     }
2544   
2545   bzero(param,sizeof(param));
2546
2547   p = param;
2548   SSVAL(p,0,76);                        /* API function number 76 (DosPrintJobEnum) */
2549   p += 2;
2550   strcpy(p,"zWrLeh");                   /* parameter description? */
2551   p = skip_string(p,1);
2552   strcpy(p,"WWzWWDDzz");                /* returned data format */
2553   p = skip_string(p,1);
2554   strcpy(p,strrchr(service,'\\')+1);    /* name of queue */
2555   p = skip_string(p,1);
2556   SSVAL(p,0,2);                 /* API function level 2, PRJINFO_2 data structure */
2557   SSVAL(p,2,1000);                      /* size of bytes of returned data buffer */
2558   p += 4;
2559   strcpy(p,"");                         /* subformat */
2560   p = skip_string(p,1);
2561
2562   DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2563   if( call_api(PTR_DIFF(p,param), 0,
2564                10, 4096,
2565                &rprcnt, &rdrcnt,
2566                param, NULL,
2567                &rparam, &rdata) )
2568     {
2569       int converter;
2570       result_code = SVAL(rparam,0);
2571       converter = SVAL(rparam,2);             /* conversion factor */
2572
2573       DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2574
2575       if (result_code == 0)                   /* if no error, */
2576         {
2577           int i;
2578           uint16 JobId;
2579           uint16 Priority;
2580           uint32 Size;
2581           char *UserName;
2582           char *JobName;
2583           char *JobTimeStr;
2584           time_t JobTime;
2585           char PrinterName[20];
2586              
2587           strcpy(PrinterName,strrchr(service,'\\')+1);       /* name of queue */
2588           strlower(PrinterName);                             /* in lower case */
2589
2590           p = rdata;                          /* received data */
2591           for( i = 0; i < SVAL(rparam,4); ++i)
2592             {
2593               JobId = SVAL(p,0);
2594               Priority = SVAL(p,2);
2595               UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2596               strlower(UserName);
2597               Priority = SVAL(p,2);
2598               JobTime = make_unix_date3( p + 12);
2599               JobTimeStr = asctime(LocalTime( &JobTime));
2600               Size = IVAL(p,16);
2601               JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2602             
2603
2604               printf("%s-%u    %s    priority %u   %s    %s   %u bytes\n", 
2605                 PrinterName, JobId, UserName,
2606                 Priority, JobTimeStr, JobName, Size);
2607    
2608 #if 0 /* DEBUG code */
2609               printf("Job Id: \"%u\"\n", SVAL(p,0));
2610               printf("Priority: \"%u\"\n", SVAL(p,2));
2611             
2612               printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2613               printf("Position: \"%u\"\n", SVAL(p,8));
2614               printf("Status: \"%u\"\n", SVAL(p,10));
2615             
2616               JobTime = make_unix_date3( p + 12);
2617               printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2618               printf("date: \"%u\"\n", SVAL(p,12));
2619
2620               printf("Size: \"%u\"\n", SVAL(p,16));
2621               printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2622               printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2623 #endif /* DEBUG CODE */ 
2624               p += 28;
2625             }
2626         }
2627     }
2628   else                  /* call_api() failed */
2629     {
2630       printf("Failed, error = %d\n", result_code);
2631     }
2632
2633   /* If any parameters or data were returned, free the storage. */
2634   if(rparam) free(rparam);
2635   if(rdata) free(rdata);
2636
2637   return;
2638 }
2639
2640 /****************************************************************************
2641 show information about a print queue
2642 ****************************************************************************/
2643 static void cmd_qinfo(char *inbuf,char *outbuf )
2644 {
2645   char *rparam = NULL;
2646   char *rdata = NULL;
2647   char *p;
2648   int rdrcnt, rprcnt;
2649   pstring param;
2650   int result_code=0;
2651   
2652   bzero(param,sizeof(param));
2653
2654   p = param;
2655   SSVAL(p,0,70);                        /* API function number 70 (DosPrintQGetInfo) */
2656   p += 2;
2657   strcpy(p,"zWrLh");                    /* parameter description? */
2658   p = skip_string(p,1);
2659   strcpy(p,"zWWWWzzzzWWzzl");           /* returned data format */
2660   p = skip_string(p,1);
2661   strcpy(p,strrchr(service,'\\')+1);    /* name of queue */
2662   p = skip_string(p,1);
2663   SSVAL(p,0,3);                         /* API function level 3, just queue info, no job info */
2664   SSVAL(p,2,1000);                      /* size of bytes of returned data buffer */
2665   p += 4;
2666   strcpy(p,"");                         /* subformat */
2667   p = skip_string(p,1);
2668
2669   DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2670   if( call_api(PTR_DIFF(p,param), 0,
2671                10, 4096,
2672                &rprcnt, &rdrcnt,
2673                param, NULL,
2674                &rparam, &rdata) )
2675         {
2676         int converter;
2677         result_code = SVAL(rparam,0);
2678         converter = SVAL(rparam,2);             /* conversion factor */
2679
2680         DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2681
2682         if (result_code == 0)                   /* if no error, */
2683             {
2684             p = rdata;                          /* received data */
2685
2686             printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2687             printf("Priority: %u\n", SVAL(p,4) );
2688             printf("Start time: %u\n", SVAL(p,6) );
2689             printf("Until time: %u\n", SVAL(p,8) );
2690             printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2691             printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2692             printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2693             printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2694             printf("Status: %u\n", SVAL(p,28) );
2695             printf("Jobs: %u\n", SVAL(p,30) );
2696             printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2697             printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2698
2699             /* Dump the driver data */
2700             {
2701             int count, x, y, c;
2702             char *ddptr;
2703
2704             ddptr = rdata + SVAL(p,40) - converter;
2705             if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2706             printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2707
2708             for(x=8; x < count; x+=16)
2709                 {
2710                 for(y=0; y < 16; y++)
2711                     {
2712                     if( (x+y) < count )
2713                         printf("%2.2X ", CVAL(ddptr,(x+y)) );
2714                     else
2715                         fputs("   ", stdout);
2716                     }
2717                 for(y=0; y < 16 && (x+y) < count; y++)
2718                     {
2719                     c = CVAL(ddptr,(x+y));
2720                     if(isprint(c))
2721                         fputc(c, stdout);
2722                     else
2723                         fputc('.', stdout);
2724                     }
2725                 fputc('\n', stdout);
2726                 }
2727             }
2728             
2729             }
2730         }
2731   else                  /* call_api() failed */
2732         {
2733         printf("Failed, error = %d\n", result_code);
2734         }
2735
2736   /* If any parameters or data were returned, free the storage. */
2737   if(rparam) free(rparam);
2738   if(rdata) free(rdata);
2739
2740   return;
2741 }
2742
2743 /****************************************************************************
2744 delete some files
2745 ****************************************************************************/
2746 static void do_del(file_info *finfo)
2747 {
2748   char *p;
2749   char *inbuf,*outbuf;
2750   pstring mask;
2751
2752   strcpy(mask,cur_dir);
2753   strcat(mask,finfo->name);
2754
2755   if (finfo->mode & aDIR) 
2756     return;
2757
2758   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2759   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2760   
2761   if (!inbuf || !outbuf)
2762     {
2763       DEBUG(0,("out of memory\n"));
2764       return;
2765     }
2766
2767   bzero(outbuf,smb_size);
2768   set_message(outbuf,1,2 + strlen(mask),True);
2769   
2770   CVAL(outbuf,smb_com) = SMBunlink;
2771   SSVAL(outbuf,smb_tid,cnum);
2772   setup_pkt(outbuf);
2773
2774   SSVAL(outbuf,smb_vwv0,0);
2775   
2776   p = smb_buf(outbuf);
2777   *p++ = 4;      
2778   strcpy(p,mask);
2779   
2780   send_smb(Client,outbuf);
2781   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2782   
2783   if (CVAL(inbuf,smb_rcls) != 0)
2784     DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2785
2786   free(inbuf);free(outbuf);
2787   
2788 }
2789
2790 /****************************************************************************
2791 delete some files
2792 ****************************************************************************/
2793 static void cmd_del(char *inbuf,char *outbuf )
2794 {
2795   pstring mask;
2796   fstring buf;
2797   int attribute = aSYSTEM | aHIDDEN;
2798
2799   if (recurse)
2800     attribute |= aDIR;
2801   
2802   strcpy(mask,cur_dir);
2803     
2804   if (!next_token(NULL,buf,NULL))
2805     {
2806       DEBUG(0,("del <filename>\n"));
2807       return;
2808     }
2809   strcat(mask,buf);
2810
2811   do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2812 }
2813
2814
2815 /****************************************************************************
2816 remove a directory
2817 ****************************************************************************/
2818 static void cmd_rmdir(char *inbuf,char *outbuf )
2819 {
2820   pstring mask;
2821   fstring buf;
2822   char *p;
2823   
2824   strcpy(mask,cur_dir);
2825   
2826   if (!next_token(NULL,buf,NULL))
2827     {
2828       DEBUG(0,("rmdir <dirname>\n"));
2829       return;
2830     }
2831   strcat(mask,buf);
2832
2833   bzero(outbuf,smb_size);
2834   set_message(outbuf,0,2 + strlen(mask),True);
2835   
2836   CVAL(outbuf,smb_com) = SMBrmdir;
2837   SSVAL(outbuf,smb_tid,cnum);
2838   setup_pkt(outbuf);
2839
2840   
2841   p = smb_buf(outbuf);
2842   *p++ = 4;      
2843   strcpy(p,mask);
2844   
2845   send_smb(Client,outbuf);
2846   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2847   
2848   if (CVAL(inbuf,smb_rcls) != 0)
2849     {
2850       DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2851       return;
2852     }
2853   
2854 }
2855
2856 /****************************************************************************
2857 rename some files
2858 ****************************************************************************/
2859 static void cmd_rename(char *inbuf,char *outbuf )
2860 {
2861   pstring src,dest;
2862   fstring buf,buf2;
2863   char *p;
2864   
2865   strcpy(src,cur_dir);
2866   strcpy(dest,cur_dir);
2867   
2868   if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2869     {
2870       DEBUG(0,("rename <src> <dest>\n"));
2871       return;
2872     }
2873   strcat(src,buf);
2874   strcat(dest,buf2);
2875
2876   bzero(outbuf,smb_size);
2877   set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2878   
2879   CVAL(outbuf,smb_com) = SMBmv;
2880   SSVAL(outbuf,smb_tid,cnum);
2881   SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2882   setup_pkt(outbuf);
2883   
2884   p = smb_buf(outbuf);
2885   *p++ = 4;      
2886   strcpy(p,src);
2887   p = skip_string(p,1);
2888   *p++ = 4;      
2889   strcpy(p,dest);
2890   
2891   send_smb(Client,outbuf);
2892   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2893   
2894   if (CVAL(inbuf,smb_rcls) != 0)
2895     {
2896       DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2897       return;
2898     }
2899   
2900 }
2901
2902
2903 /****************************************************************************
2904 toggle the prompt flag
2905 ****************************************************************************/
2906 static void cmd_prompt(void)
2907 {
2908   prompt = !prompt;
2909   DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2910 }
2911
2912
2913 /****************************************************************************
2914 set the newer than time
2915 ****************************************************************************/
2916 static void cmd_newer(void)
2917 {
2918   fstring buf;
2919   BOOL ok;
2920   struct stat sbuf;
2921
2922   ok = next_token(NULL,buf,NULL);
2923   if (ok && (sys_stat(buf,&sbuf) == 0))
2924     {
2925       newer_than = sbuf.st_mtime;
2926       DEBUG(1,("Getting files newer than %s",
2927                asctime(LocalTime(&newer_than))));
2928     }
2929   else
2930     newer_than = 0;
2931
2932   if (ok && newer_than == 0)
2933     DEBUG(0,("Error setting newer-than time\n"));
2934 }
2935
2936 /****************************************************************************
2937 set the archive level
2938 ****************************************************************************/
2939 static void cmd_archive(void)
2940 {
2941   fstring buf;
2942
2943   if (next_token(NULL,buf,NULL)) {
2944     archive_level = atoi(buf);
2945   } else
2946     DEBUG(0,("Archive level is %d\n",archive_level));
2947 }
2948
2949 /****************************************************************************
2950 toggle the lowercaseflag
2951 ****************************************************************************/
2952 static void cmd_lowercase(void)
2953 {
2954   lowercase = !lowercase;
2955   DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2956 }
2957
2958
2959
2960
2961 /****************************************************************************
2962 toggle the recurse flag
2963 ****************************************************************************/
2964 static void cmd_recurse(void)
2965 {
2966   recurse = !recurse;
2967   DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2968 }
2969
2970 /****************************************************************************
2971 toggle the translate flag
2972 ****************************************************************************/
2973 static void cmd_translate(void)
2974 {
2975   translation = !translation;
2976   DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2977         translation?"on":"off"));
2978 }
2979
2980
2981 /****************************************************************************
2982 do a printmode command
2983 ****************************************************************************/
2984 static void cmd_printmode(void)
2985 {
2986   fstring buf;
2987   fstring mode;
2988
2989   if (next_token(NULL,buf,NULL))
2990     {
2991       if (strequal(buf,"text"))
2992         printmode = 0;      
2993       else
2994         {
2995           if (strequal(buf,"graphics"))
2996             printmode = 1;
2997           else
2998             printmode = atoi(buf);
2999         }
3000     }
3001
3002   switch(printmode)
3003     {
3004     case 0: 
3005       strcpy(mode,"text");
3006       break;
3007     case 1: 
3008       strcpy(mode,"graphics");
3009       break;
3010     default: 
3011       sprintf(mode,"%d",printmode);
3012       break;
3013     }
3014
3015   DEBUG(2,("the printmode is now %s\n",mode));
3016 }
3017
3018 /****************************************************************************
3019 do the lcd command
3020 ****************************************************************************/
3021 static void cmd_lcd(void)
3022 {
3023   fstring buf;
3024   pstring d;
3025
3026   if (next_token(NULL,buf,NULL))
3027     sys_chdir(buf);
3028   DEBUG(2,("the local directory is now %s\n",GetWd(d)));
3029 }
3030
3031
3032 /****************************************************************************
3033 send a session request
3034 ****************************************************************************/
3035 static BOOL send_session_request(char *inbuf,char *outbuf)
3036 {
3037   fstring dest;
3038   char *p;
3039   int len = 4;
3040   /* send a session request (RFC 8002) */
3041
3042   strcpy(dest,desthost);
3043   p = strchr(dest,'.');
3044   if (p) *p = 0;
3045
3046   /* put in the destination name */
3047   p = outbuf+len;
3048   name_mangle(dest,p,name_type); /* 0x20 is the SMB server NetBIOS type. */
3049   len += name_len(p);
3050
3051   /* and my name */
3052   p = outbuf+len;
3053   name_mangle(myname,p,0);
3054   len += name_len(p);
3055
3056   /* setup the packet length */
3057   _smb_setlen(outbuf,len);
3058   CVAL(outbuf,0) = 0x81;
3059
3060   send_smb(Client,outbuf);
3061   DEBUG(5,("Sent session request\n"));
3062
3063   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3064
3065   if (CVAL(inbuf,0) == 0x84) /* C. Hoch  9/14/95 Start */
3066     {
3067       /* For information, here is the response structure.
3068        * We do the byte-twiddling to for portability.
3069        struct RetargetResponse{
3070        unsigned char type;
3071        unsigned char flags;
3072        int16 length;
3073        int32 ip_addr;
3074        int16 port;
3075        };
3076        */
3077       extern int Client;
3078       int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
3079       /* SESSION RETARGET */
3080       putip((char *)&dest_ip,inbuf+4);
3081
3082       close_sockets();
3083       Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
3084       if (Client == -1)
3085         return False;
3086
3087       DEBUG(3,("Retargeted\n"));
3088
3089       set_socket_options(Client,user_socket_options);
3090
3091       /* Try again */
3092       return send_session_request(inbuf,outbuf);
3093     } /* C. Hoch 9/14/95 End */
3094
3095
3096   if (CVAL(inbuf,0) != 0x82)
3097     {
3098       int ecode = CVAL(inbuf,4);
3099       DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
3100                CVAL(inbuf,0),ecode,myname,desthost));
3101       switch (ecode)
3102         {
3103         case 0x80: 
3104           DEBUG(0,("Not listening on called name\n")); 
3105           DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
3106           DEBUG(0,("You may find the -I option useful for this\n"));
3107           break;
3108         case 0x81: 
3109           DEBUG(0,("Not listening for calling name\n")); 
3110           DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
3111           DEBUG(0,("You may find the -n option useful for this\n"));
3112           break;
3113         case 0x82: 
3114           DEBUG(0,("Called name not present\n")); 
3115           DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
3116           DEBUG(0,("You may find the -I option useful for this\n"));
3117           break;
3118         case 0x83: 
3119           DEBUG(0,("Called name present, but insufficient resources\n")); 
3120           DEBUG(0,("Perhaps you should try again later?\n")); 
3121           break;
3122         default:
3123           DEBUG(0,("Unspecified error 0x%X\n",ecode)); 
3124           DEBUG(0,("Your server software is being unfriendly\n"));
3125           break;          
3126         }
3127       return(False);
3128     }
3129   return(True);
3130 }
3131
3132 static struct {
3133   int prot;
3134   char *name;
3135 } prots[] = {
3136   {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
3137   {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
3138   {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
3139   {PROTOCOL_LANMAN1,"LANMAN1.0"},
3140   {PROTOCOL_LANMAN2,"LM1.2X002"},
3141   {PROTOCOL_LANMAN2,"Samba"},
3142   {PROTOCOL_NT1,"NT LM 0.12"},
3143   {PROTOCOL_NT1,"NT LANMAN 1.0"},
3144   {-1,NULL}
3145 };
3146
3147
3148 /****************************************************************************
3149 send a login command
3150 ****************************************************************************/
3151 static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
3152 {
3153   BOOL was_null = (!inbuf && !outbuf);
3154   int sesskey=0;
3155   time_t servertime = 0;
3156   extern int serverzone;
3157   int sec_mode=0;
3158   int crypt_len;
3159   int max_vcs=0;
3160   char *pass = NULL;  
3161   pstring dev;
3162   char *p;
3163   int numprots;
3164   int tries=0;
3165
3166   if (was_null)
3167     {
3168       inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3169       outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3170     }
3171
3172 #if AJT
3173   if (strstr(service,"IPC$")) connect_as_ipc = True;
3174 #endif
3175
3176   strcpy(dev,"A:");
3177   if (connect_as_printer)
3178     strcpy(dev,"LPT1:");
3179   if (connect_as_ipc)
3180     strcpy(dev,"IPC");
3181
3182
3183   if (start_session && !send_session_request(inbuf,outbuf))
3184     {
3185       if (was_null)
3186         {
3187           free(inbuf);
3188           free(outbuf);
3189         }      
3190       return(False);
3191     }
3192
3193   bzero(outbuf,smb_size);
3194
3195   /* setup the protocol strings */
3196   {
3197     int plength;
3198
3199     for (plength=0,numprots=0;
3200          prots[numprots].name && prots[numprots].prot<=max_protocol;
3201          numprots++)
3202       plength += strlen(prots[numprots].name)+2;
3203     
3204     set_message(outbuf,0,plength,True);
3205
3206     p = smb_buf(outbuf);
3207     for (numprots=0;
3208          prots[numprots].name && prots[numprots].prot<=max_protocol;
3209          numprots++)
3210       {
3211         *p++ = 2;
3212         strcpy(p,prots[numprots].name);
3213         p += strlen(p) + 1;
3214       }
3215   }
3216
3217   CVAL(outbuf,smb_com) = SMBnegprot;
3218   setup_pkt(outbuf);
3219
3220   CVAL(smb_buf(outbuf),0) = 2;
3221
3222   send_smb(Client,outbuf);
3223   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3224
3225   show_msg(inbuf);
3226
3227   if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
3228     {
3229       DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
3230             myname,desthost,smb_errstr(inbuf)));
3231       if (was_null)
3232         {
3233           free(inbuf);
3234           free(outbuf);
3235         }
3236       return(False);
3237     }
3238
3239   Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
3240
3241
3242   if (Protocol < PROTOCOL_NT1) {    
3243     sec_mode = SVAL(inbuf,smb_vwv1);
3244     max_xmit = SVAL(inbuf,smb_vwv2);
3245     sesskey = IVAL(inbuf,smb_vwv6);
3246     serverzone = SVALS(inbuf,smb_vwv10)*60;
3247     /* this time is converted to GMT by make_unix_date */
3248     servertime = make_unix_date(inbuf+smb_vwv8);
3249     if (Protocol >= PROTOCOL_COREPLUS) {
3250       readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
3251       writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
3252     }
3253     crypt_len = smb_buflen(inbuf);
3254     memcpy(cryptkey,smb_buf(inbuf),8);
3255     DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
3256     max_vcs = SVAL(inbuf,smb_vwv4); 
3257     DEBUG(3,("max vcs %d\n",max_vcs)); 
3258     DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
3259   } else {
3260     /* NT protocol */
3261     sec_mode = CVAL(inbuf,smb_vwv1);
3262     max_xmit = IVAL(inbuf,smb_vwv3+1);
3263     sesskey = IVAL(inbuf,smb_vwv7+1);
3264     serverzone = SVALS(inbuf,smb_vwv15+1)*60;
3265     /* this time arrives in real GMT */
3266     servertime = interpret_long_date(inbuf+smb_vwv11+1);
3267     crypt_len = CVAL(inbuf,smb_vwv16+1);
3268     memcpy(cryptkey,smb_buf(inbuf),8);
3269     if (IVAL(inbuf,smb_vwv9+1) & 1)
3270       readbraw_supported = writebraw_supported = True;      
3271     DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
3272     max_vcs = SVAL(inbuf,smb_vwv2+1); 
3273     DEBUG(3,("max vcs %d\n",max_vcs));
3274     DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
3275     DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
3276   }
3277
3278   DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
3279   DEBUG(3,("max xmt %d\n",max_xmit));
3280   DEBUG(3,("Got %d byte crypt key\n",crypt_len));
3281   DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
3282
3283   doencrypt = ((sec_mode & 2) != 0);
3284
3285   if (servertime) {
3286     static BOOL done_time = False;
3287     if (!done_time) {
3288       DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
3289                asctime(LocalTime(&servertime)),
3290                -(double)(serverzone/3600.0)));
3291       done_time = True;
3292     }
3293   }
3294
3295  get_pass:
3296
3297   if (got_pass)
3298     pass = password;
3299   else
3300     pass = (char *)getpass("Password: ");
3301
3302   /* use a blank username for the 2nd try with a blank password */
3303   if (tries++ && !*pass)
3304     *username = 0;
3305
3306   if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
3307     {
3308       fstring pword;
3309       int passlen = strlen(pass)+1;
3310       strcpy(pword,pass);      
3311
3312 #ifdef SMB_PASSWD
3313       if (doencrypt && *pass) {
3314         DEBUG(3,("Using encrypted passwords\n"));
3315         passlen = 24;
3316         SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
3317       }
3318 #else
3319       doencrypt = False;
3320 #endif
3321
3322       /* if in share level security then don't send a password now */
3323       if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;} 
3324
3325       /* send a session setup command */
3326       bzero(outbuf,smb_size);
3327
3328       if (Protocol < PROTOCOL_NT1) {
3329         set_message(outbuf,10,1 + strlen(username) + passlen,True);
3330         CVAL(outbuf,smb_com) = SMBsesssetupX;
3331         setup_pkt(outbuf);
3332
3333         CVAL(outbuf,smb_vwv0) = 0xFF;
3334         SSVAL(outbuf,smb_vwv2,max_xmit);
3335         SSVAL(outbuf,smb_vwv3,2);
3336         SSVAL(outbuf,smb_vwv4,max_vcs-1);
3337         SIVAL(outbuf,smb_vwv5,sesskey);
3338         SSVAL(outbuf,smb_vwv7,passlen);
3339         p = smb_buf(outbuf);
3340         memcpy(p,pword,passlen);
3341         p += passlen;
3342         strcpy(p,username);
3343       } else {
3344         if (!doencrypt) passlen--;
3345         /* for Win95 */
3346         set_message(outbuf,13,0,True);
3347         CVAL(outbuf,smb_com) = SMBsesssetupX;
3348         setup_pkt(outbuf);
3349
3350         CVAL(outbuf,smb_vwv0) = 0xFF;
3351         SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
3352         SSVAL(outbuf,smb_vwv3,2);
3353         SSVAL(outbuf,smb_vwv4,getpid());
3354         SIVAL(outbuf,smb_vwv5,sesskey);
3355         SSVAL(outbuf,smb_vwv7,passlen);
3356         SSVAL(outbuf,smb_vwv8,0);
3357         p = smb_buf(outbuf);
3358         memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
3359         strcpy(p,username);p = skip_string(p,1);
3360         strcpy(p,workgroup);p = skip_string(p,1);
3361         strcpy(p,"Unix");p = skip_string(p,1);
3362         strcpy(p,"Samba");p = skip_string(p,1);
3363         set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
3364       }
3365
3366       send_smb(Client,outbuf);
3367       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3368
3369       show_msg(inbuf);
3370
3371       if (CVAL(inbuf,smb_rcls) != 0)
3372         {
3373           if (! *pass &&
3374               ((CVAL(inbuf,smb_rcls) == ERRDOS && 
3375                 SVAL(inbuf,smb_err) == ERRnoaccess) ||
3376                (CVAL(inbuf,smb_rcls) == ERRSRV && 
3377                 SVAL(inbuf,smb_err) == ERRbadpw)))
3378             {
3379               got_pass = False;
3380               DEBUG(3,("resending login\n"));
3381               goto get_pass;
3382             }
3383               
3384           DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s   %s\n",
3385                 username,myname,desthost,smb_errstr(inbuf)));
3386           DEBUG(0,("You might find the -U, -W or -n options useful\n"));
3387           DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
3388           DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
3389           if (was_null)
3390             {
3391               free(inbuf);
3392               free(outbuf);
3393             }
3394           return(False);
3395         }
3396
3397       if (Protocol >= PROTOCOL_NT1) {
3398         char *domain,*os,*lanman;
3399         p = smb_buf(inbuf);
3400         os = p;
3401         lanman = skip_string(os,1);
3402         domain = skip_string(lanman,1);
3403         if (*domain || *os || *lanman)
3404           DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
3405       }
3406
3407       /* use the returned uid from now on */
3408       if (SVAL(inbuf,smb_uid) != uid)
3409         DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
3410               SVAL(inbuf,smb_uid),uid));
3411       uid = SVAL(inbuf,smb_uid);
3412     }
3413
3414   /* now we've got a connection - send a tcon message */
3415   bzero(outbuf,smb_size);
3416
3417   if (strncmp(service,"\\\\",2) != 0)
3418     {
3419       DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
3420       DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
3421     }
3422
3423
3424  again2:
3425
3426   {
3427     int passlen = strlen(pass)+1;
3428     fstring pword;
3429     strcpy(pword,pass);
3430
3431 #ifdef SMB_PASSWD
3432     if (doencrypt && *pass) {
3433       passlen=24;
3434       SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);      
3435     }
3436 #endif
3437
3438     /* if in user level security then don't send a password now */
3439     if ((sec_mode & 1)) {
3440       strcpy(pword, ""); passlen=1; 
3441     }
3442
3443     if (Protocol <= PROTOCOL_COREPLUS) {
3444       set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
3445       CVAL(outbuf,smb_com) = SMBtcon;
3446       setup_pkt(outbuf);
3447
3448       p = smb_buf(outbuf);
3449       *p++ = 0x04;
3450       strcpy(p, service);
3451       p = skip_string(p,1);
3452       *p++ = 0x04;
3453       memcpy(p,pword,passlen);
3454       p += passlen;
3455       *p++ = 0x04;
3456       strcpy(p, dev);
3457     }
3458     else {
3459       set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
3460       CVAL(outbuf,smb_com) = SMBtconX;
3461       setup_pkt(outbuf);
3462   
3463       SSVAL(outbuf,smb_vwv0,0xFF);
3464       SSVAL(outbuf,smb_vwv3,passlen);
3465   
3466       p = smb_buf(outbuf);
3467       memcpy(p,pword,passlen);
3468       p += passlen;
3469       strcpy(p,service);
3470       p = skip_string(p,1);
3471       strcpy(p,dev);
3472     }
3473   }
3474
3475   send_smb(Client,outbuf);
3476   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3477
3478   /* trying again with a blank password */
3479   if (CVAL(inbuf,smb_rcls) != 0 && 
3480       (int)strlen(pass) > 0 && 
3481       !doencrypt &&
3482       Protocol >= PROTOCOL_LANMAN1)
3483     {
3484       DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
3485       strcpy(pass,"");
3486       goto again2;
3487     }  
3488
3489   if (CVAL(inbuf,smb_rcls) != 0)
3490     {
3491       DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
3492       DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
3493       DEBUG(0,("Some servers insist that these be in uppercase\n"));
3494       if (was_null)
3495         {
3496           free(inbuf);
3497           free(outbuf);
3498         }
3499       return(False);
3500     }
3501   
3502
3503   if (Protocol <= PROTOCOL_COREPLUS) {
3504     max_xmit = SVAL(inbuf,smb_vwv0);
3505
3506     cnum = SVAL(inbuf,smb_vwv1);
3507   }
3508   else {
3509     max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
3510     if (max_xmit <= 0)
3511       max_xmit = BUFFER_SIZE - 4;
3512
3513     cnum = SVAL(inbuf,smb_tid);
3514   }
3515
3516   DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
3517
3518   if (was_null)
3519     {
3520       free(inbuf);
3521       free(outbuf);
3522     }
3523   return True;
3524 }
3525
3526
3527 /****************************************************************************
3528 send a logout command
3529 ****************************************************************************/
3530 static void send_logout(void )
3531 {
3532   pstring inbuf,outbuf;
3533
3534   bzero(outbuf,smb_size);
3535   set_message(outbuf,0,0,True);
3536   CVAL(outbuf,smb_com) = SMBtdis;
3537   SSVAL(outbuf,smb_tid,cnum);
3538   setup_pkt(outbuf);
3539
3540   send_smb(Client,outbuf);
3541   receive_smb(Client,inbuf,SHORT_TIMEOUT);
3542
3543   if (CVAL(inbuf,smb_rcls) != 0)
3544     {
3545       DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
3546     }
3547
3548   
3549 #ifdef STATS
3550   stats_report();
3551 #endif
3552   exit(0);
3553 }
3554
3555
3556
3557 /****************************************************************************
3558 call a remote api
3559 ****************************************************************************/
3560 static BOOL call_api(int prcnt,int drcnt,
3561                      int mprcnt,int mdrcnt,
3562                      int *rprcnt,int *rdrcnt,
3563                      char *param,char *data,
3564                      char **rparam,char **rdata)
3565 {
3566   static char *inbuf=NULL;
3567   static char *outbuf=NULL;
3568
3569   if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3570   if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3571
3572   send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
3573                      data,param,NULL,
3574                      drcnt,prcnt,0,
3575                      mdrcnt,mprcnt,0);
3576
3577   return (receive_trans_response(inbuf,SMBtrans,
3578                                  rdrcnt,rprcnt,
3579                                  rdata,rparam));
3580 }
3581
3582 /****************************************************************************
3583   send a SMB trans or trans2 request
3584   ****************************************************************************/
3585 static BOOL send_trans_request(char *outbuf,int trans,
3586                                char *name,int fid,int flags,
3587                                char *data,char *param,uint16 *setup,
3588                                int ldata,int lparam,int lsetup,
3589                                int mdata,int mparam,int msetup)
3590 {
3591   int i;
3592   int this_ldata,this_lparam;
3593   int tot_data=0,tot_param=0;
3594   char *outdata,*outparam;
3595   pstring inbuf;
3596   char *p;
3597
3598   this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
3599   this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
3600
3601   bzero(outbuf,smb_size);
3602   set_message(outbuf,14+lsetup,0,True);
3603   CVAL(outbuf,smb_com) = trans;
3604   SSVAL(outbuf,smb_tid,cnum);
3605   setup_pkt(outbuf);
3606
3607   outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
3608   outdata = outparam+this_lparam;
3609
3610   /* primary request */
3611   SSVAL(outbuf,smb_tpscnt,lparam);      /* tpscnt */
3612   SSVAL(outbuf,smb_tdscnt,ldata);       /* tdscnt */
3613   SSVAL(outbuf,smb_mprcnt,mparam);      /* mprcnt */
3614   SSVAL(outbuf,smb_mdrcnt,mdata);       /* mdrcnt */
3615   SCVAL(outbuf,smb_msrcnt,msetup);      /* msrcnt */
3616   SSVAL(outbuf,smb_flags,flags);        /* flags */
3617   SIVAL(outbuf,smb_timeout,0);          /* timeout */
3618   SSVAL(outbuf,smb_pscnt,this_lparam);  /* pscnt */
3619   SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
3620   SSVAL(outbuf,smb_dscnt,this_ldata);   /* dscnt */
3621   SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
3622   SCVAL(outbuf,smb_suwcnt,lsetup);      /* suwcnt */
3623   for (i=0;i<lsetup;i++)                /* setup[] */
3624     SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
3625   p = smb_buf(outbuf);
3626   if (trans==SMBtrans)
3627     strcpy(p,name);                     /* name[] */
3628   else
3629     {
3630       *p++ = 0;                         /* put in a null smb_name */
3631       *p++ = 'D'; *p++ = ' ';           /* this was added because OS/2 does it */
3632     }
3633   if (this_lparam)                      /* param[] */
3634     memcpy(outparam,param,this_lparam);
3635   if (this_ldata)                       /* data[] */
3636     memcpy(outdata,data,this_ldata);
3637   set_message(outbuf,14+lsetup,         /* wcnt, bcc */
3638               PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3639
3640   show_msg(outbuf);
3641   send_smb(Client,outbuf);
3642
3643   if (this_ldata < ldata || this_lparam < lparam)
3644     {
3645       /* receive interim response */
3646       if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
3647         {
3648           DEBUG(0,("%s request failed (%s)\n",
3649                    trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
3650           return(False);
3651         }      
3652
3653       tot_data = this_ldata;
3654       tot_param = this_lparam;
3655
3656       while (tot_data < ldata || tot_param < lparam)
3657     {
3658           this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
3659           this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
3660
3661           set_message(outbuf,trans==SMBtrans?8:9,0,True);
3662           CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
3663
3664           outparam = smb_buf(outbuf);
3665           outdata = outparam+this_lparam;
3666
3667           /* secondary request */
3668           SSVAL(outbuf,smb_tpscnt,lparam);      /* tpscnt */
3669           SSVAL(outbuf,smb_tdscnt,ldata);       /* tdscnt */
3670           SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
3671           SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
3672           SSVAL(outbuf,smb_spsdisp,tot_param);  /* psdisp */
3673           SSVAL(outbuf,smb_sdscnt,this_ldata);  /* dscnt */
3674           SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
3675           SSVAL(outbuf,smb_sdsdisp,tot_data);   /* dsdisp */
3676           if (trans==SMBtrans2)
3677             SSVAL(outbuf,smb_sfid,fid);         /* fid */
3678           if (this_lparam)                      /* param[] */
3679             memcpy(outparam,param,this_lparam);
3680           if (this_ldata)                       /* data[] */
3681             memcpy(outdata,data,this_ldata);
3682           set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
3683                       PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3684
3685           show_msg(outbuf);
3686           send_smb(Client,outbuf);
3687
3688           tot_data += this_ldata;
3689           tot_param += this_lparam;
3690         }
3691     }
3692
3693     return(True);
3694 }
3695
3696 /****************************************************************************
3697 try and browse available connections on a host
3698 ****************************************************************************/
3699 static BOOL browse_host(BOOL sort)
3700 {
3701 #ifdef NOSTRCASECMP
3702 /* If strcasecmp is already defined, remove it. */
3703 #ifdef strcasecmp
3704 #undef strcasecmp
3705 #endif /* strcasecmp */
3706 #define strcasecmp StrCaseCmp
3707 #endif /* NOSTRCASECMP */
3708
3709   extern int strcasecmp();
3710
3711   char *rparam = NULL;
3712   char *rdata = NULL;
3713   char *p;
3714   int rdrcnt,rprcnt;
3715   pstring param;
3716   int count = -1;
3717
3718   /* now send a SMBtrans command with api RNetShareEnum */
3719   p = param;
3720   SSVAL(p,0,0); /* api number */
3721   p += 2;
3722   strcpy(p,"WrLeh");
3723   p = skip_string(p,1);
3724   strcpy(p,"B13BWz");
3725   p = skip_string(p,1);
3726   SSVAL(p,0,1);
3727   SSVAL(p,2,BUFFER_SIZE);
3728   p += 4;
3729
3730   if (call_api(PTR_DIFF(p,param),0,
3731                1024,BUFFER_SIZE,
3732                &rprcnt,&rdrcnt,
3733                param,NULL,
3734                &rparam,&rdata))
3735     {
3736       int res = SVAL(rparam,0);
3737       int converter=SVAL(rparam,2);
3738       int i;
3739       BOOL long_share_name=False;
3740       
3741       if (res == 0)
3742         {
3743           count=SVAL(rparam,4);
3744           p = rdata;
3745
3746           if (count > 0)
3747             {
3748               printf("\n\tSharename      Type      Comment\n");
3749               printf("\t---------      ----      -------\n");
3750             }
3751
3752           if (sort)
3753             qsort(p,count,20,QSORT_CAST strcasecmp);
3754
3755           for (i=0;i<count;i++)
3756             {
3757               char *sname = p;
3758               int type = SVAL(p,14);
3759               int comment_offset = IVAL(p,16) & 0xFFFF;
3760               fstring typestr;
3761               *typestr=0;
3762
3763               switch (type)
3764                 {
3765                 case STYPE_DISKTREE:
3766                   strcpy(typestr,"Disk"); break;
3767                 case STYPE_PRINTQ:
3768                   strcpy(typestr,"Printer"); break;           
3769                 case STYPE_DEVICE:
3770                   strcpy(typestr,"Device"); break;
3771                 case STYPE_IPC:
3772                   strcpy(typestr,"IPC"); break;      
3773                 }
3774
3775               printf("\t%-15.15s%-10.10s%s\n",
3776                      sname,
3777                      typestr,
3778                      comment_offset?rdata+comment_offset-converter:"");
3779           
3780               if (strlen(sname)>8) long_share_name=True;
3781           
3782               p += 20;
3783             }
3784
3785           if (long_share_name) {
3786             printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3787           }
3788         }
3789     }
3790   
3791   if (rparam) free(rparam);
3792   if (rdata) free(rdata);
3793
3794   return(count>0);
3795 }
3796
3797
3798 /****************************************************************************
3799 get some server info
3800 ****************************************************************************/
3801 static void server_info()
3802 {
3803   char *rparam = NULL;
3804   char *rdata = NULL;
3805   char *p;
3806   int rdrcnt,rprcnt;
3807   pstring param;
3808
3809   bzero(param,sizeof(param));
3810
3811   p = param;
3812   SSVAL(p,0,63);                /* NetServerGetInfo()? */
3813   p += 2;
3814   strcpy(p,"WrLh");
3815   p = skip_string(p,1);
3816   strcpy(p,"zzzBBzz");
3817   p = skip_string(p,1);
3818   SSVAL(p,0,10); /* level 10 */
3819   SSVAL(p,2,1000);
3820   p += 6;
3821
3822   if (call_api(PTR_DIFF(p,param),0,
3823                6,1000,
3824                &rprcnt,&rdrcnt,
3825                param,NULL,
3826                &rparam,&rdata))
3827     {
3828       int res = SVAL(rparam,0);
3829       int converter=SVAL(rparam,2);
3830
3831       if (res == 0)
3832         {
3833       p = rdata;
3834
3835       printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3836              rdata+SVAL(p,0)-converter,
3837              rdata+SVAL(p,4)-converter,
3838              rdata+SVAL(p,8)-converter,
3839              rdata+SVAL(p,14)-converter);
3840     }
3841     }
3842
3843   if (rparam) free(rparam);
3844   if (rdata) free(rdata);
3845
3846   return;
3847 }
3848
3849
3850 /****************************************************************************
3851 try and browse available connections on a host
3852 ****************************************************************************/
3853 static BOOL list_servers(char *wk_grp)
3854 {
3855   char *rparam = NULL;
3856   char *rdata = NULL;
3857   int rdrcnt,rprcnt;
3858   char *p,*svtype_p;
3859   pstring param;
3860   int uLevel = 1;
3861   int count = 0;
3862   BOOL ok = False;
3863   BOOL generic_request = False;
3864
3865
3866   if (strequal(wk_grp,"WORKGROUP")) {
3867     /* we won't specify a workgroup */
3868     generic_request = True;
3869   } 
3870
3871   /* now send a SMBtrans command with api ServerEnum? */
3872   p = param;
3873   SSVAL(p,0,0x68); /* api number */
3874   p += 2;
3875
3876   strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3877   p = skip_string(p,1);
3878
3879   strcpy(p,"B16BBDz");
3880
3881   p = skip_string(p,1);
3882   SSVAL(p,0,uLevel);
3883   SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3884   p += 4;
3885
3886   svtype_p = p;
3887   p += 4;
3888
3889   if (!generic_request) {
3890     strcpy(p, wk_grp);
3891     p = skip_string(p,1);
3892   }
3893
3894   /* first ask for a list of servers in this workgroup */
3895   SIVAL(svtype_p,0,SV_TYPE_ALL);
3896
3897   if (call_api(PTR_DIFF(p+4,param),0,
3898                8,BUFFER_SIZE - SAFETY_MARGIN,
3899                &rprcnt,&rdrcnt,
3900                param,NULL,
3901                &rparam,&rdata))
3902     {
3903       int res = SVAL(rparam,0);
3904       int converter=SVAL(rparam,2);
3905       int i;
3906
3907       if (res == 0) {   
3908         char *p2 = rdata;
3909         count=SVAL(rparam,4);
3910
3911         if (count > 0) {
3912           printf("\n\nThis machine has a browse list:\n");
3913           printf("\n\tServer               Comment\n");
3914           printf("\t---------            -------\n");
3915         }
3916         
3917         for (i=0;i<count;i++) {
3918           char *sname = p2;
3919           int comment_offset = IVAL(p2,22) & 0xFFFF;
3920           printf("\t%-16.16s     %s\n",
3921                  sname,
3922                  comment_offset?rdata+comment_offset-converter:"");
3923
3924           ok=True;
3925           p2 += 26;
3926         }
3927       }
3928     }
3929
3930   if (rparam) {free(rparam); rparam = NULL;}
3931   if (rdata) {free(rdata); rdata = NULL;}
3932
3933   /* now ask for a list of workgroups */
3934   SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3935
3936   if (call_api(PTR_DIFF(p+4,param),0,
3937                8,BUFFER_SIZE - SAFETY_MARGIN,
3938                &rprcnt,&rdrcnt,
3939                param,NULL,
3940                &rparam,&rdata))
3941     {
3942       int res = SVAL(rparam,0);
3943       int converter=SVAL(rparam,2);
3944       int i;
3945
3946       if (res == 0) {
3947         char *p2 = rdata;
3948         count=SVAL(rparam,4);
3949
3950         if (count > 0) {
3951           printf("\n\nThis machine has a workgroup list:\n");
3952           printf("\n\tWorkgroup            Master\n");
3953           printf("\t---------            -------\n");
3954         }
3955         
3956         for (i=0;i<count;i++) {
3957           char *sname = p2;
3958           int comment_offset = IVAL(p2,22) & 0xFFFF;
3959           printf("\t%-16.16s     %s\n",
3960                  sname,
3961                  comment_offset?rdata+comment_offset-converter:"");
3962           
3963           ok=True;
3964           p2 += 26;
3965         }
3966       }
3967     }
3968
3969   if (rparam) free(rparam);
3970   if (rdata) free(rdata);
3971
3972   return(ok);
3973 }
3974
3975
3976 /* This defines the commands supported by this client */
3977 struct
3978 {
3979   char *name;
3980   void (*fn)();
3981   char *description;
3982 } commands[] = 
3983 {
3984   {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3985   {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3986   {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3987   {"cd",cmd_cd,"[directory] change/report the remote directory"},
3988   {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3989   {"get",cmd_get,"<remote name> [local name] get a file"},
3990   {"mget",cmd_mget,"<mask> get all the matching files"},
3991   {"put",cmd_put,"<local name> [remote name] put a file"},
3992   {"mput",cmd_mput,"<mask> put all matching files"},
3993   {"rename",cmd_rename,"<src> <dest> rename some files"},
3994   {"more",cmd_more,"<remote name> view a remote file with your pager"},  
3995   {"mask",cmd_select,"<mask> mask all filenames against this"},
3996   {"del",cmd_del,"<mask> delete all matching files"},
3997   {"rm",cmd_del,"<mask> delete all matching files"},
3998   {"mkdir",cmd_mkdir,"<directory> make a directory"},
3999   {"md",cmd_mkdir,"<directory> make a directory"},
4000   {"rmdir",cmd_rmdir,"<directory> remove a directory"},
4001   {"rd",cmd_rmdir,"<directory> remove a directory"},
4002   {"pq",cmd_p_queue_4,"enumerate the print queue"},
4003   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},  
4004   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},  
4005   {"translate",cmd_translate,"toggle text translation for printing"},  
4006   {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},  
4007   {"print",cmd_print,"<file name> print a file"},
4008   {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
4009   {"queue",cmd_queue,"show the print queue"},
4010   {"qinfo",cmd_qinfo,"show print queue information"},
4011   {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
4012   {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
4013   {"quit",send_logout,"logoff the server"},
4014   {"q",send_logout,"logoff the server"},
4015   {"exit",send_logout,"logoff the server"},
4016   {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
4017   {"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"},
4018   {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
4019   {"blocksize",cmd_block,"blocksize <number> (default 20)" },
4020   {"tarmode",cmd_tarmode,
4021      "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
4022   {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
4023   {"help",cmd_help,"[command] give help on a command"},
4024   {"?",cmd_help,"[command] give help on a command"},
4025   {"!",NULL,"run a shell command on the local system"},
4026   {"",NULL,NULL}
4027 };
4028
4029
4030 /*******************************************************************
4031   lookup a command string in the list of commands, including 
4032   abbreviations
4033   ******************************************************************/
4034 static int process_tok(fstring tok)
4035 {
4036   int i = 0, matches = 0;
4037   int cmd=0;
4038   int tok_len = strlen(tok);
4039   
4040   while (commands[i].fn != NULL)
4041     {
4042       if (strequal(commands[i].name,tok))
4043         {
4044           matches = 1;
4045           cmd = i;
4046           break;
4047         }
4048       else if (strnequal(commands[i].name, tok, tok_len+1))
4049         {
4050           matches++;
4051           cmd = i;
4052         }
4053       i++;
4054     }
4055   
4056   if (matches == 0)
4057     return(-1);
4058   else if (matches == 1)
4059     return(cmd);
4060   else
4061     return(-2);
4062 }
4063
4064 /****************************************************************************
4065 help
4066 ****************************************************************************/
4067 void cmd_help(void)
4068 {
4069   int i=0,j;
4070   fstring buf;
4071
4072   if (next_token(NULL,buf,NULL))
4073     {
4074       if ((i = process_tok(buf)) >= 0)
4075         DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));                   
4076     }
4077   else
4078     while (commands[i].description)
4079       {
4080         for (j=0; commands[i].description && (j<5); j++) {
4081           DEBUG(0,("%-15s",commands[i].name));
4082           i++;
4083         }
4084         DEBUG(0,("\n"));
4085       }
4086 }
4087
4088 /****************************************************************************
4089 open the client sockets
4090 ****************************************************************************/
4091 static BOOL open_sockets(int port )
4092 {
4093   static int last_port;
4094   char *host;
4095   pstring service2;
4096   extern int Client;
4097 #ifdef USENMB
4098   BOOL failed = True;
4099 #endif
4100
4101   if (port == 0) port=last_port;
4102   last_port=port;
4103
4104   strupper(service);
4105
4106   if (*desthost)
4107     {
4108       host = desthost;
4109     }
4110   else
4111     {
4112       strcpy(service2,service);
4113       host = strtok(service2,"\\/");
4114       if (!host) {
4115         DEBUG(0,("Badly formed host name\n"));
4116         return(False);
4117       }
4118       strcpy(desthost,host);
4119     }
4120
4121   if (*myname == 0) {
4122       get_myname(myname,NULL);
4123   }
4124   strupper(myname);
4125
4126   DEBUG(3,("Opening sockets\n"));
4127
4128   if (!have_ip)
4129     {
4130       struct hostent *hp;
4131
4132       if ((hp = Get_Hostbyname(host))) {
4133         putip((char *)&dest_ip,(char *)hp->h_addr);
4134         failed = False;
4135       } else {
4136 #ifdef USENMB
4137         /* Try and resolve the name with the netbios server */
4138         int             bcast;
4139
4140         if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
4141                                     interpret_addr(lp_socket_address()))) != -1) {
4142           set_socket_options(bcast, "SO_BROADCAST");
4143
4144           if (name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
4145                          &dest_ip,0)) {
4146             failed = False;
4147           }
4148           close (bcast);
4149         }
4150 #endif
4151         if (failed) {
4152           DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
4153           return False;
4154         }
4155       }
4156     }
4157
4158   Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
4159   if (Client == -1)
4160     return False;
4161
4162   DEBUG(3,("Connected\n"));
4163   
4164   set_socket_options(Client,user_socket_options);  
4165   
4166   return True;
4167 }
4168
4169 /****************************************************************************
4170 wait for keyboard activity, swallowing network packets
4171 ****************************************************************************/
4172 #ifdef CLIX
4173 static char wait_keyboard(char *buffer)
4174 #else
4175 static void wait_keyboard(char *buffer)
4176 #endif
4177 {
4178   fd_set fds;
4179   int selrtn;
4180   struct timeval timeout;
4181   
4182 #ifdef CLIX
4183   int delay = 0;
4184 #endif
4185   
4186   while (1) 
4187     {
4188       extern int Client;
4189       FD_ZERO(&fds);
4190       FD_SET(Client,&fds);
4191 #ifndef CLIX
4192       FD_SET(fileno(stdin),&fds);
4193 #endif
4194
4195       timeout.tv_sec = 20;
4196       timeout.tv_usec = 0;
4197 #ifdef CLIX
4198       timeout.tv_sec = 0;
4199 #endif
4200       selrtn = sys_select(&fds,&timeout);
4201       
4202 #ifndef CLIX
4203       if (FD_ISSET(fileno(stdin),&fds))
4204         return;
4205 #else
4206       {
4207         char ch;
4208         int readret;
4209
4210     set_blocking(fileno(stdin), False); 
4211         readret = read_data( fileno(stdin), &ch, 1);
4212         set_blocking(fileno(stdin), True);
4213         if (readret == -1)
4214           {
4215             if (errno != EAGAIN)
4216               {
4217                 /* should crash here */
4218                 DEBUG(1,("readchar stdin failed\n"));
4219               }
4220           }
4221         else if (readret != 0)
4222           {
4223             return ch;
4224           }
4225       }
4226 #endif
4227       if (FD_ISSET(Client,&fds))
4228         receive_smb(Client,buffer,0);
4229       
4230 #ifdef CLIX
4231       delay++;
4232       if (delay > 100000)
4233         {
4234           delay = 0;
4235           chkpath("\\",False);
4236         }
4237 #else
4238       chkpath("\\",False);
4239 #endif
4240     }  
4241 }
4242
4243
4244 /****************************************************************************
4245 close and open the connection again
4246 ****************************************************************************/
4247 BOOL reopen_connection(char *inbuf,char *outbuf)
4248 {
4249   static int open_count=0;
4250
4251   open_count++;
4252
4253   if (open_count>5) return(False);
4254
4255   DEBUG(1,("Trying to re-open connection\n"));
4256
4257   set_message(outbuf,0,0,True);
4258   SCVAL(outbuf,smb_com,SMBtdis);
4259   SSVAL(outbuf,smb_tid,cnum);
4260   setup_pkt(outbuf);
4261
4262   send_smb(Client,outbuf);
4263   receive_smb(Client,inbuf,SHORT_TIMEOUT);
4264
4265   close_sockets();
4266   if (!open_sockets(0)) return(False);
4267
4268   return(send_login(inbuf,outbuf,True,True));
4269 }
4270
4271 /****************************************************************************
4272   process commands from the client
4273 ****************************************************************************/
4274 static BOOL process(char *base_directory)
4275 {
4276   extern FILE *dbf;
4277   pstring line;
4278   char *cmd;
4279
4280   char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4281   char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4282
4283   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
4284     return(False);
4285   
4286   bzero(OutBuffer,smb_size);
4287
4288   if (!send_login(InBuffer,OutBuffer,True,True))
4289     return(False);
4290
4291   if (*base_directory) do_cd(base_directory);
4292
4293   cmd = cmdstr;
4294   if (cmd[0] != '\0') while (cmd[0] != '\0')
4295     {
4296       char *p;
4297       fstring tok;
4298       int i;
4299
4300       if ((p = strchr(cmd, ';')) == 0)
4301         {
4302           strncpy(line, cmd, 999);
4303           line[1000] = '\0';
4304           cmd += strlen(cmd);
4305         }
4306       else
4307         {
4308           if (p - cmd > 999) p = cmd + 999;
4309           strncpy(line, cmd, p - cmd);
4310           line[p - cmd] = '\0';
4311           cmd = p + 1;
4312         }
4313
4314       /* input language code to internal one */
4315       CNV_INPUT (line);
4316       
4317       /* and get the first part of the command */
4318       {
4319         char *ptr = line;
4320         if (!next_token(&ptr,tok,NULL)) continue;
4321       }
4322
4323       if ((i = process_tok(tok)) >= 0)
4324         commands[i].fn(InBuffer,OutBuffer);
4325       else if (i == -2)
4326         DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4327       else
4328         DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4329     }
4330   else while (!feof(stdin))
4331     {
4332       fstring tok;
4333       int i;
4334
4335       bzero(OutBuffer,smb_size);
4336
4337       /* display a prompt */
4338       DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
4339       fflush(dbf);
4340
4341 #ifdef CLIX
4342       line[0] = wait_keyboard(InBuffer);
4343       /* this might not be such a good idea... */
4344       if ( line[0] == EOF)
4345         break;
4346 #else
4347       wait_keyboard(InBuffer);
4348 #endif
4349   
4350       /* and get a response */
4351 #ifdef CLIX
4352       fgets( &line[1],999, stdin);
4353 #else
4354       if (!fgets(line,1000,stdin))
4355         break;
4356 #endif
4357
4358       /* input language code to internal one */
4359       CNV_INPUT (line);
4360
4361       /* special case - first char is ! */
4362       if (*line == '!')
4363         {
4364           system(line + 1);
4365           continue;
4366         }
4367       
4368       /* and get the first part of the command */
4369       {
4370         char *ptr = line;
4371         if (!next_token(&ptr,tok,NULL)) continue;
4372       }
4373
4374       if ((i = process_tok(tok)) >= 0)
4375         commands[i].fn(InBuffer,OutBuffer);
4376       else if (i == -2)
4377         DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4378       else
4379         DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4380     }
4381   
4382   send_logout();
4383   return(True);
4384 }
4385
4386
4387 /****************************************************************************
4388 usage on the program
4389 ****************************************************************************/
4390 static void usage(char *pname)
4391 {
4392   DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
4393            pname));
4394
4395 #ifdef KANJI
4396   DEBUG(0,("[-t termcode] "));
4397 #endif /* KANJI */
4398
4399   DEBUG(0,("\nVersion %s\n",VERSION));
4400   DEBUG(0,("\t-p port               listen on the specified port\n"));
4401   DEBUG(0,("\t-d debuglevel         set the debuglevel\n"));
4402   DEBUG(0,("\t-l log basename.      Basename for log/debug files\n"));
4403   DEBUG(0,("\t-n netbios name.      Use this name as my netbios name\n"));
4404   DEBUG(0,("\t-N                    don't ask for a password\n"));
4405   DEBUG(0,("\t-P                    connect to service as a printer\n"));
4406   DEBUG(0,("\t-M host               send a winpopup message to the host\n"));
4407   DEBUG(0,("\t-m max protocol       set the max protocol level\n"));
4408   DEBUG(0,("\t-L host               get a list of shares available on a host\n"));
4409   DEBUG(0,("\t-I dest IP            use this IP to connect to\n"));
4410   DEBUG(0,("\t-E                    write messages to stderr instead of stdout\n"));
4411   DEBUG(0,("\t-U username           set the network username\n"));
4412   DEBUG(0,("\t-W workgroup          set the workgroup name\n"));
4413   DEBUG(0,("\t-c command string     execute semicolon separated commands\n"));
4414 #ifdef KANJI
4415   DEBUG(0,("\t-t terminal code      terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
4416 #endif /* KANJI */
4417   DEBUG(0,("\t-T<c|x>IXgbNa          command line tar\n"));
4418   DEBUG(0,("\t-D directory          start from directory\n"));
4419   DEBUG(0,("\n"));
4420 }
4421
4422 /****************************************************************************
4423   main program
4424 ****************************************************************************/
4425  int main(int argc,char *argv[])
4426 {
4427   fstring base_directory;
4428   char *pname = argv[0];
4429   int port = SMB_PORT;
4430   int opt;
4431   extern FILE *dbf;
4432   extern char *optarg;
4433   extern int optind;
4434   pstring query_host;
4435   BOOL message = False;
4436   extern char tar_type;
4437   static pstring servicesf = CONFIGFILE;
4438
4439   *query_host = 0;
4440   *base_directory = 0;
4441
4442   DEBUGLEVEL = 2;
4443
4444   setup_logging(pname,True);
4445
4446   TimeInit();
4447   charset_initialise();
4448
4449   pid = getpid();
4450   uid = getuid();
4451   gid = getgid();
4452   mid = pid + 100;
4453   myumask = umask(0);
4454   umask(myumask);
4455
4456   if (getenv("USER"))
4457     {
4458       strcpy(username,getenv("USER"));
4459       strupper(username);
4460     }
4461
4462   if (*username == 0 && getenv("LOGNAME"))
4463     {
4464       strcpy(username,getenv("LOGNAME"));
4465       strupper(username);
4466     }
4467
4468   if (argc < 2)
4469     {
4470       usage(pname);
4471       exit(1);
4472     }
4473   
4474   if (*argv[1] != '-')
4475     {
4476
4477       strcpy(service,argv[1]);  
4478       /* Convert any '/' characters in the service name to '\' characters */
4479       string_replace( service, '/','\\');
4480       argc--;
4481       argv++;
4482
4483       if (count_chars(service,'\\') < 3)
4484         {
4485           usage(pname);
4486           printf("\n%s: Not enough '\\' characters in service\n",service);
4487           exit(1);
4488         }
4489
4490 /*
4491       if (count_chars(service,'\\') > 3)
4492         {
4493           usage(pname);
4494           printf("\n%s: Too many '\\' characters in service\n",service);
4495           exit(1);
4496         }
4497         */
4498
4499       if (argc > 1 && (*argv[1] != '-'))
4500         {
4501           got_pass = True;
4502           strcpy(password,argv[1]);  
4503           memset(argv[1],'X',strlen(argv[1]));
4504           argc--;
4505           argv++;
4506         }
4507     }
4508
4509 #ifdef KANJI
4510   setup_term_code (KANJI);
4511 #endif
4512   while ((opt = 
4513           getopt(argc, argv,"s:B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
4514     switch (opt)
4515       {
4516       case 'm':
4517         max_protocol = interpret_protocol(optarg,max_protocol);
4518         break;
4519       case 'O':
4520         strcpy(user_socket_options,optarg);
4521         break;  
4522       case 'M':
4523         name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
4524         strcpy(desthost,optarg);
4525         strupper(desthost);
4526         message = True;
4527         break;
4528       case 'B':
4529         iface_set_default(NULL,optarg,NULL);
4530         break;
4531       case 'D':
4532         strcpy(base_directory,optarg);
4533         break;
4534       case 'T':
4535         if (!tar_parseargs(argc, argv, optarg, optind)) {
4536           usage(pname);
4537           exit(1);
4538         }
4539         break;
4540       case 'i':
4541         strcpy(scope,optarg);
4542         break;
4543       case 'L':
4544         got_pass = True;
4545         strcpy(query_host,optarg);
4546         break;
4547       case 'U':
4548         {
4549           char *p;
4550         strcpy(username,optarg);
4551         if ((p=strchr(username,'%')))
4552           {
4553             *p = 0;
4554             strcpy(password,p+1);
4555             got_pass = True;
4556             memset(strchr(optarg,'%')+1,'X',strlen(password));
4557           }
4558         }
4559             
4560         break;
4561       case 'W':
4562         strcpy(workgroup,optarg);
4563         break;
4564       case 'E':
4565         dbf = stderr;
4566         break;
4567       case 'I':
4568         {
4569           dest_ip = *interpret_addr2(optarg);
4570           if (zero_ip(dest_ip)) exit(1);
4571           have_ip = True;
4572         }
4573         break;
4574       case 'n':
4575         strcpy(myname,optarg);
4576         break;
4577       case 'N':
4578         got_pass = True;
4579         break;
4580       case 'P':
4581         connect_as_printer = True;
4582         break;
4583       case 'd':
4584         if (*optarg == 'A')
4585           DEBUGLEVEL = 10000;
4586         else
4587           DEBUGLEVEL = atoi(optarg);
4588         break;
4589       case 'l':
4590         sprintf(debugf,"%s.client",optarg);
4591         break;
4592       case 'p':
4593         port = atoi(optarg);
4594         break;
4595       case 'c':
4596         cmdstr = optarg;
4597         got_pass = True;
4598         break;
4599       case 'h':
4600         usage(pname);
4601         exit(0);
4602         break;
4603       case 's':
4604         strcpy(servicesf, optarg);
4605         break;
4606       case 't':
4607 #ifdef KANJI
4608         if (!setup_term_code (optarg)) {
4609             DEBUG(0, ("%s: unknown terminal code name\n", optarg));
4610             usage (pname);
4611             exit (1);
4612         }
4613 #endif
4614         break;
4615       default:
4616         usage(pname);
4617         exit(1);
4618       }
4619
4620   if (!tar_type && !*query_host && !*service && !message)
4621     {
4622       usage(pname);
4623       exit(1);
4624     }
4625
4626
4627   DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
4628
4629   if(!get_myname(myhostname,NULL))
4630   {
4631     DEBUG(0,("Failed to get my hostname.\n"));
4632   }
4633
4634   if (!lp_load(servicesf,True)) {
4635     fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
4636   }
4637
4638   if (*workgroup == 0)
4639     strcpy(workgroup,lp_workgroup());
4640
4641   load_interfaces();
4642   get_myname(*myname?NULL:myname,NULL);  
4643   strupper(myname);
4644
4645   if (tar_type) {
4646     recurse=True;
4647
4648     if (open_sockets(port)) {
4649         char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4650         char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4651         int ret;
4652
4653         if ((InBuffer == NULL) || (OutBuffer == NULL)) 
4654           return(1);
4655
4656         bzero(OutBuffer,smb_size);
4657         if (!send_login(InBuffer,OutBuffer,True,True))
4658           return(False);
4659
4660         if (*base_directory) do_cd(base_directory);
4661
4662         ret=process_tar(InBuffer, OutBuffer);
4663
4664         send_logout();
4665         close_sockets();
4666         return(ret);
4667     } else
4668       return(1);
4669   }
4670   
4671   if (*query_host)
4672     {
4673       int ret = 0;
4674       sprintf(service,"\\\\%s\\IPC$",query_host);
4675       strupper(service);
4676       connect_as_ipc = True;
4677       if (open_sockets(port))
4678         {
4679 #if 0
4680           *username = 0;
4681 #endif
4682           if (!send_login(NULL,NULL,True,True))
4683             return(1);
4684
4685           server_info();
4686           if (!browse_host(True)) {
4687             sleep(1);
4688             browse_host(True);
4689           }
4690           if (!list_servers(workgroup)) {
4691             sleep(1);
4692             list_servers(workgroup);
4693           }
4694
4695           send_logout();
4696           close_sockets();
4697         }
4698
4699       return(ret);
4700     }
4701
4702   if (message)
4703     {
4704       int ret = 0;
4705       if (open_sockets(port))
4706         {
4707           pstring inbuf,outbuf;
4708           bzero(outbuf,smb_size);
4709           if (!send_session_request(inbuf,outbuf))
4710             return(1);
4711
4712           send_message(inbuf,outbuf);
4713
4714           close_sockets();
4715         }
4716
4717       return(ret);
4718     }
4719
4720   if (open_sockets(port))
4721     {
4722       if (!process(base_directory))
4723         {
4724           close_sockets();
4725           return(1);
4726         }
4727       close_sockets();
4728     }
4729   else
4730     return(1);
4731
4732   return(0);
4733 }
4734
4735
4736 /* error code stuff - put together by Merik Karman
4737    merik@blackadder.dsh.oz.au */
4738
4739 typedef struct
4740 {
4741   char *name;
4742   int code;
4743   char *message;
4744 } err_code_struct;
4745
4746 /* Dos Error Messages */
4747 err_code_struct dos_msgs[] = {
4748   {"ERRbadfunc",1,"Invalid function."},
4749   {"ERRbadfile",2,"File not found."},
4750   {"ERRbadpath",3,"Directory invalid."},
4751   {"ERRnofids",4,"No file descriptors available"},
4752   {"ERRnoaccess",5,"Access denied."},
4753   {"ERRbadfid",6,"Invalid file handle."},
4754   {"ERRbadmcb",7,"Memory control blocks destroyed."},
4755   {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
4756   {"ERRbadmem",9,"Invalid memory block address."},
4757   {"ERRbadenv",10,"Invalid environment."},
4758   {"ERRbadformat",11,"Invalid format."},
4759   {"ERRbadaccess",12,"Invalid open mode."},
4760   {"ERRbaddata",13,"Invalid data."},
4761   {"ERR",14,"reserved."},
4762   {"ERRbaddrive",15,"Invalid drive specified."},
4763   {"ERRremcd",16,"A Delete Directory request attempted  to  remove  the  server's  current directory."},
4764   {"ERRdiffdevice",17,"Not same device."},
4765   {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
4766   {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing  FIDs  on the file."},
4767   {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an  invalid mode,  or an Unlock requested attempted to remove a lock held by another process."},
4768   {"ERRfilexists",80,"The file named in a Create Directory, Make  New  File  or  Link  request already exists."},
4769   {"ERRbadpipe",230,"Pipe invalid."},
4770   {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
4771   {"ERRpipeclosing",232,"Pipe close in progress."},
4772   {"ERRnotconnected",233,"No process on other end of pipe."},
4773   {"ERRmoredata",234,"There is more data to be returned."},
4774   {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
4775   {NULL,-1,NULL}};
4776
4777 /* Server Error Messages */
4778 err_code_struct server_msgs[] = {
4779   {"ERRerror",1,"Non-specific error code."},
4780   {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
4781   {"ERRbadtype",3,"reserved."},
4782   {"ERRaccess",4,"The requester does not have  the  necessary  access  rights  within  the specified  context for the requested function. The context is defined by the TID or the UID."},
4783   {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
4784   {"ERRinvnetname",6,"Invalid network name in tree connect."},
4785   {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection."},
4786   {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
4787   {"ERRqtoobig",50,"Print queue full -- no space."},
4788   {"ERRqeof",51,"EOF on print queue dump."},
4789   {"ERRinvpfid",52,"Invalid print file FID."},
4790   {"ERRsmbcmd",64,"The server did not recognize the command received."},
4791   {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
4792   {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid  combination of values."},
4793   {"ERRreserved",68,"reserved."},
4794   {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute."},
4795   {"ERRreserved",70,"reserved."},
4796   {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
4797   {"ERRpaused",81,"Server is paused."},
4798   {"ERRmsgoff",82,"Not receiving messages."},
4799   {"ERRnoroom",83,"No room to buffer message."},
4800   {"ERRrmuns",87,"Too many remote user names."},
4801   {"ERRtimeout",88,"Operation timed out."},
4802   {"ERRnoresource",89,"No resources currently available for request."},
4803   {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
4804   {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
4805   {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
4806   {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
4807   {"ERRcontmpx",252,"Continue in MPX mode."},
4808   {"ERRreserved",253,"reserved."},
4809   {"ERRreserved",254,"reserved."},
4810   {"ERRnosupport",0xFFFF,"Function not supported."},
4811   {NULL,-1,NULL}};
4812
4813 /* Hard Error Messages */
4814 err_code_struct hard_msgs[] = {
4815   {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
4816   {"ERRbadunit",20,"Unknown unit."},
4817   {"ERRnotready",21,"Drive not ready."},
4818   {"ERRbadcmd",22,"Unknown command."},
4819   {"ERRdata",23,"Data error (CRC)."},
4820   {"ERRbadreq",24,"Bad request structure length."},
4821   {"ERRseek",25 ,"Seek error."},
4822   {"ERRbadmedia",26,"Unknown media type."},
4823   {"ERRbadsector",27,"Sector not found."},
4824   {"ERRnopaper",28,"Printer out of paper."},
4825   {"ERRwrite",29,"Write fault."},
4826   {"ERRread",30,"Read fault."},
4827   {"ERRgeneral",31,"General failure."},
4828   {"ERRbadshare",32,"An open conflicts with an existing open."},
4829   {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
4830   {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
4831   {"ERRFCBUnavail",35,"No FCBs are available to process request."},
4832   {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
4833   {NULL,-1,NULL}};
4834
4835
4836 struct
4837 {
4838   int code;
4839   char *class;
4840   err_code_struct *err_msgs;
4841 } err_classes[] = { 
4842   {0,"SUCCESS",NULL},
4843   {0x01,"ERRDOS",dos_msgs},
4844   {0x02,"ERRSRV",server_msgs},
4845   {0x03,"ERRHRD",hard_msgs},
4846   {0x04,"ERRXOS",NULL},
4847   {0xE1,"ERRRMX1",NULL},
4848   {0xE2,"ERRRMX2",NULL},
4849   {0xE3,"ERRRMX3",NULL},
4850   {0xFF,"ERRCMD",NULL},
4851   {-1,NULL,NULL}};
4852
4853
4854 /****************************************************************************
4855 return a SMB error string from a SMB buffer
4856 ****************************************************************************/
4857 char *smb_errstr(char *inbuf)
4858 {
4859   static pstring ret;
4860   int class = CVAL(inbuf,smb_rcls);
4861   int num = SVAL(inbuf,smb_err);
4862   int i,j;
4863
4864   for (i=0;err_classes[i].class;i++)
4865     if (err_classes[i].code == class)
4866       {
4867         if (err_classes[i].err_msgs)
4868           {
4869             err_code_struct *err = err_classes[i].err_msgs;
4870             for (j=0;err[j].name;j++)
4871               if (num == err[j].code)
4872                 {
4873                   if (DEBUGLEVEL > 0)
4874                     sprintf(ret,"%s - %s (%s)",err_classes[i].class,
4875                             err[j].name,err[j].message);
4876                   else
4877                     sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
4878                   return ret;
4879                 }
4880           }
4881
4882         sprintf(ret,"%s - %d",err_classes[i].class,num);
4883         return ret;
4884       }
4885   
4886   sprintf(ret,"Error: Unknown error (%d,%d)",class,num);
4887   return(ret);
4888 }