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 do a directory listing, calling fn on each file found. Use the TRANSACT2
481 call for long filenames
482 ****************************************************************************/
483 static int do_long_dir(char *inbuf
,char *outbuf
,char *Mask
,int attribute
,void (*fn
)(file_info
*),BOOL recurse_dir
, BOOL dirstoo
)
485 int max_matches
= 512;
486 int info_level
= Protocol
<PROTOCOL_NT1
?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
491 char *dirlist
= NULL
;
493 int total_received
= 0;
495 char *resp_data
=NULL
;
496 char *resp_param
=NULL
;
497 int resp_data_len
= 0;
498 int resp_param_len
=0;
500 int ff_resume_key
= 0;
501 int ff_searchcount
=0;
515 if (loop_count
> 200)
517 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
523 setup
= TRANSACT2_FINDFIRST
;
524 SSVAL(param
,0,attribute
); /* attribute */
525 SSVAL(param
,2,max_matches
); /* max count */
526 SSVAL(param
,4,8+4+2); /* resume required + close on end + continue */
527 SSVAL(param
,6,info_level
);
529 pstrcpy(param
+12,mask
);
533 setup
= TRANSACT2_FINDNEXT
;
534 SSVAL(param
,0,ff_dir_handle
);
535 SSVAL(param
,2,max_matches
); /* max count */
536 SSVAL(param
,4,info_level
);
537 SIVAL(param
,6,ff_resume_key
); /* ff_resume_key */
538 SSVAL(param
,10,8+4+2); /* resume required + close on end + continue */
539 pstrcpy(param
+12,mask
);
541 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
542 ff_dir_handle
,ff_resume_key
,ff_lastname
,mask
));
544 /* ??? original code added 1 pad byte after param */
546 cli_send_trans_request(outbuf
,SMBtrans2
,NULL
,0,FID_UNUSED
,0,
548 0,12+strlen(mask
)+1,1,
551 if (!cli_receive_trans_response(inbuf
,SMBtrans2
,
552 &resp_data_len
,&resp_param_len
,
553 &resp_data
,&resp_param
))
555 DEBUG(3,("FIND%s gave %s\n",First
?"FIRST":"NEXT",smb_errstr(inbuf
)));
559 /* parse out some important return info */
563 ff_dir_handle
= SVAL(p
,0);
564 ff_searchcount
= SVAL(p
,2);
566 ff_lastname
= SVAL(p
,8);
570 ff_searchcount
= SVAL(p
,0);
572 ff_lastname
= SVAL(p
,6);
575 if (ff_searchcount
== 0)
578 /* point to the data bytes */
581 /* we might need the lastname for continuations */
588 StrnCpy(mask
,p
+ff_lastname
,resp_data_len
-ff_lastname
);
589 /* pstrcpy(mask,p+ff_lastname+94); */
592 pstrcpy(mask
,p
+ ff_lastname
+ 1);
600 /* and add them to the dirlist pool */
601 dirlist
= Realloc(dirlist
,dirlist_len
+ resp_data_len
);
605 DEBUG(0,("Failed to expand dirlist\n"));
609 /* put in a length for the last entry, to ensure we can chain entries
610 into the next packet */
613 for (p2
=p
,i
=0;i
<(ff_searchcount
-1);i
++)
614 p2
+= interpret_long_filename(info_level
,p2
,NULL
);
615 SSVAL(p2
,0,resp_data_len
- PTR_DIFF(p2
,p
));
618 /* grab the data for later use */
619 memcpy(dirlist
+dirlist_len
,p
,resp_data_len
);
620 dirlist_len
+= resp_data_len
;
622 total_received
+= ff_searchcount
;
624 if (resp_data
) free(resp_data
); resp_data
= NULL
;
625 if (resp_param
) free(resp_param
); resp_param
= NULL
;
627 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
628 ff_searchcount
,ff_eos
,ff_resume_key
));
634 for (p
=dirlist
,i
=0;i
<total_received
;i
++)
636 p
+= interpret_long_filename(info_level
,p
,&finfo
);
637 display_finfo(&finfo
);
640 for (p
=dirlist
,i
=0;i
<total_received
;i
++)
642 p
+= interpret_long_filename(info_level
,p
,&finfo
);
643 dir_action(inbuf
,outbuf
,attribute
,&finfo
,recurse_dir
,fn
,True
, dirstoo
);
646 /* free up the dirlist buffer */
647 if (dirlist
) free(dirlist
);
648 return(total_received
);
652 /****************************************************************************
653 do a directory listing, calling fn on each file found
654 ****************************************************************************/
655 static int do_short_dir(char *inbuf
,char *outbuf
,char *Mask
,int attribute
,void (*fn
)(file_info
*),BOOL recurse_dir
, BOOL dirstoo
)
661 int num_asked
= (max_xmit
- 100)/DIR_STRUCT_SIZE
;
662 int num_received
= 0;
664 char *dirlist
= NULL
;
676 bzero(outbuf
,smb_size
);
678 set_message(outbuf
,2,5 + strlen(mask
),True
);
680 set_message(outbuf
,2,5 + 21,True
);
683 if (Protocol
>= PROTOCOL_LANMAN1
)
684 CVAL(outbuf
,smb_com
) = SMBffirst
;
687 CVAL(outbuf
,smb_com
) = SMBsearch
;
689 SSVAL(outbuf
,smb_tid
,cnum
);
690 cli_setup_pkt(outbuf
);
692 SSVAL(outbuf
,smb_vwv0
,num_asked
);
693 SSVAL(outbuf
,smb_vwv1
,attribute
);
714 send_smb(Client
,outbuf
);
715 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
717 received
= SVAL(inbuf
,smb_vwv0
);
719 DEBUG(5,("dir received %d\n",received
));
721 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf
)));
723 if (received
<= 0) break;
727 dirlist
= Realloc(dirlist
,(num_received
+ received
)*DIR_STRUCT_SIZE
);
732 p
= smb_buf(inbuf
) + 3;
734 memcpy(dirlist
+num_received
*DIR_STRUCT_SIZE
,
735 p
,received
*DIR_STRUCT_SIZE
);
737 memcpy(status
,p
+ ((received
-1)*DIR_STRUCT_SIZE
),21);
739 num_received
+= received
;
741 if (CVAL(inbuf
,smb_rcls
) != 0) break;
745 if (!first
&& Protocol
>= PROTOCOL_LANMAN1
)
747 bzero(outbuf
,smb_size
);
748 CVAL(outbuf
,smb_com
) = SMBfclose
;
750 SSVAL(outbuf
,smb_tid
,cnum
);
751 cli_setup_pkt(outbuf
);
764 send_smb(Client
,outbuf
);
765 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
767 if (CVAL(inbuf
,smb_rcls
) != 0)
768 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf
)));
773 for (p
=dirlist
,i
=0;i
<num_received
;i
++)
775 p
+= interpret_short_filename(p
,&finfo
);
776 display_finfo(&finfo
);
779 for (p
=dirlist
,i
=0;i
<num_received
;i
++)
781 p
+= interpret_short_filename(p
,&finfo
);
782 dir_action(inbuf
,outbuf
,attribute
,&finfo
,recurse_dir
,fn
,False
,dirstoo
);
785 if (dirlist
) free(dirlist
);
786 return(num_received
);
791 /****************************************************************************
792 do a directory listing, calling fn on each file found
793 ****************************************************************************/
794 void do_dir(char *inbuf
,char *outbuf
,char *Mask
,int attribute
,void (*fn
)(file_info
*),BOOL recurse_dir
, BOOL dirstoo
)
796 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask
,attribute
,BOOLSTR(recurse_dir
)));
797 if (Protocol
>= PROTOCOL_LANMAN2
)
799 if (do_long_dir(inbuf
,outbuf
,Mask
,attribute
,fn
,recurse_dir
,dirstoo
) > 0)
803 expand_mask(Mask
,False
);
804 do_short_dir(inbuf
,outbuf
,Mask
,attribute
,fn
,recurse_dir
,dirstoo
);
808 /*******************************************************************
809 decide if a file should be operated on
810 ********************************************************************/
811 static BOOL
do_this_one(file_info
*finfo
)
813 if (finfo
->mode
& aDIR
) return(True
);
815 if (newer_than
&& finfo
->mtime
< newer_than
)
818 if ((archive_level
==1 || archive_level
==2) && !(finfo
->mode
& aARCH
))
825 /*****************************************************************************
826 Convert a character pointer in a cli_call_api() response to a form we can use.
827 This function contains code to prevent core dumps if the server returns
829 *****************************************************************************/
830 static char *fix_char_ptr(unsigned int datap
, unsigned int converter
, char *rdata
, int rdrcnt
)
832 if( datap
== 0 ) /* turn NULL pointers */
833 { /* into zero length strings */
838 unsigned int offset
= datap
- converter
;
840 if( offset
>= rdrcnt
)
842 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap
, converter
, (unsigned long)rdata
, rdrcnt
));
847 return &rdata
[offset
];
852 /****************************************************************************
853 interpret a short filename structure
854 The length of the structure is returned
855 ****************************************************************************/
856 static int interpret_short_filename(char *p
,file_info
*finfo
)
858 finfo
->mode
= CVAL(p
,21);
860 /* this date is converted to GMT by make_unix_date */
861 finfo
->ctime
= make_unix_date(p
+22);
862 finfo
->mtime
= finfo
->atime
= finfo
->ctime
;
863 finfo
->size
= IVAL(p
,26);
864 pstrcpy(finfo
->name
,p
+30);
866 return(DIR_STRUCT_SIZE
);
869 /****************************************************************************
870 interpret a long filename structure - this is mostly guesses at the moment
871 The length of the structure is returned
872 The structure of a long filename depends on the info level. 260 is used
873 by NT and 2 is used by OS/2
874 ****************************************************************************/
875 static int interpret_long_filename(int level
,char *p
,file_info
*finfo
)
878 memcpy(finfo
,&def_finfo
,sizeof(*finfo
));
882 case 1: /* OS/2 understands this */
885 /* these dates are converted to GMT by make_unix_date */
886 finfo
->ctime
= make_unix_date2(p
+4);
887 finfo
->atime
= make_unix_date2(p
+8);
888 finfo
->mtime
= make_unix_date2(p
+12);
889 finfo
->size
= IVAL(p
,16);
890 finfo
->mode
= CVAL(p
,24);
891 pstrcpy(finfo
->name
,p
+27);
893 return(28 + CVAL(p
,26));
895 case 2: /* this is what OS/2 uses mostly */
898 /* these dates are converted to GMT by make_unix_date */
899 finfo
->ctime
= make_unix_date2(p
+4);
900 finfo
->atime
= make_unix_date2(p
+8);
901 finfo
->mtime
= make_unix_date2(p
+12);
902 finfo
->size
= IVAL(p
,16);
903 finfo
->mode
= CVAL(p
,24);
904 pstrcpy(finfo
->name
,p
+31);
906 return(32 + CVAL(p
,30));
908 /* levels 3 and 4 are untested */
912 /* these dates are probably like the other ones */
913 finfo
->ctime
= make_unix_date2(p
+8);
914 finfo
->atime
= make_unix_date2(p
+12);
915 finfo
->mtime
= make_unix_date2(p
+16);
916 finfo
->size
= IVAL(p
,20);
917 finfo
->mode
= CVAL(p
,28);
918 pstrcpy(finfo
->name
,p
+33);
925 /* these dates are probably like the other ones */
926 finfo
->ctime
= make_unix_date2(p
+8);
927 finfo
->atime
= make_unix_date2(p
+12);
928 finfo
->mtime
= make_unix_date2(p
+16);
929 finfo
->size
= IVAL(p
,20);
930 finfo
->mode
= CVAL(p
,28);
931 pstrcpy(finfo
->name
,p
+37);
935 case 260: /* NT uses this, but also accepts 2 */
940 p
+= 4; /* next entry offset */
941 p
+= 4; /* fileindex */
943 /* these dates appear to arrive in a weird way. It seems to
944 be localtime plus the serverzone given in the initial
945 connect. This is GMT when DST is not in effect and one
946 hour from GMT otherwise. Can this really be right??
948 I suppose this could be called kludge-GMT. Is is the GMT
949 you get by using the current DST setting on a different
950 localtime. It will be cheap to calculate, I suppose, as
951 no DST tables will be needed */
953 finfo
->ctime
= interpret_long_date(p
); p
+= 8;
954 finfo
->atime
= interpret_long_date(p
); p
+= 8;
955 finfo
->mtime
= interpret_long_date(p
); p
+= 8; p
+= 8;
956 finfo
->size
= IVAL(p
,0); p
+= 8;
957 p
+= 8; /* alloc size */
958 finfo
->mode
= CVAL(p
,0); p
+= 4;
959 namelen
= IVAL(p
,0); p
+= 4;
960 p
+= 4; /* EA size */
961 p
+= 2; /* short name len? */
962 p
+= 24; /* short name? */
963 StrnCpy(finfo
->name
,p
,namelen
);
969 DEBUG(1,("Unknown long filename format %d\n",level
));
976 /****************************************************************************
977 act on the files in a dir listing
979 RJS, 4-Apr-1998, dirstoo added to allow caller to indicate that directories
980 should be processed as well.
981 ****************************************************************************/
982 static void dir_action(char *inbuf
,char *outbuf
,int attribute
,file_info
*finfo
,BOOL recurse_dir
,void (*fn
)(file_info
*),BOOL longdir
, BOOL dirstoo
)
985 if (!((finfo
->mode
& aDIR
) == 0 && *fileselection
&&
986 !mask_match(finfo
->name
,fileselection
,False
,False
)) &&
987 !(recurse_dir
&& (strequal(finfo
->name
,".") ||
988 strequal(finfo
->name
,".."))))
990 if (recurse_dir
&& (finfo
->mode
& aDIR
))
995 if (fn
&& dirstoo
&& do_this_one(finfo
)) { /* Do dirs, RJS */
999 pstrcpy(sav_dir
,cur_dir
);
1000 pstrcat(cur_dir
,finfo
->name
);
1001 pstrcat(cur_dir
,"\\");
1002 pstrcpy(mask2
,cur_dir
);
1005 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir
)));
1010 do_long_dir(inbuf
,outbuf
,mask2
,attribute
,fn
,True
, dirstoo
);
1012 do_dir(inbuf
,outbuf
,mask2
,attribute
,fn
,True
, dirstoo
);
1014 pstrcpy(cur_dir
,sav_dir
);
1018 if (fn
&& do_this_one(finfo
))
1025 /****************************************************************************
1026 get a directory listing
1027 ****************************************************************************/
1028 static void cmd_dir(char *inbuf
,char *outbuf
)
1030 int attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
1036 pstrcpy(mask
,cur_dir
);
1037 if(mask
[strlen(mask
)-1]!='\\')
1040 if (next_token(NULL
,buf
,NULL
,sizeof(buf
)))
1051 do_dir(inbuf
,outbuf
,mask
,attribute
,NULL
,recurse
,False
);
1055 DEBUG(3, ("Total bytes listed: %d\n", dir_total
));
1060 /****************************************************************************
1061 get a file from rname to lname
1062 ****************************************************************************/
1063 static void do_get(char *rname
,char *lname
,file_info
*finfo1
)
1068 BOOL newhandle
= False
;
1069 char *inbuf
,*outbuf
;
1071 BOOL close_done
= False
;
1072 BOOL ignore_close_error
= False
;
1076 struct timeval tp_start
;
1077 GetTimeOfDay(&tp_start
);
1088 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1089 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1091 if (!inbuf
|| !outbuf
)
1093 DEBUG(0,("out of memory\n"));
1097 bzero(outbuf
,smb_size
);
1098 set_message(outbuf
,15,1 + strlen(rname
),True
);
1100 CVAL(outbuf
,smb_com
) = SMBopenX
;
1101 SSVAL(outbuf
,smb_tid
,cnum
);
1102 cli_setup_pkt(outbuf
);
1104 SSVAL(outbuf
,smb_vwv0
,0xFF);
1105 SSVAL(outbuf
,smb_vwv2
,1); /* return additional info */
1106 SSVAL(outbuf
,smb_vwv3
,(DENY_NONE
<<4));
1107 SSVAL(outbuf
,smb_vwv4
,aSYSTEM
| aHIDDEN
);
1108 SSVAL(outbuf
,smb_vwv5
,aSYSTEM
| aHIDDEN
);
1109 SSVAL(outbuf
,smb_vwv8
,1);
1110 SSVAL(outbuf
,smb_vwv11
,0xffff);
1111 SSVAL(outbuf
,smb_vwv12
,0xffff);
1113 p
= smb_buf(outbuf
);
1115 p
= skip_string(p
,1);
1117 /* do a chained openX with a readX? */
1121 DEBUG(3,("Chaining readX wth openX\n"));
1122 SSVAL(outbuf
,smb_vwv0
,SMBreadX
);
1123 SSVAL(outbuf
,smb_vwv1
,smb_offset(p
,outbuf
));
1126 SCVAL(p
,smb_wct
,10);
1127 SSVAL(p
,smb_vwv0
,0xFF);
1128 SSVAL(p
,smb_vwv5
,MIN(max_xmit
-500,finfo
.size
));
1129 SSVAL(p
,smb_vwv9
,MIN(BUFFER_SIZE
,finfo
.size
));
1130 smb_setlen(outbuf
,smb_len(outbuf
)+11*2+1);
1134 if(!strcmp(lname
,"-"))
1135 handle
= fileno(stdout
);
1138 handle
= creat(lname
,0644);
1143 DEBUG(0,("Error opening local file %s\n",lname
));
1144 free(inbuf
);free(outbuf
);
1148 send_smb(Client
,outbuf
);
1149 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1151 if (CVAL(inbuf
,smb_rcls
) != 0)
1153 if (CVAL(inbuf
,smb_rcls
) == ERRSRV
&&
1154 SVAL(inbuf
,smb_err
) == ERRnoresource
&&
1155 cli_reopen_connection(inbuf
,outbuf
))
1157 do_get(rname
,lname
,finfo1
);
1160 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
1163 free(inbuf
);free(outbuf
);
1167 pstrcpy(finfo
.name
,rname
);
1171 finfo
.mode
= SVAL(inbuf
,smb_vwv3
);
1172 /* these times arrive as LOCAL time, using the DST offset
1173 corresponding to that time, we convert them to GMT */
1174 finfo
.mtime
= make_unix_date3(inbuf
+smb_vwv4
);
1175 finfo
.atime
= finfo
.ctime
= finfo
.mtime
;
1176 finfo
.size
= IVAL(inbuf
,smb_vwv6
);
1179 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo
.name
),finfo
.mode
));
1181 fnum
= SVAL(inbuf
,smb_vwv2
);
1183 /* we might have got some data from a chained readX */
1184 if (SVAL(inbuf
,smb_vwv0
) == SMBreadX
)
1186 p
= (smb_base(inbuf
)+SVAL(inbuf
,smb_vwv1
)) - smb_wct
;
1187 datalen
= SVAL(p
,smb_vwv5
);
1188 dataptr
= smb_base(inbuf
) + SVAL(p
,smb_vwv6
);
1197 DEBUG(2,("getting file %s of size %.0f bytes as %s ",
1198 CNV_LANG(finfo
.name
),
1202 while (nread
< finfo
.size
&& !close_done
)
1205 static BOOL can_chain_close
= True
;
1209 DEBUG(3,("nread=%d max_xmit=%d fsize=%.0f\n",nread
,max_xmit
,(double)finfo
.size
));
1211 /* 3 possible read types. readbraw if a large block is required.
1212 readX + close if not much left and read if neither is supported */
1214 /* we might have already read some data from a chained readX */
1215 if (dataptr
&& datalen
>0)
1218 /* if we can finish now then readX+close */
1219 if (method
<0 && can_chain_close
&& (Protocol
>= PROTOCOL_LANMAN1
) &&
1220 ((finfo
.size
- nread
) <
1221 (max_xmit
- (2*smb_size
+ 13*SIZEOFWORD
+ 300))))
1224 /* if we support readraw then use that */
1225 if (method
<0 && readbraw_supported
)
1228 /* if we can then use readX */
1229 if (method
<0 && (Protocol
>= PROTOCOL_LANMAN1
))
1240 /* use readX + close */
1241 bzero(outbuf
,smb_size
);
1242 set_message(outbuf
,10,0,True
);
1243 CVAL(outbuf
,smb_com
) = SMBreadX
;
1244 SSVAL(outbuf
,smb_tid
,cnum
);
1245 cli_setup_pkt(outbuf
);
1249 CVAL(outbuf
,smb_vwv0
) = SMBclose
;
1250 SSVAL(outbuf
,smb_vwv1
,smb_offset(smb_buf(outbuf
),outbuf
));
1253 CVAL(outbuf
,smb_vwv0
) = 0xFF;
1255 SSVAL(outbuf
,smb_vwv2
,fnum
);
1256 SIVAL(outbuf
,smb_vwv3
,nread
);
1257 SSVAL(outbuf
,smb_vwv5
,MIN(max_xmit
-200,finfo
.size
- nread
));
1258 SSVAL(outbuf
,smb_vwv6
,0);
1259 SIVAL(outbuf
,smb_vwv7
,0);
1260 SSVAL(outbuf
,smb_vwv9
,MIN(BUFFER_SIZE
,finfo
.size
-nread
));
1264 p
= smb_buf(outbuf
);
1271 /* now set the total packet length */
1272 smb_setlen(outbuf
,smb_len(outbuf
)+9);
1275 send_smb(Client
,outbuf
);
1276 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1278 if (CVAL(inbuf
,smb_rcls
) != 0)
1280 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf
)));
1285 SVAL(inbuf
,smb_vwv0
) != SMBclose
)
1287 /* NOTE: WfWg sometimes just ignores the chained
1288 command! This seems to break the spec? */
1289 DEBUG(3,("Rejected chained close?\n"));
1291 can_chain_close
= False
;
1292 ignore_close_error
= True
;
1295 datalen
= SVAL(inbuf
,smb_vwv5
);
1296 dataptr
= smb_base(inbuf
) + SVAL(inbuf
,smb_vwv6
);
1302 static int readbraw_size
= BUFFER_SIZE
;
1305 bzero(outbuf
,smb_size
);
1306 set_message(outbuf
,8,0,True
);
1307 CVAL(outbuf
,smb_com
) = SMBreadbraw
;
1308 SSVAL(outbuf
,smb_tid
,cnum
);
1309 cli_setup_pkt(outbuf
);
1310 SSVAL(outbuf
,smb_vwv0
,fnum
);
1311 SIVAL(outbuf
,smb_vwv1
,nread
);
1312 SSVAL(outbuf
,smb_vwv3
,MIN(finfo
.size
-nread
,readbraw_size
));
1313 SSVAL(outbuf
,smb_vwv4
,0);
1314 SIVALS(outbuf
,smb_vwv5
,-1);
1315 send_smb(Client
,outbuf
);
1317 /* Now read the raw data into the buffer and write it */
1318 if(read_smb_length(Client
,inbuf
,0) == -1) {
1319 DEBUG(0,("Failed to read length in readbraw\n"));
1323 /* Even though this is not an smb message, smb_len
1324 returns the generic length of an smb message */
1325 datalen
= smb_len(inbuf
);
1329 /* we got a readbraw error */
1330 DEBUG(4,("readbraw error - reducing size\n"));
1331 readbraw_size
= (readbraw_size
* 9) / 10;
1333 if (readbraw_size
< max_xmit
)
1335 DEBUG(0,("disabling readbraw\n"));
1336 readbraw_supported
= False
;
1343 if(read_data(Client
,inbuf
,datalen
) != datalen
) {
1344 DEBUG(0,("Failed to read data in readbraw\n"));
1352 /* we've already read some data with a chained readX */
1356 /* use plain read */
1357 bzero(outbuf
,smb_size
);
1358 set_message(outbuf
,5,0,True
);
1359 CVAL(outbuf
,smb_com
) = SMBread
;
1360 SSVAL(outbuf
,smb_tid
,cnum
);
1361 cli_setup_pkt(outbuf
);
1363 SSVAL(outbuf
,smb_vwv0
,fnum
);
1364 SSVAL(outbuf
,smb_vwv1
,MIN(max_xmit
-200,finfo
.size
- nread
));
1365 SIVAL(outbuf
,smb_vwv2
,nread
);
1366 SSVAL(outbuf
,smb_vwv4
,finfo
.size
- nread
);
1368 send_smb(Client
,outbuf
);
1369 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1371 if (CVAL(inbuf
,smb_rcls
) != 0)
1373 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf
)));
1377 datalen
= SVAL(inbuf
,smb_vwv0
);
1378 dataptr
= smb_buf(inbuf
) + 3;
1382 if (writefile(handle
,dataptr
,datalen
) != datalen
)
1384 DEBUG(0,("Error writing local file\n"));
1391 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname
),nread
));
1403 cli_smb_close(inbuf
, outbuf
, Client
, cnum
, fnum
);
1405 if (!ignore_close_error
&& CVAL(inbuf
,smb_rcls
) != 0)
1407 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf
)));
1410 free(inbuf
);free(outbuf
);
1418 if (archive_level
>= 2 && (finfo
.mode
& aARCH
)) {
1419 bzero(outbuf
,smb_size
);
1420 set_message(outbuf
,8,strlen(rname
)+4,True
);
1421 CVAL(outbuf
,smb_com
) = SMBsetatr
;
1422 SSVAL(outbuf
,smb_tid
,cnum
);
1423 cli_setup_pkt(outbuf
);
1424 SSVAL(outbuf
,smb_vwv0
,finfo
.mode
& ~(aARCH
));
1425 SIVALS(outbuf
,smb_vwv1
,0);
1426 p
= smb_buf(outbuf
);
1432 send_smb(Client
,outbuf
);
1433 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1437 struct timeval tp_end
;
1440 GetTimeOfDay(&tp_end
);
1442 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
1443 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
1444 get_total_time_ms
+= this_time
;
1445 get_total_size
+= finfo
.size
;
1447 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1448 finfo
.size
/ (1.024*this_time
+ 1.0e-4),
1449 get_total_size
/ (1.024*get_total_time_ms
)));
1452 free(inbuf
);free(outbuf
);
1456 /****************************************************************************
1458 ****************************************************************************/
1459 static void cmd_get(char *dum_in
, char *dum_out
)
1465 pstrcpy(rname
,cur_dir
);
1466 pstrcat(rname
,"\\");
1468 p
= rname
+ strlen(rname
);
1470 if (!next_token(NULL
,p
,NULL
,sizeof(rname
)-strlen(rname
))) {
1471 DEBUG(0,("get <filename>\n"));
1475 dos_clean_name(rname
);
1477 next_token(NULL
,lname
,NULL
,sizeof(lname
));
1479 do_get(rname
,lname
,NULL
);
1483 /****************************************************************************
1484 do a mget operation on one file
1485 ****************************************************************************/
1486 static void do_mget(file_info
*finfo
)
1491 if (strequal(finfo
->name
,".") || strequal(finfo
->name
,".."))
1496 DEBUG(0,("mget aborted\n"));
1500 if (finfo
->mode
& aDIR
)
1501 slprintf(quest
,sizeof(pstring
)-1,
1502 "Get directory %s? ",CNV_LANG(finfo
->name
));
1504 slprintf(quest
,sizeof(pstring
)-1,
1505 "Get file %s? ",CNV_LANG(finfo
->name
));
1507 if (prompt
&& !yesno(quest
)) return;
1509 if (finfo
->mode
& aDIR
)
1511 pstring saved_curdir
;
1513 char *inbuf
,*outbuf
;
1515 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1516 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1518 if (!inbuf
|| !outbuf
)
1520 DEBUG(0,("out of memory\n"));
1524 pstrcpy(saved_curdir
,cur_dir
);
1526 pstrcat(cur_dir
,finfo
->name
);
1527 pstrcat(cur_dir
,"\\");
1529 unix_format(finfo
->name
);
1532 strlower(finfo
->name
);
1534 if (!directory_exist(finfo
->name
,NULL
) &&
1535 dos_mkdir(finfo
->name
,0777) != 0)
1537 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo
->name
)));
1538 pstrcpy(cur_dir
,saved_curdir
);
1539 free(inbuf
);free(outbuf
);
1543 if (dos_chdir(finfo
->name
) != 0)
1545 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo
->name
)));
1546 pstrcpy(cur_dir
,saved_curdir
);
1547 free(inbuf
);free(outbuf
);
1552 pstrcpy(mget_mask
,cur_dir
);
1553 pstrcat(mget_mask
,"*");
1555 do_dir((char *)inbuf
,(char *)outbuf
,
1556 mget_mask
,aSYSTEM
| aHIDDEN
| aDIR
,do_mget
,False
, False
);
1558 pstrcpy(cur_dir
,saved_curdir
);
1559 free(inbuf
);free(outbuf
);
1563 pstrcpy(rname
,cur_dir
);
1564 pstrcat(rname
,finfo
->name
);
1565 do_get(rname
,finfo
->name
,finfo
);
1569 /****************************************************************************
1570 view the file using the pager
1571 ****************************************************************************/
1572 static void cmd_more(char *dum_in
, char *dum_out
)
1574 fstring rname
,lname
,tmpname
,pager_cmd
;
1577 fstrcpy(rname
,cur_dir
);
1578 fstrcat(rname
,"\\");
1581 "%s/smbmore.%d",tmpdir(),(int)getpid());
1582 fstrcpy(lname
,tmpname
);
1584 if (!next_token(NULL
,rname
+strlen(rname
),NULL
,sizeof(rname
)-strlen(rname
))) {
1585 DEBUG(0,("more <filename>\n"));
1588 dos_clean_name(rname
);
1590 do_get(rname
,lname
,NULL
);
1592 pager
=getenv("PAGER");
1594 slprintf(pager_cmd
,sizeof(pager_cmd
)-1,
1595 "%s %s",(pager
? pager
:PAGER
), tmpname
);
1602 /****************************************************************************
1604 ****************************************************************************/
1605 static void cmd_mget(char *inbuf
,char *outbuf
)
1607 int attribute
= aSYSTEM
| aHIDDEN
;
1619 while (next_token(NULL
,p
,NULL
,sizeof(buf
)))
1621 pstrcpy(mget_mask
,cur_dir
);
1622 if(mget_mask
[strlen(mget_mask
)-1]!='\\')
1623 pstrcat(mget_mask
,"\\");
1626 pstrcpy(mget_mask
,p
);
1628 pstrcat(mget_mask
,p
);
1629 do_dir((char *)inbuf
,(char *)outbuf
,mget_mask
,attribute
,do_mget
,False
,False
);
1634 pstrcpy(mget_mask
,cur_dir
);
1635 if(mget_mask
[strlen(mget_mask
)-1]!='\\')
1636 pstrcat(mget_mask
,"\\");
1637 pstrcat(mget_mask
,"*");
1638 do_dir((char *)inbuf
,(char *)outbuf
,mget_mask
,attribute
,do_mget
,False
,False
);
1642 /****************************************************************************
1643 make a directory of name "name"
1644 ****************************************************************************/
1645 static BOOL
do_mkdir(char *name
)
1648 char *inbuf
,*outbuf
;
1650 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1651 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1653 if (!inbuf
|| !outbuf
)
1655 DEBUG(0,("out of memory\n"));
1659 bzero(outbuf
,smb_size
);
1660 set_message(outbuf
,0,2 + strlen(name
),True
);
1662 CVAL(outbuf
,smb_com
) = SMBmkdir
;
1663 SSVAL(outbuf
,smb_tid
,cnum
);
1664 cli_setup_pkt(outbuf
);
1667 p
= smb_buf(outbuf
);
1671 send_smb(Client
,outbuf
);
1672 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1674 if (CVAL(inbuf
,smb_rcls
) != 0)
1676 DEBUG(0,("%s making remote directory %s\n",
1677 smb_errstr(inbuf
),CNV_LANG(name
)));
1679 free(inbuf
);free(outbuf
);
1683 free(inbuf
);free(outbuf
);
1688 /****************************************************************************
1690 ****************************************************************************/
1691 static void cmd_mkdir(char *inbuf
,char *outbuf
)
1697 pstrcpy(mask
,cur_dir
);
1699 if (!next_token(NULL
,p
,NULL
,sizeof(buf
)))
1702 DEBUG(0,("mkdir <dirname>\n"));
1714 trim_string(ddir
,".",NULL
);
1715 p
= strtok(ddir
,"/\\");
1719 if (!chkpath(ddir2
,False
))
1723 pstrcat(ddir2
,"\\");
1724 p
= strtok(NULL
,"/\\");
1732 /*******************************************************************
1733 write to a file using writebraw
1734 ********************************************************************/
1735 static int smb_writeraw(char *outbuf
,int fnum
,int pos
,char *buf
,int n
)
1740 bzero(outbuf
,smb_size
);
1741 bzero(inbuf
,smb_size
);
1742 set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?12:10,0,True
);
1744 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
1745 SSVAL(outbuf
,smb_tid
,cnum
);
1746 cli_setup_pkt(outbuf
);
1748 SSVAL(outbuf
,smb_vwv0
,fnum
);
1749 SSVAL(outbuf
,smb_vwv1
,n
);
1750 SIVAL(outbuf
,smb_vwv3
,pos
);
1751 SSVAL(outbuf
,smb_vwv7
,1);
1753 send_smb(Client
,outbuf
);
1755 if (!client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
1758 _smb_setlen(buf
-4,n
); /* HACK! XXXX */
1760 if (write_socket(Client
,buf
-4,n
+4) != n
+4)
1763 if (!client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0) {
1764 DEBUG(0,("Error writing remote file (2)\n"));
1767 return(SVAL(inbuf
,smb_vwv0
));
1772 /*******************************************************************
1774 ********************************************************************/
1775 static int smb_writefile(char *outbuf
,int fnum
,int pos
,char *buf
,int n
)
1779 if (writebraw_supported
&& n
> (max_xmit
-200))
1780 return(smb_writeraw(outbuf
,fnum
,pos
,buf
,n
));
1782 bzero(outbuf
,smb_size
);
1783 bzero(inbuf
,smb_size
);
1784 set_message(outbuf
,5,n
+ 3,True
);
1786 CVAL(outbuf
,smb_com
) = SMBwrite
;
1787 SSVAL(outbuf
,smb_tid
,cnum
);
1788 cli_setup_pkt(outbuf
);
1790 SSVAL(outbuf
,smb_vwv0
,fnum
);
1791 SSVAL(outbuf
,smb_vwv1
,n
);
1792 SIVAL(outbuf
,smb_vwv2
,pos
);
1793 SSVAL(outbuf
,smb_vwv4
,0);
1794 CVAL(smb_buf(outbuf
),0) = 1;
1795 SSVAL(smb_buf(outbuf
),1,n
);
1797 memcpy(smb_buf(outbuf
)+3,buf
,n
);
1799 send_smb(Client
,outbuf
);
1800 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1802 if (CVAL(inbuf
,smb_rcls
) != 0) {
1803 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf
)));
1806 return(SVAL(inbuf
,smb_vwv0
));
1811 /****************************************************************************
1813 ****************************************************************************/
1814 static void do_put(char *rname
,char *lname
,file_info
*finfo
)
1820 char *inbuf
,*outbuf
;
1821 time_t close_time
= finfo
->mtime
;
1823 static int maxwrite
=0;
1825 struct timeval tp_start
;
1826 GetTimeOfDay(&tp_start
);
1828 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1829 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1831 if (!inbuf
|| !outbuf
)
1833 DEBUG(0,("out of memory\n"));
1837 bzero(outbuf
,smb_size
);
1838 set_message(outbuf
,3,2 + strlen(rname
),True
);
1840 if (finfo
->mtime
== 0 || finfo
->mtime
== -1)
1841 finfo
->mtime
= finfo
->atime
= finfo
->ctime
= time(NULL
);
1843 CVAL(outbuf
,smb_com
) = SMBcreate
;
1844 SSVAL(outbuf
,smb_tid
,cnum
);
1845 cli_setup_pkt(outbuf
);
1847 SSVAL(outbuf
,smb_vwv0
,finfo
->mode
);
1848 put_dos_date3(outbuf
,smb_vwv1
,finfo
->mtime
);
1850 p
= smb_buf(outbuf
);
1854 send_smb(Client
,outbuf
);
1855 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1857 if (CVAL(inbuf
,smb_rcls
) != 0)
1859 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
1861 free(inbuf
);free(outbuf
);if (buf
) free(buf
);
1865 /* allow files to be piped into smbclient
1866 jdblair 24.jun.98 */
1867 if (!strcmp(lname
, "-")) {
1869 /* size of file is not known */
1872 f
= fopen(lname
,"r");
1877 DEBUG(0,("Error opening local file %s\n",lname
));
1878 free(inbuf
);free(outbuf
);
1883 fnum
= SVAL(inbuf
,smb_vwv0
);
1884 if (finfo
->size
< 0)
1885 finfo
->size
= file_size(lname
);
1887 DEBUG(1,("putting file %s of size %.0f bytes as %s ",lname
,(double)finfo
->size
,CNV_LANG(rname
)));
1890 maxwrite
= writebraw_supported
?MAX(max_xmit
,BUFFER_SIZE
):(max_xmit
-200);
1892 /* This is a rewrite of the read/write loop that doesn't require the input
1893 file to be of a known length. This allows the stream pointer 'f' to
1896 Rather than reallocing the read buffer every loop to keep it the min
1897 necessary length this look uses a fixed length buffer and just tests
1898 for eof on the file stream at the top of each loop.
1899 jdblair, 24.jun.98 */
1901 buf
= (char *)malloc(maxwrite
+4);
1907 fseek(f
,nread
,SEEK_SET
);
1908 if ((n
= readfile(buf
+4,1,n
,f
)) < 1)
1910 DEBUG(0,("Error reading local file\n"));
1914 ret
= smb_writefile(outbuf
,fnum
,nread
,buf
+4,n
);
1918 DEBUG(0,("Error writing file\n"));
1929 bzero(outbuf
,smb_size
);
1930 set_message(outbuf
,3,0,True
);
1931 CVAL(outbuf
,smb_com
) = SMBclose
;
1932 SSVAL(outbuf
,smb_tid
,cnum
);
1933 cli_setup_pkt(outbuf
);
1935 SSVAL(outbuf
,smb_vwv0
,fnum
);
1936 put_dos_date3(outbuf
,smb_vwv1
,close_time
);
1938 send_smb(Client
,outbuf
);
1939 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1941 if (CVAL(inbuf
,smb_rcls
) != 0)
1943 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
1945 free(inbuf
);free(outbuf
);
1952 free(inbuf
);free(outbuf
);
1956 struct timeval tp_end
;
1959 GetTimeOfDay(&tp_end
);
1961 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
1962 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
1963 put_total_time_ms
+= this_time
;
1964 put_total_size
+= finfo
->size
;
1966 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1967 finfo
->size
/ (1.024*this_time
+ 1.0e-4),
1968 put_total_size
/ (1.024*put_total_time_ms
)));
1974 /****************************************************************************
1976 ****************************************************************************/
1977 static void cmd_put(char *dum_in
, char *dum_out
)
1986 pstrcpy(rname
,cur_dir
);
1987 pstrcat(rname
,"\\");
1990 if (!next_token(NULL
,p
,NULL
,sizeof(buf
)))
1992 DEBUG(0,("put <filename>\n"));
1997 if (next_token(NULL
,p
,NULL
,sizeof(buf
)))
2000 pstrcat(rname
,lname
);
2002 dos_clean_name(rname
);
2006 /* allow '-' to represent stdin
2007 jdblair, 24.jun.98 */
2008 if (!file_exist(lname
,&st
) &&
2009 (strcmp(lname
,"-"))) {
2010 DEBUG(0,("%s does not exist\n",lname
));
2013 finfo
.mtime
= st
.st_mtime
;
2016 do_put(rname
,lname
,&finfo
);
2019 /****************************************************************************
2020 seek in a directory/file list until you get something that doesn't start with
2022 ****************************************************************************/
2023 static BOOL
seek_list(FILE *f
,char *name
)
2028 if (fscanf(f
,"%s",s
) != 1) return(False
);
2029 trim_string(s
,"./",NULL
);
2030 if (strncmp(s
,name
,strlen(name
)) != 0)
2041 /****************************************************************************
2042 set the file selection mask
2043 ****************************************************************************/
2044 static void cmd_select(char *dum_in
, char *dum_out
)
2046 pstrcpy(fileselection
,"");
2047 next_token(NULL
,fileselection
,NULL
,sizeof(fileselection
));
2051 /****************************************************************************
2053 ****************************************************************************/
2054 static void cmd_mput(char *dum_in
, char *dum_out
)
2065 while (next_token(NULL
,p
,NULL
,sizeof(buf
)))
2072 slprintf(tmpname
,sizeof(pstring
)-1,
2073 "%s/ls.smb.%d",tmpdir(),(int)getpid());
2075 slprintf(cmd
,sizeof(pstring
)-1,
2076 "find . -name \"%s\" -print > %s",p
,tmpname
);
2078 slprintf(cmd
,sizeof(pstring
)-1,
2079 "/bin/ls %s > %s",p
,tmpname
);
2082 f
= fopen(tmpname
,"r");
2089 if (fscanf(f
,"%s",lname
) != 1) break;
2090 trim_string(lname
,"./",NULL
);
2094 /* check if it's a directory */
2095 if (directory_exist(lname
,&st
))
2097 if (!recurse
) continue;
2098 slprintf(quest
,sizeof(pstring
)-1,
2099 "Put directory %s? ",lname
);
2100 if (prompt
&& !yesno(quest
))
2103 if (!seek_list(f
,lname
))
2108 pstrcpy(rname
,cur_dir
);
2109 pstrcat(rname
,lname
);
2110 if (!chkpath(rname
,False
) && !do_mkdir(rname
)) {
2112 if (!seek_list(f
,lname
))
2121 slprintf(quest
,sizeof(quest
)-1,
2122 "Put file %s? ",lname
);
2123 if (prompt
&& !yesno(quest
)) continue;
2125 pstrcpy(rname
,cur_dir
);
2126 pstrcat(rname
,lname
);
2130 /* null size so do_put knows to ignore it */
2133 /* set the date on the file */
2134 finfo
.mtime
= st
.st_mtime
;
2136 do_put(rname
,lname
,&finfo
);
2143 /****************************************************************************
2145 ****************************************************************************/
2146 static void do_cancel(int job
)
2148 char *rparam
= NULL
;
2154 bzero(param
,sizeof(param
));
2157 SSVAL(p
,0,81); /* DosPrintJobDel() */
2160 p
= skip_string(p
,1);
2162 p
= skip_string(p
,1);
2166 if (cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
,param
),0, 0,
2172 int res
= SVAL(rparam
,0);
2175 printf("Job %d cancelled\n",job
);
2177 printf("Error %d calcelling job %d\n",res
,job
);
2181 printf("Server refused cancel request\n");
2183 if (rparam
) free(rparam
);
2184 if (rdata
) free(rdata
);
2190 /****************************************************************************
2192 ****************************************************************************/
2193 static void cmd_cancel(char *inbuf
,char *outbuf
)
2198 if (!connect_as_printer
)
2200 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2201 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2204 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
))) {
2205 printf("cancel <jobid> ...\n");
2211 } while (next_token(NULL
,buf
,NULL
,sizeof(buf
)));
2217 /****************************************************************************
2219 ****************************************************************************/
2220 static void cmd_print(char *inbuf
,char *outbuf
)
2229 if (!connect_as_printer
)
2231 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2232 DEBUG(0,("Trying to print without -P may fail\n"));
2235 if (!next_token(NULL
,lname
,NULL
, sizeof(lname
)))
2237 DEBUG(0,("print <filename>\n"));
2241 pstrcpy(rname
,lname
);
2242 p
= strrchr(rname
,'/');
2247 pstrcpy(rname
,tname
);
2250 if ((int)strlen(rname
) > 14)
2253 if (strequal(lname
,"-"))
2256 pstrcpy(rname
,"stdin");
2259 dos_clean_name(rname
);
2261 bzero(outbuf
,smb_size
);
2262 set_message(outbuf
,2,2 + strlen(rname
),True
);
2264 CVAL(outbuf
,smb_com
) = SMBsplopen
;
2265 SSVAL(outbuf
,smb_tid
,cnum
);
2266 cli_setup_pkt(outbuf
);
2268 SSVAL(outbuf
,smb_vwv0
,0);
2269 SSVAL(outbuf
,smb_vwv1
,printmode
);
2271 p
= smb_buf(outbuf
);
2275 send_smb(Client
,outbuf
);
2276 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2278 if (CVAL(inbuf
,smb_rcls
) != 0)
2280 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
2285 f
= fopen(lname
,"r");
2288 DEBUG(0,("Error opening local file %s\n",lname
));
2293 fnum
= SVAL(inbuf
,smb_vwv0
);
2295 DEBUG(1,("printing file %s as %s\n",lname
,CNV_LANG(rname
)));
2301 bzero(outbuf
,smb_size
);
2302 set_message(outbuf
,1,3,True
);
2304 /* for some strange reason the OS/2 print server can't handle large
2305 packets when printing. weird */
2306 n
= MIN(1024,max_xmit
-(smb_len(outbuf
)+4));
2309 n
= printread(f
,smb_buf(outbuf
)+3,(int)(0.95*n
));
2311 n
= readfile(smb_buf(outbuf
)+3,1,n
,f
);
2314 DEBUG(0,("read gave %d\n",n
));
2318 smb_setlen(outbuf
,smb_len(outbuf
) + n
);
2320 CVAL(outbuf
,smb_com
) = SMBsplwr
;
2321 SSVAL(outbuf
,smb_tid
,cnum
);
2322 cli_setup_pkt(outbuf
);
2324 SSVAL(outbuf
,smb_vwv0
,fnum
);
2325 SSVAL(outbuf
,smb_vwv1
,n
+3);
2326 CVAL(smb_buf(outbuf
),0) = 1;
2327 SSVAL(smb_buf(outbuf
),1,n
);
2329 send_smb(Client
,outbuf
);
2330 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2332 if (CVAL(inbuf
,smb_rcls
) != 0)
2334 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf
)));
2341 DEBUG(2,("%d bytes printed\n",nread
));
2343 bzero(outbuf
,smb_size
);
2344 set_message(outbuf
,1,0,True
);
2345 CVAL(outbuf
,smb_com
) = SMBsplclose
;
2346 SSVAL(outbuf
,smb_tid
,cnum
);
2347 cli_setup_pkt(outbuf
);
2349 SSVAL(outbuf
,smb_vwv0
,fnum
);
2351 send_smb(Client
,outbuf
);
2352 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2354 if (CVAL(inbuf
,smb_rcls
) != 0)
2356 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf
)));
2366 /****************************************************************************
2367 show a print queue - this is deprecated as it uses the old smb that
2368 has limited support - the correct call is the cmd_p_queue_4() after this.
2369 ****************************************************************************/
2370 static void cmd_queue(char *inbuf
,char *outbuf
)
2375 bzero(outbuf
,smb_size
);
2376 set_message(outbuf
,2,0,True
);
2378 CVAL(outbuf
,smb_com
) = SMBsplretq
;
2379 SSVAL(outbuf
,smb_tid
,cnum
);
2380 cli_setup_pkt(outbuf
);
2382 SSVAL(outbuf
,smb_vwv0
,32); /* a max of 20 entries is to be shown */
2383 SSVAL(outbuf
,smb_vwv1
,0); /* the index into the queue */
2385 send_smb(Client
,outbuf
);
2386 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2388 if (CVAL(inbuf
,smb_rcls
) != 0)
2390 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf
)));
2394 count
= SVAL(inbuf
,smb_vwv0
);
2395 p
= smb_buf(inbuf
) + 3;
2398 DEBUG(0,("No entries in the print queue\n"));
2405 DEBUG(0,("Job Name Size Status\n"));
2411 case 0x01: safe_strcpy(status
,"held or stopped", sizeof(status
)-1); break;
2412 case 0x02: safe_strcpy(status
,"printing",sizeof(status
)-1); break;
2413 case 0x03: safe_strcpy(status
,"awaiting print", sizeof(status
)-1); break;
2414 case 0x04: safe_strcpy(status
,"in intercept",sizeof(status
)-1); break;
2415 case 0x05: safe_strcpy(status
,"file had error",sizeof(status
)-1); break;
2416 case 0x06: safe_strcpy(status
,"printer error",sizeof(status
)-1); break;
2417 default: safe_strcpy(status
,"unknown",sizeof(status
)-1); break;
2420 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2421 SVAL(p
,5),p
+12,IVAL(p
,7),status
));
2429 /****************************************************************************
2430 show information about a print queue
2431 ****************************************************************************/
2432 static void cmd_p_queue_4(char *inbuf
,char *outbuf
)
2434 char *rparam
= NULL
;
2441 if (!connect_as_printer
)
2443 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2444 DEBUG(0,("Trying to print without -P may fail\n"));
2447 bzero(param
,sizeof(param
));
2450 SSVAL(p
,0,76); /* API function number 76 (DosPrintJobEnum) */
2452 pstrcpy(p
,"zWrLeh"); /* parameter description? */
2453 p
= skip_string(p
,1);
2454 pstrcpy(p
,"WWzWWDDzz"); /* returned data format */
2455 p
= skip_string(p
,1);
2456 pstrcpy(p
,strrchr(service
,'\\')+1); /* name of queue */
2457 p
= skip_string(p
,1);
2458 SSVAL(p
,0,2); /* API function level 2, PRJINFO_2 data structure */
2459 SSVAL(p
,2,1000); /* size of bytes of returned data buffer */
2461 pstrcpy(p
,""); /* subformat */
2462 p
= skip_string(p
,1);
2464 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2465 if( cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
,param
), 0, 0,
2472 result_code
= SVAL(rparam
,0);
2473 converter
= SVAL(rparam
,2); /* conversion factor */
2475 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt
, rdrcnt
, SVAL(rparam
,4) ));
2477 if (result_code
== 0) /* if no error, */
2487 fstring PrinterName
;
2489 fstrcpy(PrinterName
,strrchr(service
,'\\')+1); /* name of queue */
2490 strlower(PrinterName
); /* in lower case */
2492 p
= rdata
; /* received data */
2493 for( i
= 0; i
< SVAL(rparam
,4); ++i
)
2496 Priority
= SVAL(p
,2);
2497 UserName
= fix_char_ptr(SVAL(p
,4), converter
, rdata
, rdrcnt
);
2499 Priority
= SVAL(p
,2);
2500 JobTime
= make_unix_date3( p
+ 12);
2501 JobTimeStr
= asctime(LocalTime( &JobTime
));
2503 JobName
= fix_char_ptr(SVAL(p
,24), converter
, rdata
, rdrcnt
);
2506 printf("%s-%u %s priority %u %s %s %u bytes\n",
2507 PrinterName
, JobId
, UserName
,
2508 Priority
, JobTimeStr
, JobName
, Size
);
2510 #if 0 /* DEBUG code */
2511 printf("Job Id: \"%u\"\n", SVAL(p
,0));
2512 printf("Priority: \"%u\"\n", SVAL(p
,2));
2514 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p
,4), converter
, rdata
, rdrcnt
) );
2515 printf("Position: \"%u\"\n", SVAL(p
,8));
2516 printf("Status: \"%u\"\n", SVAL(p
,10));
2518 JobTime
= make_unix_date3( p
+ 12);
2519 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime
)));
2520 printf("date: \"%u\"\n", SVAL(p
,12));
2522 printf("Size: \"%u\"\n", SVAL(p
,16));
2523 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p
,20), converter
, rdata
, rdrcnt
) );
2524 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p
,24), converter
, rdata
, rdrcnt
) );
2525 #endif /* DEBUG CODE */
2530 else /* cli_call_api() failed */
2532 printf("Failed, error = %d\n", result_code
);
2535 /* If any parameters or data were returned, free the storage. */
2536 if(rparam
) free(rparam
);
2537 if(rdata
) free(rdata
);
2542 /****************************************************************************
2543 show information about a print queue
2544 ****************************************************************************/
2545 static void cmd_qinfo(char *inbuf
,char *outbuf
)
2547 char *rparam
= NULL
;
2554 bzero(param
,sizeof(param
));
2557 SSVAL(p
,0,70); /* API function number 70 (DosPrintQGetInfo) */
2559 pstrcpy(p
,"zWrLh"); /* parameter description? */
2560 p
= skip_string(p
,1);
2561 pstrcpy(p
,"zWWWWzzzzWWzzl"); /* returned data format */
2562 p
= skip_string(p
,1);
2563 pstrcpy(p
,strrchr(service
,'\\')+1); /* name of queue */
2564 p
= skip_string(p
,1);
2565 SSVAL(p
,0,3); /* API function level 3, just queue info, no job info */
2566 SSVAL(p
,2,1000); /* size of bytes of returned data buffer */
2568 pstrcpy(p
,""); /* subformat */
2569 p
= skip_string(p
,1);
2571 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2572 if( cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
,param
), 0, 0,
2579 result_code
= SVAL(rparam
,0);
2580 converter
= SVAL(rparam
,2); /* conversion factor */
2582 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt
, rdrcnt
, SVAL(rparam
,4) ));
2584 if (result_code
== 0) /* if no error, */
2586 p
= rdata
; /* received data */
2588 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p
,0), converter
, rdata
, rdrcnt
) );
2589 printf("Priority: %u\n", SVAL(p
,4) );
2590 printf("Start time: %u\n", SVAL(p
,6) );
2591 printf("Until time: %u\n", SVAL(p
,8) );
2592 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p
,12), converter
, rdata
, rdrcnt
) );
2593 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p
,16), converter
, rdata
, rdrcnt
) );
2594 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p
,20), converter
, rdata
, rdrcnt
) );
2595 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p
,24), converter
, rdata
, rdrcnt
) );
2596 printf("Status: %u\n", SVAL(p
,28) );
2597 printf("Jobs: %u\n", SVAL(p
,30) );
2598 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p
,32), converter
, rdata
, rdrcnt
) );
2599 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p
,36), converter
, rdata
, rdrcnt
) );
2601 /* Dump the driver data */
2606 ddptr
= rdata
+ SVAL(p
,40) - converter
;
2607 if( SVAL(p
,40) == 0 ) {count
= 0;} else {count
= IVAL(ddptr
,0);}
2608 printf("Driverdata: size=%d, version=%u\n", count
, IVAL(ddptr
,4) );
2610 for(x
=8; x
< count
; x
+=16)
2612 for(y
=0; y
< 16; y
++)
2615 printf("%2.2X ", CVAL(ddptr
,(x
+y
)) );
2619 for(y
=0; y
< 16 && (x
+y
) < count
; y
++)
2621 c
= CVAL(ddptr
,(x
+y
));
2627 fputc('\n', stdout
);
2633 else /* cli_call_api() failed */
2635 printf("Failed, error = %d\n", result_code
);
2638 /* If any parameters or data were returned, free the storage. */
2639 if(rparam
) free(rparam
);
2640 if(rdata
) free(rdata
);
2645 /****************************************************************************
2647 ****************************************************************************/
2648 static void do_del(file_info
*finfo
)
2651 char *inbuf
,*outbuf
;
2654 pstrcpy(mask
,cur_dir
);
2655 pstrcat(mask
,finfo
->name
);
2657 if (finfo
->mode
& aDIR
)
2660 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
2661 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
2663 if (!inbuf
|| !outbuf
)
2665 DEBUG(0,("out of memory\n"));
2669 bzero(outbuf
,smb_size
);
2670 set_message(outbuf
,1,2 + strlen(mask
),True
);
2672 CVAL(outbuf
,smb_com
) = SMBunlink
;
2673 SSVAL(outbuf
,smb_tid
,cnum
);
2674 cli_setup_pkt(outbuf
);
2676 SSVAL(outbuf
,smb_vwv0
,0);
2678 p
= smb_buf(outbuf
);
2682 send_smb(Client
,outbuf
);
2683 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2685 if (CVAL(inbuf
,smb_rcls
) != 0)
2686 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf
),CNV_LANG(mask
)));
2688 free(inbuf
);free(outbuf
);
2692 /****************************************************************************
2694 ****************************************************************************/
2695 static void cmd_del(char *inbuf
,char *outbuf
)
2699 int attribute
= aSYSTEM
| aHIDDEN
;
2704 pstrcpy(mask
,cur_dir
);
2706 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2708 DEBUG(0,("del <filename>\n"));
2713 do_dir((char *)inbuf
,(char *)outbuf
,mask
,attribute
,do_del
,False
,False
);
2717 /****************************************************************************
2719 ****************************************************************************/
2720 static void cmd_rmdir(char *inbuf
,char *outbuf
)
2726 pstrcpy(mask
,cur_dir
);
2728 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2730 DEBUG(0,("rmdir <dirname>\n"));
2735 bzero(outbuf
,smb_size
);
2736 set_message(outbuf
,0,2 + strlen(mask
),True
);
2738 CVAL(outbuf
,smb_com
) = SMBrmdir
;
2739 SSVAL(outbuf
,smb_tid
,cnum
);
2740 cli_setup_pkt(outbuf
);
2743 p
= smb_buf(outbuf
);
2747 send_smb(Client
,outbuf
);
2748 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2750 if (CVAL(inbuf
,smb_rcls
) != 0)
2752 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf
),CNV_LANG(mask
)));
2758 /****************************************************************************
2760 ****************************************************************************/
2761 static void cmd_rename(char *inbuf
,char *outbuf
)
2767 pstrcpy(src
,cur_dir
);
2768 pstrcpy(dest
,cur_dir
);
2770 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
)) ||
2771 !next_token(NULL
,buf2
,NULL
, sizeof(buf2
)))
2773 DEBUG(0,("rename <src> <dest>\n"));
2779 bzero(outbuf
,smb_size
);
2780 set_message(outbuf
,1,4 + strlen(src
) + strlen(dest
),True
);
2782 CVAL(outbuf
,smb_com
) = SMBmv
;
2783 SSVAL(outbuf
,smb_tid
,cnum
);
2784 SSVAL(outbuf
,smb_vwv0
,aHIDDEN
| aDIR
| aSYSTEM
);
2785 cli_setup_pkt(outbuf
);
2787 p
= smb_buf(outbuf
);
2790 p
= skip_string(p
,1);
2794 send_smb(Client
,outbuf
);
2795 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2797 if (CVAL(inbuf
,smb_rcls
) != 0)
2799 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf
)));
2806 /****************************************************************************
2807 toggle the prompt flag
2808 ****************************************************************************/
2809 static void cmd_prompt(char *dum_in
, char *dum_out
)
2812 DEBUG(2,("prompting is now %s\n",prompt
?"on":"off"));
2816 /****************************************************************************
2817 set the newer than time
2818 ****************************************************************************/
2819 static void cmd_newer(char *dum_in
, char *dum_out
)
2823 SMB_STRUCT_STAT sbuf
;
2825 ok
= next_token(NULL
,buf
,NULL
,sizeof(buf
));
2826 if (ok
&& (dos_stat(buf
,&sbuf
) == 0))
2828 newer_than
= sbuf
.st_mtime
;
2829 DEBUG(1,("Getting files newer than %s",
2830 asctime(LocalTime(&newer_than
))));
2835 if (ok
&& newer_than
== 0)
2836 DEBUG(0,("Error setting newer-than time\n"));
2839 /****************************************************************************
2840 set the archive level
2841 ****************************************************************************/
2842 static void cmd_archive(char *dum_in
, char *dum_out
)
2846 if (next_token(NULL
,buf
,NULL
,sizeof(buf
))) {
2847 archive_level
= atoi(buf
);
2849 DEBUG(0,("Archive level is %d\n",archive_level
));
2852 /****************************************************************************
2853 toggle the lowercaseflag
2854 ****************************************************************************/
2855 static void cmd_lowercase(char *dum_in
, char *dum_out
)
2857 lowercase
= !lowercase
;
2858 DEBUG(2,("filename lowercasing is now %s\n",lowercase
?"on":"off"));
2864 /****************************************************************************
2865 toggle the recurse flag
2866 ****************************************************************************/
2867 static void cmd_recurse(char *dum_in
, char *dum_out
)
2870 DEBUG(2,("directory recursion is now %s\n",recurse
?"on":"off"));
2873 /****************************************************************************
2874 toggle the translate flag
2875 ****************************************************************************/
2876 static void cmd_translate(char *dum_in
, char *dum_out
)
2878 translation
= !translation
;
2879 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2880 translation
?"on":"off"));
2884 /****************************************************************************
2885 do a printmode command
2886 ****************************************************************************/
2887 static void cmd_printmode(char *dum_in
, char *dum_out
)
2892 if (next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2894 if (strequal(buf
,"text"))
2898 if (strequal(buf
,"graphics"))
2901 printmode
= atoi(buf
);
2908 fstrcpy(mode
,"text");
2911 fstrcpy(mode
,"graphics");
2914 slprintf(mode
,sizeof(mode
)-1,"%d",printmode
);
2918 DEBUG(2,("the printmode is now %s\n",mode
));
2921 /****************************************************************************
2923 ****************************************************************************/
2924 static void cmd_lcd(char *dum_in
, char *dum_out
)
2929 if (next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2931 DEBUG(2,("the local directory is now %s\n",GetWd(d
)));
2935 /****************************************************************************
2936 try and browse available connections on a host
2937 ****************************************************************************/
2938 static BOOL
browse_host(BOOL sort
)
2940 char *rparam
= NULL
;
2947 /* now send a SMBtrans command with api RNetShareEnum */
2949 SSVAL(p
,0,0); /* api number */
2952 p
= skip_string(p
,1);
2953 pstrcpy(p
,"B13BWz");
2954 p
= skip_string(p
,1);
2956 SSVAL(p
,2,BUFFER_SIZE
);
2959 if (cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
,param
),0, 0,
2965 int res
= SVAL(rparam
,0);
2966 int converter
=SVAL(rparam
,2);
2968 BOOL long_share_name
=False
;
2970 if (res
== 0 || res
== ERRmoredata
)
2972 count
=SVAL(rparam
,4);
2977 printf("\n\tSharename Type Comment\n");
2978 printf("\t--------- ---- -------\n");
2982 qsort(p
,count
,20,QSORT_CAST StrCaseCmp
);
2984 for (i
=0;i
<count
;i
++)
2987 int type
= SVAL(p
,14);
2988 int comment_offset
= IVAL(p
,16) & 0xFFFF;
2994 case STYPE_DISKTREE
:
2995 fstrcpy(typestr
,"Disk"); break;
2997 fstrcpy(typestr
,"Printer"); break;
2999 fstrcpy(typestr
,"Device"); break;
3001 fstrcpy(typestr
,"IPC"); break;
3004 printf("\t%-15.15s%-10.10s%s\n",
3006 comment_offset
?rdata
+comment_offset
-converter
:"");
3008 if (strlen(sname
)>8) long_share_name
=True
;
3013 if (long_share_name
) {
3014 printf("\nNOTE: There were share names longer than 8 chars.\n\
3015 On older clients these may not be accessible or may give browsing errors\n");
3018 if(res
== ERRmoredata
)
3019 printf("\nNOTE: More data was available, the list was truncated.\n");
3023 if (rparam
) free(rparam
);
3024 if (rdata
) free(rdata
);
3030 /****************************************************************************
3031 get some server info
3032 ****************************************************************************/
3033 static void server_info(void)
3035 char *rparam
= NULL
;
3041 bzero(param
,sizeof(param
));
3044 SSVAL(p
,0,63); /* NetServerGetInfo()? */
3047 p
= skip_string(p
,1);
3048 pstrcpy(p
,"zzzBBzz");
3049 p
= skip_string(p
,1);
3050 SSVAL(p
,0,10); /* level 10 */
3054 if (cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
,param
),0, 0,
3060 int res
= SVAL(rparam
,0);
3061 int converter
=SVAL(rparam
,2);
3067 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3068 rdata
+SVAL(p
,0)-converter
,
3069 rdata
+SVAL(p
,4)-converter
,
3070 rdata
+SVAL(p
,8)-converter
,
3071 rdata
+SVAL(p
,14)-converter
);
3075 if (rparam
) free(rparam
);
3076 if (rdata
) free(rdata
);
3082 /****************************************************************************
3083 try and browse available connections on a host
3084 ****************************************************************************/
3085 static BOOL
list_servers(char *wk_grp
)
3087 char *rparam
= NULL
;
3095 BOOL generic_request
= False
;
3098 if (strequal(wk_grp
,"WORKGROUP")) {
3099 /* we won't specify a workgroup */
3100 generic_request
= True
;
3103 /* now send a SMBtrans command with api ServerEnum? */
3105 SSVAL(p
,0,0x68); /* api number */
3108 pstrcpy(p
,generic_request
?"WrLehDO":"WrLehDz");
3109 p
= skip_string(p
,1);
3111 pstrcpy(p
,"B16BBDz");
3113 p
= skip_string(p
,1);
3115 SSVAL(p
,2,BUFFER_SIZE
- SAFETY_MARGIN
); /* buf length */
3121 if (!generic_request
) {
3123 p
= skip_string(p
,1);
3126 /* first ask for a list of servers in this workgroup */
3127 SIVAL(svtype_p
,0,SV_TYPE_ALL
);
3129 if (cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
+4,param
),0, 0,
3130 8, BUFFER_SIZE
- SAFETY_MARGIN
,
3135 int res
= SVAL(rparam
,0);
3136 int converter
=SVAL(rparam
,2);
3139 if (res
== 0 || res
== ERRmoredata
) {
3141 count
=SVAL(rparam
,4);
3144 printf("\n\nThis machine has a browse list:\n");
3145 printf("\n\tServer Comment\n");
3146 printf("\t--------- -------\n");
3149 for (i
=0;i
<count
;i
++) {
3151 int comment_offset
= IVAL(p2
,22) & 0xFFFF;
3152 printf("\t%-16.16s %s\n", sname
,
3153 comment_offset
?rdata
+comment_offset
-converter
:"");
3159 if(res
== ERRmoredata
)
3160 printf("\nNOTE: More data was available, the list was truncated.\n");
3164 if (rparam
) {free(rparam
); rparam
= NULL
;}
3165 if (rdata
) {free(rdata
); rdata
= NULL
;}
3167 /* now ask for a list of workgroups */
3168 SIVAL(svtype_p
,0,SV_TYPE_DOMAIN_ENUM
);
3170 if (cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
+4,param
),0, 0,
3171 8, BUFFER_SIZE
- SAFETY_MARGIN
,
3176 int res
= SVAL(rparam
,0);
3177 int converter
=SVAL(rparam
,2);
3180 if (res
== 0 || res
== ERRmoredata
) {
3182 count
=SVAL(rparam
,4);
3185 printf("\n\nThis machine has a workgroup list:\n");
3186 printf("\n\tWorkgroup Master\n");
3187 printf("\t--------- -------\n");
3190 for (i
=0;i
<count
;i
++) {
3192 int comment_offset
= IVAL(p2
,22) & 0xFFFF;
3193 printf("\t%-16.16s %s\n", sname
,
3194 comment_offset
?rdata
+comment_offset
-converter
:"");
3200 if(res
== ERRmoredata
)
3201 printf("\nNOTE: More data was available, the list was truncated.\n");
3205 if (rparam
) free(rparam
);
3206 if (rdata
) free(rdata
);
3212 /* Some constants for completing filename arguments */
3214 #define COMPL_NONE 0 /* No completions */
3215 #define COMPL_REMOTE 1 /* Complete remote filename */
3216 #define COMPL_LOCAL 2 /* Complete local filename */
3218 /* This defines the commands supported by this client */
3222 void (*fn
)(char *, char *);
3224 char compl_args
[2]; /* Completion argument info */
3227 {"ls",cmd_dir
,"<mask> list the contents of the current directory",COMPL_REMOTE
},
3228 {"dir",cmd_dir
,"<mask> list the contents of the current directory",COMPL_REMOTE
},
3229 {"lcd",cmd_lcd
,"[directory] change/report the local current working directory",COMPL_LOCAL
},
3230 {"cd",cmd_cd
,"[directory] change/report the remote directory",COMPL_REMOTE
},
3231 {"pwd",cmd_pwd
,"show current remote directory (same as 'cd' with no args)"},
3232 {"get",cmd_get
,"<remote name> [local name] get a file",COMPL_REMOTE
,COMPL_LOCAL
},
3233 {"mget",cmd_mget
,"<mask> get all the matching files",COMPL_REMOTE
},
3234 {"put",cmd_put
,"<local name> [remote name] put a file",COMPL_LOCAL
,COMPL_REMOTE
},
3235 {"mput",cmd_mput
,"<mask> put all matching files",COMPL_REMOTE
},
3236 {"rename",cmd_rename
,"<src> <dest> rename some files",COMPL_REMOTE
,COMPL_REMOTE
},
3237 {"more",cmd_more
,"<remote name> view a remote file with your pager",COMPL_REMOTE
},
3238 {"mask",cmd_select
,"<mask> mask all filenames against this",COMPL_REMOTE
},
3239 {"del",cmd_del
,"<mask> delete all matching files",COMPL_REMOTE
},
3240 {"rm",cmd_del
,"<mask> delete all matching files",COMPL_REMOTE
},
3241 {"mkdir",cmd_mkdir
,"<directory> make a directory"},
3242 {"md",cmd_mkdir
,"<directory> make a directory"},
3243 {"rmdir",cmd_rmdir
,"<directory> remove a directory"},
3244 {"rd",cmd_rmdir
,"<directory> remove a directory"},
3245 {"pq",cmd_p_queue_4
,"enumerate the print queue"},
3246 {"prompt",cmd_prompt
,"toggle prompting for filenames for mget and mput"},
3247 {"recurse",cmd_recurse
,"toggle directory recursion for mget and mput"},
3248 {"translate",cmd_translate
,"toggle text translation for printing"},
3249 {"lowercase",cmd_lowercase
,"toggle lowercasing of filenames for get"},
3250 {"print",cmd_print
,"<file name> print a file"},
3251 {"printmode",cmd_printmode
,"<graphics or text> set the print mode"},
3252 {"queue",cmd_queue
,"show the print queue"},
3253 {"qinfo",cmd_qinfo
,"show print queue information"},
3254 {"cancel",cmd_cancel
,"<jobid> cancel a print queue entry"},
3255 {"quit",cli_send_logout
,"logoff the server"},
3256 {"q",cli_send_logout
,"logoff the server"},
3257 {"exit",cli_send_logout
,"logoff the server"},
3258 {"newer",cmd_newer
,"<file> only mget files newer than the specified local file",COMPL_LOCAL
},
3259 {"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"},
3260 {"tar",cmd_tar
,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3261 {"blocksize",cmd_block
,"blocksize <number> (default 20)" },
3262 {"tarmode",cmd_tarmode
,
3263 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3264 {"setmode",cmd_setmode
,"filename <setmode string> change modes of file",COMPL_REMOTE
},
3265 {"help",cmd_help
,"[command] give help on a command"},
3266 {"?",cmd_help
,"[command] give help on a command"},
3267 {"!",NULL
,"run a shell command on the local system"},
3272 /*******************************************************************
3273 lookup a command string in the list of commands, including
3275 ******************************************************************/
3276 static int process_tok(fstring tok
)
3278 int i
= 0, matches
= 0;
3280 int tok_len
= strlen(tok
);
3282 while (commands
[i
].fn
!= NULL
)
3284 if (strequal(commands
[i
].name
,tok
))
3290 else if (strnequal(commands
[i
].name
, tok
, tok_len
))
3300 else if (matches
== 1)
3306 /****************************************************************************
3308 ****************************************************************************/
3309 static void cmd_help(char *dum_in
, char *dum_out
)
3314 if (next_token(NULL
,buf
,NULL
,sizeof(buf
)))
3316 if ((i
= process_tok(buf
)) >= 0)
3317 DEBUG(0,("HELP %s:\n\t%s\n\n",commands
[i
].name
,commands
[i
].description
));
3320 while (commands
[i
].description
)
3322 for (j
=0; commands
[i
].description
&& (j
<5); j
++) {
3323 DEBUG(0,("%-15s",commands
[i
].name
));
3332 /****************************************************************************
3333 wait for keyboard activity, swallowing network packets
3334 ****************************************************************************/
3335 static void wait_keyboard(char *buffer
)
3339 struct timeval timeout
;
3345 FD_SET(Client
,&fds
);
3346 FD_SET(fileno(stdin
),&fds
);
3348 timeout
.tv_sec
= 20;
3349 timeout
.tv_usec
= 0;
3350 selrtn
= sys_select(MAX(Client
,fileno(stdin
))+1,&fds
,&timeout
);
3352 if (FD_ISSET(fileno(stdin
),&fds
))
3355 /* We deliberately use receive_smb instead of
3356 client_receive_smb as we want to receive
3357 session keepalives and then drop them here.
3359 if (FD_ISSET(Client
,&fds
))
3360 receive_smb(Client
,buffer
,0);
3362 chkpath("\\",False
);
3366 #ifdef HAVE_LIBREADLINE
3368 /****************************************************************************
3369 completion routines for GNU Readline
3370 ****************************************************************************/
3372 /* To avoid filename completion being activated when no valid
3373 completions are found, we assign this stub completion function
3374 to the rl_completion_entry_function variable. */
3376 char *complete_cmd_null(char *text
, int state
)
3381 /* Argh. This is starting to get ugly. We need to be able to pass data
3382 back from the do_dir() iterator function. */
3384 static int compl_state
;
3385 static char *compl_text
;
3386 static pstring result
;
3388 /* Iterator function for do_dir() */
3390 void complete_process_file(file_info
*f
)
3392 /* Do we have a partial match? */
3394 if ((compl_state
>= 0) && (strncmp(compl_text
, f
->name
,
3395 strlen(compl_text
)) == 0)) {
3397 /* Return filename if we have made enough matches */
3399 if (compl_state
== 0) {
3400 pstrcpy(result
, f
->name
);
3409 /* Complete a remote file */
3411 char *complete_remote_file(char *text
, int state
)
3413 char *InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3414 char *OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3415 int attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
3418 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
3421 /* Create dir mask */
3423 pstrcpy(mask
, cur_dir
);
3426 /* Initialise static vars for filename match */
3429 compl_state
= state
;
3432 /* Iterate over all files in directory */
3434 do_dir(InBuffer
, OutBuffer
, mask
, attribute
, complete_process_file
, False
,
3442 /* Return matched filename */
3444 if (result
[0] != '\0') {
3445 return strdup(result
); /* Readline will dispose of strings */
3451 /* Complete a smbclient command */
3453 char *complete_cmd(char *text
, int state
)
3455 static int cmd_index
;
3464 /* Return the next name which partially matches the list of commands */
3466 while (strlen(name
= commands
[cmd_index
++].name
) > 0) {
3467 if (strncmp(name
, text
, strlen(text
)) == 0) {
3468 return strdup(name
);
3475 /* Main completion function for smbclient. Work out which word we are
3476 trying to complete and call the appropriate function. */
3478 char **completion_fn(char *text
, int start
, int end
)
3480 int i
, num_words
, cmd_index
;
3483 /* If we are at the start of a word, we are completing a smbclient
3487 return completion_matches(text
, complete_cmd
);
3490 /* Count # of words in command */
3493 for (i
= 0; i
<= end
; i
++) {
3494 if ((rl_line_buffer
[i
] != ' ') && (lastch
== ' '))
3496 lastch
= rl_line_buffer
[i
];
3499 if (rl_line_buffer
[end
] == ' ')
3502 /* Work out which command we are completing for */
3504 for (cmd_index
= 0; strcmp(commands
[cmd_index
].name
, "") != 0;
3507 /* Check each command in array */
3509 if (strncmp(rl_line_buffer
, commands
[cmd_index
].name
,
3510 strlen(commands
[cmd_index
].name
)) == 0) {
3512 /* Call appropriate completion function */
3514 if ((num_words
== 2) || (num_words
== 3)) {
3515 switch (commands
[cmd_index
].compl_args
[num_words
- 2]) {
3518 return completion_matches(text
, complete_remote_file
);
3522 return completion_matches(text
, filename_completion_function
);
3526 /* An invalid completion type */
3531 /* We're either completing an argument > 3 or found an invalid
3532 completion type. Either way do nothing about it. */
3541 #endif /* HAVE_LIBREADLINE */
3543 /****************************************************************************
3544 process commands from the client
3545 ****************************************************************************/
3546 static BOOL
process(char *base_directory
)
3551 char *InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3552 char *OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3554 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
3557 bzero(OutBuffer
,smb_size
);
3559 if (!cli_send_login(InBuffer
,OutBuffer
,True
,True
,NULL
))
3562 if (*base_directory
) do_cd(base_directory
);
3565 if (cmd
[0] != '\0') while (cmd
[0] != '\0')
3571 if ((p
= strchr(cmd
, ';')) == 0)
3573 strncpy(line
, cmd
, 999);
3579 if (p
- cmd
> 999) p
= cmd
+ 999;
3580 strncpy(line
, cmd
, p
- cmd
);
3581 line
[p
- cmd
] = '\0';
3585 /* input language code to internal one */
3588 /* and get the first part of the command */
3591 if (!next_token(&ptr
,tok
,NULL
,sizeof(tok
))) continue;
3594 if ((i
= process_tok(tok
)) >= 0)
3595 commands
[i
].fn(InBuffer
,OutBuffer
);
3597 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok
)));
3599 DEBUG(0,("%s: command not found\n",CNV_LANG(tok
)));
3601 else while (!feof(stdin
))
3606 bzero(OutBuffer
,smb_size
);
3608 #ifdef HAVE_LIBREADLINE
3613 /* Read input using GNU Readline */
3615 slprintf(prompt
, sizeof(prompt
) - 1, "smb: %s> ", CNV_LANG(cur_dir
));
3616 if (!readline(prompt
))
3619 /* Copy read line to samba buffer */
3621 pstrcpy(line
, rl_line_buffer
);
3622 pstrcat(line
, "\n");
3624 /* Add line to history */
3626 if (strlen(line
) > 0)
3632 /* display a prompt */
3633 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir
)));
3636 wait_keyboard(InBuffer
);
3638 /* and get a response */
3639 if (!fgets(line
,1000,stdin
))
3644 /* input language code to internal one */
3647 /* special case - first char is ! */
3654 /* and get the first part of the command */
3657 if (!next_token(&ptr
,tok
,NULL
,sizeof(tok
))) continue;
3660 if ((i
= process_tok(tok
)) >= 0)
3661 commands
[i
].fn(InBuffer
,OutBuffer
);
3663 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok
)));
3665 DEBUG(0,("%s: command not found\n",CNV_LANG(tok
)));
3668 cli_send_logout(InBuffer
,OutBuffer
);
3672 /****************************************************************************
3673 usage on the program
3674 ****************************************************************************/
3675 static void usage(char *pname
)
3677 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3680 DEBUG(0,("\nVersion %s\n",VERSION
));
3681 DEBUG(0,("\t-p port connect to the specified port\n"));
3682 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3683 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3684 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3685 DEBUG(0,("\t-N don't ask for a password\n"));
3686 DEBUG(0,("\t-P connect to service as a printer\n"));
3687 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3688 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3689 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3690 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3691 DEBUG(0,("\t-R name resolve order use these name resolution services only\n"));
3692 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3693 DEBUG(0,("\t-U username set the network username\n"));
3694 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3695 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3696 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3697 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
3698 DEBUG(0,("\t-D directory start from directory\n"));
3702 /****************************************************************************
3704 ****************************************************************************/
3705 int main(int argc
,char *argv
[])
3707 fstring base_directory
;
3708 char *pname
= argv
[0];
3709 int port
= SMB_PORT
;
3712 extern char *optarg
;
3715 BOOL message
= False
;
3716 BOOL nt_domain_logon
= False
;
3717 BOOL explicit_user
= False
;
3718 extern char tar_type
;
3719 static pstring servicesf
= CONFIGFILE
;
3721 pstring new_name_resolve_order
;
3725 pstrcpy(term_code
, KANJI
);
3731 *base_directory
= 0;
3733 *new_name_resolve_order
= 0;
3737 setup_logging(pname
,True
);
3740 charset_initialise();
3742 if(!get_myname(myhostname
,NULL
))
3744 DEBUG(0,("Failed to get my hostname.\n"));
3747 if (!lp_load(servicesf
,True
,False
,False
)) {
3748 fprintf(stderr
, "Can't load %s - run testparm to debug it\n", servicesf
);
3751 codepage_initialise(lp_client_code_page());
3753 interpret_coding_system(term_code
);
3759 pstrcpy(workgroup
,lp_workgroup());
3771 pstrcpy(username
,getenv("USER"));
3773 /* modification to support userid%passwd syntax in the USER var
3774 25.Aug.97, jdblair@uab.edu */
3776 if ((p
=strchr(username
,'%')))
3779 pstrcpy(password
,p
+1);
3781 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password
));
3786 /* modification to support PASSWD environmental var
3787 25.Aug.97, jdblair@uab.edu */
3789 if (getenv("PASSWD")) {
3790 pstrcpy(password
,getenv("PASSWD"));
3794 if (*username
== 0 && getenv("LOGNAME"))
3796 pstrcpy(username
,getenv("LOGNAME"));
3806 if (*argv
[1] != '-')
3809 pstrcpy(service
,argv
[1]);
3810 /* Convert any '/' characters in the service name to '\' characters */
3811 string_replace( service
, '/','\\');
3815 if (count_chars(service
,'\\') < 3)
3818 printf("\n%s: Not enough '\\' characters in service\n",service
);
3823 if (count_chars(service,'\\') > 3)
3826 printf("\n%s: Too many '\\' characters in service\n",service);
3831 if (argc
> 1 && (*argv
[1] != '-'))
3834 pstrcpy(password
,argv
[1]);
3835 memset(argv
[1],'X',strlen(argv
[1]));
3842 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
)
3846 max_protocol
= interpret_protocol(optarg
,max_protocol
);
3849 pstrcpy(user_socket_options
,optarg
);
3852 pstrcpy(new_name_resolve_order
, optarg
);
3855 pstrcpy(desthost
,optarg
);
3857 nt_domain_logon
= True
;
3860 name_type
= 0x03; /* messages are sent to NetBIOS name type 0x3 */
3861 pstrcpy(desthost
,optarg
);
3866 iface_set_default(NULL
,optarg
,NULL
);
3869 pstrcpy(base_directory
,optarg
);
3872 if (!tar_parseargs(argc
, argv
, optarg
, optind
)) {
3878 pstrcpy(scope
,optarg
);
3882 pstrcpy(query_host
,optarg
);
3889 explicit_user
= True
;
3890 pstrcpy(username
,optarg
);
3891 if ((lp
=strchr(username
,'%')))
3894 pstrcpy(password
,lp
+1);
3896 memset(strchr(optarg
,'%')+1,'X',strlen(password
));
3902 pstrcpy(workgroup
,optarg
);
3909 dest_ip
= *interpret_addr2(optarg
);
3910 if (zero_ip(dest_ip
)) exit(1);
3915 pstrcpy(global_myname
,optarg
);
3922 connect_as_printer
= True
;
3928 DEBUGLEVEL
= atoi(optarg
);
3931 slprintf(debugf
,sizeof(debugf
)-1, "%s.client",optarg
);
3934 port
= atoi(optarg
);
3945 pstrcpy(servicesf
, optarg
);
3948 pstrcpy(term_code
, optarg
);
3955 get_myname((*global_myname
)?NULL
:global_myname
,NULL
);
3956 strupper(global_myname
);
3958 if(*new_name_resolve_order
)
3959 lp_set_name_resolve_order(new_name_resolve_order
);
3961 if (!tar_type
&& !*query_host
&& !*service
&& !message
)
3967 #ifdef HAVE_LIBREADLINE
3969 /* Initialise GNU Readline */
3971 rl_readline_name
= "smbclient";
3972 rl_attempted_completion_function
= completion_fn
;
3973 rl_completion_entry_function
= (Function
*)complete_cmd_null
;
3975 /* Initialise history list */
3979 #endif /* HAVE_LIBREADLINE */
3981 DEBUG( 3, ( "Client started (version %s).\n", VERSION
) );
3986 if (cli_open_sockets(port
)) {
3987 char *InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3988 char *OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3991 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
3994 bzero(OutBuffer
,smb_size
);
3995 if (!cli_send_login(InBuffer
,OutBuffer
,True
,True
,NULL
))
3998 if (*base_directory
) do_cd(base_directory
);
4000 ret
=process_tar(InBuffer
, OutBuffer
);
4002 cli_send_logout(InBuffer
, OutBuffer
);
4009 if (*query_host
&& !nt_domain_logon
)
4012 slprintf(service
,sizeof(service
)-1,
4013 "\\\\%s\\IPC$",query_host
);
4015 connect_as_ipc
= True
;
4016 if (cli_open_sockets(port
))
4021 if (!cli_send_login(NULL
,NULL
,True
,True
,NULL
))
4025 if (!browse_host(True
)) {
4029 if (!list_servers(workgroup
)) {
4031 list_servers(workgroup
);
4034 cli_send_logout(NULL
,NULL
);
4044 if (cli_open_sockets(port
))
4046 pstring inbuf
,outbuf
;
4047 bzero(outbuf
,smb_size
);
4048 if (!cli_send_session_request(inbuf
,outbuf
))
4051 send_message(inbuf
,outbuf
);
4059 if (cli_open_sockets(port
))
4061 if (!process(base_directory
))