2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 pstring cur_dir
= "\\";
36 extern pstring myname
;
37 pstring password
= "";
39 pstring workgroup
=WORKGROUP
;
41 BOOL got_pass
= False
;
42 BOOL connect_as_printer
= False
;
43 BOOL connect_as_ipc
= False
;
44 extern struct in_addr ipzero
;
49 extern pstring user_socket_options
;
51 /* 30 second timeout on most commands */
52 #define CLIENT_TIMEOUT (30*1000)
53 #define SHORT_TIMEOUT (5*1000)
55 /* value for unused fid field in trans2 secondary request */
56 #define FID_UNUSED (0xFFFF)
60 int max_protocol
= PROTOCOL_NT1
;
63 time_t newer_than
= 0;
64 int archive_level
= 0;
66 extern pstring debugf
;
67 extern int DEBUGLEVEL
;
69 BOOL translation
= False
;
72 static BOOL
send_trans_request(char *outbuf
,int trans
,
73 char *name
,int fid
,int flags
,
74 char *data
,char *param
,uint16
*setup
,
75 int ldata
,int lparam
,int lsetup
,
76 int mdata
,int mparam
,int msetup
);
77 static BOOL
receive_trans_response(char *inbuf
,int trans
,
78 int *data_len
,int *param_len
,
79 char **data
,char **param
);
80 static int interpret_long_filename(int level
,char *p
,file_info
*finfo
);
81 static void dir_action(char *inbuf
,char *outbuf
,int attribute
,file_info
*finfo
,BOOL recurse_dir
,void (*fn
)(),BOOL longdir
);
82 static int interpret_short_filename(char *p
,file_info
*finfo
);
83 static BOOL
call_api(int prcnt
,int drcnt
,
84 int mprcnt
,int mdrcnt
,
85 int *rprcnt
,int *rdrcnt
,
86 char *param
,char *data
,
87 char **rparam
,char **rdata
);
90 /* clitar bits insert */
93 extern BOOL tar_reset
;
104 int max_xmit
= BUFFER_SIZE
;
106 extern pstring scope
;
112 BOOL recurse
= False
;
113 BOOL lowercase
= False
;
115 BOOL have_ip
= False
;
117 struct in_addr dest_ip
;
119 #define SEPARATORS " \t\n\r"
121 BOOL abort_mget
= True
;
125 BOOL readbraw_supported
= False
;
126 BOOL writebraw_supported
= False
;
128 pstring fileselection
= "";
130 extern file_info def_finfo
;
133 int get_total_size
= 0;
134 int get_total_time_ms
= 0;
135 int put_total_size
= 0;
136 int put_total_time_ms
= 0;
144 extern int coding_system
;
145 #define CNV_LANG(s) (coding_system == DOSV_CODE?s:dos_to_unix(s, False))
146 #define CNV_INPUT(s) (coding_system == DOSV_CODE?s:unix_to_dos(s, True))
148 setup_term_code (char *code
)
151 new = interpret_coding_system (code
, UNKNOWN_CODE
);
152 if (new != UNKNOWN_CODE
) {
159 #define CNV_LANG(s) dos2unix_format(s,False)
160 #define CNV_INPUT(s) unix2dos_format(s,True)
163 /****************************************************************************
164 setup basics in a outgoing packet
165 ****************************************************************************/
166 void setup_pkt(char *outbuf
)
168 SSVAL(outbuf
,smb_pid
,pid
);
169 SSVAL(outbuf
,smb_uid
,uid
);
170 SSVAL(outbuf
,smb_mid
,mid
);
171 if (Protocol
> PROTOCOL_COREPLUS
)
173 SCVAL(outbuf
,smb_flg
,0x8);
174 SSVAL(outbuf
,smb_flg2
,0x1);
178 /****************************************************************************
179 write to a local file with CR/LF->LF translation if appropriate. return the
180 number taken from the buffer. This may not equal the number written.
181 ****************************************************************************/
182 static int writefile(int f
, char *b
, int n
)
187 return(write(f
,b
,n
));
192 if (*b
== '\r' && (i
<(n
-1)) && *(b
+1) == '\n')
196 if (write(f
, b
, 1) != 1)
207 /****************************************************************************
208 read from a file with LF->CR/LF translation if appropriate. return the
209 number read. read approx n bytes.
210 ****************************************************************************/
211 static int readfile(char *b
, int size
, int n
, FILE *f
)
216 if (!translation
|| (size
!= 1))
217 return(fread(b
,size
,n
,f
));
222 if ((c
= getc(f
)) == EOF
)
227 if (c
== '\n') /* change all LFs to CR/LF */
240 /****************************************************************************
241 read from a file with print translation. return the number read. read approx n
243 ****************************************************************************/
244 static int printread(FILE *f
,char *b
,int n
)
248 i
= readfile(b
,1, n
-1,f
);
257 /****************************************************************************
258 check for existance of a dir
259 ****************************************************************************/
260 static BOOL
chkpath(char *path
,BOOL report
)
263 pstring inbuf
,outbuf
;
267 trim_string(path2
,NULL
,"\\");
268 if (!*path2
) *path2
= '\\';
270 bzero(outbuf
,smb_size
);
271 set_message(outbuf
,0,4 + strlen(path2
),True
);
272 SCVAL(outbuf
,smb_com
,SMBchkpth
);
273 SSVAL(outbuf
,smb_tid
,cnum
);
280 send_smb(Client
,outbuf
);
281 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
283 if (report
&& CVAL(inbuf
,smb_rcls
) != 0)
284 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf
)));
286 return(CVAL(inbuf
,smb_rcls
) == 0);
290 /****************************************************************************
292 ****************************************************************************/
293 static void send_message(char *inbuf
,char *outbuf
)
300 /* send a SMBsendstrt command */
301 bzero(outbuf
,smb_size
);
302 set_message(outbuf
,0,0,True
);
303 CVAL(outbuf
,smb_com
) = SMBsendstrt
;
304 SSVAL(outbuf
,smb_tid
,cnum
);
309 p
= skip_string(p
,1);
312 p
= skip_string(p
,1);
314 set_message(outbuf
,0,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
316 send_smb(Client
,outbuf
);
319 if (!receive_smb(Client
,inbuf
,SHORT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
321 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf
));
325 grp_id
= SVAL(inbuf
,smb_vwv0
);
327 printf("Connected. Type your message, ending it with a Control-D\n");
329 while (!feof(stdin
) && total_len
< 1600)
331 int maxlen
= MIN(1600 - total_len
,127);
338 for (l
=0;l
<maxlen
&& (c
=fgetc(stdin
))!=EOF
;l
++)
345 CVAL(outbuf
,smb_com
) = SMBsendtxt
;
347 set_message(outbuf
,1,l
+3,True
);
349 SSVAL(outbuf
,smb_vwv0
,grp_id
);
356 send_smb(Client
,outbuf
);
359 if (!receive_smb(Client
,inbuf
,SHORT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
361 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf
));
368 if (total_len
>= 1600)
369 printf("the message was truncated to 1600 bytes ");
371 printf("sent %d bytes ",total_len
);
373 printf("(status was %d-%d)\n",CVAL(inbuf
,smb_rcls
),SVAL(inbuf
,smb_err
));
375 CVAL(outbuf
,smb_com
) = SMBsendend
;
376 set_message(outbuf
,1,0,False
);
377 SSVAL(outbuf
,smb_vwv0
,grp_id
);
379 send_smb(Client
,outbuf
);
382 if (!receive_smb(Client
,inbuf
,SHORT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
384 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf
));
391 /****************************************************************************
392 check the space on a device
393 ****************************************************************************/
394 static void do_dskattr(void)
396 pstring inbuf
,outbuf
;
398 bzero(outbuf
,smb_size
);
399 set_message(outbuf
,0,0,True
);
400 CVAL(outbuf
,smb_com
) = SMBdskattr
;
401 SSVAL(outbuf
,smb_tid
,cnum
);
404 send_smb(Client
,outbuf
);
405 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
407 if (CVAL(inbuf
,smb_rcls
) != 0)
408 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf
)));
410 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
411 SVAL(inbuf
,smb_vwv0
),
412 SVAL(inbuf
,smb_vwv1
)*SVAL(inbuf
,smb_vwv2
),
413 SVAL(inbuf
,smb_vwv3
)));
416 /****************************************************************************
418 ****************************************************************************/
419 static void cmd_pwd(void)
421 DEBUG(0,("Current directory is %s",CNV_LANG(service
)));
422 DEBUG(0,("%s\n",CNV_LANG(cur_dir
)));
426 /****************************************************************************
427 change directory - inner section
428 ****************************************************************************/
429 static void do_cd(char *newdir
)
435 /* Save the current directory in case the
436 new directory is invalid */
437 strcpy(saved_dir
, cur_dir
);
442 if (*(cur_dir
+strlen(cur_dir
)-1) != '\\') {
443 strcat(cur_dir
, "\\");
445 dos_clean_name(cur_dir
);
446 strcpy(dname
,cur_dir
);
447 strcat(cur_dir
,"\\");
448 dos_clean_name(cur_dir
);
450 if (!strequal(cur_dir
,"\\"))
451 if (!chkpath(dname
,True
))
452 strcpy(cur_dir
,saved_dir
);
454 strcpy(cd_path
,cur_dir
);
457 /****************************************************************************
459 ****************************************************************************/
460 static void cmd_cd(char *inbuf
,char *outbuf
)
464 if (next_token(NULL
,buf
,NULL
))
467 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir
)));
471 /****************************************************************************
472 display info about a file
473 ****************************************************************************/
474 static void display_finfo(file_info
*finfo
)
476 time_t t
= finfo
->mtime
; /* the time is assumed to be passed as GMT */
477 DEBUG(0,(" %-30s%7.7s%10d %s",
478 CNV_LANG(finfo
->name
),
479 attrib_string(finfo
->mode
),
481 asctime(LocalTime(&t
))));
485 /****************************************************************************
486 do a directory listing, calling fn on each file found. Use the TRANSACT2
487 call for long filenames
488 ****************************************************************************/
489 static int do_long_dir(char *inbuf
,char *outbuf
,char *Mask
,int attribute
,void (*fn
)(),BOOL recurse_dir
)
491 int max_matches
= 512;
492 int info_level
= Protocol
<PROTOCOL_NT1
?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
497 char *dirlist
= NULL
;
499 int total_received
= 0;
501 char *resp_data
=NULL
;
502 char *resp_param
=NULL
;
503 int resp_data_len
= 0;
504 int resp_param_len
=0;
506 int ff_resume_key
= 0;
507 int ff_searchcount
=0;
521 if (loop_count
> 200)
523 DEBUG(0,("ERROR: Looping in FIND_NEXT??\n"));
529 setup
= TRANSACT2_FINDFIRST
;
530 SSVAL(param
,0,attribute
); /* attribute */
531 SSVAL(param
,2,max_matches
); /* max count */
532 SSVAL(param
,4,8+4+2); /* resume required + close on end + continue */
533 SSVAL(param
,6,info_level
);
535 strcpy(param
+12,mask
);
539 setup
= TRANSACT2_FINDNEXT
;
540 SSVAL(param
,0,ff_dir_handle
);
541 SSVAL(param
,2,max_matches
); /* max count */
542 SSVAL(param
,4,info_level
);
543 SIVAL(param
,6,ff_resume_key
); /* ff_resume_key */
544 SSVAL(param
,10,8+4+2); /* resume required + close on end + continue */
545 strcpy(param
+12,mask
);
547 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
548 ff_dir_handle
,ff_resume_key
,ff_lastname
,mask
));
550 /* ??? original code added 1 pad byte after param */
552 send_trans_request(outbuf
,SMBtrans2
,NULL
,FID_UNUSED
,0,
554 0,12+strlen(mask
)+1,1,
557 if (!receive_trans_response(inbuf
,SMBtrans2
,
558 &resp_data_len
,&resp_param_len
,
559 &resp_data
,&resp_param
))
561 DEBUG(3,("FIND%s gave %s\n",First
?"FIRST":"NEXT",smb_errstr(inbuf
)));
565 /* parse out some important return info */
569 ff_dir_handle
= SVAL(p
,0);
570 ff_searchcount
= SVAL(p
,2);
572 ff_lastname
= SVAL(p
,8);
576 ff_searchcount
= SVAL(p
,0);
578 ff_lastname
= SVAL(p
,6);
581 if (ff_searchcount
== 0)
584 /* point to the data bytes */
587 /* we might need the lastname for continuations */
594 StrnCpy(mask
,p
+ff_lastname
,resp_data_len
-ff_lastname
);
595 /* strcpy(mask,p+ff_lastname+94); */
598 strcpy(mask
,p
+ ff_lastname
+ 1);
606 /* and add them to the dirlist pool */
607 dirlist
= Realloc(dirlist
,dirlist_len
+ resp_data_len
);
611 DEBUG(0,("Failed to expand dirlist\n"));
615 /* put in a length for the last entry, to ensure we can chain entries
616 into the next packet */
619 for (p2
=p
,i
=0;i
<(ff_searchcount
-1);i
++)
620 p2
+= interpret_long_filename(info_level
,p2
,NULL
);
621 SSVAL(p2
,0,resp_data_len
- PTR_DIFF(p2
,p
));
624 /* grab the data for later use */
625 memcpy(dirlist
+dirlist_len
,p
,resp_data_len
);
626 dirlist_len
+= resp_data_len
;
628 total_received
+= ff_searchcount
;
630 if (resp_data
) free(resp_data
); resp_data
= NULL
;
631 if (resp_param
) free(resp_param
); resp_param
= NULL
;
633 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
634 ff_searchcount
,ff_eos
,ff_resume_key
));
640 for (p
=dirlist
,i
=0;i
<total_received
;i
++)
642 p
+= interpret_long_filename(info_level
,p
,&finfo
);
643 display_finfo(&finfo
);
646 for (p
=dirlist
,i
=0;i
<total_received
;i
++)
648 p
+= interpret_long_filename(info_level
,p
,&finfo
);
649 dir_action(inbuf
,outbuf
,attribute
,&finfo
,recurse_dir
,fn
,True
);
652 /* free up the dirlist buffer */
653 if (dirlist
) free(dirlist
);
654 return(total_received
);
658 /****************************************************************************
659 do a directory listing, calling fn on each file found
660 ****************************************************************************/
661 static int do_short_dir(char *inbuf
,char *outbuf
,char *Mask
,int attribute
,void (*fn
)(),BOOL recurse_dir
)
667 int num_asked
= (max_xmit
- 100)/DIR_STRUCT_SIZE
;
668 int num_received
= 0;
670 char *dirlist
= NULL
;
682 bzero(outbuf
,smb_size
);
684 set_message(outbuf
,2,5 + strlen(mask
),True
);
686 set_message(outbuf
,2,5 + 21,True
);
689 if (Protocol
>= PROTOCOL_LANMAN1
)
690 CVAL(outbuf
,smb_com
) = SMBffirst
;
693 CVAL(outbuf
,smb_com
) = SMBsearch
;
695 SSVAL(outbuf
,smb_tid
,cnum
);
698 SSVAL(outbuf
,smb_vwv0
,num_asked
);
699 SSVAL(outbuf
,smb_vwv1
,attribute
);
720 send_smb(Client
,outbuf
);
721 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
723 received
= SVAL(inbuf
,smb_vwv0
);
725 DEBUG(5,("dir received %d\n",received
));
727 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf
)));
729 if (received
<= 0) break;
733 dirlist
= Realloc(dirlist
,(num_received
+ received
)*DIR_STRUCT_SIZE
);
738 p
= smb_buf(inbuf
) + 3;
740 memcpy(dirlist
+num_received
*DIR_STRUCT_SIZE
,
741 p
,received
*DIR_STRUCT_SIZE
);
743 memcpy(status
,p
+ ((received
-1)*DIR_STRUCT_SIZE
),21);
745 num_received
+= received
;
747 if (CVAL(inbuf
,smb_rcls
) != 0) break;
751 if (!first
&& Protocol
>= PROTOCOL_LANMAN1
)
753 bzero(outbuf
,smb_size
);
754 CVAL(outbuf
,smb_com
) = SMBfclose
;
756 SSVAL(outbuf
,smb_tid
,cnum
);
770 send_smb(Client
,outbuf
);
771 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
773 if (CVAL(inbuf
,smb_rcls
) != 0)
774 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf
)));
779 for (p
=dirlist
,i
=0;i
<num_received
;i
++)
781 p
+= interpret_short_filename(p
,&finfo
);
782 display_finfo(&finfo
);
785 for (p
=dirlist
,i
=0;i
<num_received
;i
++)
787 p
+= interpret_short_filename(p
,&finfo
);
788 dir_action(inbuf
,outbuf
,attribute
,&finfo
,recurse_dir
,fn
,False
);
791 if (dirlist
) free(dirlist
);
792 return(num_received
);
797 /****************************************************************************
798 do a directory listing, calling fn on each file found
799 ****************************************************************************/
800 void do_dir(char *inbuf
,char *outbuf
,char *Mask
,int attribute
,void (*fn
)(),BOOL recurse_dir
)
802 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask
,attribute
,BOOLSTR(recurse_dir
)));
803 if (Protocol
>= PROTOCOL_LANMAN2
)
805 if (do_long_dir(inbuf
,outbuf
,Mask
,attribute
,fn
,recurse_dir
) > 0)
809 expand_mask(Mask
,False
);
810 do_short_dir(inbuf
,outbuf
,Mask
,attribute
,fn
,recurse_dir
);
814 /*******************************************************************
815 decide if a file should be operated on
816 ********************************************************************/
817 static BOOL
do_this_one(file_info
*finfo
)
819 if (finfo
->mode
& aDIR
) return(True
);
821 if (newer_than
&& finfo
->mtime
< newer_than
)
824 if ((archive_level
==1 || archive_level
==2) && !(finfo
->mode
& aARCH
))
831 /*****************************************************************************
832 Convert a character pointer in a call_api() response to a form we can use.
833 This function contains code to prevent core dumps if the server returns
835 *****************************************************************************/
836 static char *fix_char_ptr(unsigned int datap
, unsigned int converter
, char *rdata
, int rdrcnt
)
838 if( datap
== 0 ) /* turn NULL pointers */
839 { /* into zero length strings */
844 unsigned int offset
= datap
- converter
;
846 if( offset
< 0 || offset
>= rdrcnt
)
848 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%u, rdrcnt=%d>", datap
, converter
, (unsigned)rdata
, rdrcnt
));
853 return &rdata
[offset
];
858 /****************************************************************************
859 interpret a short filename structure
860 The length of the structure is returned
861 ****************************************************************************/
862 static int interpret_short_filename(char *p
,file_info
*finfo
)
864 finfo
->mode
= CVAL(p
,21);
866 /* this date is converted to GMT by make_unix_date */
867 finfo
->ctime
= make_unix_date(p
+22);
868 finfo
->mtime
= finfo
->atime
= finfo
->ctime
;
869 finfo
->size
= IVAL(p
,26);
870 strcpy(finfo
->name
,p
+30);
872 return(DIR_STRUCT_SIZE
);
875 /****************************************************************************
876 interpret a long filename structure - this is mostly guesses at the moment
877 The length of the structure is returned
878 The structure of a long filename depends on the info level. 260 is used
879 by NT and 2 is used by OS/2
880 ****************************************************************************/
881 static int interpret_long_filename(int level
,char *p
,file_info
*finfo
)
884 memcpy(finfo
,&def_finfo
,sizeof(*finfo
));
888 case 1: /* OS/2 understands this */
891 /* these dates are converted to GMT by make_unix_date */
892 finfo
->ctime
= make_unix_date2(p
+4);
893 finfo
->atime
= make_unix_date2(p
+8);
894 finfo
->mtime
= make_unix_date2(p
+12);
895 finfo
->size
= IVAL(p
,16);
896 finfo
->mode
= CVAL(p
,24);
897 strcpy(finfo
->name
,p
+27);
899 return(28 + CVAL(p
,26));
901 case 2: /* this is what OS/2 uses mostly */
904 /* these dates are converted to GMT by make_unix_date */
905 finfo
->ctime
= make_unix_date2(p
+4);
906 finfo
->atime
= make_unix_date2(p
+8);
907 finfo
->mtime
= make_unix_date2(p
+12);
908 finfo
->size
= IVAL(p
,16);
909 finfo
->mode
= CVAL(p
,24);
910 strcpy(finfo
->name
,p
+31);
912 return(32 + CVAL(p
,30));
914 /* levels 3 and 4 are untested */
918 /* these dates are probably like the other ones */
919 finfo
->ctime
= make_unix_date2(p
+8);
920 finfo
->atime
= make_unix_date2(p
+12);
921 finfo
->mtime
= make_unix_date2(p
+16);
922 finfo
->size
= IVAL(p
,20);
923 finfo
->mode
= CVAL(p
,28);
924 strcpy(finfo
->name
,p
+33);
931 /* these dates are probably like the other ones */
932 finfo
->ctime
= make_unix_date2(p
+8);
933 finfo
->atime
= make_unix_date2(p
+12);
934 finfo
->mtime
= make_unix_date2(p
+16);
935 finfo
->size
= IVAL(p
,20);
936 finfo
->mode
= CVAL(p
,28);
937 strcpy(finfo
->name
,p
+37);
941 case 260: /* NT uses this, but also accepts 2 */
946 p
+= 4; /* next entry offset */
947 p
+= 4; /* fileindex */
949 /* these dates appear to arrive in a weird way. It seems to
950 be localtime plus the serverzone given in the initial
951 connect. This is GMT when DST is not in effect and one
952 hour from GMT otherwise. Can this really be right??
954 I suppose this could be called kludge-GMT. Is is the GMT
955 you get by using the current DST setting on a different
956 localtime. It will be cheap to calculate, I suppose, as
957 no DST tables will be needed */
959 finfo
->ctime
= interpret_long_date(p
); p
+= 8;
960 finfo
->atime
= interpret_long_date(p
); p
+= 8;
961 finfo
->mtime
= interpret_long_date(p
); p
+= 8; p
+= 8;
962 finfo
->size
= IVAL(p
,0); p
+= 8;
963 p
+= 8; /* alloc size */
964 finfo
->mode
= CVAL(p
,0); p
+= 4;
965 namelen
= IVAL(p
,0); p
+= 4;
966 p
+= 4; /* EA size */
967 p
+= 2; /* short name len? */
968 p
+= 24; /* short name? */
969 StrnCpy(finfo
->name
,p
,namelen
);
975 DEBUG(1,("Unknown long filename format %d\n",level
));
982 /****************************************************************************
983 act on the files in a dir listing
984 ****************************************************************************/
985 static void dir_action(char *inbuf
,char *outbuf
,int attribute
,file_info
*finfo
,BOOL recurse_dir
,void (*fn
)(),BOOL longdir
)
988 if (!((finfo
->mode
& aDIR
) == 0 && *fileselection
&&
989 !mask_match(finfo
->name
,fileselection
,False
,False
)) &&
990 !(recurse_dir
&& (strequal(finfo
->name
,".") ||
991 strequal(finfo
->name
,".."))))
993 if (recurse_dir
&& (finfo
->mode
& aDIR
))
997 strcpy(sav_dir
,cur_dir
);
998 strcat(cur_dir
,finfo
->name
);
999 strcat(cur_dir
,"\\");
1000 strcpy(mask2
,cur_dir
);
1003 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir
)));
1008 do_long_dir(inbuf
,outbuf
,mask2
,attribute
,fn
,True
);
1010 do_dir(inbuf
,outbuf
,mask2
,attribute
,fn
,True
);
1012 strcpy(cur_dir
,sav_dir
);
1016 if (fn
&& do_this_one(finfo
))
1023 /****************************************************************************
1024 receive a SMB trans or trans2 response allocating the necessary memory
1025 ****************************************************************************/
1026 static BOOL
receive_trans_response(char *inbuf
,int trans
,
1027 int *data_len
,int *param_len
,
1028 char **data
,char **param
)
1032 int this_data
,this_param
;
1034 *data_len
= *param_len
= 0;
1036 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1040 if (CVAL(inbuf
,smb_com
) != trans
)
1042 DEBUG(0,("Expected %s response, got command 0x%02x\n",
1043 trans
==SMBtrans
?"SMBtrans":"SMBtrans2", CVAL(inbuf
,smb_com
)));
1046 if (CVAL(inbuf
,smb_rcls
) != 0)
1049 /* parse out the lengths */
1050 total_data
= SVAL(inbuf
,smb_tdrcnt
);
1051 total_param
= SVAL(inbuf
,smb_tprcnt
);
1054 *data
= Realloc(*data
,total_data
);
1055 *param
= Realloc(*param
,total_param
);
1059 this_data
= SVAL(inbuf
,smb_drcnt
);
1060 this_param
= SVAL(inbuf
,smb_prcnt
);
1062 memcpy(*data
+ SVAL(inbuf
,smb_drdisp
),
1063 smb_base(inbuf
) + SVAL(inbuf
,smb_droff
),
1066 memcpy(*param
+ SVAL(inbuf
,smb_prdisp
),
1067 smb_base(inbuf
) + SVAL(inbuf
,smb_proff
),
1069 *data_len
+= this_data
;
1070 *param_len
+= this_param
;
1072 /* parse out the total lengths again - they can shrink! */
1073 total_data
= SVAL(inbuf
,smb_tdrcnt
);
1074 total_param
= SVAL(inbuf
,smb_tprcnt
);
1076 if (total_data
<= *data_len
&& total_param
<= *param_len
)
1079 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1083 if (CVAL(inbuf
,smb_com
) != trans
)
1085 DEBUG(0,("Expected %s response, got command 0x%02x\n",
1086 trans
==SMBtrans
?"SMBtrans":"SMBtrans2", CVAL(inbuf
,smb_com
)));
1089 if (CVAL(inbuf
,smb_rcls
) != 0)
1097 /****************************************************************************
1098 get a directory listing
1099 ****************************************************************************/
1100 static void cmd_dir(char *inbuf
,char *outbuf
)
1102 int attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
1107 strcpy(mask
,cur_dir
);
1108 if(mask
[strlen(mask
)-1]!='\\')
1111 if (next_token(NULL
,buf
,NULL
))
1122 do_dir(inbuf
,outbuf
,mask
,attribute
,NULL
,recurse
);
1129 /****************************************************************************
1130 get a file from rname to lname
1131 ****************************************************************************/
1132 static void do_get(char *rname
,char *lname
,file_info
*finfo1
)
1137 BOOL newhandle
= False
;
1138 char *inbuf
,*outbuf
;
1140 BOOL close_done
= False
;
1141 BOOL ignore_close_error
= False
;
1145 struct timeval tp_start
;
1146 GetTimeOfDay(&tp_start
);
1157 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1158 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1160 if (!inbuf
|| !outbuf
)
1162 DEBUG(0,("out of memory\n"));
1166 bzero(outbuf
,smb_size
);
1167 set_message(outbuf
,15,1 + strlen(rname
),True
);
1169 CVAL(outbuf
,smb_com
) = SMBopenX
;
1170 SSVAL(outbuf
,smb_tid
,cnum
);
1173 SSVAL(outbuf
,smb_vwv0
,0xFF);
1174 SSVAL(outbuf
,smb_vwv2
,1);
1175 SSVAL(outbuf
,smb_vwv3
,(DENY_NONE
<<4));
1176 SSVAL(outbuf
,smb_vwv4
,aSYSTEM
| aHIDDEN
);
1177 SSVAL(outbuf
,smb_vwv5
,aSYSTEM
| aHIDDEN
);
1178 SSVAL(outbuf
,smb_vwv8
,1);
1180 p
= smb_buf(outbuf
);
1182 p
= skip_string(p
,1);
1184 /* do a chained openX with a readX? */
1188 DEBUG(3,("Chaining readX wth openX\n"));
1189 SSVAL(outbuf
,smb_vwv0
,SMBreadX
);
1190 SSVAL(outbuf
,smb_vwv1
,smb_offset(p
,outbuf
));
1193 SSVAL(p
,smb_wct
,10);
1194 SSVAL(p
,smb_vwv0
,0xFF);
1195 SSVAL(p
,smb_vwv5
,MIN(max_xmit
-500,finfo
.size
));
1196 SSVAL(p
,smb_vwv9
,MIN(BUFFER_SIZE
,finfo
.size
));
1197 smb_setlen(outbuf
,smb_len(outbuf
)+11*2+1);
1201 if(!strcmp(lname
,"-"))
1202 handle
= fileno(stdout
);
1205 handle
= creat(lname
,0644);
1210 DEBUG(0,("Error opening local file %s\n",lname
));
1211 free(inbuf
);free(outbuf
);
1215 send_smb(Client
,outbuf
);
1216 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1218 if (CVAL(inbuf
,smb_rcls
) != 0)
1220 if (CVAL(inbuf
,smb_rcls
) == ERRSRV
&&
1221 SVAL(inbuf
,smb_err
) == ERRnoresource
&&
1222 reopen_connection(inbuf
,outbuf
))
1224 do_get(rname
,lname
,finfo1
);
1227 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
1230 free(inbuf
);free(outbuf
);
1234 strcpy(finfo
.name
,rname
);
1238 finfo
.mode
= SVAL(inbuf
,smb_vwv3
);
1239 /* these times arrive as LOCAL time, using the DST offset
1240 corresponding to that time, we convert them to GMT */
1241 finfo
.mtime
= make_unix_date3(inbuf
+smb_vwv4
);
1242 finfo
.atime
= finfo
.ctime
= finfo
.mtime
;
1243 finfo
.size
= IVAL(inbuf
,smb_vwv6
);
1246 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo
.name
),finfo
.mode
));
1248 fnum
= SVAL(inbuf
,smb_vwv2
);
1250 /* we might have got some data from a chained readX */
1251 if (SVAL(inbuf
,smb_vwv0
) == SMBreadX
)
1253 p
= (smb_base(inbuf
)+SVAL(inbuf
,smb_vwv1
)) - smb_wct
;
1254 datalen
= SVAL(p
,smb_vwv5
);
1255 dataptr
= smb_base(inbuf
) + SVAL(p
,smb_vwv6
);
1264 DEBUG(2,("getting file %s of size %d bytes as %s ",
1265 CNV_LANG(finfo
.name
),
1269 while (nread
< finfo
.size
&& !close_done
)
1272 static BOOL can_chain_close
= True
;
1276 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread
,max_xmit
,finfo
.size
));
1278 /* 3 possible read types. readbraw if a large block is required.
1279 readX + close if not much left and read if neither is supported */
1281 /* we might have already read some data from a chained readX */
1282 if (dataptr
&& datalen
>0)
1285 /* if we can finish now then readX+close */
1286 if (method
<0 && can_chain_close
&& (Protocol
>= PROTOCOL_LANMAN1
) &&
1287 ((finfo
.size
- nread
) <
1288 (max_xmit
- (2*smb_size
+ 13*SIZEOFWORD
+ 300))))
1291 /* if we support readraw then use that */
1292 if (method
<0 && readbraw_supported
)
1295 /* if we can then use readX */
1296 if (method
<0 && (Protocol
>= PROTOCOL_LANMAN1
))
1307 /* use readX + close */
1308 bzero(outbuf
,smb_size
);
1309 set_message(outbuf
,10,0,True
);
1310 CVAL(outbuf
,smb_com
) = SMBreadX
;
1311 SSVAL(outbuf
,smb_tid
,cnum
);
1316 CVAL(outbuf
,smb_vwv0
) = SMBclose
;
1317 SSVAL(outbuf
,smb_vwv1
,smb_offset(smb_buf(outbuf
),outbuf
));
1320 CVAL(outbuf
,smb_vwv0
) = 0xFF;
1322 SSVAL(outbuf
,smb_vwv2
,fnum
);
1323 SIVAL(outbuf
,smb_vwv3
,nread
);
1324 SSVAL(outbuf
,smb_vwv5
,MIN(max_xmit
-200,finfo
.size
- nread
));
1325 SSVAL(outbuf
,smb_vwv6
,0);
1326 SIVAL(outbuf
,smb_vwv7
,0);
1327 SSVAL(outbuf
,smb_vwv9
,MIN(BUFFER_SIZE
,finfo
.size
-nread
));
1331 p
= smb_buf(outbuf
);
1338 /* now set the total packet length */
1339 smb_setlen(outbuf
,smb_len(outbuf
)+9);
1342 send_smb(Client
,outbuf
);
1343 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1345 if (CVAL(inbuf
,smb_rcls
) != 0)
1347 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf
)));
1352 SVAL(inbuf
,smb_vwv0
) != SMBclose
)
1354 /* NOTE: WfWg sometimes just ignores the chained
1355 command! This seems to break the spec? */
1356 DEBUG(3,("Rejected chained close?\n"));
1358 can_chain_close
= False
;
1359 ignore_close_error
= True
;
1362 datalen
= SVAL(inbuf
,smb_vwv5
);
1363 dataptr
= smb_base(inbuf
) + SVAL(inbuf
,smb_vwv6
);
1369 static int readbraw_size
= BUFFER_SIZE
;
1372 bzero(outbuf
,smb_size
);
1373 set_message(outbuf
,8,0,True
);
1374 CVAL(outbuf
,smb_com
) = SMBreadbraw
;
1375 SSVAL(outbuf
,smb_tid
,cnum
);
1377 SSVAL(outbuf
,smb_vwv0
,fnum
);
1378 SIVAL(outbuf
,smb_vwv1
,nread
);
1379 SSVAL(outbuf
,smb_vwv3
,MIN(finfo
.size
-nread
,readbraw_size
));
1380 SSVAL(outbuf
,smb_vwv4
,0);
1381 SIVALS(outbuf
,smb_vwv5
,-1);
1382 send_smb(Client
,outbuf
);
1384 /* Now read the raw data into the buffer and write it */
1385 if(read_smb_length(Client
,inbuf
,0) == -1) {
1386 DEBUG(0,("Failed to read length in readbraw\n"));
1390 /* Even though this is not an smb message, smb_len
1391 returns the generic length of an smb message */
1392 datalen
= smb_len(inbuf
);
1396 /* we got a readbraw error */
1397 DEBUG(4,("readbraw error - reducing size\n"));
1398 readbraw_size
= (readbraw_size
* 9) / 10;
1400 if (readbraw_size
< max_xmit
)
1402 DEBUG(0,("disabling readbraw\n"));
1403 readbraw_supported
= False
;
1410 if(read_data(Client
,inbuf
,datalen
) != datalen
) {
1411 DEBUG(0,("Failed to read data in readbraw\n"));
1419 /* we've already read some data with a chained readX */
1423 /* use plain read */
1424 bzero(outbuf
,smb_size
);
1425 set_message(outbuf
,5,0,True
);
1426 CVAL(outbuf
,smb_com
) = SMBread
;
1427 SSVAL(outbuf
,smb_tid
,cnum
);
1430 SSVAL(outbuf
,smb_vwv0
,fnum
);
1431 SSVAL(outbuf
,smb_vwv1
,MIN(max_xmit
-200,finfo
.size
- nread
));
1432 SIVAL(outbuf
,smb_vwv2
,nread
);
1433 SSVAL(outbuf
,smb_vwv4
,finfo
.size
- nread
);
1435 send_smb(Client
,outbuf
);
1436 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1438 if (CVAL(inbuf
,smb_rcls
) != 0)
1440 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf
)));
1444 datalen
= SVAL(inbuf
,smb_vwv0
);
1445 dataptr
= smb_buf(inbuf
) + 3;
1449 if (writefile(handle
,dataptr
,datalen
) != datalen
)
1451 DEBUG(0,("Error writing local file\n"));
1458 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname
),nread
));
1470 bzero(outbuf
,smb_size
);
1471 set_message(outbuf
,3,0,True
);
1472 CVAL(outbuf
,smb_com
) = SMBclose
;
1473 SSVAL(outbuf
,smb_tid
,cnum
);
1476 SSVAL(outbuf
,smb_vwv0
,fnum
);
1477 SIVALS(outbuf
,smb_vwv1
,-1);
1479 send_smb(Client
,outbuf
);
1480 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1482 if (!ignore_close_error
&& CVAL(inbuf
,smb_rcls
) != 0)
1484 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf
)));
1487 free(inbuf
);free(outbuf
);
1495 if (archive_level
>= 2 && (finfo
.mode
& aARCH
)) {
1496 bzero(outbuf
,smb_size
);
1497 set_message(outbuf
,8,strlen(rname
)+4,True
);
1498 CVAL(outbuf
,smb_com
) = SMBsetatr
;
1499 SSVAL(outbuf
,smb_tid
,cnum
);
1501 SSVAL(outbuf
,smb_vwv0
,finfo
.mode
& ~(aARCH
));
1502 SIVALS(outbuf
,smb_vwv1
,0);
1503 p
= smb_buf(outbuf
);
1509 send_smb(Client
,outbuf
);
1510 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1514 struct timeval tp_end
;
1517 GetTimeOfDay(&tp_end
);
1519 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
1520 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
1521 get_total_time_ms
+= this_time
;
1522 get_total_size
+= finfo
.size
;
1524 DEBUG(2,("(%g kb/s) (average %g kb/s)\n",
1525 finfo
.size
/ (1.024*this_time
+ 1.0e-4),
1526 get_total_size
/ (1.024*get_total_time_ms
)));
1529 free(inbuf
);free(outbuf
);
1533 /****************************************************************************
1535 ****************************************************************************/
1536 static void cmd_get(void)
1542 strcpy(rname
,cur_dir
);
1545 p
= rname
+ strlen(rname
);
1547 if (!next_token(NULL
,p
,NULL
)) {
1548 DEBUG(0,("get <filename>\n"));
1552 dos_clean_name(rname
);
1554 next_token(NULL
,lname
,NULL
);
1556 do_get(rname
,lname
,NULL
);
1560 /****************************************************************************
1561 do a mget operation on one file
1562 ****************************************************************************/
1563 static void do_mget(file_info
*finfo
)
1568 if (strequal(finfo
->name
,".") || strequal(finfo
->name
,".."))
1573 DEBUG(0,("mget aborted\n"));
1577 if (finfo
->mode
& aDIR
)
1578 sprintf(quest
,"Get directory %s? ",CNV_LANG(finfo
->name
));
1580 sprintf(quest
,"Get file %s? ",CNV_LANG(finfo
->name
));
1582 if (prompt
&& !yesno(quest
)) return;
1584 if (finfo
->mode
& aDIR
)
1586 pstring saved_curdir
;
1588 char *inbuf
,*outbuf
;
1590 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1591 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1593 if (!inbuf
|| !outbuf
)
1595 DEBUG(0,("out of memory\n"));
1599 strcpy(saved_curdir
,cur_dir
);
1601 strcat(cur_dir
,finfo
->name
);
1602 strcat(cur_dir
,"\\");
1604 unix_format(finfo
->name
);
1607 strlower(finfo
->name
);
1609 if (!directory_exist(finfo
->name
,NULL
) &&
1610 sys_mkdir(finfo
->name
,0777) != 0)
1612 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo
->name
)));
1613 strcpy(cur_dir
,saved_curdir
);
1614 free(inbuf
);free(outbuf
);
1618 if (sys_chdir(finfo
->name
) != 0)
1620 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo
->name
)));
1621 strcpy(cur_dir
,saved_curdir
);
1622 free(inbuf
);free(outbuf
);
1627 strcpy(mget_mask
,cur_dir
);
1628 strcat(mget_mask
,"*");
1630 do_dir((char *)inbuf
,(char *)outbuf
,
1631 mget_mask
,aSYSTEM
| aHIDDEN
| aDIR
,do_mget
,False
);
1633 strcpy(cur_dir
,saved_curdir
);
1634 free(inbuf
);free(outbuf
);
1638 strcpy(rname
,cur_dir
);
1639 strcat(rname
,finfo
->name
);
1640 do_get(rname
,finfo
->name
,finfo
);
1644 /****************************************************************************
1645 view the file using the pager
1646 ****************************************************************************/
1647 static void cmd_more(void)
1649 fstring rname
,lname
,tmpname
,pager_cmd
;
1652 strcpy(rname
,cur_dir
);
1654 sprintf(tmpname
,"/tmp/smbmore.%d",getpid());
1655 strcpy(lname
,tmpname
);
1657 if (!next_token(NULL
,rname
+strlen(rname
),NULL
)) {
1658 DEBUG(0,("more <filename>\n"));
1661 dos_clean_name(rname
);
1663 do_get(rname
,lname
,NULL
);
1665 pager
=getenv("PAGER");
1666 sprintf(pager_cmd
,"%s %s",(pager
? pager
:PAGER
), tmpname
);
1673 /****************************************************************************
1675 ****************************************************************************/
1676 static void cmd_mget(char *inbuf
,char *outbuf
)
1678 int attribute
= aSYSTEM
| aHIDDEN
;
1690 while (next_token(NULL
,p
,NULL
))
1692 strcpy(mget_mask
,cur_dir
);
1693 if(mget_mask
[strlen(mget_mask
)-1]!='\\')
1694 strcat(mget_mask
,"\\");
1697 strcpy(mget_mask
,p
);
1699 strcat(mget_mask
,p
);
1700 do_dir((char *)inbuf
,(char *)outbuf
,mget_mask
,attribute
,do_mget
,False
);
1705 strcpy(mget_mask
,cur_dir
);
1706 if(mget_mask
[strlen(mget_mask
)-1]!='\\')
1707 strcat(mget_mask
,"\\");
1708 strcat(mget_mask
,"*");
1709 do_dir((char *)inbuf
,(char *)outbuf
,mget_mask
,attribute
,do_mget
,False
);
1713 /****************************************************************************
1714 make a directory of name "name"
1715 ****************************************************************************/
1716 static BOOL
do_mkdir(char *name
)
1719 char *inbuf
,*outbuf
;
1721 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1722 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1724 if (!inbuf
|| !outbuf
)
1726 DEBUG(0,("out of memory\n"));
1730 bzero(outbuf
,smb_size
);
1731 set_message(outbuf
,0,2 + strlen(name
),True
);
1733 CVAL(outbuf
,smb_com
) = SMBmkdir
;
1734 SSVAL(outbuf
,smb_tid
,cnum
);
1738 p
= smb_buf(outbuf
);
1742 send_smb(Client
,outbuf
);
1743 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1745 if (CVAL(inbuf
,smb_rcls
) != 0)
1747 DEBUG(0,("%s making remote directory %s\n",
1748 smb_errstr(inbuf
),CNV_LANG(name
)));
1750 free(inbuf
);free(outbuf
);
1754 free(inbuf
);free(outbuf
);
1759 /****************************************************************************
1761 ****************************************************************************/
1762 static void cmd_mkdir(char *inbuf
,char *outbuf
)
1768 strcpy(mask
,cur_dir
);
1770 if (!next_token(NULL
,p
,NULL
))
1773 DEBUG(0,("mkdir <dirname>\n"));
1785 trim_string(ddir
,".",NULL
);
1786 p
= strtok(ddir
,"/\\");
1790 if (!chkpath(ddir2
,False
))
1795 p
= strtok(NULL
,"/\\");
1803 /*******************************************************************
1804 write to a file using writebraw
1805 ********************************************************************/
1806 static int smb_writeraw(char *outbuf
,int fnum
,int pos
,char *buf
,int n
)
1811 bzero(outbuf
,smb_size
);
1812 bzero(inbuf
,smb_size
);
1813 set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?12:10,0,True
);
1815 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
1816 SSVAL(outbuf
,smb_tid
,cnum
);
1819 SSVAL(outbuf
,smb_vwv0
,fnum
);
1820 SSVAL(outbuf
,smb_vwv1
,n
);
1821 SIVAL(outbuf
,smb_vwv3
,pos
);
1822 SSVAL(outbuf
,smb_vwv7
,1);
1824 send_smb(Client
,outbuf
);
1826 if (!receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
1829 _smb_setlen(buf
-4,n
); /* HACK! XXXX */
1831 if (write_socket(Client
,buf
-4,n
+4) != n
+4)
1834 if (!receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0) {
1835 DEBUG(0,("Error writing remote file (2)\n"));
1838 return(SVAL(inbuf
,smb_vwv0
));
1843 /*******************************************************************
1845 ********************************************************************/
1846 static int smb_writefile(char *outbuf
,int fnum
,int pos
,char *buf
,int n
)
1850 if (writebraw_supported
&& n
> (max_xmit
-200))
1851 return(smb_writeraw(outbuf
,fnum
,pos
,buf
,n
));
1853 bzero(outbuf
,smb_size
);
1854 bzero(inbuf
,smb_size
);
1855 set_message(outbuf
,5,n
+ 3,True
);
1857 CVAL(outbuf
,smb_com
) = SMBwrite
;
1858 SSVAL(outbuf
,smb_tid
,cnum
);
1861 SSVAL(outbuf
,smb_vwv0
,fnum
);
1862 SSVAL(outbuf
,smb_vwv1
,n
);
1863 SIVAL(outbuf
,smb_vwv2
,pos
);
1864 SSVAL(outbuf
,smb_vwv4
,0);
1865 CVAL(smb_buf(outbuf
),0) = 1;
1866 SSVAL(smb_buf(outbuf
),1,n
);
1868 memcpy(smb_buf(outbuf
)+3,buf
,n
);
1870 send_smb(Client
,outbuf
);
1871 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1873 if (CVAL(inbuf
,smb_rcls
) != 0) {
1874 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf
)));
1877 return(SVAL(inbuf
,smb_vwv0
));
1882 /****************************************************************************
1884 ****************************************************************************/
1885 static void do_put(char *rname
,char *lname
,file_info
*finfo
)
1891 char *inbuf
,*outbuf
;
1892 time_t close_time
= finfo
->mtime
;
1894 static int maxwrite
=0;
1896 struct timeval tp_start
;
1897 GetTimeOfDay(&tp_start
);
1899 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1900 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1902 if (!inbuf
|| !outbuf
)
1904 DEBUG(0,("out of memory\n"));
1908 bzero(outbuf
,smb_size
);
1909 set_message(outbuf
,3,2 + strlen(rname
),True
);
1911 if (finfo
->mtime
== 0 || finfo
->mtime
== -1)
1912 finfo
->mtime
= finfo
->atime
= finfo
->ctime
= time(NULL
);
1914 CVAL(outbuf
,smb_com
) = SMBcreate
;
1915 SSVAL(outbuf
,smb_tid
,cnum
);
1918 SSVAL(outbuf
,smb_vwv0
,finfo
->mode
);
1919 put_dos_date3(outbuf
,smb_vwv1
,finfo
->mtime
);
1921 p
= smb_buf(outbuf
);
1925 send_smb(Client
,outbuf
);
1926 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1928 if (CVAL(inbuf
,smb_rcls
) != 0)
1930 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
1932 free(inbuf
);free(outbuf
);if (buf
) free(buf
);
1936 f
= fopen(lname
,"r");
1940 DEBUG(0,("Error opening local file %s\n",lname
));
1941 free(inbuf
);free(outbuf
);
1946 fnum
= SVAL(inbuf
,smb_vwv0
);
1947 if (finfo
->size
< 0)
1948 finfo
->size
= file_size(lname
);
1950 DEBUG(1,("putting file %s of size %d bytes as %s ",lname
,finfo
->size
,CNV_LANG(rname
)));
1953 maxwrite
= writebraw_supported
?MAX(max_xmit
,BUFFER_SIZE
):(max_xmit
-200);
1955 while (nread
< finfo
->size
)
1960 n
= MIN(n
,finfo
->size
- nread
);
1962 buf
= (char *)Realloc(buf
,n
+4);
1964 fseek(f
,nread
,SEEK_SET
);
1965 if ((n
= readfile(buf
+4,1,n
,f
)) < 1)
1967 DEBUG(0,("Error reading local file\n"));
1971 ret
= smb_writefile(outbuf
,fnum
,nread
,buf
+4,n
);
1975 DEBUG(0,("Error writing file\n"));
1988 bzero(outbuf
,smb_size
);
1989 set_message(outbuf
,3,0,True
);
1990 CVAL(outbuf
,smb_com
) = SMBclose
;
1991 SSVAL(outbuf
,smb_tid
,cnum
);
1994 SSVAL(outbuf
,smb_vwv0
,fnum
);
1995 put_dos_date3(outbuf
,smb_vwv1
,close_time
);
1997 send_smb(Client
,outbuf
);
1998 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2000 if (CVAL(inbuf
,smb_rcls
) != 0)
2002 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
2004 free(inbuf
);free(outbuf
);
2011 free(inbuf
);free(outbuf
);
2015 struct timeval tp_end
;
2018 GetTimeOfDay(&tp_end
);
2020 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
2021 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
2022 put_total_time_ms
+= this_time
;
2023 put_total_size
+= finfo
->size
;
2025 DEBUG(2,("(%g kb/s) (average %g kb/s)\n",
2026 finfo
->size
/ (1.024*this_time
+ 1.0e-4),
2027 put_total_size
/ (1.024*put_total_time_ms
)));
2033 /****************************************************************************
2035 ****************************************************************************/
2036 static void cmd_put(void)
2045 strcpy(rname
,cur_dir
);
2049 if (!next_token(NULL
,p
,NULL
))
2051 DEBUG(0,("put <filename>\n"));
2056 if (next_token(NULL
,p
,NULL
))
2059 strcat(rname
,lname
);
2061 dos_clean_name(rname
);
2065 if (!file_exist(lname
,&st
)) {
2066 DEBUG(0,("%s does not exist\n",lname
));
2069 finfo
.mtime
= st
.st_mtime
;
2072 do_put(rname
,lname
,&finfo
);
2075 /****************************************************************************
2076 seek in a directory/file list until you get something that doesn't start with
2078 ****************************************************************************/
2079 static BOOL
seek_list(FILE *f
,char *name
)
2084 if (fscanf(f
,"%s",s
) != 1) return(False
);
2085 trim_string(s
,"./",NULL
);
2086 if (strncmp(s
,name
,strlen(name
)) != 0)
2097 /****************************************************************************
2098 set the file selection mask
2099 ****************************************************************************/
2100 static void cmd_select(void)
2102 strcpy(fileselection
,"");
2103 next_token(NULL
,fileselection
,NULL
);
2107 /****************************************************************************
2109 ****************************************************************************/
2110 static void cmd_mput(void)
2121 while (next_token(NULL
,p
,NULL
))
2128 sprintf(tmpname
,"/tmp/ls.smb.%d",(int)getpid());
2130 sprintf(cmd
,"find . -name \"%s\" -print > %s",p
,tmpname
);
2132 sprintf(cmd
,"/bin/ls %s > %s",p
,tmpname
);
2135 f
= fopen(tmpname
,"r");
2142 if (fscanf(f
,"%s",lname
) != 1) break;
2143 trim_string(lname
,"./",NULL
);
2147 /* check if it's a directory */
2148 if (directory_exist(lname
,&st
))
2150 if (!recurse
) continue;
2151 sprintf(quest
,"Put directory %s? ",lname
);
2152 if (prompt
&& !yesno(quest
))
2155 if (!seek_list(f
,lname
))
2160 strcpy(rname
,cur_dir
);
2161 strcat(rname
,lname
);
2162 if (!chkpath(rname
,False
) && !do_mkdir(rname
)) {
2164 if (!seek_list(f
,lname
))
2173 sprintf(quest
,"Put file %s? ",lname
);
2174 if (prompt
&& !yesno(quest
)) continue;
2176 strcpy(rname
,cur_dir
);
2177 strcat(rname
,lname
);
2181 /* null size so do_put knows to ignore it */
2184 /* set the date on the file */
2185 finfo
.mtime
= st
.st_mtime
;
2187 do_put(rname
,lname
,&finfo
);
2194 /****************************************************************************
2196 ****************************************************************************/
2197 static void do_cancel(int job
)
2199 char *rparam
= NULL
;
2205 bzero(param
,sizeof(param
));
2208 SSVAL(p
,0,81); /* DosPrintJobDel() */
2211 p
= skip_string(p
,1);
2213 p
= skip_string(p
,1);
2217 if (call_api(PTR_DIFF(p
,param
),0,
2223 int res
= SVAL(rparam
,0);
2226 printf("Job %d cancelled\n",job
);
2228 printf("Error %d calcelling job %d\n",res
,job
);
2232 printf("Server refused cancel request\n");
2234 if (rparam
) free(rparam
);
2235 if (rdata
) free(rdata
);
2241 /****************************************************************************
2243 ****************************************************************************/
2244 static void cmd_cancel(char *inbuf
,char *outbuf
)
2249 if (!connect_as_printer
)
2251 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2252 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2255 if (!next_token(NULL
,buf
,NULL
)) {
2256 printf("cancel <jobid> ...\n");
2262 } while (next_token(NULL
,buf
,NULL
));
2266 /****************************************************************************
2268 ****************************************************************************/
2269 static void cmd_stat(char *inbuf
,char *outbuf
)
2273 char *resp_data
=NULL
;
2274 char *resp_param
=NULL
;
2275 int resp_data_len
= 0;
2276 int resp_param_len
=0;
2278 uint16 setup
= TRANSACT2_QPATHINFO
;
2280 if (!next_token(NULL
,buf
,NULL
)) {
2281 printf("stat <file>\n");
2286 SSVAL(param
,0,4); /* level */
2291 send_trans_request(outbuf
,SMBtrans2
,NULL
,FID_UNUSED
,0,
2293 0,6 + strlen(p
)+1,1,
2296 receive_trans_response(inbuf
,SMBtrans2
,
2297 &resp_data_len
,&resp_param_len
,
2298 &resp_data
,&resp_param
);
2300 if (resp_data
) free(resp_data
); resp_data
= NULL
;
2301 if (resp_param
) free(resp_param
); resp_param
= NULL
;
2305 /****************************************************************************
2307 ****************************************************************************/
2308 static void cmd_print(char *inbuf
,char *outbuf
)
2317 if (!connect_as_printer
)
2319 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2320 DEBUG(0,("Trying to print without -P may fail\n"));
2323 if (!next_token(NULL
,lname
,NULL
))
2325 DEBUG(0,("print <filename>\n"));
2329 strcpy(rname
,lname
);
2330 p
= strrchr(rname
,'/');
2335 strcpy(rname
,tname
);
2338 if ((int)strlen(rname
) > 14)
2341 if (strequal(lname
,"-"))
2344 strcpy(rname
,"stdin");
2347 dos_clean_name(rname
);
2349 bzero(outbuf
,smb_size
);
2350 set_message(outbuf
,2,2 + strlen(rname
),True
);
2352 CVAL(outbuf
,smb_com
) = SMBsplopen
;
2353 SSVAL(outbuf
,smb_tid
,cnum
);
2356 SSVAL(outbuf
,smb_vwv0
,0);
2357 SSVAL(outbuf
,smb_vwv1
,printmode
);
2359 p
= smb_buf(outbuf
);
2363 send_smb(Client
,outbuf
);
2364 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2366 if (CVAL(inbuf
,smb_rcls
) != 0)
2368 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf
),CNV_LANG(rname
)));
2373 f
= fopen(lname
,"r");
2376 DEBUG(0,("Error opening local file %s\n",lname
));
2381 fnum
= SVAL(inbuf
,smb_vwv0
);
2383 DEBUG(1,("printing file %s as %s\n",lname
,CNV_LANG(rname
)));
2389 bzero(outbuf
,smb_size
);
2390 set_message(outbuf
,1,3,True
);
2392 /* for some strange reason the OS/2 print server can't handle large
2393 packets when printing. weird */
2394 n
= MIN(1024,max_xmit
-(smb_len(outbuf
)+4));
2397 n
= printread(f
,smb_buf(outbuf
)+3,(int)(0.95*n
));
2399 n
= readfile(smb_buf(outbuf
)+3,1,n
,f
);
2402 DEBUG(0,("read gave %d\n",n
));
2406 smb_setlen(outbuf
,smb_len(outbuf
) + n
);
2408 CVAL(outbuf
,smb_com
) = SMBsplwr
;
2409 SSVAL(outbuf
,smb_tid
,cnum
);
2412 SSVAL(outbuf
,smb_vwv0
,fnum
);
2413 SSVAL(outbuf
,smb_vwv1
,n
+3);
2414 CVAL(smb_buf(outbuf
),0) = 1;
2415 SSVAL(smb_buf(outbuf
),1,n
);
2417 send_smb(Client
,outbuf
);
2418 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2420 if (CVAL(inbuf
,smb_rcls
) != 0)
2422 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf
)));
2429 DEBUG(2,("%d bytes printed\n",nread
));
2431 bzero(outbuf
,smb_size
);
2432 set_message(outbuf
,1,0,True
);
2433 CVAL(outbuf
,smb_com
) = SMBsplclose
;
2434 SSVAL(outbuf
,smb_tid
,cnum
);
2437 SSVAL(outbuf
,smb_vwv0
,fnum
);
2439 send_smb(Client
,outbuf
);
2440 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2442 if (CVAL(inbuf
,smb_rcls
) != 0)
2444 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf
)));
2454 /****************************************************************************
2456 ****************************************************************************/
2457 static void cmd_queue(char *inbuf
,char *outbuf
)
2462 bzero(outbuf
,smb_size
);
2463 set_message(outbuf
,2,0,True
);
2465 CVAL(outbuf
,smb_com
) = SMBsplretq
;
2466 SSVAL(outbuf
,smb_tid
,cnum
);
2469 SSVAL(outbuf
,smb_vwv0
,32); /* a max of 20 entries is to be shown */
2470 SSVAL(outbuf
,smb_vwv1
,0); /* the index into the queue */
2472 send_smb(Client
,outbuf
);
2473 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2475 if (CVAL(inbuf
,smb_rcls
) != 0)
2477 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf
)));
2481 count
= SVAL(inbuf
,smb_vwv0
);
2482 p
= smb_buf(inbuf
) + 3;
2485 DEBUG(0,("No entries in the print queue\n"));
2492 DEBUG(0,("Job Name Size Status\n"));
2498 case 0x01: sprintf(status
,"held or stopped"); break;
2499 case 0x02: sprintf(status
,"printing"); break;
2500 case 0x03: sprintf(status
,"awaiting print"); break;
2501 case 0x04: sprintf(status
,"in intercept"); break;
2502 case 0x05: sprintf(status
,"file had error"); break;
2503 case 0x06: sprintf(status
,"printer error"); break;
2504 default: sprintf(status
,"unknown"); break;
2507 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2508 SVAL(p
,5),p
+12,IVAL(p
,7),status
));
2516 /****************************************************************************
2517 show information about a print queue
2518 ****************************************************************************/
2519 static void cmd_qinfo(char *inbuf
,char *outbuf
)
2521 char *rparam
= NULL
;
2528 bzero(param
,sizeof(param
));
2531 SSVAL(p
,0,70); /* API function number 70 (DosPrintQGetInfo) */
2533 strcpy(p
,"zWrLh"); /* parameter description? */
2534 p
= skip_string(p
,1);
2535 strcpy(p
,"zWWWWzzzzWWzzl"); /* returned data format */
2536 p
= skip_string(p
,1);
2537 strcpy(p
,strrchr(service
,'\\')+1); /* name of queue */
2538 p
= skip_string(p
,1);
2539 SSVAL(p
,0,3); /* API function level 3, just queue info, no job info */
2540 SSVAL(p
,2,1000); /* size of bytes of returned data buffer */
2542 strcpy(p
,""); /* subformat */
2543 p
= skip_string(p
,1);
2545 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2546 if( call_api(PTR_DIFF(p
,param
), 0,
2553 result_code
= SVAL(rparam
,0);
2554 converter
= SVAL(rparam
,2); /* conversion factor */
2556 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt
, rdrcnt
, SVAL(rparam
,4) ));
2558 if (result_code
== 0) /* if no error, */
2560 p
= rdata
; /* received data */
2562 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p
,0), converter
, rdata
, rdrcnt
) );
2563 printf("Priority: %u\n", SVAL(p
,4) );
2564 printf("Start time: %u\n", SVAL(p
,6) );
2565 printf("Until time: %u\n", SVAL(p
,8) );
2566 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p
,12), converter
, rdata
, rdrcnt
) );
2567 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p
,16), converter
, rdata
, rdrcnt
) );
2568 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p
,20), converter
, rdata
, rdrcnt
) );
2569 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p
,24), converter
, rdata
, rdrcnt
) );
2570 printf("Status: %u\n", SVAL(p
,28) );
2571 printf("Jobs: %u\n", SVAL(p
,30) );
2572 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p
,32), converter
, rdata
, rdrcnt
) );
2573 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p
,36), converter
, rdata
, rdrcnt
) );
2575 /* Dump the driver data */
2580 ddptr
= rdata
+ SVAL(p
,40) - converter
;
2581 if( SVAL(p
,40) == 0 ) {count
= 0;} else {count
= IVAL(ddptr
,0);}
2582 printf("Driverdata: size=%d, version=%u\n", count
, IVAL(ddptr
,4) );
2584 for(x
=8; x
< count
; x
+=16)
2586 for(y
=0; y
< 16; y
++)
2589 printf("%2.2X ", CVAL(ddptr
,(x
+y
)) );
2593 for(y
=0; y
< 16 && (x
+y
) < count
; y
++)
2595 c
= CVAL(ddptr
,(x
+y
));
2601 fputc('\n', stdout
);
2607 else /* call_api() failed */
2609 printf("Failed, error = %d\n", result_code
);
2612 /* If any parameters or data were returned, free the storage. */
2613 if(rparam
) free(rparam
);
2614 if(rdata
) free(rdata
);
2619 /****************************************************************************
2621 ****************************************************************************/
2622 static void do_del(file_info
*finfo
)
2625 char *inbuf
,*outbuf
;
2628 strcpy(mask
,cur_dir
);
2629 strcat(mask
,finfo
->name
);
2631 if (finfo
->mode
& aDIR
)
2634 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
2635 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
2637 if (!inbuf
|| !outbuf
)
2639 DEBUG(0,("out of memory\n"));
2643 bzero(outbuf
,smb_size
);
2644 set_message(outbuf
,1,2 + strlen(mask
),True
);
2646 CVAL(outbuf
,smb_com
) = SMBunlink
;
2647 SSVAL(outbuf
,smb_tid
,cnum
);
2650 SSVAL(outbuf
,smb_vwv0
,0);
2652 p
= smb_buf(outbuf
);
2656 send_smb(Client
,outbuf
);
2657 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2659 if (CVAL(inbuf
,smb_rcls
) != 0)
2660 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf
),CNV_LANG(mask
)));
2662 free(inbuf
);free(outbuf
);
2666 /****************************************************************************
2668 ****************************************************************************/
2669 static void cmd_del(char *inbuf
,char *outbuf
)
2673 int attribute
= aSYSTEM
| aHIDDEN
;
2678 strcpy(mask
,cur_dir
);
2680 if (!next_token(NULL
,buf
,NULL
))
2682 DEBUG(0,("del <filename>\n"));
2687 do_dir((char *)inbuf
,(char *)outbuf
,mask
,attribute
,do_del
,False
);
2691 /****************************************************************************
2693 ****************************************************************************/
2694 static void cmd_rmdir(char *inbuf
,char *outbuf
)
2700 strcpy(mask
,cur_dir
);
2702 if (!next_token(NULL
,buf
,NULL
))
2704 DEBUG(0,("rmdir <dirname>\n"));
2709 bzero(outbuf
,smb_size
);
2710 set_message(outbuf
,0,2 + strlen(mask
),True
);
2712 CVAL(outbuf
,smb_com
) = SMBrmdir
;
2713 SSVAL(outbuf
,smb_tid
,cnum
);
2717 p
= smb_buf(outbuf
);
2721 send_smb(Client
,outbuf
);
2722 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2724 if (CVAL(inbuf
,smb_rcls
) != 0)
2726 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf
),CNV_LANG(mask
)));
2732 /****************************************************************************
2734 ****************************************************************************/
2735 static void cmd_rename(char *inbuf
,char *outbuf
)
2741 strcpy(src
,cur_dir
);
2742 strcpy(dest
,cur_dir
);
2744 if (!next_token(NULL
,buf
,NULL
) || !next_token(NULL
,buf2
,NULL
))
2746 DEBUG(0,("rename <src> <dest>\n"));
2752 bzero(outbuf
,smb_size
);
2753 set_message(outbuf
,1,4 + strlen(src
) + strlen(dest
),True
);
2755 CVAL(outbuf
,smb_com
) = SMBmv
;
2756 SSVAL(outbuf
,smb_tid
,cnum
);
2757 SSVAL(outbuf
,smb_vwv0
,aHIDDEN
| aDIR
| aSYSTEM
);
2760 p
= smb_buf(outbuf
);
2763 p
= skip_string(p
,1);
2767 send_smb(Client
,outbuf
);
2768 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2770 if (CVAL(inbuf
,smb_rcls
) != 0)
2772 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf
)));
2779 /****************************************************************************
2780 toggle the prompt flag
2781 ****************************************************************************/
2782 static void cmd_prompt(void)
2785 DEBUG(2,("prompting is now %s\n",prompt
?"on":"off"));
2789 /****************************************************************************
2790 set the newer than time
2791 ****************************************************************************/
2792 static void cmd_newer(void)
2798 ok
= next_token(NULL
,buf
,NULL
);
2799 if (ok
&& (sys_stat(buf
,&sbuf
) == 0))
2801 newer_than
= sbuf
.st_mtime
;
2802 DEBUG(1,("Getting files newer than %s",
2803 asctime(LocalTime(&newer_than
))));
2808 if (ok
&& newer_than
== 0)
2809 DEBUG(0,("Error setting newer-than time\n"));
2812 /****************************************************************************
2813 set the archive level
2814 ****************************************************************************/
2815 static void cmd_archive(void)
2819 if (next_token(NULL
,buf
,NULL
)) {
2820 archive_level
= atoi(buf
);
2822 DEBUG(0,("Archive level is %d\n",archive_level
));
2825 /****************************************************************************
2826 toggle the lowercaseflag
2827 ****************************************************************************/
2828 static void cmd_lowercase(void)
2830 lowercase
= !lowercase
;
2831 DEBUG(2,("filename lowercasing is now %s\n",lowercase
?"on":"off"));
2837 /****************************************************************************
2838 toggle the recurse flag
2839 ****************************************************************************/
2840 static void cmd_recurse(void)
2843 DEBUG(2,("directory recursion is now %s\n",recurse
?"on":"off"));
2846 /****************************************************************************
2847 toggle the translate flag
2848 ****************************************************************************/
2849 static void cmd_translate(void)
2851 translation
= !translation
;
2852 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2853 translation
?"on":"off"));
2857 /****************************************************************************
2858 do a printmode command
2859 ****************************************************************************/
2860 static void cmd_printmode(void)
2865 if (next_token(NULL
,buf
,NULL
))
2867 if (strequal(buf
,"text"))
2871 if (strequal(buf
,"graphics"))
2874 printmode
= atoi(buf
);
2881 strcpy(mode
,"text");
2884 strcpy(mode
,"graphics");
2887 sprintf(mode
,"%d",printmode
);
2891 DEBUG(2,("the printmode is now %s\n",mode
));
2894 /****************************************************************************
2896 ****************************************************************************/
2897 static void cmd_lcd(void)
2902 if (next_token(NULL
,buf
,NULL
))
2904 DEBUG(2,("the local directory is now %s\n",GetWd(d
)));
2908 /****************************************************************************
2909 send a session request
2910 ****************************************************************************/
2911 static BOOL
send_session_request(char *inbuf
,char *outbuf
)
2916 /* send a session request (RFC 8002) */
2918 strcpy(dest
,desthost
);
2919 p
= strchr(dest
,'.');
2922 /* put in the destination name */
2924 name_mangle(dest
,p
,name_type
);
2929 name_mangle(myname
,p
,0);
2932 /* setup the packet length */
2933 _smb_setlen(outbuf
,len
);
2934 CVAL(outbuf
,0) = 0x81;
2936 send_smb(Client
,outbuf
);
2937 DEBUG(5,("Sent session request\n"));
2939 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
2941 if (CVAL(inbuf
,0) == 0x84) /* C. Hoch 9/14/95 Start */
2943 /* For information, here is the response structure.
2944 * We do the byte-twiddling to for portability.
2945 struct RetargetResponse{
2947 unsigned char flags;
2954 int port
= (CVAL(inbuf
,8)<<8)+CVAL(inbuf
,9);
2955 /* SESSION RETARGET */
2956 putip((char *)&dest_ip
,inbuf
+4);
2959 Client
= open_socket_out(SOCK_STREAM
, &dest_ip
, port
, LONG_CONNECT_TIMEOUT
);
2963 DEBUG(3,("Retargeted\n"));
2965 set_socket_options(Client
,user_socket_options
);
2968 return send_session_request(inbuf
,outbuf
);
2969 } /* C. Hoch 9/14/95 End */
2972 if (CVAL(inbuf
,0) != 0x82)
2974 int ecode
= CVAL(inbuf
,4);
2975 DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
2976 CVAL(inbuf
,0),ecode
,myname
,desthost
));
2980 DEBUG(0,("Not listening on called name\n"));
2981 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost
));
2982 DEBUG(0,("You may find the -I option useful for this\n"));
2985 DEBUG(0,("Not listening for calling name\n"));
2986 DEBUG(0,("Try to connect as another name (instead of %s)\n",myname
));
2987 DEBUG(0,("You may find the -n option useful for this\n"));
2990 DEBUG(0,("Called name not present\n"));
2991 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost
));
2992 DEBUG(0,("You may find the -I option useful for this\n"));
2995 DEBUG(0,("Called name present, but insufficient resources\n"));
2996 DEBUG(0,("Perhaps you should try again later?\n"));
2999 DEBUG(0,("Unspecified error 0x%X\n",ecode
));
3000 DEBUG(0,("Your server software is being unfriendly\n"));
3012 {PROTOCOL_CORE
,"PC NETWORK PROGRAM 1.0"},
3013 {PROTOCOL_COREPLUS
,"MICROSOFT NETWORKS 1.03"},
3014 {PROTOCOL_LANMAN1
,"MICROSOFT NETWORKS 3.0"},
3015 {PROTOCOL_LANMAN1
,"LANMAN1.0"},
3016 {PROTOCOL_LANMAN2
,"LM1.2X002"},
3017 {PROTOCOL_LANMAN2
,"Samba"},
3018 {PROTOCOL_NT1
,"NT LM 0.12"},
3019 {PROTOCOL_NT1
,"NT LANMAN 1.0"},
3024 /****************************************************************************
3025 send a login command
3026 ****************************************************************************/
3027 static BOOL
send_login(char *inbuf
,char *outbuf
,BOOL start_session
,BOOL use_setup
)
3029 BOOL was_null
= (!inbuf
&& !outbuf
);
3031 time_t servertime
= 0;
3032 extern int serverzone
;
3044 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3045 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3049 if (strstr(service
,"IPC$")) connect_as_ipc
= True
;
3053 if (connect_as_printer
)
3054 strcpy(dev
,"LPT1:");
3059 if (start_session
&& !send_session_request(inbuf
,outbuf
))
3069 bzero(outbuf
,smb_size
);
3071 /* setup the protocol strings */
3075 for (plength
=0,numprots
=0;
3076 prots
[numprots
].name
&& prots
[numprots
].prot
<=max_protocol
;
3078 plength
+= strlen(prots
[numprots
].name
)+2;
3080 set_message(outbuf
,0,plength
,True
);
3082 p
= smb_buf(outbuf
);
3084 prots
[numprots
].name
&& prots
[numprots
].prot
<=max_protocol
;
3088 strcpy(p
,prots
[numprots
].name
);
3093 CVAL(outbuf
,smb_com
) = SMBnegprot
;
3096 CVAL(smb_buf(outbuf
),0) = 2;
3098 send_smb(Client
,outbuf
);
3099 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
3103 if (CVAL(inbuf
,smb_rcls
) != 0 || ((int)SVAL(inbuf
,smb_vwv0
) >= numprots
))
3105 DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
3106 myname
,desthost
,smb_errstr(inbuf
)));
3115 Protocol
= prots
[SVAL(inbuf
,smb_vwv0
)].prot
;
3118 if (Protocol
< PROTOCOL_NT1
) {
3119 sec_mode
= SVAL(inbuf
,smb_vwv1
);
3120 max_xmit
= SVAL(inbuf
,smb_vwv2
);
3121 sesskey
= IVAL(inbuf
,smb_vwv6
);
3122 serverzone
= SVALS(inbuf
,smb_vwv10
)*60;
3123 /* this time is converted to GMT by make_unix_date */
3124 servertime
= make_unix_date(inbuf
+smb_vwv8
);
3125 if (Protocol
>= PROTOCOL_COREPLUS
) {
3126 readbraw_supported
= ((SVAL(inbuf
,smb_vwv5
) & 0x1) != 0);
3127 writebraw_supported
= ((SVAL(inbuf
,smb_vwv5
) & 0x2) != 0);
3129 crypt_len
= smb_buflen(inbuf
);
3130 memcpy(cryptkey
,smb_buf(inbuf
),8);
3131 DEBUG(3,("max mux %d\n",SVAL(inbuf
,smb_vwv3
)));
3132 max_vcs
= SVAL(inbuf
,smb_vwv4
);
3133 DEBUG(3,("max vcs %d\n",max_vcs
));
3134 DEBUG(3,("max blk %d\n",SVAL(inbuf
,smb_vwv5
)));
3137 sec_mode
= CVAL(inbuf
,smb_vwv1
);
3138 max_xmit
= IVAL(inbuf
,smb_vwv3
+1);
3139 sesskey
= IVAL(inbuf
,smb_vwv7
+1);
3140 serverzone
= SVALS(inbuf
,smb_vwv15
+1)*60;
3141 /* this time arrives in real GMT */
3142 servertime
= interpret_long_date(inbuf
+smb_vwv11
+1);
3143 crypt_len
= CVAL(inbuf
,smb_vwv16
+1);
3144 memcpy(cryptkey
,smb_buf(inbuf
),8);
3145 if (IVAL(inbuf
,smb_vwv9
+1) & 1)
3146 readbraw_supported
= writebraw_supported
= True
;
3147 DEBUG(3,("max mux %d\n",SVAL(inbuf
,smb_vwv1
+1)));
3148 max_vcs
= SVAL(inbuf
,smb_vwv2
+1);
3149 DEBUG(3,("max vcs %d\n",max_vcs
));
3150 DEBUG(3,("max raw %d\n",IVAL(inbuf
,smb_vwv5
+1)));
3151 DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf
,smb_vwv9
+1)));
3154 DEBUG(3,("Sec mode %d\n",SVAL(inbuf
,smb_vwv1
)));
3155 DEBUG(3,("max xmt %d\n",max_xmit
));
3156 DEBUG(3,("Got %d byte crypt key\n",crypt_len
));
3157 DEBUG(3,("Chose protocol [%s]\n",prots
[SVAL(inbuf
,smb_vwv0
)].name
));
3159 doencrypt
= ((sec_mode
& 2) != 0);
3162 static BOOL done_time
= False
;
3164 DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
3165 asctime(LocalTime(&servertime
)),
3166 -(double)(serverzone
/3600.0)));
3176 pass
= (char *)getpass("Password: ");
3178 /* use a blank username for the 2nd try with a blank password */
3179 if (tries
++ && !*pass
)
3182 if (Protocol
>= PROTOCOL_LANMAN1
&& use_setup
)
3185 int passlen
= strlen(pass
)+1;
3189 if (doencrypt
&& *pass
) {
3190 DEBUG(3,("Using encrypted passwords\n"));
3192 SMBencrypt(pass
,cryptkey
,pword
);
3198 /* if in share level security then don't send a password now */
3199 if (!(sec_mode
& 1)) {strcpy(pword
, "");passlen
=1;}
3201 /* send a session setup command */
3202 bzero(outbuf
,smb_size
);
3204 if (Protocol
< PROTOCOL_NT1
) {
3205 set_message(outbuf
,10,1 + strlen(username
) + passlen
,True
);
3206 CVAL(outbuf
,smb_com
) = SMBsesssetupX
;
3209 CVAL(outbuf
,smb_vwv0
) = 0xFF;
3210 SSVAL(outbuf
,smb_vwv2
,max_xmit
);
3211 SSVAL(outbuf
,smb_vwv3
,2);
3212 SSVAL(outbuf
,smb_vwv4
,max_vcs
-1);
3213 SIVAL(outbuf
,smb_vwv5
,sesskey
);
3214 SSVAL(outbuf
,smb_vwv7
,passlen
);
3215 p
= smb_buf(outbuf
);
3216 memcpy(p
,pword
,passlen
);
3220 if (!doencrypt
) passlen
--;
3222 set_message(outbuf
,13,0,True
);
3223 CVAL(outbuf
,smb_com
) = SMBsesssetupX
;
3226 CVAL(outbuf
,smb_vwv0
) = 0xFF;
3227 SSVAL(outbuf
,smb_vwv2
,BUFFER_SIZE
);
3228 SSVAL(outbuf
,smb_vwv3
,2);
3229 SSVAL(outbuf
,smb_vwv4
,getpid());
3230 SIVAL(outbuf
,smb_vwv5
,sesskey
);
3231 SSVAL(outbuf
,smb_vwv7
,passlen
);
3232 SSVAL(outbuf
,smb_vwv8
,0);
3233 p
= smb_buf(outbuf
);
3234 memcpy(p
,pword
,passlen
); p
+= SVAL(outbuf
,smb_vwv7
);
3235 strcpy(p
,username
);p
= skip_string(p
,1);
3236 strcpy(p
,workgroup
);p
= skip_string(p
,1);
3237 strcpy(p
,"Unix");p
= skip_string(p
,1);
3238 strcpy(p
,"Samba");p
= skip_string(p
,1);
3239 set_message(outbuf
,13,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
3242 send_smb(Client
,outbuf
);
3243 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
3247 if (CVAL(inbuf
,smb_rcls
) != 0)
3250 ((CVAL(inbuf
,smb_rcls
) == ERRDOS
&&
3251 SVAL(inbuf
,smb_err
) == ERRnoaccess
) ||
3252 (CVAL(inbuf
,smb_rcls
) == ERRSRV
&&
3253 SVAL(inbuf
,smb_err
) == ERRbadpw
)))
3256 DEBUG(3,("resending login\n"));
3260 DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n",
3261 username
,myname
,desthost
,smb_errstr(inbuf
)));
3262 DEBUG(0,("You might find the -U, -W or -n options useful\n"));
3263 DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
3264 DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
3273 if (Protocol
>= PROTOCOL_NT1
) {
3274 char *domain
,*os
,*lanman
;
3277 lanman
= skip_string(os
,1);
3278 domain
= skip_string(lanman
,1);
3279 if (*domain
|| *os
|| *lanman
)
3280 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain
,os
,lanman
));
3283 /* use the returned uid from now on */
3284 if (SVAL(inbuf
,smb_uid
) != uid
)
3285 DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
3286 SVAL(inbuf
,smb_uid
),uid
));
3287 uid
= SVAL(inbuf
,smb_uid
);
3290 /* now we've got a connection - send a tcon message */
3291 bzero(outbuf
,smb_size
);
3293 if (strncmp(service
,"\\\\",2) != 0)
3295 DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
3296 DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
3303 int passlen
= strlen(pass
)+1;
3308 if (doencrypt
&& *pass
) {
3310 SMBencrypt(pass
,cryptkey
,pword
);
3314 /* if in user level security then don't send a password now */
3315 if ((sec_mode
& 1)) {
3316 strcpy(pword
, ""); passlen
=1;
3319 if (Protocol
<= PROTOCOL_COREPLUS
) {
3320 set_message(outbuf
,0,6 + strlen(service
) + passlen
+ strlen(dev
),True
);
3321 CVAL(outbuf
,smb_com
) = SMBtcon
;
3324 p
= smb_buf(outbuf
);
3327 p
= skip_string(p
,1);
3329 memcpy(p
,pword
,passlen
);
3335 set_message(outbuf
,4,2 + strlen(service
) + passlen
+ strlen(dev
),True
);
3336 CVAL(outbuf
,smb_com
) = SMBtconX
;
3339 SSVAL(outbuf
,smb_vwv0
,0xFF);
3340 SSVAL(outbuf
,smb_vwv3
,passlen
);
3342 p
= smb_buf(outbuf
);
3343 memcpy(p
,pword
,passlen
);
3346 p
= skip_string(p
,1);
3351 send_smb(Client
,outbuf
);
3352 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
3354 /* trying again with a blank password */
3355 if (CVAL(inbuf
,smb_rcls
) != 0 &&
3356 (int)strlen(pass
) > 0 &&
3358 Protocol
>= PROTOCOL_LANMAN1
)
3360 DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf
)));
3365 if (CVAL(inbuf
,smb_rcls
) != 0)
3367 DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf
)));
3368 DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
3369 DEBUG(0,("Some servers insist that these be in uppercase\n"));
3379 if (Protocol
<= PROTOCOL_COREPLUS
) {
3380 max_xmit
= SVAL(inbuf
,smb_vwv0
);
3382 cnum
= SVAL(inbuf
,smb_vwv1
);
3385 max_xmit
= MIN(max_xmit
,BUFFER_SIZE
-4);
3387 max_xmit
= BUFFER_SIZE
- 4;
3389 cnum
= SVAL(inbuf
,smb_tid
);
3392 DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum
,max_xmit
));
3403 /****************************************************************************
3404 send a logout command
3405 ****************************************************************************/
3406 static void send_logout(void )
3408 pstring inbuf
,outbuf
;
3410 bzero(outbuf
,smb_size
);
3411 set_message(outbuf
,0,0,True
);
3412 CVAL(outbuf
,smb_com
) = SMBtdis
;
3413 SSVAL(outbuf
,smb_tid
,cnum
);
3416 send_smb(Client
,outbuf
);
3417 receive_smb(Client
,inbuf
,SHORT_TIMEOUT
);
3419 if (CVAL(inbuf
,smb_rcls
) != 0)
3421 DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf
)));
3433 /****************************************************************************
3435 ****************************************************************************/
3436 static BOOL
call_api(int prcnt
,int drcnt
,
3437 int mprcnt
,int mdrcnt
,
3438 int *rprcnt
,int *rdrcnt
,
3439 char *param
,char *data
,
3440 char **rparam
,char **rdata
)
3442 static char *inbuf
=NULL
;
3443 static char *outbuf
=NULL
;
3445 if (!inbuf
) inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3446 if (!outbuf
) outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3448 send_trans_request(outbuf
,SMBtrans
,"\\PIPE\\LANMAN",0,0,
3453 return (receive_trans_response(inbuf
,SMBtrans
,
3458 /****************************************************************************
3459 send a SMB trans or trans2 request
3460 ****************************************************************************/
3461 static BOOL
send_trans_request(char *outbuf
,int trans
,
3462 char *name
,int fid
,int flags
,
3463 char *data
,char *param
,uint16
*setup
,
3464 int ldata
,int lparam
,int lsetup
,
3465 int mdata
,int mparam
,int msetup
)
3468 int this_ldata
,this_lparam
;
3469 int tot_data
=0,tot_param
=0;
3470 char *outdata
,*outparam
;
3474 this_lparam
= MIN(lparam
,max_xmit
- (500+lsetup
*SIZEOFWORD
)); /* hack */
3475 this_ldata
= MIN(ldata
,max_xmit
- (500+lsetup
*SIZEOFWORD
+this_lparam
));
3477 bzero(outbuf
,smb_size
);
3478 set_message(outbuf
,14+lsetup
,0,True
);
3479 CVAL(outbuf
,smb_com
) = trans
;
3480 SSVAL(outbuf
,smb_tid
,cnum
);
3483 outparam
= smb_buf(outbuf
)+(trans
==SMBtrans
? strlen(name
)+1 : 3);
3484 outdata
= outparam
+this_lparam
;
3486 /* primary request */
3487 SSVAL(outbuf
,smb_tpscnt
,lparam
); /* tpscnt */
3488 SSVAL(outbuf
,smb_tdscnt
,ldata
); /* tdscnt */
3489 SSVAL(outbuf
,smb_mprcnt
,mparam
); /* mprcnt */
3490 SSVAL(outbuf
,smb_mdrcnt
,mdata
); /* mdrcnt */
3491 SCVAL(outbuf
,smb_msrcnt
,msetup
); /* msrcnt */
3492 SSVAL(outbuf
,smb_flags
,flags
); /* flags */
3493 SIVAL(outbuf
,smb_timeout
,0); /* timeout */
3494 SSVAL(outbuf
,smb_pscnt
,this_lparam
); /* pscnt */
3495 SSVAL(outbuf
,smb_psoff
,smb_offset(outparam
,outbuf
)); /* psoff */
3496 SSVAL(outbuf
,smb_dscnt
,this_ldata
); /* dscnt */
3497 SSVAL(outbuf
,smb_dsoff
,smb_offset(outdata
,outbuf
)); /* dsoff */
3498 SCVAL(outbuf
,smb_suwcnt
,lsetup
); /* suwcnt */
3499 for (i
=0;i
<lsetup
;i
++) /* setup[] */
3500 SSVAL(outbuf
,smb_setup
+i
*SIZEOFWORD
,setup
[i
]);
3501 p
= smb_buf(outbuf
);
3502 if (trans
==SMBtrans
)
3503 strcpy(p
,name
); /* name[] */
3506 *p
++ = 0; /* put in a null smb_name */
3507 *p
++ = 'D'; *p
++ = ' '; /* this was added because OS/2 does it */
3509 if (this_lparam
) /* param[] */
3510 memcpy(outparam
,param
,this_lparam
);
3511 if (this_ldata
) /* data[] */
3512 memcpy(outdata
,data
,this_ldata
);
3513 set_message(outbuf
,14+lsetup
, /* wcnt, bcc */
3514 PTR_DIFF(outdata
+this_ldata
,smb_buf(outbuf
)),False
);
3517 send_smb(Client
,outbuf
);
3519 if (this_ldata
< ldata
|| this_lparam
< lparam
)
3521 /* receive interim response */
3522 if (!receive_smb(Client
,inbuf
,SHORT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
3524 DEBUG(0,("%s request failed (%s)\n",
3525 trans
==SMBtrans
?"SMBtrans":"SMBtrans2", smb_errstr(inbuf
)));
3529 tot_data
= this_ldata
;
3530 tot_param
= this_lparam
;
3532 while (tot_data
< ldata
|| tot_param
< lparam
)
3534 this_lparam
= MIN(lparam
-tot_param
,max_xmit
- 500); /* hack */
3535 this_ldata
= MIN(ldata
-tot_data
,max_xmit
- (500+this_lparam
));
3537 set_message(outbuf
,trans
==SMBtrans
?8:9,0,True
);
3538 CVAL(outbuf
,smb_com
) = trans
==SMBtrans
? SMBtranss
: SMBtranss2
;
3540 outparam
= smb_buf(outbuf
);
3541 outdata
= outparam
+this_lparam
;
3543 /* secondary request */
3544 SSVAL(outbuf
,smb_tpscnt
,lparam
); /* tpscnt */
3545 SSVAL(outbuf
,smb_tdscnt
,ldata
); /* tdscnt */
3546 SSVAL(outbuf
,smb_spscnt
,this_lparam
); /* pscnt */
3547 SSVAL(outbuf
,smb_spsoff
,smb_offset(outparam
,outbuf
)); /* psoff */
3548 SSVAL(outbuf
,smb_spsdisp
,tot_param
); /* psdisp */
3549 SSVAL(outbuf
,smb_sdscnt
,this_ldata
); /* dscnt */
3550 SSVAL(outbuf
,smb_sdsoff
,smb_offset(outdata
,outbuf
)); /* dsoff */
3551 SSVAL(outbuf
,smb_sdsdisp
,tot_data
); /* dsdisp */
3552 if (trans
==SMBtrans2
)
3553 SSVAL(outbuf
,smb_sfid
,fid
); /* fid */
3554 if (this_lparam
) /* param[] */
3555 memcpy(outparam
,param
,this_lparam
);
3556 if (this_ldata
) /* data[] */
3557 memcpy(outdata
,data
,this_ldata
);
3558 set_message(outbuf
,trans
==SMBtrans
?8:9, /* wcnt, bcc */
3559 PTR_DIFF(outdata
+this_ldata
,smb_buf(outbuf
)),False
);
3562 send_smb(Client
,outbuf
);
3564 tot_data
+= this_ldata
;
3565 tot_param
+= this_lparam
;
3572 /****************************************************************************
3573 try and browse available connections on a host
3574 ****************************************************************************/
3575 static BOOL
browse_host(BOOL sort
)
3578 #define strcasecmp StrCaseCmp
3580 extern int strcasecmp();
3582 char *rparam
= NULL
;
3589 /* now send a SMBtrans command with api RNetShareEnum */
3591 SSVAL(p
,0,0); /* api number */
3594 p
= skip_string(p
,1);
3596 p
= skip_string(p
,1);
3598 SSVAL(p
,2,BUFFER_SIZE
);
3601 if (call_api(PTR_DIFF(p
,param
),0,
3607 int res
= SVAL(rparam
,0);
3608 int converter
=SVAL(rparam
,2);
3610 BOOL long_share_name
=False
;
3614 count
=SVAL(rparam
,4);
3619 printf("\n\tSharename Type Comment\n");
3620 printf("\t--------- ---- -------\n");
3624 qsort(p
,count
,20,QSORT_CAST strcasecmp
);
3626 for (i
=0;i
<count
;i
++)
3629 int type
= SVAL(p
,14);
3630 int comment_offset
= IVAL(p
,16) & 0xFFFF;
3636 case STYPE_DISKTREE
:
3637 strcpy(typestr
,"Disk"); break;
3639 strcpy(typestr
,"Printer"); break;
3641 strcpy(typestr
,"Device"); break;
3643 strcpy(typestr
,"IPC"); break;
3646 printf("\t%-15.15s%-10.10s%s\n",
3649 comment_offset
?rdata
+comment_offset
-converter
:"");
3651 if (strlen(sname
)>8) long_share_name
=True
;
3656 if (long_share_name
) {
3657 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3662 if (rparam
) free(rparam
);
3663 if (rdata
) free(rdata
);
3669 /****************************************************************************
3670 get some server info
3671 ****************************************************************************/
3672 static void server_info()
3674 char *rparam
= NULL
;
3680 bzero(param
,sizeof(param
));
3683 SSVAL(p
,0,63); /* NetServerGetInfo()? */
3686 p
= skip_string(p
,1);
3687 strcpy(p
,"zzzBBzz");
3688 p
= skip_string(p
,1);
3689 SSVAL(p
,0,10); /* level 10 */
3693 if (call_api(PTR_DIFF(p
,param
),0,
3699 int res
= SVAL(rparam
,0);
3700 int converter
=SVAL(rparam
,2);
3706 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3707 rdata
+SVAL(p
,0)-converter
,
3708 rdata
+SVAL(p
,4)-converter
,
3709 rdata
+SVAL(p
,8)-converter
,
3710 rdata
+SVAL(p
,14)-converter
);
3714 if (rparam
) free(rparam
);
3715 if (rdata
) free(rdata
);
3721 /****************************************************************************
3722 try and browse available connections on a host
3723 ****************************************************************************/
3724 static BOOL
list_servers(char *wk_grp
)
3726 char *rparam
= NULL
;
3734 BOOL generic_request
= False
;
3737 if (strequal(wk_grp
,"WORKGROUP")) {
3738 /* we won't specify a workgroup */
3739 generic_request
= True
;
3742 /* now send a SMBtrans command with api ServerEnum? */
3744 SSVAL(p
,0,0x68); /* api number */
3747 strcpy(p
,generic_request
?"WrLehDO":"WrLehDz");
3748 p
= skip_string(p
,1);
3750 strcpy(p
,"B16BBDz");
3752 p
= skip_string(p
,1);
3754 SSVAL(p
,2,0x2000); /* buf length */
3760 if (!generic_request
) {
3762 p
= skip_string(p
,1);
3765 /* first ask for a list of servers in this workgroup */
3766 SIVAL(svtype_p
,0,SV_TYPE_ALL
);
3768 if (call_api(PTR_DIFF(p
+4,param
),0,
3774 int res
= SVAL(rparam
,0);
3775 int converter
=SVAL(rparam
,2);
3780 count
=SVAL(rparam
,4);
3783 printf("\n\nThis machine has a browse list:\n");
3784 printf("\n\tServer Comment\n");
3785 printf("\t--------- -------\n");
3788 for (i
=0;i
<count
;i
++) {
3790 int comment_offset
= IVAL(p2
,22) & 0xFFFF;
3791 printf("\t%-16.16s %s\n",
3793 comment_offset
?rdata
+comment_offset
-converter
:"");
3801 if (rparam
) {free(rparam
); rparam
= NULL
;}
3802 if (rdata
) {free(rdata
); rdata
= NULL
;}
3804 /* now ask for a list of workgroups */
3805 SIVAL(svtype_p
,0,SV_TYPE_DOMAIN_ENUM
);
3807 if (call_api(PTR_DIFF(p
+4,param
),0,
3813 int res
= SVAL(rparam
,0);
3814 int converter
=SVAL(rparam
,2);
3819 count
=SVAL(rparam
,4);
3822 printf("\n\nThis machine has a workgroup list:\n");
3823 printf("\n\tWorkgroup Master\n");
3824 printf("\t--------- -------\n");
3827 for (i
=0;i
<count
;i
++) {
3829 int comment_offset
= IVAL(p2
,22) & 0xFFFF;
3830 printf("\t%-16.16s %s\n",
3832 comment_offset
?rdata
+comment_offset
-converter
:"");
3840 if (rparam
) free(rparam
);
3841 if (rdata
) free(rdata
);
3847 /* This defines the commands supported by this client */
3855 {"ls",cmd_dir
,"<mask> list the contents of the current directory"},
3856 {"dir",cmd_dir
,"<mask> list the contents of the current directory"},
3857 {"lcd",cmd_lcd
,"[directory] change/report the local current working directory"},
3858 {"cd",cmd_cd
,"[directory] change/report the remote directory"},
3859 {"pwd",cmd_pwd
,"show current remote directory (same as 'cd' with no args)"},
3860 {"get",cmd_get
,"<remote name> [local name] get a file"},
3861 {"mget",cmd_mget
,"<mask> get all the matching files"},
3862 {"put",cmd_put
,"<local name> [remote name] put a file"},
3863 {"mput",cmd_mput
,"<mask> put all matching files"},
3864 {"rename",cmd_rename
,"<src> <dest> rename some files"},
3865 {"more",cmd_more
,"<remote name> view a remote file with your pager"},
3866 {"mask",cmd_select
,"<mask> mask all filenames against this"},
3867 {"del",cmd_del
,"<mask> delete all matching files"},
3868 {"rm",cmd_del
,"<mask> delete all matching files"},
3869 {"mkdir",cmd_mkdir
,"<directory> make a directory"},
3870 {"md",cmd_mkdir
,"<directory> make a directory"},
3871 {"rmdir",cmd_rmdir
,"<directory> remove a directory"},
3872 {"rd",cmd_rmdir
,"<directory> remove a directory"},
3873 {"prompt",cmd_prompt
,"toggle prompting for filenames for mget and mput"},
3874 {"recurse",cmd_recurse
,"toggle directory recursion for mget and mput"},
3875 {"translate",cmd_translate
,"toggle text translation for printing"},
3876 {"lowercase",cmd_lowercase
,"toggle lowercasing of filenames for get"},
3877 {"print",cmd_print
,"<file name> print a file"},
3878 {"printmode",cmd_printmode
,"<graphics or text> set the print mode"},
3879 {"queue",cmd_queue
,"show the print queue"},
3880 {"qinfo",cmd_qinfo
,"show print queue information"},
3881 {"cancel",cmd_cancel
,"<jobid> cancel a print queue entry"},
3882 {"stat",cmd_stat
,"<file> get info on a file (experimental!)"},
3883 {"quit",send_logout
,"logoff the server"},
3884 {"q",send_logout
,"logoff the server"},
3885 {"exit",send_logout
,"logoff the server"},
3886 {"newer",cmd_newer
,"<file> only mget files newer than the specified local file"},
3887 {"archive",cmd_archive
,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit"},
3888 {"tar",cmd_tar
,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3889 {"blocksize",cmd_block
,"blocksize <number> (default 20)" },
3890 {"tarmode",cmd_tarmode
,
3891 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3892 {"setmode",cmd_setmode
,"filename <setmode string> change modes of file"},
3893 {"help",cmd_help
,"[command] give help on a command"},
3894 {"?",cmd_help
,"[command] give help on a command"},
3895 {"!",NULL
,"run a shell command on the local system"},
3900 /*******************************************************************
3901 lookup a command string in the list of commands, including
3903 ******************************************************************/
3904 static int process_tok(fstring tok
)
3906 int i
= 0, matches
= 0;
3908 int tok_len
= strlen(tok
);
3910 while (commands
[i
].fn
!= NULL
)
3912 if (strequal(commands
[i
].name
,tok
))
3918 else if (strnequal(commands
[i
].name
, tok
, tok_len
+1))
3928 else if (matches
== 1)
3934 /****************************************************************************
3936 ****************************************************************************/
3942 if (next_token(NULL
,buf
,NULL
))
3944 if ((i
= process_tok(buf
)) >= 0)
3945 DEBUG(0,("HELP %s:\n\t%s\n\n",commands
[i
].name
,commands
[i
].description
));
3948 while (commands
[i
].description
)
3950 for (j
=0; commands
[i
].description
&& (j
<5); j
++) {
3951 DEBUG(0,("%-15s",commands
[i
].name
));
3958 /****************************************************************************
3959 open the client sockets
3960 ****************************************************************************/
3961 static BOOL
open_sockets(int port
)
3963 static int last_port
;
3971 if (port
== 0) port
=last_port
;
3982 strcpy(service2
,service
);
3983 host
= strtok(service2
,"\\/");
3985 DEBUG(0,("Badly formed host name\n"));
3988 strcpy(desthost
,host
);
3992 get_myname(myname
,NULL
);
3996 DEBUG(3,("Opening sockets\n"));
4002 if ((hp
= Get_Hostbyname(host
))) {
4003 putip((char *)&dest_ip
,(char *)hp
->h_addr
);
4007 /* Try and resolve the name with the netbios server */
4010 if ((bcast
= open_socket_in(SOCK_DGRAM
, 0, 3,
4011 interpret_addr(lp_socket_address()))) != -1) {
4012 set_socket_options(bcast
, "SO_BROADCAST");
4014 if (name_query(bcast
, host
, 0x20, True
, True
, *iface_bcast(dest_ip
),
4022 DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host
));
4028 Client
= open_socket_out(SOCK_STREAM
, &dest_ip
, port
, LONG_CONNECT_TIMEOUT
);
4032 DEBUG(3,("Connected\n"));
4034 set_socket_options(Client
,user_socket_options
);
4039 /****************************************************************************
4040 wait for keyboard activity, swallowing network packets
4041 ****************************************************************************/
4043 static char wait_keyboard(char *buffer
)
4045 static void wait_keyboard(char *buffer
)
4050 struct timeval timeout
;
4060 FD_SET(Client
,&fds
);
4062 FD_SET(fileno(stdin
),&fds
);
4065 timeout
.tv_sec
= 20;
4066 timeout
.tv_usec
= 0;
4070 selrtn
= sys_select(&fds
,&timeout
);
4073 if (FD_ISSET(fileno(stdin
),&fds
))
4081 f_flags
= fcntl(fileno(stdin
), F_GETFL
, 0);
4082 fcntl( fileno(stdin
), F_SETFL
, f_flags
| O_NONBLOCK
);
4083 readret
= read_data( fileno(stdin
), &ch
, 1);
4084 fcntl(fileno(stdin
), F_SETFL
, f_flags
);
4087 if (errno
!= EAGAIN
)
4089 /* should crash here */
4090 DEBUG(1,("readchar stdin failed\n"));
4093 else if (readret
!= 0)
4099 if (FD_ISSET(Client
,&fds
))
4100 receive_smb(Client
,buffer
,0);
4107 chkpath("\\",False
);
4110 chkpath("\\",False
);
4116 /****************************************************************************
4117 close and open the connection again
4118 ****************************************************************************/
4119 BOOL
reopen_connection(char *inbuf
,char *outbuf
)
4121 static int open_count
=0;
4125 if (open_count
>5) return(False
);
4127 DEBUG(1,("Trying to re-open connection\n"));
4129 set_message(outbuf
,0,0,True
);
4130 SCVAL(outbuf
,smb_com
,SMBtdis
);
4131 SSVAL(outbuf
,smb_tid
,cnum
);
4134 send_smb(Client
,outbuf
);
4135 receive_smb(Client
,inbuf
,SHORT_TIMEOUT
);
4138 if (!open_sockets(0)) return(False
);
4140 return(send_login(inbuf
,outbuf
,True
,True
));
4143 /****************************************************************************
4144 process commands from the client
4145 ****************************************************************************/
4146 static BOOL
process(char *base_directory
)
4152 char *InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
4153 char *OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
4155 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
4158 bzero(OutBuffer
,smb_size
);
4160 if (!send_login(InBuffer
,OutBuffer
,True
,True
))
4163 if (*base_directory
) do_cd(base_directory
);
4166 if (cmd
[0] != '\0') while (cmd
[0] != '\0')
4172 if ((p
= strchr(cmd
, ';')) == 0)
4174 strncpy(line
, cmd
, 999);
4180 if (p
- cmd
> 999) p
= cmd
+ 999;
4181 strncpy(line
, cmd
, p
- cmd
);
4182 line
[p
- cmd
] = '\0';
4186 /* input language code to internal one */
4189 /* and get the first part of the command */
4192 if (!next_token(&ptr
,tok
,NULL
)) continue;
4195 if ((i
= process_tok(tok
)) >= 0)
4196 commands
[i
].fn(InBuffer
,OutBuffer
);
4198 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok
)));
4200 DEBUG(0,("%s: command not found\n",CNV_LANG(tok
)));
4202 else while (!feof(stdin
))
4207 bzero(OutBuffer
,smb_size
);
4209 /* display a prompt */
4210 DEBUG(1,("smb: %s> ", CNV_LANG(cur_dir
)));
4214 line
[0] = wait_keyboard(InBuffer
);
4215 /* this might not be such a good idea... */
4216 if ( line
[0] == EOF
)
4219 wait_keyboard(InBuffer
);
4222 /* and get a response */
4224 fgets( &line
[1],999, stdin
);
4226 if (!fgets(line
,1000,stdin
))
4230 /* input language code to internal one */
4233 /* special case - first char is ! */
4240 /* and get the first part of the command */
4243 if (!next_token(&ptr
,tok
,NULL
)) continue;
4246 if ((i
= process_tok(tok
)) >= 0)
4247 commands
[i
].fn(InBuffer
,OutBuffer
);
4249 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok
)));
4251 DEBUG(0,("%s: command not found\n",CNV_LANG(tok
)));
4259 /****************************************************************************
4260 usage on the program
4261 ****************************************************************************/
4262 static void usage(char *pname
)
4264 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
4268 DEBUG(0,("[-t termcode] "));
4271 DEBUG(0,("\nVersion %s\n",VERSION
));
4272 DEBUG(0,("\t-p port listen on the specified port\n"));
4273 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
4274 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
4275 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
4276 DEBUG(0,("\t-N don't ask for a password\n"));
4277 DEBUG(0,("\t-P connect to service as a printer\n"));
4278 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
4279 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
4280 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
4281 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
4282 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
4283 DEBUG(0,("\t-U username set the network username\n"));
4284 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
4285 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
4287 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
4289 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
4290 DEBUG(0,("\t-D directory start from directory\n"));
4296 /****************************************************************************
4298 ****************************************************************************/
4299 int main(int argc
,char *argv
[])
4301 fstring base_directory
;
4302 char *pname
= argv
[0];
4303 int port
= SMB_PORT
;
4306 extern char *optarg
;
4309 BOOL message
= False
;
4310 extern char tar_type
;
4311 static pstring servicesf
= CONFIGFILE
;
4314 *base_directory
= 0;
4318 setup_logging(pname
,True
);
4321 charset_initialise();
4332 strcpy(username
,getenv("USER"));
4336 if (*username
== 0 && getenv("LOGNAME"))
4338 strcpy(username
,getenv("LOGNAME"));
4348 if (*argv
[1] != '-')
4351 strcpy(service
,argv
[1]);
4355 if (count_chars(service
,'\\') < 3)
4358 printf("\n%s: Not enough '\\' characters in service\n",service
);
4363 if (count_chars(service,'\\') > 3)
4366 printf("\n%s: Too many '\\' characters in service\n",service);
4371 if (argc
> 1 && (*argv
[1] != '-'))
4374 strcpy(password
,argv
[1]);
4375 memset(argv
[1],'X',strlen(argv
[1]));
4382 setup_term_code (KANJI
);
4385 getopt(argc
, argv
,"s:B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF
)
4389 max_protocol
= interpret_protocol(optarg
,max_protocol
);
4392 strcpy(user_socket_options
,optarg
);
4396 strcpy(desthost
,optarg
);
4401 iface_set_default(NULL
,optarg
,NULL
);
4404 strcpy(base_directory
,optarg
);
4407 if (!tar_parseargs(argc
, argv
, optarg
, optind
)) {
4413 strcpy(scope
,optarg
);
4417 strcpy(query_host
,optarg
);
4422 strcpy(username
,optarg
);
4423 if ((p
=strchr(username
,'%')))
4426 strcpy(password
,p
+1);
4428 memset(strchr(optarg
,'%')+1,'X',strlen(password
));
4434 strcpy(workgroup
,optarg
);
4441 dest_ip
= *interpret_addr2(optarg
);
4442 if (zero_ip(dest_ip
)) exit(1);
4447 strcpy(myname
,optarg
);
4453 connect_as_printer
= True
;
4459 DEBUGLEVEL
= atoi(optarg
);
4462 sprintf(debugf
,"%s.client",optarg
);
4465 port
= atoi(optarg
);
4476 strcpy(servicesf
, optarg
);
4480 if (!setup_term_code (optarg
)) {
4481 DEBUG(0, ("%s: unknown terminal code name\n", optarg
));
4492 if (!tar_type
&& !*query_host
&& !*service
&& !message
)
4499 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION
));
4501 if (!lp_load(servicesf
,True
)) {
4502 fprintf(stderr
, "Can't load %s - run testparm to debug it\n", servicesf
);
4507 get_myname(*myname
?NULL
:myname
,NULL
);
4513 if (open_sockets(port
)) {
4514 char *InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
4515 char *OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
4518 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
4521 bzero(OutBuffer
,smb_size
);
4522 if (!send_login(InBuffer
,OutBuffer
,True
,True
))
4525 if (*base_directory
) do_cd(base_directory
);
4527 ret
=process_tar(InBuffer
, OutBuffer
);
4539 sprintf(service
,"\\\\%s\\IPC$",query_host
);
4541 connect_as_ipc
= True
;
4542 if (open_sockets(port
))
4547 if (!send_login(NULL
,NULL
,True
,True
))
4551 if (!browse_host(True
)) {
4555 if (!list_servers(workgroup
)) {
4557 list_servers(workgroup
);
4570 if (open_sockets(port
))
4572 pstring inbuf
,outbuf
;
4573 bzero(outbuf
,smb_size
);
4574 if (!send_session_request(inbuf
,outbuf
))
4577 send_message(inbuf
,outbuf
);
4585 if (open_sockets(port
))
4587 if (!process(base_directory
))
4601 /* error code stuff - put together by Merik Karman
4602 merik@blackadder.dsh.oz.au */
4611 /* Dos Error Messages */
4612 err_code_struct dos_msgs
[] = {
4613 {"ERRbadfunc",1,"Invalid function."},
4614 {"ERRbadfile",2,"File not found."},
4615 {"ERRbadpath",3,"Directory invalid."},
4616 {"ERRnofids",4,"No file descriptors available"},
4617 {"ERRnoaccess",5,"Access denied."},
4618 {"ERRbadfid",6,"Invalid file handle."},
4619 {"ERRbadmcb",7,"Memory control blocks destroyed."},
4620 {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
4621 {"ERRbadmem",9,"Invalid memory block address."},
4622 {"ERRbadenv",10,"Invalid environment."},
4623 {"ERRbadformat",11,"Invalid format."},
4624 {"ERRbadaccess",12,"Invalid open mode."},
4625 {"ERRbaddata",13,"Invalid data."},
4626 {"ERR",14,"reserved."},
4627 {"ERRbaddrive",15,"Invalid drive specified."},
4628 {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
4629 {"ERRdiffdevice",17,"Not same device."},
4630 {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
4631 {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
4632 {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
4633 {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
4634 {"ERRbadpipe",230,"Pipe invalid."},
4635 {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
4636 {"ERRpipeclosing",232,"Pipe close in progress."},
4637 {"ERRnotconnected",233,"No process on other end of pipe."},
4638 {"ERRmoredata",234,"There is more data to be returned."},
4639 {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
4642 /* Server Error Messages */
4643 err_code_struct server_msgs
[] = {
4644 {"ERRerror",1,"Non-specific error code."},
4645 {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
4646 {"ERRbadtype",3,"reserved."},
4647 {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
4648 {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
4649 {"ERRinvnetname",6,"Invalid network name in tree connect."},
4650 {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
4651 {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
4652 {"ERRqtoobig",50,"Print queue full -- no space."},
4653 {"ERRqeof",51,"EOF on print queue dump."},
4654 {"ERRinvpfid",52,"Invalid print file FID."},
4655 {"ERRsmbcmd",64,"The server did not recognize the command received."},
4656 {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
4657 {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
4658 {"ERRreserved",68,"reserved."},
4659 {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
4660 {"ERRreserved",70,"reserved."},
4661 {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
4662 {"ERRpaused",81,"Server is paused."},
4663 {"ERRmsgoff",82,"Not receiving messages."},
4664 {"ERRnoroom",83,"No room to buffer message."},
4665 {"ERRrmuns",87,"Too many remote user names."},
4666 {"ERRtimeout",88,"Operation timed out."},
4667 {"ERRnoresource",89,"No resources currently available for request."},
4668 {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
4669 {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
4670 {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
4671 {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
4672 {"ERRcontmpx",252,"Continue in MPX mode."},
4673 {"ERRreserved",253,"reserved."},
4674 {"ERRreserved",254,"reserved."},
4675 {"ERRnosupport",0xFFFF,"Function not supported."},
4678 /* Hard Error Messages */
4679 err_code_struct hard_msgs
[] = {
4680 {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
4681 {"ERRbadunit",20,"Unknown unit."},
4682 {"ERRnotready",21,"Drive not ready."},
4683 {"ERRbadcmd",22,"Unknown command."},
4684 {"ERRdata",23,"Data error (CRC)."},
4685 {"ERRbadreq",24,"Bad request structure length."},
4686 {"ERRseek",25 ,"Seek error."},
4687 {"ERRbadmedia",26,"Unknown media type."},
4688 {"ERRbadsector",27,"Sector not found."},
4689 {"ERRnopaper",28,"Printer out of paper."},
4690 {"ERRwrite",29,"Write fault."},
4691 {"ERRread",30,"Read fault."},
4692 {"ERRgeneral",31,"General failure."},
4693 {"ERRbadshare",32,"A open conflicts with an existing open."},
4694 {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
4695 {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
4696 {"ERRFCBUnavail",35,"No FCBs are available to process request."},
4697 {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
4705 err_code_struct
*err_msgs
;
4708 {0x01,"ERRDOS",dos_msgs
},
4709 {0x02,"ERRSRV",server_msgs
},
4710 {0x03,"ERRHRD",hard_msgs
},
4711 {0x04,"ERRXOS",NULL
},
4712 {0xE1,"ERRRMX1",NULL
},
4713 {0xE2,"ERRRMX2",NULL
},
4714 {0xE3,"ERRRMX3",NULL
},
4715 {0xFF,"ERRCMD",NULL
},
4719 /****************************************************************************
4720 return a SMB error string from a SMB buffer
4721 ****************************************************************************/
4722 char *smb_errstr(char *inbuf
)
4725 int class = CVAL(inbuf
,smb_rcls
);
4726 int num
= SVAL(inbuf
,smb_err
);
4729 for (i
=0;err_classes
[i
].class;i
++)
4730 if (err_classes
[i
].code
== class)
4732 if (err_classes
[i
].err_msgs
)
4734 err_code_struct
*err
= err_classes
[i
].err_msgs
;
4735 for (j
=0;err
[j
].name
;j
++)
4736 if (num
== err
[j
].code
)
4739 sprintf(ret
,"%s - %s (%s)",err_classes
[i
].class,
4740 err
[j
].name
,err
[j
].message
);
4742 sprintf(ret
,"%s - %s",err_classes
[i
].class,err
[j
].name
);
4747 sprintf(ret
,"%s - %d",err_classes
[i
].class,num
);
4751 sprintf(ret
,"ERROR: Unknown error (%d,%d)",class,num
);