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