- fix client for pathworks 4 access
[Samba.git] / source / client / client.c
blobcdf33a14b3da424e870b2aaab9a827299d528c16
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB client
5 Copyright (C) Andrew Tridgell 1994-1995
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.
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.
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.
22 #ifdef SYSLOG
23 #undef SYSLOG
24 #endif
26 #include "includes.h"
28 #ifndef REGISTER
29 #define REGISTER 0
30 #endif
32 pstring cur_dir = "\\";
33 pstring cd_path = "";
34 pstring service="";
35 pstring desthost="";
36 extern pstring myname;
37 pstring password = "";
38 pstring username="";
39 pstring workgroup=WORKGROUP;
40 char *cmdstr="";
41 BOOL got_pass = False;
42 BOOL connect_as_printer = False;
43 BOOL connect_as_ipc = False;
44 extern struct in_addr ipzero;
46 char cryptkey[8];
47 BOOL doencrypt=False;
49 extern pstring user_socket_options;
51 /* 30 second timeout on most commands */
52 #define CLIENT_TIMEOUT (30*1000)
53 #define SHORT_TIMEOUT (5*1000)
55 /* value for unused fid field in trans2 secondary request */
56 #define FID_UNUSED (0xFFFF)
58 int name_type = 0x20;
60 int max_protocol = PROTOCOL_NT1;
63 time_t newer_than = 0;
64 int archive_level = 0;
66 extern pstring debugf;
67 extern int DEBUGLEVEL;
69 BOOL translation = False;
72 static BOOL send_trans_request(char *outbuf,int trans,
73 char *name,int fid,int flags,
74 char *data,char *param,uint16 *setup,
75 int ldata,int lparam,int lsetup,
76 int mdata,int mparam,int msetup);
77 static BOOL receive_trans_response(char *inbuf,int trans,
78 int *data_len,int *param_len,
79 char **data,char **param);
80 static int interpret_long_filename(int level,char *p,file_info *finfo);
81 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir);
82 static int interpret_short_filename(char *p,file_info *finfo);
83 static BOOL call_api(int prcnt,int drcnt,
84 int mprcnt,int mdrcnt,
85 int *rprcnt,int *rdrcnt,
86 char *param,char *data,
87 char **rparam,char **rdata);
90 /* clitar bits insert */
91 extern int blocksize;
92 extern BOOL tar_inc;
93 extern BOOL tar_reset;
94 /* clitar bits end */
97 int cnum = 0;
98 int pid = 0;
99 int gid = 0;
100 int uid = 0;
101 int mid = 0;
102 int myumask = 0755;
104 int max_xmit = BUFFER_SIZE;
106 extern pstring scope;
108 BOOL prompt = True;
110 int printmode = 1;
112 BOOL recurse = False;
113 BOOL lowercase = False;
115 BOOL have_ip = False;
117 struct in_addr dest_ip;
119 #define SEPARATORS " \t\n\r"
121 BOOL abort_mget = True;
123 extern int Protocol;
125 BOOL readbraw_supported = False;
126 BOOL writebraw_supported = False;
128 pstring fileselection = "";
130 extern file_info def_finfo;
132 /* timing globals */
133 int get_total_size = 0;
134 int get_total_time_ms = 0;
135 int put_total_size = 0;
136 int put_total_time_ms = 0;
139 extern int Client;
141 #define USENMB
143 #ifdef KANJI
144 extern int coding_system;
145 #define CNV_LANG(s) (coding_system == DOSV_CODE?s:dos_to_unix(s, False))
146 #define CNV_INPUT(s) (coding_system == DOSV_CODE?s:unix_to_dos(s, True))
147 static BOOL
148 setup_term_code (char *code)
150 int new;
151 new = interpret_coding_system (code, UNKNOWN_CODE);
152 if (new != UNKNOWN_CODE) {
153 coding_system = new;
154 return True;
156 return False;
158 #else
159 #define CNV_LANG(s) dos2unix_format(s,False)
160 #define CNV_INPUT(s) unix2dos_format(s,True)
161 #endif
163 /****************************************************************************
164 setup basics in a outgoing packet
165 ****************************************************************************/
166 void setup_pkt(char *outbuf)
168 SSVAL(outbuf,smb_pid,pid);
169 SSVAL(outbuf,smb_uid,uid);
170 SSVAL(outbuf,smb_mid,mid);
171 if (Protocol > PROTOCOL_COREPLUS)
173 SCVAL(outbuf,smb_flg,0x8);
174 SSVAL(outbuf,smb_flg2,0x1);
178 /****************************************************************************
179 write to a local file with CR/LF->LF translation if appropriate. return the
180 number taken from the buffer. This may not equal the number written.
181 ****************************************************************************/
182 static int writefile(int f, char *b, int n)
184 int i;
186 if (!translation)
187 return(write(f,b,n));
189 i = 0;
190 while (i < n)
192 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
194 b++;i++;
196 if (write(f, b, 1) != 1)
198 break;
200 b++;
201 i++;
204 return(i);
207 /****************************************************************************
208 read from a file with LF->CR/LF translation if appropriate. return the
209 number read. read approx n bytes.
210 ****************************************************************************/
211 static int readfile(char *b, int size, int n, FILE *f)
213 int i;
214 int c;
216 if (!translation || (size != 1))
217 return(fread(b,size,n,f));
219 i = 0;
220 while (i < n)
222 if ((c = getc(f)) == EOF)
224 break;
227 if (c == '\n') /* change all LFs to CR/LF */
229 b[i++] = '\r';
230 n++;
233 b[i++] = c;
236 return(i);
240 /****************************************************************************
241 read from a file with print translation. return the number read. read approx n
242 bytes.
243 ****************************************************************************/
244 static int printread(FILE *f,char *b,int n)
246 int i;
248 i = readfile(b,1, n-1,f);
249 #if FORMFEED
250 if (feof(f) && i>0)
251 b[i++] = '\014';
252 #endif
254 return(i);
257 /****************************************************************************
258 check for existance of a dir
259 ****************************************************************************/
260 static BOOL chkpath(char *path,BOOL report)
262 fstring path2;
263 pstring inbuf,outbuf;
264 char *p;
266 strcpy(path2,path);
267 trim_string(path2,NULL,"\\");
268 if (!*path2) *path2 = '\\';
270 bzero(outbuf,smb_size);
271 set_message(outbuf,0,4 + strlen(path2),True);
272 SCVAL(outbuf,smb_com,SMBchkpth);
273 SSVAL(outbuf,smb_tid,cnum);
274 setup_pkt(outbuf);
276 p = smb_buf(outbuf);
277 *p++ = 4;
278 strcpy(p,path2);
280 send_smb(Client,outbuf);
281 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
283 if (report && CVAL(inbuf,smb_rcls) != 0)
284 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
286 return(CVAL(inbuf,smb_rcls) == 0);
290 /****************************************************************************
291 send a message
292 ****************************************************************************/
293 static void send_message(char *inbuf,char *outbuf)
295 int total_len = 0;
297 char *p;
298 int grp_id;
300 /* send a SMBsendstrt command */
301 bzero(outbuf,smb_size);
302 set_message(outbuf,0,0,True);
303 CVAL(outbuf,smb_com) = SMBsendstrt;
304 SSVAL(outbuf,smb_tid,cnum);
306 p = smb_buf(outbuf);
307 *p++ = 4;
308 strcpy(p,username);
309 p = skip_string(p,1);
310 *p++ = 4;
311 strcpy(p,desthost);
312 p = skip_string(p,1);
314 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
316 send_smb(Client,outbuf);
319 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
321 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
322 return;
325 grp_id = SVAL(inbuf,smb_vwv0);
327 printf("Connected. Type your message, ending it with a Control-D\n");
329 while (!feof(stdin) && total_len < 1600)
331 int maxlen = MIN(1600 - total_len,127);
332 pstring msg;
333 int l=0;
334 int c;
336 bzero(msg,smb_size);
338 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
340 if (c == '\n')
341 msg[l++] = '\r';
342 msg[l] = c;
345 CVAL(outbuf,smb_com) = SMBsendtxt;
347 set_message(outbuf,1,l+3,True);
349 SSVAL(outbuf,smb_vwv0,grp_id);
351 p = smb_buf(outbuf);
352 *p = 1;
353 SSVAL(p,1,l);
354 memcpy(p+3,msg,l);
356 send_smb(Client,outbuf);
359 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
361 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
362 return;
365 total_len += l;
368 if (total_len >= 1600)
369 printf("the message was truncated to 1600 bytes ");
370 else
371 printf("sent %d bytes ",total_len);
373 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
375 CVAL(outbuf,smb_com) = SMBsendend;
376 set_message(outbuf,1,0,False);
377 SSVAL(outbuf,smb_vwv0,grp_id);
379 send_smb(Client,outbuf);
382 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
384 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
385 return;
391 /****************************************************************************
392 check the space on a device
393 ****************************************************************************/
394 static void do_dskattr(void)
396 pstring inbuf,outbuf;
398 bzero(outbuf,smb_size);
399 set_message(outbuf,0,0,True);
400 CVAL(outbuf,smb_com) = SMBdskattr;
401 SSVAL(outbuf,smb_tid,cnum);
402 setup_pkt(outbuf);
404 send_smb(Client,outbuf);
405 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
407 if (CVAL(inbuf,smb_rcls) != 0)
408 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
410 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
411 SVAL(inbuf,smb_vwv0),
412 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
413 SVAL(inbuf,smb_vwv3)));
416 /****************************************************************************
417 show cd/pwd
418 ****************************************************************************/
419 static void cmd_pwd(void)
421 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
422 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
426 /****************************************************************************
427 change directory - inner section
428 ****************************************************************************/
429 static void do_cd(char *newdir)
431 char *p = newdir;
432 pstring saved_dir;
433 pstring dname;
435 /* Save the current directory in case the
436 new directory is invalid */
437 strcpy(saved_dir, cur_dir);
438 if (*p == '\\')
439 strcpy(cur_dir,p);
440 else
441 strcat(cur_dir,p);
442 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
443 strcat(cur_dir, "\\");
445 dos_clean_name(cur_dir);
446 strcpy(dname,cur_dir);
447 strcat(cur_dir,"\\");
448 dos_clean_name(cur_dir);
450 if (!strequal(cur_dir,"\\"))
451 if (!chkpath(dname,True))
452 strcpy(cur_dir,saved_dir);
454 strcpy(cd_path,cur_dir);
457 /****************************************************************************
458 change directory
459 ****************************************************************************/
460 static void cmd_cd(char *inbuf,char *outbuf)
462 fstring buf;
464 if (next_token(NULL,buf,NULL))
465 do_cd(buf);
466 else
467 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
471 /****************************************************************************
472 display info about a file
473 ****************************************************************************/
474 static void display_finfo(file_info *finfo)
476 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
477 DEBUG(0,(" %-30s%7.7s%10d %s",
478 CNV_LANG(finfo->name),
479 attrib_string(finfo->mode),
480 finfo->size,
481 asctime(LocalTime(&t))));
485 /****************************************************************************
486 do a directory listing, calling fn on each file found. Use the TRANSACT2
487 call for long filenames
488 ****************************************************************************/
489 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
491 int max_matches = 512;
492 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
493 char *p;
494 pstring mask;
495 file_info finfo;
496 int i;
497 char *dirlist = NULL;
498 int dirlist_len = 0;
499 int total_received = 0;
500 BOOL First = True;
501 char *resp_data=NULL;
502 char *resp_param=NULL;
503 int resp_data_len = 0;
504 int resp_param_len=0;
506 int ff_resume_key = 0;
507 int ff_searchcount=0;
508 int ff_eos=0;
509 int ff_lastname=0;
510 int ff_dir_handle=0;
511 int loop_count = 0;
513 uint16 setup;
514 pstring param;
516 strcpy(mask,Mask);
518 while (ff_eos == 0)
520 loop_count++;
521 if (loop_count > 200)
523 DEBUG(0,("ERROR: Looping in FIND_NEXT??\n"));
524 break;
527 if (First)
529 setup = TRANSACT2_FINDFIRST;
530 SSVAL(param,0,attribute); /* attribute */
531 SSVAL(param,2,max_matches); /* max count */
532 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
533 SSVAL(param,6,info_level);
534 SIVAL(param,8,0);
535 strcpy(param+12,mask);
537 else
539 setup = TRANSACT2_FINDNEXT;
540 SSVAL(param,0,ff_dir_handle);
541 SSVAL(param,2,max_matches); /* max count */
542 SSVAL(param,4,info_level);
543 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
544 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
545 strcpy(param+12,mask);
547 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
548 ff_dir_handle,ff_resume_key,ff_lastname,mask));
550 /* ??? original code added 1 pad byte after param */
552 send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
553 NULL,param,&setup,
554 0,12+strlen(mask)+1,1,
555 BUFFER_SIZE,10,0);
557 if (!receive_trans_response(inbuf,SMBtrans2,
558 &resp_data_len,&resp_param_len,
559 &resp_data,&resp_param))
561 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
562 break;
565 /* parse out some important return info */
566 p = resp_param;
567 if (First)
569 ff_dir_handle = SVAL(p,0);
570 ff_searchcount = SVAL(p,2);
571 ff_eos = SVAL(p,4);
572 ff_lastname = SVAL(p,8);
574 else
576 ff_searchcount = SVAL(p,0);
577 ff_eos = SVAL(p,2);
578 ff_lastname = SVAL(p,6);
581 if (ff_searchcount == 0)
582 break;
584 /* point to the data bytes */
585 p = resp_data;
587 /* we might need the lastname for continuations */
588 if (ff_lastname > 0)
590 switch(info_level)
592 case 260:
593 ff_resume_key =0;
594 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
595 /* strcpy(mask,p+ff_lastname+94); */
596 break;
597 case 1:
598 strcpy(mask,p + ff_lastname + 1);
599 ff_resume_key = 0;
600 break;
603 else
604 strcpy(mask,"");
606 /* and add them to the dirlist pool */
607 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
609 if (!dirlist)
611 DEBUG(0,("Failed to expand dirlist\n"));
612 break;
615 /* put in a length for the last entry, to ensure we can chain entries
616 into the next packet */
618 char *p2;
619 for (p2=p,i=0;i<(ff_searchcount-1);i++)
620 p2 += interpret_long_filename(info_level,p2,NULL);
621 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
624 /* grab the data for later use */
625 memcpy(dirlist+dirlist_len,p,resp_data_len);
626 dirlist_len += resp_data_len;
628 total_received += ff_searchcount;
630 if (resp_data) free(resp_data); resp_data = NULL;
631 if (resp_param) free(resp_param); resp_param = NULL;
633 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
634 ff_searchcount,ff_eos,ff_resume_key));
636 First = False;
639 if (!fn)
640 for (p=dirlist,i=0;i<total_received;i++)
642 p += interpret_long_filename(info_level,p,&finfo);
643 display_finfo(&finfo);
646 for (p=dirlist,i=0;i<total_received;i++)
648 p += interpret_long_filename(info_level,p,&finfo);
649 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
652 /* free up the dirlist buffer */
653 if (dirlist) free(dirlist);
654 return(total_received);
658 /****************************************************************************
659 do a directory listing, calling fn on each file found
660 ****************************************************************************/
661 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
663 char *p;
664 int received = 0;
665 BOOL first = True;
666 char status[21];
667 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
668 int num_received = 0;
669 int i;
670 char *dirlist = NULL;
671 pstring mask;
672 file_info finfo;
674 finfo = def_finfo;
676 bzero(status,21);
678 strcpy(mask,Mask);
680 while (1)
682 bzero(outbuf,smb_size);
683 if (first)
684 set_message(outbuf,2,5 + strlen(mask),True);
685 else
686 set_message(outbuf,2,5 + 21,True);
688 #if FFIRST
689 if (Protocol >= PROTOCOL_LANMAN1)
690 CVAL(outbuf,smb_com) = SMBffirst;
691 else
692 #endif
693 CVAL(outbuf,smb_com) = SMBsearch;
695 SSVAL(outbuf,smb_tid,cnum);
696 setup_pkt(outbuf);
698 SSVAL(outbuf,smb_vwv0,num_asked);
699 SSVAL(outbuf,smb_vwv1,attribute);
701 p = smb_buf(outbuf);
702 *p++ = 4;
704 if (first)
705 strcpy(p,mask);
706 else
707 strcpy(p,"");
708 p += strlen(p) + 1;
710 *p++ = 5;
711 if (first)
712 SSVAL(p,0,0);
713 else
715 SSVAL(p,0,21);
716 p += 2;
717 memcpy(p,status,21);
720 send_smb(Client,outbuf);
721 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
723 received = SVAL(inbuf,smb_vwv0);
725 DEBUG(5,("dir received %d\n",received));
727 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
729 if (received <= 0) break;
731 first = False;
733 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
735 if (!dirlist)
736 return 0;
738 p = smb_buf(inbuf) + 3;
740 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
741 p,received*DIR_STRUCT_SIZE);
743 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
745 num_received += received;
747 if (CVAL(inbuf,smb_rcls) != 0) break;
750 #if FFIRST
751 if (!first && Protocol >= PROTOCOL_LANMAN1)
753 bzero(outbuf,smb_size);
754 CVAL(outbuf,smb_com) = SMBfclose;
756 SSVAL(outbuf,smb_tid,cnum);
757 setup_pkt(outbuf);
759 p = smb_buf(outbuf);
760 *p++ = 4;
762 strcpy(p,"");
763 p += strlen(p) + 1;
765 *p++ = 5;
766 SSVAL(p,0,21);
767 p += 2;
768 memcpy(p,status,21);
770 send_smb(Client,outbuf);
771 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
773 if (CVAL(inbuf,smb_rcls) != 0)
774 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
776 #endif
778 if (!fn)
779 for (p=dirlist,i=0;i<num_received;i++)
781 p += interpret_short_filename(p,&finfo);
782 display_finfo(&finfo);
785 for (p=dirlist,i=0;i<num_received;i++)
787 p += interpret_short_filename(p,&finfo);
788 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
791 if (dirlist) free(dirlist);
792 return(num_received);
797 /****************************************************************************
798 do a directory listing, calling fn on each file found
799 ****************************************************************************/
800 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
802 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
803 if (Protocol >= PROTOCOL_LANMAN2)
805 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
806 return;
809 expand_mask(Mask,False);
810 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
811 return;
814 /*******************************************************************
815 decide if a file should be operated on
816 ********************************************************************/
817 static BOOL do_this_one(file_info *finfo)
819 if (finfo->mode & aDIR) return(True);
821 if (newer_than && finfo->mtime < newer_than)
822 return(False);
824 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
825 return(False);
827 return(True);
831 /*****************************************************************************
832 Convert a character pointer in a call_api() response to a form we can use.
833 This function contains code to prevent core dumps if the server returns
834 invalid data.
835 *****************************************************************************/
836 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
838 if( datap == 0 ) /* turn NULL pointers */
839 { /* into zero length strings */
840 return "";
842 else
844 unsigned int offset = datap - converter;
846 if( offset < 0 || offset >= rdrcnt )
848 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%u, rdrcnt=%d>", datap, converter, (unsigned)rdata, rdrcnt));
849 return "<ERROR>";
851 else
853 return &rdata[offset];
858 /****************************************************************************
859 interpret a short filename structure
860 The length of the structure is returned
861 ****************************************************************************/
862 static int interpret_short_filename(char *p,file_info *finfo)
864 finfo->mode = CVAL(p,21);
866 /* this date is converted to GMT by make_unix_date */
867 finfo->ctime = make_unix_date(p+22);
868 finfo->mtime = finfo->atime = finfo->ctime;
869 finfo->size = IVAL(p,26);
870 strcpy(finfo->name,p+30);
872 return(DIR_STRUCT_SIZE);
875 /****************************************************************************
876 interpret a long filename structure - this is mostly guesses at the moment
877 The length of the structure is returned
878 The structure of a long filename depends on the info level. 260 is used
879 by NT and 2 is used by OS/2
880 ****************************************************************************/
881 static int interpret_long_filename(int level,char *p,file_info *finfo)
883 if (finfo)
884 memcpy(finfo,&def_finfo,sizeof(*finfo));
886 switch (level)
888 case 1: /* OS/2 understands this */
889 if (finfo)
891 /* these dates are converted to GMT by make_unix_date */
892 finfo->ctime = make_unix_date2(p+4);
893 finfo->atime = make_unix_date2(p+8);
894 finfo->mtime = make_unix_date2(p+12);
895 finfo->size = IVAL(p,16);
896 finfo->mode = CVAL(p,24);
897 strcpy(finfo->name,p+27);
899 return(28 + CVAL(p,26));
901 case 2: /* this is what OS/2 uses mostly */
902 if (finfo)
904 /* these dates are converted to GMT by make_unix_date */
905 finfo->ctime = make_unix_date2(p+4);
906 finfo->atime = make_unix_date2(p+8);
907 finfo->mtime = make_unix_date2(p+12);
908 finfo->size = IVAL(p,16);
909 finfo->mode = CVAL(p,24);
910 strcpy(finfo->name,p+31);
912 return(32 + CVAL(p,30));
914 /* levels 3 and 4 are untested */
915 case 3:
916 if (finfo)
918 /* these dates are probably like the other ones */
919 finfo->ctime = make_unix_date2(p+8);
920 finfo->atime = make_unix_date2(p+12);
921 finfo->mtime = make_unix_date2(p+16);
922 finfo->size = IVAL(p,20);
923 finfo->mode = CVAL(p,28);
924 strcpy(finfo->name,p+33);
926 return(SVAL(p,4)+4);
928 case 4:
929 if (finfo)
931 /* these dates are probably like the other ones */
932 finfo->ctime = make_unix_date2(p+8);
933 finfo->atime = make_unix_date2(p+12);
934 finfo->mtime = make_unix_date2(p+16);
935 finfo->size = IVAL(p,20);
936 finfo->mode = CVAL(p,28);
937 strcpy(finfo->name,p+37);
939 return(SVAL(p,4)+4);
941 case 260: /* NT uses this, but also accepts 2 */
942 if (finfo)
944 int ret = SVAL(p,0);
945 int namelen;
946 p += 4; /* next entry offset */
947 p += 4; /* fileindex */
949 /* these dates appear to arrive in a weird way. It seems to
950 be localtime plus the serverzone given in the initial
951 connect. This is GMT when DST is not in effect and one
952 hour from GMT otherwise. Can this really be right??
954 I suppose this could be called kludge-GMT. Is is the GMT
955 you get by using the current DST setting on a different
956 localtime. It will be cheap to calculate, I suppose, as
957 no DST tables will be needed */
959 finfo->ctime = interpret_long_date(p); p += 8;
960 finfo->atime = interpret_long_date(p); p += 8;
961 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
962 finfo->size = IVAL(p,0); p += 8;
963 p += 8; /* alloc size */
964 finfo->mode = CVAL(p,0); p += 4;
965 namelen = IVAL(p,0); p += 4;
966 p += 4; /* EA size */
967 p += 2; /* short name len? */
968 p += 24; /* short name? */
969 StrnCpy(finfo->name,p,namelen);
970 return(ret);
972 return(SVAL(p,0));
975 DEBUG(1,("Unknown long filename format %d\n",level));
976 return(SVAL(p,0));
982 /****************************************************************************
983 act on the files in a dir listing
984 ****************************************************************************/
985 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
988 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
989 !mask_match(finfo->name,fileselection,False,False)) &&
990 !(recurse_dir && (strequal(finfo->name,".") ||
991 strequal(finfo->name,".."))))
993 if (recurse_dir && (finfo->mode & aDIR))
995 pstring mask2;
996 pstring sav_dir;
997 strcpy(sav_dir,cur_dir);
998 strcat(cur_dir,finfo->name);
999 strcat(cur_dir,"\\");
1000 strcpy(mask2,cur_dir);
1002 if (!fn)
1003 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1005 strcat(mask2,"*");
1007 if (longdir)
1008 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);
1009 else
1010 do_dir(inbuf,outbuf,mask2,attribute,fn,True);
1012 strcpy(cur_dir,sav_dir);
1014 else
1016 if (fn && do_this_one(finfo))
1017 fn(finfo);
1023 /****************************************************************************
1024 receive a SMB trans or trans2 response allocating the necessary memory
1025 ****************************************************************************/
1026 static BOOL receive_trans_response(char *inbuf,int trans,
1027 int *data_len,int *param_len,
1028 char **data,char **param)
1030 int total_data=0;
1031 int total_param=0;
1032 int this_data,this_param;
1034 *data_len = *param_len = 0;
1036 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1037 show_msg(inbuf);
1039 /* sanity check */
1040 if (CVAL(inbuf,smb_com) != trans)
1042 DEBUG(0,("Expected %s response, got command 0x%02x\n",
1043 trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
1044 return(False);
1046 if (CVAL(inbuf,smb_rcls) != 0)
1047 return(False);
1049 /* parse out the lengths */
1050 total_data = SVAL(inbuf,smb_tdrcnt);
1051 total_param = SVAL(inbuf,smb_tprcnt);
1053 /* allocate it */
1054 *data = Realloc(*data,total_data);
1055 *param = Realloc(*param,total_param);
1057 while (1)
1059 this_data = SVAL(inbuf,smb_drcnt);
1060 this_param = SVAL(inbuf,smb_prcnt);
1061 if (this_data)
1062 memcpy(*data + SVAL(inbuf,smb_drdisp),
1063 smb_base(inbuf) + SVAL(inbuf,smb_droff),
1064 this_data);
1065 if (this_param)
1066 memcpy(*param + SVAL(inbuf,smb_prdisp),
1067 smb_base(inbuf) + SVAL(inbuf,smb_proff),
1068 this_param);
1069 *data_len += this_data;
1070 *param_len += this_param;
1072 /* parse out the total lengths again - they can shrink! */
1073 total_data = SVAL(inbuf,smb_tdrcnt);
1074 total_param = SVAL(inbuf,smb_tprcnt);
1076 if (total_data <= *data_len && total_param <= *param_len)
1077 break;
1079 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1080 show_msg(inbuf);
1082 /* sanity check */
1083 if (CVAL(inbuf,smb_com) != trans)
1085 DEBUG(0,("Expected %s response, got command 0x%02x\n",
1086 trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
1087 return(False);
1089 if (CVAL(inbuf,smb_rcls) != 0)
1090 return(False);
1093 return(True);
1097 /****************************************************************************
1098 get a directory listing
1099 ****************************************************************************/
1100 static void cmd_dir(char *inbuf,char *outbuf)
1102 int attribute = aDIR | aSYSTEM | aHIDDEN;
1103 pstring mask;
1104 fstring buf;
1105 char *p=buf;
1107 strcpy(mask,cur_dir);
1108 if(mask[strlen(mask)-1]!='\\')
1109 strcat(mask,"\\");
1111 if (next_token(NULL,buf,NULL))
1113 if (*p == '\\')
1114 strcpy(mask,p);
1115 else
1116 strcat(mask,p);
1118 else {
1119 strcat(mask,"*");
1122 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1124 do_dskattr();
1129 /****************************************************************************
1130 get a file from rname to lname
1131 ****************************************************************************/
1132 static void do_get(char *rname,char *lname,file_info *finfo1)
1134 int handle=0,fnum;
1135 uint32 nread=0;
1136 char *p;
1137 BOOL newhandle = False;
1138 char *inbuf,*outbuf;
1139 file_info finfo;
1140 BOOL close_done = False;
1141 BOOL ignore_close_error = False;
1142 char *dataptr=NULL;
1143 int datalen=0;
1145 struct timeval tp_start;
1146 GetTimeOfDay(&tp_start);
1148 if (finfo1)
1149 finfo = *finfo1;
1150 else
1151 finfo = def_finfo;
1153 if (lowercase)
1154 strlower(lname);
1157 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1158 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1160 if (!inbuf || !outbuf)
1162 DEBUG(0,("out of memory\n"));
1163 return;
1166 bzero(outbuf,smb_size);
1167 set_message(outbuf,15,1 + strlen(rname),True);
1169 CVAL(outbuf,smb_com) = SMBopenX;
1170 SSVAL(outbuf,smb_tid,cnum);
1171 setup_pkt(outbuf);
1173 SSVAL(outbuf,smb_vwv0,0xFF);
1174 SSVAL(outbuf,smb_vwv2,1);
1175 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1176 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1177 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1178 SSVAL(outbuf,smb_vwv8,1);
1180 p = smb_buf(outbuf);
1181 strcpy(p,rname);
1182 p = skip_string(p,1);
1184 /* do a chained openX with a readX? */
1185 #if 1
1186 if (finfo.size > 0)
1188 DEBUG(3,("Chaining readX wth openX\n"));
1189 SSVAL(outbuf,smb_vwv0,SMBreadX);
1190 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1191 bzero(p,200);
1192 p -= smb_wct;
1193 SSVAL(p,smb_wct,10);
1194 SSVAL(p,smb_vwv0,0xFF);
1195 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1196 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1197 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1199 #endif
1201 if(!strcmp(lname,"-"))
1202 handle = fileno(stdout);
1203 else
1205 handle = creat(lname,0644);
1206 newhandle = True;
1208 if (handle < 0)
1210 DEBUG(0,("Error opening local file %s\n",lname));
1211 free(inbuf);free(outbuf);
1212 return;
1215 send_smb(Client,outbuf);
1216 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1218 if (CVAL(inbuf,smb_rcls) != 0)
1220 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1221 SVAL(inbuf,smb_err) == ERRnoresource &&
1222 reopen_connection(inbuf,outbuf))
1224 do_get(rname,lname,finfo1);
1225 return;
1227 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1228 if(newhandle)
1229 close(handle);
1230 free(inbuf);free(outbuf);
1231 return;
1234 strcpy(finfo.name,rname);
1236 if (!finfo1)
1238 finfo.mode = SVAL(inbuf,smb_vwv3);
1239 /* these times arrive as LOCAL time, using the DST offset
1240 corresponding to that time, we convert them to GMT */
1241 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1242 finfo.atime = finfo.ctime = finfo.mtime;
1243 finfo.size = IVAL(inbuf,smb_vwv6);
1246 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1248 fnum = SVAL(inbuf,smb_vwv2);
1250 /* we might have got some data from a chained readX */
1251 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1253 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1254 datalen = SVAL(p,smb_vwv5);
1255 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1257 else
1259 dataptr = NULL;
1260 datalen = 0;
1264 DEBUG(2,("getting file %s of size %d bytes as %s ",
1265 CNV_LANG(finfo.name),
1266 finfo.size,
1267 lname));
1269 while (nread < finfo.size && !close_done)
1271 int method = -1;
1272 static BOOL can_chain_close = True;
1274 p=NULL;
1276 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1278 /* 3 possible read types. readbraw if a large block is required.
1279 readX + close if not much left and read if neither is supported */
1281 /* we might have already read some data from a chained readX */
1282 if (dataptr && datalen>0)
1283 method=3;
1285 /* if we can finish now then readX+close */
1286 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1287 ((finfo.size - nread) <
1288 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1289 method = 0;
1291 /* if we support readraw then use that */
1292 if (method<0 && readbraw_supported)
1293 method = 1;
1295 /* if we can then use readX */
1296 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1297 method = 2;
1299 switch (method)
1301 /* use readX */
1302 case 0:
1303 case 2:
1304 if (method == 0)
1305 close_done = True;
1307 /* use readX + close */
1308 bzero(outbuf,smb_size);
1309 set_message(outbuf,10,0,True);
1310 CVAL(outbuf,smb_com) = SMBreadX;
1311 SSVAL(outbuf,smb_tid,cnum);
1312 setup_pkt(outbuf);
1314 if (close_done)
1316 CVAL(outbuf,smb_vwv0) = SMBclose;
1317 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1319 else
1320 CVAL(outbuf,smb_vwv0) = 0xFF;
1322 SSVAL(outbuf,smb_vwv2,fnum);
1323 SIVAL(outbuf,smb_vwv3,nread);
1324 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1325 SSVAL(outbuf,smb_vwv6,0);
1326 SIVAL(outbuf,smb_vwv7,0);
1327 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1329 if (close_done)
1331 p = smb_buf(outbuf);
1332 bzero(p,9);
1334 CVAL(p,0) = 3;
1335 SSVAL(p,1,fnum);
1336 SIVALS(p,3,-1);
1338 /* now set the total packet length */
1339 smb_setlen(outbuf,smb_len(outbuf)+9);
1342 send_smb(Client,outbuf);
1343 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1345 if (CVAL(inbuf,smb_rcls) != 0)
1347 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1348 break;
1351 if (close_done &&
1352 SVAL(inbuf,smb_vwv0) != SMBclose)
1354 /* NOTE: WfWg sometimes just ignores the chained
1355 command! This seems to break the spec? */
1356 DEBUG(3,("Rejected chained close?\n"));
1357 close_done = False;
1358 can_chain_close = False;
1359 ignore_close_error = True;
1362 datalen = SVAL(inbuf,smb_vwv5);
1363 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1364 break;
1366 /* use readbraw */
1367 case 1:
1369 static int readbraw_size = BUFFER_SIZE;
1371 extern int Client;
1372 bzero(outbuf,smb_size);
1373 set_message(outbuf,8,0,True);
1374 CVAL(outbuf,smb_com) = SMBreadbraw;
1375 SSVAL(outbuf,smb_tid,cnum);
1376 setup_pkt(outbuf);
1377 SSVAL(outbuf,smb_vwv0,fnum);
1378 SIVAL(outbuf,smb_vwv1,nread);
1379 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1380 SSVAL(outbuf,smb_vwv4,0);
1381 SIVALS(outbuf,smb_vwv5,-1);
1382 send_smb(Client,outbuf);
1384 /* Now read the raw data into the buffer and write it */
1385 if(read_smb_length(Client,inbuf,0) == -1) {
1386 DEBUG(0,("Failed to read length in readbraw\n"));
1387 exit(1);
1390 /* Even though this is not an smb message, smb_len
1391 returns the generic length of an smb message */
1392 datalen = smb_len(inbuf);
1394 if (datalen == 0)
1396 /* we got a readbraw error */
1397 DEBUG(4,("readbraw error - reducing size\n"));
1398 readbraw_size = (readbraw_size * 9) / 10;
1400 if (readbraw_size < max_xmit)
1402 DEBUG(0,("disabling readbraw\n"));
1403 readbraw_supported = False;
1406 dataptr=NULL;
1407 continue;
1410 if(read_data(Client,inbuf,datalen) != datalen) {
1411 DEBUG(0,("Failed to read data in readbraw\n"));
1412 exit(1);
1414 dataptr = inbuf;
1416 break;
1418 case 3:
1419 /* we've already read some data with a chained readX */
1420 break;
1422 default:
1423 /* use plain read */
1424 bzero(outbuf,smb_size);
1425 set_message(outbuf,5,0,True);
1426 CVAL(outbuf,smb_com) = SMBread;
1427 SSVAL(outbuf,smb_tid,cnum);
1428 setup_pkt(outbuf);
1430 SSVAL(outbuf,smb_vwv0,fnum);
1431 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1432 SIVAL(outbuf,smb_vwv2,nread);
1433 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1435 send_smb(Client,outbuf);
1436 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1438 if (CVAL(inbuf,smb_rcls) != 0)
1440 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1441 break;
1444 datalen = SVAL(inbuf,smb_vwv0);
1445 dataptr = smb_buf(inbuf) + 3;
1446 break;
1449 if (writefile(handle,dataptr,datalen) != datalen)
1451 DEBUG(0,("Error writing local file\n"));
1452 break;
1455 nread += datalen;
1456 if (datalen == 0)
1458 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1459 break;
1462 dataptr=NULL;
1463 datalen=0;
1468 if (!close_done)
1470 bzero(outbuf,smb_size);
1471 set_message(outbuf,3,0,True);
1472 CVAL(outbuf,smb_com) = SMBclose;
1473 SSVAL(outbuf,smb_tid,cnum);
1474 setup_pkt(outbuf);
1476 SSVAL(outbuf,smb_vwv0,fnum);
1477 SIVALS(outbuf,smb_vwv1,-1);
1479 send_smb(Client,outbuf);
1480 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1482 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1484 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1485 if(newhandle)
1486 close(handle);
1487 free(inbuf);free(outbuf);
1488 return;
1492 if(newhandle)
1493 close(handle);
1495 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1496 bzero(outbuf,smb_size);
1497 set_message(outbuf,8,strlen(rname)+4,True);
1498 CVAL(outbuf,smb_com) = SMBsetatr;
1499 SSVAL(outbuf,smb_tid,cnum);
1500 setup_pkt(outbuf);
1501 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1502 SIVALS(outbuf,smb_vwv1,0);
1503 p = smb_buf(outbuf);
1504 *p++ = 4;
1505 strcpy(p,rname);
1506 p += strlen(p)+1;
1507 *p++ = 4;
1508 *p = 0;
1509 send_smb(Client,outbuf);
1510 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1514 struct timeval tp_end;
1515 int this_time;
1517 GetTimeOfDay(&tp_end);
1518 this_time =
1519 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1520 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1521 get_total_time_ms += this_time;
1522 get_total_size += finfo.size;
1524 DEBUG(2,("(%g kb/s) (average %g kb/s)\n",
1525 finfo.size / (1.024*this_time + 1.0e-4),
1526 get_total_size / (1.024*get_total_time_ms)));
1529 free(inbuf);free(outbuf);
1533 /****************************************************************************
1534 get a file
1535 ****************************************************************************/
1536 static void cmd_get(void)
1538 pstring lname;
1539 pstring rname;
1540 char *p;
1542 strcpy(rname,cur_dir);
1543 strcat(rname,"\\");
1545 p = rname + strlen(rname);
1547 if (!next_token(NULL,p,NULL)) {
1548 DEBUG(0,("get <filename>\n"));
1549 return;
1551 strcpy(lname,p);
1552 dos_clean_name(rname);
1554 next_token(NULL,lname,NULL);
1556 do_get(rname,lname,NULL);
1560 /****************************************************************************
1561 do a mget operation on one file
1562 ****************************************************************************/
1563 static void do_mget(file_info *finfo)
1565 pstring rname;
1566 pstring quest;
1568 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1569 return;
1571 if (abort_mget)
1573 DEBUG(0,("mget aborted\n"));
1574 return;
1577 if (finfo->mode & aDIR)
1578 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1579 else
1580 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1582 if (prompt && !yesno(quest)) return;
1584 if (finfo->mode & aDIR)
1586 pstring saved_curdir;
1587 pstring mget_mask;
1588 char *inbuf,*outbuf;
1590 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1591 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1593 if (!inbuf || !outbuf)
1595 DEBUG(0,("out of memory\n"));
1596 return;
1599 strcpy(saved_curdir,cur_dir);
1601 strcat(cur_dir,finfo->name);
1602 strcat(cur_dir,"\\");
1604 unix_format(finfo->name);
1606 if (lowercase)
1607 strlower(finfo->name);
1609 if (!directory_exist(finfo->name,NULL) &&
1610 sys_mkdir(finfo->name,0777) != 0)
1612 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1613 strcpy(cur_dir,saved_curdir);
1614 free(inbuf);free(outbuf);
1615 return;
1618 if (sys_chdir(finfo->name) != 0)
1620 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1621 strcpy(cur_dir,saved_curdir);
1622 free(inbuf);free(outbuf);
1623 return;
1627 strcpy(mget_mask,cur_dir);
1628 strcat(mget_mask,"*");
1630 do_dir((char *)inbuf,(char *)outbuf,
1631 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1632 chdir("..");
1633 strcpy(cur_dir,saved_curdir);
1634 free(inbuf);free(outbuf);
1636 else
1638 strcpy(rname,cur_dir);
1639 strcat(rname,finfo->name);
1640 do_get(rname,finfo->name,finfo);
1644 /****************************************************************************
1645 view the file using the pager
1646 ****************************************************************************/
1647 static void cmd_more(void)
1649 fstring rname,lname,tmpname,pager_cmd;
1650 char *pager;
1652 strcpy(rname,cur_dir);
1653 strcat(rname,"\\");
1654 sprintf(tmpname,"/tmp/smbmore.%d",getpid());
1655 strcpy(lname,tmpname);
1657 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1658 DEBUG(0,("more <filename>\n"));
1659 return;
1661 dos_clean_name(rname);
1663 do_get(rname,lname,NULL);
1665 pager=getenv("PAGER");
1666 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1667 system(pager_cmd);
1668 unlink(tmpname);
1673 /****************************************************************************
1674 do a mget command
1675 ****************************************************************************/
1676 static void cmd_mget(char *inbuf,char *outbuf)
1678 int attribute = aSYSTEM | aHIDDEN;
1679 pstring mget_mask;
1680 fstring buf;
1681 char *p=buf;
1683 *mget_mask = 0;
1685 if (recurse)
1686 attribute |= aDIR;
1688 abort_mget = False;
1690 while (next_token(NULL,p,NULL))
1692 strcpy(mget_mask,cur_dir);
1693 if(mget_mask[strlen(mget_mask)-1]!='\\')
1694 strcat(mget_mask,"\\");
1696 if (*p == '\\')
1697 strcpy(mget_mask,p);
1698 else
1699 strcat(mget_mask,p);
1700 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1703 if (! *mget_mask)
1705 strcpy(mget_mask,cur_dir);
1706 if(mget_mask[strlen(mget_mask)-1]!='\\')
1707 strcat(mget_mask,"\\");
1708 strcat(mget_mask,"*");
1709 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1713 /****************************************************************************
1714 make a directory of name "name"
1715 ****************************************************************************/
1716 static BOOL do_mkdir(char *name)
1718 char *p;
1719 char *inbuf,*outbuf;
1721 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1722 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1724 if (!inbuf || !outbuf)
1726 DEBUG(0,("out of memory\n"));
1727 return False;
1730 bzero(outbuf,smb_size);
1731 set_message(outbuf,0,2 + strlen(name),True);
1733 CVAL(outbuf,smb_com) = SMBmkdir;
1734 SSVAL(outbuf,smb_tid,cnum);
1735 setup_pkt(outbuf);
1738 p = smb_buf(outbuf);
1739 *p++ = 4;
1740 strcpy(p,name);
1742 send_smb(Client,outbuf);
1743 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1745 if (CVAL(inbuf,smb_rcls) != 0)
1747 DEBUG(0,("%s making remote directory %s\n",
1748 smb_errstr(inbuf),CNV_LANG(name)));
1750 free(inbuf);free(outbuf);
1751 return(False);
1754 free(inbuf);free(outbuf);
1755 return(True);
1759 /****************************************************************************
1760 make a directory
1761 ****************************************************************************/
1762 static void cmd_mkdir(char *inbuf,char *outbuf)
1764 pstring mask;
1765 fstring buf;
1766 char *p=buf;
1768 strcpy(mask,cur_dir);
1770 if (!next_token(NULL,p,NULL))
1772 if (!recurse)
1773 DEBUG(0,("mkdir <dirname>\n"));
1774 return;
1776 strcat(mask,p);
1778 if (recurse)
1780 pstring ddir;
1781 pstring ddir2;
1782 *ddir2 = 0;
1784 strcpy(ddir,mask);
1785 trim_string(ddir,".",NULL);
1786 p = strtok(ddir,"/\\");
1787 while (p)
1789 strcat(ddir2,p);
1790 if (!chkpath(ddir2,False))
1792 do_mkdir(ddir2);
1794 strcat(ddir2,"\\");
1795 p = strtok(NULL,"/\\");
1798 else
1799 do_mkdir(mask);
1803 /*******************************************************************
1804 write to a file using writebraw
1805 ********************************************************************/
1806 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1808 extern int Client;
1809 pstring inbuf;
1811 bzero(outbuf,smb_size);
1812 bzero(inbuf,smb_size);
1813 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1815 CVAL(outbuf,smb_com) = SMBwritebraw;
1816 SSVAL(outbuf,smb_tid,cnum);
1817 setup_pkt(outbuf);
1819 SSVAL(outbuf,smb_vwv0,fnum);
1820 SSVAL(outbuf,smb_vwv1,n);
1821 SIVAL(outbuf,smb_vwv3,pos);
1822 SSVAL(outbuf,smb_vwv7,1);
1824 send_smb(Client,outbuf);
1826 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1827 return(0);
1829 _smb_setlen(buf-4,n); /* HACK! XXXX */
1831 if (write_socket(Client,buf-4,n+4) != n+4)
1832 return(0);
1834 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1835 DEBUG(0,("Error writing remote file (2)\n"));
1836 return(0);
1838 return(SVAL(inbuf,smb_vwv0));
1843 /*******************************************************************
1844 write to a file
1845 ********************************************************************/
1846 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1848 pstring inbuf;
1850 if (writebraw_supported && n > (max_xmit-200))
1851 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1853 bzero(outbuf,smb_size);
1854 bzero(inbuf,smb_size);
1855 set_message(outbuf,5,n + 3,True);
1857 CVAL(outbuf,smb_com) = SMBwrite;
1858 SSVAL(outbuf,smb_tid,cnum);
1859 setup_pkt(outbuf);
1861 SSVAL(outbuf,smb_vwv0,fnum);
1862 SSVAL(outbuf,smb_vwv1,n);
1863 SIVAL(outbuf,smb_vwv2,pos);
1864 SSVAL(outbuf,smb_vwv4,0);
1865 CVAL(smb_buf(outbuf),0) = 1;
1866 SSVAL(smb_buf(outbuf),1,n);
1868 memcpy(smb_buf(outbuf)+3,buf,n);
1870 send_smb(Client,outbuf);
1871 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1873 if (CVAL(inbuf,smb_rcls) != 0) {
1874 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1875 return(0);
1877 return(SVAL(inbuf,smb_vwv0));
1882 /****************************************************************************
1883 put a single file
1884 ****************************************************************************/
1885 static void do_put(char *rname,char *lname,file_info *finfo)
1887 int fnum;
1888 FILE *f;
1889 int nread=0;
1890 char *p;
1891 char *inbuf,*outbuf;
1892 time_t close_time = finfo->mtime;
1893 char *buf=NULL;
1894 static int maxwrite=0;
1896 struct timeval tp_start;
1897 GetTimeOfDay(&tp_start);
1899 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1900 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1902 if (!inbuf || !outbuf)
1904 DEBUG(0,("out of memory\n"));
1905 return;
1908 bzero(outbuf,smb_size);
1909 set_message(outbuf,3,2 + strlen(rname),True);
1911 if (finfo->mtime == 0 || finfo->mtime == -1)
1912 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1914 CVAL(outbuf,smb_com) = SMBcreate;
1915 SSVAL(outbuf,smb_tid,cnum);
1916 setup_pkt(outbuf);
1918 SSVAL(outbuf,smb_vwv0,finfo->mode);
1919 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1921 p = smb_buf(outbuf);
1922 *p++ = 4;
1923 strcpy(p,rname);
1925 send_smb(Client,outbuf);
1926 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1928 if (CVAL(inbuf,smb_rcls) != 0)
1930 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1932 free(inbuf);free(outbuf);if (buf) free(buf);
1933 return;
1936 f = fopen(lname,"r");
1938 if (!f)
1940 DEBUG(0,("Error opening local file %s\n",lname));
1941 free(inbuf);free(outbuf);
1942 return;
1946 fnum = SVAL(inbuf,smb_vwv0);
1947 if (finfo->size < 0)
1948 finfo->size = file_size(lname);
1950 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1952 if (!maxwrite)
1953 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1955 while (nread < finfo->size)
1957 int n = maxwrite;
1958 int ret;
1960 n = MIN(n,finfo->size - nread);
1962 buf = (char *)Realloc(buf,n+4);
1964 fseek(f,nread,SEEK_SET);
1965 if ((n = readfile(buf+4,1,n,f)) < 1)
1967 DEBUG(0,("Error reading local file\n"));
1968 break;
1971 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1973 if (n != ret) {
1974 if (!maxwrite) {
1975 DEBUG(0,("Error writing file\n"));
1976 break;
1977 } else {
1978 maxwrite /= 2;
1979 continue;
1983 nread += n;
1988 bzero(outbuf,smb_size);
1989 set_message(outbuf,3,0,True);
1990 CVAL(outbuf,smb_com) = SMBclose;
1991 SSVAL(outbuf,smb_tid,cnum);
1992 setup_pkt(outbuf);
1994 SSVAL(outbuf,smb_vwv0,fnum);
1995 put_dos_date3(outbuf,smb_vwv1,close_time);
1997 send_smb(Client,outbuf);
1998 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2000 if (CVAL(inbuf,smb_rcls) != 0)
2002 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2003 fclose(f);
2004 free(inbuf);free(outbuf);
2005 if (buf) free(buf);
2006 return;
2010 fclose(f);
2011 free(inbuf);free(outbuf);
2012 if (buf) free(buf);
2015 struct timeval tp_end;
2016 int this_time;
2018 GetTimeOfDay(&tp_end);
2019 this_time =
2020 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
2021 (tp_end.tv_usec - tp_start.tv_usec)/1000;
2022 put_total_time_ms += this_time;
2023 put_total_size += finfo->size;
2025 DEBUG(2,("(%g kb/s) (average %g kb/s)\n",
2026 finfo->size / (1.024*this_time + 1.0e-4),
2027 put_total_size / (1.024*put_total_time_ms)));
2033 /****************************************************************************
2034 put a file
2035 ****************************************************************************/
2036 static void cmd_put(void)
2038 pstring lname;
2039 pstring rname;
2040 fstring buf;
2041 char *p=buf;
2042 file_info finfo;
2043 finfo = def_finfo;
2045 strcpy(rname,cur_dir);
2046 strcat(rname,"\\");
2049 if (!next_token(NULL,p,NULL))
2051 DEBUG(0,("put <filename>\n"));
2052 return;
2054 strcpy(lname,p);
2056 if (next_token(NULL,p,NULL))
2057 strcat(rname,p);
2058 else
2059 strcat(rname,lname);
2061 dos_clean_name(rname);
2064 struct stat st;
2065 if (!file_exist(lname,&st)) {
2066 DEBUG(0,("%s does not exist\n",lname));
2067 return;
2069 finfo.mtime = st.st_mtime;
2072 do_put(rname,lname,&finfo);
2075 /****************************************************************************
2076 seek in a directory/file list until you get something that doesn't start with
2077 the specified name
2078 ****************************************************************************/
2079 static BOOL seek_list(FILE *f,char *name)
2081 pstring s;
2082 while (!feof(f))
2084 if (fscanf(f,"%s",s) != 1) return(False);
2085 trim_string(s,"./",NULL);
2086 if (strncmp(s,name,strlen(name)) != 0)
2088 strcpy(name,s);
2089 return(True);
2093 return(False);
2097 /****************************************************************************
2098 set the file selection mask
2099 ****************************************************************************/
2100 static void cmd_select(void)
2102 strcpy(fileselection,"");
2103 next_token(NULL,fileselection,NULL);
2107 /****************************************************************************
2108 mput some files
2109 ****************************************************************************/
2110 static void cmd_mput(void)
2112 pstring lname;
2113 pstring rname;
2114 file_info finfo;
2115 fstring buf;
2116 char *p=buf;
2118 finfo = def_finfo;
2121 while (next_token(NULL,p,NULL))
2123 struct stat st;
2124 pstring cmd;
2125 pstring tmpname;
2126 FILE *f;
2128 sprintf(tmpname,"/tmp/ls.smb.%d",(int)getpid());
2129 if (recurse)
2130 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2131 else
2132 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2133 system(cmd);
2135 f = fopen(tmpname,"r");
2136 if (!f) continue;
2138 while (!feof(f))
2140 pstring quest;
2142 if (fscanf(f,"%s",lname) != 1) break;
2143 trim_string(lname,"./",NULL);
2145 again1:
2147 /* check if it's a directory */
2148 if (directory_exist(lname,&st))
2150 if (!recurse) continue;
2151 sprintf(quest,"Put directory %s? ",lname);
2152 if (prompt && !yesno(quest))
2154 strcat(lname,"/");
2155 if (!seek_list(f,lname))
2156 break;
2157 goto again1;
2160 strcpy(rname,cur_dir);
2161 strcat(rname,lname);
2162 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2163 strcat(lname,"/");
2164 if (!seek_list(f,lname))
2165 break;
2166 goto again1;
2169 continue;
2171 else
2173 sprintf(quest,"Put file %s? ",lname);
2174 if (prompt && !yesno(quest)) continue;
2176 strcpy(rname,cur_dir);
2177 strcat(rname,lname);
2179 dos_format(rname);
2181 /* null size so do_put knows to ignore it */
2182 finfo.size = -1;
2184 /* set the date on the file */
2185 finfo.mtime = st.st_mtime;
2187 do_put(rname,lname,&finfo);
2189 fclose(f);
2190 unlink(tmpname);
2194 /****************************************************************************
2195 cancel a print job
2196 ****************************************************************************/
2197 static void do_cancel(int job)
2199 char *rparam = NULL;
2200 char *rdata = NULL;
2201 char *p;
2202 int rdrcnt,rprcnt;
2203 pstring param;
2205 bzero(param,sizeof(param));
2207 p = param;
2208 SSVAL(p,0,81); /* DosPrintJobDel() */
2209 p += 2;
2210 strcpy(p,"W");
2211 p = skip_string(p,1);
2212 strcpy(p,"");
2213 p = skip_string(p,1);
2214 SSVAL(p,0,job);
2215 p += 2;
2217 if (call_api(PTR_DIFF(p,param),0,
2218 6,1000,
2219 &rprcnt,&rdrcnt,
2220 param,NULL,
2221 &rparam,&rdata))
2223 int res = SVAL(rparam,0);
2225 if (!res)
2226 printf("Job %d cancelled\n",job);
2227 else
2228 printf("Error %d calcelling job %d\n",res,job);
2229 return;
2231 else
2232 printf("Server refused cancel request\n");
2234 if (rparam) free(rparam);
2235 if (rdata) free(rdata);
2237 return;
2241 /****************************************************************************
2242 cancel a print job
2243 ****************************************************************************/
2244 static void cmd_cancel(char *inbuf,char *outbuf )
2246 fstring buf;
2247 int job;
2249 if (!connect_as_printer)
2251 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2252 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2255 if (!next_token(NULL,buf,NULL)) {
2256 printf("cancel <jobid> ...\n");
2257 return;
2259 do {
2260 job = atoi(buf);
2261 do_cancel(job);
2262 } while (next_token(NULL,buf,NULL));
2266 /****************************************************************************
2267 get info on a file
2268 ****************************************************************************/
2269 static void cmd_stat(char *inbuf,char *outbuf)
2271 fstring buf;
2272 pstring param;
2273 char *resp_data=NULL;
2274 char *resp_param=NULL;
2275 int resp_data_len = 0;
2276 int resp_param_len=0;
2277 char *p;
2278 uint16 setup = TRANSACT2_QPATHINFO;
2280 if (!next_token(NULL,buf,NULL)) {
2281 printf("stat <file>\n");
2282 return;
2285 bzero(param,6);
2286 SSVAL(param,0,4); /* level */
2287 p = param+6;
2288 strcpy(p,cur_dir);
2289 strcat(p,buf);
2291 send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
2292 NULL,param,&setup,
2293 0,6 + strlen(p)+1,1,
2294 BUFFER_SIZE,2,0);
2296 receive_trans_response(inbuf,SMBtrans2,
2297 &resp_data_len,&resp_param_len,
2298 &resp_data,&resp_param);
2300 if (resp_data) free(resp_data); resp_data = NULL;
2301 if (resp_param) free(resp_param); resp_param = NULL;
2305 /****************************************************************************
2306 print a file
2307 ****************************************************************************/
2308 static void cmd_print(char *inbuf,char *outbuf )
2310 int fnum;
2311 FILE *f = NULL;
2312 uint32 nread=0;
2313 pstring lname;
2314 pstring rname;
2315 char *p;
2317 if (!connect_as_printer)
2319 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2320 DEBUG(0,("Trying to print without -P may fail\n"));
2323 if (!next_token(NULL,lname,NULL))
2325 DEBUG(0,("print <filename>\n"));
2326 return;
2329 strcpy(rname,lname);
2330 p = strrchr(rname,'/');
2331 if (p)
2333 pstring tname;
2334 strcpy(tname,p+1);
2335 strcpy(rname,tname);
2338 if ((int)strlen(rname) > 14)
2339 rname[14] = 0;
2341 if (strequal(lname,"-"))
2343 f = stdin;
2344 strcpy(rname,"stdin");
2347 dos_clean_name(rname);
2349 bzero(outbuf,smb_size);
2350 set_message(outbuf,2,2 + strlen(rname),True);
2352 CVAL(outbuf,smb_com) = SMBsplopen;
2353 SSVAL(outbuf,smb_tid,cnum);
2354 setup_pkt(outbuf);
2356 SSVAL(outbuf,smb_vwv0,0);
2357 SSVAL(outbuf,smb_vwv1,printmode);
2359 p = smb_buf(outbuf);
2360 *p++ = 4;
2361 strcpy(p,rname);
2363 send_smb(Client,outbuf);
2364 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2366 if (CVAL(inbuf,smb_rcls) != 0)
2368 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2369 return;
2372 if (!f)
2373 f = fopen(lname,"r");
2374 if (!f)
2376 DEBUG(0,("Error opening local file %s\n",lname));
2377 return;
2381 fnum = SVAL(inbuf,smb_vwv0);
2383 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2385 while (!feof(f))
2387 int n;
2389 bzero(outbuf,smb_size);
2390 set_message(outbuf,1,3,True);
2392 /* for some strange reason the OS/2 print server can't handle large
2393 packets when printing. weird */
2394 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2396 if (translation)
2397 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2398 else
2399 n = readfile(smb_buf(outbuf)+3,1,n,f);
2400 if (n <= 0)
2402 DEBUG(0,("read gave %d\n",n));
2403 break;
2406 smb_setlen(outbuf,smb_len(outbuf) + n);
2408 CVAL(outbuf,smb_com) = SMBsplwr;
2409 SSVAL(outbuf,smb_tid,cnum);
2410 setup_pkt(outbuf);
2412 SSVAL(outbuf,smb_vwv0,fnum);
2413 SSVAL(outbuf,smb_vwv1,n+3);
2414 CVAL(smb_buf(outbuf),0) = 1;
2415 SSVAL(smb_buf(outbuf),1,n);
2417 send_smb(Client,outbuf);
2418 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2420 if (CVAL(inbuf,smb_rcls) != 0)
2422 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2423 break;
2426 nread += n;
2429 DEBUG(2,("%d bytes printed\n",nread));
2431 bzero(outbuf,smb_size);
2432 set_message(outbuf,1,0,True);
2433 CVAL(outbuf,smb_com) = SMBsplclose;
2434 SSVAL(outbuf,smb_tid,cnum);
2435 setup_pkt(outbuf);
2437 SSVAL(outbuf,smb_vwv0,fnum);
2439 send_smb(Client,outbuf);
2440 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2442 if (CVAL(inbuf,smb_rcls) != 0)
2444 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2445 if (f != stdin)
2446 fclose(f);
2447 return;
2450 if (f != stdin)
2451 fclose(f);
2454 /****************************************************************************
2455 show a print queue
2456 ****************************************************************************/
2457 static void cmd_queue(char *inbuf,char *outbuf )
2459 int count;
2460 char *p;
2462 bzero(outbuf,smb_size);
2463 set_message(outbuf,2,0,True);
2465 CVAL(outbuf,smb_com) = SMBsplretq;
2466 SSVAL(outbuf,smb_tid,cnum);
2467 setup_pkt(outbuf);
2469 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2470 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2472 send_smb(Client,outbuf);
2473 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2475 if (CVAL(inbuf,smb_rcls) != 0)
2477 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2478 return;
2481 count = SVAL(inbuf,smb_vwv0);
2482 p = smb_buf(inbuf) + 3;
2483 if (count <= 0)
2485 DEBUG(0,("No entries in the print queue\n"));
2486 return;
2490 char status[20];
2492 DEBUG(0,("Job Name Size Status\n"));
2494 while (count--)
2496 switch (CVAL(p,4))
2498 case 0x01: sprintf(status,"held or stopped"); break;
2499 case 0x02: sprintf(status,"printing"); break;
2500 case 0x03: sprintf(status,"awaiting print"); break;
2501 case 0x04: sprintf(status,"in intercept"); break;
2502 case 0x05: sprintf(status,"file had error"); break;
2503 case 0x06: sprintf(status,"printer error"); break;
2504 default: sprintf(status,"unknown"); break;
2507 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2508 SVAL(p,5),p+12,IVAL(p,7),status));
2509 p += 28;
2516 /****************************************************************************
2517 show information about a print queue
2518 ****************************************************************************/
2519 static void cmd_qinfo(char *inbuf,char *outbuf )
2521 char *rparam = NULL;
2522 char *rdata = NULL;
2523 char *p;
2524 int rdrcnt, rprcnt;
2525 pstring param;
2526 int result_code=0;
2528 bzero(param,sizeof(param));
2530 p = param;
2531 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2532 p += 2;
2533 strcpy(p,"zWrLh"); /* parameter description? */
2534 p = skip_string(p,1);
2535 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2536 p = skip_string(p,1);
2537 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2538 p = skip_string(p,1);
2539 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2540 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2541 p += 4;
2542 strcpy(p,""); /* subformat */
2543 p = skip_string(p,1);
2545 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2546 if( call_api(PTR_DIFF(p,param), 0,
2547 10, 4096,
2548 &rprcnt, &rdrcnt,
2549 param, NULL,
2550 &rparam, &rdata) )
2552 int converter;
2553 result_code = SVAL(rparam,0);
2554 converter = SVAL(rparam,2); /* conversion factor */
2556 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2558 if (result_code == 0) /* if no error, */
2560 p = rdata; /* received data */
2562 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2563 printf("Priority: %u\n", SVAL(p,4) );
2564 printf("Start time: %u\n", SVAL(p,6) );
2565 printf("Until time: %u\n", SVAL(p,8) );
2566 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2567 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2568 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2569 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2570 printf("Status: %u\n", SVAL(p,28) );
2571 printf("Jobs: %u\n", SVAL(p,30) );
2572 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2573 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2575 /* Dump the driver data */
2577 int count, x, y, c;
2578 char *ddptr;
2580 ddptr = rdata + SVAL(p,40) - converter;
2581 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2582 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2584 for(x=8; x < count; x+=16)
2586 for(y=0; y < 16; y++)
2588 if( (x+y) < count )
2589 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2590 else
2591 fputs(" ", stdout);
2593 for(y=0; y < 16 && (x+y) < count; y++)
2595 c = CVAL(ddptr,(x+y));
2596 if(isprint(c))
2597 fputc(c, stdout);
2598 else
2599 fputc('.', stdout);
2601 fputc('\n', stdout);
2607 else /* call_api() failed */
2609 printf("Failed, error = %d\n", result_code);
2612 /* If any parameters or data were returned, free the storage. */
2613 if(rparam) free(rparam);
2614 if(rdata) free(rdata);
2616 return;
2619 /****************************************************************************
2620 delete some files
2621 ****************************************************************************/
2622 static void do_del(file_info *finfo)
2624 char *p;
2625 char *inbuf,*outbuf;
2626 pstring mask;
2628 strcpy(mask,cur_dir);
2629 strcat(mask,finfo->name);
2631 if (finfo->mode & aDIR)
2632 return;
2634 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2635 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2637 if (!inbuf || !outbuf)
2639 DEBUG(0,("out of memory\n"));
2640 return;
2643 bzero(outbuf,smb_size);
2644 set_message(outbuf,1,2 + strlen(mask),True);
2646 CVAL(outbuf,smb_com) = SMBunlink;
2647 SSVAL(outbuf,smb_tid,cnum);
2648 setup_pkt(outbuf);
2650 SSVAL(outbuf,smb_vwv0,0);
2652 p = smb_buf(outbuf);
2653 *p++ = 4;
2654 strcpy(p,mask);
2656 send_smb(Client,outbuf);
2657 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2659 if (CVAL(inbuf,smb_rcls) != 0)
2660 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2662 free(inbuf);free(outbuf);
2666 /****************************************************************************
2667 delete some files
2668 ****************************************************************************/
2669 static void cmd_del(char *inbuf,char *outbuf )
2671 pstring mask;
2672 fstring buf;
2673 int attribute = aSYSTEM | aHIDDEN;
2675 if (recurse)
2676 attribute |= aDIR;
2678 strcpy(mask,cur_dir);
2680 if (!next_token(NULL,buf,NULL))
2682 DEBUG(0,("del <filename>\n"));
2683 return;
2685 strcat(mask,buf);
2687 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2691 /****************************************************************************
2692 remove a directory
2693 ****************************************************************************/
2694 static void cmd_rmdir(char *inbuf,char *outbuf )
2696 pstring mask;
2697 fstring buf;
2698 char *p;
2700 strcpy(mask,cur_dir);
2702 if (!next_token(NULL,buf,NULL))
2704 DEBUG(0,("rmdir <dirname>\n"));
2705 return;
2707 strcat(mask,buf);
2709 bzero(outbuf,smb_size);
2710 set_message(outbuf,0,2 + strlen(mask),True);
2712 CVAL(outbuf,smb_com) = SMBrmdir;
2713 SSVAL(outbuf,smb_tid,cnum);
2714 setup_pkt(outbuf);
2717 p = smb_buf(outbuf);
2718 *p++ = 4;
2719 strcpy(p,mask);
2721 send_smb(Client,outbuf);
2722 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2724 if (CVAL(inbuf,smb_rcls) != 0)
2726 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2727 return;
2732 /****************************************************************************
2733 rename some files
2734 ****************************************************************************/
2735 static void cmd_rename(char *inbuf,char *outbuf )
2737 pstring src,dest;
2738 fstring buf,buf2;
2739 char *p;
2741 strcpy(src,cur_dir);
2742 strcpy(dest,cur_dir);
2744 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2746 DEBUG(0,("rename <src> <dest>\n"));
2747 return;
2749 strcat(src,buf);
2750 strcat(dest,buf2);
2752 bzero(outbuf,smb_size);
2753 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2755 CVAL(outbuf,smb_com) = SMBmv;
2756 SSVAL(outbuf,smb_tid,cnum);
2757 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2758 setup_pkt(outbuf);
2760 p = smb_buf(outbuf);
2761 *p++ = 4;
2762 strcpy(p,src);
2763 p = skip_string(p,1);
2764 *p++ = 4;
2765 strcpy(p,dest);
2767 send_smb(Client,outbuf);
2768 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2770 if (CVAL(inbuf,smb_rcls) != 0)
2772 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2773 return;
2779 /****************************************************************************
2780 toggle the prompt flag
2781 ****************************************************************************/
2782 static void cmd_prompt(void)
2784 prompt = !prompt;
2785 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2789 /****************************************************************************
2790 set the newer than time
2791 ****************************************************************************/
2792 static void cmd_newer(void)
2794 fstring buf;
2795 BOOL ok;
2796 struct stat sbuf;
2798 ok = next_token(NULL,buf,NULL);
2799 if (ok && (sys_stat(buf,&sbuf) == 0))
2801 newer_than = sbuf.st_mtime;
2802 DEBUG(1,("Getting files newer than %s",
2803 asctime(LocalTime(&newer_than))));
2805 else
2806 newer_than = 0;
2808 if (ok && newer_than == 0)
2809 DEBUG(0,("Error setting newer-than time\n"));
2812 /****************************************************************************
2813 set the archive level
2814 ****************************************************************************/
2815 static void cmd_archive(void)
2817 fstring buf;
2819 if (next_token(NULL,buf,NULL)) {
2820 archive_level = atoi(buf);
2821 } else
2822 DEBUG(0,("Archive level is %d\n",archive_level));
2825 /****************************************************************************
2826 toggle the lowercaseflag
2827 ****************************************************************************/
2828 static void cmd_lowercase(void)
2830 lowercase = !lowercase;
2831 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2837 /****************************************************************************
2838 toggle the recurse flag
2839 ****************************************************************************/
2840 static void cmd_recurse(void)
2842 recurse = !recurse;
2843 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2846 /****************************************************************************
2847 toggle the translate flag
2848 ****************************************************************************/
2849 static void cmd_translate(void)
2851 translation = !translation;
2852 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2853 translation?"on":"off"));
2857 /****************************************************************************
2858 do a printmode command
2859 ****************************************************************************/
2860 static void cmd_printmode(void)
2862 fstring buf;
2863 fstring mode;
2865 if (next_token(NULL,buf,NULL))
2867 if (strequal(buf,"text"))
2868 printmode = 0;
2869 else
2871 if (strequal(buf,"graphics"))
2872 printmode = 1;
2873 else
2874 printmode = atoi(buf);
2878 switch(printmode)
2880 case 0:
2881 strcpy(mode,"text");
2882 break;
2883 case 1:
2884 strcpy(mode,"graphics");
2885 break;
2886 default:
2887 sprintf(mode,"%d",printmode);
2888 break;
2891 DEBUG(2,("the printmode is now %s\n",mode));
2894 /****************************************************************************
2895 do the lcd command
2896 ****************************************************************************/
2897 static void cmd_lcd(void)
2899 fstring buf;
2900 pstring d;
2902 if (next_token(NULL,buf,NULL))
2903 sys_chdir(buf);
2904 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2908 /****************************************************************************
2909 send a session request
2910 ****************************************************************************/
2911 static BOOL send_session_request(char *inbuf,char *outbuf)
2913 fstring dest;
2914 char *p;
2915 int len = 4;
2916 /* send a session request (RFC 8002) */
2918 strcpy(dest,desthost);
2919 p = strchr(dest,'.');
2920 if (p) *p = 0;
2922 /* put in the destination name */
2923 p = outbuf+len;
2924 name_mangle(dest,p,name_type);
2925 len += name_len(p);
2927 /* and my name */
2928 p = outbuf+len;
2929 name_mangle(myname,p,0);
2930 len += name_len(p);
2932 /* setup the packet length */
2933 _smb_setlen(outbuf,len);
2934 CVAL(outbuf,0) = 0x81;
2936 send_smb(Client,outbuf);
2937 DEBUG(5,("Sent session request\n"));
2939 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2941 if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */
2943 /* For information, here is the response structure.
2944 * We do the byte-twiddling to for portability.
2945 struct RetargetResponse{
2946 unsigned char type;
2947 unsigned char flags;
2948 int16 length;
2949 int32 ip_addr;
2950 int16 port;
2953 extern int Client;
2954 int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
2955 /* SESSION RETARGET */
2956 putip((char *)&dest_ip,inbuf+4);
2958 close_sockets();
2959 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
2960 if (Client == -1)
2961 return False;
2963 DEBUG(3,("Retargeted\n"));
2965 set_socket_options(Client,user_socket_options);
2967 /* Try again */
2968 return send_session_request(inbuf,outbuf);
2969 } /* C. Hoch 9/14/95 End */
2972 if (CVAL(inbuf,0) != 0x82)
2974 int ecode = CVAL(inbuf,4);
2975 DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
2976 CVAL(inbuf,0),ecode,myname,desthost));
2977 switch (ecode)
2979 case 0x80:
2980 DEBUG(0,("Not listening on called name\n"));
2981 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
2982 DEBUG(0,("You may find the -I option useful for this\n"));
2983 break;
2984 case 0x81:
2985 DEBUG(0,("Not listening for calling name\n"));
2986 DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
2987 DEBUG(0,("You may find the -n option useful for this\n"));
2988 break;
2989 case 0x82:
2990 DEBUG(0,("Called name not present\n"));
2991 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
2992 DEBUG(0,("You may find the -I option useful for this\n"));
2993 break;
2994 case 0x83:
2995 DEBUG(0,("Called name present, but insufficient resources\n"));
2996 DEBUG(0,("Perhaps you should try again later?\n"));
2997 break;
2998 default:
2999 DEBUG(0,("Unspecified error 0x%X\n",ecode));
3000 DEBUG(0,("Your server software is being unfriendly\n"));
3001 break;
3003 return(False);
3005 return(True);
3008 static struct {
3009 int prot;
3010 char *name;
3011 } prots[] = {
3012 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
3013 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
3014 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
3015 {PROTOCOL_LANMAN1,"LANMAN1.0"},
3016 {PROTOCOL_LANMAN2,"LM1.2X002"},
3017 {PROTOCOL_LANMAN2,"Samba"},
3018 {PROTOCOL_NT1,"NT LM 0.12"},
3019 {PROTOCOL_NT1,"NT LANMAN 1.0"},
3020 {-1,NULL}
3024 /****************************************************************************
3025 send a login command
3026 ****************************************************************************/
3027 static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
3029 BOOL was_null = (!inbuf && !outbuf);
3030 int sesskey=0;
3031 time_t servertime = 0;
3032 extern int serverzone;
3033 int sec_mode=0;
3034 int crypt_len;
3035 int max_vcs=0;
3036 char *pass = NULL;
3037 pstring dev;
3038 char *p;
3039 int numprots;
3040 int tries=0;
3042 if (was_null)
3044 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3045 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3048 #if AJT
3049 if (strstr(service,"IPC$")) connect_as_ipc = True;
3050 #endif
3052 strcpy(dev,"A:");
3053 if (connect_as_printer)
3054 strcpy(dev,"LPT1:");
3055 if (connect_as_ipc)
3056 strcpy(dev,"IPC");
3059 if (start_session && !send_session_request(inbuf,outbuf))
3061 if (was_null)
3063 free(inbuf);
3064 free(outbuf);
3066 return(False);
3069 bzero(outbuf,smb_size);
3071 /* setup the protocol strings */
3073 int plength;
3075 for (plength=0,numprots=0;
3076 prots[numprots].name && prots[numprots].prot<=max_protocol;
3077 numprots++)
3078 plength += strlen(prots[numprots].name)+2;
3080 set_message(outbuf,0,plength,True);
3082 p = smb_buf(outbuf);
3083 for (numprots=0;
3084 prots[numprots].name && prots[numprots].prot<=max_protocol;
3085 numprots++)
3087 *p++ = 2;
3088 strcpy(p,prots[numprots].name);
3089 p += strlen(p) + 1;
3093 CVAL(outbuf,smb_com) = SMBnegprot;
3094 setup_pkt(outbuf);
3096 CVAL(smb_buf(outbuf),0) = 2;
3098 send_smb(Client,outbuf);
3099 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3101 show_msg(inbuf);
3103 if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
3105 DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
3106 myname,desthost,smb_errstr(inbuf)));
3107 if (was_null)
3109 free(inbuf);
3110 free(outbuf);
3112 return(False);
3115 Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
3118 if (Protocol < PROTOCOL_NT1) {
3119 sec_mode = SVAL(inbuf,smb_vwv1);
3120 max_xmit = SVAL(inbuf,smb_vwv2);
3121 sesskey = IVAL(inbuf,smb_vwv6);
3122 serverzone = SVALS(inbuf,smb_vwv10)*60;
3123 /* this time is converted to GMT by make_unix_date */
3124 servertime = make_unix_date(inbuf+smb_vwv8);
3125 if (Protocol >= PROTOCOL_COREPLUS) {
3126 readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
3127 writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
3129 crypt_len = smb_buflen(inbuf);
3130 memcpy(cryptkey,smb_buf(inbuf),8);
3131 DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
3132 max_vcs = SVAL(inbuf,smb_vwv4);
3133 DEBUG(3,("max vcs %d\n",max_vcs));
3134 DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
3135 } else {
3136 /* NT protocol */
3137 sec_mode = CVAL(inbuf,smb_vwv1);
3138 max_xmit = IVAL(inbuf,smb_vwv3+1);
3139 sesskey = IVAL(inbuf,smb_vwv7+1);
3140 serverzone = SVALS(inbuf,smb_vwv15+1)*60;
3141 /* this time arrives in real GMT */
3142 servertime = interpret_long_date(inbuf+smb_vwv11+1);
3143 crypt_len = CVAL(inbuf,smb_vwv16+1);
3144 memcpy(cryptkey,smb_buf(inbuf),8);
3145 if (IVAL(inbuf,smb_vwv9+1) & 1)
3146 readbraw_supported = writebraw_supported = True;
3147 DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
3148 max_vcs = SVAL(inbuf,smb_vwv2+1);
3149 DEBUG(3,("max vcs %d\n",max_vcs));
3150 DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
3151 DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
3154 DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
3155 DEBUG(3,("max xmt %d\n",max_xmit));
3156 DEBUG(3,("Got %d byte crypt key\n",crypt_len));
3157 DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
3159 doencrypt = ((sec_mode & 2) != 0);
3161 if (servertime) {
3162 static BOOL done_time = False;
3163 if (!done_time) {
3164 DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
3165 asctime(LocalTime(&servertime)),
3166 -(double)(serverzone/3600.0)));
3167 done_time = True;
3171 get_pass:
3173 if (got_pass)
3174 pass = password;
3175 else
3176 pass = (char *)getpass("Password: ");
3178 /* use a blank username for the 2nd try with a blank password */
3179 if (tries++ && !*pass)
3180 *username = 0;
3182 if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
3184 fstring pword;
3185 int passlen = strlen(pass)+1;
3186 strcpy(pword,pass);
3188 #ifdef SMB_PASSWD
3189 if (doencrypt && *pass) {
3190 DEBUG(3,("Using encrypted passwords\n"));
3191 passlen = 24;
3192 SMBencrypt(pass,cryptkey,pword);
3194 #else
3195 doencrypt = False;
3196 #endif
3198 /* if in share level security then don't send a password now */
3199 if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;}
3201 /* send a session setup command */
3202 bzero(outbuf,smb_size);
3204 if (Protocol < PROTOCOL_NT1) {
3205 set_message(outbuf,10,1 + strlen(username) + passlen,True);
3206 CVAL(outbuf,smb_com) = SMBsesssetupX;
3207 setup_pkt(outbuf);
3209 CVAL(outbuf,smb_vwv0) = 0xFF;
3210 SSVAL(outbuf,smb_vwv2,max_xmit);
3211 SSVAL(outbuf,smb_vwv3,2);
3212 SSVAL(outbuf,smb_vwv4,max_vcs-1);
3213 SIVAL(outbuf,smb_vwv5,sesskey);
3214 SSVAL(outbuf,smb_vwv7,passlen);
3215 p = smb_buf(outbuf);
3216 memcpy(p,pword,passlen);
3217 p += passlen;
3218 strcpy(p,username);
3219 } else {
3220 if (!doencrypt) passlen--;
3221 /* for Win95 */
3222 set_message(outbuf,13,0,True);
3223 CVAL(outbuf,smb_com) = SMBsesssetupX;
3224 setup_pkt(outbuf);
3226 CVAL(outbuf,smb_vwv0) = 0xFF;
3227 SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
3228 SSVAL(outbuf,smb_vwv3,2);
3229 SSVAL(outbuf,smb_vwv4,getpid());
3230 SIVAL(outbuf,smb_vwv5,sesskey);
3231 SSVAL(outbuf,smb_vwv7,passlen);
3232 SSVAL(outbuf,smb_vwv8,0);
3233 p = smb_buf(outbuf);
3234 memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
3235 strcpy(p,username);p = skip_string(p,1);
3236 strcpy(p,workgroup);p = skip_string(p,1);
3237 strcpy(p,"Unix");p = skip_string(p,1);
3238 strcpy(p,"Samba");p = skip_string(p,1);
3239 set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
3242 send_smb(Client,outbuf);
3243 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3245 show_msg(inbuf);
3247 if (CVAL(inbuf,smb_rcls) != 0)
3249 if (! *pass &&
3250 ((CVAL(inbuf,smb_rcls) == ERRDOS &&
3251 SVAL(inbuf,smb_err) == ERRnoaccess) ||
3252 (CVAL(inbuf,smb_rcls) == ERRSRV &&
3253 SVAL(inbuf,smb_err) == ERRbadpw)))
3255 got_pass = False;
3256 DEBUG(3,("resending login\n"));
3257 goto get_pass;
3260 DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n",
3261 username,myname,desthost,smb_errstr(inbuf)));
3262 DEBUG(0,("You might find the -U, -W or -n options useful\n"));
3263 DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
3264 DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
3265 if (was_null)
3267 free(inbuf);
3268 free(outbuf);
3270 return(False);
3273 if (Protocol >= PROTOCOL_NT1) {
3274 char *domain,*os,*lanman;
3275 p = smb_buf(inbuf);
3276 os = p;
3277 lanman = skip_string(os,1);
3278 domain = skip_string(lanman,1);
3279 if (*domain || *os || *lanman)
3280 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
3283 /* use the returned uid from now on */
3284 if (SVAL(inbuf,smb_uid) != uid)
3285 DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
3286 SVAL(inbuf,smb_uid),uid));
3287 uid = SVAL(inbuf,smb_uid);
3290 /* now we've got a connection - send a tcon message */
3291 bzero(outbuf,smb_size);
3293 if (strncmp(service,"\\\\",2) != 0)
3295 DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
3296 DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
3300 again2:
3303 int passlen = strlen(pass)+1;
3304 fstring pword;
3305 strcpy(pword,pass);
3307 #ifdef SMB_PASSWD
3308 if (doencrypt && *pass) {
3309 passlen=24;
3310 SMBencrypt(pass,cryptkey,pword);
3312 #endif
3314 /* if in user level security then don't send a password now */
3315 if ((sec_mode & 1)) {
3316 strcpy(pword, ""); passlen=1;
3319 if (Protocol <= PROTOCOL_COREPLUS) {
3320 set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
3321 CVAL(outbuf,smb_com) = SMBtcon;
3322 setup_pkt(outbuf);
3324 p = smb_buf(outbuf);
3325 *p++ = 0x04;
3326 strcpy(p, service);
3327 p = skip_string(p,1);
3328 *p++ = 0x04;
3329 memcpy(p,pword,passlen);
3330 p += passlen;
3331 *p++ = 0x04;
3332 strcpy(p, dev);
3334 else {
3335 set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
3336 CVAL(outbuf,smb_com) = SMBtconX;
3337 setup_pkt(outbuf);
3339 SSVAL(outbuf,smb_vwv0,0xFF);
3340 SSVAL(outbuf,smb_vwv3,passlen);
3342 p = smb_buf(outbuf);
3343 memcpy(p,pword,passlen);
3344 p += passlen;
3345 strcpy(p,service);
3346 p = skip_string(p,1);
3347 strcpy(p,dev);
3351 send_smb(Client,outbuf);
3352 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3354 /* trying again with a blank password */
3355 if (CVAL(inbuf,smb_rcls) != 0 &&
3356 (int)strlen(pass) > 0 &&
3357 !doencrypt &&
3358 Protocol >= PROTOCOL_LANMAN1)
3360 DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
3361 strcpy(pass,"");
3362 goto again2;
3365 if (CVAL(inbuf,smb_rcls) != 0)
3367 DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
3368 DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
3369 DEBUG(0,("Some servers insist that these be in uppercase\n"));
3370 if (was_null)
3372 free(inbuf);
3373 free(outbuf);
3375 return(False);
3379 if (Protocol <= PROTOCOL_COREPLUS) {
3380 max_xmit = SVAL(inbuf,smb_vwv0);
3382 cnum = SVAL(inbuf,smb_vwv1);
3384 else {
3385 max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
3386 if (max_xmit <= 0)
3387 max_xmit = BUFFER_SIZE - 4;
3389 cnum = SVAL(inbuf,smb_tid);
3392 DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
3394 if (was_null)
3396 free(inbuf);
3397 free(outbuf);
3399 return True;
3403 /****************************************************************************
3404 send a logout command
3405 ****************************************************************************/
3406 static void send_logout(void )
3408 pstring inbuf,outbuf;
3410 bzero(outbuf,smb_size);
3411 set_message(outbuf,0,0,True);
3412 CVAL(outbuf,smb_com) = SMBtdis;
3413 SSVAL(outbuf,smb_tid,cnum);
3414 setup_pkt(outbuf);
3416 send_smb(Client,outbuf);
3417 receive_smb(Client,inbuf,SHORT_TIMEOUT);
3419 if (CVAL(inbuf,smb_rcls) != 0)
3421 DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
3425 #ifdef STATS
3426 stats_report();
3427 #endif
3428 exit(0);
3433 /****************************************************************************
3434 call a remote api
3435 ****************************************************************************/
3436 static BOOL call_api(int prcnt,int drcnt,
3437 int mprcnt,int mdrcnt,
3438 int *rprcnt,int *rdrcnt,
3439 char *param,char *data,
3440 char **rparam,char **rdata)
3442 static char *inbuf=NULL;
3443 static char *outbuf=NULL;
3445 if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3446 if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3448 send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
3449 data,param,NULL,
3450 drcnt,prcnt,0,
3451 mdrcnt,mprcnt,0);
3453 return (receive_trans_response(inbuf,SMBtrans,
3454 rdrcnt,rprcnt,
3455 rdata,rparam));
3458 /****************************************************************************
3459 send a SMB trans or trans2 request
3460 ****************************************************************************/
3461 static BOOL send_trans_request(char *outbuf,int trans,
3462 char *name,int fid,int flags,
3463 char *data,char *param,uint16 *setup,
3464 int ldata,int lparam,int lsetup,
3465 int mdata,int mparam,int msetup)
3467 int i;
3468 int this_ldata,this_lparam;
3469 int tot_data=0,tot_param=0;
3470 char *outdata,*outparam;
3471 pstring inbuf;
3472 char *p;
3474 this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
3475 this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
3477 bzero(outbuf,smb_size);
3478 set_message(outbuf,14+lsetup,0,True);
3479 CVAL(outbuf,smb_com) = trans;
3480 SSVAL(outbuf,smb_tid,cnum);
3481 setup_pkt(outbuf);
3483 outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
3484 outdata = outparam+this_lparam;
3486 /* primary request */
3487 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3488 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3489 SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */
3490 SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */
3491 SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */
3492 SSVAL(outbuf,smb_flags,flags); /* flags */
3493 SIVAL(outbuf,smb_timeout,0); /* timeout */
3494 SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
3495 SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
3496 SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */
3497 SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
3498 SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */
3499 for (i=0;i<lsetup;i++) /* setup[] */
3500 SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
3501 p = smb_buf(outbuf);
3502 if (trans==SMBtrans)
3503 strcpy(p,name); /* name[] */
3504 else
3506 *p++ = 0; /* put in a null smb_name */
3507 *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */
3509 if (this_lparam) /* param[] */
3510 memcpy(outparam,param,this_lparam);
3511 if (this_ldata) /* data[] */
3512 memcpy(outdata,data,this_ldata);
3513 set_message(outbuf,14+lsetup, /* wcnt, bcc */
3514 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3516 show_msg(outbuf);
3517 send_smb(Client,outbuf);
3519 if (this_ldata < ldata || this_lparam < lparam)
3521 /* receive interim response */
3522 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
3524 DEBUG(0,("%s request failed (%s)\n",
3525 trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
3526 return(False);
3529 tot_data = this_ldata;
3530 tot_param = this_lparam;
3532 while (tot_data < ldata || tot_param < lparam)
3534 this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
3535 this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
3537 set_message(outbuf,trans==SMBtrans?8:9,0,True);
3538 CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
3540 outparam = smb_buf(outbuf);
3541 outdata = outparam+this_lparam;
3543 /* secondary request */
3544 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3545 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3546 SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
3547 SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
3548 SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */
3549 SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */
3550 SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
3551 SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */
3552 if (trans==SMBtrans2)
3553 SSVAL(outbuf,smb_sfid,fid); /* fid */
3554 if (this_lparam) /* param[] */
3555 memcpy(outparam,param,this_lparam);
3556 if (this_ldata) /* data[] */
3557 memcpy(outdata,data,this_ldata);
3558 set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
3559 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3561 show_msg(outbuf);
3562 send_smb(Client,outbuf);
3564 tot_data += this_ldata;
3565 tot_param += this_lparam;
3569 return(True);
3572 /****************************************************************************
3573 try and browse available connections on a host
3574 ****************************************************************************/
3575 static BOOL browse_host(BOOL sort)
3577 #ifdef NOSTRCASECMP
3578 #define strcasecmp StrCaseCmp
3579 #endif
3580 extern int strcasecmp();
3582 char *rparam = NULL;
3583 char *rdata = NULL;
3584 char *p;
3585 int rdrcnt,rprcnt;
3586 pstring param;
3587 int count = -1;
3589 /* now send a SMBtrans command with api RNetShareEnum */
3590 p = param;
3591 SSVAL(p,0,0); /* api number */
3592 p += 2;
3593 strcpy(p,"WrLeh");
3594 p = skip_string(p,1);
3595 strcpy(p,"B13BWz");
3596 p = skip_string(p,1);
3597 SSVAL(p,0,1);
3598 SSVAL(p,2,BUFFER_SIZE);
3599 p += 4;
3601 if (call_api(PTR_DIFF(p,param),0,
3602 1024,BUFFER_SIZE,
3603 &rprcnt,&rdrcnt,
3604 param,NULL,
3605 &rparam,&rdata))
3607 int res = SVAL(rparam,0);
3608 int converter=SVAL(rparam,2);
3609 int i;
3610 BOOL long_share_name=False;
3612 if (res == 0)
3614 count=SVAL(rparam,4);
3615 p = rdata;
3617 if (count > 0)
3619 printf("\n\tSharename Type Comment\n");
3620 printf("\t--------- ---- -------\n");
3623 if (sort)
3624 qsort(p,count,20,QSORT_CAST strcasecmp);
3626 for (i=0;i<count;i++)
3628 char *sname = p;
3629 int type = SVAL(p,14);
3630 int comment_offset = IVAL(p,16) & 0xFFFF;
3631 fstring typestr;
3632 *typestr=0;
3634 switch (type)
3636 case STYPE_DISKTREE:
3637 strcpy(typestr,"Disk"); break;
3638 case STYPE_PRINTQ:
3639 strcpy(typestr,"Printer"); break;
3640 case STYPE_DEVICE:
3641 strcpy(typestr,"Device"); break;
3642 case STYPE_IPC:
3643 strcpy(typestr,"IPC"); break;
3646 printf("\t%-15.15s%-10.10s%s\n",
3647 sname,
3648 typestr,
3649 comment_offset?rdata+comment_offset-converter:"");
3651 if (strlen(sname)>8) long_share_name=True;
3653 p += 20;
3656 if (long_share_name) {
3657 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3662 if (rparam) free(rparam);
3663 if (rdata) free(rdata);
3665 return(count>0);
3669 /****************************************************************************
3670 get some server info
3671 ****************************************************************************/
3672 static void server_info()
3674 char *rparam = NULL;
3675 char *rdata = NULL;
3676 char *p;
3677 int rdrcnt,rprcnt;
3678 pstring param;
3680 bzero(param,sizeof(param));
3682 p = param;
3683 SSVAL(p,0,63); /* NetServerGetInfo()? */
3684 p += 2;
3685 strcpy(p,"WrLh");
3686 p = skip_string(p,1);
3687 strcpy(p,"zzzBBzz");
3688 p = skip_string(p,1);
3689 SSVAL(p,0,10); /* level 10 */
3690 SSVAL(p,2,1000);
3691 p += 6;
3693 if (call_api(PTR_DIFF(p,param),0,
3694 6,1000,
3695 &rprcnt,&rdrcnt,
3696 param,NULL,
3697 &rparam,&rdata))
3699 int res = SVAL(rparam,0);
3700 int converter=SVAL(rparam,2);
3702 if (res == 0)
3704 p = rdata;
3706 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3707 rdata+SVAL(p,0)-converter,
3708 rdata+SVAL(p,4)-converter,
3709 rdata+SVAL(p,8)-converter,
3710 rdata+SVAL(p,14)-converter);
3714 if (rparam) free(rparam);
3715 if (rdata) free(rdata);
3717 return;
3721 /****************************************************************************
3722 try and browse available connections on a host
3723 ****************************************************************************/
3724 static BOOL list_servers(char *wk_grp)
3726 char *rparam = NULL;
3727 char *rdata = NULL;
3728 int rdrcnt,rprcnt;
3729 char *p,*svtype_p;
3730 pstring param;
3731 int uLevel = 1;
3732 int count = 0;
3733 BOOL ok = False;
3734 BOOL generic_request = False;
3737 if (strequal(wk_grp,"WORKGROUP")) {
3738 /* we won't specify a workgroup */
3739 generic_request = True;
3742 /* now send a SMBtrans command with api ServerEnum? */
3743 p = param;
3744 SSVAL(p,0,0x68); /* api number */
3745 p += 2;
3747 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3748 p = skip_string(p,1);
3750 strcpy(p,"B16BBDz");
3752 p = skip_string(p,1);
3753 SSVAL(p,0,uLevel);
3754 SSVAL(p,2,0x2000); /* buf length */
3755 p += 4;
3757 svtype_p = p;
3758 p += 4;
3760 if (!generic_request) {
3761 strcpy(p, wk_grp);
3762 p = skip_string(p,1);
3765 /* first ask for a list of servers in this workgroup */
3766 SIVAL(svtype_p,0,SV_TYPE_ALL);
3768 if (call_api(PTR_DIFF(p+4,param),0,
3769 8,10000,
3770 &rprcnt,&rdrcnt,
3771 param,NULL,
3772 &rparam,&rdata))
3774 int res = SVAL(rparam,0);
3775 int converter=SVAL(rparam,2);
3776 int i;
3778 if (res == 0) {
3779 char *p2 = rdata;
3780 count=SVAL(rparam,4);
3782 if (count > 0) {
3783 printf("\n\nThis machine has a browse list:\n");
3784 printf("\n\tServer Comment\n");
3785 printf("\t--------- -------\n");
3788 for (i=0;i<count;i++) {
3789 char *sname = p2;
3790 int comment_offset = IVAL(p2,22) & 0xFFFF;
3791 printf("\t%-16.16s %s\n",
3792 sname,
3793 comment_offset?rdata+comment_offset-converter:"");
3795 ok=True;
3796 p2 += 26;
3801 if (rparam) {free(rparam); rparam = NULL;}
3802 if (rdata) {free(rdata); rdata = NULL;}
3804 /* now ask for a list of workgroups */
3805 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3807 if (call_api(PTR_DIFF(p+4,param),0,
3808 8,10000,
3809 &rprcnt,&rdrcnt,
3810 param,NULL,
3811 &rparam,&rdata))
3813 int res = SVAL(rparam,0);
3814 int converter=SVAL(rparam,2);
3815 int i;
3817 if (res == 0) {
3818 char *p2 = rdata;
3819 count=SVAL(rparam,4);
3821 if (count > 0) {
3822 printf("\n\nThis machine has a workgroup list:\n");
3823 printf("\n\tWorkgroup Master\n");
3824 printf("\t--------- -------\n");
3827 for (i=0;i<count;i++) {
3828 char *sname = p2;
3829 int comment_offset = IVAL(p2,22) & 0xFFFF;
3830 printf("\t%-16.16s %s\n",
3831 sname,
3832 comment_offset?rdata+comment_offset-converter:"");
3834 ok=True;
3835 p2 += 26;
3840 if (rparam) free(rparam);
3841 if (rdata) free(rdata);
3843 return(ok);
3847 /* This defines the commands supported by this client */
3848 struct
3850 char *name;
3851 void (*fn)();
3852 char *description;
3853 } commands[] =
3855 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3856 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3857 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3858 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3859 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3860 {"get",cmd_get,"<remote name> [local name] get a file"},
3861 {"mget",cmd_mget,"<mask> get all the matching files"},
3862 {"put",cmd_put,"<local name> [remote name] put a file"},
3863 {"mput",cmd_mput,"<mask> put all matching files"},
3864 {"rename",cmd_rename,"<src> <dest> rename some files"},
3865 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3866 {"mask",cmd_select,"<mask> mask all filenames against this"},
3867 {"del",cmd_del,"<mask> delete all matching files"},
3868 {"rm",cmd_del,"<mask> delete all matching files"},
3869 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3870 {"md",cmd_mkdir,"<directory> make a directory"},
3871 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
3872 {"rd",cmd_rmdir,"<directory> remove a directory"},
3873 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
3874 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
3875 {"translate",cmd_translate,"toggle text translation for printing"},
3876 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
3877 {"print",cmd_print,"<file name> print a file"},
3878 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
3879 {"queue",cmd_queue,"show the print queue"},
3880 {"qinfo",cmd_qinfo,"show print queue information"},
3881 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
3882 {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
3883 {"quit",send_logout,"logoff the server"},
3884 {"q",send_logout,"logoff the server"},
3885 {"exit",send_logout,"logoff the server"},
3886 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
3887 {"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"},
3888 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3889 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
3890 {"tarmode",cmd_tarmode,
3891 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3892 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
3893 {"help",cmd_help,"[command] give help on a command"},
3894 {"?",cmd_help,"[command] give help on a command"},
3895 {"!",NULL,"run a shell command on the local system"},
3896 {"",NULL,NULL}
3900 /*******************************************************************
3901 lookup a command string in the list of commands, including
3902 abbreviations
3903 ******************************************************************/
3904 static int process_tok(fstring tok)
3906 int i = 0, matches = 0;
3907 int cmd=0;
3908 int tok_len = strlen(tok);
3910 while (commands[i].fn != NULL)
3912 if (strequal(commands[i].name,tok))
3914 matches = 1;
3915 cmd = i;
3916 break;
3918 else if (strnequal(commands[i].name, tok, tok_len+1))
3920 matches++;
3921 cmd = i;
3923 i++;
3926 if (matches == 0)
3927 return(-1);
3928 else if (matches == 1)
3929 return(cmd);
3930 else
3931 return(-2);
3934 /****************************************************************************
3935 help
3936 ****************************************************************************/
3937 void cmd_help(void)
3939 int i=0,j;
3940 fstring buf;
3942 if (next_token(NULL,buf,NULL))
3944 if ((i = process_tok(buf)) >= 0)
3945 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3947 else
3948 while (commands[i].description)
3950 for (j=0; commands[i].description && (j<5); j++) {
3951 DEBUG(0,("%-15s",commands[i].name));
3952 i++;
3954 DEBUG(0,("\n"));
3958 /****************************************************************************
3959 open the client sockets
3960 ****************************************************************************/
3961 static BOOL open_sockets(int port )
3963 static int last_port;
3964 char *host;
3965 pstring service2;
3966 extern int Client;
3967 #ifdef USENMB
3968 BOOL failed = True;
3969 #endif
3971 if (port == 0) port=last_port;
3972 last_port=port;
3974 strupper(service);
3976 if (*desthost)
3978 host = desthost;
3980 else
3982 strcpy(service2,service);
3983 host = strtok(service2,"\\/");
3984 if (!host) {
3985 DEBUG(0,("Badly formed host name\n"));
3986 return(False);
3988 strcpy(desthost,host);
3991 if (*myname == 0) {
3992 get_myname(myname,NULL);
3994 strupper(myname);
3996 DEBUG(3,("Opening sockets\n"));
3998 if (!have_ip)
4000 struct hostent *hp;
4002 if ((hp = Get_Hostbyname(host))) {
4003 putip((char *)&dest_ip,(char *)hp->h_addr);
4004 failed = False;
4005 } else {
4006 #ifdef USENMB
4007 /* Try and resolve the name with the netbios server */
4008 int bcast;
4010 if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
4011 interpret_addr(lp_socket_address()))) != -1) {
4012 set_socket_options(bcast, "SO_BROADCAST");
4014 if (name_query(bcast, host, 0x20, True, True, *iface_bcast(dest_ip),
4015 &dest_ip,0)) {
4016 failed = False;
4018 close (bcast);
4020 #endif
4021 if (failed) {
4022 DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
4023 return False;
4028 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
4029 if (Client == -1)
4030 return False;
4032 DEBUG(3,("Connected\n"));
4034 set_socket_options(Client,user_socket_options);
4036 return True;
4039 /****************************************************************************
4040 wait for keyboard activity, swallowing network packets
4041 ****************************************************************************/
4042 #ifdef CLIX
4043 static char wait_keyboard(char *buffer)
4044 #else
4045 static void wait_keyboard(char *buffer)
4046 #endif
4048 fd_set fds;
4049 int selrtn;
4050 struct timeval timeout;
4052 #ifdef CLIX
4053 int delay = 0;
4054 #endif
4056 while (1)
4058 extern int Client;
4059 FD_ZERO(&fds);
4060 FD_SET(Client,&fds);
4061 #ifndef CLIX
4062 FD_SET(fileno(stdin),&fds);
4063 #endif
4065 timeout.tv_sec = 20;
4066 timeout.tv_usec = 0;
4067 #ifdef CLIX
4068 timeout.tv_sec = 0;
4069 #endif
4070 selrtn = sys_select(&fds,&timeout);
4072 #ifndef CLIX
4073 if (FD_ISSET(fileno(stdin),&fds))
4074 return;
4075 #else
4077 char ch;
4078 int f_flags;
4079 int readret;
4081 f_flags = fcntl(fileno(stdin), F_GETFL, 0);
4082 fcntl( fileno(stdin), F_SETFL, f_flags | O_NONBLOCK);
4083 readret = read_data( fileno(stdin), &ch, 1);
4084 fcntl(fileno(stdin), F_SETFL, f_flags);
4085 if (readret == -1)
4087 if (errno != EAGAIN)
4089 /* should crash here */
4090 DEBUG(1,("readchar stdin failed\n"));
4093 else if (readret != 0)
4095 return ch;
4098 #endif
4099 if (FD_ISSET(Client,&fds))
4100 receive_smb(Client,buffer,0);
4102 #ifdef CLIX
4103 delay++;
4104 if (delay > 100000)
4106 delay = 0;
4107 chkpath("\\",False);
4109 #else
4110 chkpath("\\",False);
4111 #endif
4116 /****************************************************************************
4117 close and open the connection again
4118 ****************************************************************************/
4119 BOOL reopen_connection(char *inbuf,char *outbuf)
4121 static int open_count=0;
4123 open_count++;
4125 if (open_count>5) return(False);
4127 DEBUG(1,("Trying to re-open connection\n"));
4129 set_message(outbuf,0,0,True);
4130 SCVAL(outbuf,smb_com,SMBtdis);
4131 SSVAL(outbuf,smb_tid,cnum);
4132 setup_pkt(outbuf);
4134 send_smb(Client,outbuf);
4135 receive_smb(Client,inbuf,SHORT_TIMEOUT);
4137 close_sockets();
4138 if (!open_sockets(0)) return(False);
4140 return(send_login(inbuf,outbuf,True,True));
4143 /****************************************************************************
4144 process commands from the client
4145 ****************************************************************************/
4146 static BOOL process(char *base_directory)
4148 extern FILE *dbf;
4149 pstring line;
4150 char *cmd;
4152 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4153 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4155 if ((InBuffer == NULL) || (OutBuffer == NULL))
4156 return(False);
4158 bzero(OutBuffer,smb_size);
4160 if (!send_login(InBuffer,OutBuffer,True,True))
4161 return(False);
4163 if (*base_directory) do_cd(base_directory);
4165 cmd = cmdstr;
4166 if (cmd[0] != '\0') while (cmd[0] != '\0')
4168 char *p;
4169 fstring tok;
4170 int i;
4172 if ((p = strchr(cmd, ';')) == 0)
4174 strncpy(line, cmd, 999);
4175 line[1000] = '\0';
4176 cmd += strlen(cmd);
4178 else
4180 if (p - cmd > 999) p = cmd + 999;
4181 strncpy(line, cmd, p - cmd);
4182 line[p - cmd] = '\0';
4183 cmd = p + 1;
4186 /* input language code to internal one */
4187 CNV_INPUT (line);
4189 /* and get the first part of the command */
4191 char *ptr = line;
4192 if (!next_token(&ptr,tok,NULL)) continue;
4195 if ((i = process_tok(tok)) >= 0)
4196 commands[i].fn(InBuffer,OutBuffer);
4197 else if (i == -2)
4198 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4199 else
4200 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4202 else while (!feof(stdin))
4204 fstring tok;
4205 int i;
4207 bzero(OutBuffer,smb_size);
4209 /* display a prompt */
4210 DEBUG(1,("smb: %s> ", CNV_LANG(cur_dir)));
4211 fflush(dbf);
4213 #ifdef CLIX
4214 line[0] = wait_keyboard(InBuffer);
4215 /* this might not be such a good idea... */
4216 if ( line[0] == EOF)
4217 break;
4218 #else
4219 wait_keyboard(InBuffer);
4220 #endif
4222 /* and get a response */
4223 #ifdef CLIX
4224 fgets( &line[1],999, stdin);
4225 #else
4226 if (!fgets(line,1000,stdin))
4227 break;
4228 #endif
4230 /* input language code to internal one */
4231 CNV_INPUT (line);
4233 /* special case - first char is ! */
4234 if (*line == '!')
4236 system(line + 1);
4237 continue;
4240 /* and get the first part of the command */
4242 char *ptr = line;
4243 if (!next_token(&ptr,tok,NULL)) continue;
4246 if ((i = process_tok(tok)) >= 0)
4247 commands[i].fn(InBuffer,OutBuffer);
4248 else if (i == -2)
4249 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4250 else
4251 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4254 send_logout();
4255 return(True);
4259 /****************************************************************************
4260 usage on the program
4261 ****************************************************************************/
4262 static void usage(char *pname)
4264 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
4265 pname));
4267 #ifdef KANJI
4268 DEBUG(0,("[-t termcode] "));
4269 #endif /* KANJI */
4271 DEBUG(0,("\nVersion %s\n",VERSION));
4272 DEBUG(0,("\t-p port listen on the specified port\n"));
4273 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
4274 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
4275 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
4276 DEBUG(0,("\t-N don't ask for a password\n"));
4277 DEBUG(0,("\t-P connect to service as a printer\n"));
4278 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
4279 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
4280 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
4281 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
4282 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
4283 DEBUG(0,("\t-U username set the network username\n"));
4284 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
4285 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
4286 #ifdef KANJI
4287 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
4288 #endif /* KANJI */
4289 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
4290 DEBUG(0,("\t-D directory start from directory\n"));
4291 DEBUG(0,("\n"));
4296 /****************************************************************************
4297 main program
4298 ****************************************************************************/
4299 int main(int argc,char *argv[])
4301 fstring base_directory;
4302 char *pname = argv[0];
4303 int port = SMB_PORT;
4304 int opt;
4305 extern FILE *dbf;
4306 extern char *optarg;
4307 extern int optind;
4308 pstring query_host;
4309 BOOL message = False;
4310 extern char tar_type;
4311 static pstring servicesf = CONFIGFILE;
4313 *query_host = 0;
4314 *base_directory = 0;
4316 DEBUGLEVEL = 2;
4318 setup_logging(pname,True);
4320 TimeInit();
4321 charset_initialise();
4323 pid = getpid();
4324 uid = getuid();
4325 gid = getgid();
4326 mid = pid + 100;
4327 myumask = umask(0);
4328 umask(myumask);
4330 if (getenv("USER"))
4332 strcpy(username,getenv("USER"));
4333 strupper(username);
4336 if (*username == 0 && getenv("LOGNAME"))
4338 strcpy(username,getenv("LOGNAME"));
4339 strupper(username);
4342 if (argc < 2)
4344 usage(pname);
4345 exit(1);
4348 if (*argv[1] != '-')
4351 strcpy(service,argv[1]);
4352 argc--;
4353 argv++;
4355 if (count_chars(service,'\\') < 3)
4357 usage(pname);
4358 printf("\n%s: Not enough '\\' characters in service\n",service);
4359 exit(1);
4363 if (count_chars(service,'\\') > 3)
4365 usage(pname);
4366 printf("\n%s: Too many '\\' characters in service\n",service);
4367 exit(1);
4371 if (argc > 1 && (*argv[1] != '-'))
4373 got_pass = True;
4374 strcpy(password,argv[1]);
4375 memset(argv[1],'X',strlen(argv[1]));
4376 argc--;
4377 argv++;
4381 #ifdef KANJI
4382 setup_term_code (KANJI);
4383 #endif
4384 while ((opt =
4385 getopt(argc, argv,"s:B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
4386 switch (opt)
4388 case 'm':
4389 max_protocol = interpret_protocol(optarg,max_protocol);
4390 break;
4391 case 'O':
4392 strcpy(user_socket_options,optarg);
4393 break;
4394 case 'M':
4395 name_type = 3;
4396 strcpy(desthost,optarg);
4397 strupper(desthost);
4398 message = True;
4399 break;
4400 case 'B':
4401 iface_set_default(NULL,optarg,NULL);
4402 break;
4403 case 'D':
4404 strcpy(base_directory,optarg);
4405 break;
4406 case 'T':
4407 if (!tar_parseargs(argc, argv, optarg, optind)) {
4408 usage(pname);
4409 exit(1);
4411 break;
4412 case 'i':
4413 strcpy(scope,optarg);
4414 break;
4415 case 'L':
4416 got_pass = True;
4417 strcpy(query_host,optarg);
4418 break;
4419 case 'U':
4421 char *p;
4422 strcpy(username,optarg);
4423 if ((p=strchr(username,'%')))
4425 *p = 0;
4426 strcpy(password,p+1);
4427 got_pass = True;
4428 memset(strchr(optarg,'%')+1,'X',strlen(password));
4432 break;
4433 case 'W':
4434 strcpy(workgroup,optarg);
4435 break;
4436 case 'E':
4437 dbf = stderr;
4438 break;
4439 case 'I':
4441 dest_ip = *interpret_addr2(optarg);
4442 if (zero_ip(dest_ip)) exit(1);
4443 have_ip = True;
4445 break;
4446 case 'n':
4447 strcpy(myname,optarg);
4448 break;
4449 case 'N':
4450 got_pass = True;
4451 break;
4452 case 'P':
4453 connect_as_printer = True;
4454 break;
4455 case 'd':
4456 if (*optarg == 'A')
4457 DEBUGLEVEL = 10000;
4458 else
4459 DEBUGLEVEL = atoi(optarg);
4460 break;
4461 case 'l':
4462 sprintf(debugf,"%s.client",optarg);
4463 break;
4464 case 'p':
4465 port = atoi(optarg);
4466 break;
4467 case 'c':
4468 cmdstr = optarg;
4469 got_pass = True;
4470 break;
4471 case 'h':
4472 usage(pname);
4473 exit(0);
4474 break;
4475 case 's':
4476 strcpy(servicesf, optarg);
4477 break;
4478 case 't':
4479 #ifdef KANJI
4480 if (!setup_term_code (optarg)) {
4481 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
4482 usage (pname);
4483 exit (1);
4485 #endif
4486 break;
4487 default:
4488 usage(pname);
4489 exit(1);
4492 if (!tar_type && !*query_host && !*service && !message)
4494 usage(pname);
4495 exit(1);
4499 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
4501 if (!lp_load(servicesf,True)) {
4502 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
4503 return (-1);
4506 load_interfaces();
4507 get_myname(*myname?NULL:myname,NULL);
4508 strupper(myname);
4510 if (tar_type) {
4511 recurse=True;
4513 if (open_sockets(port)) {
4514 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4515 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4516 int ret;
4518 if ((InBuffer == NULL) || (OutBuffer == NULL))
4519 return(1);
4521 bzero(OutBuffer,smb_size);
4522 if (!send_login(InBuffer,OutBuffer,True,True))
4523 return(False);
4525 if (*base_directory) do_cd(base_directory);
4527 ret=process_tar(InBuffer, OutBuffer);
4529 send_logout();
4530 close_sockets();
4531 return(ret);
4532 } else
4533 return(1);
4536 if (*query_host)
4538 int ret = 0;
4539 sprintf(service,"\\\\%s\\IPC$",query_host);
4540 strupper(service);
4541 connect_as_ipc = True;
4542 if (open_sockets(port))
4544 #if 0
4545 *username = 0;
4546 #endif
4547 if (!send_login(NULL,NULL,True,True))
4548 return(1);
4550 server_info();
4551 if (!browse_host(True)) {
4552 sleep(1);
4553 browse_host(True);
4555 if (!list_servers(workgroup)) {
4556 sleep(1);
4557 list_servers(workgroup);
4560 send_logout();
4561 close_sockets();
4564 return(ret);
4567 if (message)
4569 int ret = 0;
4570 if (open_sockets(port))
4572 pstring inbuf,outbuf;
4573 bzero(outbuf,smb_size);
4574 if (!send_session_request(inbuf,outbuf))
4575 return(1);
4577 send_message(inbuf,outbuf);
4579 close_sockets();
4582 return(ret);
4585 if (open_sockets(port))
4587 if (!process(base_directory))
4589 close_sockets();
4590 return(1);
4592 close_sockets();
4594 else
4595 return(1);
4597 return(0);
4601 /* error code stuff - put together by Merik Karman
4602 merik@blackadder.dsh.oz.au */
4604 typedef struct
4606 char *name;
4607 int code;
4608 char *message;
4609 } err_code_struct;
4611 /* Dos Error Messages */
4612 err_code_struct dos_msgs[] = {
4613 {"ERRbadfunc",1,"Invalid function."},
4614 {"ERRbadfile",2,"File not found."},
4615 {"ERRbadpath",3,"Directory invalid."},
4616 {"ERRnofids",4,"No file descriptors available"},
4617 {"ERRnoaccess",5,"Access denied."},
4618 {"ERRbadfid",6,"Invalid file handle."},
4619 {"ERRbadmcb",7,"Memory control blocks destroyed."},
4620 {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
4621 {"ERRbadmem",9,"Invalid memory block address."},
4622 {"ERRbadenv",10,"Invalid environment."},
4623 {"ERRbadformat",11,"Invalid format."},
4624 {"ERRbadaccess",12,"Invalid open mode."},
4625 {"ERRbaddata",13,"Invalid data."},
4626 {"ERR",14,"reserved."},
4627 {"ERRbaddrive",15,"Invalid drive specified."},
4628 {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
4629 {"ERRdiffdevice",17,"Not same device."},
4630 {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
4631 {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
4632 {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
4633 {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
4634 {"ERRbadpipe",230,"Pipe invalid."},
4635 {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
4636 {"ERRpipeclosing",232,"Pipe close in progress."},
4637 {"ERRnotconnected",233,"No process on other end of pipe."},
4638 {"ERRmoredata",234,"There is more data to be returned."},
4639 {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
4640 {NULL,-1,NULL}};
4642 /* Server Error Messages */
4643 err_code_struct server_msgs[] = {
4644 {"ERRerror",1,"Non-specific error code."},
4645 {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
4646 {"ERRbadtype",3,"reserved."},
4647 {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
4648 {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
4649 {"ERRinvnetname",6,"Invalid network name in tree connect."},
4650 {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
4651 {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
4652 {"ERRqtoobig",50,"Print queue full -- no space."},
4653 {"ERRqeof",51,"EOF on print queue dump."},
4654 {"ERRinvpfid",52,"Invalid print file FID."},
4655 {"ERRsmbcmd",64,"The server did not recognize the command received."},
4656 {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
4657 {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
4658 {"ERRreserved",68,"reserved."},
4659 {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
4660 {"ERRreserved",70,"reserved."},
4661 {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
4662 {"ERRpaused",81,"Server is paused."},
4663 {"ERRmsgoff",82,"Not receiving messages."},
4664 {"ERRnoroom",83,"No room to buffer message."},
4665 {"ERRrmuns",87,"Too many remote user names."},
4666 {"ERRtimeout",88,"Operation timed out."},
4667 {"ERRnoresource",89,"No resources currently available for request."},
4668 {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
4669 {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
4670 {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
4671 {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
4672 {"ERRcontmpx",252,"Continue in MPX mode."},
4673 {"ERRreserved",253,"reserved."},
4674 {"ERRreserved",254,"reserved."},
4675 {"ERRnosupport",0xFFFF,"Function not supported."},
4676 {NULL,-1,NULL}};
4678 /* Hard Error Messages */
4679 err_code_struct hard_msgs[] = {
4680 {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
4681 {"ERRbadunit",20,"Unknown unit."},
4682 {"ERRnotready",21,"Drive not ready."},
4683 {"ERRbadcmd",22,"Unknown command."},
4684 {"ERRdata",23,"Data error (CRC)."},
4685 {"ERRbadreq",24,"Bad request structure length."},
4686 {"ERRseek",25 ,"Seek error."},
4687 {"ERRbadmedia",26,"Unknown media type."},
4688 {"ERRbadsector",27,"Sector not found."},
4689 {"ERRnopaper",28,"Printer out of paper."},
4690 {"ERRwrite",29,"Write fault."},
4691 {"ERRread",30,"Read fault."},
4692 {"ERRgeneral",31,"General failure."},
4693 {"ERRbadshare",32,"A open conflicts with an existing open."},
4694 {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
4695 {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
4696 {"ERRFCBUnavail",35,"No FCBs are available to process request."},
4697 {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
4698 {NULL,-1,NULL}};
4701 struct
4703 int code;
4704 char *class;
4705 err_code_struct *err_msgs;
4706 } err_classes[] = {
4707 {0,"SUCCESS",NULL},
4708 {0x01,"ERRDOS",dos_msgs},
4709 {0x02,"ERRSRV",server_msgs},
4710 {0x03,"ERRHRD",hard_msgs},
4711 {0x04,"ERRXOS",NULL},
4712 {0xE1,"ERRRMX1",NULL},
4713 {0xE2,"ERRRMX2",NULL},
4714 {0xE3,"ERRRMX3",NULL},
4715 {0xFF,"ERRCMD",NULL},
4716 {-1,NULL,NULL}};
4719 /****************************************************************************
4720 return a SMB error string from a SMB buffer
4721 ****************************************************************************/
4722 char *smb_errstr(char *inbuf)
4724 static pstring ret;
4725 int class = CVAL(inbuf,smb_rcls);
4726 int num = SVAL(inbuf,smb_err);
4727 int i,j;
4729 for (i=0;err_classes[i].class;i++)
4730 if (err_classes[i].code == class)
4732 if (err_classes[i].err_msgs)
4734 err_code_struct *err = err_classes[i].err_msgs;
4735 for (j=0;err[j].name;j++)
4736 if (num == err[j].code)
4738 if (DEBUGLEVEL > 0)
4739 sprintf(ret,"%s - %s (%s)",err_classes[i].class,
4740 err[j].name,err[j].message);
4741 else
4742 sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
4743 return ret;
4747 sprintf(ret,"%s - %d",err_classes[i].class,num);
4748 return ret;
4751 sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num);
4752 return(ret);