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);
88 static BOOL do_this_one(file_info *finfo);
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;
146 extern int coding_system;
147 #define CNV_LANG(s) (coding_system == DOSV_CODE?s:dos_to_unix(s, False))
148 #define CNV_INPUT(s) (coding_system == DOSV_CODE?s:unix_to_dos(s, True))
150 setup_term_code (char *code)
153 new = interpret_coding_system (code, UNKNOWN_CODE);
154 if (new != UNKNOWN_CODE) {
161 #define CNV_LANG(s) dos2unix_format(s,False)
162 #define CNV_INPUT(s) unix2dos_format(s,True)
165 /****************************************************************************
166 setup basics in a outgoing packet
167 ****************************************************************************/
168 void setup_pkt(char *outbuf)
170 SSVAL(outbuf,smb_pid,pid);
171 SSVAL(outbuf,smb_uid,uid);
172 SSVAL(outbuf,smb_mid,mid);
173 if (Protocol > PROTOCOL_COREPLUS)
175 SCVAL(outbuf,smb_flg,0x8);
176 SSVAL(outbuf,smb_flg2,0x1);
180 /****************************************************************************
181 write to a local file with CR/LF->LF translation if appropriate. return the
182 number taken from the buffer. This may not equal the number written.
183 ****************************************************************************/
184 static int writefile(int f, char *b, int n)
189 return(write(f,b,n));
194 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
198 if (write(f, b, 1) != 1)
209 /****************************************************************************
210 read from a file with LF->CR/LF translation if appropriate. return the
211 number read. read approx n bytes.
212 ****************************************************************************/
213 static int readfile(char *b, int size, int n, FILE *f)
218 if (!translation || (size != 1))
219 return(fread(b,size,n,f));
224 if ((c = getc(f)) == EOF)
229 if (c == '\n') /* change all LFs to CR/LF */
243 /****************************************************************************
244 read from a file with print translation. return the number read. read approx n
246 ****************************************************************************/
247 static int printread(FILE *f,char *b,int n)
251 i = readfile(b,1, n-1,f);
260 /****************************************************************************
261 check for existance of a dir
262 ****************************************************************************/
263 static BOOL chkpath(char *path,BOOL report)
266 pstring inbuf,outbuf;
270 trim_string(path2,NULL,"\\");
271 if (!*path2) *path2 = '\\';
273 bzero(outbuf,smb_size);
274 set_message(outbuf,0,4 + strlen(path2),True);
275 SCVAL(outbuf,smb_com,SMBchkpth);
276 SSVAL(outbuf,smb_tid,cnum);
283 send_smb(Client,outbuf);
284 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
286 if (report && CVAL(inbuf,smb_rcls) != 0)
287 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
289 return(CVAL(inbuf,smb_rcls) == 0);
293 /****************************************************************************
295 ****************************************************************************/
296 static void send_message(char *inbuf,char *outbuf)
303 /* send a SMBsendstrt command */
304 bzero(outbuf,smb_size);
305 set_message(outbuf,0,0,True);
306 CVAL(outbuf,smb_com) = SMBsendstrt;
307 SSVAL(outbuf,smb_tid,cnum);
312 p = skip_string(p,1);
315 p = skip_string(p,1);
317 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
319 send_smb(Client,outbuf);
322 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
324 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
328 grp_id = SVAL(inbuf,smb_vwv0);
330 printf("Connected. Type your message, ending it with a Control-D\n");
332 while (!feof(stdin) && total_len < 1600)
334 int maxlen = MIN(1600 - total_len,127);
341 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
348 CVAL(outbuf,smb_com) = SMBsendtxt;
350 set_message(outbuf,1,l+3,True);
352 SSVAL(outbuf,smb_vwv0,grp_id);
359 send_smb(Client,outbuf);
362 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
364 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
371 if (total_len >= 1600)
372 printf("the message was truncated to 1600 bytes ");
374 printf("sent %d bytes ",total_len);
376 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
378 CVAL(outbuf,smb_com) = SMBsendend;
379 set_message(outbuf,1,0,False);
380 SSVAL(outbuf,smb_vwv0,grp_id);
382 send_smb(Client,outbuf);
385 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
387 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
394 /****************************************************************************
395 check the space on a device
396 ****************************************************************************/
397 static void do_dskattr(void)
399 pstring inbuf,outbuf;
401 bzero(outbuf,smb_size);
402 set_message(outbuf,0,0,True);
403 CVAL(outbuf,smb_com) = SMBdskattr;
404 SSVAL(outbuf,smb_tid,cnum);
407 send_smb(Client,outbuf);
408 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
410 if (CVAL(inbuf,smb_rcls) != 0)
411 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
413 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
414 SVAL(inbuf,smb_vwv0),
415 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
416 SVAL(inbuf,smb_vwv3)));
419 /****************************************************************************
421 ****************************************************************************/
422 static void cmd_pwd(void)
424 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
425 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
429 /****************************************************************************
430 change directory - inner section
431 ****************************************************************************/
432 static void do_cd(char *newdir)
438 /* Save the current directory in case the
439 new directory is invalid */
440 strcpy(saved_dir, cur_dir);
445 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
446 strcat(cur_dir, "\\");
448 dos_clean_name(cur_dir);
449 strcpy(dname,cur_dir);
450 strcat(cur_dir,"\\");
451 dos_clean_name(cur_dir);
453 if (!strequal(cur_dir,"\\"))
454 if (!chkpath(dname,True))
455 strcpy(cur_dir,saved_dir);
457 strcpy(cd_path,cur_dir);
460 /****************************************************************************
462 ****************************************************************************/
463 static void cmd_cd(char *inbuf,char *outbuf)
467 if (next_token(NULL,buf,NULL))
470 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
474 /****************************************************************************
475 display info about a file
476 ****************************************************************************/
477 static void display_finfo(file_info *finfo)
479 if (do_this_one(finfo)) {
480 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
481 DEBUG(0,(" %-30s%7.7s%10d %s",
482 CNV_LANG(finfo->name),
483 attrib_string(finfo->mode),
485 asctime(LocalTime(&t))));
486 dir_total += finfo->size;
491 /****************************************************************************
492 do a directory listing, calling fn on each file found. Use the TRANSACT2
493 call for long filenames
494 ****************************************************************************/
495 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
497 int max_matches = 512;
498 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
503 char *dirlist = NULL;
505 int total_received = 0;
507 char *resp_data=NULL;
508 char *resp_param=NULL;
509 int resp_data_len = 0;
510 int resp_param_len=0;
512 int ff_resume_key = 0;
513 int ff_searchcount=0;
527 if (loop_count > 200)
529 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
535 setup = TRANSACT2_FINDFIRST;
536 SSVAL(param,0,attribute); /* attribute */
537 SSVAL(param,2,max_matches); /* max count */
538 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
539 SSVAL(param,6,info_level);
541 strcpy(param+12,mask);
545 setup = TRANSACT2_FINDNEXT;
546 SSVAL(param,0,ff_dir_handle);
547 SSVAL(param,2,max_matches); /* max count */
548 SSVAL(param,4,info_level);
549 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
550 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
551 strcpy(param+12,mask);
553 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
554 ff_dir_handle,ff_resume_key,ff_lastname,mask));
556 /* ??? original code added 1 pad byte after param */
558 send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
560 0,12+strlen(mask)+1,1,
563 if (!receive_trans_response(inbuf,SMBtrans2,
564 &resp_data_len,&resp_param_len,
565 &resp_data,&resp_param))
567 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
571 /* parse out some important return info */
575 ff_dir_handle = SVAL(p,0);
576 ff_searchcount = SVAL(p,2);
578 ff_lastname = SVAL(p,8);
582 ff_searchcount = SVAL(p,0);
584 ff_lastname = SVAL(p,6);
587 if (ff_searchcount == 0)
590 /* point to the data bytes */
593 /* we might need the lastname for continuations */
600 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
601 /* strcpy(mask,p+ff_lastname+94); */
604 strcpy(mask,p + ff_lastname + 1);
612 /* and add them to the dirlist pool */
613 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
617 DEBUG(0,("Failed to expand dirlist\n"));
621 /* put in a length for the last entry, to ensure we can chain entries
622 into the next packet */
625 for (p2=p,i=0;i<(ff_searchcount-1);i++)
626 p2 += interpret_long_filename(info_level,p2,NULL);
627 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
630 /* grab the data for later use */
631 memcpy(dirlist+dirlist_len,p,resp_data_len);
632 dirlist_len += resp_data_len;
634 total_received += ff_searchcount;
636 if (resp_data) free(resp_data); resp_data = NULL;
637 if (resp_param) free(resp_param); resp_param = NULL;
639 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
640 ff_searchcount,ff_eos,ff_resume_key));
646 for (p=dirlist,i=0;i<total_received;i++)
648 p += interpret_long_filename(info_level,p,&finfo);
649 display_finfo(&finfo);
652 for (p=dirlist,i=0;i<total_received;i++)
654 p += interpret_long_filename(info_level,p,&finfo);
655 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
658 /* free up the dirlist buffer */
659 if (dirlist) free(dirlist);
660 return(total_received);
664 /****************************************************************************
665 do a directory listing, calling fn on each file found
666 ****************************************************************************/
667 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
673 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
674 int num_received = 0;
676 char *dirlist = NULL;
688 bzero(outbuf,smb_size);
690 set_message(outbuf,2,5 + strlen(mask),True);
692 set_message(outbuf,2,5 + 21,True);
695 if (Protocol >= PROTOCOL_LANMAN1)
696 CVAL(outbuf,smb_com) = SMBffirst;
699 CVAL(outbuf,smb_com) = SMBsearch;
701 SSVAL(outbuf,smb_tid,cnum);
704 SSVAL(outbuf,smb_vwv0,num_asked);
705 SSVAL(outbuf,smb_vwv1,attribute);
726 send_smb(Client,outbuf);
727 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
729 received = SVAL(inbuf,smb_vwv0);
731 DEBUG(5,("dir received %d\n",received));
733 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
735 if (received <= 0) break;
739 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
744 p = smb_buf(inbuf) + 3;
746 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
747 p,received*DIR_STRUCT_SIZE);
749 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
751 num_received += received;
753 if (CVAL(inbuf,smb_rcls) != 0) break;
757 if (!first && Protocol >= PROTOCOL_LANMAN1)
759 bzero(outbuf,smb_size);
760 CVAL(outbuf,smb_com) = SMBfclose;
762 SSVAL(outbuf,smb_tid,cnum);
776 send_smb(Client,outbuf);
777 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
779 if (CVAL(inbuf,smb_rcls) != 0)
780 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
785 for (p=dirlist,i=0;i<num_received;i++)
787 p += interpret_short_filename(p,&finfo);
788 display_finfo(&finfo);
791 for (p=dirlist,i=0;i<num_received;i++)
793 p += interpret_short_filename(p,&finfo);
794 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
797 if (dirlist) free(dirlist);
798 return(num_received);
803 /****************************************************************************
804 do a directory listing, calling fn on each file found
805 ****************************************************************************/
806 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
808 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
809 if (Protocol >= PROTOCOL_LANMAN2)
811 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
815 expand_mask(Mask,False);
816 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
820 /*******************************************************************
821 decide if a file should be operated on
822 ********************************************************************/
823 static BOOL do_this_one(file_info *finfo)
825 if (finfo->mode & aDIR) return(True);
827 if (newer_than && finfo->mtime < newer_than)
830 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
837 /*****************************************************************************
838 Convert a character pointer in a call_api() response to a form we can use.
839 This function contains code to prevent core dumps if the server returns
841 *****************************************************************************/
842 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
844 if( datap == 0 ) /* turn NULL pointers */
845 { /* into zero length strings */
850 unsigned int offset = datap - converter;
852 if( offset >= rdrcnt )
854 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
859 return &rdata[offset];
864 /****************************************************************************
865 interpret a short filename structure
866 The length of the structure is returned
867 ****************************************************************************/
868 static int interpret_short_filename(char *p,file_info *finfo)
870 finfo->mode = CVAL(p,21);
872 /* this date is converted to GMT by make_unix_date */
873 finfo->ctime = make_unix_date(p+22);
874 finfo->mtime = finfo->atime = finfo->ctime;
875 finfo->size = IVAL(p,26);
876 strcpy(finfo->name,p+30);
878 return(DIR_STRUCT_SIZE);
881 /****************************************************************************
882 interpret a long filename structure - this is mostly guesses at the moment
883 The length of the structure is returned
884 The structure of a long filename depends on the info level. 260 is used
885 by NT and 2 is used by OS/2
886 ****************************************************************************/
887 static int interpret_long_filename(int level,char *p,file_info *finfo)
890 memcpy(finfo,&def_finfo,sizeof(*finfo));
894 case 1: /* OS/2 understands this */
897 /* these dates are converted to GMT by make_unix_date */
898 finfo->ctime = make_unix_date2(p+4);
899 finfo->atime = make_unix_date2(p+8);
900 finfo->mtime = make_unix_date2(p+12);
901 finfo->size = IVAL(p,16);
902 finfo->mode = CVAL(p,24);
903 strcpy(finfo->name,p+27);
905 return(28 + CVAL(p,26));
907 case 2: /* this is what OS/2 uses mostly */
910 /* these dates are converted to GMT by make_unix_date */
911 finfo->ctime = make_unix_date2(p+4);
912 finfo->atime = make_unix_date2(p+8);
913 finfo->mtime = make_unix_date2(p+12);
914 finfo->size = IVAL(p,16);
915 finfo->mode = CVAL(p,24);
916 strcpy(finfo->name,p+31);
918 return(32 + CVAL(p,30));
920 /* levels 3 and 4 are untested */
924 /* these dates are probably like the other ones */
925 finfo->ctime = make_unix_date2(p+8);
926 finfo->atime = make_unix_date2(p+12);
927 finfo->mtime = make_unix_date2(p+16);
928 finfo->size = IVAL(p,20);
929 finfo->mode = CVAL(p,28);
930 strcpy(finfo->name,p+33);
937 /* these dates are probably like the other ones */
938 finfo->ctime = make_unix_date2(p+8);
939 finfo->atime = make_unix_date2(p+12);
940 finfo->mtime = make_unix_date2(p+16);
941 finfo->size = IVAL(p,20);
942 finfo->mode = CVAL(p,28);
943 strcpy(finfo->name,p+37);
947 case 260: /* NT uses this, but also accepts 2 */
952 p += 4; /* next entry offset */
953 p += 4; /* fileindex */
955 /* these dates appear to arrive in a weird way. It seems to
956 be localtime plus the serverzone given in the initial
957 connect. This is GMT when DST is not in effect and one
958 hour from GMT otherwise. Can this really be right??
960 I suppose this could be called kludge-GMT. Is is the GMT
961 you get by using the current DST setting on a different
962 localtime. It will be cheap to calculate, I suppose, as
963 no DST tables will be needed */
965 finfo->ctime = interpret_long_date(p); p += 8;
966 finfo->atime = interpret_long_date(p); p += 8;
967 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
968 finfo->size = IVAL(p,0); p += 8;
969 p += 8; /* alloc size */
970 finfo->mode = CVAL(p,0); p += 4;
971 namelen = IVAL(p,0); p += 4;
972 p += 4; /* EA size */
973 p += 2; /* short name len? */
974 p += 24; /* short name? */
975 StrnCpy(finfo->name,p,namelen);
981 DEBUG(1,("Unknown long filename format %d\n",level));
988 /****************************************************************************
989 act on the files in a dir listing
990 ****************************************************************************/
991 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
994 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
995 !mask_match(finfo->name,fileselection,False,False)) &&
996 !(recurse_dir && (strequal(finfo->name,".") ||
997 strequal(finfo->name,".."))))
999 if (recurse_dir && (finfo->mode & aDIR))
1003 strcpy(sav_dir,cur_dir);
1004 strcat(cur_dir,finfo->name);
1005 strcat(cur_dir,"\\");
1006 strcpy(mask2,cur_dir);
1009 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1014 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);
1016 do_dir(inbuf,outbuf,mask2,attribute,fn,True);
1018 strcpy(cur_dir,sav_dir);
1022 if (fn && do_this_one(finfo))
1029 /****************************************************************************
1030 receive a SMB trans or trans2 response allocating the necessary memory
1031 ****************************************************************************/
1032 static BOOL receive_trans_response(char *inbuf,int trans,
1033 int *data_len,int *param_len,
1034 char **data,char **param)
1038 int this_data,this_param;
1040 *data_len = *param_len = 0;
1042 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1046 if (CVAL(inbuf,smb_com) != trans)
1048 DEBUG(0,("Expected %s response, got command 0x%02x\n",
1049 trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
1052 if (CVAL(inbuf,smb_rcls) != 0)
1055 /* parse out the lengths */
1056 total_data = SVAL(inbuf,smb_tdrcnt);
1057 total_param = SVAL(inbuf,smb_tprcnt);
1060 *data = Realloc(*data,total_data);
1061 *param = Realloc(*param,total_param);
1065 this_data = SVAL(inbuf,smb_drcnt);
1066 this_param = SVAL(inbuf,smb_prcnt);
1068 memcpy(*data + SVAL(inbuf,smb_drdisp),
1069 smb_base(inbuf) + SVAL(inbuf,smb_droff),
1072 memcpy(*param + SVAL(inbuf,smb_prdisp),
1073 smb_base(inbuf) + SVAL(inbuf,smb_proff),
1075 *data_len += this_data;
1076 *param_len += this_param;
1078 /* parse out the total lengths again - they can shrink! */
1079 total_data = SVAL(inbuf,smb_tdrcnt);
1080 total_param = SVAL(inbuf,smb_tprcnt);
1082 if (total_data <= *data_len && total_param <= *param_len)
1085 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1089 if (CVAL(inbuf,smb_com) != trans)
1091 DEBUG(0,("Expected %s response, got command 0x%02x\n",
1092 trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
1095 if (CVAL(inbuf,smb_rcls) != 0)
1103 /****************************************************************************
1104 get a directory listing
1105 ****************************************************************************/
1106 static void cmd_dir(char *inbuf,char *outbuf)
1108 int attribute = aDIR | aSYSTEM | aHIDDEN;
1114 strcpy(mask,cur_dir);
1115 if(mask[strlen(mask)-1]!='\\')
1118 if (next_token(NULL,buf,NULL))
1129 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1133 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1138 /****************************************************************************
1139 get a file from rname to lname
1140 ****************************************************************************/
1141 static void do_get(char *rname,char *lname,file_info *finfo1)
1146 BOOL newhandle = False;
1147 char *inbuf,*outbuf;
1149 BOOL close_done = False;
1150 BOOL ignore_close_error = False;
1154 struct timeval tp_start;
1155 GetTimeOfDay(&tp_start);
1166 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1167 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1169 if (!inbuf || !outbuf)
1171 DEBUG(0,("out of memory\n"));
1175 bzero(outbuf,smb_size);
1176 set_message(outbuf,15,1 + strlen(rname),True);
1178 CVAL(outbuf,smb_com) = SMBopenX;
1179 SSVAL(outbuf,smb_tid,cnum);
1182 SSVAL(outbuf,smb_vwv0,0xFF);
1183 SSVAL(outbuf,smb_vwv2,1);
1184 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1185 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1186 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1187 SSVAL(outbuf,smb_vwv8,1);
1189 p = smb_buf(outbuf);
1191 p = skip_string(p,1);
1193 /* do a chained openX with a readX? */
1197 DEBUG(3,("Chaining readX wth openX\n"));
1198 SSVAL(outbuf,smb_vwv0,SMBreadX);
1199 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1202 SSVAL(p,smb_wct,10);
1203 SSVAL(p,smb_vwv0,0xFF);
1204 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1205 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1206 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1210 if(!strcmp(lname,"-"))
1211 handle = fileno(stdout);
1214 handle = creat(lname,0644);
1219 DEBUG(0,("Error opening local file %s\n",lname));
1220 free(inbuf);free(outbuf);
1224 send_smb(Client,outbuf);
1225 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1227 if (CVAL(inbuf,smb_rcls) != 0)
1229 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1230 SVAL(inbuf,smb_err) == ERRnoresource &&
1231 reopen_connection(inbuf,outbuf))
1233 do_get(rname,lname,finfo1);
1236 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1239 free(inbuf);free(outbuf);
1243 strcpy(finfo.name,rname);
1247 finfo.mode = SVAL(inbuf,smb_vwv3);
1248 /* these times arrive as LOCAL time, using the DST offset
1249 corresponding to that time, we convert them to GMT */
1250 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1251 finfo.atime = finfo.ctime = finfo.mtime;
1252 finfo.size = IVAL(inbuf,smb_vwv6);
1255 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1257 fnum = SVAL(inbuf,smb_vwv2);
1259 /* we might have got some data from a chained readX */
1260 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1262 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1263 datalen = SVAL(p,smb_vwv5);
1264 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1273 DEBUG(2,("getting file %s of size %d bytes as %s ",
1274 CNV_LANG(finfo.name),
1278 while (nread < finfo.size && !close_done)
1281 static BOOL can_chain_close = True;
1285 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1287 /* 3 possible read types. readbraw if a large block is required.
1288 readX + close if not much left and read if neither is supported */
1290 /* we might have already read some data from a chained readX */
1291 if (dataptr && datalen>0)
1294 /* if we can finish now then readX+close */
1295 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1296 ((finfo.size - nread) <
1297 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1300 /* if we support readraw then use that */
1301 if (method<0 && readbraw_supported)
1304 /* if we can then use readX */
1305 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1316 /* use readX + close */
1317 bzero(outbuf,smb_size);
1318 set_message(outbuf,10,0,True);
1319 CVAL(outbuf,smb_com) = SMBreadX;
1320 SSVAL(outbuf,smb_tid,cnum);
1325 CVAL(outbuf,smb_vwv0) = SMBclose;
1326 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1329 CVAL(outbuf,smb_vwv0) = 0xFF;
1331 SSVAL(outbuf,smb_vwv2,fnum);
1332 SIVAL(outbuf,smb_vwv3,nread);
1333 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1334 SSVAL(outbuf,smb_vwv6,0);
1335 SIVAL(outbuf,smb_vwv7,0);
1336 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1340 p = smb_buf(outbuf);
1347 /* now set the total packet length */
1348 smb_setlen(outbuf,smb_len(outbuf)+9);
1351 send_smb(Client,outbuf);
1352 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1354 if (CVAL(inbuf,smb_rcls) != 0)
1356 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1361 SVAL(inbuf,smb_vwv0) != SMBclose)
1363 /* NOTE: WfWg sometimes just ignores the chained
1364 command! This seems to break the spec? */
1365 DEBUG(3,("Rejected chained close?\n"));
1367 can_chain_close = False;
1368 ignore_close_error = True;
1371 datalen = SVAL(inbuf,smb_vwv5);
1372 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1378 static int readbraw_size = BUFFER_SIZE;
1381 bzero(outbuf,smb_size);
1382 set_message(outbuf,8,0,True);
1383 CVAL(outbuf,smb_com) = SMBreadbraw;
1384 SSVAL(outbuf,smb_tid,cnum);
1386 SSVAL(outbuf,smb_vwv0,fnum);
1387 SIVAL(outbuf,smb_vwv1,nread);
1388 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1389 SSVAL(outbuf,smb_vwv4,0);
1390 SIVALS(outbuf,smb_vwv5,-1);
1391 send_smb(Client,outbuf);
1393 /* Now read the raw data into the buffer and write it */
1394 if(read_smb_length(Client,inbuf,0) == -1) {
1395 DEBUG(0,("Failed to read length in readbraw\n"));
1399 /* Even though this is not an smb message, smb_len
1400 returns the generic length of an smb message */
1401 datalen = smb_len(inbuf);
1405 /* we got a readbraw error */
1406 DEBUG(4,("readbraw error - reducing size\n"));
1407 readbraw_size = (readbraw_size * 9) / 10;
1409 if (readbraw_size < max_xmit)
1411 DEBUG(0,("disabling readbraw\n"));
1412 readbraw_supported = False;
1419 if(read_data(Client,inbuf,datalen) != datalen) {
1420 DEBUG(0,("Failed to read data in readbraw\n"));
1428 /* we've already read some data with a chained readX */
1432 /* use plain read */
1433 bzero(outbuf,smb_size);
1434 set_message(outbuf,5,0,True);
1435 CVAL(outbuf,smb_com) = SMBread;
1436 SSVAL(outbuf,smb_tid,cnum);
1439 SSVAL(outbuf,smb_vwv0,fnum);
1440 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1441 SIVAL(outbuf,smb_vwv2,nread);
1442 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1444 send_smb(Client,outbuf);
1445 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1447 if (CVAL(inbuf,smb_rcls) != 0)
1449 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1453 datalen = SVAL(inbuf,smb_vwv0);
1454 dataptr = smb_buf(inbuf) + 3;
1458 if (writefile(handle,dataptr,datalen) != datalen)
1460 DEBUG(0,("Error writing local file\n"));
1467 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1479 bzero(outbuf,smb_size);
1480 set_message(outbuf,3,0,True);
1481 CVAL(outbuf,smb_com) = SMBclose;
1482 SSVAL(outbuf,smb_tid,cnum);
1485 SSVAL(outbuf,smb_vwv0,fnum);
1486 SIVALS(outbuf,smb_vwv1,-1);
1488 send_smb(Client,outbuf);
1489 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1491 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1493 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1496 free(inbuf);free(outbuf);
1504 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1505 bzero(outbuf,smb_size);
1506 set_message(outbuf,8,strlen(rname)+4,True);
1507 CVAL(outbuf,smb_com) = SMBsetatr;
1508 SSVAL(outbuf,smb_tid,cnum);
1510 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1511 SIVALS(outbuf,smb_vwv1,0);
1512 p = smb_buf(outbuf);
1518 send_smb(Client,outbuf);
1519 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1523 struct timeval tp_end;
1526 GetTimeOfDay(&tp_end);
1528 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1529 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1530 get_total_time_ms += this_time;
1531 get_total_size += finfo.size;
1533 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1534 finfo.size / (1.024*this_time + 1.0e-4),
1535 get_total_size / (1.024*get_total_time_ms)));
1538 free(inbuf);free(outbuf);
1542 /****************************************************************************
1544 ****************************************************************************/
1545 static void cmd_get(void)
1551 strcpy(rname,cur_dir);
1554 p = rname + strlen(rname);
1556 if (!next_token(NULL,p,NULL)) {
1557 DEBUG(0,("get <filename>\n"));
1561 dos_clean_name(rname);
1563 next_token(NULL,lname,NULL);
1565 do_get(rname,lname,NULL);
1569 /****************************************************************************
1570 do a mget operation on one file
1571 ****************************************************************************/
1572 static void do_mget(file_info *finfo)
1577 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1582 DEBUG(0,("mget aborted\n"));
1586 if (finfo->mode & aDIR)
1587 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1589 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1591 if (prompt && !yesno(quest)) return;
1593 if (finfo->mode & aDIR)
1595 pstring saved_curdir;
1597 char *inbuf,*outbuf;
1599 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1600 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1602 if (!inbuf || !outbuf)
1604 DEBUG(0,("out of memory\n"));
1608 strcpy(saved_curdir,cur_dir);
1610 strcat(cur_dir,finfo->name);
1611 strcat(cur_dir,"\\");
1613 unix_format(finfo->name);
1616 strlower(finfo->name);
1618 if (!directory_exist(finfo->name,NULL) &&
1619 sys_mkdir(finfo->name,0777) != 0)
1621 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1622 strcpy(cur_dir,saved_curdir);
1623 free(inbuf);free(outbuf);
1627 if (sys_chdir(finfo->name) != 0)
1629 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1630 strcpy(cur_dir,saved_curdir);
1631 free(inbuf);free(outbuf);
1636 strcpy(mget_mask,cur_dir);
1637 strcat(mget_mask,"*");
1639 do_dir((char *)inbuf,(char *)outbuf,
1640 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1642 strcpy(cur_dir,saved_curdir);
1643 free(inbuf);free(outbuf);
1647 strcpy(rname,cur_dir);
1648 strcat(rname,finfo->name);
1649 do_get(rname,finfo->name,finfo);
1653 /****************************************************************************
1654 view the file using the pager
1655 ****************************************************************************/
1656 static void cmd_more(void)
1658 fstring rname,lname,tmpname,pager_cmd;
1661 strcpy(rname,cur_dir);
1663 sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1664 strcpy(lname,tmpname);
1666 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1667 DEBUG(0,("more <filename>\n"));
1670 dos_clean_name(rname);
1672 do_get(rname,lname,NULL);
1674 pager=getenv("PAGER");
1675 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1682 /****************************************************************************
1684 ****************************************************************************/
1685 static void cmd_mget(char *inbuf,char *outbuf)
1687 int attribute = aSYSTEM | aHIDDEN;
1699 while (next_token(NULL,p,NULL))
1701 strcpy(mget_mask,cur_dir);
1702 if(mget_mask[strlen(mget_mask)-1]!='\\')
1703 strcat(mget_mask,"\\");
1706 strcpy(mget_mask,p);
1708 strcat(mget_mask,p);
1709 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1714 strcpy(mget_mask,cur_dir);
1715 if(mget_mask[strlen(mget_mask)-1]!='\\')
1716 strcat(mget_mask,"\\");
1717 strcat(mget_mask,"*");
1718 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1722 /****************************************************************************
1723 make a directory of name "name"
1724 ****************************************************************************/
1725 static BOOL do_mkdir(char *name)
1728 char *inbuf,*outbuf;
1730 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1731 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1733 if (!inbuf || !outbuf)
1735 DEBUG(0,("out of memory\n"));
1739 bzero(outbuf,smb_size);
1740 set_message(outbuf,0,2 + strlen(name),True);
1742 CVAL(outbuf,smb_com) = SMBmkdir;
1743 SSVAL(outbuf,smb_tid,cnum);
1747 p = smb_buf(outbuf);
1751 send_smb(Client,outbuf);
1752 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1754 if (CVAL(inbuf,smb_rcls) != 0)
1756 DEBUG(0,("%s making remote directory %s\n",
1757 smb_errstr(inbuf),CNV_LANG(name)));
1759 free(inbuf);free(outbuf);
1763 free(inbuf);free(outbuf);
1768 /****************************************************************************
1770 ****************************************************************************/
1771 static void cmd_mkdir(char *inbuf,char *outbuf)
1777 strcpy(mask,cur_dir);
1779 if (!next_token(NULL,p,NULL))
1782 DEBUG(0,("mkdir <dirname>\n"));
1794 trim_string(ddir,".",NULL);
1795 p = strtok(ddir,"/\\");
1799 if (!chkpath(ddir2,False))
1804 p = strtok(NULL,"/\\");
1812 /*******************************************************************
1813 write to a file using writebraw
1814 ********************************************************************/
1815 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1820 bzero(outbuf,smb_size);
1821 bzero(inbuf,smb_size);
1822 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1824 CVAL(outbuf,smb_com) = SMBwritebraw;
1825 SSVAL(outbuf,smb_tid,cnum);
1828 SSVAL(outbuf,smb_vwv0,fnum);
1829 SSVAL(outbuf,smb_vwv1,n);
1830 SIVAL(outbuf,smb_vwv3,pos);
1831 SSVAL(outbuf,smb_vwv7,1);
1833 send_smb(Client,outbuf);
1835 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1838 _smb_setlen(buf-4,n); /* HACK! XXXX */
1840 if (write_socket(Client,buf-4,n+4) != n+4)
1843 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1844 DEBUG(0,("Error writing remote file (2)\n"));
1847 return(SVAL(inbuf,smb_vwv0));
1852 /*******************************************************************
1854 ********************************************************************/
1855 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1859 if (writebraw_supported && n > (max_xmit-200))
1860 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1862 bzero(outbuf,smb_size);
1863 bzero(inbuf,smb_size);
1864 set_message(outbuf,5,n + 3,True);
1866 CVAL(outbuf,smb_com) = SMBwrite;
1867 SSVAL(outbuf,smb_tid,cnum);
1870 SSVAL(outbuf,smb_vwv0,fnum);
1871 SSVAL(outbuf,smb_vwv1,n);
1872 SIVAL(outbuf,smb_vwv2,pos);
1873 SSVAL(outbuf,smb_vwv4,0);
1874 CVAL(smb_buf(outbuf),0) = 1;
1875 SSVAL(smb_buf(outbuf),1,n);
1877 memcpy(smb_buf(outbuf)+3,buf,n);
1879 send_smb(Client,outbuf);
1880 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1882 if (CVAL(inbuf,smb_rcls) != 0) {
1883 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1886 return(SVAL(inbuf,smb_vwv0));
1891 /****************************************************************************
1893 ****************************************************************************/
1894 static void do_put(char *rname,char *lname,file_info *finfo)
1900 char *inbuf,*outbuf;
1901 time_t close_time = finfo->mtime;
1903 static int maxwrite=0;
1905 struct timeval tp_start;
1906 GetTimeOfDay(&tp_start);
1908 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1909 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1911 if (!inbuf || !outbuf)
1913 DEBUG(0,("out of memory\n"));
1917 bzero(outbuf,smb_size);
1918 set_message(outbuf,3,2 + strlen(rname),True);
1920 if (finfo->mtime == 0 || finfo->mtime == -1)
1921 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1923 CVAL(outbuf,smb_com) = SMBcreate;
1924 SSVAL(outbuf,smb_tid,cnum);
1927 SSVAL(outbuf,smb_vwv0,finfo->mode);
1928 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1930 p = smb_buf(outbuf);
1934 send_smb(Client,outbuf);
1935 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1937 if (CVAL(inbuf,smb_rcls) != 0)
1939 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1941 free(inbuf);free(outbuf);if (buf) free(buf);
1945 f = fopen(lname,"r");
1949 DEBUG(0,("Error opening local file %s\n",lname));
1950 free(inbuf);free(outbuf);
1955 fnum = SVAL(inbuf,smb_vwv0);
1956 if (finfo->size < 0)
1957 finfo->size = file_size(lname);
1959 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1962 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1964 while (nread < finfo->size)
1969 n = MIN(n,finfo->size - nread);
1971 buf = (char *)Realloc(buf,n+4);
1973 fseek(f,nread,SEEK_SET);
1974 if ((n = readfile(buf+4,1,n,f)) < 1)
1976 DEBUG(0,("Error reading local file\n"));
1980 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1984 DEBUG(0,("Error writing file\n"));
1997 bzero(outbuf,smb_size);
1998 set_message(outbuf,3,0,True);
1999 CVAL(outbuf,smb_com) = SMBclose;
2000 SSVAL(outbuf,smb_tid,cnum);
2003 SSVAL(outbuf,smb_vwv0,fnum);
2004 put_dos_date3(outbuf,smb_vwv1,close_time);
2006 send_smb(Client,outbuf);
2007 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2009 if (CVAL(inbuf,smb_rcls) != 0)
2011 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2013 free(inbuf);free(outbuf);
2020 free(inbuf);free(outbuf);
2024 struct timeval tp_end;
2027 GetTimeOfDay(&tp_end);
2029 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
2030 (tp_end.tv_usec - tp_start.tv_usec)/1000;
2031 put_total_time_ms += this_time;
2032 put_total_size += finfo->size;
2034 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
2035 finfo->size / (1.024*this_time + 1.0e-4),
2036 put_total_size / (1.024*put_total_time_ms)));
2042 /****************************************************************************
2044 ****************************************************************************/
2045 static void cmd_put(void)
2054 strcpy(rname,cur_dir);
2058 if (!next_token(NULL,p,NULL))
2060 DEBUG(0,("put <filename>\n"));
2065 if (next_token(NULL,p,NULL))
2068 strcat(rname,lname);
2070 dos_clean_name(rname);
2074 if (!file_exist(lname,&st)) {
2075 DEBUG(0,("%s does not exist\n",lname));
2078 finfo.mtime = st.st_mtime;
2081 do_put(rname,lname,&finfo);
2084 /****************************************************************************
2085 seek in a directory/file list until you get something that doesn't start with
2087 ****************************************************************************/
2088 static BOOL seek_list(FILE *f,char *name)
2093 if (fscanf(f,"%s",s) != 1) return(False);
2094 trim_string(s,"./",NULL);
2095 if (strncmp(s,name,strlen(name)) != 0)
2106 /****************************************************************************
2107 set the file selection mask
2108 ****************************************************************************/
2109 static void cmd_select(void)
2111 strcpy(fileselection,"");
2112 next_token(NULL,fileselection,NULL);
2116 /****************************************************************************
2118 ****************************************************************************/
2119 static void cmd_mput(void)
2130 while (next_token(NULL,p,NULL))
2137 sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2139 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2141 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2144 f = fopen(tmpname,"r");
2151 if (fscanf(f,"%s",lname) != 1) break;
2152 trim_string(lname,"./",NULL);
2156 /* check if it's a directory */
2157 if (directory_exist(lname,&st))
2159 if (!recurse) continue;
2160 sprintf(quest,"Put directory %s? ",lname);
2161 if (prompt && !yesno(quest))
2164 if (!seek_list(f,lname))
2169 strcpy(rname,cur_dir);
2170 strcat(rname,lname);
2171 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2173 if (!seek_list(f,lname))
2182 sprintf(quest,"Put file %s? ",lname);
2183 if (prompt && !yesno(quest)) continue;
2185 strcpy(rname,cur_dir);
2186 strcat(rname,lname);
2190 /* null size so do_put knows to ignore it */
2193 /* set the date on the file */
2194 finfo.mtime = st.st_mtime;
2196 do_put(rname,lname,&finfo);
2203 /****************************************************************************
2205 ****************************************************************************/
2206 static void do_cancel(int job)
2208 char *rparam = NULL;
2214 bzero(param,sizeof(param));
2217 SSVAL(p,0,81); /* DosPrintJobDel() */
2220 p = skip_string(p,1);
2222 p = skip_string(p,1);
2226 if (call_api(PTR_DIFF(p,param),0,
2232 int res = SVAL(rparam,0);
2235 printf("Job %d cancelled\n",job);
2237 printf("Error %d calcelling job %d\n",res,job);
2241 printf("Server refused cancel request\n");
2243 if (rparam) free(rparam);
2244 if (rdata) free(rdata);
2250 /****************************************************************************
2252 ****************************************************************************/
2253 static void cmd_cancel(char *inbuf,char *outbuf )
2258 if (!connect_as_printer)
2260 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2261 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2264 if (!next_token(NULL,buf,NULL)) {
2265 printf("cancel <jobid> ...\n");
2271 } while (next_token(NULL,buf,NULL));
2275 /****************************************************************************
2277 ****************************************************************************/
2278 static void cmd_stat(char *inbuf,char *outbuf)
2282 char *resp_data=NULL;
2283 char *resp_param=NULL;
2284 int resp_data_len = 0;
2285 int resp_param_len=0;
2287 uint16 setup = TRANSACT2_QPATHINFO;
2289 if (!next_token(NULL,buf,NULL)) {
2290 printf("stat <file>\n");
2295 SSVAL(param,0,4); /* level */
2300 send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
2302 0,6 + strlen(p)+1,1,
2305 receive_trans_response(inbuf,SMBtrans2,
2306 &resp_data_len,&resp_param_len,
2307 &resp_data,&resp_param);
2309 if (resp_data) free(resp_data); resp_data = NULL;
2310 if (resp_param) free(resp_param); resp_param = NULL;
2314 /****************************************************************************
2316 ****************************************************************************/
2317 static void cmd_print(char *inbuf,char *outbuf )
2326 if (!connect_as_printer)
2328 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2329 DEBUG(0,("Trying to print without -P may fail\n"));
2332 if (!next_token(NULL,lname,NULL))
2334 DEBUG(0,("print <filename>\n"));
2338 strcpy(rname,lname);
2339 p = strrchr(rname,'/');
2344 strcpy(rname,tname);
2347 if ((int)strlen(rname) > 14)
2350 if (strequal(lname,"-"))
2353 strcpy(rname,"stdin");
2356 dos_clean_name(rname);
2358 bzero(outbuf,smb_size);
2359 set_message(outbuf,2,2 + strlen(rname),True);
2361 CVAL(outbuf,smb_com) = SMBsplopen;
2362 SSVAL(outbuf,smb_tid,cnum);
2365 SSVAL(outbuf,smb_vwv0,0);
2366 SSVAL(outbuf,smb_vwv1,printmode);
2368 p = smb_buf(outbuf);
2372 send_smb(Client,outbuf);
2373 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2375 if (CVAL(inbuf,smb_rcls) != 0)
2377 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2382 f = fopen(lname,"r");
2385 DEBUG(0,("Error opening local file %s\n",lname));
2390 fnum = SVAL(inbuf,smb_vwv0);
2392 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2398 bzero(outbuf,smb_size);
2399 set_message(outbuf,1,3,True);
2401 /* for some strange reason the OS/2 print server can't handle large
2402 packets when printing. weird */
2403 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2406 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2408 n = readfile(smb_buf(outbuf)+3,1,n,f);
2411 DEBUG(0,("read gave %d\n",n));
2415 smb_setlen(outbuf,smb_len(outbuf) + n);
2417 CVAL(outbuf,smb_com) = SMBsplwr;
2418 SSVAL(outbuf,smb_tid,cnum);
2421 SSVAL(outbuf,smb_vwv0,fnum);
2422 SSVAL(outbuf,smb_vwv1,n+3);
2423 CVAL(smb_buf(outbuf),0) = 1;
2424 SSVAL(smb_buf(outbuf),1,n);
2426 send_smb(Client,outbuf);
2427 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2429 if (CVAL(inbuf,smb_rcls) != 0)
2431 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2438 DEBUG(2,("%d bytes printed\n",nread));
2440 bzero(outbuf,smb_size);
2441 set_message(outbuf,1,0,True);
2442 CVAL(outbuf,smb_com) = SMBsplclose;
2443 SSVAL(outbuf,smb_tid,cnum);
2446 SSVAL(outbuf,smb_vwv0,fnum);
2448 send_smb(Client,outbuf);
2449 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2451 if (CVAL(inbuf,smb_rcls) != 0)
2453 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2463 /****************************************************************************
2464 show a print queue - this is deprecated as it uses the old smb that
2465 has limited support - the correct call is the cmd_p_queue_4() after this.
2466 ****************************************************************************/
2467 static void cmd_queue(char *inbuf,char *outbuf )
2472 bzero(outbuf,smb_size);
2473 set_message(outbuf,2,0,True);
2475 CVAL(outbuf,smb_com) = SMBsplretq;
2476 SSVAL(outbuf,smb_tid,cnum);
2479 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2480 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2482 send_smb(Client,outbuf);
2483 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2485 if (CVAL(inbuf,smb_rcls) != 0)
2487 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2491 count = SVAL(inbuf,smb_vwv0);
2492 p = smb_buf(inbuf) + 3;
2495 DEBUG(0,("No entries in the print queue\n"));
2502 DEBUG(0,("Job Name Size Status\n"));
2508 case 0x01: sprintf(status,"held or stopped"); break;
2509 case 0x02: sprintf(status,"printing"); break;
2510 case 0x03: sprintf(status,"awaiting print"); break;
2511 case 0x04: sprintf(status,"in intercept"); break;
2512 case 0x05: sprintf(status,"file had error"); break;
2513 case 0x06: sprintf(status,"printer error"); break;
2514 default: sprintf(status,"unknown"); break;
2517 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2518 SVAL(p,5),p+12,IVAL(p,7),status));
2526 /****************************************************************************
2527 show information about a print queue
2528 ****************************************************************************/
2529 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2531 char *rparam = NULL;
2538 if (!connect_as_printer)
2540 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2541 DEBUG(0,("Trying to print without -P may fail\n"));
2544 bzero(param,sizeof(param));
2547 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2549 strcpy(p,"zWrLeh"); /* parameter description? */
2550 p = skip_string(p,1);
2551 strcpy(p,"WWzWWDDzz"); /* returned data format */
2552 p = skip_string(p,1);
2553 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2554 p = skip_string(p,1);
2555 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2556 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2558 strcpy(p,""); /* subformat */
2559 p = skip_string(p,1);
2561 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2562 if( call_api(PTR_DIFF(p,param), 0,
2569 result_code = SVAL(rparam,0);
2570 converter = SVAL(rparam,2); /* conversion factor */
2572 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2574 if (result_code == 0) /* if no error, */
2584 char PrinterName[20];
2586 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2587 strlower(PrinterName); /* in lower case */
2589 p = rdata; /* received data */
2590 for( i = 0; i < SVAL(rparam,4); ++i)
2593 Priority = SVAL(p,2);
2594 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2596 Priority = SVAL(p,2);
2597 JobTime = make_unix_date3( p + 12);
2598 JobTimeStr = asctime(LocalTime( &JobTime));
2600 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2603 printf("%s-%u %s priority %u %s %s %u bytes\n",
2604 PrinterName, JobId, UserName,
2605 Priority, JobTimeStr, JobName, Size);
2607 #if 0 /* DEBUG code */
2608 printf("Job Id: \"%u\"\n", SVAL(p,0));
2609 printf("Priority: \"%u\"\n", SVAL(p,2));
2611 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2612 printf("Position: \"%u\"\n", SVAL(p,8));
2613 printf("Status: \"%u\"\n", SVAL(p,10));
2615 JobTime = make_unix_date3( p + 12);
2616 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2617 printf("date: \"%u\"\n", SVAL(p,12));
2619 printf("Size: \"%u\"\n", SVAL(p,16));
2620 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2621 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2622 #endif /* DEBUG CODE */
2627 else /* call_api() failed */
2629 printf("Failed, error = %d\n", result_code);
2632 /* If any parameters or data were returned, free the storage. */
2633 if(rparam) free(rparam);
2634 if(rdata) free(rdata);
2639 /****************************************************************************
2640 show information about a print queue
2641 ****************************************************************************/
2642 static void cmd_qinfo(char *inbuf,char *outbuf )
2644 char *rparam = NULL;
2651 bzero(param,sizeof(param));
2654 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2656 strcpy(p,"zWrLh"); /* parameter description? */
2657 p = skip_string(p,1);
2658 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2659 p = skip_string(p,1);
2660 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2661 p = skip_string(p,1);
2662 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2663 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2665 strcpy(p,""); /* subformat */
2666 p = skip_string(p,1);
2668 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2669 if( call_api(PTR_DIFF(p,param), 0,
2676 result_code = SVAL(rparam,0);
2677 converter = SVAL(rparam,2); /* conversion factor */
2679 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2681 if (result_code == 0) /* if no error, */
2683 p = rdata; /* received data */
2685 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2686 printf("Priority: %u\n", SVAL(p,4) );
2687 printf("Start time: %u\n", SVAL(p,6) );
2688 printf("Until time: %u\n", SVAL(p,8) );
2689 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2690 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2691 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2692 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2693 printf("Status: %u\n", SVAL(p,28) );
2694 printf("Jobs: %u\n", SVAL(p,30) );
2695 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2696 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2698 /* Dump the driver data */
2703 ddptr = rdata + SVAL(p,40) - converter;
2704 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2705 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2707 for(x=8; x < count; x+=16)
2709 for(y=0; y < 16; y++)
2712 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2716 for(y=0; y < 16 && (x+y) < count; y++)
2718 c = CVAL(ddptr,(x+y));
2724 fputc('\n', stdout);
2730 else /* call_api() failed */
2732 printf("Failed, error = %d\n", result_code);
2735 /* If any parameters or data were returned, free the storage. */
2736 if(rparam) free(rparam);
2737 if(rdata) free(rdata);
2742 /****************************************************************************
2744 ****************************************************************************/
2745 static void do_del(file_info *finfo)
2748 char *inbuf,*outbuf;
2751 strcpy(mask,cur_dir);
2752 strcat(mask,finfo->name);
2754 if (finfo->mode & aDIR)
2757 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2758 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2760 if (!inbuf || !outbuf)
2762 DEBUG(0,("out of memory\n"));
2766 bzero(outbuf,smb_size);
2767 set_message(outbuf,1,2 + strlen(mask),True);
2769 CVAL(outbuf,smb_com) = SMBunlink;
2770 SSVAL(outbuf,smb_tid,cnum);
2773 SSVAL(outbuf,smb_vwv0,0);
2775 p = smb_buf(outbuf);
2779 send_smb(Client,outbuf);
2780 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2782 if (CVAL(inbuf,smb_rcls) != 0)
2783 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2785 free(inbuf);free(outbuf);
2789 /****************************************************************************
2791 ****************************************************************************/
2792 static void cmd_del(char *inbuf,char *outbuf )
2796 int attribute = aSYSTEM | aHIDDEN;
2801 strcpy(mask,cur_dir);
2803 if (!next_token(NULL,buf,NULL))
2805 DEBUG(0,("del <filename>\n"));
2810 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2814 /****************************************************************************
2816 ****************************************************************************/
2817 static void cmd_rmdir(char *inbuf,char *outbuf )
2823 strcpy(mask,cur_dir);
2825 if (!next_token(NULL,buf,NULL))
2827 DEBUG(0,("rmdir <dirname>\n"));
2832 bzero(outbuf,smb_size);
2833 set_message(outbuf,0,2 + strlen(mask),True);
2835 CVAL(outbuf,smb_com) = SMBrmdir;
2836 SSVAL(outbuf,smb_tid,cnum);
2840 p = smb_buf(outbuf);
2844 send_smb(Client,outbuf);
2845 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2847 if (CVAL(inbuf,smb_rcls) != 0)
2849 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2855 /****************************************************************************
2857 ****************************************************************************/
2858 static void cmd_rename(char *inbuf,char *outbuf )
2864 strcpy(src,cur_dir);
2865 strcpy(dest,cur_dir);
2867 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2869 DEBUG(0,("rename <src> <dest>\n"));
2875 bzero(outbuf,smb_size);
2876 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2878 CVAL(outbuf,smb_com) = SMBmv;
2879 SSVAL(outbuf,smb_tid,cnum);
2880 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2883 p = smb_buf(outbuf);
2886 p = skip_string(p,1);
2890 send_smb(Client,outbuf);
2891 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2893 if (CVAL(inbuf,smb_rcls) != 0)
2895 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2902 /****************************************************************************
2903 toggle the prompt flag
2904 ****************************************************************************/
2905 static void cmd_prompt(void)
2908 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2912 /****************************************************************************
2913 set the newer than time
2914 ****************************************************************************/
2915 static void cmd_newer(void)
2921 ok = next_token(NULL,buf,NULL);
2922 if (ok && (sys_stat(buf,&sbuf) == 0))
2924 newer_than = sbuf.st_mtime;
2925 DEBUG(1,("Getting files newer than %s",
2926 asctime(LocalTime(&newer_than))));
2931 if (ok && newer_than == 0)
2932 DEBUG(0,("Error setting newer-than time\n"));
2935 /****************************************************************************
2936 set the archive level
2937 ****************************************************************************/
2938 static void cmd_archive(void)
2942 if (next_token(NULL,buf,NULL)) {
2943 archive_level = atoi(buf);
2945 DEBUG(0,("Archive level is %d\n",archive_level));
2948 /****************************************************************************
2949 toggle the lowercaseflag
2950 ****************************************************************************/
2951 static void cmd_lowercase(void)
2953 lowercase = !lowercase;
2954 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2960 /****************************************************************************
2961 toggle the recurse flag
2962 ****************************************************************************/
2963 static void cmd_recurse(void)
2966 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2969 /****************************************************************************
2970 toggle the translate flag
2971 ****************************************************************************/
2972 static void cmd_translate(void)
2974 translation = !translation;
2975 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2976 translation?"on":"off"));
2980 /****************************************************************************
2981 do a printmode command
2982 ****************************************************************************/
2983 static void cmd_printmode(void)
2988 if (next_token(NULL,buf,NULL))
2990 if (strequal(buf,"text"))
2994 if (strequal(buf,"graphics"))
2997 printmode = atoi(buf);
3004 strcpy(mode,"text");
3007 strcpy(mode,"graphics");
3010 sprintf(mode,"%d",printmode);
3014 DEBUG(2,("the printmode is now %s\n",mode));
3017 /****************************************************************************
3019 ****************************************************************************/
3020 static void cmd_lcd(void)
3025 if (next_token(NULL,buf,NULL))
3027 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
3031 /****************************************************************************
3032 send a session request
3033 ****************************************************************************/
3034 static BOOL send_session_request(char *inbuf,char *outbuf)
3039 /* send a session request (RFC 8002) */
3041 strcpy(dest,desthost);
3042 p = strchr(dest,'.');
3045 /* put in the destination name */
3047 name_mangle(dest,p,name_type); /* 0x20 is the SMB server NetBIOS type. */
3052 name_mangle(myname,p,0);
3055 /* setup the packet length */
3056 _smb_setlen(outbuf,len);
3057 CVAL(outbuf,0) = 0x81;
3059 send_smb(Client,outbuf);
3060 DEBUG(5,("Sent session request\n"));
3062 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3064 if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */
3066 /* For information, here is the response structure.
3067 * We do the byte-twiddling to for portability.
3068 struct RetargetResponse{
3070 unsigned char flags;
3077 int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
3078 /* SESSION RETARGET */
3079 putip((char *)&dest_ip,inbuf+4);
3082 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
3086 DEBUG(3,("Retargeted\n"));
3088 set_socket_options(Client,user_socket_options);
3091 return send_session_request(inbuf,outbuf);
3092 } /* C. Hoch 9/14/95 End */
3095 if (CVAL(inbuf,0) != 0x82)
3097 int ecode = CVAL(inbuf,4);
3098 DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
3099 CVAL(inbuf,0),ecode,myname,desthost));
3103 DEBUG(0,("Not listening on called name\n"));
3104 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
3105 DEBUG(0,("You may find the -I option useful for this\n"));
3108 DEBUG(0,("Not listening for calling name\n"));
3109 DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
3110 DEBUG(0,("You may find the -n option useful for this\n"));
3113 DEBUG(0,("Called name not present\n"));
3114 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
3115 DEBUG(0,("You may find the -I option useful for this\n"));
3118 DEBUG(0,("Called name present, but insufficient resources\n"));
3119 DEBUG(0,("Perhaps you should try again later?\n"));
3122 DEBUG(0,("Unspecified error 0x%X\n",ecode));
3123 DEBUG(0,("Your server software is being unfriendly\n"));
3135 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
3136 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
3137 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
3138 {PROTOCOL_LANMAN1,"LANMAN1.0"},
3139 {PROTOCOL_LANMAN2,"LM1.2X002"},
3140 {PROTOCOL_LANMAN2,"Samba"},
3141 {PROTOCOL_NT1,"NT LM 0.12"},
3142 {PROTOCOL_NT1,"NT LANMAN 1.0"},
3147 /****************************************************************************
3148 send a login command
3149 ****************************************************************************/
3150 static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
3152 BOOL was_null = (!inbuf && !outbuf);
3154 time_t servertime = 0;
3155 extern int serverzone;
3167 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3168 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3172 if (strstr(service,"IPC$")) connect_as_ipc = True;
3176 if (connect_as_printer)
3177 strcpy(dev,"LPT1:");
3182 if (start_session && !send_session_request(inbuf,outbuf))
3192 bzero(outbuf,smb_size);
3194 /* setup the protocol strings */
3198 for (plength=0,numprots=0;
3199 prots[numprots].name && prots[numprots].prot<=max_protocol;
3201 plength += strlen(prots[numprots].name)+2;
3203 set_message(outbuf,0,plength,True);
3205 p = smb_buf(outbuf);
3207 prots[numprots].name && prots[numprots].prot<=max_protocol;
3211 strcpy(p,prots[numprots].name);
3216 CVAL(outbuf,smb_com) = SMBnegprot;
3219 CVAL(smb_buf(outbuf),0) = 2;
3221 send_smb(Client,outbuf);
3222 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3226 if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
3228 DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
3229 myname,desthost,smb_errstr(inbuf)));
3238 Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
3241 if (Protocol < PROTOCOL_NT1) {
3242 sec_mode = SVAL(inbuf,smb_vwv1);
3243 max_xmit = SVAL(inbuf,smb_vwv2);
3244 sesskey = IVAL(inbuf,smb_vwv6);
3245 serverzone = SVALS(inbuf,smb_vwv10)*60;
3246 /* this time is converted to GMT by make_unix_date */
3247 servertime = make_unix_date(inbuf+smb_vwv8);
3248 if (Protocol >= PROTOCOL_COREPLUS) {
3249 readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
3250 writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
3252 crypt_len = smb_buflen(inbuf);
3253 memcpy(cryptkey,smb_buf(inbuf),8);
3254 DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
3255 max_vcs = SVAL(inbuf,smb_vwv4);
3256 DEBUG(3,("max vcs %d\n",max_vcs));
3257 DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
3260 sec_mode = CVAL(inbuf,smb_vwv1);
3261 max_xmit = IVAL(inbuf,smb_vwv3+1);
3262 sesskey = IVAL(inbuf,smb_vwv7+1);
3263 serverzone = SVALS(inbuf,smb_vwv15+1)*60;
3264 /* this time arrives in real GMT */
3265 servertime = interpret_long_date(inbuf+smb_vwv11+1);
3266 crypt_len = CVAL(inbuf,smb_vwv16+1);
3267 memcpy(cryptkey,smb_buf(inbuf),8);
3268 if (IVAL(inbuf,smb_vwv9+1) & 1)
3269 readbraw_supported = writebraw_supported = True;
3270 DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
3271 max_vcs = SVAL(inbuf,smb_vwv2+1);
3272 DEBUG(3,("max vcs %d\n",max_vcs));
3273 DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
3274 DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
3277 DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
3278 DEBUG(3,("max xmt %d\n",max_xmit));
3279 DEBUG(3,("Got %d byte crypt key\n",crypt_len));
3280 DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
3282 doencrypt = ((sec_mode & 2) != 0);
3285 static BOOL done_time = False;
3287 DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
3288 asctime(LocalTime(&servertime)),
3289 -(double)(serverzone/3600.0)));
3299 pass = (char *)getpass("Password: ");
3301 /* use a blank username for the 2nd try with a blank password */
3302 if (tries++ && !*pass)
3305 if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
3308 int passlen = strlen(pass)+1;
3312 if (doencrypt && *pass) {
3313 DEBUG(3,("Using encrypted passwords\n"));
3315 SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
3321 /* if in share level security then don't send a password now */
3322 if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;}
3324 /* send a session setup command */
3325 bzero(outbuf,smb_size);
3327 if (Protocol < PROTOCOL_NT1) {
3328 set_message(outbuf,10,1 + strlen(username) + passlen,True);
3329 CVAL(outbuf,smb_com) = SMBsesssetupX;
3332 CVAL(outbuf,smb_vwv0) = 0xFF;
3333 SSVAL(outbuf,smb_vwv2,max_xmit);
3334 SSVAL(outbuf,smb_vwv3,2);
3335 SSVAL(outbuf,smb_vwv4,max_vcs-1);
3336 SIVAL(outbuf,smb_vwv5,sesskey);
3337 SSVAL(outbuf,smb_vwv7,passlen);
3338 p = smb_buf(outbuf);
3339 memcpy(p,pword,passlen);
3343 if (!doencrypt) passlen--;
3345 set_message(outbuf,13,0,True);
3346 CVAL(outbuf,smb_com) = SMBsesssetupX;
3349 CVAL(outbuf,smb_vwv0) = 0xFF;
3350 SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
3351 SSVAL(outbuf,smb_vwv3,2);
3352 SSVAL(outbuf,smb_vwv4,getpid());
3353 SIVAL(outbuf,smb_vwv5,sesskey);
3354 SSVAL(outbuf,smb_vwv7,passlen);
3355 SSVAL(outbuf,smb_vwv8,0);
3356 p = smb_buf(outbuf);
3357 memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
3358 strcpy(p,username);p = skip_string(p,1);
3359 strcpy(p,workgroup);p = skip_string(p,1);
3360 strcpy(p,"Unix");p = skip_string(p,1);
3361 strcpy(p,"Samba");p = skip_string(p,1);
3362 set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
3365 send_smb(Client,outbuf);
3366 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3370 if (CVAL(inbuf,smb_rcls) != 0)
3373 ((CVAL(inbuf,smb_rcls) == ERRDOS &&
3374 SVAL(inbuf,smb_err) == ERRnoaccess) ||
3375 (CVAL(inbuf,smb_rcls) == ERRSRV &&
3376 SVAL(inbuf,smb_err) == ERRbadpw)))
3379 DEBUG(3,("resending login\n"));
3383 DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n",
3384 username,myname,desthost,smb_errstr(inbuf)));
3385 DEBUG(0,("You might find the -U, -W or -n options useful\n"));
3386 DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
3387 DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
3396 if (Protocol >= PROTOCOL_NT1) {
3397 char *domain,*os,*lanman;
3400 lanman = skip_string(os,1);
3401 domain = skip_string(lanman,1);
3402 if (*domain || *os || *lanman)
3403 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
3406 /* use the returned uid from now on */
3407 if (SVAL(inbuf,smb_uid) != uid)
3408 DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
3409 SVAL(inbuf,smb_uid),uid));
3410 uid = SVAL(inbuf,smb_uid);
3413 /* now we've got a connection - send a tcon message */
3414 bzero(outbuf,smb_size);
3416 if (strncmp(service,"\\\\",2) != 0)
3418 DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
3419 DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
3426 int passlen = strlen(pass)+1;
3431 if (doencrypt && *pass) {
3433 SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
3437 /* if in user level security then don't send a password now */
3438 if ((sec_mode & 1)) {
3439 strcpy(pword, ""); passlen=1;
3442 if (Protocol <= PROTOCOL_COREPLUS) {
3443 set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
3444 CVAL(outbuf,smb_com) = SMBtcon;
3447 p = smb_buf(outbuf);
3450 p = skip_string(p,1);
3452 memcpy(p,pword,passlen);
3458 set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
3459 CVAL(outbuf,smb_com) = SMBtconX;
3462 SSVAL(outbuf,smb_vwv0,0xFF);
3463 SSVAL(outbuf,smb_vwv3,passlen);
3465 p = smb_buf(outbuf);
3466 memcpy(p,pword,passlen);
3469 p = skip_string(p,1);
3474 send_smb(Client,outbuf);
3475 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3477 /* trying again with a blank password */
3478 if (CVAL(inbuf,smb_rcls) != 0 &&
3479 (int)strlen(pass) > 0 &&
3481 Protocol >= PROTOCOL_LANMAN1)
3483 DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
3488 if (CVAL(inbuf,smb_rcls) != 0)
3490 DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
3491 DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
3492 DEBUG(0,("Some servers insist that these be in uppercase\n"));
3502 if (Protocol <= PROTOCOL_COREPLUS) {
3503 max_xmit = SVAL(inbuf,smb_vwv0);
3505 cnum = SVAL(inbuf,smb_vwv1);
3508 max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
3510 max_xmit = BUFFER_SIZE - 4;
3512 cnum = SVAL(inbuf,smb_tid);
3515 DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
3526 /****************************************************************************
3527 send a logout command
3528 ****************************************************************************/
3529 static void send_logout(void )
3531 pstring inbuf,outbuf;
3533 bzero(outbuf,smb_size);
3534 set_message(outbuf,0,0,True);
3535 CVAL(outbuf,smb_com) = SMBtdis;
3536 SSVAL(outbuf,smb_tid,cnum);
3539 send_smb(Client,outbuf);
3540 receive_smb(Client,inbuf,SHORT_TIMEOUT);
3542 if (CVAL(inbuf,smb_rcls) != 0)
3544 DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
3556 /****************************************************************************
3558 ****************************************************************************/
3559 static BOOL call_api(int prcnt,int drcnt,
3560 int mprcnt,int mdrcnt,
3561 int *rprcnt,int *rdrcnt,
3562 char *param,char *data,
3563 char **rparam,char **rdata)
3565 static char *inbuf=NULL;
3566 static char *outbuf=NULL;
3568 if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3569 if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3571 send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
3576 return (receive_trans_response(inbuf,SMBtrans,
3581 /****************************************************************************
3582 send a SMB trans or trans2 request
3583 ****************************************************************************/
3584 static BOOL send_trans_request(char *outbuf,int trans,
3585 char *name,int fid,int flags,
3586 char *data,char *param,uint16 *setup,
3587 int ldata,int lparam,int lsetup,
3588 int mdata,int mparam,int msetup)
3591 int this_ldata,this_lparam;
3592 int tot_data=0,tot_param=0;
3593 char *outdata,*outparam;
3597 this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
3598 this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
3600 bzero(outbuf,smb_size);
3601 set_message(outbuf,14+lsetup,0,True);
3602 CVAL(outbuf,smb_com) = trans;
3603 SSVAL(outbuf,smb_tid,cnum);
3606 outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
3607 outdata = outparam+this_lparam;
3609 /* primary request */
3610 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3611 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3612 SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */
3613 SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */
3614 SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */
3615 SSVAL(outbuf,smb_flags,flags); /* flags */
3616 SIVAL(outbuf,smb_timeout,0); /* timeout */
3617 SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
3618 SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
3619 SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */
3620 SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
3621 SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */
3622 for (i=0;i<lsetup;i++) /* setup[] */
3623 SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
3624 p = smb_buf(outbuf);
3625 if (trans==SMBtrans)
3626 strcpy(p,name); /* name[] */
3629 *p++ = 0; /* put in a null smb_name */
3630 *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */
3632 if (this_lparam) /* param[] */
3633 memcpy(outparam,param,this_lparam);
3634 if (this_ldata) /* data[] */
3635 memcpy(outdata,data,this_ldata);
3636 set_message(outbuf,14+lsetup, /* wcnt, bcc */
3637 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3640 send_smb(Client,outbuf);
3642 if (this_ldata < ldata || this_lparam < lparam)
3644 /* receive interim response */
3645 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
3647 DEBUG(0,("%s request failed (%s)\n",
3648 trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
3652 tot_data = this_ldata;
3653 tot_param = this_lparam;
3655 while (tot_data < ldata || tot_param < lparam)
3657 this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
3658 this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
3660 set_message(outbuf,trans==SMBtrans?8:9,0,True);
3661 CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
3663 outparam = smb_buf(outbuf);
3664 outdata = outparam+this_lparam;
3666 /* secondary request */
3667 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3668 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3669 SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
3670 SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
3671 SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */
3672 SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */
3673 SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
3674 SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */
3675 if (trans==SMBtrans2)
3676 SSVAL(outbuf,smb_sfid,fid); /* fid */
3677 if (this_lparam) /* param[] */
3678 memcpy(outparam,param,this_lparam);
3679 if (this_ldata) /* data[] */
3680 memcpy(outdata,data,this_ldata);
3681 set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
3682 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3685 send_smb(Client,outbuf);
3687 tot_data += this_ldata;
3688 tot_param += this_lparam;
3695 /****************************************************************************
3696 try and browse available connections on a host
3697 ****************************************************************************/
3698 static BOOL browse_host(BOOL sort)
3701 /* If strcasecmp is already defined, remove it. */
3704 #endif /* strcasecmp */
3705 #define strcasecmp StrCaseCmp
3706 #endif /* NOSTRCASECMP */
3708 extern int strcasecmp();
3710 char *rparam = NULL;
3717 /* now send a SMBtrans command with api RNetShareEnum */
3719 SSVAL(p,0,0); /* api number */
3722 p = skip_string(p,1);
3724 p = skip_string(p,1);
3726 SSVAL(p,2,BUFFER_SIZE);
3729 if (call_api(PTR_DIFF(p,param),0,
3735 int res = SVAL(rparam,0);
3736 int converter=SVAL(rparam,2);
3738 BOOL long_share_name=False;
3742 count=SVAL(rparam,4);
3747 printf("\n\tSharename Type Comment\n");
3748 printf("\t--------- ---- -------\n");
3752 qsort(p,count,20,QSORT_CAST strcasecmp);
3754 for (i=0;i<count;i++)
3757 int type = SVAL(p,14);
3758 int comment_offset = IVAL(p,16) & 0xFFFF;
3764 case STYPE_DISKTREE:
3765 strcpy(typestr,"Disk"); break;
3767 strcpy(typestr,"Printer"); break;
3769 strcpy(typestr,"Device"); break;
3771 strcpy(typestr,"IPC"); break;
3774 printf("\t%-15.15s%-10.10s%s\n",
3777 comment_offset?rdata+comment_offset-converter:"");
3779 if (strlen(sname)>8) long_share_name=True;
3784 if (long_share_name) {
3785 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3790 if (rparam) free(rparam);
3791 if (rdata) free(rdata);
3797 /****************************************************************************
3798 get some server info
3799 ****************************************************************************/
3800 static void server_info()
3802 char *rparam = NULL;
3808 bzero(param,sizeof(param));
3811 SSVAL(p,0,63); /* NetServerGetInfo()? */
3814 p = skip_string(p,1);
3815 strcpy(p,"zzzBBzz");
3816 p = skip_string(p,1);
3817 SSVAL(p,0,10); /* level 10 */
3821 if (call_api(PTR_DIFF(p,param),0,
3827 int res = SVAL(rparam,0);
3828 int converter=SVAL(rparam,2);
3834 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3835 rdata+SVAL(p,0)-converter,
3836 rdata+SVAL(p,4)-converter,
3837 rdata+SVAL(p,8)-converter,
3838 rdata+SVAL(p,14)-converter);
3842 if (rparam) free(rparam);
3843 if (rdata) free(rdata);
3849 /****************************************************************************
3850 try and browse available connections on a host
3851 ****************************************************************************/
3852 static BOOL list_servers(char *wk_grp)
3854 char *rparam = NULL;
3862 BOOL generic_request = False;
3865 if (strequal(wk_grp,"WORKGROUP")) {
3866 /* we won't specify a workgroup */
3867 generic_request = True;
3870 /* now send a SMBtrans command with api ServerEnum? */
3872 SSVAL(p,0,0x68); /* api number */
3875 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3876 p = skip_string(p,1);
3878 strcpy(p,"B16BBDz");
3880 p = skip_string(p,1);
3882 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3888 if (!generic_request) {
3890 p = skip_string(p,1);
3893 /* first ask for a list of servers in this workgroup */
3894 SIVAL(svtype_p,0,SV_TYPE_ALL);
3896 if (call_api(PTR_DIFF(p+4,param),0,
3897 8,BUFFER_SIZE - SAFETY_MARGIN,
3902 int res = SVAL(rparam,0);
3903 int converter=SVAL(rparam,2);
3908 count=SVAL(rparam,4);
3911 printf("\n\nThis machine has a browse list:\n");
3912 printf("\n\tServer Comment\n");
3913 printf("\t--------- -------\n");
3916 for (i=0;i<count;i++) {
3918 int comment_offset = IVAL(p2,22) & 0xFFFF;
3919 printf("\t%-16.16s %s\n",
3921 comment_offset?rdata+comment_offset-converter:"");
3929 if (rparam) {free(rparam); rparam = NULL;}
3930 if (rdata) {free(rdata); rdata = NULL;}
3932 /* now ask for a list of workgroups */
3933 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3935 if (call_api(PTR_DIFF(p+4,param),0,
3936 8,BUFFER_SIZE - SAFETY_MARGIN,
3941 int res = SVAL(rparam,0);
3942 int converter=SVAL(rparam,2);
3947 count=SVAL(rparam,4);
3950 printf("\n\nThis machine has a workgroup list:\n");
3951 printf("\n\tWorkgroup Master\n");
3952 printf("\t--------- -------\n");
3955 for (i=0;i<count;i++) {
3957 int comment_offset = IVAL(p2,22) & 0xFFFF;
3958 printf("\t%-16.16s %s\n",
3960 comment_offset?rdata+comment_offset-converter:"");
3968 if (rparam) free(rparam);
3969 if (rdata) free(rdata);
3975 /* This defines the commands supported by this client */
3983 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3984 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3985 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3986 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3987 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3988 {"get",cmd_get,"<remote name> [local name] get a file"},
3989 {"mget",cmd_mget,"<mask> get all the matching files"},
3990 {"put",cmd_put,"<local name> [remote name] put a file"},
3991 {"mput",cmd_mput,"<mask> put all matching files"},
3992 {"rename",cmd_rename,"<src> <dest> rename some files"},
3993 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3994 {"mask",cmd_select,"<mask> mask all filenames against this"},
3995 {"del",cmd_del,"<mask> delete all matching files"},
3996 {"rm",cmd_del,"<mask> delete all matching files"},
3997 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3998 {"md",cmd_mkdir,"<directory> make a directory"},
3999 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
4000 {"rd",cmd_rmdir,"<directory> remove a directory"},
4001 {"pq",cmd_p_queue_4,"enumerate the print queue"},
4002 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
4003 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
4004 {"translate",cmd_translate,"toggle text translation for printing"},
4005 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
4006 {"print",cmd_print,"<file name> print a file"},
4007 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
4008 {"queue",cmd_queue,"show the print queue"},
4009 {"qinfo",cmd_qinfo,"show print queue information"},
4010 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
4011 {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
4012 {"quit",send_logout,"logoff the server"},
4013 {"q",send_logout,"logoff the server"},
4014 {"exit",send_logout,"logoff the server"},
4015 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
4016 {"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"},
4017 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
4018 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
4019 {"tarmode",cmd_tarmode,
4020 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
4021 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
4022 {"help",cmd_help,"[command] give help on a command"},
4023 {"?",cmd_help,"[command] give help on a command"},
4024 {"!",NULL,"run a shell command on the local system"},
4029 /*******************************************************************
4030 lookup a command string in the list of commands, including
4032 ******************************************************************/
4033 static int process_tok(fstring tok)
4035 int i = 0, matches = 0;
4037 int tok_len = strlen(tok);
4039 while (commands[i].fn != NULL)
4041 if (strequal(commands[i].name,tok))
4047 else if (strnequal(commands[i].name, tok, tok_len+1))
4057 else if (matches == 1)
4063 /****************************************************************************
4065 ****************************************************************************/
4071 if (next_token(NULL,buf,NULL))
4073 if ((i = process_tok(buf)) >= 0)
4074 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
4077 while (commands[i].description)
4079 for (j=0; commands[i].description && (j<5); j++) {
4080 DEBUG(0,("%-15s",commands[i].name));
4087 /****************************************************************************
4088 open the client sockets
4089 ****************************************************************************/
4090 static BOOL open_sockets(int port )
4092 static int last_port;
4100 if (port == 0) port=last_port;
4111 strcpy(service2,service);
4112 host = strtok(service2,"\\/");
4114 DEBUG(0,("Badly formed host name\n"));
4117 strcpy(desthost,host);
4121 get_myname(myname,NULL);
4125 DEBUG(3,("Opening sockets\n"));
4131 if ((hp = Get_Hostbyname(host))) {
4132 putip((char *)&dest_ip,(char *)hp->h_addr);
4136 /* Try and resolve the name with the netbios server */
4139 if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
4140 interpret_addr(lp_socket_address()))) != -1) {
4141 set_socket_options(bcast, "SO_BROADCAST");
4143 if (name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
4151 DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
4157 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
4161 DEBUG(3,("Connected\n"));
4163 set_socket_options(Client,user_socket_options);
4168 /****************************************************************************
4169 wait for keyboard activity, swallowing network packets
4170 ****************************************************************************/
4172 static char wait_keyboard(char *buffer)
4174 static void wait_keyboard(char *buffer)
4179 struct timeval timeout;
4189 FD_SET(Client,&fds);
4191 FD_SET(fileno(stdin),&fds);
4194 timeout.tv_sec = 20;
4195 timeout.tv_usec = 0;
4199 selrtn = sys_select(&fds,&timeout);
4202 if (FD_ISSET(fileno(stdin),&fds))
4209 set_blocking(fileno(stdin), False);
4210 readret = read_data( fileno(stdin), &ch, 1);
4211 set_blocking(fileno(stdin), True);
4214 if (errno != EAGAIN)
4216 /* should crash here */
4217 DEBUG(1,("readchar stdin failed\n"));
4220 else if (readret != 0)
4226 if (FD_ISSET(Client,&fds))
4227 receive_smb(Client,buffer,0);
4234 chkpath("\\",False);
4237 chkpath("\\",False);
4243 /****************************************************************************
4244 close and open the connection again
4245 ****************************************************************************/
4246 BOOL reopen_connection(char *inbuf,char *outbuf)
4248 static int open_count=0;
4252 if (open_count>5) return(False);
4254 DEBUG(1,("Trying to re-open connection\n"));
4256 set_message(outbuf,0,0,True);
4257 SCVAL(outbuf,smb_com,SMBtdis);
4258 SSVAL(outbuf,smb_tid,cnum);
4261 send_smb(Client,outbuf);
4262 receive_smb(Client,inbuf,SHORT_TIMEOUT);
4265 if (!open_sockets(0)) return(False);
4267 return(send_login(inbuf,outbuf,True,True));
4270 /****************************************************************************
4271 process commands from the client
4272 ****************************************************************************/
4273 static BOOL process(char *base_directory)
4279 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4280 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4282 if ((InBuffer == NULL) || (OutBuffer == NULL))
4285 bzero(OutBuffer,smb_size);
4287 if (!send_login(InBuffer,OutBuffer,True,True))
4290 if (*base_directory) do_cd(base_directory);
4293 if (cmd[0] != '\0') while (cmd[0] != '\0')
4299 if ((p = strchr(cmd, ';')) == 0)
4301 strncpy(line, cmd, 999);
4307 if (p - cmd > 999) p = cmd + 999;
4308 strncpy(line, cmd, p - cmd);
4309 line[p - cmd] = '\0';
4313 /* input language code to internal one */
4316 /* and get the first part of the command */
4319 if (!next_token(&ptr,tok,NULL)) continue;
4322 if ((i = process_tok(tok)) >= 0)
4323 commands[i].fn(InBuffer,OutBuffer);
4325 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4327 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4329 else while (!feof(stdin))
4334 bzero(OutBuffer,smb_size);
4336 /* display a prompt */
4337 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
4341 line[0] = wait_keyboard(InBuffer);
4342 /* this might not be such a good idea... */
4343 if ( line[0] == EOF)
4346 wait_keyboard(InBuffer);
4349 /* and get a response */
4351 fgets( &line[1],999, stdin);
4353 if (!fgets(line,1000,stdin))
4357 /* input language code to internal one */
4360 /* special case - first char is ! */
4367 /* and get the first part of the command */
4370 if (!next_token(&ptr,tok,NULL)) continue;
4373 if ((i = process_tok(tok)) >= 0)
4374 commands[i].fn(InBuffer,OutBuffer);
4376 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4378 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4386 /****************************************************************************
4387 usage on the program
4388 ****************************************************************************/
4389 static void usage(char *pname)
4391 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
4395 DEBUG(0,("[-t termcode] "));
4398 DEBUG(0,("\nVersion %s\n",VERSION));
4399 DEBUG(0,("\t-p port listen on the specified port\n"));
4400 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
4401 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
4402 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
4403 DEBUG(0,("\t-N don't ask for a password\n"));
4404 DEBUG(0,("\t-P connect to service as a printer\n"));
4405 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
4406 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
4407 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
4408 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
4409 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
4410 DEBUG(0,("\t-U username set the network username\n"));
4411 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
4412 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
4414 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
4416 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
4417 DEBUG(0,("\t-D directory start from directory\n"));
4421 /****************************************************************************
4423 ****************************************************************************/
4424 int main(int argc,char *argv[])
4426 fstring base_directory;
4427 char *pname = argv[0];
4428 int port = SMB_PORT;
4431 extern char *optarg;
4434 BOOL message = False;
4435 extern char tar_type;
4436 static pstring servicesf = CONFIGFILE;
4439 *base_directory = 0;
4443 setup_logging(pname,True);
4446 charset_initialise();
4457 strcpy(username,getenv("USER"));
4461 if (*username == 0 && getenv("LOGNAME"))
4463 strcpy(username,getenv("LOGNAME"));
4473 if (*argv[1] != '-')
4476 strcpy(service,argv[1]);
4477 /* Convert any '/' characters in the service name to '\' characters */
4478 string_replace( service, '/','\\');
4482 if (count_chars(service,'\\') < 3)
4485 printf("\n%s: Not enough '\\' characters in service\n",service);
4490 if (count_chars(service,'\\') > 3)
4493 printf("\n%s: Too many '\\' characters in service\n",service);
4498 if (argc > 1 && (*argv[1] != '-'))
4501 strcpy(password,argv[1]);
4502 memset(argv[1],'X',strlen(argv[1]));
4509 setup_term_code (KANJI);
4512 getopt(argc, argv,"s:B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
4516 max_protocol = interpret_protocol(optarg,max_protocol);
4519 strcpy(user_socket_options,optarg);
4522 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
4523 strcpy(desthost,optarg);
4528 iface_set_default(NULL,optarg,NULL);
4531 strcpy(base_directory,optarg);
4534 if (!tar_parseargs(argc, argv, optarg, optind)) {
4540 strcpy(scope,optarg);
4544 strcpy(query_host,optarg);
4549 strcpy(username,optarg);
4550 if ((p=strchr(username,'%')))
4553 strcpy(password,p+1);
4555 memset(strchr(optarg,'%')+1,'X',strlen(password));
4561 strcpy(workgroup,optarg);
4568 dest_ip = *interpret_addr2(optarg);
4569 if (zero_ip(dest_ip)) exit(1);
4574 strcpy(myname,optarg);
4580 connect_as_printer = True;
4586 DEBUGLEVEL = atoi(optarg);
4589 sprintf(debugf,"%s.client",optarg);
4592 port = atoi(optarg);
4603 strcpy(servicesf, optarg);
4607 if (!setup_term_code (optarg)) {
4608 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
4619 if (!tar_type && !*query_host && !*service && !message)
4626 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
4628 if (!lp_load(servicesf,True)) {
4629 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
4632 if (*workgroup == 0)
4633 strcpy(workgroup,lp_workgroup());
4636 get_myname(*myname?NULL:myname,NULL);
4642 if (open_sockets(port)) {
4643 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4644 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4647 if ((InBuffer == NULL) || (OutBuffer == NULL))
4650 bzero(OutBuffer,smb_size);
4651 if (!send_login(InBuffer,OutBuffer,True,True))
4654 if (*base_directory) do_cd(base_directory);
4656 ret=process_tar(InBuffer, OutBuffer);
4668 sprintf(service,"\\\\%s\\IPC$",query_host);
4670 connect_as_ipc = True;
4671 if (open_sockets(port))
4676 if (!send_login(NULL,NULL,True,True))
4680 if (!browse_host(True)) {
4684 if (!list_servers(workgroup)) {
4686 list_servers(workgroup);
4699 if (open_sockets(port))
4701 pstring inbuf,outbuf;
4702 bzero(outbuf,smb_size);
4703 if (!send_session_request(inbuf,outbuf))
4706 send_message(inbuf,outbuf);
4714 if (open_sockets(port))
4716 if (!process(base_directory))
4730 /* error code stuff - put together by Merik Karman
4731 merik@blackadder.dsh.oz.au */
4740 /* Dos Error Messages */
4741 err_code_struct dos_msgs[] = {
4742 {"ERRbadfunc",1,"Invalid function."},
4743 {"ERRbadfile",2,"File not found."},
4744 {"ERRbadpath",3,"Directory invalid."},
4745 {"ERRnofids",4,"No file descriptors available"},
4746 {"ERRnoaccess",5,"Access denied."},
4747 {"ERRbadfid",6,"Invalid file handle."},
4748 {"ERRbadmcb",7,"Memory control blocks destroyed."},
4749 {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
4750 {"ERRbadmem",9,"Invalid memory block address."},
4751 {"ERRbadenv",10,"Invalid environment."},
4752 {"ERRbadformat",11,"Invalid format."},
4753 {"ERRbadaccess",12,"Invalid open mode."},
4754 {"ERRbaddata",13,"Invalid data."},
4755 {"ERR",14,"reserved."},
4756 {"ERRbaddrive",15,"Invalid drive specified."},
4757 {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
4758 {"ERRdiffdevice",17,"Not same device."},
4759 {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
4760 {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
4761 {"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."},
4762 {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
4763 {"ERRbadpipe",230,"Pipe invalid."},
4764 {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
4765 {"ERRpipeclosing",232,"Pipe close in progress."},
4766 {"ERRnotconnected",233,"No process on other end of pipe."},
4767 {"ERRmoredata",234,"There is more data to be returned."},
4768 {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
4771 /* Server Error Messages */
4772 err_code_struct server_msgs[] = {
4773 {"ERRerror",1,"Non-specific error code."},
4774 {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
4775 {"ERRbadtype",3,"reserved."},
4776 {"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."},
4777 {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
4778 {"ERRinvnetname",6,"Invalid network name in tree connect."},
4779 {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
4780 {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
4781 {"ERRqtoobig",50,"Print queue full -- no space."},
4782 {"ERRqeof",51,"EOF on print queue dump."},
4783 {"ERRinvpfid",52,"Invalid print file FID."},
4784 {"ERRsmbcmd",64,"The server did not recognize the command received."},
4785 {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
4786 {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
4787 {"ERRreserved",68,"reserved."},
4788 {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
4789 {"ERRreserved",70,"reserved."},
4790 {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
4791 {"ERRpaused",81,"Server is paused."},
4792 {"ERRmsgoff",82,"Not receiving messages."},
4793 {"ERRnoroom",83,"No room to buffer message."},
4794 {"ERRrmuns",87,"Too many remote user names."},
4795 {"ERRtimeout",88,"Operation timed out."},
4796 {"ERRnoresource",89,"No resources currently available for request."},
4797 {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
4798 {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
4799 {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
4800 {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
4801 {"ERRcontmpx",252,"Continue in MPX mode."},
4802 {"ERRreserved",253,"reserved."},
4803 {"ERRreserved",254,"reserved."},
4804 {"ERRnosupport",0xFFFF,"Function not supported."},
4807 /* Hard Error Messages */
4808 err_code_struct hard_msgs[] = {
4809 {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
4810 {"ERRbadunit",20,"Unknown unit."},
4811 {"ERRnotready",21,"Drive not ready."},
4812 {"ERRbadcmd",22,"Unknown command."},
4813 {"ERRdata",23,"Data error (CRC)."},
4814 {"ERRbadreq",24,"Bad request structure length."},
4815 {"ERRseek",25 ,"Seek error."},
4816 {"ERRbadmedia",26,"Unknown media type."},
4817 {"ERRbadsector",27,"Sector not found."},
4818 {"ERRnopaper",28,"Printer out of paper."},
4819 {"ERRwrite",29,"Write fault."},
4820 {"ERRread",30,"Read fault."},
4821 {"ERRgeneral",31,"General failure."},
4822 {"ERRbadshare",32,"An open conflicts with an existing open."},
4823 {"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."},
4824 {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
4825 {"ERRFCBUnavail",35,"No FCBs are available to process request."},
4826 {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
4834 err_code_struct *err_msgs;
4837 {0x01,"ERRDOS",dos_msgs},
4838 {0x02,"ERRSRV",server_msgs},
4839 {0x03,"ERRHRD",hard_msgs},
4840 {0x04,"ERRXOS",NULL},
4841 {0xE1,"ERRRMX1",NULL},
4842 {0xE2,"ERRRMX2",NULL},
4843 {0xE3,"ERRRMX3",NULL},
4844 {0xFF,"ERRCMD",NULL},
4848 /****************************************************************************
4849 return a SMB error string from a SMB buffer
4850 ****************************************************************************/
4851 char *smb_errstr(char *inbuf)
4854 int class = CVAL(inbuf,smb_rcls);
4855 int num = SVAL(inbuf,smb_err);
4858 for (i=0;err_classes[i].class;i++)
4859 if (err_classes[i].code == class)
4861 if (err_classes[i].err_msgs)
4863 err_code_struct *err = err_classes[i].err_msgs;
4864 for (j=0;err[j].name;j++)
4865 if (num == err[j].code)
4868 sprintf(ret,"%s - %s (%s)",err_classes[i].class,
4869 err[j].name,err[j].message);
4871 sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
4876 sprintf(ret,"%s - %d",err_classes[i].class,num);
4880 sprintf(ret,"Error: Unknown error (%d,%d)",class,num);