2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1997
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 = "";
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 >= 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(1,("(%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,"%s/smbmore.%d",tmpdir(),(int)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(1,("(%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,"%s/ls.smb.%d",tmpdir(),(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 /****************************************************************************
2455 show a print queue - this is deprecated as it uses the old smb that
2456 has limited support - the correct call is the cmd_p_queue_4() after this.
2457 ****************************************************************************/
2458 static void cmd_queue(char *inbuf,char *outbuf )
2463 bzero(outbuf,smb_size);
2464 set_message(outbuf,2,0,True);
2466 CVAL(outbuf,smb_com) = SMBsplretq;
2467 SSVAL(outbuf,smb_tid,cnum);
2470 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2471 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2473 send_smb(Client,outbuf);
2474 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2476 if (CVAL(inbuf,smb_rcls) != 0)
2478 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2482 count = SVAL(inbuf,smb_vwv0);
2483 p = smb_buf(inbuf) + 3;
2486 DEBUG(0,("No entries in the print queue\n"));
2493 DEBUG(0,("Job Name Size Status\n"));
2499 case 0x01: sprintf(status,"held or stopped"); break;
2500 case 0x02: sprintf(status,"printing"); break;
2501 case 0x03: sprintf(status,"awaiting print"); break;
2502 case 0x04: sprintf(status,"in intercept"); break;
2503 case 0x05: sprintf(status,"file had error"); break;
2504 case 0x06: sprintf(status,"printer error"); break;
2505 default: sprintf(status,"unknown"); break;
2508 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2509 SVAL(p,5),p+12,IVAL(p,7),status));
2517 /****************************************************************************
2518 show information about a print queue
2519 ****************************************************************************/
2520 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2522 char *rparam = NULL;
2529 if (!connect_as_printer)
2531 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2532 DEBUG(0,("Trying to print without -P may fail\n"));
2535 bzero(param,sizeof(param));
2538 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2540 strcpy(p,"zWrLeh"); /* parameter description? */
2541 p = skip_string(p,1);
2542 strcpy(p,"WWzWWDDzz"); /* returned data format */
2543 p = skip_string(p,1);
2544 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2545 p = skip_string(p,1);
2546 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2547 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2549 strcpy(p,""); /* subformat */
2550 p = skip_string(p,1);
2552 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2553 if( call_api(PTR_DIFF(p,param), 0,
2560 result_code = SVAL(rparam,0);
2561 converter = SVAL(rparam,2); /* conversion factor */
2563 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2565 if (result_code == 0) /* if no error, */
2575 char PrinterName[20];
2577 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2578 strlower(PrinterName); /* in lower case */
2580 p = rdata; /* received data */
2581 for( i = 0; i < SVAL(rparam,4); ++i)
2584 Priority = SVAL(p,2);
2585 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2587 Priority = SVAL(p,2);
2588 JobTime = make_unix_date3( p + 12);
2589 JobTimeStr = asctime(LocalTime( &JobTime));
2591 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2594 printf("%s-%u %s priority %u %s %s %u bytes\n",
2595 PrinterName, JobId, UserName,
2596 Priority, JobTimeStr, JobName, Size);
2598 #if 0 /* DEBUG code */
2599 printf("Job Id: \"%u\"\n", SVAL(p,0));
2600 printf("Priority: \"%u\"\n", SVAL(p,2));
2602 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2603 printf("Position: \"%u\"\n", SVAL(p,8));
2604 printf("Status: \"%u\"\n", SVAL(p,10));
2606 JobTime = make_unix_date3( p + 12);
2607 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2608 printf("date: \"%u\"\n", SVAL(p,12));
2610 printf("Size: \"%u\"\n", SVAL(p,16));
2611 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2612 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2613 #endif /* DEBUG CODE */
2618 else /* call_api() failed */
2620 printf("Failed, error = %d\n", result_code);
2623 /* If any parameters or data were returned, free the storage. */
2624 if(rparam) free(rparam);
2625 if(rdata) free(rdata);
2630 /****************************************************************************
2631 show information about a print queue
2632 ****************************************************************************/
2633 static void cmd_qinfo(char *inbuf,char *outbuf )
2635 char *rparam = NULL;
2642 bzero(param,sizeof(param));
2645 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2647 strcpy(p,"zWrLh"); /* parameter description? */
2648 p = skip_string(p,1);
2649 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2650 p = skip_string(p,1);
2651 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2652 p = skip_string(p,1);
2653 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2654 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2656 strcpy(p,""); /* subformat */
2657 p = skip_string(p,1);
2659 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2660 if( call_api(PTR_DIFF(p,param), 0,
2667 result_code = SVAL(rparam,0);
2668 converter = SVAL(rparam,2); /* conversion factor */
2670 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2672 if (result_code == 0) /* if no error, */
2674 p = rdata; /* received data */
2676 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2677 printf("Priority: %u\n", SVAL(p,4) );
2678 printf("Start time: %u\n", SVAL(p,6) );
2679 printf("Until time: %u\n", SVAL(p,8) );
2680 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2681 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2682 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2683 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2684 printf("Status: %u\n", SVAL(p,28) );
2685 printf("Jobs: %u\n", SVAL(p,30) );
2686 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2687 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2689 /* Dump the driver data */
2694 ddptr = rdata + SVAL(p,40) - converter;
2695 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2696 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2698 for(x=8; x < count; x+=16)
2700 for(y=0; y < 16; y++)
2703 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2707 for(y=0; y < 16 && (x+y) < count; y++)
2709 c = CVAL(ddptr,(x+y));
2715 fputc('\n', stdout);
2721 else /* call_api() failed */
2723 printf("Failed, error = %d\n", result_code);
2726 /* If any parameters or data were returned, free the storage. */
2727 if(rparam) free(rparam);
2728 if(rdata) free(rdata);
2733 /****************************************************************************
2735 ****************************************************************************/
2736 static void do_del(file_info *finfo)
2739 char *inbuf,*outbuf;
2742 strcpy(mask,cur_dir);
2743 strcat(mask,finfo->name);
2745 if (finfo->mode & aDIR)
2748 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2749 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2751 if (!inbuf || !outbuf)
2753 DEBUG(0,("out of memory\n"));
2757 bzero(outbuf,smb_size);
2758 set_message(outbuf,1,2 + strlen(mask),True);
2760 CVAL(outbuf,smb_com) = SMBunlink;
2761 SSVAL(outbuf,smb_tid,cnum);
2764 SSVAL(outbuf,smb_vwv0,0);
2766 p = smb_buf(outbuf);
2770 send_smb(Client,outbuf);
2771 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2773 if (CVAL(inbuf,smb_rcls) != 0)
2774 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2776 free(inbuf);free(outbuf);
2780 /****************************************************************************
2782 ****************************************************************************/
2783 static void cmd_del(char *inbuf,char *outbuf )
2787 int attribute = aSYSTEM | aHIDDEN;
2792 strcpy(mask,cur_dir);
2794 if (!next_token(NULL,buf,NULL))
2796 DEBUG(0,("del <filename>\n"));
2801 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2805 /****************************************************************************
2807 ****************************************************************************/
2808 static void cmd_rmdir(char *inbuf,char *outbuf )
2814 strcpy(mask,cur_dir);
2816 if (!next_token(NULL,buf,NULL))
2818 DEBUG(0,("rmdir <dirname>\n"));
2823 bzero(outbuf,smb_size);
2824 set_message(outbuf,0,2 + strlen(mask),True);
2826 CVAL(outbuf,smb_com) = SMBrmdir;
2827 SSVAL(outbuf,smb_tid,cnum);
2831 p = smb_buf(outbuf);
2835 send_smb(Client,outbuf);
2836 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2838 if (CVAL(inbuf,smb_rcls) != 0)
2840 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2846 /****************************************************************************
2848 ****************************************************************************/
2849 static void cmd_rename(char *inbuf,char *outbuf )
2855 strcpy(src,cur_dir);
2856 strcpy(dest,cur_dir);
2858 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2860 DEBUG(0,("rename <src> <dest>\n"));
2866 bzero(outbuf,smb_size);
2867 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2869 CVAL(outbuf,smb_com) = SMBmv;
2870 SSVAL(outbuf,smb_tid,cnum);
2871 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2874 p = smb_buf(outbuf);
2877 p = skip_string(p,1);
2881 send_smb(Client,outbuf);
2882 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2884 if (CVAL(inbuf,smb_rcls) != 0)
2886 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2893 /****************************************************************************
2894 toggle the prompt flag
2895 ****************************************************************************/
2896 static void cmd_prompt(void)
2899 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2903 /****************************************************************************
2904 set the newer than time
2905 ****************************************************************************/
2906 static void cmd_newer(void)
2912 ok = next_token(NULL,buf,NULL);
2913 if (ok && (sys_stat(buf,&sbuf) == 0))
2915 newer_than = sbuf.st_mtime;
2916 DEBUG(1,("Getting files newer than %s",
2917 asctime(LocalTime(&newer_than))));
2922 if (ok && newer_than == 0)
2923 DEBUG(0,("Error setting newer-than time\n"));
2926 /****************************************************************************
2927 set the archive level
2928 ****************************************************************************/
2929 static void cmd_archive(void)
2933 if (next_token(NULL,buf,NULL)) {
2934 archive_level = atoi(buf);
2936 DEBUG(0,("Archive level is %d\n",archive_level));
2939 /****************************************************************************
2940 toggle the lowercaseflag
2941 ****************************************************************************/
2942 static void cmd_lowercase(void)
2944 lowercase = !lowercase;
2945 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2951 /****************************************************************************
2952 toggle the recurse flag
2953 ****************************************************************************/
2954 static void cmd_recurse(void)
2957 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2960 /****************************************************************************
2961 toggle the translate flag
2962 ****************************************************************************/
2963 static void cmd_translate(void)
2965 translation = !translation;
2966 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2967 translation?"on":"off"));
2971 /****************************************************************************
2972 do a printmode command
2973 ****************************************************************************/
2974 static void cmd_printmode(void)
2979 if (next_token(NULL,buf,NULL))
2981 if (strequal(buf,"text"))
2985 if (strequal(buf,"graphics"))
2988 printmode = atoi(buf);
2995 strcpy(mode,"text");
2998 strcpy(mode,"graphics");
3001 sprintf(mode,"%d",printmode);
3005 DEBUG(2,("the printmode is now %s\n",mode));
3008 /****************************************************************************
3010 ****************************************************************************/
3011 static void cmd_lcd(void)
3016 if (next_token(NULL,buf,NULL))
3018 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
3022 /****************************************************************************
3023 send a session request
3024 ****************************************************************************/
3025 static BOOL send_session_request(char *inbuf,char *outbuf)
3030 /* send a session request (RFC 8002) */
3032 strcpy(dest,desthost);
3033 p = strchr(dest,'.');
3036 /* put in the destination name */
3038 name_mangle(dest,p,name_type); /* 0x20 is the SMB server NetBIOS type. */
3043 name_mangle(myname,p,0);
3046 /* setup the packet length */
3047 _smb_setlen(outbuf,len);
3048 CVAL(outbuf,0) = 0x81;
3050 send_smb(Client,outbuf);
3051 DEBUG(5,("Sent session request\n"));
3053 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3055 if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */
3057 /* For information, here is the response structure.
3058 * We do the byte-twiddling to for portability.
3059 struct RetargetResponse{
3061 unsigned char flags;
3068 int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
3069 /* SESSION RETARGET */
3070 putip((char *)&dest_ip,inbuf+4);
3073 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
3077 DEBUG(3,("Retargeted\n"));
3079 set_socket_options(Client,user_socket_options);
3082 return send_session_request(inbuf,outbuf);
3083 } /* C. Hoch 9/14/95 End */
3086 if (CVAL(inbuf,0) != 0x82)
3088 int ecode = CVAL(inbuf,4);
3089 DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
3090 CVAL(inbuf,0),ecode,myname,desthost));
3094 DEBUG(0,("Not listening on called name\n"));
3095 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
3096 DEBUG(0,("You may find the -I option useful for this\n"));
3099 DEBUG(0,("Not listening for calling name\n"));
3100 DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
3101 DEBUG(0,("You may find the -n option useful for this\n"));
3104 DEBUG(0,("Called name not present\n"));
3105 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
3106 DEBUG(0,("You may find the -I option useful for this\n"));
3109 DEBUG(0,("Called name present, but insufficient resources\n"));
3110 DEBUG(0,("Perhaps you should try again later?\n"));
3113 DEBUG(0,("Unspecified error 0x%X\n",ecode));
3114 DEBUG(0,("Your server software is being unfriendly\n"));
3126 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
3127 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
3128 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
3129 {PROTOCOL_LANMAN1,"LANMAN1.0"},
3130 {PROTOCOL_LANMAN2,"LM1.2X002"},
3131 {PROTOCOL_LANMAN2,"Samba"},
3132 {PROTOCOL_NT1,"NT LM 0.12"},
3133 {PROTOCOL_NT1,"NT LANMAN 1.0"},
3138 /****************************************************************************
3139 send a login command
3140 ****************************************************************************/
3141 static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
3143 BOOL was_null = (!inbuf && !outbuf);
3145 time_t servertime = 0;
3146 extern int serverzone;
3158 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3159 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3163 if (strstr(service,"IPC$")) connect_as_ipc = True;
3167 if (connect_as_printer)
3168 strcpy(dev,"LPT1:");
3173 if (start_session && !send_session_request(inbuf,outbuf))
3183 bzero(outbuf,smb_size);
3185 /* setup the protocol strings */
3189 for (plength=0,numprots=0;
3190 prots[numprots].name && prots[numprots].prot<=max_protocol;
3192 plength += strlen(prots[numprots].name)+2;
3194 set_message(outbuf,0,plength,True);
3196 p = smb_buf(outbuf);
3198 prots[numprots].name && prots[numprots].prot<=max_protocol;
3202 strcpy(p,prots[numprots].name);
3207 CVAL(outbuf,smb_com) = SMBnegprot;
3210 CVAL(smb_buf(outbuf),0) = 2;
3212 send_smb(Client,outbuf);
3213 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3217 if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
3219 DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
3220 myname,desthost,smb_errstr(inbuf)));
3229 Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
3232 if (Protocol < PROTOCOL_NT1) {
3233 sec_mode = SVAL(inbuf,smb_vwv1);
3234 max_xmit = SVAL(inbuf,smb_vwv2);
3235 sesskey = IVAL(inbuf,smb_vwv6);
3236 serverzone = SVALS(inbuf,smb_vwv10)*60;
3237 /* this time is converted to GMT by make_unix_date */
3238 servertime = make_unix_date(inbuf+smb_vwv8);
3239 if (Protocol >= PROTOCOL_COREPLUS) {
3240 readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
3241 writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
3243 crypt_len = smb_buflen(inbuf);
3244 memcpy(cryptkey,smb_buf(inbuf),8);
3245 DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
3246 max_vcs = SVAL(inbuf,smb_vwv4);
3247 DEBUG(3,("max vcs %d\n",max_vcs));
3248 DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
3251 sec_mode = CVAL(inbuf,smb_vwv1);
3252 max_xmit = IVAL(inbuf,smb_vwv3+1);
3253 sesskey = IVAL(inbuf,smb_vwv7+1);
3254 serverzone = SVALS(inbuf,smb_vwv15+1)*60;
3255 /* this time arrives in real GMT */
3256 servertime = interpret_long_date(inbuf+smb_vwv11+1);
3257 crypt_len = CVAL(inbuf,smb_vwv16+1);
3258 memcpy(cryptkey,smb_buf(inbuf),8);
3259 if (IVAL(inbuf,smb_vwv9+1) & 1)
3260 readbraw_supported = writebraw_supported = True;
3261 DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
3262 max_vcs = SVAL(inbuf,smb_vwv2+1);
3263 DEBUG(3,("max vcs %d\n",max_vcs));
3264 DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
3265 DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
3268 DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
3269 DEBUG(3,("max xmt %d\n",max_xmit));
3270 DEBUG(3,("Got %d byte crypt key\n",crypt_len));
3271 DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
3273 doencrypt = ((sec_mode & 2) != 0);
3276 static BOOL done_time = False;
3278 DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
3279 asctime(LocalTime(&servertime)),
3280 -(double)(serverzone/3600.0)));
3290 pass = (char *)getpass("Password: ");
3292 /* use a blank username for the 2nd try with a blank password */
3293 if (tries++ && !*pass)
3296 if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
3299 int passlen = strlen(pass)+1;
3303 if (doencrypt && *pass) {
3304 DEBUG(3,("Using encrypted passwords\n"));
3306 SMBencrypt(pass,cryptkey,pword);
3312 /* if in share level security then don't send a password now */
3313 if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;}
3315 /* send a session setup command */
3316 bzero(outbuf,smb_size);
3318 if (Protocol < PROTOCOL_NT1) {
3319 set_message(outbuf,10,1 + strlen(username) + passlen,True);
3320 CVAL(outbuf,smb_com) = SMBsesssetupX;
3323 CVAL(outbuf,smb_vwv0) = 0xFF;
3324 SSVAL(outbuf,smb_vwv2,max_xmit);
3325 SSVAL(outbuf,smb_vwv3,2);
3326 SSVAL(outbuf,smb_vwv4,max_vcs-1);
3327 SIVAL(outbuf,smb_vwv5,sesskey);
3328 SSVAL(outbuf,smb_vwv7,passlen);
3329 p = smb_buf(outbuf);
3330 memcpy(p,pword,passlen);
3334 if (!doencrypt) passlen--;
3336 set_message(outbuf,13,0,True);
3337 CVAL(outbuf,smb_com) = SMBsesssetupX;
3340 CVAL(outbuf,smb_vwv0) = 0xFF;
3341 SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
3342 SSVAL(outbuf,smb_vwv3,2);
3343 SSVAL(outbuf,smb_vwv4,getpid());
3344 SIVAL(outbuf,smb_vwv5,sesskey);
3345 SSVAL(outbuf,smb_vwv7,passlen);
3346 SSVAL(outbuf,smb_vwv8,0);
3347 p = smb_buf(outbuf);
3348 memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
3349 strcpy(p,username);p = skip_string(p,1);
3350 strcpy(p,workgroup);p = skip_string(p,1);
3351 strcpy(p,"Unix");p = skip_string(p,1);
3352 strcpy(p,"Samba");p = skip_string(p,1);
3353 set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
3356 send_smb(Client,outbuf);
3357 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3361 if (CVAL(inbuf,smb_rcls) != 0)
3364 ((CVAL(inbuf,smb_rcls) == ERRDOS &&
3365 SVAL(inbuf,smb_err) == ERRnoaccess) ||
3366 (CVAL(inbuf,smb_rcls) == ERRSRV &&
3367 SVAL(inbuf,smb_err) == ERRbadpw)))
3370 DEBUG(3,("resending login\n"));
3374 DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n",
3375 username,myname,desthost,smb_errstr(inbuf)));
3376 DEBUG(0,("You might find the -U, -W or -n options useful\n"));
3377 DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
3378 DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
3387 if (Protocol >= PROTOCOL_NT1) {
3388 char *domain,*os,*lanman;
3391 lanman = skip_string(os,1);
3392 domain = skip_string(lanman,1);
3393 if (*domain || *os || *lanman)
3394 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
3397 /* use the returned uid from now on */
3398 if (SVAL(inbuf,smb_uid) != uid)
3399 DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
3400 SVAL(inbuf,smb_uid),uid));
3401 uid = SVAL(inbuf,smb_uid);
3404 /* now we've got a connection - send a tcon message */
3405 bzero(outbuf,smb_size);
3407 if (strncmp(service,"\\\\",2) != 0)
3409 DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
3410 DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
3417 int passlen = strlen(pass)+1;
3422 if (doencrypt && *pass) {
3424 SMBencrypt(pass,cryptkey,pword);
3428 /* if in user level security then don't send a password now */
3429 if ((sec_mode & 1)) {
3430 strcpy(pword, ""); passlen=1;
3433 if (Protocol <= PROTOCOL_COREPLUS) {
3434 set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
3435 CVAL(outbuf,smb_com) = SMBtcon;
3438 p = smb_buf(outbuf);
3441 p = skip_string(p,1);
3443 memcpy(p,pword,passlen);
3449 set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
3450 CVAL(outbuf,smb_com) = SMBtconX;
3453 SSVAL(outbuf,smb_vwv0,0xFF);
3454 SSVAL(outbuf,smb_vwv3,passlen);
3456 p = smb_buf(outbuf);
3457 memcpy(p,pword,passlen);
3460 p = skip_string(p,1);
3465 send_smb(Client,outbuf);
3466 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3468 /* trying again with a blank password */
3469 if (CVAL(inbuf,smb_rcls) != 0 &&
3470 (int)strlen(pass) > 0 &&
3472 Protocol >= PROTOCOL_LANMAN1)
3474 DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
3479 if (CVAL(inbuf,smb_rcls) != 0)
3481 DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
3482 DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
3483 DEBUG(0,("Some servers insist that these be in uppercase\n"));
3493 if (Protocol <= PROTOCOL_COREPLUS) {
3494 max_xmit = SVAL(inbuf,smb_vwv0);
3496 cnum = SVAL(inbuf,smb_vwv1);
3499 max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
3501 max_xmit = BUFFER_SIZE - 4;
3503 cnum = SVAL(inbuf,smb_tid);
3506 DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
3517 /****************************************************************************
3518 send a logout command
3519 ****************************************************************************/
3520 static void send_logout(void )
3522 pstring inbuf,outbuf;
3524 bzero(outbuf,smb_size);
3525 set_message(outbuf,0,0,True);
3526 CVAL(outbuf,smb_com) = SMBtdis;
3527 SSVAL(outbuf,smb_tid,cnum);
3530 send_smb(Client,outbuf);
3531 receive_smb(Client,inbuf,SHORT_TIMEOUT);
3533 if (CVAL(inbuf,smb_rcls) != 0)
3535 DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
3547 /****************************************************************************
3549 ****************************************************************************/
3550 static BOOL call_api(int prcnt,int drcnt,
3551 int mprcnt,int mdrcnt,
3552 int *rprcnt,int *rdrcnt,
3553 char *param,char *data,
3554 char **rparam,char **rdata)
3556 static char *inbuf=NULL;
3557 static char *outbuf=NULL;
3559 if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3560 if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3562 send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
3567 return (receive_trans_response(inbuf,SMBtrans,
3572 /****************************************************************************
3573 send a SMB trans or trans2 request
3574 ****************************************************************************/
3575 static BOOL send_trans_request(char *outbuf,int trans,
3576 char *name,int fid,int flags,
3577 char *data,char *param,uint16 *setup,
3578 int ldata,int lparam,int lsetup,
3579 int mdata,int mparam,int msetup)
3582 int this_ldata,this_lparam;
3583 int tot_data=0,tot_param=0;
3584 char *outdata,*outparam;
3588 this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
3589 this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
3591 bzero(outbuf,smb_size);
3592 set_message(outbuf,14+lsetup,0,True);
3593 CVAL(outbuf,smb_com) = trans;
3594 SSVAL(outbuf,smb_tid,cnum);
3597 outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
3598 outdata = outparam+this_lparam;
3600 /* primary request */
3601 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3602 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3603 SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */
3604 SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */
3605 SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */
3606 SSVAL(outbuf,smb_flags,flags); /* flags */
3607 SIVAL(outbuf,smb_timeout,0); /* timeout */
3608 SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
3609 SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
3610 SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */
3611 SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
3612 SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */
3613 for (i=0;i<lsetup;i++) /* setup[] */
3614 SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
3615 p = smb_buf(outbuf);
3616 if (trans==SMBtrans)
3617 strcpy(p,name); /* name[] */
3620 *p++ = 0; /* put in a null smb_name */
3621 *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */
3623 if (this_lparam) /* param[] */
3624 memcpy(outparam,param,this_lparam);
3625 if (this_ldata) /* data[] */
3626 memcpy(outdata,data,this_ldata);
3627 set_message(outbuf,14+lsetup, /* wcnt, bcc */
3628 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3631 send_smb(Client,outbuf);
3633 if (this_ldata < ldata || this_lparam < lparam)
3635 /* receive interim response */
3636 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
3638 DEBUG(0,("%s request failed (%s)\n",
3639 trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
3643 tot_data = this_ldata;
3644 tot_param = this_lparam;
3646 while (tot_data < ldata || tot_param < lparam)
3648 this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
3649 this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
3651 set_message(outbuf,trans==SMBtrans?8:9,0,True);
3652 CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
3654 outparam = smb_buf(outbuf);
3655 outdata = outparam+this_lparam;
3657 /* secondary request */
3658 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3659 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3660 SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
3661 SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
3662 SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */
3663 SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */
3664 SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
3665 SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */
3666 if (trans==SMBtrans2)
3667 SSVAL(outbuf,smb_sfid,fid); /* fid */
3668 if (this_lparam) /* param[] */
3669 memcpy(outparam,param,this_lparam);
3670 if (this_ldata) /* data[] */
3671 memcpy(outdata,data,this_ldata);
3672 set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
3673 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3676 send_smb(Client,outbuf);
3678 tot_data += this_ldata;
3679 tot_param += this_lparam;
3686 /****************************************************************************
3687 try and browse available connections on a host
3688 ****************************************************************************/
3689 static BOOL browse_host(BOOL sort)
3692 #define strcasecmp StrCaseCmp
3694 extern int strcasecmp();
3696 char *rparam = NULL;
3703 /* now send a SMBtrans command with api RNetShareEnum */
3705 SSVAL(p,0,0); /* api number */
3708 p = skip_string(p,1);
3710 p = skip_string(p,1);
3712 SSVAL(p,2,BUFFER_SIZE);
3715 if (call_api(PTR_DIFF(p,param),0,
3721 int res = SVAL(rparam,0);
3722 int converter=SVAL(rparam,2);
3724 BOOL long_share_name=False;
3728 count=SVAL(rparam,4);
3733 printf("\n\tSharename Type Comment\n");
3734 printf("\t--------- ---- -------\n");
3738 qsort(p,count,20,QSORT_CAST strcasecmp);
3740 for (i=0;i<count;i++)
3743 int type = SVAL(p,14);
3744 int comment_offset = IVAL(p,16) & 0xFFFF;
3750 case STYPE_DISKTREE:
3751 strcpy(typestr,"Disk"); break;
3753 strcpy(typestr,"Printer"); break;
3755 strcpy(typestr,"Device"); break;
3757 strcpy(typestr,"IPC"); break;
3760 printf("\t%-15.15s%-10.10s%s\n",
3763 comment_offset?rdata+comment_offset-converter:"");
3765 if (strlen(sname)>8) long_share_name=True;
3770 if (long_share_name) {
3771 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3776 if (rparam) free(rparam);
3777 if (rdata) free(rdata);
3783 /****************************************************************************
3784 get some server info
3785 ****************************************************************************/
3786 static void server_info()
3788 char *rparam = NULL;
3794 bzero(param,sizeof(param));
3797 SSVAL(p,0,63); /* NetServerGetInfo()? */
3800 p = skip_string(p,1);
3801 strcpy(p,"zzzBBzz");
3802 p = skip_string(p,1);
3803 SSVAL(p,0,10); /* level 10 */
3807 if (call_api(PTR_DIFF(p,param),0,
3813 int res = SVAL(rparam,0);
3814 int converter=SVAL(rparam,2);
3820 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3821 rdata+SVAL(p,0)-converter,
3822 rdata+SVAL(p,4)-converter,
3823 rdata+SVAL(p,8)-converter,
3824 rdata+SVAL(p,14)-converter);
3828 if (rparam) free(rparam);
3829 if (rdata) free(rdata);
3835 /****************************************************************************
3836 try and browse available connections on a host
3837 ****************************************************************************/
3838 static BOOL list_servers(char *wk_grp)
3840 char *rparam = NULL;
3848 BOOL generic_request = False;
3851 if (strequal(wk_grp,"WORKGROUP")) {
3852 /* we won't specify a workgroup */
3853 generic_request = True;
3856 /* now send a SMBtrans command with api ServerEnum? */
3858 SSVAL(p,0,0x68); /* api number */
3861 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3862 p = skip_string(p,1);
3864 strcpy(p,"B16BBDz");
3866 p = skip_string(p,1);
3868 SSVAL(p,2,0x2000); /* buf length */
3874 if (!generic_request) {
3876 p = skip_string(p,1);
3879 /* first ask for a list of servers in this workgroup */
3880 SIVAL(svtype_p,0,SV_TYPE_ALL);
3882 if (call_api(PTR_DIFF(p+4,param),0,
3888 int res = SVAL(rparam,0);
3889 int converter=SVAL(rparam,2);
3894 count=SVAL(rparam,4);
3897 printf("\n\nThis machine has a browse list:\n");
3898 printf("\n\tServer Comment\n");
3899 printf("\t--------- -------\n");
3902 for (i=0;i<count;i++) {
3904 int comment_offset = IVAL(p2,22) & 0xFFFF;
3905 printf("\t%-16.16s %s\n",
3907 comment_offset?rdata+comment_offset-converter:"");
3915 if (rparam) {free(rparam); rparam = NULL;}
3916 if (rdata) {free(rdata); rdata = NULL;}
3918 /* now ask for a list of workgroups */
3919 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3921 if (call_api(PTR_DIFF(p+4,param),0,
3927 int res = SVAL(rparam,0);
3928 int converter=SVAL(rparam,2);
3933 count=SVAL(rparam,4);
3936 printf("\n\nThis machine has a workgroup list:\n");
3937 printf("\n\tWorkgroup Master\n");
3938 printf("\t--------- -------\n");
3941 for (i=0;i<count;i++) {
3943 int comment_offset = IVAL(p2,22) & 0xFFFF;
3944 printf("\t%-16.16s %s\n",
3946 comment_offset?rdata+comment_offset-converter:"");
3954 if (rparam) free(rparam);
3955 if (rdata) free(rdata);
3961 /* This defines the commands supported by this client */
3969 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3970 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3971 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3972 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3973 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3974 {"get",cmd_get,"<remote name> [local name] get a file"},
3975 {"mget",cmd_mget,"<mask> get all the matching files"},
3976 {"put",cmd_put,"<local name> [remote name] put a file"},
3977 {"mput",cmd_mput,"<mask> put all matching files"},
3978 {"rename",cmd_rename,"<src> <dest> rename some files"},
3979 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3980 {"mask",cmd_select,"<mask> mask all filenames against this"},
3981 {"del",cmd_del,"<mask> delete all matching files"},
3982 {"rm",cmd_del,"<mask> delete all matching files"},
3983 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3984 {"md",cmd_mkdir,"<directory> make a directory"},
3985 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
3986 {"rd",cmd_rmdir,"<directory> remove a directory"},
3987 {"pq",cmd_p_queue_4,"enumerate the print queue"},
3988 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
3989 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
3990 {"translate",cmd_translate,"toggle text translation for printing"},
3991 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
3992 {"print",cmd_print,"<file name> print a file"},
3993 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
3994 {"queue",cmd_queue,"show the print queue"},
3995 {"qinfo",cmd_qinfo,"show print queue information"},
3996 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
3997 {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
3998 {"quit",send_logout,"logoff the server"},
3999 {"q",send_logout,"logoff the server"},
4000 {"exit",send_logout,"logoff the server"},
4001 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
4002 {"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"},
4003 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
4004 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
4005 {"tarmode",cmd_tarmode,
4006 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
4007 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
4008 {"help",cmd_help,"[command] give help on a command"},
4009 {"?",cmd_help,"[command] give help on a command"},
4010 {"!",NULL,"run a shell command on the local system"},
4015 /*******************************************************************
4016 lookup a command string in the list of commands, including
4018 ******************************************************************/
4019 static int process_tok(fstring tok)
4021 int i = 0, matches = 0;
4023 int tok_len = strlen(tok);
4025 while (commands[i].fn != NULL)
4027 if (strequal(commands[i].name,tok))
4033 else if (strnequal(commands[i].name, tok, tok_len+1))
4043 else if (matches == 1)
4049 /****************************************************************************
4051 ****************************************************************************/
4057 if (next_token(NULL,buf,NULL))
4059 if ((i = process_tok(buf)) >= 0)
4060 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
4063 while (commands[i].description)
4065 for (j=0; commands[i].description && (j<5); j++) {
4066 DEBUG(0,("%-15s",commands[i].name));
4073 /****************************************************************************
4074 open the client sockets
4075 ****************************************************************************/
4076 static BOOL open_sockets(int port )
4078 static int last_port;
4086 if (port == 0) port=last_port;
4097 strcpy(service2,service);
4098 host = strtok(service2,"\\/");
4100 DEBUG(0,("Badly formed host name\n"));
4103 strcpy(desthost,host);
4107 get_myname(myname,NULL);
4111 DEBUG(3,("Opening sockets\n"));
4117 if ((hp = Get_Hostbyname(host))) {
4118 putip((char *)&dest_ip,(char *)hp->h_addr);
4122 /* Try and resolve the name with the netbios server */
4125 if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
4126 interpret_addr(lp_socket_address()))) != -1) {
4127 set_socket_options(bcast, "SO_BROADCAST");
4129 if (name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
4137 DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
4143 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
4147 DEBUG(3,("Connected\n"));
4149 set_socket_options(Client,user_socket_options);
4154 /****************************************************************************
4155 wait for keyboard activity, swallowing network packets
4156 ****************************************************************************/
4158 static char wait_keyboard(char *buffer)
4160 static void wait_keyboard(char *buffer)
4165 struct timeval timeout;
4175 FD_SET(Client,&fds);
4177 FD_SET(fileno(stdin),&fds);
4180 timeout.tv_sec = 20;
4181 timeout.tv_usec = 0;
4185 selrtn = sys_select(&fds,&timeout);
4188 if (FD_ISSET(fileno(stdin),&fds))
4196 f_flags = fcntl(fileno(stdin), F_GETFL, 0);
4197 fcntl( fileno(stdin), F_SETFL, f_flags | O_NONBLOCK);
4198 readret = read_data( fileno(stdin), &ch, 1);
4199 fcntl(fileno(stdin), F_SETFL, f_flags);
4202 if (errno != EAGAIN)
4204 /* should crash here */
4205 DEBUG(1,("readchar stdin failed\n"));
4208 else if (readret != 0)
4214 if (FD_ISSET(Client,&fds))
4215 receive_smb(Client,buffer,0);
4222 chkpath("\\",False);
4225 chkpath("\\",False);
4231 /****************************************************************************
4232 close and open the connection again
4233 ****************************************************************************/
4234 BOOL reopen_connection(char *inbuf,char *outbuf)
4236 static int open_count=0;
4240 if (open_count>5) return(False);
4242 DEBUG(1,("Trying to re-open connection\n"));
4244 set_message(outbuf,0,0,True);
4245 SCVAL(outbuf,smb_com,SMBtdis);
4246 SSVAL(outbuf,smb_tid,cnum);
4249 send_smb(Client,outbuf);
4250 receive_smb(Client,inbuf,SHORT_TIMEOUT);
4253 if (!open_sockets(0)) return(False);
4255 return(send_login(inbuf,outbuf,True,True));
4258 /****************************************************************************
4259 process commands from the client
4260 ****************************************************************************/
4261 static BOOL process(char *base_directory)
4267 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4268 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4270 if ((InBuffer == NULL) || (OutBuffer == NULL))
4273 bzero(OutBuffer,smb_size);
4275 if (!send_login(InBuffer,OutBuffer,True,True))
4278 if (*base_directory) do_cd(base_directory);
4281 if (cmd[0] != '\0') while (cmd[0] != '\0')
4287 if ((p = strchr(cmd, ';')) == 0)
4289 strncpy(line, cmd, 999);
4295 if (p - cmd > 999) p = cmd + 999;
4296 strncpy(line, cmd, p - cmd);
4297 line[p - cmd] = '\0';
4301 /* input language code to internal one */
4304 /* and get the first part of the command */
4307 if (!next_token(&ptr,tok,NULL)) continue;
4310 if ((i = process_tok(tok)) >= 0)
4311 commands[i].fn(InBuffer,OutBuffer);
4313 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4315 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4317 else while (!feof(stdin))
4322 bzero(OutBuffer,smb_size);
4324 /* display a prompt */
4325 DEBUG(1,("smb: %s> ", CNV_LANG(cur_dir)));
4329 line[0] = wait_keyboard(InBuffer);
4330 /* this might not be such a good idea... */
4331 if ( line[0] == EOF)
4334 wait_keyboard(InBuffer);
4337 /* and get a response */
4339 fgets( &line[1],999, stdin);
4341 if (!fgets(line,1000,stdin))
4345 /* input language code to internal one */
4348 /* special case - first char is ! */
4355 /* and get the first part of the command */
4358 if (!next_token(&ptr,tok,NULL)) continue;
4361 if ((i = process_tok(tok)) >= 0)
4362 commands[i].fn(InBuffer,OutBuffer);
4364 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4366 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4374 /****************************************************************************
4375 usage on the program
4376 ****************************************************************************/
4377 static void usage(char *pname)
4379 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
4383 DEBUG(0,("[-t termcode] "));
4386 DEBUG(0,("\nVersion %s\n",VERSION));
4387 DEBUG(0,("\t-p port listen on the specified port\n"));
4388 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
4389 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
4390 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
4391 DEBUG(0,("\t-N don't ask for a password\n"));
4392 DEBUG(0,("\t-P connect to service as a printer\n"));
4393 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
4394 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
4395 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
4396 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
4397 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
4398 DEBUG(0,("\t-U username set the network username\n"));
4399 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
4400 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
4402 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
4404 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
4405 DEBUG(0,("\t-D directory start from directory\n"));
4409 /****************************************************************************
4411 ****************************************************************************/
4412 int main(int argc,char *argv[])
4414 fstring base_directory;
4415 char *pname = argv[0];
4416 int port = SMB_PORT;
4419 extern char *optarg;
4422 BOOL message = False;
4423 extern char tar_type;
4424 static pstring servicesf = CONFIGFILE;
4427 *base_directory = 0;
4431 setup_logging(pname,True);
4434 charset_initialise();
4445 strcpy(username,getenv("USER"));
4449 if (*username == 0 && getenv("LOGNAME"))
4451 strcpy(username,getenv("LOGNAME"));
4461 if (*argv[1] != '-')
4464 strcpy(service,argv[1]);
4465 /* Convert any '/' characters in the service name to '\' characters */
4466 string_replace( service, '/','\\');
4470 if (count_chars(service,'\\') < 3)
4473 printf("\n%s: Not enough '\\' characters in service\n",service);
4478 if (count_chars(service,'\\') > 3)
4481 printf("\n%s: Too many '\\' characters in service\n",service);
4486 if (argc > 1 && (*argv[1] != '-'))
4489 strcpy(password,argv[1]);
4490 memset(argv[1],'X',strlen(argv[1]));
4497 setup_term_code (KANJI);
4500 getopt(argc, argv,"s:B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
4504 max_protocol = interpret_protocol(optarg,max_protocol);
4507 strcpy(user_socket_options,optarg);
4510 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
4511 strcpy(desthost,optarg);
4516 iface_set_default(NULL,optarg,NULL);
4519 strcpy(base_directory,optarg);
4522 if (!tar_parseargs(argc, argv, optarg, optind)) {
4528 strcpy(scope,optarg);
4532 strcpy(query_host,optarg);
4537 strcpy(username,optarg);
4538 if ((p=strchr(username,'%')))
4541 strcpy(password,p+1);
4543 memset(strchr(optarg,'%')+1,'X',strlen(password));
4549 strcpy(workgroup,optarg);
4556 dest_ip = *interpret_addr2(optarg);
4557 if (zero_ip(dest_ip)) exit(1);
4562 strcpy(myname,optarg);
4568 connect_as_printer = True;
4574 DEBUGLEVEL = atoi(optarg);
4577 sprintf(debugf,"%s.client",optarg);
4580 port = atoi(optarg);
4591 strcpy(servicesf, optarg);
4595 if (!setup_term_code (optarg)) {
4596 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
4607 if (!tar_type && !*query_host && !*service && !message)
4614 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
4616 if (!lp_load(servicesf,True)) {
4617 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
4620 if (*workgroup == 0)
4621 strcpy(workgroup,lp_workgroup());
4624 get_myname(*myname?NULL:myname,NULL);
4630 if (open_sockets(port)) {
4631 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4632 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4635 if ((InBuffer == NULL) || (OutBuffer == NULL))
4638 bzero(OutBuffer,smb_size);
4639 if (!send_login(InBuffer,OutBuffer,True,True))
4642 if (*base_directory) do_cd(base_directory);
4644 ret=process_tar(InBuffer, OutBuffer);
4656 sprintf(service,"\\\\%s\\IPC$",query_host);
4658 connect_as_ipc = True;
4659 if (open_sockets(port))
4664 if (!send_login(NULL,NULL,True,True))
4668 if (!browse_host(True)) {
4672 if (!list_servers(workgroup)) {
4674 list_servers(workgroup);
4687 if (open_sockets(port))
4689 pstring inbuf,outbuf;
4690 bzero(outbuf,smb_size);
4691 if (!send_session_request(inbuf,outbuf))
4694 send_message(inbuf,outbuf);
4702 if (open_sockets(port))
4704 if (!process(base_directory))
4718 /* error code stuff - put together by Merik Karman
4719 merik@blackadder.dsh.oz.au */
4728 /* Dos Error Messages */
4729 err_code_struct dos_msgs[] = {
4730 {"ERRbadfunc",1,"Invalid function."},
4731 {"ERRbadfile",2,"File not found."},
4732 {"ERRbadpath",3,"Directory invalid."},
4733 {"ERRnofids",4,"No file descriptors available"},
4734 {"ERRnoaccess",5,"Access denied."},
4735 {"ERRbadfid",6,"Invalid file handle."},
4736 {"ERRbadmcb",7,"Memory control blocks destroyed."},
4737 {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
4738 {"ERRbadmem",9,"Invalid memory block address."},
4739 {"ERRbadenv",10,"Invalid environment."},
4740 {"ERRbadformat",11,"Invalid format."},
4741 {"ERRbadaccess",12,"Invalid open mode."},
4742 {"ERRbaddata",13,"Invalid data."},
4743 {"ERR",14,"reserved."},
4744 {"ERRbaddrive",15,"Invalid drive specified."},
4745 {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
4746 {"ERRdiffdevice",17,"Not same device."},
4747 {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
4748 {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
4749 {"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."},
4750 {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
4751 {"ERRbadpipe",230,"Pipe invalid."},
4752 {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
4753 {"ERRpipeclosing",232,"Pipe close in progress."},
4754 {"ERRnotconnected",233,"No process on other end of pipe."},
4755 {"ERRmoredata",234,"There is more data to be returned."},
4756 {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
4759 /* Server Error Messages */
4760 err_code_struct server_msgs[] = {
4761 {"ERRerror",1,"Non-specific error code."},
4762 {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
4763 {"ERRbadtype",3,"reserved."},
4764 {"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."},
4765 {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
4766 {"ERRinvnetname",6,"Invalid network name in tree connect."},
4767 {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
4768 {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
4769 {"ERRqtoobig",50,"Print queue full -- no space."},
4770 {"ERRqeof",51,"EOF on print queue dump."},
4771 {"ERRinvpfid",52,"Invalid print file FID."},
4772 {"ERRsmbcmd",64,"The server did not recognize the command received."},
4773 {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
4774 {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
4775 {"ERRreserved",68,"reserved."},
4776 {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
4777 {"ERRreserved",70,"reserved."},
4778 {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
4779 {"ERRpaused",81,"Server is paused."},
4780 {"ERRmsgoff",82,"Not receiving messages."},
4781 {"ERRnoroom",83,"No room to buffer message."},
4782 {"ERRrmuns",87,"Too many remote user names."},
4783 {"ERRtimeout",88,"Operation timed out."},
4784 {"ERRnoresource",89,"No resources currently available for request."},
4785 {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
4786 {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
4787 {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
4788 {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
4789 {"ERRcontmpx",252,"Continue in MPX mode."},
4790 {"ERRreserved",253,"reserved."},
4791 {"ERRreserved",254,"reserved."},
4792 {"ERRnosupport",0xFFFF,"Function not supported."},
4795 /* Hard Error Messages */
4796 err_code_struct hard_msgs[] = {
4797 {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
4798 {"ERRbadunit",20,"Unknown unit."},
4799 {"ERRnotready",21,"Drive not ready."},
4800 {"ERRbadcmd",22,"Unknown command."},
4801 {"ERRdata",23,"Data error (CRC)."},
4802 {"ERRbadreq",24,"Bad request structure length."},
4803 {"ERRseek",25 ,"Seek error."},
4804 {"ERRbadmedia",26,"Unknown media type."},
4805 {"ERRbadsector",27,"Sector not found."},
4806 {"ERRnopaper",28,"Printer out of paper."},
4807 {"ERRwrite",29,"Write fault."},
4808 {"ERRread",30,"Read fault."},
4809 {"ERRgeneral",31,"General failure."},
4810 {"ERRbadshare",32,"A open conflicts with an existing open."},
4811 {"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."},
4812 {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
4813 {"ERRFCBUnavail",35,"No FCBs are available to process request."},
4814 {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
4822 err_code_struct *err_msgs;
4825 {0x01,"ERRDOS",dos_msgs},
4826 {0x02,"ERRSRV",server_msgs},
4827 {0x03,"ERRHRD",hard_msgs},
4828 {0x04,"ERRXOS",NULL},
4829 {0xE1,"ERRRMX1",NULL},
4830 {0xE2,"ERRRMX2",NULL},
4831 {0xE3,"ERRRMX3",NULL},
4832 {0xFF,"ERRCMD",NULL},
4836 /****************************************************************************
4837 return a SMB error string from a SMB buffer
4838 ****************************************************************************/
4839 char *smb_errstr(char *inbuf)
4842 int class = CVAL(inbuf,smb_rcls);
4843 int num = SVAL(inbuf,smb_err);
4846 for (i=0;err_classes[i].class;i++)
4847 if (err_classes[i].code == class)
4849 if (err_classes[i].err_msgs)
4851 err_code_struct *err = err_classes[i].err_msgs;
4852 for (j=0;err[j].name;j++)
4853 if (num == err[j].code)
4856 sprintf(ret,"%s - %s (%s)",err_classes[i].class,
4857 err[j].name,err[j].message);
4859 sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
4864 sprintf(ret,"%s - %d",err_classes[i].class,num);
4868 sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num);