2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1998
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.
30 pstring cur_dir = "\\";
32 extern pstring service;
33 extern pstring desthost;
34 extern pstring global_myname;
35 extern pstring myhostname;
36 extern pstring password;
37 extern pstring username;
38 extern pstring workgroup;
42 extern BOOL connect_as_printer;
43 extern BOOL connect_as_ipc;
44 extern struct in_addr ipzero;
46 extern BOOL doencrypt;
48 extern pstring user_socket_options;
50 static int process_tok(fstring tok);
51 static void cmd_help(char *dum_in, char *dum_out);
53 /* 30 second timeout on most commands */
54 #define CLIENT_TIMEOUT (30*1000)
55 #define SHORT_TIMEOUT (5*1000)
57 /* value for unused fid field in trans2 secondary request */
58 #define FID_UNUSED (0xFFFF)
62 extern int max_protocol;
65 time_t newer_than = 0;
66 int archive_level = 0;
68 extern pstring debugf;
69 extern int DEBUGLEVEL;
71 BOOL translation = False;
83 static int interpret_long_filename(int level,char *p,file_info *finfo);
84 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo);
85 static int interpret_short_filename(char *p,file_info *finfo);
86 static BOOL do_this_one(file_info *finfo);
88 /* clitar bits insert */
91 extern BOOL tar_reset;
103 BOOL recurse = False;
104 BOOL lowercase = False;
106 struct in_addr dest_ip;
108 #define SEPARATORS " \t\n\r"
110 BOOL abort_mget = True;
114 extern BOOL readbraw_supported ;
115 extern BOOL writebraw_supported;
117 pstring fileselection = "";
119 extern file_info def_finfo;
122 int get_total_size = 0;
123 int get_total_time_ms = 0;
124 int put_total_size = 0;
125 int put_total_time_ms = 0;
134 #define CNV_LANG(s) dos_to_unix(s,False)
135 #define CNV_INPUT(s) unix_to_dos(s,True)
137 /****************************************************************************
138 send an SMBclose on an SMB file handle
139 ****************************************************************************/
140 static void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
142 bzero(outbuf,smb_size);
143 set_message(outbuf,3,0,True);
145 CVAL (outbuf,smb_com) = SMBclose;
146 SSVAL(outbuf,smb_tid,c_num);
147 cli_setup_pkt(outbuf);
148 SSVAL (outbuf,smb_vwv0, f_num);
149 SIVALS(outbuf,smb_vwv1, -1);
151 send_smb(clnt_fd, outbuf);
152 client_receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
156 /****************************************************************************
157 write to a local file with CR/LF->LF translation if appropriate. return the
158 number taken from the buffer. This may not equal the number written.
159 ****************************************************************************/
160 static int writefile(int f, char *b, int n)
165 return(write(f,b,n));
170 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
174 if (write(f, b, 1) != 1)
185 /****************************************************************************
186 read from a file with LF->CR/LF translation if appropriate. return the
187 number read. read approx n bytes.
188 ****************************************************************************/
189 static int readfile(char *b, int size, int n, FILE *f)
194 if (!translation || (size != 1))
195 return(fread(b,size,n,f));
200 if ((c = getc(f)) == EOF)
205 if (c == '\n') /* change all LFs to CR/LF */
219 /****************************************************************************
220 read from a file with print translation. return the number read. read approx n
222 ****************************************************************************/
223 static int printread(FILE *f,char *b,int n)
227 i = readfile(b,1, n-1,f);
236 /****************************************************************************
237 check for existance of a dir
238 ****************************************************************************/
239 static BOOL chkpath(char *path,BOOL report)
242 pstring inbuf,outbuf;
246 trim_string(path2,NULL,"\\");
247 if (!*path2) *path2 = '\\';
249 bzero(outbuf,smb_size);
250 set_message(outbuf,0,4 + strlen(path2),True);
251 SCVAL(outbuf,smb_com,SMBchkpth);
252 SSVAL(outbuf,smb_tid,cnum);
253 cli_setup_pkt(outbuf);
261 /* this little bit of code can be used to extract NT error codes.
262 Just feed a bunch of "cd foo" commands to smbclient then watch
263 in netmon (tridge) */
265 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
266 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
271 send_smb(Client,outbuf);
272 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
274 if (report && CVAL(inbuf,smb_rcls) != 0)
275 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
277 return(CVAL(inbuf,smb_rcls) == 0);
281 /****************************************************************************
283 ****************************************************************************/
284 static void send_message(char *inbuf,char *outbuf)
291 /* send a SMBsendstrt command */
292 bzero(outbuf,smb_size);
293 set_message(outbuf,0,0,True);
294 CVAL(outbuf,smb_com) = SMBsendstrt;
295 SSVAL(outbuf,smb_tid,cnum);
300 p = skip_string(p,1);
303 p = skip_string(p,1);
305 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
307 send_smb(Client,outbuf);
310 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
312 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
316 grp_id = SVAL(inbuf,smb_vwv0);
318 printf("Connected. Type your message, ending it with a Control-D\n");
320 while (!feof(stdin) && total_len < 1600)
322 int maxlen = MIN(1600 - total_len,127);
329 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
336 CVAL(outbuf,smb_com) = SMBsendtxt;
338 set_message(outbuf,1,l+3,True);
340 SSVAL(outbuf,smb_vwv0,grp_id);
347 send_smb(Client,outbuf);
350 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
352 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
359 if (total_len >= 1600)
360 printf("the message was truncated to 1600 bytes ");
362 printf("sent %d bytes ",total_len);
364 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
366 CVAL(outbuf,smb_com) = SMBsendend;
367 set_message(outbuf,1,0,False);
368 SSVAL(outbuf,smb_vwv0,grp_id);
370 send_smb(Client,outbuf);
373 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
375 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
382 /****************************************************************************
383 check the space on a device
384 ****************************************************************************/
385 static void do_dskattr(void)
387 pstring inbuf,outbuf;
389 bzero(outbuf,smb_size);
390 set_message(outbuf,0,0,True);
391 CVAL(outbuf,smb_com) = SMBdskattr;
392 SSVAL(outbuf,smb_tid,cnum);
393 cli_setup_pkt(outbuf);
395 send_smb(Client,outbuf);
396 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
398 if (CVAL(inbuf,smb_rcls) != 0)
399 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
401 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
402 SVAL(inbuf,smb_vwv0),
403 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
404 SVAL(inbuf,smb_vwv3)));
407 /****************************************************************************
409 ****************************************************************************/
410 static void cmd_pwd(char *dum_in, char *dum_out)
412 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
413 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
417 /****************************************************************************
418 change directory - inner section
419 ****************************************************************************/
420 static void do_cd(char *newdir)
426 /* Save the current directory in case the
427 new directory is invalid */
428 pstrcpy(saved_dir, cur_dir);
433 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
434 pstrcat(cur_dir, "\\");
436 dos_clean_name(cur_dir);
437 pstrcpy(dname,cur_dir);
438 pstrcat(cur_dir,"\\");
439 dos_clean_name(cur_dir);
441 if (!strequal(cur_dir,"\\"))
442 if (!chkpath(dname,True))
443 pstrcpy(cur_dir,saved_dir);
445 pstrcpy(cd_path,cur_dir);
448 /****************************************************************************
450 ****************************************************************************/
451 static void cmd_cd(char *inbuf,char *outbuf)
455 if (next_token(NULL,buf,NULL,sizeof(buf)))
458 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
462 /****************************************************************************
463 display info about a file
464 ****************************************************************************/
465 static void display_finfo(file_info *finfo)
467 if (do_this_one(finfo)) {
468 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
469 DEBUG(0,(" %-30s%7.7s%.0f %s",
470 CNV_LANG(finfo->name),
471 attrib_string(finfo->mode),
473 asctime(LocalTime(&t))));
474 dir_total += finfo->size;
479 /****************************************************************************
480 calculate size of a file
481 ****************************************************************************/
482 static void do_du(file_info *finfo)
484 if (do_this_one(finfo)) {
485 dir_total += finfo->size;
490 /****************************************************************************
491 do a directory listing, calling fn on each file found. Use the TRANSACT2
492 call for long filenames
493 ****************************************************************************/
494 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
496 int max_matches = 512;
497 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
502 char *dirlist = NULL;
504 int total_received = 0;
506 char *resp_data=NULL;
507 char *resp_param=NULL;
508 int resp_data_len = 0;
509 int resp_param_len=0;
511 int ff_resume_key = 0;
512 int ff_searchcount=0;
526 if (loop_count > 200)
528 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
534 setup = TRANSACT2_FINDFIRST;
535 SSVAL(param,0,attribute); /* attribute */
536 SSVAL(param,2,max_matches); /* max count */
537 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
538 SSVAL(param,6,info_level);
540 pstrcpy(param+12,mask);
544 setup = TRANSACT2_FINDNEXT;
545 SSVAL(param,0,ff_dir_handle);
546 SSVAL(param,2,max_matches); /* max count */
547 SSVAL(param,4,info_level);
548 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
549 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
550 pstrcpy(param+12,mask);
552 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
553 ff_dir_handle,ff_resume_key,ff_lastname,mask));
555 /* ??? original code added 1 pad byte after param */
557 cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
559 0,12+strlen(mask)+1,1,
562 if (!cli_receive_trans_response(inbuf,SMBtrans2,
563 &resp_data_len,&resp_param_len,
564 &resp_data,&resp_param))
566 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
570 /* parse out some important return info */
574 ff_dir_handle = SVAL(p,0);
575 ff_searchcount = SVAL(p,2);
577 ff_lastname = SVAL(p,8);
581 ff_searchcount = SVAL(p,0);
583 ff_lastname = SVAL(p,6);
586 if (ff_searchcount == 0)
589 /* point to the data bytes */
592 /* we might need the lastname for continuations */
599 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
600 /* pstrcpy(mask,p+ff_lastname+94); */
603 pstrcpy(mask,p + ff_lastname + 1);
611 /* and add them to the dirlist pool */
612 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
616 DEBUG(0,("Failed to expand dirlist\n"));
620 /* put in a length for the last entry, to ensure we can chain entries
621 into the next packet */
624 for (p2=p,i=0;i<(ff_searchcount-1);i++)
625 p2 += interpret_long_filename(info_level,p2,NULL);
626 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
629 /* grab the data for later use */
630 memcpy(dirlist+dirlist_len,p,resp_data_len);
631 dirlist_len += resp_data_len;
633 total_received += ff_searchcount;
635 if (resp_data) free(resp_data); resp_data = NULL;
636 if (resp_param) free(resp_param); resp_param = NULL;
638 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
639 ff_searchcount,ff_eos,ff_resume_key));
645 for (p=dirlist,i=0;i<total_received;i++)
647 p += interpret_long_filename(info_level,p,&finfo);
648 display_finfo(&finfo);
651 for (p=dirlist,i=0;i<total_received;i++)
653 p += interpret_long_filename(info_level,p,&finfo);
654 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True, dirstoo);
657 /* free up the dirlist buffer */
658 if (dirlist) free(dirlist);
659 return(total_received);
663 /****************************************************************************
664 do a directory listing, calling fn on each file found
665 ****************************************************************************/
666 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
672 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
673 int num_received = 0;
675 char *dirlist = NULL;
687 bzero(outbuf,smb_size);
689 set_message(outbuf,2,5 + strlen(mask),True);
691 set_message(outbuf,2,5 + 21,True);
694 if (Protocol >= PROTOCOL_LANMAN1)
695 CVAL(outbuf,smb_com) = SMBffirst;
698 CVAL(outbuf,smb_com) = SMBsearch;
700 SSVAL(outbuf,smb_tid,cnum);
701 cli_setup_pkt(outbuf);
703 SSVAL(outbuf,smb_vwv0,num_asked);
704 SSVAL(outbuf,smb_vwv1,attribute);
725 send_smb(Client,outbuf);
726 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
728 received = SVAL(inbuf,smb_vwv0);
730 DEBUG(5,("dir received %d\n",received));
732 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
734 if (received <= 0) break;
738 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
743 p = smb_buf(inbuf) + 3;
745 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
746 p,received*DIR_STRUCT_SIZE);
748 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
750 num_received += received;
752 if (CVAL(inbuf,smb_rcls) != 0) break;
756 if (!first && Protocol >= PROTOCOL_LANMAN1)
758 bzero(outbuf,smb_size);
759 CVAL(outbuf,smb_com) = SMBfclose;
761 SSVAL(outbuf,smb_tid,cnum);
762 cli_setup_pkt(outbuf);
775 send_smb(Client,outbuf);
776 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
778 if (CVAL(inbuf,smb_rcls) != 0)
779 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
784 for (p=dirlist,i=0;i<num_received;i++)
786 p += interpret_short_filename(p,&finfo);
787 display_finfo(&finfo);
790 for (p=dirlist,i=0;i<num_received;i++)
792 p += interpret_short_filename(p,&finfo);
793 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False,dirstoo);
796 if (dirlist) free(dirlist);
797 return(num_received);
802 /****************************************************************************
803 do a directory listing, calling fn on each file found
804 ****************************************************************************/
805 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
807 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
808 if (Protocol >= PROTOCOL_LANMAN2)
810 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo) > 0)
814 expand_mask(Mask,False);
815 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo);
819 /*******************************************************************
820 decide if a file should be operated on
821 ********************************************************************/
822 static BOOL do_this_one(file_info *finfo)
824 if (finfo->mode & aDIR) return(True);
826 if (newer_than && finfo->mtime < newer_than)
829 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
836 /*****************************************************************************
837 Convert a character pointer in a cli_call_api() response to a form we can use.
838 This function contains code to prevent core dumps if the server returns
840 *****************************************************************************/
841 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
843 if( datap == 0 ) /* turn NULL pointers */
844 { /* into zero length strings */
849 unsigned int offset = datap - converter;
851 if( offset >= rdrcnt )
853 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
858 return &rdata[offset];
863 /****************************************************************************
864 interpret a short filename structure
865 The length of the structure is returned
866 ****************************************************************************/
867 static int interpret_short_filename(char *p,file_info *finfo)
869 finfo->mode = CVAL(p,21);
871 /* this date is converted to GMT by make_unix_date */
872 finfo->ctime = make_unix_date(p+22);
873 finfo->mtime = finfo->atime = finfo->ctime;
874 finfo->size = IVAL(p,26);
875 pstrcpy(finfo->name,p+30);
877 return(DIR_STRUCT_SIZE);
880 /****************************************************************************
881 interpret a long filename structure - this is mostly guesses at the moment
882 The length of the structure is returned
883 The structure of a long filename depends on the info level. 260 is used
884 by NT and 2 is used by OS/2
885 ****************************************************************************/
886 static int interpret_long_filename(int level,char *p,file_info *finfo)
889 memcpy(finfo,&def_finfo,sizeof(*finfo));
893 case 1: /* OS/2 understands this */
896 /* these dates are converted to GMT by make_unix_date */
897 finfo->ctime = make_unix_date2(p+4);
898 finfo->atime = make_unix_date2(p+8);
899 finfo->mtime = make_unix_date2(p+12);
900 finfo->size = IVAL(p,16);
901 finfo->mode = CVAL(p,24);
902 pstrcpy(finfo->name,p+27);
904 return(28 + CVAL(p,26));
906 case 2: /* this is what OS/2 uses mostly */
909 /* these dates are converted to GMT by make_unix_date */
910 finfo->ctime = make_unix_date2(p+4);
911 finfo->atime = make_unix_date2(p+8);
912 finfo->mtime = make_unix_date2(p+12);
913 finfo->size = IVAL(p,16);
914 finfo->mode = CVAL(p,24);
915 pstrcpy(finfo->name,p+31);
917 return(32 + CVAL(p,30));
919 /* levels 3 and 4 are untested */
923 /* these dates are probably like the other ones */
924 finfo->ctime = make_unix_date2(p+8);
925 finfo->atime = make_unix_date2(p+12);
926 finfo->mtime = make_unix_date2(p+16);
927 finfo->size = IVAL(p,20);
928 finfo->mode = CVAL(p,28);
929 pstrcpy(finfo->name,p+33);
936 /* these dates are probably like the other ones */
937 finfo->ctime = make_unix_date2(p+8);
938 finfo->atime = make_unix_date2(p+12);
939 finfo->mtime = make_unix_date2(p+16);
940 finfo->size = IVAL(p,20);
941 finfo->mode = CVAL(p,28);
942 pstrcpy(finfo->name,p+37);
946 case 260: /* NT uses this, but also accepts 2 */
951 p += 4; /* next entry offset */
952 p += 4; /* fileindex */
954 /* these dates appear to arrive in a weird way. It seems to
955 be localtime plus the serverzone given in the initial
956 connect. This is GMT when DST is not in effect and one
957 hour from GMT otherwise. Can this really be right??
959 I suppose this could be called kludge-GMT. Is is the GMT
960 you get by using the current DST setting on a different
961 localtime. It will be cheap to calculate, I suppose, as
962 no DST tables will be needed */
964 finfo->ctime = interpret_long_date(p); p += 8;
965 finfo->atime = interpret_long_date(p); p += 8;
966 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
967 finfo->size = IVAL(p,0); p += 8;
968 p += 8; /* alloc size */
969 finfo->mode = CVAL(p,0); p += 4;
970 namelen = IVAL(p,0); p += 4;
971 p += 4; /* EA size */
972 p += 2; /* short name len? */
973 p += 24; /* short name? */
974 StrnCpy(finfo->name,p,namelen);
980 DEBUG(1,("Unknown long filename format %d\n",level));
987 /****************************************************************************
988 act on the files in a dir listing
990 RJS, 4-Apr-1998, dirstoo added to allow caller to indicate that directories
991 should be processed as well.
992 ****************************************************************************/
993 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo)
996 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
997 !mask_match(finfo->name,fileselection,False,False)) &&
998 !(recurse_dir && (strequal(finfo->name,".") ||
999 strequal(finfo->name,".."))))
1001 if (recurse_dir && (finfo->mode & aDIR))
1006 if (fn && dirstoo && do_this_one(finfo)) { /* Do dirs, RJS */
1010 pstrcpy(sav_dir,cur_dir);
1011 pstrcat(cur_dir,finfo->name);
1012 pstrcat(cur_dir,"\\");
1013 pstrcpy(mask2,cur_dir);
1016 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1021 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1023 do_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1025 pstrcpy(cur_dir,sav_dir);
1029 if (fn && do_this_one(finfo))
1036 /****************************************************************************
1037 get a directory listing
1038 ****************************************************************************/
1039 static void cmd_dir(char *inbuf,char *outbuf)
1041 int attribute = aDIR | aSYSTEM | aHIDDEN;
1047 pstrcpy(mask,cur_dir);
1048 if(mask[strlen(mask)-1]!='\\')
1051 if (next_token(NULL,buf,NULL,sizeof(buf)))
1062 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse,False);
1066 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1070 /****************************************************************************
1071 get a directory listing
1072 ****************************************************************************/
1073 static void cmd_du(char *inbuf,char *outbuf)
1075 int attribute = aDIR | aSYSTEM | aHIDDEN;
1081 pstrcpy(mask,cur_dir);
1082 if(mask[strlen(mask)-1]!='\\')
1085 if (next_token(NULL,buf,NULL,sizeof(buf)))
1096 do_dir(inbuf,outbuf,mask,attribute,do_du,recurse,False);
1100 DEBUG(0, ("Total number of bytes: %d\n", dir_total));
1103 /****************************************************************************
1104 get a file from rname to lname
1105 ****************************************************************************/
1106 static void do_get(char *rname,char *lname,file_info *finfo1)
1111 BOOL newhandle = False;
1112 char *inbuf,*outbuf;
1114 BOOL close_done = False;
1115 BOOL ignore_close_error = False;
1119 struct timeval tp_start;
1120 GetTimeOfDay(&tp_start);
1131 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1132 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1134 if (!inbuf || !outbuf)
1136 DEBUG(0,("out of memory\n"));
1140 bzero(outbuf,smb_size);
1141 set_message(outbuf,15,1 + strlen(rname),True);
1143 CVAL(outbuf,smb_com) = SMBopenX;
1144 SSVAL(outbuf,smb_tid,cnum);
1145 cli_setup_pkt(outbuf);
1147 SSVAL(outbuf,smb_vwv0,0xFF);
1148 SSVAL(outbuf,smb_vwv2,1); /* return additional info */
1149 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1150 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1151 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1152 SSVAL(outbuf,smb_vwv8,1);
1153 SSVAL(outbuf,smb_vwv11,0xffff);
1154 SSVAL(outbuf,smb_vwv12,0xffff);
1156 p = smb_buf(outbuf);
1158 p = skip_string(p,1);
1160 /* do a chained openX with a readX? */
1164 DEBUG(3,("Chaining readX wth openX\n"));
1165 SSVAL(outbuf,smb_vwv0,SMBreadX);
1166 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1169 SCVAL(p,smb_wct,10);
1170 SSVAL(p,smb_vwv0,0xFF);
1171 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1172 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1173 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1177 if(!strcmp(lname,"-"))
1178 handle = fileno(stdout);
1181 handle = creat(lname,0644);
1186 DEBUG(0,("Error opening local file %s\n",lname));
1187 free(inbuf);free(outbuf);
1191 send_smb(Client,outbuf);
1192 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1194 if (CVAL(inbuf,smb_rcls) != 0)
1196 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1197 SVAL(inbuf,smb_err) == ERRnoresource &&
1198 cli_reopen_connection(inbuf,outbuf))
1200 do_get(rname,lname,finfo1);
1203 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1206 free(inbuf);free(outbuf);
1210 pstrcpy(finfo.name,rname);
1214 finfo.mode = SVAL(inbuf,smb_vwv3);
1215 /* these times arrive as LOCAL time, using the DST offset
1216 corresponding to that time, we convert them to GMT */
1217 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1218 finfo.atime = finfo.ctime = finfo.mtime;
1219 finfo.size = IVAL(inbuf,smb_vwv6);
1222 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1224 fnum = SVAL(inbuf,smb_vwv2);
1226 /* we might have got some data from a chained readX */
1227 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1229 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1230 datalen = SVAL(p,smb_vwv5);
1231 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1240 DEBUG(2,("getting file %s of size %.0f bytes as %s ",
1241 CNV_LANG(finfo.name),
1245 while (nread < finfo.size && !close_done)
1248 static BOOL can_chain_close = True;
1252 DEBUG(3,("nread=%d max_xmit=%d fsize=%.0f\n",nread,max_xmit,(double)finfo.size));
1254 /* 3 possible read types. readbraw if a large block is required.
1255 readX + close if not much left and read if neither is supported */
1257 /* we might have already read some data from a chained readX */
1258 if (dataptr && datalen>0)
1261 /* if we can finish now then readX+close */
1262 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1263 ((finfo.size - nread) <
1264 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1267 /* if we support readraw then use that */
1268 if (method<0 && readbraw_supported)
1271 /* if we can then use readX */
1272 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1283 /* use readX + close */
1284 bzero(outbuf,smb_size);
1285 set_message(outbuf,10,0,True);
1286 CVAL(outbuf,smb_com) = SMBreadX;
1287 SSVAL(outbuf,smb_tid,cnum);
1288 cli_setup_pkt(outbuf);
1292 CVAL(outbuf,smb_vwv0) = SMBclose;
1293 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1296 CVAL(outbuf,smb_vwv0) = 0xFF;
1298 SSVAL(outbuf,smb_vwv2,fnum);
1299 SIVAL(outbuf,smb_vwv3,nread);
1300 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1301 SSVAL(outbuf,smb_vwv6,0);
1302 SIVAL(outbuf,smb_vwv7,0);
1303 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1307 p = smb_buf(outbuf);
1314 /* now set the total packet length */
1315 smb_setlen(outbuf,smb_len(outbuf)+9);
1318 send_smb(Client,outbuf);
1319 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1321 if (CVAL(inbuf,smb_rcls) != 0)
1323 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1328 SVAL(inbuf,smb_vwv0) != SMBclose)
1330 /* NOTE: WfWg sometimes just ignores the chained
1331 command! This seems to break the spec? */
1332 DEBUG(3,("Rejected chained close?\n"));
1334 can_chain_close = False;
1335 ignore_close_error = True;
1338 datalen = SVAL(inbuf,smb_vwv5);
1339 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1345 static int readbraw_size = BUFFER_SIZE;
1348 bzero(outbuf,smb_size);
1349 set_message(outbuf,8,0,True);
1350 CVAL(outbuf,smb_com) = SMBreadbraw;
1351 SSVAL(outbuf,smb_tid,cnum);
1352 cli_setup_pkt(outbuf);
1353 SSVAL(outbuf,smb_vwv0,fnum);
1354 SIVAL(outbuf,smb_vwv1,nread);
1355 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1356 SSVAL(outbuf,smb_vwv4,0);
1357 SIVALS(outbuf,smb_vwv5,-1);
1358 send_smb(Client,outbuf);
1360 /* Now read the raw data into the buffer and write it */
1361 if(read_smb_length(Client,inbuf,0) == -1) {
1362 DEBUG(0,("Failed to read length in readbraw\n"));
1366 /* Even though this is not an smb message, smb_len
1367 returns the generic length of an smb message */
1368 datalen = smb_len(inbuf);
1372 /* we got a readbraw error */
1373 DEBUG(4,("readbraw error - reducing size\n"));
1374 readbraw_size = (readbraw_size * 9) / 10;
1376 if (readbraw_size < max_xmit)
1378 DEBUG(0,("disabling readbraw\n"));
1379 readbraw_supported = False;
1386 if(read_data(Client,inbuf,datalen) != datalen) {
1387 DEBUG(0,("Failed to read data in readbraw\n"));
1395 /* we've already read some data with a chained readX */
1399 /* use plain read */
1400 bzero(outbuf,smb_size);
1401 set_message(outbuf,5,0,True);
1402 CVAL(outbuf,smb_com) = SMBread;
1403 SSVAL(outbuf,smb_tid,cnum);
1404 cli_setup_pkt(outbuf);
1406 SSVAL(outbuf,smb_vwv0,fnum);
1407 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1408 SIVAL(outbuf,smb_vwv2,nread);
1409 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1411 send_smb(Client,outbuf);
1412 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1414 if (CVAL(inbuf,smb_rcls) != 0)
1416 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1420 datalen = SVAL(inbuf,smb_vwv0);
1421 dataptr = smb_buf(inbuf) + 3;
1425 if (writefile(handle,dataptr,datalen) != datalen)
1427 DEBUG(0,("Error writing local file\n"));
1434 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1446 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1448 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1450 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1453 free(inbuf);free(outbuf);
1461 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1462 bzero(outbuf,smb_size);
1463 set_message(outbuf,8,strlen(rname)+4,True);
1464 CVAL(outbuf,smb_com) = SMBsetatr;
1465 SSVAL(outbuf,smb_tid,cnum);
1466 cli_setup_pkt(outbuf);
1467 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1468 SIVALS(outbuf,smb_vwv1,0);
1469 p = smb_buf(outbuf);
1475 send_smb(Client,outbuf);
1476 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1480 struct timeval tp_end;
1483 GetTimeOfDay(&tp_end);
1485 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1486 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1487 get_total_time_ms += this_time;
1488 get_total_size += finfo.size;
1490 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1491 finfo.size / (1.024*this_time + 1.0e-4),
1492 get_total_size / (1.024*get_total_time_ms)));
1495 free(inbuf);free(outbuf);
1499 /****************************************************************************
1501 ****************************************************************************/
1502 static void cmd_get(char *dum_in, char *dum_out)
1508 pstrcpy(rname,cur_dir);
1509 pstrcat(rname,"\\");
1511 p = rname + strlen(rname);
1513 if (!next_token(NULL,p,NULL,sizeof(rname)-strlen(rname))) {
1514 DEBUG(0,("get <filename>\n"));
1518 dos_clean_name(rname);
1520 next_token(NULL,lname,NULL,sizeof(lname));
1522 do_get(rname,lname,NULL);
1526 /****************************************************************************
1527 do a mget operation on one file
1528 ****************************************************************************/
1529 static void do_mget(file_info *finfo)
1534 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1539 DEBUG(0,("mget aborted\n"));
1543 if (finfo->mode & aDIR)
1544 slprintf(quest,sizeof(pstring)-1,
1545 "Get directory %s? ",CNV_LANG(finfo->name));
1547 slprintf(quest,sizeof(pstring)-1,
1548 "Get file %s? ",CNV_LANG(finfo->name));
1550 if (prompt && !yesno(quest)) return;
1552 if (finfo->mode & aDIR)
1554 pstring saved_curdir;
1556 char *inbuf,*outbuf;
1558 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1559 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1561 if (!inbuf || !outbuf)
1563 DEBUG(0,("out of memory\n"));
1567 pstrcpy(saved_curdir,cur_dir);
1569 pstrcat(cur_dir,finfo->name);
1570 pstrcat(cur_dir,"\\");
1572 unix_format(finfo->name);
1575 strlower(finfo->name);
1577 if (!directory_exist(finfo->name,NULL) &&
1578 dos_mkdir(finfo->name,0777) != 0)
1580 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1581 pstrcpy(cur_dir,saved_curdir);
1582 free(inbuf);free(outbuf);
1586 if (dos_chdir(finfo->name) != 0)
1588 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1589 pstrcpy(cur_dir,saved_curdir);
1590 free(inbuf);free(outbuf);
1595 pstrcpy(mget_mask,cur_dir);
1596 pstrcat(mget_mask,"*");
1598 do_dir((char *)inbuf,(char *)outbuf,
1599 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False, False);
1601 pstrcpy(cur_dir,saved_curdir);
1602 free(inbuf);free(outbuf);
1606 pstrcpy(rname,cur_dir);
1607 pstrcat(rname,finfo->name);
1608 do_get(rname,finfo->name,finfo);
1612 /****************************************************************************
1613 view the file using the pager
1614 ****************************************************************************/
1615 static void cmd_more(char *dum_in, char *dum_out)
1617 fstring rname,lname,tmpname,pager_cmd;
1620 fstrcpy(rname,cur_dir);
1621 fstrcat(rname,"\\");
1624 "%s/smbmore.%d",tmpdir(),(int)getpid());
1625 fstrcpy(lname,tmpname);
1627 if (!next_token(NULL,rname+strlen(rname),NULL,sizeof(rname)-strlen(rname))) {
1628 DEBUG(0,("more <filename>\n"));
1631 dos_clean_name(rname);
1633 do_get(rname,lname,NULL);
1635 pager=getenv("PAGER");
1637 slprintf(pager_cmd,sizeof(pager_cmd)-1,
1638 "%s %s",(pager? pager:PAGER), tmpname);
1645 /****************************************************************************
1647 ****************************************************************************/
1648 static void cmd_mget(char *inbuf,char *outbuf)
1650 int attribute = aSYSTEM | aHIDDEN;
1662 while (next_token(NULL,p,NULL,sizeof(buf)))
1664 pstrcpy(mget_mask,cur_dir);
1665 if(mget_mask[strlen(mget_mask)-1]!='\\')
1666 pstrcat(mget_mask,"\\");
1669 pstrcpy(mget_mask,p);
1671 pstrcat(mget_mask,p);
1672 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1677 pstrcpy(mget_mask,cur_dir);
1678 if(mget_mask[strlen(mget_mask)-1]!='\\')
1679 pstrcat(mget_mask,"\\");
1680 pstrcat(mget_mask,"*");
1681 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1685 /****************************************************************************
1686 make a directory of name "name"
1687 ****************************************************************************/
1688 static BOOL do_mkdir(char *name)
1691 char *inbuf,*outbuf;
1693 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1694 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1696 if (!inbuf || !outbuf)
1698 DEBUG(0,("out of memory\n"));
1702 bzero(outbuf,smb_size);
1703 set_message(outbuf,0,2 + strlen(name),True);
1705 CVAL(outbuf,smb_com) = SMBmkdir;
1706 SSVAL(outbuf,smb_tid,cnum);
1707 cli_setup_pkt(outbuf);
1710 p = smb_buf(outbuf);
1714 send_smb(Client,outbuf);
1715 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1717 if (CVAL(inbuf,smb_rcls) != 0)
1719 DEBUG(0,("%s making remote directory %s\n",
1720 smb_errstr(inbuf),CNV_LANG(name)));
1722 free(inbuf);free(outbuf);
1726 free(inbuf);free(outbuf);
1731 /****************************************************************************
1733 ****************************************************************************/
1734 static void cmd_mkdir(char *inbuf,char *outbuf)
1740 pstrcpy(mask,cur_dir);
1742 if (!next_token(NULL,p,NULL,sizeof(buf)))
1745 DEBUG(0,("mkdir <dirname>\n"));
1757 trim_string(ddir,".",NULL);
1758 p = strtok(ddir,"/\\");
1762 if (!chkpath(ddir2,False))
1766 pstrcat(ddir2,"\\");
1767 p = strtok(NULL,"/\\");
1775 /*******************************************************************
1776 write to a file using writebraw
1777 ********************************************************************/
1778 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1783 bzero(outbuf,smb_size);
1784 bzero(inbuf,smb_size);
1785 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1787 CVAL(outbuf,smb_com) = SMBwritebraw;
1788 SSVAL(outbuf,smb_tid,cnum);
1789 cli_setup_pkt(outbuf);
1791 SSVAL(outbuf,smb_vwv0,fnum);
1792 SSVAL(outbuf,smb_vwv1,n);
1793 SIVAL(outbuf,smb_vwv3,pos);
1794 SSVAL(outbuf,smb_vwv7,1);
1796 send_smb(Client,outbuf);
1798 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1801 _smb_setlen(buf-4,n); /* HACK! XXXX */
1803 if (write_socket(Client,buf-4,n+4) != n+4)
1806 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1807 DEBUG(0,("Error writing remote file (2)\n"));
1810 return(SVAL(inbuf,smb_vwv0));
1815 /*******************************************************************
1817 ********************************************************************/
1818 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1822 if (writebraw_supported && n > (max_xmit-200))
1823 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1825 bzero(outbuf,smb_size);
1826 bzero(inbuf,smb_size);
1827 set_message(outbuf,5,n + 3,True);
1829 CVAL(outbuf,smb_com) = SMBwrite;
1830 SSVAL(outbuf,smb_tid,cnum);
1831 cli_setup_pkt(outbuf);
1833 SSVAL(outbuf,smb_vwv0,fnum);
1834 SSVAL(outbuf,smb_vwv1,n);
1835 SIVAL(outbuf,smb_vwv2,pos);
1836 SSVAL(outbuf,smb_vwv4,0);
1837 CVAL(smb_buf(outbuf),0) = 1;
1838 SSVAL(smb_buf(outbuf),1,n);
1840 memcpy(smb_buf(outbuf)+3,buf,n);
1842 send_smb(Client,outbuf);
1843 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1845 if (CVAL(inbuf,smb_rcls) != 0) {
1846 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1849 return(SVAL(inbuf,smb_vwv0));
1854 /****************************************************************************
1856 ****************************************************************************/
1857 static void do_put(char *rname,char *lname,file_info *finfo)
1863 char *inbuf,*outbuf;
1864 time_t close_time = finfo->mtime;
1866 static int maxwrite=0;
1868 struct timeval tp_start;
1869 GetTimeOfDay(&tp_start);
1871 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1872 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1874 if (!inbuf || !outbuf)
1876 DEBUG(0,("out of memory\n"));
1880 bzero(outbuf,smb_size);
1881 set_message(outbuf,3,2 + strlen(rname),True);
1883 if (finfo->mtime == 0 || finfo->mtime == -1)
1884 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1886 CVAL(outbuf,smb_com) = SMBcreate;
1887 SSVAL(outbuf,smb_tid,cnum);
1888 cli_setup_pkt(outbuf);
1890 SSVAL(outbuf,smb_vwv0,finfo->mode);
1891 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1893 p = smb_buf(outbuf);
1897 send_smb(Client,outbuf);
1898 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1900 if (CVAL(inbuf,smb_rcls) != 0)
1902 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1904 free(inbuf);free(outbuf);if (buf) free(buf);
1908 /* allow files to be piped into smbclient
1909 jdblair 24.jun.98 */
1910 if (!strcmp(lname, "-")) {
1912 /* size of file is not known */
1915 f = fopen(lname,"r");
1920 DEBUG(0,("Error opening local file %s\n",lname));
1921 free(inbuf);free(outbuf);
1926 fnum = SVAL(inbuf,smb_vwv0);
1927 if (finfo->size < 0)
1928 finfo->size = file_size(lname);
1930 DEBUG(1,("putting file %s of size %.0f bytes as %s ",lname,(double)finfo->size,CNV_LANG(rname)));
1933 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1935 /* This is a rewrite of the read/write loop that doesn't require the input
1936 file to be of a known length. This allows the stream pointer 'f' to
1939 Rather than reallocing the read buffer every loop to keep it the min
1940 necessary length this look uses a fixed length buffer and just tests
1941 for eof on the file stream at the top of each loop.
1942 jdblair, 24.jun.98 */
1944 buf = (char *)malloc(maxwrite+4);
1950 fseek(f,nread,SEEK_SET);
1951 if ((n = readfile(buf+4,1,n,f)) < 1)
1953 DEBUG(0,("Error reading local file\n"));
1957 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1961 DEBUG(0,("Error writing file\n"));
1972 bzero(outbuf,smb_size);
1973 set_message(outbuf,3,0,True);
1974 CVAL(outbuf,smb_com) = SMBclose;
1975 SSVAL(outbuf,smb_tid,cnum);
1976 cli_setup_pkt(outbuf);
1978 SSVAL(outbuf,smb_vwv0,fnum);
1979 put_dos_date3(outbuf,smb_vwv1,close_time);
1981 send_smb(Client,outbuf);
1982 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1984 if (CVAL(inbuf,smb_rcls) != 0)
1986 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1988 free(inbuf);free(outbuf);
1995 free(inbuf);free(outbuf);
1999 struct timeval tp_end;
2002 GetTimeOfDay(&tp_end);
2004 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
2005 (tp_end.tv_usec - tp_start.tv_usec)/1000;
2006 put_total_time_ms += this_time;
2007 put_total_size += finfo->size;
2009 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
2010 finfo->size / (1.024*this_time + 1.0e-4),
2011 put_total_size / (1.024*put_total_time_ms)));
2017 /****************************************************************************
2019 ****************************************************************************/
2020 static void cmd_put(char *dum_in, char *dum_out)
2029 pstrcpy(rname,cur_dir);
2030 pstrcat(rname,"\\");
2033 if (!next_token(NULL,p,NULL,sizeof(buf)))
2035 DEBUG(0,("put <filename>\n"));
2040 if (next_token(NULL,p,NULL,sizeof(buf)))
2043 pstrcat(rname,lname);
2045 dos_clean_name(rname);
2049 /* allow '-' to represent stdin
2050 jdblair, 24.jun.98 */
2051 if (!file_exist(lname,&st) &&
2052 (strcmp(lname,"-"))) {
2053 DEBUG(0,("%s does not exist\n",lname));
2056 finfo.mtime = st.st_mtime;
2059 do_put(rname,lname,&finfo);
2062 /****************************************************************************
2063 seek in a directory/file list until you get something that doesn't start with
2065 ****************************************************************************/
2066 static BOOL seek_list(FILE *f,char *name)
2071 if (fscanf(f,"%s",s) != 1) return(False);
2072 trim_string(s,"./",NULL);
2073 if (strncmp(s,name,strlen(name)) != 0)
2084 /****************************************************************************
2085 set the file selection mask
2086 ****************************************************************************/
2087 static void cmd_select(char *dum_in, char *dum_out)
2089 pstrcpy(fileselection,"");
2090 next_token(NULL,fileselection,NULL,sizeof(fileselection));
2094 /****************************************************************************
2096 ****************************************************************************/
2097 static void cmd_mput(char *dum_in, char *dum_out)
2108 while (next_token(NULL,p,NULL,sizeof(buf)))
2115 slprintf(tmpname,sizeof(pstring)-1,
2116 "%s/ls.smb.%d",tmpdir(),(int)getpid());
2118 slprintf(cmd,sizeof(pstring)-1,
2119 "find . -name \"%s\" -print > %s",p,tmpname);
2121 slprintf(cmd,sizeof(pstring)-1,
2122 "/bin/ls %s > %s",p,tmpname);
2125 f = fopen(tmpname,"r");
2132 if (fscanf(f,"%s",lname) != 1) break;
2133 trim_string(lname,"./",NULL);
2137 /* check if it's a directory */
2138 if (directory_exist(lname,&st))
2140 if (!recurse) continue;
2141 slprintf(quest,sizeof(pstring)-1,
2142 "Put directory %s? ",lname);
2143 if (prompt && !yesno(quest))
2146 if (!seek_list(f,lname))
2151 pstrcpy(rname,cur_dir);
2152 pstrcat(rname,lname);
2153 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2155 if (!seek_list(f,lname))
2164 slprintf(quest,sizeof(quest)-1,
2165 "Put file %s? ",lname);
2166 if (prompt && !yesno(quest)) continue;
2168 pstrcpy(rname,cur_dir);
2169 pstrcat(rname,lname);
2173 /* null size so do_put knows to ignore it */
2176 /* set the date on the file */
2177 finfo.mtime = st.st_mtime;
2179 do_put(rname,lname,&finfo);
2186 /****************************************************************************
2188 ****************************************************************************/
2189 static void do_cancel(int job)
2191 char *rparam = NULL;
2197 bzero(param,sizeof(param));
2200 SSVAL(p,0,81); /* DosPrintJobDel() */
2203 p = skip_string(p,1);
2205 p = skip_string(p,1);
2209 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2215 int res = SVAL(rparam,0);
2218 printf("Job %d cancelled\n",job);
2220 printf("Error %d calcelling job %d\n",res,job);
2224 printf("Server refused cancel request\n");
2226 if (rparam) free(rparam);
2227 if (rdata) free(rdata);
2233 /****************************************************************************
2235 ****************************************************************************/
2236 static void cmd_cancel(char *inbuf,char *outbuf )
2241 if (!connect_as_printer)
2243 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2244 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2247 if (!next_token(NULL,buf,NULL,sizeof(buf))) {
2248 printf("cancel <jobid> ...\n");
2254 } while (next_token(NULL,buf,NULL,sizeof(buf)));
2260 /****************************************************************************
2262 ****************************************************************************/
2263 static void cmd_print(char *inbuf,char *outbuf )
2272 if (!connect_as_printer)
2274 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2275 DEBUG(0,("Trying to print without -P may fail\n"));
2278 if (!next_token(NULL,lname,NULL, sizeof(lname)))
2280 DEBUG(0,("print <filename>\n"));
2284 pstrcpy(rname,lname);
2285 p = strrchr(rname,'/');
2290 pstrcpy(rname,tname);
2293 if ((int)strlen(rname) > 14)
2296 if (strequal(lname,"-"))
2299 pstrcpy(rname,"stdin");
2302 dos_clean_name(rname);
2304 bzero(outbuf,smb_size);
2305 set_message(outbuf,2,2 + strlen(rname),True);
2307 CVAL(outbuf,smb_com) = SMBsplopen;
2308 SSVAL(outbuf,smb_tid,cnum);
2309 cli_setup_pkt(outbuf);
2311 SSVAL(outbuf,smb_vwv0,0);
2312 SSVAL(outbuf,smb_vwv1,printmode);
2314 p = smb_buf(outbuf);
2318 send_smb(Client,outbuf);
2319 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2321 if (CVAL(inbuf,smb_rcls) != 0)
2323 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2328 f = fopen(lname,"r");
2331 DEBUG(0,("Error opening local file %s\n",lname));
2336 fnum = SVAL(inbuf,smb_vwv0);
2338 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2344 bzero(outbuf,smb_size);
2345 set_message(outbuf,1,3,True);
2347 /* for some strange reason the OS/2 print server can't handle large
2348 packets when printing. weird */
2349 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2352 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2354 n = readfile(smb_buf(outbuf)+3,1,n,f);
2357 DEBUG(0,("read gave %d\n",n));
2361 smb_setlen(outbuf,smb_len(outbuf) + n);
2363 CVAL(outbuf,smb_com) = SMBsplwr;
2364 SSVAL(outbuf,smb_tid,cnum);
2365 cli_setup_pkt(outbuf);
2367 SSVAL(outbuf,smb_vwv0,fnum);
2368 SSVAL(outbuf,smb_vwv1,n+3);
2369 CVAL(smb_buf(outbuf),0) = 1;
2370 SSVAL(smb_buf(outbuf),1,n);
2372 send_smb(Client,outbuf);
2373 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2375 if (CVAL(inbuf,smb_rcls) != 0)
2377 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2384 DEBUG(2,("%d bytes printed\n",nread));
2386 bzero(outbuf,smb_size);
2387 set_message(outbuf,1,0,True);
2388 CVAL(outbuf,smb_com) = SMBsplclose;
2389 SSVAL(outbuf,smb_tid,cnum);
2390 cli_setup_pkt(outbuf);
2392 SSVAL(outbuf,smb_vwv0,fnum);
2394 send_smb(Client,outbuf);
2395 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2397 if (CVAL(inbuf,smb_rcls) != 0)
2399 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2409 /****************************************************************************
2410 show a print queue - this is deprecated as it uses the old smb that
2411 has limited support - the correct call is the cmd_p_queue_4() after this.
2412 ****************************************************************************/
2413 static void cmd_queue(char *inbuf,char *outbuf )
2418 bzero(outbuf,smb_size);
2419 set_message(outbuf,2,0,True);
2421 CVAL(outbuf,smb_com) = SMBsplretq;
2422 SSVAL(outbuf,smb_tid,cnum);
2423 cli_setup_pkt(outbuf);
2425 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2426 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2428 send_smb(Client,outbuf);
2429 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2431 if (CVAL(inbuf,smb_rcls) != 0)
2433 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2437 count = SVAL(inbuf,smb_vwv0);
2438 p = smb_buf(inbuf) + 3;
2441 DEBUG(0,("No entries in the print queue\n"));
2448 DEBUG(0,("Job Name Size Status\n"));
2454 case 0x01: safe_strcpy(status,"held or stopped", sizeof(status)-1); break;
2455 case 0x02: safe_strcpy(status,"printing",sizeof(status)-1); break;
2456 case 0x03: safe_strcpy(status,"awaiting print", sizeof(status)-1); break;
2457 case 0x04: safe_strcpy(status,"in intercept",sizeof(status)-1); break;
2458 case 0x05: safe_strcpy(status,"file had error",sizeof(status)-1); break;
2459 case 0x06: safe_strcpy(status,"printer error",sizeof(status)-1); break;
2460 default: safe_strcpy(status,"unknown",sizeof(status)-1); break;
2463 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2464 SVAL(p,5),p+12,IVAL(p,7),status));
2472 /****************************************************************************
2473 show information about a print queue
2474 ****************************************************************************/
2475 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2477 char *rparam = NULL;
2484 if (!connect_as_printer)
2486 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2487 DEBUG(0,("Trying to print without -P may fail\n"));
2490 bzero(param,sizeof(param));
2493 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2495 pstrcpy(p,"zWrLeh"); /* parameter description? */
2496 p = skip_string(p,1);
2497 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
2498 p = skip_string(p,1);
2499 pstrcpy(p,strrchr(service,'\\')+1); /* name of queue */
2500 p = skip_string(p,1);
2501 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2502 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2504 pstrcpy(p,""); /* subformat */
2505 p = skip_string(p,1);
2507 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2508 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2515 result_code = SVAL(rparam,0);
2516 converter = SVAL(rparam,2); /* conversion factor */
2518 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2520 if (result_code == 0) /* if no error, */
2530 fstring PrinterName;
2532 fstrcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2533 strlower(PrinterName); /* in lower case */
2535 p = rdata; /* received data */
2536 for( i = 0; i < SVAL(rparam,4); ++i)
2539 Priority = SVAL(p,2);
2540 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2542 Priority = SVAL(p,2);
2543 JobTime = make_unix_date3( p + 12);
2544 JobTimeStr = asctime(LocalTime( &JobTime));
2546 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2549 printf("%s-%u %s priority %u %s %s %u bytes\n",
2550 PrinterName, JobId, UserName,
2551 Priority, JobTimeStr, JobName, Size);
2553 #if 0 /* DEBUG code */
2554 printf("Job Id: \"%u\"\n", SVAL(p,0));
2555 printf("Priority: \"%u\"\n", SVAL(p,2));
2557 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2558 printf("Position: \"%u\"\n", SVAL(p,8));
2559 printf("Status: \"%u\"\n", SVAL(p,10));
2561 JobTime = make_unix_date3( p + 12);
2562 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2563 printf("date: \"%u\"\n", SVAL(p,12));
2565 printf("Size: \"%u\"\n", SVAL(p,16));
2566 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2567 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2568 #endif /* DEBUG CODE */
2573 else /* cli_call_api() failed */
2575 printf("Failed, error = %d\n", result_code);
2578 /* If any parameters or data were returned, free the storage. */
2579 if(rparam) free(rparam);
2580 if(rdata) free(rdata);
2585 /****************************************************************************
2586 show information about a print queue
2587 ****************************************************************************/
2588 static void cmd_qinfo(char *inbuf,char *outbuf )
2590 char *rparam = NULL;
2597 bzero(param,sizeof(param));
2600 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2602 pstrcpy(p,"zWrLh"); /* parameter description? */
2603 p = skip_string(p,1);
2604 pstrcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2605 p = skip_string(p,1);
2606 pstrcpy(p,strrchr(service,'\\')+1); /* name of queue */
2607 p = skip_string(p,1);
2608 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2609 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2611 pstrcpy(p,""); /* subformat */
2612 p = skip_string(p,1);
2614 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2615 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2622 result_code = SVAL(rparam,0);
2623 converter = SVAL(rparam,2); /* conversion factor */
2625 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2627 if (result_code == 0) /* if no error, */
2629 p = rdata; /* received data */
2631 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2632 printf("Priority: %u\n", SVAL(p,4) );
2633 printf("Start time: %u\n", SVAL(p,6) );
2634 printf("Until time: %u\n", SVAL(p,8) );
2635 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2636 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2637 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2638 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2639 printf("Status: %u\n", SVAL(p,28) );
2640 printf("Jobs: %u\n", SVAL(p,30) );
2641 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2642 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2644 /* Dump the driver data */
2649 ddptr = rdata + SVAL(p,40) - converter;
2650 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2651 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2653 for(x=8; x < count; x+=16)
2655 for(y=0; y < 16; y++)
2658 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2662 for(y=0; y < 16 && (x+y) < count; y++)
2664 c = CVAL(ddptr,(x+y));
2670 fputc('\n', stdout);
2676 else /* cli_call_api() failed */
2678 printf("Failed, error = %d\n", result_code);
2681 /* If any parameters or data were returned, free the storage. */
2682 if(rparam) free(rparam);
2683 if(rdata) free(rdata);
2688 /****************************************************************************
2690 ****************************************************************************/
2691 static void do_del(file_info *finfo)
2694 char *inbuf,*outbuf;
2697 pstrcpy(mask,cur_dir);
2698 pstrcat(mask,finfo->name);
2700 if (finfo->mode & aDIR)
2703 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2704 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2706 if (!inbuf || !outbuf)
2708 DEBUG(0,("out of memory\n"));
2712 bzero(outbuf,smb_size);
2713 set_message(outbuf,1,2 + strlen(mask),True);
2715 CVAL(outbuf,smb_com) = SMBunlink;
2716 SSVAL(outbuf,smb_tid,cnum);
2717 cli_setup_pkt(outbuf);
2719 SSVAL(outbuf,smb_vwv0,0);
2721 p = smb_buf(outbuf);
2725 send_smb(Client,outbuf);
2726 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2728 if (CVAL(inbuf,smb_rcls) != 0)
2729 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2731 free(inbuf);free(outbuf);
2735 /****************************************************************************
2737 ****************************************************************************/
2738 static void cmd_del(char *inbuf,char *outbuf )
2742 int attribute = aSYSTEM | aHIDDEN;
2747 pstrcpy(mask,cur_dir);
2749 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2751 DEBUG(0,("del <filename>\n"));
2756 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False,False);
2760 /****************************************************************************
2762 ****************************************************************************/
2763 static void cmd_rmdir(char *inbuf,char *outbuf )
2769 pstrcpy(mask,cur_dir);
2771 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2773 DEBUG(0,("rmdir <dirname>\n"));
2778 bzero(outbuf,smb_size);
2779 set_message(outbuf,0,2 + strlen(mask),True);
2781 CVAL(outbuf,smb_com) = SMBrmdir;
2782 SSVAL(outbuf,smb_tid,cnum);
2783 cli_setup_pkt(outbuf);
2786 p = smb_buf(outbuf);
2790 send_smb(Client,outbuf);
2791 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2793 if (CVAL(inbuf,smb_rcls) != 0)
2795 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2801 /****************************************************************************
2803 ****************************************************************************/
2804 static void cmd_rename(char *inbuf,char *outbuf )
2810 pstrcpy(src,cur_dir);
2811 pstrcpy(dest,cur_dir);
2813 if (!next_token(NULL,buf,NULL,sizeof(buf)) ||
2814 !next_token(NULL,buf2,NULL, sizeof(buf2)))
2816 DEBUG(0,("rename <src> <dest>\n"));
2822 bzero(outbuf,smb_size);
2823 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2825 CVAL(outbuf,smb_com) = SMBmv;
2826 SSVAL(outbuf,smb_tid,cnum);
2827 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2828 cli_setup_pkt(outbuf);
2830 p = smb_buf(outbuf);
2833 p = skip_string(p,1);
2837 send_smb(Client,outbuf);
2838 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2840 if (CVAL(inbuf,smb_rcls) != 0)
2842 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2849 /****************************************************************************
2850 toggle the prompt flag
2851 ****************************************************************************/
2852 static void cmd_prompt(char *dum_in, char *dum_out)
2855 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2859 /****************************************************************************
2860 set the newer than time
2861 ****************************************************************************/
2862 static void cmd_newer(char *dum_in, char *dum_out)
2866 SMB_STRUCT_STAT sbuf;
2868 ok = next_token(NULL,buf,NULL,sizeof(buf));
2869 if (ok && (dos_stat(buf,&sbuf) == 0))
2871 newer_than = sbuf.st_mtime;
2872 DEBUG(1,("Getting files newer than %s",
2873 asctime(LocalTime(&newer_than))));
2878 if (ok && newer_than == 0)
2879 DEBUG(0,("Error setting newer-than time\n"));
2882 /****************************************************************************
2883 set the archive level
2884 ****************************************************************************/
2885 static void cmd_archive(char *dum_in, char *dum_out)
2889 if (next_token(NULL,buf,NULL,sizeof(buf))) {
2890 archive_level = atoi(buf);
2892 DEBUG(0,("Archive level is %d\n",archive_level));
2895 /****************************************************************************
2896 toggle the lowercaseflag
2897 ****************************************************************************/
2898 static void cmd_lowercase(char *dum_in, char *dum_out)
2900 lowercase = !lowercase;
2901 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2907 /****************************************************************************
2908 toggle the recurse flag
2909 ****************************************************************************/
2910 static void cmd_recurse(char *dum_in, char *dum_out)
2913 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2916 /****************************************************************************
2917 toggle the translate flag
2918 ****************************************************************************/
2919 static void cmd_translate(char *dum_in, char *dum_out)
2921 translation = !translation;
2922 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2923 translation?"on":"off"));
2927 /****************************************************************************
2928 do a printmode command
2929 ****************************************************************************/
2930 static void cmd_printmode(char *dum_in, char *dum_out)
2935 if (next_token(NULL,buf,NULL,sizeof(buf)))
2937 if (strequal(buf,"text"))
2941 if (strequal(buf,"graphics"))
2944 printmode = atoi(buf);
2951 fstrcpy(mode,"text");
2954 fstrcpy(mode,"graphics");
2957 slprintf(mode,sizeof(mode)-1,"%d",printmode);
2961 DEBUG(2,("the printmode is now %s\n",mode));
2964 /****************************************************************************
2966 ****************************************************************************/
2967 static void cmd_lcd(char *dum_in, char *dum_out)
2972 if (next_token(NULL,buf,NULL,sizeof(buf)))
2974 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2978 /****************************************************************************
2979 try and browse available connections on a host
2980 ****************************************************************************/
2981 static BOOL browse_host(BOOL sort)
2983 char *rparam = NULL;
2990 /* now send a SMBtrans command with api RNetShareEnum */
2992 SSVAL(p,0,0); /* api number */
2995 p = skip_string(p,1);
2996 pstrcpy(p,"B13BWz");
2997 p = skip_string(p,1);
2999 SSVAL(p,2,BUFFER_SIZE);
3002 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3008 int res = SVAL(rparam,0);
3009 int converter=SVAL(rparam,2);
3011 BOOL long_share_name=False;
3013 if (res == 0 || res == ERRmoredata)
3015 count=SVAL(rparam,4);
3020 printf("\n\tSharename Type Comment\n");
3021 printf("\t--------- ---- -------\n");
3025 qsort(p,count,20,QSORT_CAST StrCaseCmp);
3027 for (i=0;i<count;i++)
3030 int type = SVAL(p,14);
3031 int comment_offset = IVAL(p,16) & 0xFFFF;
3037 case STYPE_DISKTREE:
3038 fstrcpy(typestr,"Disk"); break;
3040 fstrcpy(typestr,"Printer"); break;
3042 fstrcpy(typestr,"Device"); break;
3044 fstrcpy(typestr,"IPC"); break;
3047 printf("\t%-15.15s%-10.10s%s\n",
3049 comment_offset?rdata+comment_offset-converter:"");
3051 if (strlen(sname)>8) long_share_name=True;
3056 if (long_share_name) {
3057 printf("\nNOTE: There were share names longer than 8 chars.\n\
3058 On older clients these may not be accessible or may give browsing errors\n");
3061 if(res == ERRmoredata)
3062 printf("\nNOTE: More data was available, the list was truncated.\n");
3066 if (rparam) free(rparam);
3067 if (rdata) free(rdata);
3073 /****************************************************************************
3074 get some server info
3075 ****************************************************************************/
3076 static void server_info(void)
3078 char *rparam = NULL;
3084 bzero(param,sizeof(param));
3087 SSVAL(p,0,63); /* NetServerGetInfo()? */
3090 p = skip_string(p,1);
3091 pstrcpy(p,"zzzBBzz");
3092 p = skip_string(p,1);
3093 SSVAL(p,0,10); /* level 10 */
3097 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3103 int res = SVAL(rparam,0);
3104 int converter=SVAL(rparam,2);
3110 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3111 rdata+SVAL(p,0)-converter,
3112 rdata+SVAL(p,4)-converter,
3113 rdata+SVAL(p,8)-converter,
3114 rdata+SVAL(p,14)-converter);
3118 if (rparam) free(rparam);
3119 if (rdata) free(rdata);
3125 /****************************************************************************
3126 try and browse available connections on a host
3127 ****************************************************************************/
3128 static BOOL list_servers(char *wk_grp)
3130 char *rparam = NULL;
3138 BOOL generic_request = False;
3141 if (strequal(wk_grp,"WORKGROUP")) {
3142 /* we won't specify a workgroup */
3143 generic_request = True;
3146 /* now send a SMBtrans command with api ServerEnum? */
3148 SSVAL(p,0,0x68); /* api number */
3151 pstrcpy(p,generic_request?"WrLehDO":"WrLehDz");
3152 p = skip_string(p,1);
3154 pstrcpy(p,"B16BBDz");
3156 p = skip_string(p,1);
3158 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3164 if (!generic_request) {
3166 p = skip_string(p,1);
3169 /* first ask for a list of servers in this workgroup */
3170 SIVAL(svtype_p,0,SV_TYPE_ALL);
3172 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3173 8, BUFFER_SIZE - SAFETY_MARGIN,
3178 int res = SVAL(rparam,0);
3179 int converter=SVAL(rparam,2);
3182 if (res == 0 || res == ERRmoredata) {
3184 count=SVAL(rparam,4);
3187 printf("\n\nThis machine has a browse list:\n");
3188 printf("\n\tServer Comment\n");
3189 printf("\t--------- -------\n");
3192 for (i=0;i<count;i++) {
3194 int comment_offset = IVAL(p2,22) & 0xFFFF;
3195 printf("\t%-16.16s %s\n", sname,
3196 comment_offset?rdata+comment_offset-converter:"");
3202 if(res == ERRmoredata)
3203 printf("\nNOTE: More data was available, the list was truncated.\n");
3207 if (rparam) {free(rparam); rparam = NULL;}
3208 if (rdata) {free(rdata); rdata = NULL;}
3210 /* now ask for a list of workgroups */
3211 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3213 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3214 8, BUFFER_SIZE - SAFETY_MARGIN,
3219 int res = SVAL(rparam,0);
3220 int converter=SVAL(rparam,2);
3223 if (res == 0 || res == ERRmoredata) {
3225 count=SVAL(rparam,4);
3228 printf("\n\nThis machine has a workgroup list:\n");
3229 printf("\n\tWorkgroup Master\n");
3230 printf("\t--------- -------\n");
3233 for (i=0;i<count;i++) {
3235 int comment_offset = IVAL(p2,22) & 0xFFFF;
3236 printf("\t%-16.16s %s\n", sname,
3237 comment_offset?rdata+comment_offset-converter:"");
3243 if(res == ERRmoredata)
3244 printf("\nNOTE: More data was available, the list was truncated.\n");
3248 if (rparam) free(rparam);
3249 if (rdata) free(rdata);
3255 /* Some constants for completing filename arguments */
3257 #define COMPL_NONE 0 /* No completions */
3258 #define COMPL_REMOTE 1 /* Complete remote filename */
3259 #define COMPL_LOCAL 2 /* Complete local filename */
3261 /* This defines the commands supported by this client */
3265 void (*fn)(char *, char *);
3267 char compl_args[2]; /* Completion argument info */
3270 {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3271 {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3272 {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3273 {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
3274 {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
3275 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
3276 {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
3277 {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
3278 {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
3279 {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
3280 {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
3281 {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},
3282 {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
3283 {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
3284 {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
3285 {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
3286 {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
3287 {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
3288 {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
3289 {"pq",cmd_p_queue_4,"enumerate the print queue",{COMPL_NONE,COMPL_NONE}},
3290 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
3291 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},
3292 {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
3293 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},
3294 {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
3295 {"printmode",cmd_printmode,"<graphics or text> set the print mode",{COMPL_NONE,COMPL_NONE}},
3296 {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}},
3297 {"qinfo",cmd_qinfo,"show print queue information",{COMPL_NONE,COMPL_NONE}},
3298 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
3299 {"quit",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3300 {"q",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3301 {"exit",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3302 {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
3303 {"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",{COMPL_NONE,COMPL_NONE}},
3304 {"tar",cmd_tar,"tar <c|x>[IXbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
3305 {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
3306 {"tarmode",cmd_tarmode,
3307 "<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
3308 {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
3309 {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
3310 {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
3311 {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
3312 {"",NULL,NULL,{COMPL_NONE,COMPL_NONE}}
3316 /*******************************************************************
3317 lookup a command string in the list of commands, including
3319 ******************************************************************/
3320 static int process_tok(fstring tok)
3322 int i = 0, matches = 0;
3324 int tok_len = strlen(tok);
3326 while (commands[i].fn != NULL)
3328 if (strequal(commands[i].name,tok))
3334 else if (strnequal(commands[i].name, tok, tok_len))
3344 else if (matches == 1)
3350 /****************************************************************************
3352 ****************************************************************************/
3353 static void cmd_help(char *dum_in, char *dum_out)
3358 if (next_token(NULL,buf,NULL,sizeof(buf)))
3360 if ((i = process_tok(buf)) >= 0)
3361 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3364 while (commands[i].description)
3366 for (j=0; commands[i].description && (j<5); j++) {
3367 DEBUG(0,("%-15s",commands[i].name));
3376 /****************************************************************************
3377 wait for keyboard activity, swallowing network packets
3378 ****************************************************************************/
3379 static void wait_keyboard(char *buffer)
3383 struct timeval timeout;
3389 FD_SET(Client,&fds);
3390 FD_SET(fileno(stdin),&fds);
3392 timeout.tv_sec = 20;
3393 timeout.tv_usec = 0;
3394 selrtn = sys_select(MAX(Client,fileno(stdin))+1,&fds,&timeout);
3396 if (FD_ISSET(fileno(stdin),&fds))
3399 /* We deliberately use receive_smb instead of
3400 client_receive_smb as we want to receive
3401 session keepalives and then drop them here.
3403 if (FD_ISSET(Client,&fds))
3404 receive_smb(Client,buffer,0);
3406 chkpath("\\",False);
3410 #ifdef HAVE_LIBREADLINE
3412 /****************************************************************************
3413 completion routines for GNU Readline
3414 ****************************************************************************/
3416 /* To avoid filename completion being activated when no valid
3417 completions are found, we assign this stub completion function
3418 to the rl_completion_entry_function variable. */
3420 char *complete_cmd_null(char *text, int state)
3425 /* Argh. This is starting to get ugly. We need to be able to pass data
3426 back from the do_dir() iterator function. */
3428 static int compl_state;
3429 static char *compl_text;
3430 static pstring result;
3432 /* Iterator function for do_dir() */
3434 void complete_process_file(file_info *f)
3436 /* Do we have a partial match? */
3438 if ((compl_state >= 0) && (strncmp(compl_text, f->name,
3439 strlen(compl_text)) == 0)) {
3441 /* Return filename if we have made enough matches */
3443 if (compl_state == 0) {
3444 pstrcpy(result, f->name);
3453 /* Complete a remote file */
3455 char *complete_remote_file(char *text, int state)
3457 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3458 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3459 int attribute = aDIR | aSYSTEM | aHIDDEN;
3462 if ((InBuffer == NULL) || (OutBuffer == NULL))
3465 /* Create dir mask */
3467 pstrcpy(mask, cur_dir);
3470 /* Initialise static vars for filename match */
3473 compl_state = state;
3476 /* Iterate over all files in directory */
3478 do_dir(InBuffer, OutBuffer, mask, attribute, complete_process_file, False,
3486 /* Return matched filename */
3488 if (result[0] != '\0') {
3489 return strdup(result); /* Readline will dispose of strings */
3495 /* Complete a smbclient command */
3497 char *complete_cmd(char *text, int state)
3499 static int cmd_index;
3508 /* Return the next name which partially matches the list of commands */
3510 while (strlen(name = commands[cmd_index++].name) > 0) {
3511 if (strncmp(name, text, strlen(text)) == 0) {
3512 return strdup(name);
3519 /* Main completion function for smbclient. Work out which word we are
3520 trying to complete and call the appropriate function. */
3522 char **completion_fn(char *text, int start, int end)
3524 int i, num_words, cmd_index;
3527 /* If we are at the start of a word, we are completing a smbclient
3531 return completion_matches(text, complete_cmd);
3534 /* Count # of words in command */
3537 for (i = 0; i <= end; i++) {
3538 if ((rl_line_buffer[i] != ' ') && (lastch == ' '))
3540 lastch = rl_line_buffer[i];
3543 if (rl_line_buffer[end] == ' ')
3546 /* Work out which command we are completing for */
3548 for (cmd_index = 0; strcmp(commands[cmd_index].name, "") != 0;
3551 /* Check each command in array */
3553 if (strncmp(rl_line_buffer, commands[cmd_index].name,
3554 strlen(commands[cmd_index].name)) == 0) {
3556 /* Call appropriate completion function */
3558 if ((num_words == 2) || (num_words == 3)) {
3559 switch (commands[cmd_index].compl_args[num_words - 2]) {
3562 return completion_matches(text, complete_remote_file);
3566 return completion_matches(text, filename_completion_function);
3570 /* An invalid completion type */
3575 /* We're either completing an argument > 3 or found an invalid
3576 completion type. Either way do nothing about it. */
3585 #endif /* HAVE_LIBREADLINE */
3587 /****************************************************************************
3588 process commands from the client
3589 ****************************************************************************/
3590 static BOOL process(char *base_directory)
3595 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3596 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3598 if ((InBuffer == NULL) || (OutBuffer == NULL))
3601 bzero(OutBuffer,smb_size);
3603 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3606 if (*base_directory) do_cd(base_directory);
3609 if (cmd[0] != '\0') while (cmd[0] != '\0')
3615 if ((p = strchr(cmd, ';')) == 0)
3617 strncpy(line, cmd, 999);
3623 if (p - cmd > 999) p = cmd + 999;
3624 strncpy(line, cmd, p - cmd);
3625 line[p - cmd] = '\0';
3629 /* input language code to internal one */
3632 /* and get the first part of the command */
3635 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
3638 if ((i = process_tok(tok)) >= 0)
3639 commands[i].fn(InBuffer,OutBuffer);
3641 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3643 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3645 else while (!feof(stdin))
3650 bzero(OutBuffer,smb_size);
3652 #ifdef HAVE_LIBREADLINE
3657 /* Read input using GNU Readline */
3659 slprintf(prompt, sizeof(prompt) - 1, "smb: %s> ", CNV_LANG(cur_dir));
3660 if (!readline(prompt))
3663 /* Copy read line to samba buffer */
3665 pstrcpy(line, rl_line_buffer);
3666 pstrcat(line, "\n");
3668 /* Add line to history */
3670 if (strlen(line) > 0)
3676 /* display a prompt */
3677 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3680 wait_keyboard(InBuffer);
3682 /* and get a response */
3683 if (!fgets(line,1000,stdin))
3688 /* input language code to internal one */
3691 /* special case - first char is ! */
3698 /* and get the first part of the command */
3701 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
3704 if ((i = process_tok(tok)) >= 0)
3705 commands[i].fn(InBuffer,OutBuffer);
3707 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3709 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3712 cli_send_logout(InBuffer,OutBuffer);
3716 /****************************************************************************
3717 usage on the program
3718 ****************************************************************************/
3719 static void usage(char *pname)
3721 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3724 DEBUG(0,("\nVersion %s\n",VERSION));
3725 DEBUG(0,("\t-p port connect to the specified port\n"));
3726 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3727 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3728 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3729 DEBUG(0,("\t-N don't ask for a password\n"));
3730 DEBUG(0,("\t-P connect to service as a printer\n"));
3731 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3732 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3733 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3734 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3735 DEBUG(0,("\t-R name resolve order use these name resolution services only\n"));
3736 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3737 DEBUG(0,("\t-U username set the network username\n"));
3738 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3739 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3740 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3741 DEBUG(0,("\t-T<c|x>IXgbNan command line tar\n"));
3742 DEBUG(0,("\t-D directory start from directory\n"));
3746 /****************************************************************************
3748 ****************************************************************************/
3749 int main(int argc,char *argv[])
3751 fstring base_directory;
3752 char *pname = argv[0];
3753 int port = SMB_PORT;
3756 extern char *optarg;
3759 BOOL message = False;
3760 BOOL nt_domain_logon = False;
3761 BOOL explicit_user = False;
3762 extern char tar_type;
3763 static pstring servicesf = CONFIGFILE;
3765 pstring new_name_resolve_order;
3769 pstrcpy(term_code, KANJI);
3775 *base_directory = 0;
3777 *new_name_resolve_order = 0;
3781 setup_logging(pname,True);
3784 charset_initialise();
3786 if(!get_myname(myhostname,NULL))
3788 DEBUG(0,("Failed to get my hostname.\n"));
3791 if (!lp_load(servicesf,True,False,False)) {
3792 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3795 codepage_initialise(lp_client_code_page());
3797 interpret_coding_system(term_code);
3803 pstrcpy(workgroup,lp_workgroup());
3815 pstrcpy(username,getenv("USER"));
3817 /* modification to support userid%passwd syntax in the USER var
3818 25.Aug.97, jdblair@uab.edu */
3820 if ((p=strchr(username,'%')))
3823 pstrcpy(password,p+1);
3825 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3830 /* modification to support PASSWD environmental var
3831 25.Aug.97, jdblair@uab.edu */
3833 if (getenv("PASSWD")) {
3834 pstrcpy(password,getenv("PASSWD"));
3838 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
3844 if ((p = getenv("PASSWD_FD")) != NULL) {
3845 pstrcpy(spec, "descriptor ");
3847 sscanf(p, "%d", &fd);
3849 } else if ((p = getenv("PASSWD_FILE")) != NULL) {
3850 fd = open(p, O_RDONLY);
3853 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
3854 spec, strerror(errno));
3859 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
3860 p && p - pass < sizeof(pass);) {
3861 switch (read(fd, p, 1)) {
3863 if (*p != '\n' && *p != '\0') {
3864 *++p = '\0'; /* advance p, and null-terminate pass */
3869 *p = '\0'; /* null-terminate it, just in case... */
3870 p = NULL; /* then force the loop condition to become false */
3873 fprintf(stderr, "Error reading password from file %s: %s\n",
3874 spec, "empty password\n");
3879 fprintf(stderr, "Error reading password from file %s: %s\n",
3880 spec, strerror(errno));
3884 pstrcpy(password, pass);
3890 if (*username == 0 && getenv("LOGNAME"))
3892 pstrcpy(username,getenv("LOGNAME"));
3902 if (*argv[1] != '-')
3905 pstrcpy(service,argv[1]);
3906 /* Convert any '/' characters in the service name to '\' characters */
3907 string_replace( service, '/','\\');
3911 if (count_chars(service,'\\') < 3)
3914 printf("\n%s: Not enough '\\' characters in service\n",service);
3919 if (count_chars(service,'\\') > 3)
3922 printf("\n%s: Too many '\\' characters in service\n",service);
3927 if (argc > 1 && (*argv[1] != '-'))
3930 pstrcpy(password,argv[1]);
3931 memset(argv[1],'X',strlen(argv[1]));
3938 getopt(argc, argv,"s:B:O:R:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
3942 max_protocol = interpret_protocol(optarg,max_protocol);
3945 pstrcpy(user_socket_options,optarg);
3948 pstrcpy(new_name_resolve_order, optarg);
3951 pstrcpy(desthost,optarg);
3953 nt_domain_logon = True;
3956 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3957 pstrcpy(desthost,optarg);
3962 iface_set_default(NULL,optarg,NULL);
3965 pstrcpy(base_directory,optarg);
3968 if (!tar_parseargs(argc, argv, optarg, optind)) {
3974 pstrcpy(scope,optarg);
3978 pstrcpy(query_host,optarg);
3985 explicit_user = True;
3986 pstrcpy(username,optarg);
3987 if ((lp=strchr(username,'%')))
3990 pstrcpy(password,lp+1);
3992 memset(strchr(optarg,'%')+1,'X',strlen(password));
3998 pstrcpy(workgroup,optarg);
4005 dest_ip = *interpret_addr2(optarg);
4006 if (zero_ip(dest_ip)) exit(1);
4011 pstrcpy(global_myname,optarg);
4018 connect_as_printer = True;
4024 DEBUGLEVEL = atoi(optarg);
4027 slprintf(debugf,sizeof(debugf)-1, "%s.client",optarg);
4030 port = atoi(optarg);
4041 pstrcpy(servicesf, optarg);
4044 pstrcpy(term_code, optarg);
4051 get_myname((*global_myname)?NULL:global_myname,NULL);
4052 strupper(global_myname);
4054 if(*new_name_resolve_order)
4055 lp_set_name_resolve_order(new_name_resolve_order);
4057 if (!tar_type && !*query_host && !*service && !message)
4063 #ifdef HAVE_LIBREADLINE
4065 /* Initialise GNU Readline */
4067 rl_readline_name = "smbclient";
4068 rl_attempted_completion_function = completion_fn;
4069 rl_completion_entry_function = (Function *)complete_cmd_null;
4071 /* Initialise history list */
4075 #endif /* HAVE_LIBREADLINE */
4077 DEBUG( 3, ( "Client started (version %s).\n", VERSION ) );
4082 if (cli_open_sockets(port)) {
4083 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4084 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4087 if ((InBuffer == NULL) || (OutBuffer == NULL))
4090 bzero(OutBuffer,smb_size);
4091 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
4094 if (*base_directory) do_cd(base_directory);
4096 ret=process_tar(InBuffer, OutBuffer);
4098 cli_send_logout(InBuffer, OutBuffer);
4105 if (*query_host && !nt_domain_logon)
4108 slprintf(service,sizeof(service)-1,
4109 "\\\\%s\\IPC$",query_host);
4111 connect_as_ipc = True;
4112 if (cli_open_sockets(port))
4117 if (!cli_send_login(NULL,NULL,True,True,NULL))
4121 if (!browse_host(True)) {
4125 if (!list_servers(workgroup)) {
4127 list_servers(workgroup);
4130 cli_send_logout(NULL,NULL);
4140 if (cli_open_sockets(port))
4142 pstring inbuf,outbuf;
4143 bzero(outbuf,smb_size);
4144 if (!cli_send_session_request(inbuf,outbuf))
4147 send_message(inbuf,outbuf);
4155 if (cli_open_sockets(port))
4157 if (!process(base_directory))