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 BOOL in_client
;
33 extern pstring service
;
34 extern pstring desthost
;
35 extern pstring global_myname
;
36 extern pstring myhostname
;
37 extern pstring password
;
38 extern pstring username
;
39 extern pstring workgroup
;
43 extern BOOL connect_as_printer
;
44 extern BOOL connect_as_ipc
;
45 extern struct in_addr ipzero
;
47 extern BOOL doencrypt
;
49 extern pstring user_socket_options
;
51 static int process_tok(fstring tok
);
52 static void cmd_help(char *dum_in
, char *dum_out
);
54 /* 30 second timeout on most commands */
55 #define CLIENT_TIMEOUT (30*1000)
56 #define SHORT_TIMEOUT (5*1000)
58 /* value for unused fid field in trans2 secondary request */
59 #define FID_UNUSED (0xFFFF)
63 extern int max_protocol
;
66 time_t newer_than
= 0;
67 int archive_level
= 0;
69 extern pstring debugf
;
70 extern int DEBUGLEVEL
;
72 BOOL translation
= False
;
82 static int interpret_long_filename(int level
,char *p
,file_info
*finfo
);
83 static void dir_action(char *inbuf
,char *outbuf
,int attribute
,file_info
*finfo
,BOOL recurse_dir
,void (*fn
)(file_info
*),BOOL longdir
, BOOL dirstoo
);
84 static int interpret_short_filename(char *p
,file_info
*finfo
);
85 static BOOL
do_this_one(file_info
*finfo
);
87 /* clitar bits insert */
90 extern BOOL tar_reset
;
94 mode_t myumask
= 0755;
102 BOOL recurse
= False
;
103 BOOL lowercase
= False
;
105 struct in_addr dest_ip
;
107 #define SEPARATORS " \t\n\r"
109 BOOL abort_mget
= True
;
113 extern BOOL readbraw_supported
;
114 extern BOOL writebraw_supported
;
116 pstring fileselection
= "";
118 extern file_info def_finfo
;
121 int get_total_size
= 0;
122 int get_total_time_ms
= 0;
123 int put_total_size
= 0;
124 int put_total_time_ms
= 0;
133 #define CNV_LANG(s) dos_to_unix(s,False)
134 #define CNV_INPUT(s) unix_to_dos(s,True)
136 /****************************************************************************
137 send an SMBclose on an SMB file handle
138 ****************************************************************************/
139 static void cli_smb_close(char *inbuf
, char *outbuf
, int clnt_fd
, int c_num
, int f_num
)
141 bzero(outbuf
,smb_size
);
142 set_message(outbuf
,3,0,True
);
144 CVAL (outbuf
,smb_com
) = SMBclose
;
145 SSVAL(outbuf
,smb_tid
,c_num
);
146 cli_setup_pkt(outbuf
);
147 SSVAL (outbuf
,smb_vwv0
, f_num
);
148 SIVALS(outbuf
,smb_vwv1
, -1);
150 send_smb(clnt_fd
, outbuf
);
151 client_receive_smb(clnt_fd
,inbuf
,CLIENT_TIMEOUT
);
155 /****************************************************************************
156 write to a local file with CR/LF->LF translation if appropriate. return the
157 number taken from the buffer. This may not equal the number written.
158 ****************************************************************************/
159 static int writefile(int f
, char *b
, int n
)
164 return(write(f
,b
,n
));
169 if (*b
== '\r' && (i
<(n
-1)) && *(b
+1) == '\n')
173 if (write(f
, b
, 1) != 1)
184 /****************************************************************************
185 read from a file with LF->CR/LF translation if appropriate. return the
186 number read. read approx n bytes.
187 ****************************************************************************/
188 static int readfile(char *b
, int size
, int n
, FILE *f
)
193 if (!translation
|| (size
!= 1))
194 return(fread(b
,size
,n
,f
));
199 if ((c
= getc(f
)) == EOF
)
204 if (c
== '\n') /* change all LFs to CR/LF */
218 /****************************************************************************
219 read from a file with print translation. return the number read. read approx n
221 ****************************************************************************/
222 static int printread(FILE *f
,char *b
,int n
)
226 i
= readfile(b
,1, n
-1,f
);
235 /****************************************************************************
236 check for existance of a dir
237 ****************************************************************************/
238 static BOOL
chkpath(char *path
,BOOL report
)
241 pstring inbuf
,outbuf
;
245 trim_string(path2
,NULL
,"\\");
246 if (!*path2
) *path2
= '\\';
248 bzero(outbuf
,smb_size
);
249 set_message(outbuf
,0,4 + strlen(path2
),True
);
250 SCVAL(outbuf
,smb_com
,SMBchkpth
);
251 SSVAL(outbuf
,smb_tid
,cnum
);
252 cli_setup_pkt(outbuf
);
260 /* this little bit of code can be used to extract NT error codes.
261 Just feed a bunch of "cd foo" commands to smbclient then watch
262 in netmon (tridge) */
264 SIVAL(outbuf
, smb_rcls
, code
| 0xC0000000);
265 SSVAL(outbuf
, smb_flg2
, SVAL(outbuf
, smb_flg2
) | (1<<14));
270 send_smb(Client
,outbuf
);
271 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
273 if (report
&& CVAL(inbuf
,smb_rcls
) != 0)
274 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf
)));
276 return(CVAL(inbuf
,smb_rcls
) == 0);
280 /****************************************************************************
282 ****************************************************************************/
283 static void send_message(char *inbuf
,char *outbuf
)
290 /* send a SMBsendstrt command */
291 bzero(outbuf
,smb_size
);
292 set_message(outbuf
,0,0,True
);
293 CVAL(outbuf
,smb_com
) = SMBsendstrt
;
294 SSVAL(outbuf
,smb_tid
,cnum
);
299 p
= skip_string(p
,1);
302 p
= skip_string(p
,1);
304 set_message(outbuf
,0,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
306 send_smb(Client
,outbuf
);
309 if (!client_receive_smb(Client
,inbuf
,SHORT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
311 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf
));
315 grp_id
= SVAL(inbuf
,smb_vwv0
);
317 printf("Connected. Type your message, ending it with a Control-D\n");
319 while (!feof(stdin
) && total_len
< 1600)
321 int maxlen
= MIN(1600 - total_len
,127);
328 for (l
=0;l
<maxlen
&& (c
=fgetc(stdin
))!=EOF
;l
++)
335 CVAL(outbuf
,smb_com
) = SMBsendtxt
;
337 set_message(outbuf
,1,l
+3,True
);
339 SSVAL(outbuf
,smb_vwv0
,grp_id
);
346 send_smb(Client
,outbuf
);
349 if (!client_receive_smb(Client
,inbuf
,SHORT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
351 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf
));
358 if (total_len
>= 1600)
359 printf("the message was truncated to 1600 bytes ");
361 printf("sent %d bytes ",total_len
);
363 printf("(status was %d-%d)\n",CVAL(inbuf
,smb_rcls
),SVAL(inbuf
,smb_err
));
365 CVAL(outbuf
,smb_com
) = SMBsendend
;
366 set_message(outbuf
,1,0,False
);
367 SSVAL(outbuf
,smb_vwv0
,grp_id
);
369 send_smb(Client
,outbuf
);
372 if (!client_receive_smb(Client
,inbuf
,SHORT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
374 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf
));
381 /****************************************************************************
382 check the space on a device
383 ****************************************************************************/
384 static void do_dskattr(void)
386 pstring inbuf
,outbuf
;
388 bzero(outbuf
,smb_size
);
389 set_message(outbuf
,0,0,True
);
390 CVAL(outbuf
,smb_com
) = SMBdskattr
;
391 SSVAL(outbuf
,smb_tid
,cnum
);
392 cli_setup_pkt(outbuf
);
394 send_smb(Client
,outbuf
);
395 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
397 if (CVAL(inbuf
,smb_rcls
) != 0)
398 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf
)));
400 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
401 SVAL(inbuf
,smb_vwv0
),
402 SVAL(inbuf
,smb_vwv1
)*SVAL(inbuf
,smb_vwv2
),
403 SVAL(inbuf
,smb_vwv3
)));
406 /****************************************************************************
408 ****************************************************************************/
409 static void cmd_pwd(char *dum_in
, char *dum_out
)
411 DEBUG(0,("Current directory is %s",CNV_LANG(service
)));
412 DEBUG(0,("%s\n",CNV_LANG(cur_dir
)));
416 /****************************************************************************
417 change directory - inner section
418 ****************************************************************************/
419 static void do_cd(char *newdir
)
427 /* Save the current directory in case the
428 new directory is invalid */
429 pstrcpy(saved_dir
, cur_dir
);
434 if (*(cur_dir
+strlen(cur_dir
)-1) != '\\') {
435 pstrcat(cur_dir
, "\\");
437 dos_clean_name(cur_dir
);
438 pstrcpy(dname
,cur_dir
);
439 pstrcat(cur_dir
,"\\");
440 dos_clean_name(cur_dir
);
442 if (!strequal(cur_dir
,"\\"))
443 if (!chkpath(dname
,True
))
444 pstrcpy(cur_dir
,saved_dir
);
446 pstrcpy(cd_path
,cur_dir
);
449 /****************************************************************************
451 ****************************************************************************/
452 static void cmd_cd(char *inbuf
,char *outbuf
)
456 if (next_token(NULL
,buf
,NULL
,sizeof(buf
)))
459 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir
)));
463 /****************************************************************************
464 display info about a file
465 ****************************************************************************/
466 static void display_finfo(file_info
*finfo
)
468 if (do_this_one(finfo
)) {
469 time_t t
= finfo
->mtime
; /* the time is assumed to be passed as GMT */
470 DEBUG(0,(" %-30s%7.7s%.0f %s",
471 CNV_LANG(finfo
->name
),
472 attrib_string(finfo
->mode
),
474 asctime(LocalTime(&t
))));
475 dir_total
+= finfo
->size
;
480 /****************************************************************************
481 calculate size of a file
482 ****************************************************************************/
483 static void do_du(file_info
*finfo
)
485 if (do_this_one(finfo
)) {
486 dir_total
+= finfo
->size
;
491 /****************************************************************************
492 do a directory listing, calling fn on each file found. Use the TRANSACT2
493 call for long filenames
494 ****************************************************************************/
495 static int do_long_dir(char *inbuf
,char *outbuf
,char *Mask
,int attribute
,void (*fn
)(file_info
*),BOOL recurse_dir
, BOOL dirstoo
)
497 int max_matches
= 512;
498 int info_level
= Protocol
<PROTOCOL_NT1
?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
503 char *dirlist
= NULL
;
505 int total_received
= 0;
507 char *resp_data
=NULL
;
508 char *resp_param
=NULL
;
509 int resp_data_len
= 0;
510 int resp_param_len
=0;
512 int ff_resume_key
= 0;
513 int ff_searchcount
=0;
527 if (loop_count
> 200)
529 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
535 setup
= TRANSACT2_FINDFIRST
;
536 SSVAL(param
,0,attribute
); /* attribute */
537 SSVAL(param
,2,max_matches
); /* max count */
538 SSVAL(param
,4,8+4+2); /* resume required + close on end + continue */
539 SSVAL(param
,6,info_level
);
541 pstrcpy(param
+12,mask
);
545 setup
= TRANSACT2_FINDNEXT
;
546 SSVAL(param
,0,ff_dir_handle
);
547 SSVAL(param
,2,max_matches
); /* max count */
548 SSVAL(param
,4,info_level
);
549 SIVAL(param
,6,ff_resume_key
); /* ff_resume_key */
550 SSVAL(param
,10,8+4+2); /* resume required + close on end + continue */
551 pstrcpy(param
+12,mask
);
553 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
554 ff_dir_handle
,ff_resume_key
,ff_lastname
,mask
));
556 /* ??? original code added 1 pad byte after param */
558 cli_send_trans_request(outbuf
,SMBtrans2
,NULL
,0,FID_UNUSED
,0,
560 0,12+strlen(mask
)+1,1,
563 if (!cli_receive_trans_response(inbuf
,SMBtrans2
,
564 &resp_data_len
,&resp_param_len
,
565 &resp_data
,&resp_param
))
567 DEBUG(3,("FIND%s gave %s\n",First
?"FIRST":"NEXT",smb_errstr(inbuf
)));
571 /* parse out some important return info */
575 ff_dir_handle
= SVAL(p
,0);
576 ff_searchcount
= SVAL(p
,2);
578 ff_lastname
= SVAL(p
,8);
582 ff_searchcount
= SVAL(p
,0);
584 ff_lastname
= SVAL(p
,6);
587 if (ff_searchcount
== 0)
590 /* point to the data bytes */
593 /* we might need the lastname for continuations */
600 StrnCpy(mask
,p
+ff_lastname
,resp_data_len
-ff_lastname
);
601 /* pstrcpy(mask,p+ff_lastname+94); */
604 pstrcpy(mask
,p
+ ff_lastname
+ 1);
612 /* and add them to the dirlist pool */
613 dirlist
= Realloc(dirlist
,dirlist_len
+ resp_data_len
);
617 DEBUG(0,("Failed to expand dirlist\n"));
621 /* put in a length for the last entry, to ensure we can chain entries
622 into the next packet */
625 for (p2
=p
,i
=0;i
<(ff_searchcount
-1);i
++)
626 p2
+= interpret_long_filename(info_level
,p2
,NULL
);
627 SSVAL(p2
,0,resp_data_len
- PTR_DIFF(p2
,p
));
630 /* grab the data for later use */
631 memcpy(dirlist
+dirlist_len
,p
,resp_data_len
);
632 dirlist_len
+= resp_data_len
;
634 total_received
+= ff_searchcount
;
636 if (resp_data
) free(resp_data
); resp_data
= NULL
;
637 if (resp_param
) free(resp_param
); resp_param
= NULL
;
639 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
640 ff_searchcount
,ff_eos
,ff_resume_key
));
646 for (p
=dirlist
,i
=0;i
<total_received
;i
++)
648 p
+= interpret_long_filename(info_level
,p
,&finfo
);
649 display_finfo(&finfo
);
652 for (p
=dirlist
,i
=0;i
<total_received
;i
++)
654 p
+= interpret_long_filename(info_level
,p
,&finfo
);
655 dir_action(inbuf
,outbuf
,attribute
,&finfo
,recurse_dir
,fn
,True
, dirstoo
);
658 /* free up the dirlist buffer */
659 if (dirlist
) free(dirlist
);
660 return(total_received
);
664 /****************************************************************************
665 do a directory listing, calling fn on each file found
666 ****************************************************************************/
667 static int do_short_dir(char *inbuf
,char *outbuf
,char *Mask
,int attribute
,void (*fn
)(file_info
*),BOOL recurse_dir
, BOOL dirstoo
)
673 int num_asked
= (max_xmit
- 100)/DIR_STRUCT_SIZE
;
674 int num_received
= 0;
676 char *dirlist
= NULL
;
688 bzero(outbuf
,smb_size
);
690 set_message(outbuf
,2,5 + strlen(mask
),True
);
692 set_message(outbuf
,2,5 + 21,True
);
695 if (Protocol
>= PROTOCOL_LANMAN1
)
696 CVAL(outbuf
,smb_com
) = SMBffirst
;
699 CVAL(outbuf
,smb_com
) = SMBsearch
;
701 SSVAL(outbuf
,smb_tid
,cnum
);
702 cli_setup_pkt(outbuf
);
704 SSVAL(outbuf
,smb_vwv0
,num_asked
);
705 SSVAL(outbuf
,smb_vwv1
,attribute
);
726 send_smb(Client
,outbuf
);
727 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
729 received
= SVAL(inbuf
,smb_vwv0
);
731 DEBUG(5,("dir received %d\n",received
));
733 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf
)));
735 if (received
<= 0) break;
739 dirlist
= Realloc(dirlist
,(num_received
+ received
)*DIR_STRUCT_SIZE
);
744 p
= smb_buf(inbuf
) + 3;
746 memcpy(dirlist
+num_received
*DIR_STRUCT_SIZE
,
747 p
,received
*DIR_STRUCT_SIZE
);
749 memcpy(status
,p
+ ((received
-1)*DIR_STRUCT_SIZE
),21);
751 num_received
+= received
;
753 if (CVAL(inbuf
,smb_rcls
) != 0) break;
757 if (!first
&& Protocol
>= PROTOCOL_LANMAN1
)
759 bzero(outbuf
,smb_size
);
760 CVAL(outbuf
,smb_com
) = SMBfclose
;
762 SSVAL(outbuf
,smb_tid
,cnum
);
763 cli_setup_pkt(outbuf
);
776 send_smb(Client
,outbuf
);
777 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
779 if (CVAL(inbuf
,smb_rcls
) != 0)
780 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf
)));
785 for (p
=dirlist
,i
=0;i
<num_received
;i
++)
787 p
+= interpret_short_filename(p
,&finfo
);
788 display_finfo(&finfo
);
791 for (p
=dirlist
,i
=0;i
<num_received
;i
++)
793 p
+= interpret_short_filename(p
,&finfo
);
794 dir_action(inbuf
,outbuf
,attribute
,&finfo
,recurse_dir
,fn
,False
,dirstoo
);
797 if (dirlist
) free(dirlist
);
798 return(num_received
);
803 /****************************************************************************
804 do a directory listing, calling fn on each file found
805 ****************************************************************************/
806 void do_dir(char *inbuf
,char *outbuf
,char *mask
,int attribute
,void (*fn
)(file_info
*),BOOL recurse_dir
, BOOL dirstoo
)
809 DEBUG(5,("do_dir(%s,%x,%s)\n",mask
,attribute
,BOOLSTR(recurse_dir
)));
810 if (Protocol
>= PROTOCOL_LANMAN2
)
812 if (do_long_dir(inbuf
,outbuf
,mask
,attribute
,fn
,recurse_dir
,dirstoo
) > 0)
816 expand_mask(mask
,False
);
817 do_short_dir(inbuf
,outbuf
,mask
,attribute
,fn
,recurse_dir
,dirstoo
);
821 /*******************************************************************
822 decide if a file should be operated on
823 ********************************************************************/
824 static BOOL
do_this_one(file_info
*finfo
)
826 if (finfo
->mode
& aDIR
) return(True
);
828 if (newer_than
&& finfo
->mtime
< newer_than
)
831 if ((archive_level
==1 || archive_level
==2) && !(finfo
->mode
& aARCH
))
838 /*****************************************************************************
839 Convert a character pointer in a cli_call_api() response to a form we can use.
840 This function contains code to prevent core dumps if the server returns
842 *****************************************************************************/
843 static char *fix_char_ptr(unsigned int datap
, unsigned int converter
, char *rdata
, int rdrcnt
)
845 if( datap
== 0 ) /* turn NULL pointers */
846 { /* into zero length strings */
851 unsigned int offset
= datap
- converter
;
853 if( offset
>= rdrcnt
)
855 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap
, converter
, (unsigned long)rdata
, rdrcnt
));
860 return &rdata
[offset
];
865 /****************************************************************************
866 interpret a short filename structure
867 The length of the structure is returned
868 ****************************************************************************/
869 static int interpret_short_filename(char *p
,file_info
*finfo
)
871 finfo
->mode
= CVAL(p
,21);
873 /* this date is converted to GMT by make_unix_date */
874 finfo
->ctime
= make_unix_date(p
+22);
875 finfo
->mtime
= finfo
->atime
= finfo
->ctime
;
876 finfo
->size
= IVAL(p
,26);
877 pstrcpy(finfo
->name
,p
+30);
879 return(DIR_STRUCT_SIZE
);
882 /****************************************************************************
883 interpret a long filename structure - this is mostly guesses at the moment
884 The length of the structure is returned
885 The structure of a long filename depends on the info level. 260 is used
886 by NT and 2 is used by OS/2
887 ****************************************************************************/
888 static int interpret_long_filename(int level
,char *p
,file_info
*finfo
)
891 memcpy(finfo
,&def_finfo
,sizeof(*finfo
));
895 case 1: /* OS/2 understands this */
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
+27);
906 return(28 + CVAL(p
,26));
908 case 2: /* this is what OS/2 uses mostly */
911 /* these dates are converted to GMT by make_unix_date */
912 finfo
->ctime
= make_unix_date2(p
+4);
913 finfo
->atime
= make_unix_date2(p
+8);
914 finfo
->mtime
= make_unix_date2(p
+12);
915 finfo
->size
= IVAL(p
,16);
916 finfo
->mode
= CVAL(p
,24);
917 pstrcpy(finfo
->name
,p
+31);
919 return(32 + CVAL(p
,30));
921 /* levels 3 and 4 are untested */
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
+33);
938 /* these dates are probably like the other ones */
939 finfo
->ctime
= make_unix_date2(p
+8);
940 finfo
->atime
= make_unix_date2(p
+12);
941 finfo
->mtime
= make_unix_date2(p
+16);
942 finfo
->size
= IVAL(p
,20);
943 finfo
->mode
= CVAL(p
,28);
944 pstrcpy(finfo
->name
,p
+37);
948 case 260: /* NT uses this, but also accepts 2 */
953 p
+= 4; /* next entry offset */
954 p
+= 4; /* fileindex */
956 /* these dates appear to arrive in a weird way. It seems to
957 be localtime plus the serverzone given in the initial
958 connect. This is GMT when DST is not in effect and one
959 hour from GMT otherwise. Can this really be right??
961 I suppose this could be called kludge-GMT. Is is the GMT
962 you get by using the current DST setting on a different
963 localtime. It will be cheap to calculate, I suppose, as
964 no DST tables will be needed */
966 finfo
->ctime
= interpret_long_date(p
); p
+= 8;
967 finfo
->atime
= interpret_long_date(p
); p
+= 8;
968 finfo
->mtime
= interpret_long_date(p
); p
+= 8; p
+= 8;
969 finfo
->size
= IVAL(p
,0); p
+= 8;
970 p
+= 8; /* alloc size */
971 finfo
->mode
= CVAL(p
,0); p
+= 4;
972 namelen
= IVAL(p
,0); p
+= 4;
973 p
+= 4; /* EA size */
974 p
+= 2; /* short name len? */
975 p
+= 24; /* short name? */
976 StrnCpy(finfo
->name
,p
,namelen
);
982 DEBUG(1,("Unknown long filename format %d\n",level
));
989 /****************************************************************************
990 act on the files in a dir listing
992 RJS, 4-Apr-1998, dirstoo added to allow caller to indicate that directories
993 should be processed as well.
994 ****************************************************************************/
995 static void dir_action(char *inbuf
,char *outbuf
,int attribute
,file_info
*finfo
,BOOL recurse_dir
,void (*fn
)(file_info
*),BOOL longdir
, BOOL dirstoo
)
998 if (!((finfo
->mode
& aDIR
) == 0 && *fileselection
&&
999 !mask_match(finfo
->name
,fileselection
,False
,False
)) &&
1000 !(recurse_dir
&& (strequal(finfo
->name
,".") ||
1001 strequal(finfo
->name
,".."))))
1003 if (recurse_dir
&& (finfo
->mode
& aDIR
))
1008 if (fn
&& dirstoo
&& do_this_one(finfo
)) { /* Do dirs, RJS */
1012 pstrcpy(sav_dir
,cur_dir
);
1013 pstrcat(cur_dir
,finfo
->name
);
1014 pstrcat(cur_dir
,"\\");
1015 pstrcpy(mask2
,cur_dir
);
1018 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir
)));
1023 do_long_dir(inbuf
,outbuf
,mask2
,attribute
,fn
,True
, dirstoo
);
1025 do_dir(inbuf
,outbuf
,mask2
,attribute
,fn
,True
, dirstoo
);
1027 pstrcpy(cur_dir
,sav_dir
);
1031 if (fn
&& do_this_one(finfo
))
1038 /****************************************************************************
1039 get a directory listing
1040 ****************************************************************************/
1041 static void cmd_dir(char *inbuf
,char *outbuf
)
1043 int attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
1049 pstrcpy(mask
,cur_dir
);
1050 if(mask
[strlen(mask
)-1]!='\\')
1053 if (next_token(NULL
,buf
,NULL
,sizeof(buf
))) {
1064 do_dir(inbuf
,outbuf
,mask
,attribute
,NULL
,recurse
,False
);
1068 DEBUG(3, ("Total bytes listed: %d\n", dir_total
));
1072 /****************************************************************************
1073 get a directory listing
1074 ****************************************************************************/
1075 static void cmd_du(char *inbuf
,char *outbuf
)
1077 int attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
1083 pstrcpy(mask
,cur_dir
);
1084 if(mask
[strlen(mask
)-1]!='\\')
1087 if (next_token(NULL
,buf
,NULL
,sizeof(buf
)))
1099 do_dir(inbuf
,outbuf
,mask
,attribute
,do_du
,recurse
,False
);
1103 DEBUG(0, ("Total number of bytes: %d\n", dir_total
));
1106 /****************************************************************************
1107 get a file from rname to lname
1108 ****************************************************************************/
1109 static void do_get(char *rname
,char *lname
,file_info
*finfo1
)
1114 BOOL newhandle
= False
;
1115 char *inbuf
,*outbuf
;
1117 BOOL close_done
= False
;
1118 BOOL ignore_close_error
= False
;
1122 struct timeval tp_start
;
1123 GetTimeOfDay(&tp_start
);
1134 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1135 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1137 if (!inbuf
|| !outbuf
)
1139 DEBUG(0,("out of memory\n"));
1143 bzero(outbuf
,smb_size
);
1144 set_message(outbuf
,15,1 + strlen(rname
),True
);
1146 CVAL(outbuf
,smb_com
) = SMBopenX
;
1147 SSVAL(outbuf
,smb_tid
,cnum
);
1148 cli_setup_pkt(outbuf
);
1150 SSVAL(outbuf
,smb_vwv0
,0xFF);
1151 SSVAL(outbuf
,smb_vwv2
,1); /* return additional info */
1152 SSVAL(outbuf
,smb_vwv3
,(DENY_NONE
<<4));
1153 SSVAL(outbuf
,smb_vwv4
,aSYSTEM
| aHIDDEN
);
1154 SSVAL(outbuf
,smb_vwv5
,aSYSTEM
| aHIDDEN
);
1155 SSVAL(outbuf
,smb_vwv8
,1);
1156 SSVAL(outbuf
,smb_vwv11
,0xffff);
1157 SSVAL(outbuf
,smb_vwv12
,0xffff);
1159 p
= smb_buf(outbuf
);
1161 p
= skip_string(p
,1);
1163 /* do a chained openX with a readX? */
1167 DEBUG(3,("Chaining readX wth openX\n"));
1168 SSVAL(outbuf
,smb_vwv0
,SMBreadX
);
1169 SSVAL(outbuf
,smb_vwv1
,smb_offset(p
,outbuf
));
1172 SCVAL(p
,smb_wct
,10);
1173 SSVAL(p
,smb_vwv0
,0xFF);
1174 SSVAL(p
,smb_vwv5
,MIN(max_xmit
-500,finfo
.size
));
1175 SSVAL(p
,smb_vwv9
,MIN(BUFFER_SIZE
,finfo
.size
));
1176 smb_setlen(outbuf
,smb_len(outbuf
)+11*2+1);
1180 if(!strcmp(lname
,"-"))
1181 handle
= fileno(stdout
);
1184 handle
= creat(lname
,0644);
1189 DEBUG(0,("Error opening local file %s\n",lname
));
1190 free(inbuf
);free(outbuf
);
1194 send_smb(Client
,outbuf
);
1195 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1197 if (CVAL(inbuf
,smb_rcls
) != 0)
1199 if (CVAL(inbuf
,smb_rcls
) == ERRSRV
&&
1200 SVAL(inbuf
,smb_err
) == ERRnoresource
&&
1201 cli_reopen_connection(inbuf
,outbuf
))
1203 do_get(rname
,lname
,finfo1
);
1206 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
1209 free(inbuf
);free(outbuf
);
1213 pstrcpy(finfo
.name
,rname
);
1217 finfo
.mode
= SVAL(inbuf
,smb_vwv3
);
1218 /* these times arrive as LOCAL time, using the DST offset
1219 corresponding to that time, we convert them to GMT */
1220 finfo
.mtime
= make_unix_date3(inbuf
+smb_vwv4
);
1221 finfo
.atime
= finfo
.ctime
= finfo
.mtime
;
1222 finfo
.size
= IVAL(inbuf
,smb_vwv6
);
1225 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo
.name
),finfo
.mode
));
1227 fnum
= SVAL(inbuf
,smb_vwv2
);
1229 /* we might have got some data from a chained readX */
1230 if (SVAL(inbuf
,smb_vwv0
) == SMBreadX
)
1232 p
= (smb_base(inbuf
)+SVAL(inbuf
,smb_vwv1
)) - smb_wct
;
1233 datalen
= SVAL(p
,smb_vwv5
);
1234 dataptr
= smb_base(inbuf
) + SVAL(p
,smb_vwv6
);
1243 DEBUG(2,("getting file %s of size %.0f bytes as %s ",
1244 CNV_LANG(finfo
.name
),
1248 while (nread
< finfo
.size
&& !close_done
)
1251 static BOOL can_chain_close
= True
;
1255 DEBUG(3,("nread=%d max_xmit=%d fsize=%.0f\n",nread
,max_xmit
,(double)finfo
.size
));
1257 /* 3 possible read types. readbraw if a large block is required.
1258 readX + close if not much left and read if neither is supported */
1260 /* we might have already read some data from a chained readX */
1261 if (dataptr
&& datalen
>0)
1264 /* if we can finish now then readX+close */
1265 if (method
<0 && can_chain_close
&& (Protocol
>= PROTOCOL_LANMAN1
) &&
1266 ((finfo
.size
- nread
) <
1267 (max_xmit
- (2*smb_size
+ 13*SIZEOFWORD
+ 300))))
1270 /* if we support readraw then use that */
1271 if (method
<0 && readbraw_supported
)
1274 /* if we can then use readX */
1275 if (method
<0 && (Protocol
>= PROTOCOL_LANMAN1
))
1286 /* use readX + close */
1287 bzero(outbuf
,smb_size
);
1288 set_message(outbuf
,10,0,True
);
1289 CVAL(outbuf
,smb_com
) = SMBreadX
;
1290 SSVAL(outbuf
,smb_tid
,cnum
);
1291 cli_setup_pkt(outbuf
);
1295 CVAL(outbuf
,smb_vwv0
) = SMBclose
;
1296 SSVAL(outbuf
,smb_vwv1
,smb_offset(smb_buf(outbuf
),outbuf
));
1299 CVAL(outbuf
,smb_vwv0
) = 0xFF;
1301 SSVAL(outbuf
,smb_vwv2
,fnum
);
1302 SIVAL(outbuf
,smb_vwv3
,nread
);
1303 SSVAL(outbuf
,smb_vwv5
,MIN(max_xmit
-200,finfo
.size
- nread
));
1304 SSVAL(outbuf
,smb_vwv6
,0);
1305 SIVAL(outbuf
,smb_vwv7
,0);
1306 SSVAL(outbuf
,smb_vwv9
,MIN(BUFFER_SIZE
,finfo
.size
-nread
));
1310 p
= smb_buf(outbuf
);
1317 /* now set the total packet length */
1318 smb_setlen(outbuf
,smb_len(outbuf
)+9);
1321 send_smb(Client
,outbuf
);
1322 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1324 if (CVAL(inbuf
,smb_rcls
) != 0)
1326 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf
)));
1331 SVAL(inbuf
,smb_vwv0
) != SMBclose
)
1333 /* NOTE: WfWg sometimes just ignores the chained
1334 command! This seems to break the spec? */
1335 DEBUG(3,("Rejected chained close?\n"));
1337 can_chain_close
= False
;
1338 ignore_close_error
= True
;
1341 datalen
= SVAL(inbuf
,smb_vwv5
);
1342 dataptr
= smb_base(inbuf
) + SVAL(inbuf
,smb_vwv6
);
1348 static int readbraw_size
= BUFFER_SIZE
;
1351 bzero(outbuf
,smb_size
);
1352 set_message(outbuf
,8,0,True
);
1353 CVAL(outbuf
,smb_com
) = SMBreadbraw
;
1354 SSVAL(outbuf
,smb_tid
,cnum
);
1355 cli_setup_pkt(outbuf
);
1356 SSVAL(outbuf
,smb_vwv0
,fnum
);
1357 SIVAL(outbuf
,smb_vwv1
,nread
);
1358 SSVAL(outbuf
,smb_vwv3
,MIN(finfo
.size
-nread
,readbraw_size
));
1359 SSVAL(outbuf
,smb_vwv4
,0);
1360 SIVALS(outbuf
,smb_vwv5
,-1);
1361 send_smb(Client
,outbuf
);
1363 /* Now read the raw data into the buffer and write it */
1364 if(read_smb_length(Client
,inbuf
,0) == -1) {
1365 DEBUG(0,("Failed to read length in readbraw\n"));
1369 /* Even though this is not an smb message, smb_len
1370 returns the generic length of an smb message */
1371 datalen
= smb_len(inbuf
);
1375 /* we got a readbraw error */
1376 DEBUG(4,("readbraw error - reducing size\n"));
1377 readbraw_size
= (readbraw_size
* 9) / 10;
1379 if (readbraw_size
< max_xmit
)
1381 DEBUG(0,("disabling readbraw\n"));
1382 readbraw_supported
= False
;
1389 if(read_data(Client
,inbuf
,datalen
) != datalen
) {
1390 DEBUG(0,("Failed to read data in readbraw\n"));
1398 /* we've already read some data with a chained readX */
1402 /* use plain read */
1403 bzero(outbuf
,smb_size
);
1404 set_message(outbuf
,5,0,True
);
1405 CVAL(outbuf
,smb_com
) = SMBread
;
1406 SSVAL(outbuf
,smb_tid
,cnum
);
1407 cli_setup_pkt(outbuf
);
1409 SSVAL(outbuf
,smb_vwv0
,fnum
);
1410 SSVAL(outbuf
,smb_vwv1
,MIN(max_xmit
-200,finfo
.size
- nread
));
1411 SIVAL(outbuf
,smb_vwv2
,nread
);
1412 SSVAL(outbuf
,smb_vwv4
,finfo
.size
- nread
);
1414 send_smb(Client
,outbuf
);
1415 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1417 if (CVAL(inbuf
,smb_rcls
) != 0)
1419 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf
)));
1423 datalen
= SVAL(inbuf
,smb_vwv0
);
1424 dataptr
= smb_buf(inbuf
) + 3;
1428 if (writefile(handle
,dataptr
,datalen
) != datalen
)
1430 DEBUG(0,("Error writing local file\n"));
1437 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname
),nread
));
1449 cli_smb_close(inbuf
, outbuf
, Client
, cnum
, fnum
);
1451 if (!ignore_close_error
&& CVAL(inbuf
,smb_rcls
) != 0)
1453 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf
)));
1456 free(inbuf
);free(outbuf
);
1464 if (archive_level
>= 2 && (finfo
.mode
& aARCH
)) {
1465 bzero(outbuf
,smb_size
);
1466 set_message(outbuf
,8,strlen(rname
)+4,True
);
1467 CVAL(outbuf
,smb_com
) = SMBsetatr
;
1468 SSVAL(outbuf
,smb_tid
,cnum
);
1469 cli_setup_pkt(outbuf
);
1470 SSVAL(outbuf
,smb_vwv0
,finfo
.mode
& ~(aARCH
));
1471 SIVALS(outbuf
,smb_vwv1
,0);
1472 p
= smb_buf(outbuf
);
1478 send_smb(Client
,outbuf
);
1479 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1483 struct timeval tp_end
;
1486 GetTimeOfDay(&tp_end
);
1488 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
1489 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
1490 get_total_time_ms
+= this_time
;
1491 get_total_size
+= finfo
.size
;
1493 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1494 finfo
.size
/ (1.024*this_time
+ 1.0e-4),
1495 get_total_size
/ (1.024*get_total_time_ms
)));
1498 free(inbuf
);free(outbuf
);
1502 /****************************************************************************
1504 ****************************************************************************/
1505 static void cmd_get(char *dum_in
, char *dum_out
)
1511 pstrcpy(rname
,cur_dir
);
1512 pstrcat(rname
,"\\");
1514 p
= rname
+ strlen(rname
);
1516 if (!next_token(NULL
,p
,NULL
,sizeof(rname
)-strlen(rname
))) {
1517 DEBUG(0,("get <filename>\n"));
1521 dos_clean_name(rname
);
1523 next_token(NULL
,lname
,NULL
,sizeof(lname
));
1525 do_get(rname
,lname
,NULL
);
1529 /****************************************************************************
1530 do a mget operation on one file
1531 ****************************************************************************/
1532 static void do_mget(file_info
*finfo
)
1537 if (strequal(finfo
->name
,".") || strequal(finfo
->name
,".."))
1542 DEBUG(0,("mget aborted\n"));
1546 if (finfo
->mode
& aDIR
)
1547 slprintf(quest
,sizeof(pstring
)-1,
1548 "Get directory %s? ",CNV_LANG(finfo
->name
));
1550 slprintf(quest
,sizeof(pstring
)-1,
1551 "Get file %s? ",CNV_LANG(finfo
->name
));
1553 if (prompt
&& !yesno(quest
)) return;
1555 if (finfo
->mode
& aDIR
)
1557 pstring saved_curdir
;
1559 char *inbuf
,*outbuf
;
1561 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1562 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1564 if (!inbuf
|| !outbuf
)
1566 DEBUG(0,("out of memory\n"));
1570 pstrcpy(saved_curdir
,cur_dir
);
1572 pstrcat(cur_dir
,finfo
->name
);
1573 pstrcat(cur_dir
,"\\");
1575 unix_format(finfo
->name
);
1578 strlower(finfo
->name
);
1580 if (!directory_exist(finfo
->name
,NULL
) &&
1581 dos_mkdir(finfo
->name
,0777) != 0)
1583 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo
->name
)));
1584 pstrcpy(cur_dir
,saved_curdir
);
1585 free(inbuf
);free(outbuf
);
1589 if (dos_chdir(finfo
->name
) != 0)
1591 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo
->name
)));
1592 pstrcpy(cur_dir
,saved_curdir
);
1593 free(inbuf
);free(outbuf
);
1598 pstrcpy(mget_mask
,cur_dir
);
1599 pstrcat(mget_mask
,"*");
1601 do_dir((char *)inbuf
,(char *)outbuf
,
1602 mget_mask
,aSYSTEM
| aHIDDEN
| aDIR
,do_mget
,False
, False
);
1604 pstrcpy(cur_dir
,saved_curdir
);
1605 free(inbuf
);free(outbuf
);
1609 pstrcpy(rname
,cur_dir
);
1610 pstrcat(rname
,finfo
->name
);
1611 do_get(rname
,finfo
->name
,finfo
);
1615 /****************************************************************************
1616 view the file using the pager
1617 ****************************************************************************/
1618 static void cmd_more(char *dum_in
, char *dum_out
)
1620 fstring rname
,lname
,tmpname
,pager_cmd
;
1623 fstrcpy(rname
,cur_dir
);
1624 fstrcat(rname
,"\\");
1627 "%s/smbmore.%d",tmpdir(),(int)getpid());
1628 fstrcpy(lname
,tmpname
);
1630 if (!next_token(NULL
,rname
+strlen(rname
),NULL
,sizeof(rname
)-strlen(rname
))) {
1631 DEBUG(0,("more <filename>\n"));
1634 dos_clean_name(rname
);
1636 do_get(rname
,lname
,NULL
);
1638 pager
=getenv("PAGER");
1640 slprintf(pager_cmd
,sizeof(pager_cmd
)-1,
1641 "%s %s",(pager
? pager
:PAGER
), tmpname
);
1648 /****************************************************************************
1650 ****************************************************************************/
1651 static void cmd_mget(char *inbuf
,char *outbuf
)
1653 int attribute
= aSYSTEM
| aHIDDEN
;
1665 while (next_token(NULL
,p
,NULL
,sizeof(buf
)))
1667 pstrcpy(mget_mask
,cur_dir
);
1668 if(mget_mask
[strlen(mget_mask
)-1]!='\\')
1669 pstrcat(mget_mask
,"\\");
1672 pstrcpy(mget_mask
,p
);
1674 pstrcat(mget_mask
,p
);
1675 do_dir((char *)inbuf
,(char *)outbuf
,mget_mask
,attribute
,do_mget
,False
,False
);
1680 pstrcpy(mget_mask
,cur_dir
);
1681 if(mget_mask
[strlen(mget_mask
)-1]!='\\')
1682 pstrcat(mget_mask
,"\\");
1683 pstrcat(mget_mask
,"*");
1684 do_dir((char *)inbuf
,(char *)outbuf
,mget_mask
,attribute
,do_mget
,False
,False
);
1688 /****************************************************************************
1689 make a directory of name "name"
1690 ****************************************************************************/
1691 static BOOL
do_mkdir(char *name
)
1694 char *inbuf
,*outbuf
;
1696 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1697 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1699 if (!inbuf
|| !outbuf
)
1701 DEBUG(0,("out of memory\n"));
1705 bzero(outbuf
,smb_size
);
1706 set_message(outbuf
,0,2 + strlen(name
),True
);
1708 CVAL(outbuf
,smb_com
) = SMBmkdir
;
1709 SSVAL(outbuf
,smb_tid
,cnum
);
1710 cli_setup_pkt(outbuf
);
1713 p
= smb_buf(outbuf
);
1717 send_smb(Client
,outbuf
);
1718 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1720 if (CVAL(inbuf
,smb_rcls
) != 0)
1722 DEBUG(0,("%s making remote directory %s\n",
1723 smb_errstr(inbuf
),CNV_LANG(name
)));
1725 free(inbuf
);free(outbuf
);
1729 free(inbuf
);free(outbuf
);
1734 /****************************************************************************
1736 ****************************************************************************/
1737 static void cmd_mkdir(char *inbuf
,char *outbuf
)
1743 pstrcpy(mask
,cur_dir
);
1745 if (!next_token(NULL
,p
,NULL
,sizeof(buf
)))
1748 DEBUG(0,("mkdir <dirname>\n"));
1760 trim_string(ddir
,".",NULL
);
1761 p
= strtok(ddir
,"/\\");
1765 if (!chkpath(ddir2
,False
))
1769 pstrcat(ddir2
,"\\");
1770 p
= strtok(NULL
,"/\\");
1778 /*******************************************************************
1779 write to a file using writebraw
1780 ********************************************************************/
1781 static int smb_writeraw(char *outbuf
,int fnum
,int pos
,char *buf
,int n
)
1786 bzero(outbuf
,smb_size
);
1787 bzero(inbuf
,smb_size
);
1788 set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?12:10,0,True
);
1790 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
1791 SSVAL(outbuf
,smb_tid
,cnum
);
1792 cli_setup_pkt(outbuf
);
1794 SSVAL(outbuf
,smb_vwv0
,fnum
);
1795 SSVAL(outbuf
,smb_vwv1
,n
);
1796 SIVAL(outbuf
,smb_vwv3
,pos
);
1797 SSVAL(outbuf
,smb_vwv7
,1);
1799 send_smb(Client
,outbuf
);
1801 if (!client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
1804 _smb_setlen(buf
-4,n
); /* HACK! XXXX */
1806 if (write_socket(Client
,buf
-4,n
+4) != n
+4)
1809 if (!client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0) {
1810 DEBUG(0,("Error writing remote file (2)\n"));
1813 return(SVAL(inbuf
,smb_vwv0
));
1818 /*******************************************************************
1820 ********************************************************************/
1821 static int smb_writefile(char *outbuf
,int fnum
,int pos
,char *buf
,int n
)
1825 if (writebraw_supported
&& n
> (max_xmit
-200))
1826 return(smb_writeraw(outbuf
,fnum
,pos
,buf
,n
));
1828 bzero(outbuf
,smb_size
);
1829 bzero(inbuf
,smb_size
);
1830 set_message(outbuf
,5,n
+ 3,True
);
1832 CVAL(outbuf
,smb_com
) = SMBwrite
;
1833 SSVAL(outbuf
,smb_tid
,cnum
);
1834 cli_setup_pkt(outbuf
);
1836 SSVAL(outbuf
,smb_vwv0
,fnum
);
1837 SSVAL(outbuf
,smb_vwv1
,n
);
1838 SIVAL(outbuf
,smb_vwv2
,pos
);
1839 SSVAL(outbuf
,smb_vwv4
,0);
1840 CVAL(smb_buf(outbuf
),0) = 1;
1841 SSVAL(smb_buf(outbuf
),1,n
);
1843 memcpy(smb_buf(outbuf
)+3,buf
,n
);
1845 send_smb(Client
,outbuf
);
1846 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1848 if (CVAL(inbuf
,smb_rcls
) != 0) {
1849 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf
)));
1852 return(SVAL(inbuf
,smb_vwv0
));
1857 /****************************************************************************
1859 ****************************************************************************/
1860 static void do_put(char *rname
,char *lname
,file_info
*finfo
)
1866 char *inbuf
,*outbuf
;
1867 time_t close_time
= finfo
->mtime
;
1869 static int maxwrite
=0;
1871 struct timeval tp_start
;
1872 GetTimeOfDay(&tp_start
);
1874 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1875 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1877 if (!inbuf
|| !outbuf
)
1879 DEBUG(0,("out of memory\n"));
1883 bzero(outbuf
,smb_size
);
1884 set_message(outbuf
,3,2 + strlen(rname
),True
);
1886 if (finfo
->mtime
== 0 || finfo
->mtime
== -1)
1887 finfo
->mtime
= finfo
->atime
= finfo
->ctime
= time(NULL
);
1889 CVAL(outbuf
,smb_com
) = SMBcreate
;
1890 SSVAL(outbuf
,smb_tid
,cnum
);
1891 cli_setup_pkt(outbuf
);
1893 SSVAL(outbuf
,smb_vwv0
,finfo
->mode
);
1894 put_dos_date3(outbuf
,smb_vwv1
,finfo
->mtime
);
1896 p
= smb_buf(outbuf
);
1900 send_smb(Client
,outbuf
);
1901 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1903 if (CVAL(inbuf
,smb_rcls
) != 0)
1905 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
1907 free(inbuf
);free(outbuf
);if (buf
) free(buf
);
1911 /* allow files to be piped into smbclient
1912 jdblair 24.jun.98 */
1913 if (!strcmp(lname
, "-")) {
1915 /* size of file is not known */
1918 f
= fopen(lname
,"r");
1923 DEBUG(0,("Error opening local file %s\n",lname
));
1924 free(inbuf
);free(outbuf
);
1929 fnum
= SVAL(inbuf
,smb_vwv0
);
1930 if (finfo
->size
< 0)
1931 finfo
->size
= file_size(lname
);
1933 DEBUG(1,("putting file %s of size %.0f bytes as %s ",lname
,(double)finfo
->size
,CNV_LANG(rname
)));
1936 maxwrite
= writebraw_supported
?MAX(max_xmit
,BUFFER_SIZE
):(max_xmit
-200);
1938 /* This is a rewrite of the read/write loop that doesn't require the input
1939 file to be of a known length. This allows the stream pointer 'f' to
1942 Rather than reallocing the read buffer every loop to keep it the min
1943 necessary length this look uses a fixed length buffer and just tests
1944 for eof on the file stream at the top of each loop.
1945 jdblair, 24.jun.98 */
1947 buf
= (char *)malloc(maxwrite
+4);
1953 fseek(f
,nread
,SEEK_SET
);
1954 if ((n
= readfile(buf
+4,1,n
,f
)) < 1)
1956 DEBUG(0,("Error reading local file\n"));
1960 ret
= smb_writefile(outbuf
,fnum
,nread
,buf
+4,n
);
1964 DEBUG(0,("Error writing file\n"));
1975 bzero(outbuf
,smb_size
);
1976 set_message(outbuf
,3,0,True
);
1977 CVAL(outbuf
,smb_com
) = SMBclose
;
1978 SSVAL(outbuf
,smb_tid
,cnum
);
1979 cli_setup_pkt(outbuf
);
1981 SSVAL(outbuf
,smb_vwv0
,fnum
);
1982 put_dos_date3(outbuf
,smb_vwv1
,close_time
);
1984 send_smb(Client
,outbuf
);
1985 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1987 if (CVAL(inbuf
,smb_rcls
) != 0)
1989 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
1991 free(inbuf
);free(outbuf
);
1998 free(inbuf
);free(outbuf
);
2002 struct timeval tp_end
;
2005 GetTimeOfDay(&tp_end
);
2007 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
2008 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
2009 put_total_time_ms
+= this_time
;
2010 put_total_size
+= finfo
->size
;
2012 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
2013 finfo
->size
/ (1.024*this_time
+ 1.0e-4),
2014 put_total_size
/ (1.024*put_total_time_ms
)));
2020 /****************************************************************************
2022 ****************************************************************************/
2023 static void cmd_put(char *dum_in
, char *dum_out
)
2032 pstrcpy(rname
,cur_dir
);
2033 pstrcat(rname
,"\\");
2036 if (!next_token(NULL
,p
,NULL
,sizeof(buf
)))
2038 DEBUG(0,("put <filename>\n"));
2043 if (next_token(NULL
,p
,NULL
,sizeof(buf
)))
2046 pstrcat(rname
,lname
);
2048 dos_clean_name(rname
);
2052 /* allow '-' to represent stdin
2053 jdblair, 24.jun.98 */
2054 if (!file_exist(lname
,&st
) &&
2055 (strcmp(lname
,"-"))) {
2056 DEBUG(0,("%s does not exist\n",lname
));
2059 finfo
.mtime
= st
.st_mtime
;
2062 do_put(rname
,lname
,&finfo
);
2065 /****************************************************************************
2066 seek in a directory/file list until you get something that doesn't start with
2068 ****************************************************************************/
2069 static BOOL
seek_list(FILE *f
,char *name
)
2074 if (fscanf(f
,"%s",s
) != 1) return(False
);
2075 trim_string(s
,"./",NULL
);
2076 if (strncmp(s
,name
,strlen(name
)) != 0)
2087 /****************************************************************************
2088 set the file selection mask
2089 ****************************************************************************/
2090 static void cmd_select(char *dum_in
, char *dum_out
)
2092 pstrcpy(fileselection
,"");
2093 next_token(NULL
,fileselection
,NULL
,sizeof(fileselection
));
2097 /****************************************************************************
2099 ****************************************************************************/
2100 static void cmd_mput(char *dum_in
, char *dum_out
)
2111 while (next_token(NULL
,p
,NULL
,sizeof(buf
)))
2118 slprintf(tmpname
,sizeof(pstring
)-1,
2119 "%s/ls.smb.%d",tmpdir(),(int)getpid());
2121 slprintf(cmd
,sizeof(pstring
)-1,
2122 "find . -name \"%s\" -print > %s",p
,tmpname
);
2124 slprintf(cmd
,sizeof(pstring
)-1,
2125 "/bin/ls %s > %s",p
,tmpname
);
2128 f
= fopen(tmpname
,"r");
2135 if (fscanf(f
,"%s",lname
) != 1) break;
2136 trim_string(lname
,"./",NULL
);
2140 /* check if it's a directory */
2141 if (directory_exist(lname
,&st
))
2143 if (!recurse
) continue;
2144 slprintf(quest
,sizeof(pstring
)-1,
2145 "Put directory %s? ",lname
);
2146 if (prompt
&& !yesno(quest
))
2149 if (!seek_list(f
,lname
))
2154 pstrcpy(rname
,cur_dir
);
2155 pstrcat(rname
,lname
);
2156 if (!chkpath(rname
,False
) && !do_mkdir(rname
)) {
2158 if (!seek_list(f
,lname
))
2167 slprintf(quest
,sizeof(quest
)-1,
2168 "Put file %s? ",lname
);
2169 if (prompt
&& !yesno(quest
)) continue;
2171 pstrcpy(rname
,cur_dir
);
2172 pstrcat(rname
,lname
);
2176 /* null size so do_put knows to ignore it */
2179 /* set the date on the file */
2180 finfo
.mtime
= st
.st_mtime
;
2182 do_put(rname
,lname
,&finfo
);
2189 /****************************************************************************
2191 ****************************************************************************/
2192 static void do_cancel(int job
)
2194 char *rparam
= NULL
;
2200 bzero(param
,sizeof(param
));
2203 SSVAL(p
,0,81); /* DosPrintJobDel() */
2206 p
= skip_string(p
,1);
2208 p
= skip_string(p
,1);
2212 if (cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
,param
),0, 0,
2218 int res
= SVAL(rparam
,0);
2221 printf("Job %d cancelled\n",job
);
2223 printf("Error %d calcelling job %d\n",res
,job
);
2227 printf("Server refused cancel request\n");
2229 if (rparam
) free(rparam
);
2230 if (rdata
) free(rdata
);
2236 /****************************************************************************
2238 ****************************************************************************/
2239 static void cmd_cancel(char *inbuf
,char *outbuf
)
2244 if (!connect_as_printer
)
2246 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2247 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2250 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
))) {
2251 printf("cancel <jobid> ...\n");
2257 } while (next_token(NULL
,buf
,NULL
,sizeof(buf
)));
2263 /****************************************************************************
2265 ****************************************************************************/
2266 static void cmd_print(char *inbuf
,char *outbuf
)
2275 if (!connect_as_printer
)
2277 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2278 DEBUG(0,("Trying to print without -P may fail\n"));
2281 if (!next_token(NULL
,lname
,NULL
, sizeof(lname
)))
2283 DEBUG(0,("print <filename>\n"));
2287 pstrcpy(rname
,lname
);
2288 p
= strrchr(rname
,'/');
2293 pstrcpy(rname
,tname
);
2296 if ((int)strlen(rname
) > 14)
2299 if (strequal(lname
,"-"))
2302 pstrcpy(rname
,"stdin");
2305 dos_clean_name(rname
);
2307 bzero(outbuf
,smb_size
);
2308 set_message(outbuf
,2,2 + strlen(rname
),True
);
2310 CVAL(outbuf
,smb_com
) = SMBsplopen
;
2311 SSVAL(outbuf
,smb_tid
,cnum
);
2312 cli_setup_pkt(outbuf
);
2314 SSVAL(outbuf
,smb_vwv0
,0);
2315 SSVAL(outbuf
,smb_vwv1
,printmode
);
2317 p
= smb_buf(outbuf
);
2321 send_smb(Client
,outbuf
);
2322 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2324 if (CVAL(inbuf
,smb_rcls
) != 0)
2326 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
2331 f
= fopen(lname
,"r");
2334 DEBUG(0,("Error opening local file %s\n",lname
));
2339 fnum
= SVAL(inbuf
,smb_vwv0
);
2341 DEBUG(1,("printing file %s as %s\n",lname
,CNV_LANG(rname
)));
2347 bzero(outbuf
,smb_size
);
2348 set_message(outbuf
,1,3,True
);
2350 /* for some strange reason the OS/2 print server can't handle large
2351 packets when printing. weird */
2352 n
= MIN(1024,max_xmit
-(smb_len(outbuf
)+4));
2355 n
= printread(f
,smb_buf(outbuf
)+3,(int)(0.95*n
));
2357 n
= readfile(smb_buf(outbuf
)+3,1,n
,f
);
2360 DEBUG(0,("read gave %d\n",n
));
2364 smb_setlen(outbuf
,smb_len(outbuf
) + n
);
2366 CVAL(outbuf
,smb_com
) = SMBsplwr
;
2367 SSVAL(outbuf
,smb_tid
,cnum
);
2368 cli_setup_pkt(outbuf
);
2370 SSVAL(outbuf
,smb_vwv0
,fnum
);
2371 SSVAL(outbuf
,smb_vwv1
,n
+3);
2372 CVAL(smb_buf(outbuf
),0) = 1;
2373 SSVAL(smb_buf(outbuf
),1,n
);
2375 send_smb(Client
,outbuf
);
2376 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2378 if (CVAL(inbuf
,smb_rcls
) != 0)
2380 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf
)));
2387 DEBUG(2,("%d bytes printed\n",nread
));
2389 bzero(outbuf
,smb_size
);
2390 set_message(outbuf
,1,0,True
);
2391 CVAL(outbuf
,smb_com
) = SMBsplclose
;
2392 SSVAL(outbuf
,smb_tid
,cnum
);
2393 cli_setup_pkt(outbuf
);
2395 SSVAL(outbuf
,smb_vwv0
,fnum
);
2397 send_smb(Client
,outbuf
);
2398 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2400 if (CVAL(inbuf
,smb_rcls
) != 0)
2402 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf
)));
2412 /****************************************************************************
2413 show a print queue - this is deprecated as it uses the old smb that
2414 has limited support - the correct call is the cmd_p_queue_4() after this.
2415 ****************************************************************************/
2416 static void cmd_queue(char *inbuf
,char *outbuf
)
2421 bzero(outbuf
,smb_size
);
2422 set_message(outbuf
,2,0,True
);
2424 CVAL(outbuf
,smb_com
) = SMBsplretq
;
2425 SSVAL(outbuf
,smb_tid
,cnum
);
2426 cli_setup_pkt(outbuf
);
2428 SSVAL(outbuf
,smb_vwv0
,32); /* a max of 20 entries is to be shown */
2429 SSVAL(outbuf
,smb_vwv1
,0); /* the index into the queue */
2431 send_smb(Client
,outbuf
);
2432 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2434 if (CVAL(inbuf
,smb_rcls
) != 0)
2436 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf
)));
2440 count
= SVAL(inbuf
,smb_vwv0
);
2441 p
= smb_buf(inbuf
) + 3;
2444 DEBUG(0,("No entries in the print queue\n"));
2451 DEBUG(0,("Job Name Size Status\n"));
2457 case 0x01: safe_strcpy(status
,"held or stopped", sizeof(status
)-1); break;
2458 case 0x02: safe_strcpy(status
,"printing",sizeof(status
)-1); break;
2459 case 0x03: safe_strcpy(status
,"awaiting print", sizeof(status
)-1); break;
2460 case 0x04: safe_strcpy(status
,"in intercept",sizeof(status
)-1); break;
2461 case 0x05: safe_strcpy(status
,"file had error",sizeof(status
)-1); break;
2462 case 0x06: safe_strcpy(status
,"printer error",sizeof(status
)-1); break;
2463 default: safe_strcpy(status
,"unknown",sizeof(status
)-1); break;
2466 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2467 SVAL(p
,5),p
+12,IVAL(p
,7),status
));
2475 /****************************************************************************
2476 show information about a print queue
2477 ****************************************************************************/
2478 static void cmd_p_queue_4(char *inbuf
,char *outbuf
)
2480 char *rparam
= NULL
;
2487 if (!connect_as_printer
)
2489 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2490 DEBUG(0,("Trying to print without -P may fail\n"));
2493 bzero(param
,sizeof(param
));
2496 SSVAL(p
,0,76); /* API function number 76 (DosPrintJobEnum) */
2498 pstrcpy(p
,"zWrLeh"); /* parameter description? */
2499 p
= skip_string(p
,1);
2500 pstrcpy(p
,"WWzWWDDzz"); /* returned data format */
2501 p
= skip_string(p
,1);
2502 pstrcpy(p
,strrchr(service
,'\\')+1); /* name of queue */
2503 p
= skip_string(p
,1);
2504 SSVAL(p
,0,2); /* API function level 2, PRJINFO_2 data structure */
2505 SSVAL(p
,2,1000); /* size of bytes of returned data buffer */
2507 pstrcpy(p
,""); /* subformat */
2508 p
= skip_string(p
,1);
2510 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2511 if( cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
,param
), 0, 0,
2518 result_code
= SVAL(rparam
,0);
2519 converter
= SVAL(rparam
,2); /* conversion factor */
2521 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt
, rdrcnt
, SVAL(rparam
,4) ));
2523 if (result_code
== 0) /* if no error, */
2533 fstring PrinterName
;
2535 fstrcpy(PrinterName
,strrchr(service
,'\\')+1); /* name of queue */
2536 strlower(PrinterName
); /* in lower case */
2538 p
= rdata
; /* received data */
2539 for( i
= 0; i
< SVAL(rparam
,4); ++i
)
2542 Priority
= SVAL(p
,2);
2543 UserName
= fix_char_ptr(SVAL(p
,4), converter
, rdata
, rdrcnt
);
2545 Priority
= SVAL(p
,2);
2546 JobTime
= make_unix_date3( p
+ 12);
2547 JobTimeStr
= asctime(LocalTime( &JobTime
));
2549 JobName
= fix_char_ptr(SVAL(p
,24), converter
, rdata
, rdrcnt
);
2552 printf("%s-%u %s priority %u %s %s %u bytes\n",
2553 PrinterName
, JobId
, UserName
,
2554 Priority
, JobTimeStr
, JobName
, Size
);
2556 #if 0 /* DEBUG code */
2557 printf("Job Id: \"%u\"\n", SVAL(p
,0));
2558 printf("Priority: \"%u\"\n", SVAL(p
,2));
2560 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p
,4), converter
, rdata
, rdrcnt
) );
2561 printf("Position: \"%u\"\n", SVAL(p
,8));
2562 printf("Status: \"%u\"\n", SVAL(p
,10));
2564 JobTime
= make_unix_date3( p
+ 12);
2565 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime
)));
2566 printf("date: \"%u\"\n", SVAL(p
,12));
2568 printf("Size: \"%u\"\n", SVAL(p
,16));
2569 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p
,20), converter
, rdata
, rdrcnt
) );
2570 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p
,24), converter
, rdata
, rdrcnt
) );
2571 #endif /* DEBUG CODE */
2576 else /* cli_call_api() failed */
2578 printf("Failed, error = %d\n", result_code
);
2581 /* If any parameters or data were returned, free the storage. */
2582 if(rparam
) free(rparam
);
2583 if(rdata
) free(rdata
);
2588 /****************************************************************************
2589 show information about a print queue
2590 ****************************************************************************/
2591 static void cmd_qinfo(char *inbuf
,char *outbuf
)
2593 char *rparam
= NULL
;
2600 bzero(param
,sizeof(param
));
2603 SSVAL(p
,0,70); /* API function number 70 (DosPrintQGetInfo) */
2605 pstrcpy(p
,"zWrLh"); /* parameter description? */
2606 p
= skip_string(p
,1);
2607 pstrcpy(p
,"zWWWWzzzzWWzzl"); /* returned data format */
2608 p
= skip_string(p
,1);
2609 pstrcpy(p
,strrchr(service
,'\\')+1); /* name of queue */
2610 p
= skip_string(p
,1);
2611 SSVAL(p
,0,3); /* API function level 3, just queue info, no job info */
2612 SSVAL(p
,2,1000); /* size of bytes of returned data buffer */
2614 pstrcpy(p
,""); /* subformat */
2615 p
= skip_string(p
,1);
2617 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2618 if( cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
,param
), 0, 0,
2625 result_code
= SVAL(rparam
,0);
2626 converter
= SVAL(rparam
,2); /* conversion factor */
2628 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt
, rdrcnt
, SVAL(rparam
,4) ));
2630 if (result_code
== 0) /* if no error, */
2632 p
= rdata
; /* received data */
2634 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p
,0), converter
, rdata
, rdrcnt
) );
2635 printf("Priority: %u\n", SVAL(p
,4) );
2636 printf("Start time: %u\n", SVAL(p
,6) );
2637 printf("Until time: %u\n", SVAL(p
,8) );
2638 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p
,12), converter
, rdata
, rdrcnt
) );
2639 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p
,16), converter
, rdata
, rdrcnt
) );
2640 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p
,20), converter
, rdata
, rdrcnt
) );
2641 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p
,24), converter
, rdata
, rdrcnt
) );
2642 printf("Status: %u\n", SVAL(p
,28) );
2643 printf("Jobs: %u\n", SVAL(p
,30) );
2644 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p
,32), converter
, rdata
, rdrcnt
) );
2645 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p
,36), converter
, rdata
, rdrcnt
) );
2647 /* Dump the driver data */
2652 ddptr
= rdata
+ SVAL(p
,40) - converter
;
2653 if( SVAL(p
,40) == 0 ) {count
= 0;} else {count
= IVAL(ddptr
,0);}
2654 printf("Driverdata: size=%d, version=%u\n", count
, IVAL(ddptr
,4) );
2656 for(x
=8; x
< count
; x
+=16)
2658 for(y
=0; y
< 16; y
++)
2661 printf("%2.2X ", CVAL(ddptr
,(x
+y
)) );
2665 for(y
=0; y
< 16 && (x
+y
) < count
; y
++)
2667 c
= CVAL(ddptr
,(x
+y
));
2673 fputc('\n', stdout
);
2679 else /* cli_call_api() failed */
2681 printf("Failed, error = %d\n", result_code
);
2684 /* If any parameters or data were returned, free the storage. */
2685 if(rparam
) free(rparam
);
2686 if(rdata
) free(rdata
);
2691 /****************************************************************************
2693 ****************************************************************************/
2694 static void do_del(file_info
*finfo
)
2697 char *inbuf
,*outbuf
;
2700 pstrcpy(mask
,cur_dir
);
2701 pstrcat(mask
,finfo
->name
);
2703 if (finfo
->mode
& aDIR
)
2706 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
2707 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
2709 if (!inbuf
|| !outbuf
)
2711 DEBUG(0,("out of memory\n"));
2715 bzero(outbuf
,smb_size
);
2716 set_message(outbuf
,1,2 + strlen(mask
),True
);
2718 CVAL(outbuf
,smb_com
) = SMBunlink
;
2719 SSVAL(outbuf
,smb_tid
,cnum
);
2720 cli_setup_pkt(outbuf
);
2722 SSVAL(outbuf
,smb_vwv0
,0);
2724 p
= smb_buf(outbuf
);
2728 send_smb(Client
,outbuf
);
2729 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2731 if (CVAL(inbuf
,smb_rcls
) != 0)
2732 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf
),CNV_LANG(mask
)));
2734 free(inbuf
);free(outbuf
);
2738 /****************************************************************************
2740 ****************************************************************************/
2741 static void cmd_del(char *inbuf
,char *outbuf
)
2745 int attribute
= aSYSTEM
| aHIDDEN
;
2750 pstrcpy(mask
,cur_dir
);
2752 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2754 DEBUG(0,("del <filename>\n"));
2759 do_dir((char *)inbuf
,(char *)outbuf
,mask
,attribute
,do_del
,False
,False
);
2763 /****************************************************************************
2765 ****************************************************************************/
2766 static void cmd_rmdir(char *inbuf
,char *outbuf
)
2772 pstrcpy(mask
,cur_dir
);
2774 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2776 DEBUG(0,("rmdir <dirname>\n"));
2781 bzero(outbuf
,smb_size
);
2782 set_message(outbuf
,0,2 + strlen(mask
),True
);
2784 CVAL(outbuf
,smb_com
) = SMBrmdir
;
2785 SSVAL(outbuf
,smb_tid
,cnum
);
2786 cli_setup_pkt(outbuf
);
2789 p
= smb_buf(outbuf
);
2793 send_smb(Client
,outbuf
);
2794 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2796 if (CVAL(inbuf
,smb_rcls
) != 0)
2798 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf
),CNV_LANG(mask
)));
2804 /****************************************************************************
2806 ****************************************************************************/
2807 static void cmd_rename(char *inbuf
,char *outbuf
)
2813 pstrcpy(src
,cur_dir
);
2814 pstrcpy(dest
,cur_dir
);
2816 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
)) ||
2817 !next_token(NULL
,buf2
,NULL
, sizeof(buf2
)))
2819 DEBUG(0,("rename <src> <dest>\n"));
2825 bzero(outbuf
,smb_size
);
2826 set_message(outbuf
,1,4 + strlen(src
) + strlen(dest
),True
);
2828 CVAL(outbuf
,smb_com
) = SMBmv
;
2829 SSVAL(outbuf
,smb_tid
,cnum
);
2830 SSVAL(outbuf
,smb_vwv0
,aHIDDEN
| aDIR
| aSYSTEM
);
2831 cli_setup_pkt(outbuf
);
2833 p
= smb_buf(outbuf
);
2836 p
= skip_string(p
,1);
2840 send_smb(Client
,outbuf
);
2841 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2843 if (CVAL(inbuf
,smb_rcls
) != 0)
2845 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf
)));
2852 /****************************************************************************
2853 toggle the prompt flag
2854 ****************************************************************************/
2855 static void cmd_prompt(char *dum_in
, char *dum_out
)
2858 DEBUG(2,("prompting is now %s\n",prompt
?"on":"off"));
2862 /****************************************************************************
2863 set the newer than time
2864 ****************************************************************************/
2865 static void cmd_newer(char *dum_in
, char *dum_out
)
2869 SMB_STRUCT_STAT sbuf
;
2871 ok
= next_token(NULL
,buf
,NULL
,sizeof(buf
));
2872 if (ok
&& (dos_stat(buf
,&sbuf
) == 0))
2874 newer_than
= sbuf
.st_mtime
;
2875 DEBUG(1,("Getting files newer than %s",
2876 asctime(LocalTime(&newer_than
))));
2881 if (ok
&& newer_than
== 0)
2882 DEBUG(0,("Error setting newer-than time\n"));
2885 /****************************************************************************
2886 set the archive level
2887 ****************************************************************************/
2888 static void cmd_archive(char *dum_in
, char *dum_out
)
2892 if (next_token(NULL
,buf
,NULL
,sizeof(buf
))) {
2893 archive_level
= atoi(buf
);
2895 DEBUG(0,("Archive level is %d\n",archive_level
));
2898 /****************************************************************************
2899 toggle the lowercaseflag
2900 ****************************************************************************/
2901 static void cmd_lowercase(char *dum_in
, char *dum_out
)
2903 lowercase
= !lowercase
;
2904 DEBUG(2,("filename lowercasing is now %s\n",lowercase
?"on":"off"));
2910 /****************************************************************************
2911 toggle the recurse flag
2912 ****************************************************************************/
2913 static void cmd_recurse(char *dum_in
, char *dum_out
)
2916 DEBUG(2,("directory recursion is now %s\n",recurse
?"on":"off"));
2919 /****************************************************************************
2920 toggle the translate flag
2921 ****************************************************************************/
2922 static void cmd_translate(char *dum_in
, char *dum_out
)
2924 translation
= !translation
;
2925 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2926 translation
?"on":"off"));
2930 /****************************************************************************
2931 do a printmode command
2932 ****************************************************************************/
2933 static void cmd_printmode(char *dum_in
, char *dum_out
)
2938 if (next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2940 if (strequal(buf
,"text"))
2944 if (strequal(buf
,"graphics"))
2947 printmode
= atoi(buf
);
2954 fstrcpy(mode
,"text");
2957 fstrcpy(mode
,"graphics");
2960 slprintf(mode
,sizeof(mode
)-1,"%d",printmode
);
2964 DEBUG(2,("the printmode is now %s\n",mode
));
2967 /****************************************************************************
2969 ****************************************************************************/
2970 static void cmd_lcd(char *dum_in
, char *dum_out
)
2975 if (next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2977 DEBUG(2,("the local directory is now %s\n",GetWd(d
)));
2981 /****************************************************************************
2982 try and browse available connections on a host
2983 ****************************************************************************/
2984 static BOOL
browse_host(BOOL sort
)
2986 char *rparam
= NULL
;
2993 /* now send a SMBtrans command with api RNetShareEnum */
2995 SSVAL(p
,0,0); /* api number */
2998 p
= skip_string(p
,1);
2999 pstrcpy(p
,"B13BWz");
3000 p
= skip_string(p
,1);
3002 SSVAL(p
,2,BUFFER_SIZE
);
3005 if (cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
,param
),0, 0,
3011 int res
= SVAL(rparam
,0);
3012 int converter
=SVAL(rparam
,2);
3014 BOOL long_share_name
=False
;
3016 if (res
== 0 || res
== ERRmoredata
)
3018 count
=SVAL(rparam
,4);
3023 printf("\n\tSharename Type Comment\n");
3024 printf("\t--------- ---- -------\n");
3028 qsort(p
,count
,20,QSORT_CAST StrCaseCmp
);
3030 for (i
=0;i
<count
;i
++)
3033 int type
= SVAL(p
,14);
3034 int comment_offset
= IVAL(p
,16) & 0xFFFF;
3040 case STYPE_DISKTREE
:
3041 fstrcpy(typestr
,"Disk"); break;
3043 fstrcpy(typestr
,"Printer"); break;
3045 fstrcpy(typestr
,"Device"); break;
3047 fstrcpy(typestr
,"IPC"); break;
3050 printf("\t%-15.15s%-10.10s%s\n",
3052 comment_offset
?rdata
+comment_offset
-converter
:"");
3054 if (strlen(sname
)>8) long_share_name
=True
;
3059 if (long_share_name
) {
3060 printf("\nNOTE: There were share names longer than 8 chars.\n\
3061 On older clients these may not be accessible or may give browsing errors\n");
3064 if(res
== ERRmoredata
)
3065 printf("\nNOTE: More data was available, the list was truncated.\n");
3069 if (rparam
) free(rparam
);
3070 if (rdata
) free(rdata
);
3076 /****************************************************************************
3077 get some server info
3078 ****************************************************************************/
3079 static void server_info(void)
3081 char *rparam
= NULL
;
3087 bzero(param
,sizeof(param
));
3090 SSVAL(p
,0,63); /* NetServerGetInfo()? */
3093 p
= skip_string(p
,1);
3094 pstrcpy(p
,"zzzBBzz");
3095 p
= skip_string(p
,1);
3096 SSVAL(p
,0,10); /* level 10 */
3100 if (cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
,param
),0, 0,
3106 int res
= SVAL(rparam
,0);
3107 int converter
=SVAL(rparam
,2);
3113 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3114 rdata
+SVAL(p
,0)-converter
,
3115 rdata
+SVAL(p
,4)-converter
,
3116 rdata
+SVAL(p
,8)-converter
,
3117 rdata
+SVAL(p
,14)-converter
);
3121 if (rparam
) free(rparam
);
3122 if (rdata
) free(rdata
);
3128 /****************************************************************************
3129 try and browse available connections on a host
3130 ****************************************************************************/
3131 static BOOL
list_servers(char *wk_grp
)
3133 char *rparam
= NULL
;
3141 BOOL generic_request
= False
;
3144 if (strequal(wk_grp
,"WORKGROUP")) {
3145 /* we won't specify a workgroup */
3146 generic_request
= True
;
3149 /* now send a SMBtrans command with api ServerEnum? */
3151 SSVAL(p
,0,0x68); /* api number */
3154 pstrcpy(p
,generic_request
?"WrLehDO":"WrLehDz");
3155 p
= skip_string(p
,1);
3157 pstrcpy(p
,"B16BBDz");
3159 p
= skip_string(p
,1);
3161 SSVAL(p
,2,BUFFER_SIZE
- SAFETY_MARGIN
); /* buf length */
3167 if (!generic_request
) {
3169 p
= skip_string(p
,1);
3172 /* first ask for a list of servers in this workgroup */
3173 SIVAL(svtype_p
,0,SV_TYPE_ALL
);
3175 if (cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
+4,param
),0, 0,
3176 8, BUFFER_SIZE
- SAFETY_MARGIN
,
3181 int res
= SVAL(rparam
,0);
3182 int converter
=SVAL(rparam
,2);
3185 if (res
== 0 || res
== ERRmoredata
) {
3187 count
=SVAL(rparam
,4);
3190 printf("\n\nThis machine has a browse list:\n");
3191 printf("\n\tServer Comment\n");
3192 printf("\t--------- -------\n");
3195 for (i
=0;i
<count
;i
++) {
3197 int comment_offset
= IVAL(p2
,22) & 0xFFFF;
3198 printf("\t%-16.16s %s\n", sname
,
3199 comment_offset
?rdata
+comment_offset
-converter
:"");
3205 if(res
== ERRmoredata
)
3206 printf("\nNOTE: More data was available, the list was truncated.\n");
3210 if (rparam
) {free(rparam
); rparam
= NULL
;}
3211 if (rdata
) {free(rdata
); rdata
= NULL
;}
3213 /* now ask for a list of workgroups */
3214 SIVAL(svtype_p
,0,SV_TYPE_DOMAIN_ENUM
);
3216 if (cli_call_api(PIPE_LANMAN
, 0,PTR_DIFF(p
+4,param
),0, 0,
3217 8, BUFFER_SIZE
- SAFETY_MARGIN
,
3222 int res
= SVAL(rparam
,0);
3223 int converter
=SVAL(rparam
,2);
3226 if (res
== 0 || res
== ERRmoredata
) {
3228 count
=SVAL(rparam
,4);
3231 printf("\n\nThis machine has a workgroup list:\n");
3232 printf("\n\tWorkgroup Master\n");
3233 printf("\t--------- -------\n");
3236 for (i
=0;i
<count
;i
++) {
3238 int comment_offset
= IVAL(p2
,22) & 0xFFFF;
3239 printf("\t%-16.16s %s\n", sname
,
3240 comment_offset
?rdata
+comment_offset
-converter
:"");
3246 if(res
== ERRmoredata
)
3247 printf("\nNOTE: More data was available, the list was truncated.\n");
3251 if (rparam
) free(rparam
);
3252 if (rdata
) free(rdata
);
3258 /* Some constants for completing filename arguments */
3260 #define COMPL_NONE 0 /* No completions */
3261 #define COMPL_REMOTE 1 /* Complete remote filename */
3262 #define COMPL_LOCAL 2 /* Complete local filename */
3264 /* This defines the commands supported by this client */
3268 void (*fn
)(char *, char *);
3270 char compl_args
[2]; /* Completion argument info */
3273 {"ls",cmd_dir
,"<mask> list the contents of the current directory",{COMPL_REMOTE
,COMPL_NONE
}},
3274 {"dir",cmd_dir
,"<mask> list the contents of the current directory",{COMPL_REMOTE
,COMPL_NONE
}},
3275 {"du",cmd_du
,"<mask> computes the total size of the current directory",{COMPL_REMOTE
,COMPL_NONE
}},
3276 {"lcd",cmd_lcd
,"[directory] change/report the local current working directory",{COMPL_LOCAL
,COMPL_NONE
}},
3277 {"cd",cmd_cd
,"[directory] change/report the remote directory",{COMPL_REMOTE
,COMPL_NONE
}},
3278 {"pwd",cmd_pwd
,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE
,COMPL_NONE
}},
3279 {"get",cmd_get
,"<remote name> [local name] get a file",{COMPL_REMOTE
,COMPL_LOCAL
}},
3280 {"mget",cmd_mget
,"<mask> get all the matching files",{COMPL_REMOTE
,COMPL_NONE
}},
3281 {"put",cmd_put
,"<local name> [remote name] put a file",{COMPL_LOCAL
,COMPL_REMOTE
}},
3282 {"mput",cmd_mput
,"<mask> put all matching files",{COMPL_REMOTE
,COMPL_NONE
}},
3283 {"rename",cmd_rename
,"<src> <dest> rename some files",{COMPL_REMOTE
,COMPL_REMOTE
}},
3284 {"more",cmd_more
,"<remote name> view a remote file with your pager",{COMPL_REMOTE
,COMPL_NONE
}},
3285 {"mask",cmd_select
,"<mask> mask all filenames against this",{COMPL_REMOTE
,COMPL_NONE
}},
3286 {"del",cmd_del
,"<mask> delete all matching files",{COMPL_REMOTE
,COMPL_NONE
}},
3287 {"rm",cmd_del
,"<mask> delete all matching files",{COMPL_REMOTE
,COMPL_NONE
}},
3288 {"mkdir",cmd_mkdir
,"<directory> make a directory",{COMPL_NONE
,COMPL_NONE
}},
3289 {"md",cmd_mkdir
,"<directory> make a directory",{COMPL_NONE
,COMPL_NONE
}},
3290 {"rmdir",cmd_rmdir
,"<directory> remove a directory",{COMPL_NONE
,COMPL_NONE
}},
3291 {"rd",cmd_rmdir
,"<directory> remove a directory",{COMPL_NONE
,COMPL_NONE
}},
3292 {"pq",cmd_p_queue_4
,"enumerate the print queue",{COMPL_NONE
,COMPL_NONE
}},
3293 {"prompt",cmd_prompt
,"toggle prompting for filenames for mget and mput",{COMPL_NONE
,COMPL_NONE
}},
3294 {"recurse",cmd_recurse
,"toggle directory recursion for mget and mput",{COMPL_NONE
,COMPL_NONE
}},
3295 {"translate",cmd_translate
,"toggle text translation for printing",{COMPL_NONE
,COMPL_NONE
}},
3296 {"lowercase",cmd_lowercase
,"toggle lowercasing of filenames for get",{COMPL_NONE
,COMPL_NONE
}},
3297 {"print",cmd_print
,"<file name> print a file",{COMPL_NONE
,COMPL_NONE
}},
3298 {"printmode",cmd_printmode
,"<graphics or text> set the print mode",{COMPL_NONE
,COMPL_NONE
}},
3299 {"queue",cmd_queue
,"show the print queue",{COMPL_NONE
,COMPL_NONE
}},
3300 {"qinfo",cmd_qinfo
,"show print queue information",{COMPL_NONE
,COMPL_NONE
}},
3301 {"cancel",cmd_cancel
,"<jobid> cancel a print queue entry",{COMPL_NONE
,COMPL_NONE
}},
3302 {"quit",cli_send_logout
,"logoff the server",{COMPL_NONE
,COMPL_NONE
}},
3303 {"q",cli_send_logout
,"logoff the server",{COMPL_NONE
,COMPL_NONE
}},
3304 {"exit",cli_send_logout
,"logoff the server",{COMPL_NONE
,COMPL_NONE
}},
3305 {"newer",cmd_newer
,"<file> only mget files newer than the specified local file",{COMPL_LOCAL
,COMPL_NONE
}},
3306 {"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
}},
3307 {"tar",cmd_tar
,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE
,COMPL_NONE
}},
3308 {"blocksize",cmd_block
,"blocksize <number> (default 20)",{COMPL_NONE
,COMPL_NONE
}},
3309 {"tarmode",cmd_tarmode
,
3310 "<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE
,COMPL_NONE
}},
3311 {"setmode",cmd_setmode
,"filename <setmode string> change modes of file",{COMPL_REMOTE
,COMPL_NONE
}},
3312 {"help",cmd_help
,"[command] give help on a command",{COMPL_NONE
,COMPL_NONE
}},
3313 {"?",cmd_help
,"[command] give help on a command",{COMPL_NONE
,COMPL_NONE
}},
3314 {"!",NULL
,"run a shell command on the local system",{COMPL_NONE
,COMPL_NONE
}},
3315 {"",NULL
,NULL
,{COMPL_NONE
,COMPL_NONE
}}
3319 /*******************************************************************
3320 lookup a command string in the list of commands, including
3322 ******************************************************************/
3323 static int process_tok(fstring tok
)
3325 int i
= 0, matches
= 0;
3327 int tok_len
= strlen(tok
);
3329 while (commands
[i
].fn
!= NULL
)
3331 if (strequal(commands
[i
].name
,tok
))
3337 else if (strnequal(commands
[i
].name
, tok
, tok_len
))
3347 else if (matches
== 1)
3353 /****************************************************************************
3355 ****************************************************************************/
3356 static void cmd_help(char *dum_in
, char *dum_out
)
3361 if (next_token(NULL
,buf
,NULL
,sizeof(buf
)))
3363 if ((i
= process_tok(buf
)) >= 0)
3364 DEBUG(0,("HELP %s:\n\t%s\n\n",commands
[i
].name
,commands
[i
].description
));
3367 while (commands
[i
].description
)
3369 for (j
=0; commands
[i
].description
&& (j
<5); j
++) {
3370 DEBUG(0,("%-15s",commands
[i
].name
));
3377 #ifndef HAVE_LIBREADLINE
3379 /****************************************************************************
3380 wait for keyboard activity, swallowing network packets
3381 ****************************************************************************/
3382 static void wait_keyboard(char *buffer
)
3385 struct timeval timeout
;
3391 FD_SET(Client
,&fds
);
3392 FD_SET(fileno(stdin
),&fds
);
3394 timeout
.tv_sec
= 20;
3395 timeout
.tv_usec
= 0;
3396 sys_select(MAX(Client
,fileno(stdin
))+1,&fds
,&timeout
);
3398 if (FD_ISSET(fileno(stdin
),&fds
))
3401 /* We deliberately use receive_smb instead of
3402 client_receive_smb as we want to receive
3403 session keepalives and then drop them here.
3405 if (FD_ISSET(Client
,&fds
))
3406 receive_smb(Client
,buffer
,0);
3408 chkpath("\\",False
);
3412 #else /* if HAVE_LIBREADLINE */
3414 /****************************************************************************
3415 completion routines for GNU Readline
3416 ****************************************************************************/
3418 /* To avoid filename completion being activated when no valid
3419 completions are found, we assign this stub completion function
3420 to the rl_completion_entry_function variable. */
3422 char *complete_cmd_null(char *text
, int state
)
3427 /* Argh. This is starting to get ugly. We need to be able to pass data
3428 back from the do_dir() iterator function. */
3430 static int compl_state
;
3431 static char *compl_text
;
3432 static pstring result
;
3434 /* Iterator function for do_dir() */
3436 void complete_process_file(file_info
*f
)
3438 /* Do we have a partial match? */
3440 if ((compl_state
>= 0) && (strncmp(compl_text
, f
->name
,
3441 strlen(compl_text
)) == 0)) {
3443 /* Return filename if we have made enough matches */
3445 if (compl_state
== 0) {
3446 pstrcpy(result
, f
->name
);
3455 /* Complete a remote file */
3457 char *complete_remote_file(char *text
, int state
)
3459 char *InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3460 char *OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3461 int attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
3464 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
3467 /* Create dir mask */
3469 pstrcpy(mask
, cur_dir
);
3472 /* Initialise static vars for filename match */
3475 compl_state
= state
;
3478 /* Iterate over all files in directory */
3480 do_dir(InBuffer
, OutBuffer
, mask
, attribute
, complete_process_file
, False
,
3488 /* Return matched filename */
3490 if (result
[0] != '\0') {
3491 return strdup(result
); /* Readline will dispose of strings */
3497 /* Complete a smbclient command */
3499 char *complete_cmd(char *text
, int state
)
3501 static int cmd_index
;
3510 /* Return the next name which partially matches the list of commands */
3512 while (strlen(name
= commands
[cmd_index
++].name
) > 0) {
3513 if (strncmp(name
, text
, strlen(text
)) == 0) {
3514 return strdup(name
);
3521 /* Main completion function for smbclient. Work out which word we are
3522 trying to complete and call the appropriate function. */
3524 char **completion_fn(char *text
, int start
, int end
)
3526 int i
, num_words
, cmd_index
;
3529 /* If we are at the start of a word, we are completing a smbclient
3533 return completion_matches(text
, complete_cmd
);
3536 /* Count # of words in command */
3539 for (i
= 0; i
<= end
; i
++) {
3540 if ((rl_line_buffer
[i
] != ' ') && (lastch
== ' '))
3542 lastch
= rl_line_buffer
[i
];
3545 if (rl_line_buffer
[end
] == ' ')
3548 /* Work out which command we are completing for */
3550 for (cmd_index
= 0; strcmp(commands
[cmd_index
].name
, "") != 0;
3553 /* Check each command in array */
3555 if (strncmp(rl_line_buffer
, commands
[cmd_index
].name
,
3556 strlen(commands
[cmd_index
].name
)) == 0) {
3558 /* Call appropriate completion function */
3560 if ((num_words
== 2) || (num_words
== 3)) {
3561 switch (commands
[cmd_index
].compl_args
[num_words
- 2]) {
3564 return completion_matches(text
, complete_remote_file
);
3568 return completion_matches(text
, filename_completion_function
);
3572 /* An invalid completion type */
3577 /* We're either completing an argument > 3 or found an invalid
3578 completion type. Either way do nothing about it. */
3587 #endif /* HAVE_LIBREADLINE */
3589 /****************************************************************************
3590 process commands from the client
3591 ****************************************************************************/
3592 static BOOL
process(char *base_directory
)
3597 char *InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3598 char *OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3600 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
3603 bzero(OutBuffer
,smb_size
);
3605 if (!cli_send_login(InBuffer
,OutBuffer
,True
,True
,NULL
))
3608 if (*base_directory
) do_cd(base_directory
);
3611 if (cmd
[0] != '\0') while (cmd
[0] != '\0')
3617 if ((p
= strchr(cmd
, ';')) == 0)
3619 strncpy(line
, cmd
, 999);
3625 if (p
- cmd
> 999) p
= cmd
+ 999;
3626 strncpy(line
, cmd
, p
- cmd
);
3627 line
[p
- cmd
] = '\0';
3631 /* input language code to internal one */
3634 /* and get the first part of the command */
3637 if (!next_token(&ptr
,tok
,NULL
,sizeof(tok
))) continue;
3640 if ((i
= process_tok(tok
)) >= 0)
3641 commands
[i
].fn(InBuffer
,OutBuffer
);
3643 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok
)));
3645 DEBUG(0,("%s: command not found\n",CNV_LANG(tok
)));
3647 else while (!feof(stdin
))
3652 bzero(OutBuffer
,smb_size
);
3654 #ifdef HAVE_LIBREADLINE
3659 /* Read input using GNU Readline */
3661 slprintf(prompt
, sizeof(prompt
) - 1, "smb: %s> ", CNV_LANG(cur_dir
));
3662 if (!readline(prompt
))
3665 /* Copy read line to samba buffer */
3667 pstrcpy(line
, rl_line_buffer
);
3668 pstrcat(line
, "\n");
3670 /* Add line to history */
3672 if (strlen(line
) > 0)
3678 /* display a prompt */
3679 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir
)));
3682 wait_keyboard(InBuffer
);
3684 /* and get a response */
3685 if (!fgets(line
,1000,stdin
))
3690 /* input language code to internal one */
3693 /* special case - first char is ! */
3700 /* and get the first part of the command */
3703 if (!next_token(&ptr
,tok
,NULL
,sizeof(tok
))) continue;
3706 if ((i
= process_tok(tok
)) >= 0)
3707 commands
[i
].fn(InBuffer
,OutBuffer
);
3709 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok
)));
3711 DEBUG(0,("%s: command not found\n",CNV_LANG(tok
)));
3714 cli_send_logout(InBuffer
,OutBuffer
);
3718 /****************************************************************************
3719 usage on the program
3720 ****************************************************************************/
3721 static void usage(char *pname
)
3723 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3726 DEBUG(0,("\nVersion %s\n",VERSION
));
3727 DEBUG(0,("\t-p port connect to the specified port\n"));
3728 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3729 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3730 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3731 DEBUG(0,("\t-N don't ask for a password\n"));
3732 DEBUG(0,("\t-P connect to service as a printer\n"));
3733 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3734 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3735 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3736 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3737 DEBUG(0,("\t-R name resolve order use these name resolution services only\n"));
3738 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3739 DEBUG(0,("\t-U username set the network username\n"));
3740 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3741 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3742 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3743 DEBUG(0,("\t-T<c|x>IXFqgbNan command line tar\n"));
3744 DEBUG(0,("\t-D directory start from directory\n"));
3748 /****************************************************************************
3750 ****************************************************************************/
3751 int main(int argc
,char *argv
[])
3753 fstring base_directory
;
3754 char *pname
= argv
[0];
3755 int port
= SMB_PORT
;
3758 extern char *optarg
;
3761 BOOL message
= False
;
3762 BOOL nt_domain_logon
= False
;
3763 BOOL explicit_user
= False
;
3764 extern char tar_type
;
3765 static pstring servicesf
= CONFIGFILE
;
3767 pstring new_name_resolve_order
;
3771 pstrcpy(term_code
, KANJI
);
3777 *base_directory
= 0;
3779 *new_name_resolve_order
= 0;
3783 setup_logging(pname
,True
);
3786 charset_initialise();
3788 if(!get_myname(myhostname
,NULL
))
3790 DEBUG(0,("Failed to get my hostname.\n"));
3795 if (!lp_load(servicesf
,True
,False
,False
)) {
3796 fprintf(stderr
, "Can't load %s - run testparm to debug it\n", servicesf
);
3799 codepage_initialise(lp_client_code_page());
3801 interpret_coding_system(term_code
);
3807 pstrcpy(workgroup
,lp_workgroup());
3810 pid
= (uint16
)getpid();
3811 vuid
= (uint16
)getuid();
3818 pstrcpy(username
,getenv("USER"));
3820 /* modification to support userid%passwd syntax in the USER var
3821 25.Aug.97, jdblair@uab.edu */
3823 if ((p
=strchr(username
,'%')))
3826 pstrcpy(password
,p
+1);
3828 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password
));
3833 /* modification to support PASSWD environmental var
3834 25.Aug.97, jdblair@uab.edu */
3836 if (getenv("PASSWD")) {
3837 pstrcpy(password
,getenv("PASSWD"));
3841 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
3843 BOOL close_it
= False
;
3847 if ((p
= getenv("PASSWD_FD")) != NULL
) {
3848 pstrcpy(spec
, "descriptor ");
3850 sscanf(p
, "%d", &fd
);
3852 } else if ((p
= getenv("PASSWD_FILE")) != NULL
) {
3853 fd
= open(p
, O_RDONLY
);
3856 fprintf(stderr
, "Error opening PASSWD_FILE %s: %s\n",
3857 spec
, strerror(errno
));
3862 for(p
= pass
, *p
= '\0'; /* ensure that pass is null-terminated */
3863 p
&& p
- pass
< sizeof(pass
);) {
3864 switch (read(fd
, p
, 1)) {
3866 if (*p
!= '\n' && *p
!= '\0') {
3867 *++p
= '\0'; /* advance p, and null-terminate pass */
3872 *p
= '\0'; /* null-terminate it, just in case... */
3873 p
= NULL
; /* then force the loop condition to become false */
3876 fprintf(stderr
, "Error reading password from file %s: %s\n",
3877 spec
, "empty password\n");
3882 fprintf(stderr
, "Error reading password from file %s: %s\n",
3883 spec
, strerror(errno
));
3887 pstrcpy(password
, pass
);
3893 if (*username
== 0 && getenv("LOGNAME"))
3895 pstrcpy(username
,getenv("LOGNAME"));
3905 if (*argv
[1] != '-')
3908 pstrcpy(service
,argv
[1]);
3909 /* Convert any '/' characters in the service name to '\' characters */
3910 string_replace( service
, '/','\\');
3914 if (count_chars(service
,'\\') < 3)
3917 printf("\n%s: Not enough '\\' characters in service\n",service
);
3922 if (count_chars(service,'\\') > 3)
3925 printf("\n%s: Too many '\\' characters in service\n",service);
3930 if (argc
> 1 && (*argv
[1] != '-'))
3933 pstrcpy(password
,argv
[1]);
3934 memset(argv
[1],'X',strlen(argv
[1]));
3941 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
)
3945 max_protocol
= interpret_protocol(optarg
,max_protocol
);
3948 pstrcpy(user_socket_options
,optarg
);
3951 pstrcpy(new_name_resolve_order
, optarg
);
3954 pstrcpy(desthost
,optarg
);
3956 nt_domain_logon
= True
;
3959 name_type
= 0x03; /* messages are sent to NetBIOS name type 0x3 */
3960 pstrcpy(desthost
,optarg
);
3965 iface_set_default(NULL
,optarg
,NULL
);
3968 pstrcpy(base_directory
,optarg
);
3971 if (!tar_parseargs(argc
, argv
, optarg
, optind
)) {
3977 pstrcpy(scope
,optarg
);
3981 pstrcpy(query_host
,optarg
);
3988 explicit_user
= True
;
3989 pstrcpy(username
,optarg
);
3990 if ((lp
=strchr(username
,'%')))
3993 pstrcpy(password
,lp
+1);
3995 memset(strchr(optarg
,'%')+1,'X',strlen(password
));
4001 pstrcpy(workgroup
,optarg
);
4008 dest_ip
= *interpret_addr2(optarg
);
4009 if (zero_ip(dest_ip
)) exit(1);
4014 pstrcpy(global_myname
,optarg
);
4021 connect_as_printer
= True
;
4027 DEBUGLEVEL
= atoi(optarg
);
4030 slprintf(debugf
,sizeof(debugf
)-1, "%s.client",optarg
);
4033 port
= atoi(optarg
);
4044 pstrcpy(servicesf
, optarg
);
4047 pstrcpy(term_code
, optarg
);
4054 get_myname((*global_myname
)?NULL
:global_myname
,NULL
);
4055 strupper(global_myname
);
4057 if(*new_name_resolve_order
)
4058 lp_set_name_resolve_order(new_name_resolve_order
);
4060 if (!tar_type
&& !*query_host
&& !*service
&& !message
)
4066 #ifdef HAVE_LIBREADLINE
4068 /* Initialise GNU Readline */
4070 rl_readline_name
= "smbclient";
4071 rl_attempted_completion_function
= completion_fn
;
4072 rl_completion_entry_function
= (Function
*)complete_cmd_null
;
4074 /* Initialise history list */
4078 #endif /* HAVE_LIBREADLINE */
4080 DEBUG( 3, ( "Client started (version %s).\n", VERSION
) );
4085 if (cli_open_sockets(port
)) {
4086 char *InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
4087 char *OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
4090 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
4093 bzero(OutBuffer
,smb_size
);
4094 if (!cli_send_login(InBuffer
,OutBuffer
,True
,True
,NULL
))
4097 if (*base_directory
) do_cd(base_directory
);
4099 ret
=process_tar(InBuffer
, OutBuffer
);
4101 cli_send_logout(InBuffer
, OutBuffer
);
4108 if (*query_host
&& !nt_domain_logon
)
4111 slprintf(service
,sizeof(service
)-1,
4112 "\\\\%s\\IPC$",query_host
);
4114 connect_as_ipc
= True
;
4115 if (cli_open_sockets(port
))
4120 if (!cli_send_login(NULL
,NULL
,True
,True
,NULL
))
4124 if (!browse_host(True
)) {
4128 if (!list_servers(workgroup
)) {
4130 list_servers(workgroup
);
4133 cli_send_logout(NULL
,NULL
);
4143 if (cli_open_sockets(port
))
4145 pstring inbuf
,outbuf
;
4146 bzero(outbuf
,smb_size
);
4147 if (!cli_send_session_request(inbuf
,outbuf
))
4150 send_message(inbuf
,outbuf
);
4158 if (cli_open_sockets(port
))
4160 if (!process(base_directory
))