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 extern pstring myhostname;
38 pstring password = "";
42 BOOL got_pass = False;
43 BOOL connect_as_printer = False;
44 BOOL connect_as_ipc = False;
45 extern struct in_addr ipzero;
50 extern pstring user_socket_options;
52 /* 30 second timeout on most commands */
53 #define CLIENT_TIMEOUT (30*1000)
54 #define SHORT_TIMEOUT (5*1000)
56 /* value for unused fid field in trans2 secondary request */
57 #define FID_UNUSED (0xFFFF)
61 int max_protocol = PROTOCOL_NT1;
64 time_t newer_than = 0;
65 int archive_level = 0;
67 extern pstring debugf;
68 extern int DEBUGLEVEL;
70 BOOL translation = False;
73 static BOOL send_trans_request(char *outbuf,int trans,
74 char *name,int fid,int flags,
75 char *data,char *param,uint16 *setup,
76 int ldata,int lparam,int lsetup,
77 int mdata,int mparam,int msetup);
78 static BOOL receive_trans_response(char *inbuf,int trans,
79 int *data_len,int *param_len,
80 char **data,char **param);
81 static int interpret_long_filename(int level,char *p,file_info *finfo);
82 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir);
83 static int interpret_short_filename(char *p,file_info *finfo);
84 static BOOL call_api(int prcnt,int drcnt,
85 int mprcnt,int mdrcnt,
86 int *rprcnt,int *rdrcnt,
87 char *param,char *data,
88 char **rparam,char **rdata);
89 static BOOL do_this_one(file_info *finfo);
91 /* clitar bits insert */
94 extern BOOL tar_reset;
105 int max_xmit = BUFFER_SIZE;
107 extern pstring scope;
113 BOOL recurse = False;
114 BOOL lowercase = False;
116 BOOL have_ip = False;
118 struct in_addr dest_ip;
120 #define SEPARATORS " \t\n\r"
122 BOOL abort_mget = True;
126 BOOL readbraw_supported = False;
127 BOOL writebraw_supported = False;
129 pstring fileselection = "";
131 extern file_info def_finfo;
134 int get_total_size = 0;
135 int get_total_time_ms = 0;
136 int put_total_size = 0;
137 int put_total_time_ms = 0;
147 extern int coding_system;
148 #define CNV_LANG(s) (coding_system == DOSV_CODE?s:dos_to_unix(s, False))
149 #define CNV_INPUT(s) (coding_system == DOSV_CODE?s:unix_to_dos(s, True))
151 setup_term_code (char *code)
154 new = interpret_coding_system (code, UNKNOWN_CODE);
155 if (new != UNKNOWN_CODE) {
162 #define CNV_LANG(s) dos2unix_format(s,False)
163 #define CNV_INPUT(s) unix2dos_format(s,True)
166 /****************************************************************************
167 setup basics in a outgoing packet
168 ****************************************************************************/
169 void setup_pkt(char *outbuf)
171 SSVAL(outbuf,smb_pid,pid);
172 SSVAL(outbuf,smb_uid,uid);
173 SSVAL(outbuf,smb_mid,mid);
174 if (Protocol > PROTOCOL_COREPLUS)
176 SCVAL(outbuf,smb_flg,0x8);
177 SSVAL(outbuf,smb_flg2,0x1);
181 /****************************************************************************
182 write to a local file with CR/LF->LF translation if appropriate. return the
183 number taken from the buffer. This may not equal the number written.
184 ****************************************************************************/
185 static int writefile(int f, char *b, int n)
190 return(write(f,b,n));
195 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
199 if (write(f, b, 1) != 1)
210 /****************************************************************************
211 read from a file with LF->CR/LF translation if appropriate. return the
212 number read. read approx n bytes.
213 ****************************************************************************/
214 static int readfile(char *b, int size, int n, FILE *f)
219 if (!translation || (size != 1))
220 return(fread(b,size,n,f));
225 if ((c = getc(f)) == EOF)
230 if (c == '\n') /* change all LFs to CR/LF */
244 /****************************************************************************
245 read from a file with print translation. return the number read. read approx n
247 ****************************************************************************/
248 static int printread(FILE *f,char *b,int n)
252 i = readfile(b,1, n-1,f);
261 /****************************************************************************
262 check for existance of a dir
263 ****************************************************************************/
264 static BOOL chkpath(char *path,BOOL report)
267 pstring inbuf,outbuf;
271 trim_string(path2,NULL,"\\");
272 if (!*path2) *path2 = '\\';
274 bzero(outbuf,smb_size);
275 set_message(outbuf,0,4 + strlen(path2),True);
276 SCVAL(outbuf,smb_com,SMBchkpth);
277 SSVAL(outbuf,smb_tid,cnum);
284 send_smb(Client,outbuf);
285 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
287 if (report && CVAL(inbuf,smb_rcls) != 0)
288 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
290 return(CVAL(inbuf,smb_rcls) == 0);
294 /****************************************************************************
296 ****************************************************************************/
297 static void send_message(char *inbuf,char *outbuf)
304 /* send a SMBsendstrt command */
305 bzero(outbuf,smb_size);
306 set_message(outbuf,0,0,True);
307 CVAL(outbuf,smb_com) = SMBsendstrt;
308 SSVAL(outbuf,smb_tid,cnum);
313 p = skip_string(p,1);
316 p = skip_string(p,1);
318 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
320 send_smb(Client,outbuf);
323 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
325 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
329 grp_id = SVAL(inbuf,smb_vwv0);
331 printf("Connected. Type your message, ending it with a Control-D\n");
333 while (!feof(stdin) && total_len < 1600)
335 int maxlen = MIN(1600 - total_len,127);
342 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
349 CVAL(outbuf,smb_com) = SMBsendtxt;
351 set_message(outbuf,1,l+3,True);
353 SSVAL(outbuf,smb_vwv0,grp_id);
360 send_smb(Client,outbuf);
363 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
365 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
372 if (total_len >= 1600)
373 printf("the message was truncated to 1600 bytes ");
375 printf("sent %d bytes ",total_len);
377 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
379 CVAL(outbuf,smb_com) = SMBsendend;
380 set_message(outbuf,1,0,False);
381 SSVAL(outbuf,smb_vwv0,grp_id);
383 send_smb(Client,outbuf);
386 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
388 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
395 /****************************************************************************
396 check the space on a device
397 ****************************************************************************/
398 static void do_dskattr(void)
400 pstring inbuf,outbuf;
402 bzero(outbuf,smb_size);
403 set_message(outbuf,0,0,True);
404 CVAL(outbuf,smb_com) = SMBdskattr;
405 SSVAL(outbuf,smb_tid,cnum);
408 send_smb(Client,outbuf);
409 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
411 if (CVAL(inbuf,smb_rcls) != 0)
412 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
414 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
415 SVAL(inbuf,smb_vwv0),
416 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
417 SVAL(inbuf,smb_vwv3)));
420 /****************************************************************************
422 ****************************************************************************/
423 static void cmd_pwd(void)
425 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
426 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
430 /****************************************************************************
431 change directory - inner section
432 ****************************************************************************/
433 static void do_cd(char *newdir)
439 /* Save the current directory in case the
440 new directory is invalid */
441 strcpy(saved_dir, cur_dir);
446 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
447 strcat(cur_dir, "\\");
449 dos_clean_name(cur_dir);
450 strcpy(dname,cur_dir);
451 strcat(cur_dir,"\\");
452 dos_clean_name(cur_dir);
454 if (!strequal(cur_dir,"\\"))
455 if (!chkpath(dname,True))
456 strcpy(cur_dir,saved_dir);
458 strcpy(cd_path,cur_dir);
461 /****************************************************************************
463 ****************************************************************************/
464 static void cmd_cd(char *inbuf,char *outbuf)
468 if (next_token(NULL,buf,NULL))
471 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
475 /****************************************************************************
476 display info about a file
477 ****************************************************************************/
478 static void display_finfo(file_info *finfo)
480 if (do_this_one(finfo)) {
481 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
482 DEBUG(0,(" %-30s%7.7s%10d %s",
483 CNV_LANG(finfo->name),
484 attrib_string(finfo->mode),
486 asctime(LocalTime(&t))));
487 dir_total += finfo->size;
492 /****************************************************************************
493 do a directory listing, calling fn on each file found. Use the TRANSACT2
494 call for long filenames
495 ****************************************************************************/
496 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
498 int max_matches = 512;
499 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
504 char *dirlist = NULL;
506 int total_received = 0;
508 char *resp_data=NULL;
509 char *resp_param=NULL;
510 int resp_data_len = 0;
511 int resp_param_len=0;
513 int ff_resume_key = 0;
514 int ff_searchcount=0;
528 if (loop_count > 200)
530 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
536 setup = TRANSACT2_FINDFIRST;
537 SSVAL(param,0,attribute); /* attribute */
538 SSVAL(param,2,max_matches); /* max count */
539 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
540 SSVAL(param,6,info_level);
542 strcpy(param+12,mask);
546 setup = TRANSACT2_FINDNEXT;
547 SSVAL(param,0,ff_dir_handle);
548 SSVAL(param,2,max_matches); /* max count */
549 SSVAL(param,4,info_level);
550 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
551 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
552 strcpy(param+12,mask);
554 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
555 ff_dir_handle,ff_resume_key,ff_lastname,mask));
557 /* ??? original code added 1 pad byte after param */
559 send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
561 0,12+strlen(mask)+1,1,
564 if (!receive_trans_response(inbuf,SMBtrans2,
565 &resp_data_len,&resp_param_len,
566 &resp_data,&resp_param))
568 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
572 /* parse out some important return info */
576 ff_dir_handle = SVAL(p,0);
577 ff_searchcount = SVAL(p,2);
579 ff_lastname = SVAL(p,8);
583 ff_searchcount = SVAL(p,0);
585 ff_lastname = SVAL(p,6);
588 if (ff_searchcount == 0)
591 /* point to the data bytes */
594 /* we might need the lastname for continuations */
601 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
602 /* strcpy(mask,p+ff_lastname+94); */
605 strcpy(mask,p + ff_lastname + 1);
613 /* and add them to the dirlist pool */
614 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
618 DEBUG(0,("Failed to expand dirlist\n"));
622 /* put in a length for the last entry, to ensure we can chain entries
623 into the next packet */
626 for (p2=p,i=0;i<(ff_searchcount-1);i++)
627 p2 += interpret_long_filename(info_level,p2,NULL);
628 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
631 /* grab the data for later use */
632 memcpy(dirlist+dirlist_len,p,resp_data_len);
633 dirlist_len += resp_data_len;
635 total_received += ff_searchcount;
637 if (resp_data) free(resp_data); resp_data = NULL;
638 if (resp_param) free(resp_param); resp_param = NULL;
640 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
641 ff_searchcount,ff_eos,ff_resume_key));
647 for (p=dirlist,i=0;i<total_received;i++)
649 p += interpret_long_filename(info_level,p,&finfo);
650 display_finfo(&finfo);
653 for (p=dirlist,i=0;i<total_received;i++)
655 p += interpret_long_filename(info_level,p,&finfo);
656 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
659 /* free up the dirlist buffer */
660 if (dirlist) free(dirlist);
661 return(total_received);
665 /****************************************************************************
666 do a directory listing, calling fn on each file found
667 ****************************************************************************/
668 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
674 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
675 int num_received = 0;
677 char *dirlist = NULL;
689 bzero(outbuf,smb_size);
691 set_message(outbuf,2,5 + strlen(mask),True);
693 set_message(outbuf,2,5 + 21,True);
696 if (Protocol >= PROTOCOL_LANMAN1)
697 CVAL(outbuf,smb_com) = SMBffirst;
700 CVAL(outbuf,smb_com) = SMBsearch;
702 SSVAL(outbuf,smb_tid,cnum);
705 SSVAL(outbuf,smb_vwv0,num_asked);
706 SSVAL(outbuf,smb_vwv1,attribute);
727 send_smb(Client,outbuf);
728 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
730 received = SVAL(inbuf,smb_vwv0);
732 DEBUG(5,("dir received %d\n",received));
734 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
736 if (received <= 0) break;
740 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
745 p = smb_buf(inbuf) + 3;
747 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
748 p,received*DIR_STRUCT_SIZE);
750 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
752 num_received += received;
754 if (CVAL(inbuf,smb_rcls) != 0) break;
758 if (!first && Protocol >= PROTOCOL_LANMAN1)
760 bzero(outbuf,smb_size);
761 CVAL(outbuf,smb_com) = SMBfclose;
763 SSVAL(outbuf,smb_tid,cnum);
777 send_smb(Client,outbuf);
778 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
780 if (CVAL(inbuf,smb_rcls) != 0)
781 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
786 for (p=dirlist,i=0;i<num_received;i++)
788 p += interpret_short_filename(p,&finfo);
789 display_finfo(&finfo);
792 for (p=dirlist,i=0;i<num_received;i++)
794 p += interpret_short_filename(p,&finfo);
795 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
798 if (dirlist) free(dirlist);
799 return(num_received);
804 /****************************************************************************
805 do a directory listing, calling fn on each file found
806 ****************************************************************************/
807 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
809 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
810 if (Protocol >= PROTOCOL_LANMAN2)
812 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
816 expand_mask(Mask,False);
817 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
821 /*******************************************************************
822 decide if a file should be operated on
823 ********************************************************************/
824 static BOOL do_this_one(file_info *finfo)
826 if (finfo->mode & aDIR) return(True);
828 if (newer_than && finfo->mtime < newer_than)
831 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
838 /*****************************************************************************
839 Convert a character pointer in a call_api() response to a form we can use.
840 This function contains code to prevent core dumps if the server returns
842 *****************************************************************************/
843 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
845 if( datap == 0 ) /* turn NULL pointers */
846 { /* into zero length strings */
851 unsigned int offset = datap - converter;
853 if( offset >= rdrcnt )
855 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
860 return &rdata[offset];
865 /****************************************************************************
866 interpret a short filename structure
867 The length of the structure is returned
868 ****************************************************************************/
869 static int interpret_short_filename(char *p,file_info *finfo)
871 finfo->mode = CVAL(p,21);
873 /* this date is converted to GMT by make_unix_date */
874 finfo->ctime = make_unix_date(p+22);
875 finfo->mtime = finfo->atime = finfo->ctime;
876 finfo->size = IVAL(p,26);
877 strcpy(finfo->name,p+30);
879 return(DIR_STRUCT_SIZE);
882 /****************************************************************************
883 interpret a long filename structure - this is mostly guesses at the moment
884 The length of the structure is returned
885 The structure of a long filename depends on the info level. 260 is used
886 by NT and 2 is used by OS/2
887 ****************************************************************************/
888 static int interpret_long_filename(int level,char *p,file_info *finfo)
891 memcpy(finfo,&def_finfo,sizeof(*finfo));
895 case 1: /* OS/2 understands this */
898 /* these dates are converted to GMT by make_unix_date */
899 finfo->ctime = make_unix_date2(p+4);
900 finfo->atime = make_unix_date2(p+8);
901 finfo->mtime = make_unix_date2(p+12);
902 finfo->size = IVAL(p,16);
903 finfo->mode = CVAL(p,24);
904 strcpy(finfo->name,p+27);
906 return(28 + CVAL(p,26));
908 case 2: /* this is what OS/2 uses mostly */
911 /* these dates are converted to GMT by make_unix_date */
912 finfo->ctime = make_unix_date2(p+4);
913 finfo->atime = make_unix_date2(p+8);
914 finfo->mtime = make_unix_date2(p+12);
915 finfo->size = IVAL(p,16);
916 finfo->mode = CVAL(p,24);
917 strcpy(finfo->name,p+31);
919 return(32 + CVAL(p,30));
921 /* levels 3 and 4 are untested */
925 /* these dates are probably like the other ones */
926 finfo->ctime = make_unix_date2(p+8);
927 finfo->atime = make_unix_date2(p+12);
928 finfo->mtime = make_unix_date2(p+16);
929 finfo->size = IVAL(p,20);
930 finfo->mode = CVAL(p,28);
931 strcpy(finfo->name,p+33);
938 /* these dates are probably like the other ones */
939 finfo->ctime = make_unix_date2(p+8);
940 finfo->atime = make_unix_date2(p+12);
941 finfo->mtime = make_unix_date2(p+16);
942 finfo->size = IVAL(p,20);
943 finfo->mode = CVAL(p,28);
944 strcpy(finfo->name,p+37);
948 case 260: /* NT uses this, but also accepts 2 */
953 p += 4; /* next entry offset */
954 p += 4; /* fileindex */
956 /* these dates appear to arrive in a weird way. It seems to
957 be localtime plus the serverzone given in the initial
958 connect. This is GMT when DST is not in effect and one
959 hour from GMT otherwise. Can this really be right??
961 I suppose this could be called kludge-GMT. Is is the GMT
962 you get by using the current DST setting on a different
963 localtime. It will be cheap to calculate, I suppose, as
964 no DST tables will be needed */
966 finfo->ctime = interpret_long_date(p); p += 8;
967 finfo->atime = interpret_long_date(p); p += 8;
968 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
969 finfo->size = IVAL(p,0); p += 8;
970 p += 8; /* alloc size */
971 finfo->mode = CVAL(p,0); p += 4;
972 namelen = IVAL(p,0); p += 4;
973 p += 4; /* EA size */
974 p += 2; /* short name len? */
975 p += 24; /* short name? */
976 StrnCpy(finfo->name,p,namelen);
982 DEBUG(1,("Unknown long filename format %d\n",level));
989 /****************************************************************************
990 act on the files in a dir listing
991 ****************************************************************************/
992 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
995 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
996 !mask_match(finfo->name,fileselection,False,False)) &&
997 !(recurse_dir && (strequal(finfo->name,".") ||
998 strequal(finfo->name,".."))))
1000 if (recurse_dir && (finfo->mode & aDIR))
1004 strcpy(sav_dir,cur_dir);
1005 strcat(cur_dir,finfo->name);
1006 strcat(cur_dir,"\\");
1007 strcpy(mask2,cur_dir);
1010 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1015 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);
1017 do_dir(inbuf,outbuf,mask2,attribute,fn,True);
1019 strcpy(cur_dir,sav_dir);
1023 if (fn && do_this_one(finfo))
1030 /****************************************************************************
1031 receive a SMB trans or trans2 response allocating the necessary memory
1032 ****************************************************************************/
1033 static BOOL receive_trans_response(char *inbuf,int trans,
1034 int *data_len,int *param_len,
1035 char **data,char **param)
1039 int this_data,this_param;
1041 *data_len = *param_len = 0;
1043 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1047 if (CVAL(inbuf,smb_com) != trans)
1049 DEBUG(0,("Expected %s response, got command 0x%02x\n",
1050 trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
1053 if (CVAL(inbuf,smb_rcls) != 0)
1056 /* parse out the lengths */
1057 total_data = SVAL(inbuf,smb_tdrcnt);
1058 total_param = SVAL(inbuf,smb_tprcnt);
1061 *data = Realloc(*data,total_data);
1062 *param = Realloc(*param,total_param);
1066 this_data = SVAL(inbuf,smb_drcnt);
1067 this_param = SVAL(inbuf,smb_prcnt);
1069 memcpy(*data + SVAL(inbuf,smb_drdisp),
1070 smb_base(inbuf) + SVAL(inbuf,smb_droff),
1073 memcpy(*param + SVAL(inbuf,smb_prdisp),
1074 smb_base(inbuf) + SVAL(inbuf,smb_proff),
1076 *data_len += this_data;
1077 *param_len += this_param;
1079 /* parse out the total lengths again - they can shrink! */
1080 total_data = SVAL(inbuf,smb_tdrcnt);
1081 total_param = SVAL(inbuf,smb_tprcnt);
1083 if (total_data <= *data_len && total_param <= *param_len)
1086 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1090 if (CVAL(inbuf,smb_com) != trans)
1092 DEBUG(0,("Expected %s response, got command 0x%02x\n",
1093 trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
1096 if (CVAL(inbuf,smb_rcls) != 0)
1104 /****************************************************************************
1105 get a directory listing
1106 ****************************************************************************/
1107 static void cmd_dir(char *inbuf,char *outbuf)
1109 int attribute = aDIR | aSYSTEM | aHIDDEN;
1115 strcpy(mask,cur_dir);
1116 if(mask[strlen(mask)-1]!='\\')
1119 if (next_token(NULL,buf,NULL))
1130 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1134 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1139 /****************************************************************************
1140 get a file from rname to lname
1141 ****************************************************************************/
1142 static void do_get(char *rname,char *lname,file_info *finfo1)
1147 BOOL newhandle = False;
1148 char *inbuf,*outbuf;
1150 BOOL close_done = False;
1151 BOOL ignore_close_error = False;
1155 struct timeval tp_start;
1156 GetTimeOfDay(&tp_start);
1167 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1168 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1170 if (!inbuf || !outbuf)
1172 DEBUG(0,("out of memory\n"));
1176 bzero(outbuf,smb_size);
1177 set_message(outbuf,15,1 + strlen(rname),True);
1179 CVAL(outbuf,smb_com) = SMBopenX;
1180 SSVAL(outbuf,smb_tid,cnum);
1183 SSVAL(outbuf,smb_vwv0,0xFF);
1184 SSVAL(outbuf,smb_vwv2,1);
1185 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1186 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1187 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1188 SSVAL(outbuf,smb_vwv8,1);
1190 p = smb_buf(outbuf);
1192 p = skip_string(p,1);
1194 /* do a chained openX with a readX? */
1198 DEBUG(3,("Chaining readX wth openX\n"));
1199 SSVAL(outbuf,smb_vwv0,SMBreadX);
1200 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1203 SSVAL(p,smb_wct,10);
1204 SSVAL(p,smb_vwv0,0xFF);
1205 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1206 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1207 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1211 if(!strcmp(lname,"-"))
1212 handle = fileno(stdout);
1215 handle = creat(lname,0644);
1220 DEBUG(0,("Error opening local file %s\n",lname));
1221 free(inbuf);free(outbuf);
1225 send_smb(Client,outbuf);
1226 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1228 if (CVAL(inbuf,smb_rcls) != 0)
1230 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1231 SVAL(inbuf,smb_err) == ERRnoresource &&
1232 reopen_connection(inbuf,outbuf))
1234 do_get(rname,lname,finfo1);
1237 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1240 free(inbuf);free(outbuf);
1244 strcpy(finfo.name,rname);
1248 finfo.mode = SVAL(inbuf,smb_vwv3);
1249 /* these times arrive as LOCAL time, using the DST offset
1250 corresponding to that time, we convert them to GMT */
1251 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1252 finfo.atime = finfo.ctime = finfo.mtime;
1253 finfo.size = IVAL(inbuf,smb_vwv6);
1256 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1258 fnum = SVAL(inbuf,smb_vwv2);
1260 /* we might have got some data from a chained readX */
1261 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1263 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1264 datalen = SVAL(p,smb_vwv5);
1265 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1274 DEBUG(2,("getting file %s of size %d bytes as %s ",
1275 CNV_LANG(finfo.name),
1279 while (nread < finfo.size && !close_done)
1282 static BOOL can_chain_close = True;
1286 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1288 /* 3 possible read types. readbraw if a large block is required.
1289 readX + close if not much left and read if neither is supported */
1291 /* we might have already read some data from a chained readX */
1292 if (dataptr && datalen>0)
1295 /* if we can finish now then readX+close */
1296 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1297 ((finfo.size - nread) <
1298 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1301 /* if we support readraw then use that */
1302 if (method<0 && readbraw_supported)
1305 /* if we can then use readX */
1306 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1317 /* use readX + close */
1318 bzero(outbuf,smb_size);
1319 set_message(outbuf,10,0,True);
1320 CVAL(outbuf,smb_com) = SMBreadX;
1321 SSVAL(outbuf,smb_tid,cnum);
1326 CVAL(outbuf,smb_vwv0) = SMBclose;
1327 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1330 CVAL(outbuf,smb_vwv0) = 0xFF;
1332 SSVAL(outbuf,smb_vwv2,fnum);
1333 SIVAL(outbuf,smb_vwv3,nread);
1334 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1335 SSVAL(outbuf,smb_vwv6,0);
1336 SIVAL(outbuf,smb_vwv7,0);
1337 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1341 p = smb_buf(outbuf);
1348 /* now set the total packet length */
1349 smb_setlen(outbuf,smb_len(outbuf)+9);
1352 send_smb(Client,outbuf);
1353 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1355 if (CVAL(inbuf,smb_rcls) != 0)
1357 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1362 SVAL(inbuf,smb_vwv0) != SMBclose)
1364 /* NOTE: WfWg sometimes just ignores the chained
1365 command! This seems to break the spec? */
1366 DEBUG(3,("Rejected chained close?\n"));
1368 can_chain_close = False;
1369 ignore_close_error = True;
1372 datalen = SVAL(inbuf,smb_vwv5);
1373 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1379 static int readbraw_size = BUFFER_SIZE;
1382 bzero(outbuf,smb_size);
1383 set_message(outbuf,8,0,True);
1384 CVAL(outbuf,smb_com) = SMBreadbraw;
1385 SSVAL(outbuf,smb_tid,cnum);
1387 SSVAL(outbuf,smb_vwv0,fnum);
1388 SIVAL(outbuf,smb_vwv1,nread);
1389 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1390 SSVAL(outbuf,smb_vwv4,0);
1391 SIVALS(outbuf,smb_vwv5,-1);
1392 send_smb(Client,outbuf);
1394 /* Now read the raw data into the buffer and write it */
1395 if(read_smb_length(Client,inbuf,0) == -1) {
1396 DEBUG(0,("Failed to read length in readbraw\n"));
1400 /* Even though this is not an smb message, smb_len
1401 returns the generic length of an smb message */
1402 datalen = smb_len(inbuf);
1406 /* we got a readbraw error */
1407 DEBUG(4,("readbraw error - reducing size\n"));
1408 readbraw_size = (readbraw_size * 9) / 10;
1410 if (readbraw_size < max_xmit)
1412 DEBUG(0,("disabling readbraw\n"));
1413 readbraw_supported = False;
1420 if(read_data(Client,inbuf,datalen) != datalen) {
1421 DEBUG(0,("Failed to read data in readbraw\n"));
1429 /* we've already read some data with a chained readX */
1433 /* use plain read */
1434 bzero(outbuf,smb_size);
1435 set_message(outbuf,5,0,True);
1436 CVAL(outbuf,smb_com) = SMBread;
1437 SSVAL(outbuf,smb_tid,cnum);
1440 SSVAL(outbuf,smb_vwv0,fnum);
1441 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1442 SIVAL(outbuf,smb_vwv2,nread);
1443 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1445 send_smb(Client,outbuf);
1446 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1448 if (CVAL(inbuf,smb_rcls) != 0)
1450 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1454 datalen = SVAL(inbuf,smb_vwv0);
1455 dataptr = smb_buf(inbuf) + 3;
1459 if (writefile(handle,dataptr,datalen) != datalen)
1461 DEBUG(0,("Error writing local file\n"));
1468 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1480 bzero(outbuf,smb_size);
1481 set_message(outbuf,3,0,True);
1482 CVAL(outbuf,smb_com) = SMBclose;
1483 SSVAL(outbuf,smb_tid,cnum);
1486 SSVAL(outbuf,smb_vwv0,fnum);
1487 SIVALS(outbuf,smb_vwv1,-1);
1489 send_smb(Client,outbuf);
1490 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1492 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1494 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1497 free(inbuf);free(outbuf);
1505 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1506 bzero(outbuf,smb_size);
1507 set_message(outbuf,8,strlen(rname)+4,True);
1508 CVAL(outbuf,smb_com) = SMBsetatr;
1509 SSVAL(outbuf,smb_tid,cnum);
1511 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1512 SIVALS(outbuf,smb_vwv1,0);
1513 p = smb_buf(outbuf);
1519 send_smb(Client,outbuf);
1520 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1524 struct timeval tp_end;
1527 GetTimeOfDay(&tp_end);
1529 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1530 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1531 get_total_time_ms += this_time;
1532 get_total_size += finfo.size;
1534 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1535 finfo.size / (1.024*this_time + 1.0e-4),
1536 get_total_size / (1.024*get_total_time_ms)));
1539 free(inbuf);free(outbuf);
1543 /****************************************************************************
1545 ****************************************************************************/
1546 static void cmd_get(void)
1552 strcpy(rname,cur_dir);
1555 p = rname + strlen(rname);
1557 if (!next_token(NULL,p,NULL)) {
1558 DEBUG(0,("get <filename>\n"));
1562 dos_clean_name(rname);
1564 next_token(NULL,lname,NULL);
1566 do_get(rname,lname,NULL);
1570 /****************************************************************************
1571 do a mget operation on one file
1572 ****************************************************************************/
1573 static void do_mget(file_info *finfo)
1578 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1583 DEBUG(0,("mget aborted\n"));
1587 if (finfo->mode & aDIR)
1588 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1590 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1592 if (prompt && !yesno(quest)) return;
1594 if (finfo->mode & aDIR)
1596 pstring saved_curdir;
1598 char *inbuf,*outbuf;
1600 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1601 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1603 if (!inbuf || !outbuf)
1605 DEBUG(0,("out of memory\n"));
1609 strcpy(saved_curdir,cur_dir);
1611 strcat(cur_dir,finfo->name);
1612 strcat(cur_dir,"\\");
1614 unix_format(finfo->name);
1617 strlower(finfo->name);
1619 if (!directory_exist(finfo->name,NULL) &&
1620 sys_mkdir(finfo->name,0777) != 0)
1622 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1623 strcpy(cur_dir,saved_curdir);
1624 free(inbuf);free(outbuf);
1628 if (sys_chdir(finfo->name) != 0)
1630 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1631 strcpy(cur_dir,saved_curdir);
1632 free(inbuf);free(outbuf);
1637 strcpy(mget_mask,cur_dir);
1638 strcat(mget_mask,"*");
1640 do_dir((char *)inbuf,(char *)outbuf,
1641 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1643 strcpy(cur_dir,saved_curdir);
1644 free(inbuf);free(outbuf);
1648 strcpy(rname,cur_dir);
1649 strcat(rname,finfo->name);
1650 do_get(rname,finfo->name,finfo);
1654 /****************************************************************************
1655 view the file using the pager
1656 ****************************************************************************/
1657 static void cmd_more(void)
1659 fstring rname,lname,tmpname,pager_cmd;
1662 strcpy(rname,cur_dir);
1664 sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1665 strcpy(lname,tmpname);
1667 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1668 DEBUG(0,("more <filename>\n"));
1671 dos_clean_name(rname);
1673 do_get(rname,lname,NULL);
1675 pager=getenv("PAGER");
1676 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1683 /****************************************************************************
1685 ****************************************************************************/
1686 static void cmd_mget(char *inbuf,char *outbuf)
1688 int attribute = aSYSTEM | aHIDDEN;
1700 while (next_token(NULL,p,NULL))
1702 strcpy(mget_mask,cur_dir);
1703 if(mget_mask[strlen(mget_mask)-1]!='\\')
1704 strcat(mget_mask,"\\");
1707 strcpy(mget_mask,p);
1709 strcat(mget_mask,p);
1710 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1715 strcpy(mget_mask,cur_dir);
1716 if(mget_mask[strlen(mget_mask)-1]!='\\')
1717 strcat(mget_mask,"\\");
1718 strcat(mget_mask,"*");
1719 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1723 /****************************************************************************
1724 make a directory of name "name"
1725 ****************************************************************************/
1726 static BOOL do_mkdir(char *name)
1729 char *inbuf,*outbuf;
1731 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1732 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1734 if (!inbuf || !outbuf)
1736 DEBUG(0,("out of memory\n"));
1740 bzero(outbuf,smb_size);
1741 set_message(outbuf,0,2 + strlen(name),True);
1743 CVAL(outbuf,smb_com) = SMBmkdir;
1744 SSVAL(outbuf,smb_tid,cnum);
1748 p = smb_buf(outbuf);
1752 send_smb(Client,outbuf);
1753 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1755 if (CVAL(inbuf,smb_rcls) != 0)
1757 DEBUG(0,("%s making remote directory %s\n",
1758 smb_errstr(inbuf),CNV_LANG(name)));
1760 free(inbuf);free(outbuf);
1764 free(inbuf);free(outbuf);
1769 /****************************************************************************
1771 ****************************************************************************/
1772 static void cmd_mkdir(char *inbuf,char *outbuf)
1778 strcpy(mask,cur_dir);
1780 if (!next_token(NULL,p,NULL))
1783 DEBUG(0,("mkdir <dirname>\n"));
1795 trim_string(ddir,".",NULL);
1796 p = strtok(ddir,"/\\");
1800 if (!chkpath(ddir2,False))
1805 p = strtok(NULL,"/\\");
1813 /*******************************************************************
1814 write to a file using writebraw
1815 ********************************************************************/
1816 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1821 bzero(outbuf,smb_size);
1822 bzero(inbuf,smb_size);
1823 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1825 CVAL(outbuf,smb_com) = SMBwritebraw;
1826 SSVAL(outbuf,smb_tid,cnum);
1829 SSVAL(outbuf,smb_vwv0,fnum);
1830 SSVAL(outbuf,smb_vwv1,n);
1831 SIVAL(outbuf,smb_vwv3,pos);
1832 SSVAL(outbuf,smb_vwv7,1);
1834 send_smb(Client,outbuf);
1836 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1839 _smb_setlen(buf-4,n); /* HACK! XXXX */
1841 if (write_socket(Client,buf-4,n+4) != n+4)
1844 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1845 DEBUG(0,("Error writing remote file (2)\n"));
1848 return(SVAL(inbuf,smb_vwv0));
1853 /*******************************************************************
1855 ********************************************************************/
1856 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1860 if (writebraw_supported && n > (max_xmit-200))
1861 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1863 bzero(outbuf,smb_size);
1864 bzero(inbuf,smb_size);
1865 set_message(outbuf,5,n + 3,True);
1867 CVAL(outbuf,smb_com) = SMBwrite;
1868 SSVAL(outbuf,smb_tid,cnum);
1871 SSVAL(outbuf,smb_vwv0,fnum);
1872 SSVAL(outbuf,smb_vwv1,n);
1873 SIVAL(outbuf,smb_vwv2,pos);
1874 SSVAL(outbuf,smb_vwv4,0);
1875 CVAL(smb_buf(outbuf),0) = 1;
1876 SSVAL(smb_buf(outbuf),1,n);
1878 memcpy(smb_buf(outbuf)+3,buf,n);
1880 send_smb(Client,outbuf);
1881 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1883 if (CVAL(inbuf,smb_rcls) != 0) {
1884 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1887 return(SVAL(inbuf,smb_vwv0));
1892 /****************************************************************************
1894 ****************************************************************************/
1895 static void do_put(char *rname,char *lname,file_info *finfo)
1901 char *inbuf,*outbuf;
1902 time_t close_time = finfo->mtime;
1904 static int maxwrite=0;
1906 struct timeval tp_start;
1907 GetTimeOfDay(&tp_start);
1909 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1910 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1912 if (!inbuf || !outbuf)
1914 DEBUG(0,("out of memory\n"));
1918 bzero(outbuf,smb_size);
1919 set_message(outbuf,3,2 + strlen(rname),True);
1921 if (finfo->mtime == 0 || finfo->mtime == -1)
1922 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1924 CVAL(outbuf,smb_com) = SMBcreate;
1925 SSVAL(outbuf,smb_tid,cnum);
1928 SSVAL(outbuf,smb_vwv0,finfo->mode);
1929 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1931 p = smb_buf(outbuf);
1935 send_smb(Client,outbuf);
1936 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1938 if (CVAL(inbuf,smb_rcls) != 0)
1940 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1942 free(inbuf);free(outbuf);if (buf) free(buf);
1946 f = fopen(lname,"r");
1950 DEBUG(0,("Error opening local file %s\n",lname));
1951 free(inbuf);free(outbuf);
1956 fnum = SVAL(inbuf,smb_vwv0);
1957 if (finfo->size < 0)
1958 finfo->size = file_size(lname);
1960 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1963 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1965 while (nread < finfo->size)
1970 n = MIN(n,finfo->size - nread);
1972 buf = (char *)Realloc(buf,n+4);
1974 fseek(f,nread,SEEK_SET);
1975 if ((n = readfile(buf+4,1,n,f)) < 1)
1977 DEBUG(0,("Error reading local file\n"));
1981 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1985 DEBUG(0,("Error writing file\n"));
1998 bzero(outbuf,smb_size);
1999 set_message(outbuf,3,0,True);
2000 CVAL(outbuf,smb_com) = SMBclose;
2001 SSVAL(outbuf,smb_tid,cnum);
2004 SSVAL(outbuf,smb_vwv0,fnum);
2005 put_dos_date3(outbuf,smb_vwv1,close_time);
2007 send_smb(Client,outbuf);
2008 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2010 if (CVAL(inbuf,smb_rcls) != 0)
2012 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2014 free(inbuf);free(outbuf);
2021 free(inbuf);free(outbuf);
2025 struct timeval tp_end;
2028 GetTimeOfDay(&tp_end);
2030 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
2031 (tp_end.tv_usec - tp_start.tv_usec)/1000;
2032 put_total_time_ms += this_time;
2033 put_total_size += finfo->size;
2035 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
2036 finfo->size / (1.024*this_time + 1.0e-4),
2037 put_total_size / (1.024*put_total_time_ms)));
2043 /****************************************************************************
2045 ****************************************************************************/
2046 static void cmd_put(void)
2055 strcpy(rname,cur_dir);
2059 if (!next_token(NULL,p,NULL))
2061 DEBUG(0,("put <filename>\n"));
2066 if (next_token(NULL,p,NULL))
2069 strcat(rname,lname);
2071 dos_clean_name(rname);
2075 if (!file_exist(lname,&st)) {
2076 DEBUG(0,("%s does not exist\n",lname));
2079 finfo.mtime = st.st_mtime;
2082 do_put(rname,lname,&finfo);
2085 /****************************************************************************
2086 seek in a directory/file list until you get something that doesn't start with
2088 ****************************************************************************/
2089 static BOOL seek_list(FILE *f,char *name)
2094 if (fscanf(f,"%s",s) != 1) return(False);
2095 trim_string(s,"./",NULL);
2096 if (strncmp(s,name,strlen(name)) != 0)
2107 /****************************************************************************
2108 set the file selection mask
2109 ****************************************************************************/
2110 static void cmd_select(void)
2112 strcpy(fileselection,"");
2113 next_token(NULL,fileselection,NULL);
2117 /****************************************************************************
2119 ****************************************************************************/
2120 static void cmd_mput(void)
2131 while (next_token(NULL,p,NULL))
2138 sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2140 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2142 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2145 f = fopen(tmpname,"r");
2152 if (fscanf(f,"%s",lname) != 1) break;
2153 trim_string(lname,"./",NULL);
2157 /* check if it's a directory */
2158 if (directory_exist(lname,&st))
2160 if (!recurse) continue;
2161 sprintf(quest,"Put directory %s? ",lname);
2162 if (prompt && !yesno(quest))
2165 if (!seek_list(f,lname))
2170 strcpy(rname,cur_dir);
2171 strcat(rname,lname);
2172 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2174 if (!seek_list(f,lname))
2183 sprintf(quest,"Put file %s? ",lname);
2184 if (prompt && !yesno(quest)) continue;
2186 strcpy(rname,cur_dir);
2187 strcat(rname,lname);
2191 /* null size so do_put knows to ignore it */
2194 /* set the date on the file */
2195 finfo.mtime = st.st_mtime;
2197 do_put(rname,lname,&finfo);
2204 /****************************************************************************
2206 ****************************************************************************/
2207 static void do_cancel(int job)
2209 char *rparam = NULL;
2215 bzero(param,sizeof(param));
2218 SSVAL(p,0,81); /* DosPrintJobDel() */
2221 p = skip_string(p,1);
2223 p = skip_string(p,1);
2227 if (call_api(PTR_DIFF(p,param),0,
2233 int res = SVAL(rparam,0);
2236 printf("Job %d cancelled\n",job);
2238 printf("Error %d calcelling job %d\n",res,job);
2242 printf("Server refused cancel request\n");
2244 if (rparam) free(rparam);
2245 if (rdata) free(rdata);
2251 /****************************************************************************
2253 ****************************************************************************/
2254 static void cmd_cancel(char *inbuf,char *outbuf )
2259 if (!connect_as_printer)
2261 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2262 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2265 if (!next_token(NULL,buf,NULL)) {
2266 printf("cancel <jobid> ...\n");
2272 } while (next_token(NULL,buf,NULL));
2276 /****************************************************************************
2278 ****************************************************************************/
2279 static void cmd_stat(char *inbuf,char *outbuf)
2283 char *resp_data=NULL;
2284 char *resp_param=NULL;
2285 int resp_data_len = 0;
2286 int resp_param_len=0;
2288 uint16 setup = TRANSACT2_QPATHINFO;
2290 if (!next_token(NULL,buf,NULL)) {
2291 printf("stat <file>\n");
2296 SSVAL(param,0,4); /* level */
2301 send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
2303 0,6 + strlen(p)+1,1,
2306 receive_trans_response(inbuf,SMBtrans2,
2307 &resp_data_len,&resp_param_len,
2308 &resp_data,&resp_param);
2310 if (resp_data) free(resp_data); resp_data = NULL;
2311 if (resp_param) free(resp_param); resp_param = NULL;
2315 /****************************************************************************
2317 ****************************************************************************/
2318 static void cmd_print(char *inbuf,char *outbuf )
2327 if (!connect_as_printer)
2329 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2330 DEBUG(0,("Trying to print without -P may fail\n"));
2333 if (!next_token(NULL,lname,NULL))
2335 DEBUG(0,("print <filename>\n"));
2339 strcpy(rname,lname);
2340 p = strrchr(rname,'/');
2345 strcpy(rname,tname);
2348 if ((int)strlen(rname) > 14)
2351 if (strequal(lname,"-"))
2354 strcpy(rname,"stdin");
2357 dos_clean_name(rname);
2359 bzero(outbuf,smb_size);
2360 set_message(outbuf,2,2 + strlen(rname),True);
2362 CVAL(outbuf,smb_com) = SMBsplopen;
2363 SSVAL(outbuf,smb_tid,cnum);
2366 SSVAL(outbuf,smb_vwv0,0);
2367 SSVAL(outbuf,smb_vwv1,printmode);
2369 p = smb_buf(outbuf);
2373 send_smb(Client,outbuf);
2374 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2376 if (CVAL(inbuf,smb_rcls) != 0)
2378 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2383 f = fopen(lname,"r");
2386 DEBUG(0,("Error opening local file %s\n",lname));
2391 fnum = SVAL(inbuf,smb_vwv0);
2393 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2399 bzero(outbuf,smb_size);
2400 set_message(outbuf,1,3,True);
2402 /* for some strange reason the OS/2 print server can't handle large
2403 packets when printing. weird */
2404 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2407 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2409 n = readfile(smb_buf(outbuf)+3,1,n,f);
2412 DEBUG(0,("read gave %d\n",n));
2416 smb_setlen(outbuf,smb_len(outbuf) + n);
2418 CVAL(outbuf,smb_com) = SMBsplwr;
2419 SSVAL(outbuf,smb_tid,cnum);
2422 SSVAL(outbuf,smb_vwv0,fnum);
2423 SSVAL(outbuf,smb_vwv1,n+3);
2424 CVAL(smb_buf(outbuf),0) = 1;
2425 SSVAL(smb_buf(outbuf),1,n);
2427 send_smb(Client,outbuf);
2428 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2430 if (CVAL(inbuf,smb_rcls) != 0)
2432 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2439 DEBUG(2,("%d bytes printed\n",nread));
2441 bzero(outbuf,smb_size);
2442 set_message(outbuf,1,0,True);
2443 CVAL(outbuf,smb_com) = SMBsplclose;
2444 SSVAL(outbuf,smb_tid,cnum);
2447 SSVAL(outbuf,smb_vwv0,fnum);
2449 send_smb(Client,outbuf);
2450 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2452 if (CVAL(inbuf,smb_rcls) != 0)
2454 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2464 /****************************************************************************
2465 show a print queue - this is deprecated as it uses the old smb that
2466 has limited support - the correct call is the cmd_p_queue_4() after this.
2467 ****************************************************************************/
2468 static void cmd_queue(char *inbuf,char *outbuf )
2473 bzero(outbuf,smb_size);
2474 set_message(outbuf,2,0,True);
2476 CVAL(outbuf,smb_com) = SMBsplretq;
2477 SSVAL(outbuf,smb_tid,cnum);
2480 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2481 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2483 send_smb(Client,outbuf);
2484 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2486 if (CVAL(inbuf,smb_rcls) != 0)
2488 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2492 count = SVAL(inbuf,smb_vwv0);
2493 p = smb_buf(inbuf) + 3;
2496 DEBUG(0,("No entries in the print queue\n"));
2503 DEBUG(0,("Job Name Size Status\n"));
2509 case 0x01: sprintf(status,"held or stopped"); break;
2510 case 0x02: sprintf(status,"printing"); break;
2511 case 0x03: sprintf(status,"awaiting print"); break;
2512 case 0x04: sprintf(status,"in intercept"); break;
2513 case 0x05: sprintf(status,"file had error"); break;
2514 case 0x06: sprintf(status,"printer error"); break;
2515 default: sprintf(status,"unknown"); break;
2518 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2519 SVAL(p,5),p+12,IVAL(p,7),status));
2527 /****************************************************************************
2528 show information about a print queue
2529 ****************************************************************************/
2530 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2532 char *rparam = NULL;
2539 if (!connect_as_printer)
2541 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2542 DEBUG(0,("Trying to print without -P may fail\n"));
2545 bzero(param,sizeof(param));
2548 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2550 strcpy(p,"zWrLeh"); /* parameter description? */
2551 p = skip_string(p,1);
2552 strcpy(p,"WWzWWDDzz"); /* returned data format */
2553 p = skip_string(p,1);
2554 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2555 p = skip_string(p,1);
2556 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2557 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2559 strcpy(p,""); /* subformat */
2560 p = skip_string(p,1);
2562 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2563 if( call_api(PTR_DIFF(p,param), 0,
2570 result_code = SVAL(rparam,0);
2571 converter = SVAL(rparam,2); /* conversion factor */
2573 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2575 if (result_code == 0) /* if no error, */
2585 char PrinterName[20];
2587 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2588 strlower(PrinterName); /* in lower case */
2590 p = rdata; /* received data */
2591 for( i = 0; i < SVAL(rparam,4); ++i)
2594 Priority = SVAL(p,2);
2595 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2597 Priority = SVAL(p,2);
2598 JobTime = make_unix_date3( p + 12);
2599 JobTimeStr = asctime(LocalTime( &JobTime));
2601 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2604 printf("%s-%u %s priority %u %s %s %u bytes\n",
2605 PrinterName, JobId, UserName,
2606 Priority, JobTimeStr, JobName, Size);
2608 #if 0 /* DEBUG code */
2609 printf("Job Id: \"%u\"\n", SVAL(p,0));
2610 printf("Priority: \"%u\"\n", SVAL(p,2));
2612 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2613 printf("Position: \"%u\"\n", SVAL(p,8));
2614 printf("Status: \"%u\"\n", SVAL(p,10));
2616 JobTime = make_unix_date3( p + 12);
2617 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2618 printf("date: \"%u\"\n", SVAL(p,12));
2620 printf("Size: \"%u\"\n", SVAL(p,16));
2621 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2622 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2623 #endif /* DEBUG CODE */
2628 else /* call_api() failed */
2630 printf("Failed, error = %d\n", result_code);
2633 /* If any parameters or data were returned, free the storage. */
2634 if(rparam) free(rparam);
2635 if(rdata) free(rdata);
2640 /****************************************************************************
2641 show information about a print queue
2642 ****************************************************************************/
2643 static void cmd_qinfo(char *inbuf,char *outbuf )
2645 char *rparam = NULL;
2652 bzero(param,sizeof(param));
2655 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2657 strcpy(p,"zWrLh"); /* parameter description? */
2658 p = skip_string(p,1);
2659 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2660 p = skip_string(p,1);
2661 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2662 p = skip_string(p,1);
2663 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2664 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2666 strcpy(p,""); /* subformat */
2667 p = skip_string(p,1);
2669 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2670 if( call_api(PTR_DIFF(p,param), 0,
2677 result_code = SVAL(rparam,0);
2678 converter = SVAL(rparam,2); /* conversion factor */
2680 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2682 if (result_code == 0) /* if no error, */
2684 p = rdata; /* received data */
2686 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2687 printf("Priority: %u\n", SVAL(p,4) );
2688 printf("Start time: %u\n", SVAL(p,6) );
2689 printf("Until time: %u\n", SVAL(p,8) );
2690 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2691 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2692 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2693 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2694 printf("Status: %u\n", SVAL(p,28) );
2695 printf("Jobs: %u\n", SVAL(p,30) );
2696 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2697 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2699 /* Dump the driver data */
2704 ddptr = rdata + SVAL(p,40) - converter;
2705 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2706 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2708 for(x=8; x < count; x+=16)
2710 for(y=0; y < 16; y++)
2713 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2717 for(y=0; y < 16 && (x+y) < count; y++)
2719 c = CVAL(ddptr,(x+y));
2725 fputc('\n', stdout);
2731 else /* call_api() failed */
2733 printf("Failed, error = %d\n", result_code);
2736 /* If any parameters or data were returned, free the storage. */
2737 if(rparam) free(rparam);
2738 if(rdata) free(rdata);
2743 /****************************************************************************
2745 ****************************************************************************/
2746 static void do_del(file_info *finfo)
2749 char *inbuf,*outbuf;
2752 strcpy(mask,cur_dir);
2753 strcat(mask,finfo->name);
2755 if (finfo->mode & aDIR)
2758 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2759 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2761 if (!inbuf || !outbuf)
2763 DEBUG(0,("out of memory\n"));
2767 bzero(outbuf,smb_size);
2768 set_message(outbuf,1,2 + strlen(mask),True);
2770 CVAL(outbuf,smb_com) = SMBunlink;
2771 SSVAL(outbuf,smb_tid,cnum);
2774 SSVAL(outbuf,smb_vwv0,0);
2776 p = smb_buf(outbuf);
2780 send_smb(Client,outbuf);
2781 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2783 if (CVAL(inbuf,smb_rcls) != 0)
2784 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2786 free(inbuf);free(outbuf);
2790 /****************************************************************************
2792 ****************************************************************************/
2793 static void cmd_del(char *inbuf,char *outbuf )
2797 int attribute = aSYSTEM | aHIDDEN;
2802 strcpy(mask,cur_dir);
2804 if (!next_token(NULL,buf,NULL))
2806 DEBUG(0,("del <filename>\n"));
2811 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2815 /****************************************************************************
2817 ****************************************************************************/
2818 static void cmd_rmdir(char *inbuf,char *outbuf )
2824 strcpy(mask,cur_dir);
2826 if (!next_token(NULL,buf,NULL))
2828 DEBUG(0,("rmdir <dirname>\n"));
2833 bzero(outbuf,smb_size);
2834 set_message(outbuf,0,2 + strlen(mask),True);
2836 CVAL(outbuf,smb_com) = SMBrmdir;
2837 SSVAL(outbuf,smb_tid,cnum);
2841 p = smb_buf(outbuf);
2845 send_smb(Client,outbuf);
2846 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2848 if (CVAL(inbuf,smb_rcls) != 0)
2850 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2856 /****************************************************************************
2858 ****************************************************************************/
2859 static void cmd_rename(char *inbuf,char *outbuf )
2865 strcpy(src,cur_dir);
2866 strcpy(dest,cur_dir);
2868 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2870 DEBUG(0,("rename <src> <dest>\n"));
2876 bzero(outbuf,smb_size);
2877 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2879 CVAL(outbuf,smb_com) = SMBmv;
2880 SSVAL(outbuf,smb_tid,cnum);
2881 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2884 p = smb_buf(outbuf);
2887 p = skip_string(p,1);
2891 send_smb(Client,outbuf);
2892 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2894 if (CVAL(inbuf,smb_rcls) != 0)
2896 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2903 /****************************************************************************
2904 toggle the prompt flag
2905 ****************************************************************************/
2906 static void cmd_prompt(void)
2909 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2913 /****************************************************************************
2914 set the newer than time
2915 ****************************************************************************/
2916 static void cmd_newer(void)
2922 ok = next_token(NULL,buf,NULL);
2923 if (ok && (sys_stat(buf,&sbuf) == 0))
2925 newer_than = sbuf.st_mtime;
2926 DEBUG(1,("Getting files newer than %s",
2927 asctime(LocalTime(&newer_than))));
2932 if (ok && newer_than == 0)
2933 DEBUG(0,("Error setting newer-than time\n"));
2936 /****************************************************************************
2937 set the archive level
2938 ****************************************************************************/
2939 static void cmd_archive(void)
2943 if (next_token(NULL,buf,NULL)) {
2944 archive_level = atoi(buf);
2946 DEBUG(0,("Archive level is %d\n",archive_level));
2949 /****************************************************************************
2950 toggle the lowercaseflag
2951 ****************************************************************************/
2952 static void cmd_lowercase(void)
2954 lowercase = !lowercase;
2955 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2961 /****************************************************************************
2962 toggle the recurse flag
2963 ****************************************************************************/
2964 static void cmd_recurse(void)
2967 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2970 /****************************************************************************
2971 toggle the translate flag
2972 ****************************************************************************/
2973 static void cmd_translate(void)
2975 translation = !translation;
2976 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2977 translation?"on":"off"));
2981 /****************************************************************************
2982 do a printmode command
2983 ****************************************************************************/
2984 static void cmd_printmode(void)
2989 if (next_token(NULL,buf,NULL))
2991 if (strequal(buf,"text"))
2995 if (strequal(buf,"graphics"))
2998 printmode = atoi(buf);
3005 strcpy(mode,"text");
3008 strcpy(mode,"graphics");
3011 sprintf(mode,"%d",printmode);
3015 DEBUG(2,("the printmode is now %s\n",mode));
3018 /****************************************************************************
3020 ****************************************************************************/
3021 static void cmd_lcd(void)
3026 if (next_token(NULL,buf,NULL))
3028 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
3032 /****************************************************************************
3033 send a session request
3034 ****************************************************************************/
3035 static BOOL send_session_request(char *inbuf,char *outbuf)
3040 /* send a session request (RFC 8002) */
3042 strcpy(dest,desthost);
3043 p = strchr(dest,'.');
3046 /* put in the destination name */
3048 name_mangle(dest,p,name_type); /* 0x20 is the SMB server NetBIOS type. */
3053 name_mangle(myname,p,0);
3056 /* setup the packet length */
3057 _smb_setlen(outbuf,len);
3058 CVAL(outbuf,0) = 0x81;
3060 send_smb(Client,outbuf);
3061 DEBUG(5,("Sent session request\n"));
3063 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3065 if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */
3067 /* For information, here is the response structure.
3068 * We do the byte-twiddling to for portability.
3069 struct RetargetResponse{
3071 unsigned char flags;
3078 int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
3079 /* SESSION RETARGET */
3080 putip((char *)&dest_ip,inbuf+4);
3083 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
3087 DEBUG(3,("Retargeted\n"));
3089 set_socket_options(Client,user_socket_options);
3092 return send_session_request(inbuf,outbuf);
3093 } /* C. Hoch 9/14/95 End */
3096 if (CVAL(inbuf,0) != 0x82)
3098 int ecode = CVAL(inbuf,4);
3099 DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
3100 CVAL(inbuf,0),ecode,myname,desthost));
3104 DEBUG(0,("Not listening on called name\n"));
3105 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
3106 DEBUG(0,("You may find the -I option useful for this\n"));
3109 DEBUG(0,("Not listening for calling name\n"));
3110 DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
3111 DEBUG(0,("You may find the -n option useful for this\n"));
3114 DEBUG(0,("Called name not present\n"));
3115 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
3116 DEBUG(0,("You may find the -I option useful for this\n"));
3119 DEBUG(0,("Called name present, but insufficient resources\n"));
3120 DEBUG(0,("Perhaps you should try again later?\n"));
3123 DEBUG(0,("Unspecified error 0x%X\n",ecode));
3124 DEBUG(0,("Your server software is being unfriendly\n"));
3136 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
3137 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
3138 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
3139 {PROTOCOL_LANMAN1,"LANMAN1.0"},
3140 {PROTOCOL_LANMAN2,"LM1.2X002"},
3141 {PROTOCOL_LANMAN2,"Samba"},
3142 {PROTOCOL_NT1,"NT LM 0.12"},
3143 {PROTOCOL_NT1,"NT LANMAN 1.0"},
3148 /****************************************************************************
3149 send a login command
3150 ****************************************************************************/
3151 static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
3153 BOOL was_null = (!inbuf && !outbuf);
3155 time_t servertime = 0;
3156 extern int serverzone;
3168 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3169 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3173 if (strstr(service,"IPC$")) connect_as_ipc = True;
3177 if (connect_as_printer)
3178 strcpy(dev,"LPT1:");
3183 if (start_session && !send_session_request(inbuf,outbuf))
3193 bzero(outbuf,smb_size);
3195 /* setup the protocol strings */
3199 for (plength=0,numprots=0;
3200 prots[numprots].name && prots[numprots].prot<=max_protocol;
3202 plength += strlen(prots[numprots].name)+2;
3204 set_message(outbuf,0,plength,True);
3206 p = smb_buf(outbuf);
3208 prots[numprots].name && prots[numprots].prot<=max_protocol;
3212 strcpy(p,prots[numprots].name);
3217 CVAL(outbuf,smb_com) = SMBnegprot;
3220 CVAL(smb_buf(outbuf),0) = 2;
3222 send_smb(Client,outbuf);
3223 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3227 if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
3229 DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
3230 myname,desthost,smb_errstr(inbuf)));
3239 Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
3242 if (Protocol < PROTOCOL_NT1) {
3243 sec_mode = SVAL(inbuf,smb_vwv1);
3244 max_xmit = SVAL(inbuf,smb_vwv2);
3245 sesskey = IVAL(inbuf,smb_vwv6);
3246 serverzone = SVALS(inbuf,smb_vwv10)*60;
3247 /* this time is converted to GMT by make_unix_date */
3248 servertime = make_unix_date(inbuf+smb_vwv8);
3249 if (Protocol >= PROTOCOL_COREPLUS) {
3250 readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
3251 writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
3253 crypt_len = smb_buflen(inbuf);
3254 memcpy(cryptkey,smb_buf(inbuf),8);
3255 DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
3256 max_vcs = SVAL(inbuf,smb_vwv4);
3257 DEBUG(3,("max vcs %d\n",max_vcs));
3258 DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
3261 sec_mode = CVAL(inbuf,smb_vwv1);
3262 max_xmit = IVAL(inbuf,smb_vwv3+1);
3263 sesskey = IVAL(inbuf,smb_vwv7+1);
3264 serverzone = SVALS(inbuf,smb_vwv15+1)*60;
3265 /* this time arrives in real GMT */
3266 servertime = interpret_long_date(inbuf+smb_vwv11+1);
3267 crypt_len = CVAL(inbuf,smb_vwv16+1);
3268 memcpy(cryptkey,smb_buf(inbuf),8);
3269 if (IVAL(inbuf,smb_vwv9+1) & 1)
3270 readbraw_supported = writebraw_supported = True;
3271 DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
3272 max_vcs = SVAL(inbuf,smb_vwv2+1);
3273 DEBUG(3,("max vcs %d\n",max_vcs));
3274 DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
3275 DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
3278 DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
3279 DEBUG(3,("max xmt %d\n",max_xmit));
3280 DEBUG(3,("Got %d byte crypt key\n",crypt_len));
3281 DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
3283 doencrypt = ((sec_mode & 2) != 0);
3286 static BOOL done_time = False;
3288 DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
3289 asctime(LocalTime(&servertime)),
3290 -(double)(serverzone/3600.0)));
3300 pass = (char *)getpass("Password: ");
3302 /* use a blank username for the 2nd try with a blank password */
3303 if (tries++ && !*pass)
3306 if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
3309 int passlen = strlen(pass)+1;
3313 if (doencrypt && *pass) {
3314 DEBUG(3,("Using encrypted passwords\n"));
3316 SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
3322 /* if in share level security then don't send a password now */
3323 if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;}
3325 /* send a session setup command */
3326 bzero(outbuf,smb_size);
3328 if (Protocol < PROTOCOL_NT1) {
3329 set_message(outbuf,10,1 + strlen(username) + passlen,True);
3330 CVAL(outbuf,smb_com) = SMBsesssetupX;
3333 CVAL(outbuf,smb_vwv0) = 0xFF;
3334 SSVAL(outbuf,smb_vwv2,max_xmit);
3335 SSVAL(outbuf,smb_vwv3,2);
3336 SSVAL(outbuf,smb_vwv4,max_vcs-1);
3337 SIVAL(outbuf,smb_vwv5,sesskey);
3338 SSVAL(outbuf,smb_vwv7,passlen);
3339 p = smb_buf(outbuf);
3340 memcpy(p,pword,passlen);
3344 if (!doencrypt) passlen--;
3346 set_message(outbuf,13,0,True);
3347 CVAL(outbuf,smb_com) = SMBsesssetupX;
3350 CVAL(outbuf,smb_vwv0) = 0xFF;
3351 SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
3352 SSVAL(outbuf,smb_vwv3,2);
3353 SSVAL(outbuf,smb_vwv4,getpid());
3354 SIVAL(outbuf,smb_vwv5,sesskey);
3355 SSVAL(outbuf,smb_vwv7,passlen);
3356 SSVAL(outbuf,smb_vwv8,0);
3357 p = smb_buf(outbuf);
3358 memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
3359 strcpy(p,username);p = skip_string(p,1);
3360 strcpy(p,workgroup);p = skip_string(p,1);
3361 strcpy(p,"Unix");p = skip_string(p,1);
3362 strcpy(p,"Samba");p = skip_string(p,1);
3363 set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
3366 send_smb(Client,outbuf);
3367 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3371 if (CVAL(inbuf,smb_rcls) != 0)
3374 ((CVAL(inbuf,smb_rcls) == ERRDOS &&
3375 SVAL(inbuf,smb_err) == ERRnoaccess) ||
3376 (CVAL(inbuf,smb_rcls) == ERRSRV &&
3377 SVAL(inbuf,smb_err) == ERRbadpw)))
3380 DEBUG(3,("resending login\n"));
3384 DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n",
3385 username,myname,desthost,smb_errstr(inbuf)));
3386 DEBUG(0,("You might find the -U, -W or -n options useful\n"));
3387 DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
3388 DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
3397 if (Protocol >= PROTOCOL_NT1) {
3398 char *domain,*os,*lanman;
3401 lanman = skip_string(os,1);
3402 domain = skip_string(lanman,1);
3403 if (*domain || *os || *lanman)
3404 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
3407 /* use the returned uid from now on */
3408 if (SVAL(inbuf,smb_uid) != uid)
3409 DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
3410 SVAL(inbuf,smb_uid),uid));
3411 uid = SVAL(inbuf,smb_uid);
3414 /* now we've got a connection - send a tcon message */
3415 bzero(outbuf,smb_size);
3417 if (strncmp(service,"\\\\",2) != 0)
3419 DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
3420 DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
3427 int passlen = strlen(pass)+1;
3432 if (doencrypt && *pass) {
3434 SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
3438 /* if in user level security then don't send a password now */
3439 if ((sec_mode & 1)) {
3440 strcpy(pword, ""); passlen=1;
3443 if (Protocol <= PROTOCOL_COREPLUS) {
3444 set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
3445 CVAL(outbuf,smb_com) = SMBtcon;
3448 p = smb_buf(outbuf);
3451 p = skip_string(p,1);
3453 memcpy(p,pword,passlen);
3459 set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
3460 CVAL(outbuf,smb_com) = SMBtconX;
3463 SSVAL(outbuf,smb_vwv0,0xFF);
3464 SSVAL(outbuf,smb_vwv3,passlen);
3466 p = smb_buf(outbuf);
3467 memcpy(p,pword,passlen);
3470 p = skip_string(p,1);
3475 send_smb(Client,outbuf);
3476 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3478 /* trying again with a blank password */
3479 if (CVAL(inbuf,smb_rcls) != 0 &&
3480 (int)strlen(pass) > 0 &&
3482 Protocol >= PROTOCOL_LANMAN1)
3484 DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
3489 if (CVAL(inbuf,smb_rcls) != 0)
3491 DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
3492 DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
3493 DEBUG(0,("Some servers insist that these be in uppercase\n"));
3503 if (Protocol <= PROTOCOL_COREPLUS) {
3504 max_xmit = SVAL(inbuf,smb_vwv0);
3506 cnum = SVAL(inbuf,smb_vwv1);
3509 max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
3511 max_xmit = BUFFER_SIZE - 4;
3513 cnum = SVAL(inbuf,smb_tid);
3516 DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
3527 /****************************************************************************
3528 send a logout command
3529 ****************************************************************************/
3530 static void send_logout(void )
3532 pstring inbuf,outbuf;
3534 bzero(outbuf,smb_size);
3535 set_message(outbuf,0,0,True);
3536 CVAL(outbuf,smb_com) = SMBtdis;
3537 SSVAL(outbuf,smb_tid,cnum);
3540 send_smb(Client,outbuf);
3541 receive_smb(Client,inbuf,SHORT_TIMEOUT);
3543 if (CVAL(inbuf,smb_rcls) != 0)
3545 DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
3557 /****************************************************************************
3559 ****************************************************************************/
3560 static BOOL call_api(int prcnt,int drcnt,
3561 int mprcnt,int mdrcnt,
3562 int *rprcnt,int *rdrcnt,
3563 char *param,char *data,
3564 char **rparam,char **rdata)
3566 static char *inbuf=NULL;
3567 static char *outbuf=NULL;
3569 if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3570 if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3572 send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
3577 return (receive_trans_response(inbuf,SMBtrans,
3582 /****************************************************************************
3583 send a SMB trans or trans2 request
3584 ****************************************************************************/
3585 static BOOL send_trans_request(char *outbuf,int trans,
3586 char *name,int fid,int flags,
3587 char *data,char *param,uint16 *setup,
3588 int ldata,int lparam,int lsetup,
3589 int mdata,int mparam,int msetup)
3592 int this_ldata,this_lparam;
3593 int tot_data=0,tot_param=0;
3594 char *outdata,*outparam;
3598 this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
3599 this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
3601 bzero(outbuf,smb_size);
3602 set_message(outbuf,14+lsetup,0,True);
3603 CVAL(outbuf,smb_com) = trans;
3604 SSVAL(outbuf,smb_tid,cnum);
3607 outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
3608 outdata = outparam+this_lparam;
3610 /* primary request */
3611 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3612 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3613 SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */
3614 SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */
3615 SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */
3616 SSVAL(outbuf,smb_flags,flags); /* flags */
3617 SIVAL(outbuf,smb_timeout,0); /* timeout */
3618 SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
3619 SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
3620 SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */
3621 SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
3622 SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */
3623 for (i=0;i<lsetup;i++) /* setup[] */
3624 SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
3625 p = smb_buf(outbuf);
3626 if (trans==SMBtrans)
3627 strcpy(p,name); /* name[] */
3630 *p++ = 0; /* put in a null smb_name */
3631 *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */
3633 if (this_lparam) /* param[] */
3634 memcpy(outparam,param,this_lparam);
3635 if (this_ldata) /* data[] */
3636 memcpy(outdata,data,this_ldata);
3637 set_message(outbuf,14+lsetup, /* wcnt, bcc */
3638 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3641 send_smb(Client,outbuf);
3643 if (this_ldata < ldata || this_lparam < lparam)
3645 /* receive interim response */
3646 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
3648 DEBUG(0,("%s request failed (%s)\n",
3649 trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
3653 tot_data = this_ldata;
3654 tot_param = this_lparam;
3656 while (tot_data < ldata || tot_param < lparam)
3658 this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
3659 this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
3661 set_message(outbuf,trans==SMBtrans?8:9,0,True);
3662 CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
3664 outparam = smb_buf(outbuf);
3665 outdata = outparam+this_lparam;
3667 /* secondary request */
3668 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3669 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3670 SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
3671 SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
3672 SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */
3673 SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */
3674 SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
3675 SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */
3676 if (trans==SMBtrans2)
3677 SSVAL(outbuf,smb_sfid,fid); /* fid */
3678 if (this_lparam) /* param[] */
3679 memcpy(outparam,param,this_lparam);
3680 if (this_ldata) /* data[] */
3681 memcpy(outdata,data,this_ldata);
3682 set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
3683 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3686 send_smb(Client,outbuf);
3688 tot_data += this_ldata;
3689 tot_param += this_lparam;
3696 /****************************************************************************
3697 try and browse available connections on a host
3698 ****************************************************************************/
3699 static BOOL browse_host(BOOL sort)
3702 /* If strcasecmp is already defined, remove it. */
3705 #endif /* strcasecmp */
3706 #define strcasecmp StrCaseCmp
3707 #endif /* NOSTRCASECMP */
3709 extern int strcasecmp();
3711 char *rparam = NULL;
3718 /* now send a SMBtrans command with api RNetShareEnum */
3720 SSVAL(p,0,0); /* api number */
3723 p = skip_string(p,1);
3725 p = skip_string(p,1);
3727 SSVAL(p,2,BUFFER_SIZE);
3730 if (call_api(PTR_DIFF(p,param),0,
3736 int res = SVAL(rparam,0);
3737 int converter=SVAL(rparam,2);
3739 BOOL long_share_name=False;
3743 count=SVAL(rparam,4);
3748 printf("\n\tSharename Type Comment\n");
3749 printf("\t--------- ---- -------\n");
3753 qsort(p,count,20,QSORT_CAST strcasecmp);
3755 for (i=0;i<count;i++)
3758 int type = SVAL(p,14);
3759 int comment_offset = IVAL(p,16) & 0xFFFF;
3765 case STYPE_DISKTREE:
3766 strcpy(typestr,"Disk"); break;
3768 strcpy(typestr,"Printer"); break;
3770 strcpy(typestr,"Device"); break;
3772 strcpy(typestr,"IPC"); break;
3775 printf("\t%-15.15s%-10.10s%s\n",
3778 comment_offset?rdata+comment_offset-converter:"");
3780 if (strlen(sname)>8) long_share_name=True;
3785 if (long_share_name) {
3786 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3791 if (rparam) free(rparam);
3792 if (rdata) free(rdata);
3798 /****************************************************************************
3799 get some server info
3800 ****************************************************************************/
3801 static void server_info()
3803 char *rparam = NULL;
3809 bzero(param,sizeof(param));
3812 SSVAL(p,0,63); /* NetServerGetInfo()? */
3815 p = skip_string(p,1);
3816 strcpy(p,"zzzBBzz");
3817 p = skip_string(p,1);
3818 SSVAL(p,0,10); /* level 10 */
3822 if (call_api(PTR_DIFF(p,param),0,
3828 int res = SVAL(rparam,0);
3829 int converter=SVAL(rparam,2);
3835 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3836 rdata+SVAL(p,0)-converter,
3837 rdata+SVAL(p,4)-converter,
3838 rdata+SVAL(p,8)-converter,
3839 rdata+SVAL(p,14)-converter);
3843 if (rparam) free(rparam);
3844 if (rdata) free(rdata);
3850 /****************************************************************************
3851 try and browse available connections on a host
3852 ****************************************************************************/
3853 static BOOL list_servers(char *wk_grp)
3855 char *rparam = NULL;
3863 BOOL generic_request = False;
3866 if (strequal(wk_grp,"WORKGROUP")) {
3867 /* we won't specify a workgroup */
3868 generic_request = True;
3871 /* now send a SMBtrans command with api ServerEnum? */
3873 SSVAL(p,0,0x68); /* api number */
3876 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3877 p = skip_string(p,1);
3879 strcpy(p,"B16BBDz");
3881 p = skip_string(p,1);
3883 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3889 if (!generic_request) {
3891 p = skip_string(p,1);
3894 /* first ask for a list of servers in this workgroup */
3895 SIVAL(svtype_p,0,SV_TYPE_ALL);
3897 if (call_api(PTR_DIFF(p+4,param),0,
3898 8,BUFFER_SIZE - SAFETY_MARGIN,
3903 int res = SVAL(rparam,0);
3904 int converter=SVAL(rparam,2);
3909 count=SVAL(rparam,4);
3912 printf("\n\nThis machine has a browse list:\n");
3913 printf("\n\tServer Comment\n");
3914 printf("\t--------- -------\n");
3917 for (i=0;i<count;i++) {
3919 int comment_offset = IVAL(p2,22) & 0xFFFF;
3920 printf("\t%-16.16s %s\n",
3922 comment_offset?rdata+comment_offset-converter:"");
3930 if (rparam) {free(rparam); rparam = NULL;}
3931 if (rdata) {free(rdata); rdata = NULL;}
3933 /* now ask for a list of workgroups */
3934 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3936 if (call_api(PTR_DIFF(p+4,param),0,
3937 8,BUFFER_SIZE - SAFETY_MARGIN,
3942 int res = SVAL(rparam,0);
3943 int converter=SVAL(rparam,2);
3948 count=SVAL(rparam,4);
3951 printf("\n\nThis machine has a workgroup list:\n");
3952 printf("\n\tWorkgroup Master\n");
3953 printf("\t--------- -------\n");
3956 for (i=0;i<count;i++) {
3958 int comment_offset = IVAL(p2,22) & 0xFFFF;
3959 printf("\t%-16.16s %s\n",
3961 comment_offset?rdata+comment_offset-converter:"");
3969 if (rparam) free(rparam);
3970 if (rdata) free(rdata);
3976 /* This defines the commands supported by this client */
3984 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3985 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3986 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3987 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3988 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3989 {"get",cmd_get,"<remote name> [local name] get a file"},
3990 {"mget",cmd_mget,"<mask> get all the matching files"},
3991 {"put",cmd_put,"<local name> [remote name] put a file"},
3992 {"mput",cmd_mput,"<mask> put all matching files"},
3993 {"rename",cmd_rename,"<src> <dest> rename some files"},
3994 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3995 {"mask",cmd_select,"<mask> mask all filenames against this"},
3996 {"del",cmd_del,"<mask> delete all matching files"},
3997 {"rm",cmd_del,"<mask> delete all matching files"},
3998 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3999 {"md",cmd_mkdir,"<directory> make a directory"},
4000 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
4001 {"rd",cmd_rmdir,"<directory> remove a directory"},
4002 {"pq",cmd_p_queue_4,"enumerate the print queue"},
4003 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
4004 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
4005 {"translate",cmd_translate,"toggle text translation for printing"},
4006 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
4007 {"print",cmd_print,"<file name> print a file"},
4008 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
4009 {"queue",cmd_queue,"show the print queue"},
4010 {"qinfo",cmd_qinfo,"show print queue information"},
4011 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
4012 {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
4013 {"quit",send_logout,"logoff the server"},
4014 {"q",send_logout,"logoff the server"},
4015 {"exit",send_logout,"logoff the server"},
4016 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
4017 {"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"},
4018 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
4019 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
4020 {"tarmode",cmd_tarmode,
4021 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
4022 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
4023 {"help",cmd_help,"[command] give help on a command"},
4024 {"?",cmd_help,"[command] give help on a command"},
4025 {"!",NULL,"run a shell command on the local system"},
4030 /*******************************************************************
4031 lookup a command string in the list of commands, including
4033 ******************************************************************/
4034 static int process_tok(fstring tok)
4036 int i = 0, matches = 0;
4038 int tok_len = strlen(tok);
4040 while (commands[i].fn != NULL)
4042 if (strequal(commands[i].name,tok))
4048 else if (strnequal(commands[i].name, tok, tok_len+1))
4058 else if (matches == 1)
4064 /****************************************************************************
4066 ****************************************************************************/
4072 if (next_token(NULL,buf,NULL))
4074 if ((i = process_tok(buf)) >= 0)
4075 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
4078 while (commands[i].description)
4080 for (j=0; commands[i].description && (j<5); j++) {
4081 DEBUG(0,("%-15s",commands[i].name));
4088 /****************************************************************************
4089 open the client sockets
4090 ****************************************************************************/
4091 static BOOL open_sockets(int port )
4093 static int last_port;
4101 if (port == 0) port=last_port;
4112 strcpy(service2,service);
4113 host = strtok(service2,"\\/");
4115 DEBUG(0,("Badly formed host name\n"));
4118 strcpy(desthost,host);
4122 get_myname(myname,NULL);
4126 DEBUG(3,("Opening sockets\n"));
4132 if ((hp = Get_Hostbyname(host))) {
4133 putip((char *)&dest_ip,(char *)hp->h_addr);
4137 /* Try and resolve the name with the netbios server */
4140 if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
4141 interpret_addr(lp_socket_address()))) != -1) {
4142 set_socket_options(bcast, "SO_BROADCAST");
4144 if (name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
4152 DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
4158 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
4162 DEBUG(3,("Connected\n"));
4164 set_socket_options(Client,user_socket_options);
4169 /****************************************************************************
4170 wait for keyboard activity, swallowing network packets
4171 ****************************************************************************/
4173 static char wait_keyboard(char *buffer)
4175 static void wait_keyboard(char *buffer)
4180 struct timeval timeout;
4190 FD_SET(Client,&fds);
4192 FD_SET(fileno(stdin),&fds);
4195 timeout.tv_sec = 20;
4196 timeout.tv_usec = 0;
4200 selrtn = sys_select(&fds,&timeout);
4203 if (FD_ISSET(fileno(stdin),&fds))
4210 set_blocking(fileno(stdin), False);
4211 readret = read_data( fileno(stdin), &ch, 1);
4212 set_blocking(fileno(stdin), True);
4215 if (errno != EAGAIN)
4217 /* should crash here */
4218 DEBUG(1,("readchar stdin failed\n"));
4221 else if (readret != 0)
4227 if (FD_ISSET(Client,&fds))
4228 receive_smb(Client,buffer,0);
4235 chkpath("\\",False);
4238 chkpath("\\",False);
4244 /****************************************************************************
4245 close and open the connection again
4246 ****************************************************************************/
4247 BOOL reopen_connection(char *inbuf,char *outbuf)
4249 static int open_count=0;
4253 if (open_count>5) return(False);
4255 DEBUG(1,("Trying to re-open connection\n"));
4257 set_message(outbuf,0,0,True);
4258 SCVAL(outbuf,smb_com,SMBtdis);
4259 SSVAL(outbuf,smb_tid,cnum);
4262 send_smb(Client,outbuf);
4263 receive_smb(Client,inbuf,SHORT_TIMEOUT);
4266 if (!open_sockets(0)) return(False);
4268 return(send_login(inbuf,outbuf,True,True));
4271 /****************************************************************************
4272 process commands from the client
4273 ****************************************************************************/
4274 static BOOL process(char *base_directory)
4280 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4281 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4283 if ((InBuffer == NULL) || (OutBuffer == NULL))
4286 bzero(OutBuffer,smb_size);
4288 if (!send_login(InBuffer,OutBuffer,True,True))
4291 if (*base_directory) do_cd(base_directory);
4294 if (cmd[0] != '\0') while (cmd[0] != '\0')
4300 if ((p = strchr(cmd, ';')) == 0)
4302 strncpy(line, cmd, 999);
4308 if (p - cmd > 999) p = cmd + 999;
4309 strncpy(line, cmd, p - cmd);
4310 line[p - cmd] = '\0';
4314 /* input language code to internal one */
4317 /* and get the first part of the command */
4320 if (!next_token(&ptr,tok,NULL)) continue;
4323 if ((i = process_tok(tok)) >= 0)
4324 commands[i].fn(InBuffer,OutBuffer);
4326 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4328 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4330 else while (!feof(stdin))
4335 bzero(OutBuffer,smb_size);
4337 /* display a prompt */
4338 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
4342 line[0] = wait_keyboard(InBuffer);
4343 /* this might not be such a good idea... */
4344 if ( line[0] == EOF)
4347 wait_keyboard(InBuffer);
4350 /* and get a response */
4352 fgets( &line[1],999, stdin);
4354 if (!fgets(line,1000,stdin))
4358 /* input language code to internal one */
4361 /* special case - first char is ! */
4368 /* and get the first part of the command */
4371 if (!next_token(&ptr,tok,NULL)) continue;
4374 if ((i = process_tok(tok)) >= 0)
4375 commands[i].fn(InBuffer,OutBuffer);
4377 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4379 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4387 /****************************************************************************
4388 usage on the program
4389 ****************************************************************************/
4390 static void usage(char *pname)
4392 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
4396 DEBUG(0,("[-t termcode] "));
4399 DEBUG(0,("\nVersion %s\n",VERSION));
4400 DEBUG(0,("\t-p port listen on the specified port\n"));
4401 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
4402 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
4403 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
4404 DEBUG(0,("\t-N don't ask for a password\n"));
4405 DEBUG(0,("\t-P connect to service as a printer\n"));
4406 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
4407 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
4408 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
4409 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
4410 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
4411 DEBUG(0,("\t-U username set the network username\n"));
4412 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
4413 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
4415 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
4417 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
4418 DEBUG(0,("\t-D directory start from directory\n"));
4422 /****************************************************************************
4424 ****************************************************************************/
4425 int main(int argc,char *argv[])
4427 fstring base_directory;
4428 char *pname = argv[0];
4429 int port = SMB_PORT;
4432 extern char *optarg;
4435 BOOL message = False;
4436 extern char tar_type;
4437 static pstring servicesf = CONFIGFILE;
4440 *base_directory = 0;
4444 setup_logging(pname,True);
4447 charset_initialise();
4458 strcpy(username,getenv("USER"));
4462 if (*username == 0 && getenv("LOGNAME"))
4464 strcpy(username,getenv("LOGNAME"));
4474 if (*argv[1] != '-')
4477 strcpy(service,argv[1]);
4478 /* Convert any '/' characters in the service name to '\' characters */
4479 string_replace( service, '/','\\');
4483 if (count_chars(service,'\\') < 3)
4486 printf("\n%s: Not enough '\\' characters in service\n",service);
4491 if (count_chars(service,'\\') > 3)
4494 printf("\n%s: Too many '\\' characters in service\n",service);
4499 if (argc > 1 && (*argv[1] != '-'))
4502 strcpy(password,argv[1]);
4503 memset(argv[1],'X',strlen(argv[1]));
4510 setup_term_code (KANJI);
4513 getopt(argc, argv,"s:B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
4517 max_protocol = interpret_protocol(optarg,max_protocol);
4520 strcpy(user_socket_options,optarg);
4523 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
4524 strcpy(desthost,optarg);
4529 iface_set_default(NULL,optarg,NULL);
4532 strcpy(base_directory,optarg);
4535 if (!tar_parseargs(argc, argv, optarg, optind)) {
4541 strcpy(scope,optarg);
4545 strcpy(query_host,optarg);
4550 strcpy(username,optarg);
4551 if ((p=strchr(username,'%')))
4554 strcpy(password,p+1);
4556 memset(strchr(optarg,'%')+1,'X',strlen(password));
4562 strcpy(workgroup,optarg);
4569 dest_ip = *interpret_addr2(optarg);
4570 if (zero_ip(dest_ip)) exit(1);
4575 strcpy(myname,optarg);
4581 connect_as_printer = True;
4587 DEBUGLEVEL = atoi(optarg);
4590 sprintf(debugf,"%s.client",optarg);
4593 port = atoi(optarg);
4604 strcpy(servicesf, optarg);
4608 if (!setup_term_code (optarg)) {
4609 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
4620 if (!tar_type && !*query_host && !*service && !message)
4627 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
4629 if(!get_myname(myhostname,NULL))
4631 DEBUG(0,("Failed to get my hostname.\n"));
4634 if (!lp_load(servicesf,True)) {
4635 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
4638 if (*workgroup == 0)
4639 strcpy(workgroup,lp_workgroup());
4642 get_myname(*myname?NULL:myname,NULL);
4648 if (open_sockets(port)) {
4649 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4650 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4653 if ((InBuffer == NULL) || (OutBuffer == NULL))
4656 bzero(OutBuffer,smb_size);
4657 if (!send_login(InBuffer,OutBuffer,True,True))
4660 if (*base_directory) do_cd(base_directory);
4662 ret=process_tar(InBuffer, OutBuffer);
4674 sprintf(service,"\\\\%s\\IPC$",query_host);
4676 connect_as_ipc = True;
4677 if (open_sockets(port))
4682 if (!send_login(NULL,NULL,True,True))
4686 if (!browse_host(True)) {
4690 if (!list_servers(workgroup)) {
4692 list_servers(workgroup);
4705 if (open_sockets(port))
4707 pstring inbuf,outbuf;
4708 bzero(outbuf,smb_size);
4709 if (!send_session_request(inbuf,outbuf))
4712 send_message(inbuf,outbuf);
4720 if (open_sockets(port))
4722 if (!process(base_directory))
4736 /* error code stuff - put together by Merik Karman
4737 merik@blackadder.dsh.oz.au */
4746 /* Dos Error Messages */
4747 err_code_struct dos_msgs[] = {
4748 {"ERRbadfunc",1,"Invalid function."},
4749 {"ERRbadfile",2,"File not found."},
4750 {"ERRbadpath",3,"Directory invalid."},
4751 {"ERRnofids",4,"No file descriptors available"},
4752 {"ERRnoaccess",5,"Access denied."},
4753 {"ERRbadfid",6,"Invalid file handle."},
4754 {"ERRbadmcb",7,"Memory control blocks destroyed."},
4755 {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
4756 {"ERRbadmem",9,"Invalid memory block address."},
4757 {"ERRbadenv",10,"Invalid environment."},
4758 {"ERRbadformat",11,"Invalid format."},
4759 {"ERRbadaccess",12,"Invalid open mode."},
4760 {"ERRbaddata",13,"Invalid data."},
4761 {"ERR",14,"reserved."},
4762 {"ERRbaddrive",15,"Invalid drive specified."},
4763 {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
4764 {"ERRdiffdevice",17,"Not same device."},
4765 {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
4766 {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
4767 {"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."},
4768 {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
4769 {"ERRbadpipe",230,"Pipe invalid."},
4770 {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
4771 {"ERRpipeclosing",232,"Pipe close in progress."},
4772 {"ERRnotconnected",233,"No process on other end of pipe."},
4773 {"ERRmoredata",234,"There is more data to be returned."},
4774 {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
4777 /* Server Error Messages */
4778 err_code_struct server_msgs[] = {
4779 {"ERRerror",1,"Non-specific error code."},
4780 {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
4781 {"ERRbadtype",3,"reserved."},
4782 {"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."},
4783 {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
4784 {"ERRinvnetname",6,"Invalid network name in tree connect."},
4785 {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
4786 {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
4787 {"ERRqtoobig",50,"Print queue full -- no space."},
4788 {"ERRqeof",51,"EOF on print queue dump."},
4789 {"ERRinvpfid",52,"Invalid print file FID."},
4790 {"ERRsmbcmd",64,"The server did not recognize the command received."},
4791 {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
4792 {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
4793 {"ERRreserved",68,"reserved."},
4794 {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
4795 {"ERRreserved",70,"reserved."},
4796 {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
4797 {"ERRpaused",81,"Server is paused."},
4798 {"ERRmsgoff",82,"Not receiving messages."},
4799 {"ERRnoroom",83,"No room to buffer message."},
4800 {"ERRrmuns",87,"Too many remote user names."},
4801 {"ERRtimeout",88,"Operation timed out."},
4802 {"ERRnoresource",89,"No resources currently available for request."},
4803 {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
4804 {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
4805 {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
4806 {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
4807 {"ERRcontmpx",252,"Continue in MPX mode."},
4808 {"ERRreserved",253,"reserved."},
4809 {"ERRreserved",254,"reserved."},
4810 {"ERRnosupport",0xFFFF,"Function not supported."},
4813 /* Hard Error Messages */
4814 err_code_struct hard_msgs[] = {
4815 {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
4816 {"ERRbadunit",20,"Unknown unit."},
4817 {"ERRnotready",21,"Drive not ready."},
4818 {"ERRbadcmd",22,"Unknown command."},
4819 {"ERRdata",23,"Data error (CRC)."},
4820 {"ERRbadreq",24,"Bad request structure length."},
4821 {"ERRseek",25 ,"Seek error."},
4822 {"ERRbadmedia",26,"Unknown media type."},
4823 {"ERRbadsector",27,"Sector not found."},
4824 {"ERRnopaper",28,"Printer out of paper."},
4825 {"ERRwrite",29,"Write fault."},
4826 {"ERRread",30,"Read fault."},
4827 {"ERRgeneral",31,"General failure."},
4828 {"ERRbadshare",32,"An open conflicts with an existing open."},
4829 {"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."},
4830 {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
4831 {"ERRFCBUnavail",35,"No FCBs are available to process request."},
4832 {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
4840 err_code_struct *err_msgs;
4843 {0x01,"ERRDOS",dos_msgs},
4844 {0x02,"ERRSRV",server_msgs},
4845 {0x03,"ERRHRD",hard_msgs},
4846 {0x04,"ERRXOS",NULL},
4847 {0xE1,"ERRRMX1",NULL},
4848 {0xE2,"ERRRMX2",NULL},
4849 {0xE3,"ERRRMX3",NULL},
4850 {0xFF,"ERRCMD",NULL},
4854 /****************************************************************************
4855 return a SMB error string from a SMB buffer
4856 ****************************************************************************/
4857 char *smb_errstr(char *inbuf)
4860 int class = CVAL(inbuf,smb_rcls);
4861 int num = SVAL(inbuf,smb_err);
4864 for (i=0;err_classes[i].class;i++)
4865 if (err_classes[i].code == class)
4867 if (err_classes[i].err_msgs)
4869 err_code_struct *err = err_classes[i].err_msgs;
4870 for (j=0;err[j].name;j++)
4871 if (num == err[j].code)
4874 sprintf(ret,"%s - %s (%s)",err_classes[i].class,
4875 err[j].name,err[j].message);
4877 sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
4882 sprintf(ret,"%s - %d",err_classes[i].class,num);
4886 sprintf(ret,"Error: Unknown error (%d,%d)",class,num);