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;
146 extern int coding_system;
147 static BOOL setup_term_code (char *code)
150 new = interpret_coding_system (code, UNKNOWN_CODE);
151 if (new != UNKNOWN_CODE) {
157 #define CNV_LANG(s) dos2unix_format(s,False)
158 #define CNV_INPUT(s) unix2dos_format(s,True)
160 /****************************************************************************
161 setup basics in a outgoing packet
162 ****************************************************************************/
163 void setup_pkt(char *outbuf)
165 SSVAL(outbuf,smb_pid,pid);
166 SSVAL(outbuf,smb_uid,uid);
167 SSVAL(outbuf,smb_mid,mid);
168 if (Protocol > PROTOCOL_COREPLUS)
170 SCVAL(outbuf,smb_flg,0x8);
171 SSVAL(outbuf,smb_flg2,0x1);
175 /****************************************************************************
176 write to a local file with CR/LF->LF translation if appropriate. return the
177 number taken from the buffer. This may not equal the number written.
178 ****************************************************************************/
179 static int writefile(int f, char *b, int n)
184 return(write(f,b,n));
189 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
193 if (write(f, b, 1) != 1)
204 /****************************************************************************
205 read from a file with LF->CR/LF translation if appropriate. return the
206 number read. read approx n bytes.
207 ****************************************************************************/
208 static int readfile(char *b, int size, int n, FILE *f)
213 if (!translation || (size != 1))
214 return(fread(b,size,n,f));
219 if ((c = getc(f)) == EOF)
224 if (c == '\n') /* change all LFs to CR/LF */
238 /****************************************************************************
239 read from a file with print translation. return the number read. read approx n
241 ****************************************************************************/
242 static int printread(FILE *f,char *b,int n)
246 i = readfile(b,1, n-1,f);
255 /****************************************************************************
256 check for existance of a dir
257 ****************************************************************************/
258 static BOOL chkpath(char *path,BOOL report)
261 pstring inbuf,outbuf;
265 trim_string(path2,NULL,"\\");
266 if (!*path2) *path2 = '\\';
268 bzero(outbuf,smb_size);
269 set_message(outbuf,0,4 + strlen(path2),True);
270 SCVAL(outbuf,smb_com,SMBchkpth);
271 SSVAL(outbuf,smb_tid,cnum);
280 /* this little bit of code can be used to extract NT error codes.
281 Just feed a bunch of "cd foo" commands to smbclient then watch
282 in netmon (tridge) */
284 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
285 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
290 send_smb(Client,outbuf);
291 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
293 if (report && CVAL(inbuf,smb_rcls) != 0)
294 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
296 return(CVAL(inbuf,smb_rcls) == 0);
300 /****************************************************************************
302 ****************************************************************************/
303 static void send_message(char *inbuf,char *outbuf)
310 /* send a SMBsendstrt command */
311 bzero(outbuf,smb_size);
312 set_message(outbuf,0,0,True);
313 CVAL(outbuf,smb_com) = SMBsendstrt;
314 SSVAL(outbuf,smb_tid,cnum);
319 p = skip_string(p,1);
322 p = skip_string(p,1);
324 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
326 send_smb(Client,outbuf);
329 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
331 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
335 grp_id = SVAL(inbuf,smb_vwv0);
337 printf("Connected. Type your message, ending it with a Control-D\n");
339 while (!feof(stdin) && total_len < 1600)
341 int maxlen = MIN(1600 - total_len,127);
348 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
355 CVAL(outbuf,smb_com) = SMBsendtxt;
357 set_message(outbuf,1,l+3,True);
359 SSVAL(outbuf,smb_vwv0,grp_id);
366 send_smb(Client,outbuf);
369 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
371 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
378 if (total_len >= 1600)
379 printf("the message was truncated to 1600 bytes ");
381 printf("sent %d bytes ",total_len);
383 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
385 CVAL(outbuf,smb_com) = SMBsendend;
386 set_message(outbuf,1,0,False);
387 SSVAL(outbuf,smb_vwv0,grp_id);
389 send_smb(Client,outbuf);
392 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
394 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
401 /****************************************************************************
402 check the space on a device
403 ****************************************************************************/
404 static void do_dskattr(void)
406 pstring inbuf,outbuf;
408 bzero(outbuf,smb_size);
409 set_message(outbuf,0,0,True);
410 CVAL(outbuf,smb_com) = SMBdskattr;
411 SSVAL(outbuf,smb_tid,cnum);
414 send_smb(Client,outbuf);
415 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
417 if (CVAL(inbuf,smb_rcls) != 0)
418 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
420 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
421 SVAL(inbuf,smb_vwv0),
422 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
423 SVAL(inbuf,smb_vwv3)));
426 /****************************************************************************
428 ****************************************************************************/
429 static void cmd_pwd(void)
431 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
432 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
436 /****************************************************************************
437 change directory - inner section
438 ****************************************************************************/
439 static void do_cd(char *newdir)
445 /* Save the current directory in case the
446 new directory is invalid */
447 strcpy(saved_dir, cur_dir);
452 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
453 strcat(cur_dir, "\\");
455 dos_clean_name(cur_dir);
456 strcpy(dname,cur_dir);
457 strcat(cur_dir,"\\");
458 dos_clean_name(cur_dir);
460 if (!strequal(cur_dir,"\\"))
461 if (!chkpath(dname,True))
462 strcpy(cur_dir,saved_dir);
464 strcpy(cd_path,cur_dir);
467 /****************************************************************************
469 ****************************************************************************/
470 static void cmd_cd(char *inbuf,char *outbuf)
474 if (next_token(NULL,buf,NULL))
477 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
481 /****************************************************************************
482 display info about a file
483 ****************************************************************************/
484 static void display_finfo(file_info *finfo)
486 if (do_this_one(finfo)) {
487 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
488 DEBUG(0,(" %-30s%7.7s%10d %s",
489 CNV_LANG(finfo->name),
490 attrib_string(finfo->mode),
492 asctime(LocalTime(&t))));
493 dir_total += finfo->size;
498 /****************************************************************************
499 do a directory listing, calling fn on each file found. Use the TRANSACT2
500 call for long filenames
501 ****************************************************************************/
502 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
504 int max_matches = 512;
505 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
510 char *dirlist = NULL;
512 int total_received = 0;
514 char *resp_data=NULL;
515 char *resp_param=NULL;
516 int resp_data_len = 0;
517 int resp_param_len=0;
519 int ff_resume_key = 0;
520 int ff_searchcount=0;
534 if (loop_count > 200)
536 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
542 setup = TRANSACT2_FINDFIRST;
543 SSVAL(param,0,attribute); /* attribute */
544 SSVAL(param,2,max_matches); /* max count */
545 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
546 SSVAL(param,6,info_level);
548 strcpy(param+12,mask);
552 setup = TRANSACT2_FINDNEXT;
553 SSVAL(param,0,ff_dir_handle);
554 SSVAL(param,2,max_matches); /* max count */
555 SSVAL(param,4,info_level);
556 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
557 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
558 strcpy(param+12,mask);
560 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
561 ff_dir_handle,ff_resume_key,ff_lastname,mask));
563 /* ??? original code added 1 pad byte after param */
565 send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
567 0,12+strlen(mask)+1,1,
570 if (!receive_trans_response(inbuf,SMBtrans2,
571 &resp_data_len,&resp_param_len,
572 &resp_data,&resp_param))
574 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
578 /* parse out some important return info */
582 ff_dir_handle = SVAL(p,0);
583 ff_searchcount = SVAL(p,2);
585 ff_lastname = SVAL(p,8);
589 ff_searchcount = SVAL(p,0);
591 ff_lastname = SVAL(p,6);
594 if (ff_searchcount == 0)
597 /* point to the data bytes */
600 /* we might need the lastname for continuations */
607 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
608 /* strcpy(mask,p+ff_lastname+94); */
611 strcpy(mask,p + ff_lastname + 1);
619 /* and add them to the dirlist pool */
620 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
624 DEBUG(0,("Failed to expand dirlist\n"));
628 /* put in a length for the last entry, to ensure we can chain entries
629 into the next packet */
632 for (p2=p,i=0;i<(ff_searchcount-1);i++)
633 p2 += interpret_long_filename(info_level,p2,NULL);
634 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
637 /* grab the data for later use */
638 memcpy(dirlist+dirlist_len,p,resp_data_len);
639 dirlist_len += resp_data_len;
641 total_received += ff_searchcount;
643 if (resp_data) free(resp_data); resp_data = NULL;
644 if (resp_param) free(resp_param); resp_param = NULL;
646 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
647 ff_searchcount,ff_eos,ff_resume_key));
653 for (p=dirlist,i=0;i<total_received;i++)
655 p += interpret_long_filename(info_level,p,&finfo);
656 display_finfo(&finfo);
659 for (p=dirlist,i=0;i<total_received;i++)
661 p += interpret_long_filename(info_level,p,&finfo);
662 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
665 /* free up the dirlist buffer */
666 if (dirlist) free(dirlist);
667 return(total_received);
671 /****************************************************************************
672 do a directory listing, calling fn on each file found
673 ****************************************************************************/
674 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
680 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
681 int num_received = 0;
683 char *dirlist = NULL;
695 bzero(outbuf,smb_size);
697 set_message(outbuf,2,5 + strlen(mask),True);
699 set_message(outbuf,2,5 + 21,True);
702 if (Protocol >= PROTOCOL_LANMAN1)
703 CVAL(outbuf,smb_com) = SMBffirst;
706 CVAL(outbuf,smb_com) = SMBsearch;
708 SSVAL(outbuf,smb_tid,cnum);
711 SSVAL(outbuf,smb_vwv0,num_asked);
712 SSVAL(outbuf,smb_vwv1,attribute);
733 send_smb(Client,outbuf);
734 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
736 received = SVAL(inbuf,smb_vwv0);
738 DEBUG(5,("dir received %d\n",received));
740 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
742 if (received <= 0) break;
746 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
751 p = smb_buf(inbuf) + 3;
753 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
754 p,received*DIR_STRUCT_SIZE);
756 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
758 num_received += received;
760 if (CVAL(inbuf,smb_rcls) != 0) break;
764 if (!first && Protocol >= PROTOCOL_LANMAN1)
766 bzero(outbuf,smb_size);
767 CVAL(outbuf,smb_com) = SMBfclose;
769 SSVAL(outbuf,smb_tid,cnum);
783 send_smb(Client,outbuf);
784 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
786 if (CVAL(inbuf,smb_rcls) != 0)
787 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
792 for (p=dirlist,i=0;i<num_received;i++)
794 p += interpret_short_filename(p,&finfo);
795 display_finfo(&finfo);
798 for (p=dirlist,i=0;i<num_received;i++)
800 p += interpret_short_filename(p,&finfo);
801 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
804 if (dirlist) free(dirlist);
805 return(num_received);
810 /****************************************************************************
811 do a directory listing, calling fn on each file found
812 ****************************************************************************/
813 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
815 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
816 if (Protocol >= PROTOCOL_LANMAN2)
818 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
822 expand_mask(Mask,False);
823 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
827 /*******************************************************************
828 decide if a file should be operated on
829 ********************************************************************/
830 static BOOL do_this_one(file_info *finfo)
832 if (finfo->mode & aDIR) return(True);
834 if (newer_than && finfo->mtime < newer_than)
837 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
844 /*****************************************************************************
845 Convert a character pointer in a call_api() response to a form we can use.
846 This function contains code to prevent core dumps if the server returns
848 *****************************************************************************/
849 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
851 if( datap == 0 ) /* turn NULL pointers */
852 { /* into zero length strings */
857 unsigned int offset = datap - converter;
859 if( offset >= rdrcnt )
861 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
866 return &rdata[offset];
871 /****************************************************************************
872 interpret a short filename structure
873 The length of the structure is returned
874 ****************************************************************************/
875 static int interpret_short_filename(char *p,file_info *finfo)
877 finfo->mode = CVAL(p,21);
879 /* this date is converted to GMT by make_unix_date */
880 finfo->ctime = make_unix_date(p+22);
881 finfo->mtime = finfo->atime = finfo->ctime;
882 finfo->size = IVAL(p,26);
883 strcpy(finfo->name,p+30);
885 return(DIR_STRUCT_SIZE);
888 /****************************************************************************
889 interpret a long filename structure - this is mostly guesses at the moment
890 The length of the structure is returned
891 The structure of a long filename depends on the info level. 260 is used
892 by NT and 2 is used by OS/2
893 ****************************************************************************/
894 static int interpret_long_filename(int level,char *p,file_info *finfo)
897 memcpy(finfo,&def_finfo,sizeof(*finfo));
901 case 1: /* OS/2 understands this */
904 /* these dates are converted to GMT by make_unix_date */
905 finfo->ctime = make_unix_date2(p+4);
906 finfo->atime = make_unix_date2(p+8);
907 finfo->mtime = make_unix_date2(p+12);
908 finfo->size = IVAL(p,16);
909 finfo->mode = CVAL(p,24);
910 strcpy(finfo->name,p+27);
912 return(28 + CVAL(p,26));
914 case 2: /* this is what OS/2 uses mostly */
917 /* these dates are converted to GMT by make_unix_date */
918 finfo->ctime = make_unix_date2(p+4);
919 finfo->atime = make_unix_date2(p+8);
920 finfo->mtime = make_unix_date2(p+12);
921 finfo->size = IVAL(p,16);
922 finfo->mode = CVAL(p,24);
923 strcpy(finfo->name,p+31);
925 return(32 + CVAL(p,30));
927 /* levels 3 and 4 are untested */
931 /* these dates are probably like the other ones */
932 finfo->ctime = make_unix_date2(p+8);
933 finfo->atime = make_unix_date2(p+12);
934 finfo->mtime = make_unix_date2(p+16);
935 finfo->size = IVAL(p,20);
936 finfo->mode = CVAL(p,28);
937 strcpy(finfo->name,p+33);
944 /* these dates are probably like the other ones */
945 finfo->ctime = make_unix_date2(p+8);
946 finfo->atime = make_unix_date2(p+12);
947 finfo->mtime = make_unix_date2(p+16);
948 finfo->size = IVAL(p,20);
949 finfo->mode = CVAL(p,28);
950 strcpy(finfo->name,p+37);
954 case 260: /* NT uses this, but also accepts 2 */
959 p += 4; /* next entry offset */
960 p += 4; /* fileindex */
962 /* these dates appear to arrive in a weird way. It seems to
963 be localtime plus the serverzone given in the initial
964 connect. This is GMT when DST is not in effect and one
965 hour from GMT otherwise. Can this really be right??
967 I suppose this could be called kludge-GMT. Is is the GMT
968 you get by using the current DST setting on a different
969 localtime. It will be cheap to calculate, I suppose, as
970 no DST tables will be needed */
972 finfo->ctime = interpret_long_date(p); p += 8;
973 finfo->atime = interpret_long_date(p); p += 8;
974 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
975 finfo->size = IVAL(p,0); p += 8;
976 p += 8; /* alloc size */
977 finfo->mode = CVAL(p,0); p += 4;
978 namelen = IVAL(p,0); p += 4;
979 p += 4; /* EA size */
980 p += 2; /* short name len? */
981 p += 24; /* short name? */
982 StrnCpy(finfo->name,p,namelen);
988 DEBUG(1,("Unknown long filename format %d\n",level));
995 /****************************************************************************
996 act on the files in a dir listing
997 ****************************************************************************/
998 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
1001 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
1002 !mask_match(finfo->name,fileselection,False,False)) &&
1003 !(recurse_dir && (strequal(finfo->name,".") ||
1004 strequal(finfo->name,".."))))
1006 if (recurse_dir && (finfo->mode & aDIR))
1010 strcpy(sav_dir,cur_dir);
1011 strcat(cur_dir,finfo->name);
1012 strcat(cur_dir,"\\");
1013 strcpy(mask2,cur_dir);
1016 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1021 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);
1023 do_dir(inbuf,outbuf,mask2,attribute,fn,True);
1025 strcpy(cur_dir,sav_dir);
1029 if (fn && do_this_one(finfo))
1036 /****************************************************************************
1037 receive a SMB trans or trans2 response allocating the necessary memory
1038 ****************************************************************************/
1039 static BOOL receive_trans_response(char *inbuf,int trans,
1040 int *data_len,int *param_len,
1041 char **data,char **param)
1045 int this_data,this_param;
1047 *data_len = *param_len = 0;
1049 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1053 if (CVAL(inbuf,smb_com) != trans)
1055 DEBUG(0,("Expected %s response, got command 0x%02x\n",
1056 trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
1059 if (CVAL(inbuf,smb_rcls) != 0)
1062 /* parse out the lengths */
1063 total_data = SVAL(inbuf,smb_tdrcnt);
1064 total_param = SVAL(inbuf,smb_tprcnt);
1067 *data = Realloc(*data,total_data);
1068 *param = Realloc(*param,total_param);
1072 this_data = SVAL(inbuf,smb_drcnt);
1073 this_param = SVAL(inbuf,smb_prcnt);
1075 memcpy(*data + SVAL(inbuf,smb_drdisp),
1076 smb_base(inbuf) + SVAL(inbuf,smb_droff),
1079 memcpy(*param + SVAL(inbuf,smb_prdisp),
1080 smb_base(inbuf) + SVAL(inbuf,smb_proff),
1082 *data_len += this_data;
1083 *param_len += this_param;
1085 /* parse out the total lengths again - they can shrink! */
1086 total_data = SVAL(inbuf,smb_tdrcnt);
1087 total_param = SVAL(inbuf,smb_tprcnt);
1089 if (total_data <= *data_len && total_param <= *param_len)
1092 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1096 if (CVAL(inbuf,smb_com) != trans)
1098 DEBUG(0,("Expected %s response, got command 0x%02x\n",
1099 trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
1102 if (CVAL(inbuf,smb_rcls) != 0)
1110 /****************************************************************************
1111 get a directory listing
1112 ****************************************************************************/
1113 static void cmd_dir(char *inbuf,char *outbuf)
1115 int attribute = aDIR | aSYSTEM | aHIDDEN;
1121 strcpy(mask,cur_dir);
1122 if(mask[strlen(mask)-1]!='\\')
1125 if (next_token(NULL,buf,NULL))
1136 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1140 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1145 /****************************************************************************
1146 get a file from rname to lname
1147 ****************************************************************************/
1148 static void do_get(char *rname,char *lname,file_info *finfo1)
1153 BOOL newhandle = False;
1154 char *inbuf,*outbuf;
1156 BOOL close_done = False;
1157 BOOL ignore_close_error = False;
1161 struct timeval tp_start;
1162 GetTimeOfDay(&tp_start);
1173 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1174 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1176 if (!inbuf || !outbuf)
1178 DEBUG(0,("out of memory\n"));
1182 bzero(outbuf,smb_size);
1183 set_message(outbuf,15,1 + strlen(rname),True);
1185 CVAL(outbuf,smb_com) = SMBopenX;
1186 SSVAL(outbuf,smb_tid,cnum);
1189 SSVAL(outbuf,smb_vwv0,0xFF);
1190 SSVAL(outbuf,smb_vwv2,1);
1191 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1192 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1193 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1194 SSVAL(outbuf,smb_vwv8,1);
1196 p = smb_buf(outbuf);
1198 p = skip_string(p,1);
1200 /* do a chained openX with a readX? */
1204 DEBUG(3,("Chaining readX wth openX\n"));
1205 SSVAL(outbuf,smb_vwv0,SMBreadX);
1206 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1209 SSVAL(p,smb_wct,10);
1210 SSVAL(p,smb_vwv0,0xFF);
1211 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1212 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1213 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1217 if(!strcmp(lname,"-"))
1218 handle = fileno(stdout);
1221 handle = creat(lname,0644);
1226 DEBUG(0,("Error opening local file %s\n",lname));
1227 free(inbuf);free(outbuf);
1231 send_smb(Client,outbuf);
1232 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1234 if (CVAL(inbuf,smb_rcls) != 0)
1236 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1237 SVAL(inbuf,smb_err) == ERRnoresource &&
1238 reopen_connection(inbuf,outbuf))
1240 do_get(rname,lname,finfo1);
1243 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1246 free(inbuf);free(outbuf);
1250 strcpy(finfo.name,rname);
1254 finfo.mode = SVAL(inbuf,smb_vwv3);
1255 /* these times arrive as LOCAL time, using the DST offset
1256 corresponding to that time, we convert them to GMT */
1257 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1258 finfo.atime = finfo.ctime = finfo.mtime;
1259 finfo.size = IVAL(inbuf,smb_vwv6);
1262 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1264 fnum = SVAL(inbuf,smb_vwv2);
1266 /* we might have got some data from a chained readX */
1267 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1269 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1270 datalen = SVAL(p,smb_vwv5);
1271 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1280 DEBUG(2,("getting file %s of size %d bytes as %s ",
1281 CNV_LANG(finfo.name),
1285 while (nread < finfo.size && !close_done)
1288 static BOOL can_chain_close = True;
1292 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1294 /* 3 possible read types. readbraw if a large block is required.
1295 readX + close if not much left and read if neither is supported */
1297 /* we might have already read some data from a chained readX */
1298 if (dataptr && datalen>0)
1301 /* if we can finish now then readX+close */
1302 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1303 ((finfo.size - nread) <
1304 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1307 /* if we support readraw then use that */
1308 if (method<0 && readbraw_supported)
1311 /* if we can then use readX */
1312 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1323 /* use readX + close */
1324 bzero(outbuf,smb_size);
1325 set_message(outbuf,10,0,True);
1326 CVAL(outbuf,smb_com) = SMBreadX;
1327 SSVAL(outbuf,smb_tid,cnum);
1332 CVAL(outbuf,smb_vwv0) = SMBclose;
1333 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1336 CVAL(outbuf,smb_vwv0) = 0xFF;
1338 SSVAL(outbuf,smb_vwv2,fnum);
1339 SIVAL(outbuf,smb_vwv3,nread);
1340 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1341 SSVAL(outbuf,smb_vwv6,0);
1342 SIVAL(outbuf,smb_vwv7,0);
1343 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1347 p = smb_buf(outbuf);
1354 /* now set the total packet length */
1355 smb_setlen(outbuf,smb_len(outbuf)+9);
1358 send_smb(Client,outbuf);
1359 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1361 if (CVAL(inbuf,smb_rcls) != 0)
1363 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1368 SVAL(inbuf,smb_vwv0) != SMBclose)
1370 /* NOTE: WfWg sometimes just ignores the chained
1371 command! This seems to break the spec? */
1372 DEBUG(3,("Rejected chained close?\n"));
1374 can_chain_close = False;
1375 ignore_close_error = True;
1378 datalen = SVAL(inbuf,smb_vwv5);
1379 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1385 static int readbraw_size = BUFFER_SIZE;
1388 bzero(outbuf,smb_size);
1389 set_message(outbuf,8,0,True);
1390 CVAL(outbuf,smb_com) = SMBreadbraw;
1391 SSVAL(outbuf,smb_tid,cnum);
1393 SSVAL(outbuf,smb_vwv0,fnum);
1394 SIVAL(outbuf,smb_vwv1,nread);
1395 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1396 SSVAL(outbuf,smb_vwv4,0);
1397 SIVALS(outbuf,smb_vwv5,-1);
1398 send_smb(Client,outbuf);
1400 /* Now read the raw data into the buffer and write it */
1401 if(read_smb_length(Client,inbuf,0) == -1) {
1402 DEBUG(0,("Failed to read length in readbraw\n"));
1406 /* Even though this is not an smb message, smb_len
1407 returns the generic length of an smb message */
1408 datalen = smb_len(inbuf);
1412 /* we got a readbraw error */
1413 DEBUG(4,("readbraw error - reducing size\n"));
1414 readbraw_size = (readbraw_size * 9) / 10;
1416 if (readbraw_size < max_xmit)
1418 DEBUG(0,("disabling readbraw\n"));
1419 readbraw_supported = False;
1426 if(read_data(Client,inbuf,datalen) != datalen) {
1427 DEBUG(0,("Failed to read data in readbraw\n"));
1435 /* we've already read some data with a chained readX */
1439 /* use plain read */
1440 bzero(outbuf,smb_size);
1441 set_message(outbuf,5,0,True);
1442 CVAL(outbuf,smb_com) = SMBread;
1443 SSVAL(outbuf,smb_tid,cnum);
1446 SSVAL(outbuf,smb_vwv0,fnum);
1447 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1448 SIVAL(outbuf,smb_vwv2,nread);
1449 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1451 send_smb(Client,outbuf);
1452 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1454 if (CVAL(inbuf,smb_rcls) != 0)
1456 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1460 datalen = SVAL(inbuf,smb_vwv0);
1461 dataptr = smb_buf(inbuf) + 3;
1465 if (writefile(handle,dataptr,datalen) != datalen)
1467 DEBUG(0,("Error writing local file\n"));
1474 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1486 bzero(outbuf,smb_size);
1487 set_message(outbuf,3,0,True);
1488 CVAL(outbuf,smb_com) = SMBclose;
1489 SSVAL(outbuf,smb_tid,cnum);
1492 SSVAL(outbuf,smb_vwv0,fnum);
1493 SIVALS(outbuf,smb_vwv1,-1);
1495 send_smb(Client,outbuf);
1496 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1498 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1500 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1503 free(inbuf);free(outbuf);
1511 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1512 bzero(outbuf,smb_size);
1513 set_message(outbuf,8,strlen(rname)+4,True);
1514 CVAL(outbuf,smb_com) = SMBsetatr;
1515 SSVAL(outbuf,smb_tid,cnum);
1517 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1518 SIVALS(outbuf,smb_vwv1,0);
1519 p = smb_buf(outbuf);
1525 send_smb(Client,outbuf);
1526 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1530 struct timeval tp_end;
1533 GetTimeOfDay(&tp_end);
1535 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1536 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1537 get_total_time_ms += this_time;
1538 get_total_size += finfo.size;
1540 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1541 finfo.size / (1.024*this_time + 1.0e-4),
1542 get_total_size / (1.024*get_total_time_ms)));
1545 free(inbuf);free(outbuf);
1549 /****************************************************************************
1551 ****************************************************************************/
1552 static void cmd_get(void)
1558 strcpy(rname,cur_dir);
1561 p = rname + strlen(rname);
1563 if (!next_token(NULL,p,NULL)) {
1564 DEBUG(0,("get <filename>\n"));
1568 dos_clean_name(rname);
1570 next_token(NULL,lname,NULL);
1572 do_get(rname,lname,NULL);
1576 /****************************************************************************
1577 do a mget operation on one file
1578 ****************************************************************************/
1579 static void do_mget(file_info *finfo)
1584 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1589 DEBUG(0,("mget aborted\n"));
1593 if (finfo->mode & aDIR)
1594 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1596 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1598 if (prompt && !yesno(quest)) return;
1600 if (finfo->mode & aDIR)
1602 pstring saved_curdir;
1604 char *inbuf,*outbuf;
1606 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1607 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1609 if (!inbuf || !outbuf)
1611 DEBUG(0,("out of memory\n"));
1615 strcpy(saved_curdir,cur_dir);
1617 strcat(cur_dir,finfo->name);
1618 strcat(cur_dir,"\\");
1620 unix_format(finfo->name);
1623 strlower(finfo->name);
1625 if (!directory_exist(finfo->name,NULL) &&
1626 sys_mkdir(finfo->name,0777) != 0)
1628 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1629 strcpy(cur_dir,saved_curdir);
1630 free(inbuf);free(outbuf);
1634 if (sys_chdir(finfo->name) != 0)
1636 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1637 strcpy(cur_dir,saved_curdir);
1638 free(inbuf);free(outbuf);
1643 strcpy(mget_mask,cur_dir);
1644 strcat(mget_mask,"*");
1646 do_dir((char *)inbuf,(char *)outbuf,
1647 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1649 strcpy(cur_dir,saved_curdir);
1650 free(inbuf);free(outbuf);
1654 strcpy(rname,cur_dir);
1655 strcat(rname,finfo->name);
1656 do_get(rname,finfo->name,finfo);
1660 /****************************************************************************
1661 view the file using the pager
1662 ****************************************************************************/
1663 static void cmd_more(void)
1665 fstring rname,lname,tmpname,pager_cmd;
1668 strcpy(rname,cur_dir);
1670 sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1671 strcpy(lname,tmpname);
1673 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1674 DEBUG(0,("more <filename>\n"));
1677 dos_clean_name(rname);
1679 do_get(rname,lname,NULL);
1681 pager=getenv("PAGER");
1682 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1689 /****************************************************************************
1691 ****************************************************************************/
1692 static void cmd_mget(char *inbuf,char *outbuf)
1694 int attribute = aSYSTEM | aHIDDEN;
1706 while (next_token(NULL,p,NULL))
1708 strcpy(mget_mask,cur_dir);
1709 if(mget_mask[strlen(mget_mask)-1]!='\\')
1710 strcat(mget_mask,"\\");
1713 strcpy(mget_mask,p);
1715 strcat(mget_mask,p);
1716 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1721 strcpy(mget_mask,cur_dir);
1722 if(mget_mask[strlen(mget_mask)-1]!='\\')
1723 strcat(mget_mask,"\\");
1724 strcat(mget_mask,"*");
1725 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1729 /****************************************************************************
1730 make a directory of name "name"
1731 ****************************************************************************/
1732 static BOOL do_mkdir(char *name)
1735 char *inbuf,*outbuf;
1737 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1738 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1740 if (!inbuf || !outbuf)
1742 DEBUG(0,("out of memory\n"));
1746 bzero(outbuf,smb_size);
1747 set_message(outbuf,0,2 + strlen(name),True);
1749 CVAL(outbuf,smb_com) = SMBmkdir;
1750 SSVAL(outbuf,smb_tid,cnum);
1754 p = smb_buf(outbuf);
1758 send_smb(Client,outbuf);
1759 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1761 if (CVAL(inbuf,smb_rcls) != 0)
1763 DEBUG(0,("%s making remote directory %s\n",
1764 smb_errstr(inbuf),CNV_LANG(name)));
1766 free(inbuf);free(outbuf);
1770 free(inbuf);free(outbuf);
1775 /****************************************************************************
1777 ****************************************************************************/
1778 static void cmd_mkdir(char *inbuf,char *outbuf)
1784 strcpy(mask,cur_dir);
1786 if (!next_token(NULL,p,NULL))
1789 DEBUG(0,("mkdir <dirname>\n"));
1801 trim_string(ddir,".",NULL);
1802 p = strtok(ddir,"/\\");
1806 if (!chkpath(ddir2,False))
1811 p = strtok(NULL,"/\\");
1819 /*******************************************************************
1820 write to a file using writebraw
1821 ********************************************************************/
1822 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1827 bzero(outbuf,smb_size);
1828 bzero(inbuf,smb_size);
1829 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1831 CVAL(outbuf,smb_com) = SMBwritebraw;
1832 SSVAL(outbuf,smb_tid,cnum);
1835 SSVAL(outbuf,smb_vwv0,fnum);
1836 SSVAL(outbuf,smb_vwv1,n);
1837 SIVAL(outbuf,smb_vwv3,pos);
1838 SSVAL(outbuf,smb_vwv7,1);
1840 send_smb(Client,outbuf);
1842 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1845 _smb_setlen(buf-4,n); /* HACK! XXXX */
1847 if (write_socket(Client,buf-4,n+4) != n+4)
1850 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1851 DEBUG(0,("Error writing remote file (2)\n"));
1854 return(SVAL(inbuf,smb_vwv0));
1859 /*******************************************************************
1861 ********************************************************************/
1862 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1866 if (writebraw_supported && n > (max_xmit-200))
1867 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1869 bzero(outbuf,smb_size);
1870 bzero(inbuf,smb_size);
1871 set_message(outbuf,5,n + 3,True);
1873 CVAL(outbuf,smb_com) = SMBwrite;
1874 SSVAL(outbuf,smb_tid,cnum);
1877 SSVAL(outbuf,smb_vwv0,fnum);
1878 SSVAL(outbuf,smb_vwv1,n);
1879 SIVAL(outbuf,smb_vwv2,pos);
1880 SSVAL(outbuf,smb_vwv4,0);
1881 CVAL(smb_buf(outbuf),0) = 1;
1882 SSVAL(smb_buf(outbuf),1,n);
1884 memcpy(smb_buf(outbuf)+3,buf,n);
1886 send_smb(Client,outbuf);
1887 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1889 if (CVAL(inbuf,smb_rcls) != 0) {
1890 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1893 return(SVAL(inbuf,smb_vwv0));
1898 /****************************************************************************
1900 ****************************************************************************/
1901 static void do_put(char *rname,char *lname,file_info *finfo)
1907 char *inbuf,*outbuf;
1908 time_t close_time = finfo->mtime;
1910 static int maxwrite=0;
1912 struct timeval tp_start;
1913 GetTimeOfDay(&tp_start);
1915 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1916 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1918 if (!inbuf || !outbuf)
1920 DEBUG(0,("out of memory\n"));
1924 bzero(outbuf,smb_size);
1925 set_message(outbuf,3,2 + strlen(rname),True);
1927 if (finfo->mtime == 0 || finfo->mtime == -1)
1928 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1930 CVAL(outbuf,smb_com) = SMBcreate;
1931 SSVAL(outbuf,smb_tid,cnum);
1934 SSVAL(outbuf,smb_vwv0,finfo->mode);
1935 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1937 p = smb_buf(outbuf);
1941 send_smb(Client,outbuf);
1942 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1944 if (CVAL(inbuf,smb_rcls) != 0)
1946 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1948 free(inbuf);free(outbuf);if (buf) free(buf);
1952 f = fopen(lname,"r");
1956 DEBUG(0,("Error opening local file %s\n",lname));
1957 free(inbuf);free(outbuf);
1962 fnum = SVAL(inbuf,smb_vwv0);
1963 if (finfo->size < 0)
1964 finfo->size = file_size(lname);
1966 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1969 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1971 while (nread < finfo->size)
1976 n = MIN(n,finfo->size - nread);
1978 buf = (char *)Realloc(buf,n+4);
1980 fseek(f,nread,SEEK_SET);
1981 if ((n = readfile(buf+4,1,n,f)) < 1)
1983 DEBUG(0,("Error reading local file\n"));
1987 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1991 DEBUG(0,("Error writing file\n"));
2004 bzero(outbuf,smb_size);
2005 set_message(outbuf,3,0,True);
2006 CVAL(outbuf,smb_com) = SMBclose;
2007 SSVAL(outbuf,smb_tid,cnum);
2010 SSVAL(outbuf,smb_vwv0,fnum);
2011 put_dos_date3(outbuf,smb_vwv1,close_time);
2013 send_smb(Client,outbuf);
2014 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2016 if (CVAL(inbuf,smb_rcls) != 0)
2018 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2020 free(inbuf);free(outbuf);
2027 free(inbuf);free(outbuf);
2031 struct timeval tp_end;
2034 GetTimeOfDay(&tp_end);
2036 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
2037 (tp_end.tv_usec - tp_start.tv_usec)/1000;
2038 put_total_time_ms += this_time;
2039 put_total_size += finfo->size;
2041 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
2042 finfo->size / (1.024*this_time + 1.0e-4),
2043 put_total_size / (1.024*put_total_time_ms)));
2049 /****************************************************************************
2051 ****************************************************************************/
2052 static void cmd_put(void)
2061 strcpy(rname,cur_dir);
2065 if (!next_token(NULL,p,NULL))
2067 DEBUG(0,("put <filename>\n"));
2072 if (next_token(NULL,p,NULL))
2075 strcat(rname,lname);
2077 dos_clean_name(rname);
2081 if (!file_exist(lname,&st)) {
2082 DEBUG(0,("%s does not exist\n",lname));
2085 finfo.mtime = st.st_mtime;
2088 do_put(rname,lname,&finfo);
2091 /****************************************************************************
2092 seek in a directory/file list until you get something that doesn't start with
2094 ****************************************************************************/
2095 static BOOL seek_list(FILE *f,char *name)
2100 if (fscanf(f,"%s",s) != 1) return(False);
2101 trim_string(s,"./",NULL);
2102 if (strncmp(s,name,strlen(name)) != 0)
2113 /****************************************************************************
2114 set the file selection mask
2115 ****************************************************************************/
2116 static void cmd_select(void)
2118 strcpy(fileselection,"");
2119 next_token(NULL,fileselection,NULL);
2123 /****************************************************************************
2125 ****************************************************************************/
2126 static void cmd_mput(void)
2137 while (next_token(NULL,p,NULL))
2144 sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2146 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2148 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2151 f = fopen(tmpname,"r");
2158 if (fscanf(f,"%s",lname) != 1) break;
2159 trim_string(lname,"./",NULL);
2163 /* check if it's a directory */
2164 if (directory_exist(lname,&st))
2166 if (!recurse) continue;
2167 sprintf(quest,"Put directory %s? ",lname);
2168 if (prompt && !yesno(quest))
2171 if (!seek_list(f,lname))
2176 strcpy(rname,cur_dir);
2177 strcat(rname,lname);
2178 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2180 if (!seek_list(f,lname))
2189 sprintf(quest,"Put file %s? ",lname);
2190 if (prompt && !yesno(quest)) continue;
2192 strcpy(rname,cur_dir);
2193 strcat(rname,lname);
2197 /* null size so do_put knows to ignore it */
2200 /* set the date on the file */
2201 finfo.mtime = st.st_mtime;
2203 do_put(rname,lname,&finfo);
2210 /****************************************************************************
2212 ****************************************************************************/
2213 static void do_cancel(int job)
2215 char *rparam = NULL;
2221 bzero(param,sizeof(param));
2224 SSVAL(p,0,81); /* DosPrintJobDel() */
2227 p = skip_string(p,1);
2229 p = skip_string(p,1);
2233 if (call_api(PTR_DIFF(p,param),0,
2239 int res = SVAL(rparam,0);
2242 printf("Job %d cancelled\n",job);
2244 printf("Error %d calcelling job %d\n",res,job);
2248 printf("Server refused cancel request\n");
2250 if (rparam) free(rparam);
2251 if (rdata) free(rdata);
2257 /****************************************************************************
2259 ****************************************************************************/
2260 static void cmd_cancel(char *inbuf,char *outbuf )
2265 if (!connect_as_printer)
2267 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2268 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2271 if (!next_token(NULL,buf,NULL)) {
2272 printf("cancel <jobid> ...\n");
2278 } while (next_token(NULL,buf,NULL));
2282 /****************************************************************************
2284 ****************************************************************************/
2285 static void cmd_stat(char *inbuf,char *outbuf)
2289 char *resp_data=NULL;
2290 char *resp_param=NULL;
2291 int resp_data_len = 0;
2292 int resp_param_len=0;
2294 uint16 setup = TRANSACT2_QPATHINFO;
2296 if (!next_token(NULL,buf,NULL)) {
2297 printf("stat <file>\n");
2302 SSVAL(param,0,4); /* level */
2307 send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
2309 0,6 + strlen(p)+1,1,
2312 receive_trans_response(inbuf,SMBtrans2,
2313 &resp_data_len,&resp_param_len,
2314 &resp_data,&resp_param);
2316 if (resp_data) free(resp_data); resp_data = NULL;
2317 if (resp_param) free(resp_param); resp_param = NULL;
2321 /****************************************************************************
2323 ****************************************************************************/
2324 static void cmd_print(char *inbuf,char *outbuf )
2333 if (!connect_as_printer)
2335 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2336 DEBUG(0,("Trying to print without -P may fail\n"));
2339 if (!next_token(NULL,lname,NULL))
2341 DEBUG(0,("print <filename>\n"));
2345 strcpy(rname,lname);
2346 p = strrchr(rname,'/');
2351 strcpy(rname,tname);
2354 if ((int)strlen(rname) > 14)
2357 if (strequal(lname,"-"))
2360 strcpy(rname,"stdin");
2363 dos_clean_name(rname);
2365 bzero(outbuf,smb_size);
2366 set_message(outbuf,2,2 + strlen(rname),True);
2368 CVAL(outbuf,smb_com) = SMBsplopen;
2369 SSVAL(outbuf,smb_tid,cnum);
2372 SSVAL(outbuf,smb_vwv0,0);
2373 SSVAL(outbuf,smb_vwv1,printmode);
2375 p = smb_buf(outbuf);
2379 send_smb(Client,outbuf);
2380 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2382 if (CVAL(inbuf,smb_rcls) != 0)
2384 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2389 f = fopen(lname,"r");
2392 DEBUG(0,("Error opening local file %s\n",lname));
2397 fnum = SVAL(inbuf,smb_vwv0);
2399 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2405 bzero(outbuf,smb_size);
2406 set_message(outbuf,1,3,True);
2408 /* for some strange reason the OS/2 print server can't handle large
2409 packets when printing. weird */
2410 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2413 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2415 n = readfile(smb_buf(outbuf)+3,1,n,f);
2418 DEBUG(0,("read gave %d\n",n));
2422 smb_setlen(outbuf,smb_len(outbuf) + n);
2424 CVAL(outbuf,smb_com) = SMBsplwr;
2425 SSVAL(outbuf,smb_tid,cnum);
2428 SSVAL(outbuf,smb_vwv0,fnum);
2429 SSVAL(outbuf,smb_vwv1,n+3);
2430 CVAL(smb_buf(outbuf),0) = 1;
2431 SSVAL(smb_buf(outbuf),1,n);
2433 send_smb(Client,outbuf);
2434 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2436 if (CVAL(inbuf,smb_rcls) != 0)
2438 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2445 DEBUG(2,("%d bytes printed\n",nread));
2447 bzero(outbuf,smb_size);
2448 set_message(outbuf,1,0,True);
2449 CVAL(outbuf,smb_com) = SMBsplclose;
2450 SSVAL(outbuf,smb_tid,cnum);
2453 SSVAL(outbuf,smb_vwv0,fnum);
2455 send_smb(Client,outbuf);
2456 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2458 if (CVAL(inbuf,smb_rcls) != 0)
2460 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2470 /****************************************************************************
2471 show a print queue - this is deprecated as it uses the old smb that
2472 has limited support - the correct call is the cmd_p_queue_4() after this.
2473 ****************************************************************************/
2474 static void cmd_queue(char *inbuf,char *outbuf )
2479 bzero(outbuf,smb_size);
2480 set_message(outbuf,2,0,True);
2482 CVAL(outbuf,smb_com) = SMBsplretq;
2483 SSVAL(outbuf,smb_tid,cnum);
2486 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2487 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2489 send_smb(Client,outbuf);
2490 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2492 if (CVAL(inbuf,smb_rcls) != 0)
2494 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2498 count = SVAL(inbuf,smb_vwv0);
2499 p = smb_buf(inbuf) + 3;
2502 DEBUG(0,("No entries in the print queue\n"));
2509 DEBUG(0,("Job Name Size Status\n"));
2515 case 0x01: sprintf(status,"held or stopped"); break;
2516 case 0x02: sprintf(status,"printing"); break;
2517 case 0x03: sprintf(status,"awaiting print"); break;
2518 case 0x04: sprintf(status,"in intercept"); break;
2519 case 0x05: sprintf(status,"file had error"); break;
2520 case 0x06: sprintf(status,"printer error"); break;
2521 default: sprintf(status,"unknown"); break;
2524 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2525 SVAL(p,5),p+12,IVAL(p,7),status));
2533 /****************************************************************************
2534 show information about a print queue
2535 ****************************************************************************/
2536 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2538 char *rparam = NULL;
2545 if (!connect_as_printer)
2547 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2548 DEBUG(0,("Trying to print without -P may fail\n"));
2551 bzero(param,sizeof(param));
2554 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2556 strcpy(p,"zWrLeh"); /* parameter description? */
2557 p = skip_string(p,1);
2558 strcpy(p,"WWzWWDDzz"); /* returned data format */
2559 p = skip_string(p,1);
2560 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2561 p = skip_string(p,1);
2562 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2563 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2565 strcpy(p,""); /* subformat */
2566 p = skip_string(p,1);
2568 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2569 if( call_api(PTR_DIFF(p,param), 0,
2576 result_code = SVAL(rparam,0);
2577 converter = SVAL(rparam,2); /* conversion factor */
2579 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2581 if (result_code == 0) /* if no error, */
2591 char PrinterName[20];
2593 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2594 strlower(PrinterName); /* in lower case */
2596 p = rdata; /* received data */
2597 for( i = 0; i < SVAL(rparam,4); ++i)
2600 Priority = SVAL(p,2);
2601 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2603 Priority = SVAL(p,2);
2604 JobTime = make_unix_date3( p + 12);
2605 JobTimeStr = asctime(LocalTime( &JobTime));
2607 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2610 printf("%s-%u %s priority %u %s %s %u bytes\n",
2611 PrinterName, JobId, UserName,
2612 Priority, JobTimeStr, JobName, Size);
2614 #if 0 /* DEBUG code */
2615 printf("Job Id: \"%u\"\n", SVAL(p,0));
2616 printf("Priority: \"%u\"\n", SVAL(p,2));
2618 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2619 printf("Position: \"%u\"\n", SVAL(p,8));
2620 printf("Status: \"%u\"\n", SVAL(p,10));
2622 JobTime = make_unix_date3( p + 12);
2623 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2624 printf("date: \"%u\"\n", SVAL(p,12));
2626 printf("Size: \"%u\"\n", SVAL(p,16));
2627 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2628 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2629 #endif /* DEBUG CODE */
2634 else /* call_api() failed */
2636 printf("Failed, error = %d\n", result_code);
2639 /* If any parameters or data were returned, free the storage. */
2640 if(rparam) free(rparam);
2641 if(rdata) free(rdata);
2646 /****************************************************************************
2647 show information about a print queue
2648 ****************************************************************************/
2649 static void cmd_qinfo(char *inbuf,char *outbuf )
2651 char *rparam = NULL;
2658 bzero(param,sizeof(param));
2661 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2663 strcpy(p,"zWrLh"); /* parameter description? */
2664 p = skip_string(p,1);
2665 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2666 p = skip_string(p,1);
2667 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2668 p = skip_string(p,1);
2669 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2670 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2672 strcpy(p,""); /* subformat */
2673 p = skip_string(p,1);
2675 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2676 if( call_api(PTR_DIFF(p,param), 0,
2683 result_code = SVAL(rparam,0);
2684 converter = SVAL(rparam,2); /* conversion factor */
2686 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2688 if (result_code == 0) /* if no error, */
2690 p = rdata; /* received data */
2692 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2693 printf("Priority: %u\n", SVAL(p,4) );
2694 printf("Start time: %u\n", SVAL(p,6) );
2695 printf("Until time: %u\n", SVAL(p,8) );
2696 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2697 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2698 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2699 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2700 printf("Status: %u\n", SVAL(p,28) );
2701 printf("Jobs: %u\n", SVAL(p,30) );
2702 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2703 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2705 /* Dump the driver data */
2710 ddptr = rdata + SVAL(p,40) - converter;
2711 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2712 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2714 for(x=8; x < count; x+=16)
2716 for(y=0; y < 16; y++)
2719 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2723 for(y=0; y < 16 && (x+y) < count; y++)
2725 c = CVAL(ddptr,(x+y));
2731 fputc('\n', stdout);
2737 else /* call_api() failed */
2739 printf("Failed, error = %d\n", result_code);
2742 /* If any parameters or data were returned, free the storage. */
2743 if(rparam) free(rparam);
2744 if(rdata) free(rdata);
2749 /****************************************************************************
2751 ****************************************************************************/
2752 static void do_del(file_info *finfo)
2755 char *inbuf,*outbuf;
2758 strcpy(mask,cur_dir);
2759 strcat(mask,finfo->name);
2761 if (finfo->mode & aDIR)
2764 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2765 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2767 if (!inbuf || !outbuf)
2769 DEBUG(0,("out of memory\n"));
2773 bzero(outbuf,smb_size);
2774 set_message(outbuf,1,2 + strlen(mask),True);
2776 CVAL(outbuf,smb_com) = SMBunlink;
2777 SSVAL(outbuf,smb_tid,cnum);
2780 SSVAL(outbuf,smb_vwv0,0);
2782 p = smb_buf(outbuf);
2786 send_smb(Client,outbuf);
2787 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2789 if (CVAL(inbuf,smb_rcls) != 0)
2790 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2792 free(inbuf);free(outbuf);
2796 /****************************************************************************
2798 ****************************************************************************/
2799 static void cmd_del(char *inbuf,char *outbuf )
2803 int attribute = aSYSTEM | aHIDDEN;
2808 strcpy(mask,cur_dir);
2810 if (!next_token(NULL,buf,NULL))
2812 DEBUG(0,("del <filename>\n"));
2817 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2821 /****************************************************************************
2823 ****************************************************************************/
2824 static void cmd_rmdir(char *inbuf,char *outbuf )
2830 strcpy(mask,cur_dir);
2832 if (!next_token(NULL,buf,NULL))
2834 DEBUG(0,("rmdir <dirname>\n"));
2839 bzero(outbuf,smb_size);
2840 set_message(outbuf,0,2 + strlen(mask),True);
2842 CVAL(outbuf,smb_com) = SMBrmdir;
2843 SSVAL(outbuf,smb_tid,cnum);
2847 p = smb_buf(outbuf);
2851 send_smb(Client,outbuf);
2852 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2854 if (CVAL(inbuf,smb_rcls) != 0)
2856 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2862 /****************************************************************************
2864 ****************************************************************************/
2865 static void cmd_rename(char *inbuf,char *outbuf )
2871 strcpy(src,cur_dir);
2872 strcpy(dest,cur_dir);
2874 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2876 DEBUG(0,("rename <src> <dest>\n"));
2882 bzero(outbuf,smb_size);
2883 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2885 CVAL(outbuf,smb_com) = SMBmv;
2886 SSVAL(outbuf,smb_tid,cnum);
2887 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2890 p = smb_buf(outbuf);
2893 p = skip_string(p,1);
2897 send_smb(Client,outbuf);
2898 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2900 if (CVAL(inbuf,smb_rcls) != 0)
2902 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2909 /****************************************************************************
2910 toggle the prompt flag
2911 ****************************************************************************/
2912 static void cmd_prompt(void)
2915 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2919 /****************************************************************************
2920 set the newer than time
2921 ****************************************************************************/
2922 static void cmd_newer(void)
2928 ok = next_token(NULL,buf,NULL);
2929 if (ok && (sys_stat(buf,&sbuf) == 0))
2931 newer_than = sbuf.st_mtime;
2932 DEBUG(1,("Getting files newer than %s",
2933 asctime(LocalTime(&newer_than))));
2938 if (ok && newer_than == 0)
2939 DEBUG(0,("Error setting newer-than time\n"));
2942 /****************************************************************************
2943 set the archive level
2944 ****************************************************************************/
2945 static void cmd_archive(void)
2949 if (next_token(NULL,buf,NULL)) {
2950 archive_level = atoi(buf);
2952 DEBUG(0,("Archive level is %d\n",archive_level));
2955 /****************************************************************************
2956 toggle the lowercaseflag
2957 ****************************************************************************/
2958 static void cmd_lowercase(void)
2960 lowercase = !lowercase;
2961 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2967 /****************************************************************************
2968 toggle the recurse flag
2969 ****************************************************************************/
2970 static void cmd_recurse(void)
2973 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2976 /****************************************************************************
2977 toggle the translate flag
2978 ****************************************************************************/
2979 static void cmd_translate(void)
2981 translation = !translation;
2982 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2983 translation?"on":"off"));
2987 /****************************************************************************
2988 do a printmode command
2989 ****************************************************************************/
2990 static void cmd_printmode(void)
2995 if (next_token(NULL,buf,NULL))
2997 if (strequal(buf,"text"))
3001 if (strequal(buf,"graphics"))
3004 printmode = atoi(buf);
3011 strcpy(mode,"text");
3014 strcpy(mode,"graphics");
3017 sprintf(mode,"%d",printmode);
3021 DEBUG(2,("the printmode is now %s\n",mode));
3024 /****************************************************************************
3026 ****************************************************************************/
3027 static void cmd_lcd(void)
3032 if (next_token(NULL,buf,NULL))
3034 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
3038 /****************************************************************************
3039 send a session request
3040 ****************************************************************************/
3041 static BOOL send_session_request(char *inbuf,char *outbuf)
3046 /* send a session request (RFC 8002) */
3048 strcpy(dest,desthost);
3049 p = strchr(dest,'.');
3052 /* put in the destination name */
3054 name_mangle(dest,p,name_type); /* 0x20 is the SMB server NetBIOS type. */
3059 name_mangle(myname,p,0);
3062 /* setup the packet length */
3063 _smb_setlen(outbuf,len);
3064 CVAL(outbuf,0) = 0x81;
3066 send_smb(Client,outbuf);
3067 DEBUG(5,("Sent session request\n"));
3069 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3071 if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */
3073 /* For information, here is the response structure.
3074 * We do the byte-twiddling to for portability.
3075 struct RetargetResponse{
3077 unsigned char flags;
3084 int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
3085 /* SESSION RETARGET */
3086 putip((char *)&dest_ip,inbuf+4);
3089 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
3093 DEBUG(3,("Retargeted\n"));
3095 set_socket_options(Client,user_socket_options);
3098 return send_session_request(inbuf,outbuf);
3099 } /* C. Hoch 9/14/95 End */
3102 if (CVAL(inbuf,0) != 0x82)
3104 int ecode = CVAL(inbuf,4);
3105 DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
3106 CVAL(inbuf,0),ecode,myname,desthost));
3110 DEBUG(0,("Not listening on called name\n"));
3111 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
3112 DEBUG(0,("You may find the -I option useful for this\n"));
3115 DEBUG(0,("Not listening for calling name\n"));
3116 DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
3117 DEBUG(0,("You may find the -n option useful for this\n"));
3120 DEBUG(0,("Called name not present\n"));
3121 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
3122 DEBUG(0,("You may find the -I option useful for this\n"));
3125 DEBUG(0,("Called name present, but insufficient resources\n"));
3126 DEBUG(0,("Perhaps you should try again later?\n"));
3129 DEBUG(0,("Unspecified error 0x%X\n",ecode));
3130 DEBUG(0,("Your server software is being unfriendly\n"));
3142 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
3143 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
3144 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
3145 {PROTOCOL_LANMAN1,"LANMAN1.0"},
3146 {PROTOCOL_LANMAN2,"LM1.2X002"},
3147 {PROTOCOL_LANMAN2,"Samba"},
3148 {PROTOCOL_NT1,"NT LM 0.12"},
3149 {PROTOCOL_NT1,"NT LANMAN 1.0"},
3154 /****************************************************************************
3155 send a login command
3156 ****************************************************************************/
3157 static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
3159 BOOL was_null = (!inbuf && !outbuf);
3161 time_t servertime = 0;
3162 extern int serverzone;
3174 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3175 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3179 if (strstr(service,"IPC$")) connect_as_ipc = True;
3183 if (connect_as_printer)
3184 strcpy(dev,"LPT1:");
3189 if (start_session && !send_session_request(inbuf,outbuf))
3199 bzero(outbuf,smb_size);
3201 /* setup the protocol strings */
3205 for (plength=0,numprots=0;
3206 prots[numprots].name && prots[numprots].prot<=max_protocol;
3208 plength += strlen(prots[numprots].name)+2;
3210 set_message(outbuf,0,plength,True);
3212 p = smb_buf(outbuf);
3214 prots[numprots].name && prots[numprots].prot<=max_protocol;
3218 strcpy(p,prots[numprots].name);
3223 CVAL(outbuf,smb_com) = SMBnegprot;
3226 CVAL(smb_buf(outbuf),0) = 2;
3228 send_smb(Client,outbuf);
3229 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3233 if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
3235 DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
3236 myname,desthost,smb_errstr(inbuf)));
3245 Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
3248 if (Protocol < PROTOCOL_NT1) {
3249 sec_mode = SVAL(inbuf,smb_vwv1);
3250 max_xmit = SVAL(inbuf,smb_vwv2);
3251 sesskey = IVAL(inbuf,smb_vwv6);
3252 serverzone = SVALS(inbuf,smb_vwv10)*60;
3253 /* this time is converted to GMT by make_unix_date */
3254 servertime = make_unix_date(inbuf+smb_vwv8);
3255 if (Protocol >= PROTOCOL_COREPLUS) {
3256 readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
3257 writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
3259 crypt_len = smb_buflen(inbuf);
3260 memcpy(cryptkey,smb_buf(inbuf),8);
3261 DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
3262 max_vcs = SVAL(inbuf,smb_vwv4);
3263 DEBUG(3,("max vcs %d\n",max_vcs));
3264 DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
3267 sec_mode = CVAL(inbuf,smb_vwv1);
3268 max_xmit = IVAL(inbuf,smb_vwv3+1);
3269 sesskey = IVAL(inbuf,smb_vwv7+1);
3270 serverzone = SVALS(inbuf,smb_vwv15+1)*60;
3271 /* this time arrives in real GMT */
3272 servertime = interpret_long_date(inbuf+smb_vwv11+1);
3273 crypt_len = CVAL(inbuf,smb_vwv16+1);
3274 memcpy(cryptkey,smb_buf(inbuf),8);
3275 if (IVAL(inbuf,smb_vwv9+1) & 1)
3276 readbraw_supported = writebraw_supported = True;
3277 DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
3278 max_vcs = SVAL(inbuf,smb_vwv2+1);
3279 DEBUG(3,("max vcs %d\n",max_vcs));
3280 DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
3281 DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
3284 DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
3285 DEBUG(3,("max xmt %d\n",max_xmit));
3286 DEBUG(3,("Got %d byte crypt key\n",crypt_len));
3287 DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
3289 doencrypt = ((sec_mode & 2) != 0);
3292 static BOOL done_time = False;
3294 DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
3295 asctime(LocalTime(&servertime)),
3296 -(double)(serverzone/3600.0)));
3306 pass = (char *)getpass("Password: ");
3308 /* use a blank username for the 2nd try with a blank password */
3309 if (tries++ && !*pass)
3312 if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
3315 int passlen = strlen(pass)+1;
3318 if (doencrypt && *pass) {
3319 DEBUG(3,("Using encrypted passwords\n"));
3321 SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
3324 /* if in share level security then don't send a password now */
3325 if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;}
3327 /* send a session setup command */
3328 bzero(outbuf,smb_size);
3330 if (Protocol < PROTOCOL_NT1) {
3331 set_message(outbuf,10,1 + strlen(username) + passlen,True);
3332 CVAL(outbuf,smb_com) = SMBsesssetupX;
3335 CVAL(outbuf,smb_vwv0) = 0xFF;
3336 SSVAL(outbuf,smb_vwv2,max_xmit);
3337 SSVAL(outbuf,smb_vwv3,2);
3338 SSVAL(outbuf,smb_vwv4,max_vcs-1);
3339 SIVAL(outbuf,smb_vwv5,sesskey);
3340 SSVAL(outbuf,smb_vwv7,passlen);
3341 p = smb_buf(outbuf);
3342 memcpy(p,pword,passlen);
3346 if (!doencrypt) passlen--;
3348 set_message(outbuf,13,0,True);
3349 CVAL(outbuf,smb_com) = SMBsesssetupX;
3352 CVAL(outbuf,smb_vwv0) = 0xFF;
3353 SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
3354 SSVAL(outbuf,smb_vwv3,2);
3355 SSVAL(outbuf,smb_vwv4,getpid());
3356 SIVAL(outbuf,smb_vwv5,sesskey);
3357 SSVAL(outbuf,smb_vwv7,passlen);
3358 SSVAL(outbuf,smb_vwv8,0);
3359 p = smb_buf(outbuf);
3360 memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
3361 strcpy(p,username);p = skip_string(p,1);
3362 strcpy(p,workgroup);p = skip_string(p,1);
3363 strcpy(p,"Unix");p = skip_string(p,1);
3364 strcpy(p,"Samba");p = skip_string(p,1);
3365 set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
3368 send_smb(Client,outbuf);
3369 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3373 if (CVAL(inbuf,smb_rcls) != 0)
3376 ((CVAL(inbuf,smb_rcls) == ERRDOS &&
3377 SVAL(inbuf,smb_err) == ERRnoaccess) ||
3378 (CVAL(inbuf,smb_rcls) == ERRSRV &&
3379 SVAL(inbuf,smb_err) == ERRbadpw)))
3382 DEBUG(3,("resending login\n"));
3386 DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n",
3387 username,myname,desthost,smb_errstr(inbuf)));
3388 DEBUG(0,("You might find the -U, -W or -n options useful\n"));
3389 DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
3390 DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
3399 if (Protocol >= PROTOCOL_NT1) {
3400 char *domain,*os,*lanman;
3403 lanman = skip_string(os,1);
3404 domain = skip_string(lanman,1);
3405 if (*domain || *os || *lanman)
3406 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
3409 /* use the returned uid from now on */
3410 if (SVAL(inbuf,smb_uid) != uid)
3411 DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
3412 SVAL(inbuf,smb_uid),uid));
3413 uid = SVAL(inbuf,smb_uid);
3416 if (SVAL(inbuf, smb_vwv2) & 1)
3417 DEBUG(1,("connected as guest "));
3419 DEBUG(1,("security=user\n"));
3421 DEBUG(1,("security=share\n"));
3423 /* now we've got a connection - send a tcon message */
3424 bzero(outbuf,smb_size);
3426 if (strncmp(service,"\\\\",2) != 0)
3428 DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
3429 DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
3436 int passlen = strlen(pass)+1;
3440 if (doencrypt && *pass) {
3442 SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
3445 /* if in user level security then don't send a password now */
3446 if ((sec_mode & 1)) {
3447 strcpy(pword, ""); passlen=1;
3450 if (Protocol <= PROTOCOL_COREPLUS) {
3451 set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
3452 CVAL(outbuf,smb_com) = SMBtcon;
3455 p = smb_buf(outbuf);
3458 p = skip_string(p,1);
3460 memcpy(p,pword,passlen);
3466 set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
3467 CVAL(outbuf,smb_com) = SMBtconX;
3470 SSVAL(outbuf,smb_vwv0,0xFF);
3471 SSVAL(outbuf,smb_vwv3,passlen);
3473 p = smb_buf(outbuf);
3474 memcpy(p,pword,passlen);
3477 p = skip_string(p,1);
3482 send_smb(Client,outbuf);
3483 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3485 /* trying again with a blank password */
3486 if (CVAL(inbuf,smb_rcls) != 0 &&
3487 (int)strlen(pass) > 0 &&
3489 Protocol >= PROTOCOL_LANMAN1)
3491 DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
3496 if (CVAL(inbuf,smb_rcls) != 0)
3498 DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
3499 DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
3500 DEBUG(0,("Some servers insist that these be in uppercase\n"));
3510 if (Protocol <= PROTOCOL_COREPLUS) {
3511 max_xmit = SVAL(inbuf,smb_vwv0);
3513 cnum = SVAL(inbuf,smb_vwv1);
3516 max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
3518 max_xmit = BUFFER_SIZE - 4;
3520 cnum = SVAL(inbuf,smb_tid);
3523 DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
3535 /****************************************************************************
3536 send a logout command
3537 ****************************************************************************/
3538 static void send_logout(void )
3540 pstring inbuf,outbuf;
3542 bzero(outbuf,smb_size);
3543 set_message(outbuf,0,0,True);
3544 CVAL(outbuf,smb_com) = SMBtdis;
3545 SSVAL(outbuf,smb_tid,cnum);
3548 send_smb(Client,outbuf);
3549 receive_smb(Client,inbuf,SHORT_TIMEOUT);
3551 if (CVAL(inbuf,smb_rcls) != 0)
3553 DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
3565 /****************************************************************************
3567 ****************************************************************************/
3568 static BOOL call_api(int prcnt,int drcnt,
3569 int mprcnt,int mdrcnt,
3570 int *rprcnt,int *rdrcnt,
3571 char *param,char *data,
3572 char **rparam,char **rdata)
3574 static char *inbuf=NULL;
3575 static char *outbuf=NULL;
3577 if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3578 if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3580 send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
3585 return (receive_trans_response(inbuf,SMBtrans,
3590 /****************************************************************************
3591 send a SMB trans or trans2 request
3592 ****************************************************************************/
3593 static BOOL send_trans_request(char *outbuf,int trans,
3594 char *name,int fid,int flags,
3595 char *data,char *param,uint16 *setup,
3596 int ldata,int lparam,int lsetup,
3597 int mdata,int mparam,int msetup)
3600 int this_ldata,this_lparam;
3601 int tot_data=0,tot_param=0;
3602 char *outdata,*outparam;
3606 this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
3607 this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
3609 bzero(outbuf,smb_size);
3610 set_message(outbuf,14+lsetup,0,True);
3611 CVAL(outbuf,smb_com) = trans;
3612 SSVAL(outbuf,smb_tid,cnum);
3615 outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
3616 outdata = outparam+this_lparam;
3618 /* primary request */
3619 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3620 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3621 SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */
3622 SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */
3623 SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */
3624 SSVAL(outbuf,smb_flags,flags); /* flags */
3625 SIVAL(outbuf,smb_timeout,0); /* timeout */
3626 SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
3627 SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
3628 SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */
3629 SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
3630 SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */
3631 for (i=0;i<lsetup;i++) /* setup[] */
3632 SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
3633 p = smb_buf(outbuf);
3634 if (trans==SMBtrans)
3635 strcpy(p,name); /* name[] */
3638 *p++ = 0; /* put in a null smb_name */
3639 *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */
3641 if (this_lparam) /* param[] */
3642 memcpy(outparam,param,this_lparam);
3643 if (this_ldata) /* data[] */
3644 memcpy(outdata,data,this_ldata);
3645 set_message(outbuf,14+lsetup, /* wcnt, bcc */
3646 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3649 send_smb(Client,outbuf);
3651 if (this_ldata < ldata || this_lparam < lparam)
3653 /* receive interim response */
3654 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
3656 DEBUG(0,("%s request failed (%s)\n",
3657 trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
3661 tot_data = this_ldata;
3662 tot_param = this_lparam;
3664 while (tot_data < ldata || tot_param < lparam)
3666 this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
3667 this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
3669 set_message(outbuf,trans==SMBtrans?8:9,0,True);
3670 CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
3672 outparam = smb_buf(outbuf);
3673 outdata = outparam+this_lparam;
3675 /* secondary request */
3676 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3677 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3678 SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
3679 SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
3680 SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */
3681 SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */
3682 SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
3683 SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */
3684 if (trans==SMBtrans2)
3685 SSVAL(outbuf,smb_sfid,fid); /* fid */
3686 if (this_lparam) /* param[] */
3687 memcpy(outparam,param,this_lparam);
3688 if (this_ldata) /* data[] */
3689 memcpy(outdata,data,this_ldata);
3690 set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
3691 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3694 send_smb(Client,outbuf);
3696 tot_data += this_ldata;
3697 tot_param += this_lparam;
3705 /****************************************************************************
3706 try and browse available connections on a host
3707 ****************************************************************************/
3708 static BOOL browse_host(BOOL sort)
3711 /* If strcasecmp is already defined, remove it. */
3714 #endif /* strcasecmp */
3715 #define strcasecmp StrCaseCmp
3716 #endif /* NOSTRCASECMP */
3718 extern int strcasecmp();
3720 char *rparam = NULL;
3727 /* now send a SMBtrans command with api RNetShareEnum */
3729 SSVAL(p,0,0); /* api number */
3732 p = skip_string(p,1);
3734 p = skip_string(p,1);
3736 SSVAL(p,2,BUFFER_SIZE);
3739 if (call_api(PTR_DIFF(p,param),0,
3745 int res = SVAL(rparam,0);
3746 int converter=SVAL(rparam,2);
3748 BOOL long_share_name=False;
3752 count=SVAL(rparam,4);
3757 printf("\n\tSharename Type Comment\n");
3758 printf("\t--------- ---- -------\n");
3762 qsort(p,count,20,QSORT_CAST strcasecmp);
3764 for (i=0;i<count;i++)
3767 int type = SVAL(p,14);
3768 int comment_offset = IVAL(p,16) & 0xFFFF;
3774 case STYPE_DISKTREE:
3775 strcpy(typestr,"Disk"); break;
3777 strcpy(typestr,"Printer"); break;
3779 strcpy(typestr,"Device"); break;
3781 strcpy(typestr,"IPC"); break;
3784 printf("\t%-15.15s%-10.10s%s\n",
3787 comment_offset?rdata+comment_offset-converter:"");
3789 if (strlen(sname)>8) long_share_name=True;
3794 if (long_share_name) {
3795 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3800 if (rparam) free(rparam);
3801 if (rdata) free(rdata);
3807 /****************************************************************************
3808 get some server info
3809 ****************************************************************************/
3810 static void server_info()
3812 char *rparam = NULL;
3818 bzero(param,sizeof(param));
3821 SSVAL(p,0,63); /* NetServerGetInfo()? */
3824 p = skip_string(p,1);
3825 strcpy(p,"zzzBBzz");
3826 p = skip_string(p,1);
3827 SSVAL(p,0,10); /* level 10 */
3831 if (call_api(PTR_DIFF(p,param),0,
3837 int res = SVAL(rparam,0);
3838 int converter=SVAL(rparam,2);
3844 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3845 rdata+SVAL(p,0)-converter,
3846 rdata+SVAL(p,4)-converter,
3847 rdata+SVAL(p,8)-converter,
3848 rdata+SVAL(p,14)-converter);
3852 if (rparam) free(rparam);
3853 if (rdata) free(rdata);
3859 /****************************************************************************
3860 try and browse available connections on a host
3861 ****************************************************************************/
3862 static BOOL list_servers(char *wk_grp)
3864 char *rparam = NULL;
3872 BOOL generic_request = False;
3875 if (strequal(wk_grp,"WORKGROUP")) {
3876 /* we won't specify a workgroup */
3877 generic_request = True;
3880 /* now send a SMBtrans command with api ServerEnum? */
3882 SSVAL(p,0,0x68); /* api number */
3885 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3886 p = skip_string(p,1);
3888 strcpy(p,"B16BBDz");
3890 p = skip_string(p,1);
3892 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3898 if (!generic_request) {
3900 p = skip_string(p,1);
3903 /* first ask for a list of servers in this workgroup */
3904 SIVAL(svtype_p,0,SV_TYPE_ALL);
3906 if (call_api(PTR_DIFF(p+4,param),0,
3907 8,BUFFER_SIZE - SAFETY_MARGIN,
3912 int res = SVAL(rparam,0);
3913 int converter=SVAL(rparam,2);
3918 count=SVAL(rparam,4);
3921 printf("\n\nThis machine has a browse list:\n");
3922 printf("\n\tServer Comment\n");
3923 printf("\t--------- -------\n");
3926 for (i=0;i<count;i++) {
3928 int comment_offset = IVAL(p2,22) & 0xFFFF;
3929 printf("\t%-16.16s %s\n",
3931 comment_offset?rdata+comment_offset-converter:"");
3939 if (rparam) {free(rparam); rparam = NULL;}
3940 if (rdata) {free(rdata); rdata = NULL;}
3942 /* now ask for a list of workgroups */
3943 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3945 if (call_api(PTR_DIFF(p+4,param),0,
3946 8,BUFFER_SIZE - SAFETY_MARGIN,
3951 int res = SVAL(rparam,0);
3952 int converter=SVAL(rparam,2);
3957 count=SVAL(rparam,4);
3960 printf("\n\nThis machine has a workgroup list:\n");
3961 printf("\n\tWorkgroup Master\n");
3962 printf("\t--------- -------\n");
3965 for (i=0;i<count;i++) {
3967 int comment_offset = IVAL(p2,22) & 0xFFFF;
3968 printf("\t%-16.16s %s\n",
3970 comment_offset?rdata+comment_offset-converter:"");
3978 if (rparam) free(rparam);
3979 if (rdata) free(rdata);
3985 /* This defines the commands supported by this client */
3993 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3994 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3995 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3996 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3997 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3998 {"get",cmd_get,"<remote name> [local name] get a file"},
3999 {"mget",cmd_mget,"<mask> get all the matching files"},
4000 {"put",cmd_put,"<local name> [remote name] put a file"},
4001 {"mput",cmd_mput,"<mask> put all matching files"},
4002 {"rename",cmd_rename,"<src> <dest> rename some files"},
4003 {"more",cmd_more,"<remote name> view a remote file with your pager"},
4004 {"mask",cmd_select,"<mask> mask all filenames against this"},
4005 {"del",cmd_del,"<mask> delete all matching files"},
4006 {"rm",cmd_del,"<mask> delete all matching files"},
4007 {"mkdir",cmd_mkdir,"<directory> make a directory"},
4008 {"md",cmd_mkdir,"<directory> make a directory"},
4009 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
4010 {"rd",cmd_rmdir,"<directory> remove a directory"},
4011 {"pq",cmd_p_queue_4,"enumerate the print queue"},
4012 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
4013 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
4014 {"translate",cmd_translate,"toggle text translation for printing"},
4015 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
4016 {"print",cmd_print,"<file name> print a file"},
4017 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
4018 {"queue",cmd_queue,"show the print queue"},
4019 {"qinfo",cmd_qinfo,"show print queue information"},
4020 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
4021 {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
4022 {"quit",send_logout,"logoff the server"},
4023 {"q",send_logout,"logoff the server"},
4024 {"exit",send_logout,"logoff the server"},
4025 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
4026 {"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"},
4027 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
4028 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
4029 {"tarmode",cmd_tarmode,
4030 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
4031 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
4032 {"help",cmd_help,"[command] give help on a command"},
4033 {"?",cmd_help,"[command] give help on a command"},
4034 {"!",NULL,"run a shell command on the local system"},
4039 /*******************************************************************
4040 lookup a command string in the list of commands, including
4042 ******************************************************************/
4043 static int process_tok(fstring tok)
4045 int i = 0, matches = 0;
4047 int tok_len = strlen(tok);
4049 while (commands[i].fn != NULL)
4051 if (strequal(commands[i].name,tok))
4057 else if (strnequal(commands[i].name, tok, tok_len+1))
4067 else if (matches == 1)
4073 /****************************************************************************
4075 ****************************************************************************/
4081 if (next_token(NULL,buf,NULL))
4083 if ((i = process_tok(buf)) >= 0)
4084 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
4087 while (commands[i].description)
4089 for (j=0; commands[i].description && (j<5); j++) {
4090 DEBUG(0,("%-15s",commands[i].name));
4097 /****************************************************************************
4098 open the client sockets
4099 ****************************************************************************/
4100 static BOOL open_sockets(int port )
4102 static int last_port;
4110 if (port == 0) port=last_port;
4121 strcpy(service2,service);
4122 host = strtok(service2,"\\/");
4124 DEBUG(0,("Badly formed host name\n"));
4127 strcpy(desthost,host);
4131 get_myname(myname,NULL);
4135 DEBUG(3,("Opening sockets\n"));
4141 if ((hp = Get_Hostbyname(host))) {
4142 putip((char *)&dest_ip,(char *)hp->h_addr);
4146 /* Try and resolve the name with the netbios server */
4149 if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
4150 interpret_addr(lp_socket_address()))) != -1) {
4151 set_socket_options(bcast, "SO_BROADCAST");
4153 if (name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
4161 DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
4167 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
4171 DEBUG(3,("Connected\n"));
4173 set_socket_options(Client,user_socket_options);
4178 /****************************************************************************
4179 wait for keyboard activity, swallowing network packets
4180 ****************************************************************************/
4182 static char wait_keyboard(char *buffer)
4184 static void wait_keyboard(char *buffer)
4189 struct timeval timeout;
4199 FD_SET(Client,&fds);
4201 FD_SET(fileno(stdin),&fds);
4204 timeout.tv_sec = 20;
4205 timeout.tv_usec = 0;
4209 selrtn = sys_select(&fds,&timeout);
4212 if (FD_ISSET(fileno(stdin),&fds))
4219 set_blocking(fileno(stdin), False);
4220 readret = read_data( fileno(stdin), &ch, 1);
4221 set_blocking(fileno(stdin), True);
4224 if (errno != EAGAIN)
4226 /* should crash here */
4227 DEBUG(1,("readchar stdin failed\n"));
4230 else if (readret != 0)
4236 if (FD_ISSET(Client,&fds))
4237 receive_smb(Client,buffer,0);
4244 chkpath("\\",False);
4247 chkpath("\\",False);
4253 /****************************************************************************
4254 close and open the connection again
4255 ****************************************************************************/
4256 BOOL reopen_connection(char *inbuf,char *outbuf)
4258 static int open_count=0;
4262 if (open_count>5) return(False);
4264 DEBUG(1,("Trying to re-open connection\n"));
4266 set_message(outbuf,0,0,True);
4267 SCVAL(outbuf,smb_com,SMBtdis);
4268 SSVAL(outbuf,smb_tid,cnum);
4271 send_smb(Client,outbuf);
4272 receive_smb(Client,inbuf,SHORT_TIMEOUT);
4275 if (!open_sockets(0)) return(False);
4277 return(send_login(inbuf,outbuf,True,True));
4280 /****************************************************************************
4281 process commands from the client
4282 ****************************************************************************/
4283 static BOOL process(char *base_directory)
4289 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4290 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4292 if ((InBuffer == NULL) || (OutBuffer == NULL))
4295 bzero(OutBuffer,smb_size);
4297 if (!send_login(InBuffer,OutBuffer,True,True))
4300 if (*base_directory) do_cd(base_directory);
4303 if (cmd[0] != '\0') while (cmd[0] != '\0')
4309 if ((p = strchr(cmd, ';')) == 0)
4311 strncpy(line, cmd, 999);
4317 if (p - cmd > 999) p = cmd + 999;
4318 strncpy(line, cmd, p - cmd);
4319 line[p - cmd] = '\0';
4323 /* input language code to internal one */
4326 /* and get the first part of the command */
4329 if (!next_token(&ptr,tok,NULL)) continue;
4332 if ((i = process_tok(tok)) >= 0)
4333 commands[i].fn(InBuffer,OutBuffer);
4335 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4337 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4339 else while (!feof(stdin))
4344 bzero(OutBuffer,smb_size);
4346 /* display a prompt */
4347 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
4351 line[0] = wait_keyboard(InBuffer);
4352 /* this might not be such a good idea... */
4353 if ( line[0] == EOF)
4356 wait_keyboard(InBuffer);
4359 /* and get a response */
4361 fgets( &line[1],999, stdin);
4363 if (!fgets(line,1000,stdin))
4367 /* input language code to internal one */
4370 /* special case - first char is ! */
4377 /* and get the first part of the command */
4380 if (!next_token(&ptr,tok,NULL)) continue;
4383 if ((i = process_tok(tok)) >= 0)
4384 commands[i].fn(InBuffer,OutBuffer);
4386 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4388 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4396 /****************************************************************************
4397 usage on the program
4398 ****************************************************************************/
4399 static void usage(char *pname)
4401 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
4404 DEBUG(0,("\nVersion %s\n",VERSION));
4405 DEBUG(0,("\t-p port listen on the specified port\n"));
4406 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
4407 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
4408 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
4409 DEBUG(0,("\t-N don't ask for a password\n"));
4410 DEBUG(0,("\t-P connect to service as a printer\n"));
4411 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
4412 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
4413 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
4414 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
4415 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
4416 DEBUG(0,("\t-U username set the network username\n"));
4417 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
4418 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
4419 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
4420 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
4421 DEBUG(0,("\t-D directory start from directory\n"));
4425 /****************************************************************************
4427 ****************************************************************************/
4428 int main(int argc,char *argv[])
4430 fstring base_directory;
4431 char *pname = argv[0];
4432 int port = SMB_PORT;
4435 extern char *optarg;
4438 BOOL message = False;
4439 extern char tar_type;
4440 static pstring servicesf = CONFIGFILE;
4445 strcpy(term_code, KANJI);
4451 *base_directory = 0;
4455 setup_logging(pname,True);
4458 charset_initialise();
4469 strcpy(username,getenv("USER"));
4471 /* modification to support userid%passwd syntax in the USER var
4472 25.Aug.97, jdblair@uab.edu */
4474 if ((p=strchr(username,'%')))
4477 strcpy(password,p+1);
4479 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
4484 /* modification to support PASSWD environmental var
4485 25.Aug.97, jdblair@uab.edu */
4487 if (getenv("PASSWD"))
4488 strcpy(password,getenv("PASSWD"));
4490 if (*username == 0 && getenv("LOGNAME"))
4492 strcpy(username,getenv("LOGNAME"));
4502 if (*argv[1] != '-')
4505 strcpy(service,argv[1]);
4506 /* Convert any '/' characters in the service name to '\' characters */
4507 string_replace( service, '/','\\');
4511 if (count_chars(service,'\\') < 3)
4514 printf("\n%s: Not enough '\\' characters in service\n",service);
4519 if (count_chars(service,'\\') > 3)
4522 printf("\n%s: Too many '\\' characters in service\n",service);
4527 if (argc > 1 && (*argv[1] != '-'))
4530 strcpy(password,argv[1]);
4531 memset(argv[1],'X',strlen(argv[1]));
4538 getopt(argc, argv,"s:B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
4542 max_protocol = interpret_protocol(optarg,max_protocol);
4545 strcpy(user_socket_options,optarg);
4548 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
4549 strcpy(desthost,optarg);
4554 iface_set_default(NULL,optarg,NULL);
4557 strcpy(base_directory,optarg);
4560 if (!tar_parseargs(argc, argv, optarg, optind)) {
4566 strcpy(scope,optarg);
4570 strcpy(query_host,optarg);
4575 strcpy(username,optarg);
4576 if ((lp=strchr(username,'%')))
4579 strcpy(password,lp+1);
4581 memset(strchr(optarg,'%')+1,'X',strlen(password));
4587 strcpy(workgroup,optarg);
4594 dest_ip = *interpret_addr2(optarg);
4595 if (zero_ip(dest_ip)) exit(1);
4600 strcpy(myname,optarg);
4606 connect_as_printer = True;
4612 DEBUGLEVEL = atoi(optarg);
4615 sprintf(debugf,"%s.client",optarg);
4618 port = atoi(optarg);
4629 strcpy(servicesf, optarg);
4632 strcpy(term_code, optarg);
4639 if (!tar_type && !*query_host && !*service && !message)
4646 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
4648 if(!get_myname(myhostname,NULL))
4650 DEBUG(0,("Failed to get my hostname.\n"));
4653 if (!lp_load(servicesf,True)) {
4654 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
4657 codepage_initialise(lp_client_code_page());
4659 if(lp_client_code_page() == KANJI_CODEPAGE)
4661 if (!setup_term_code (term_code))
4663 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
4669 if (*workgroup == 0)
4670 strcpy(workgroup,lp_workgroup());
4673 get_myname((*myname)?NULL:myname,NULL);
4679 if (open_sockets(port)) {
4680 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4681 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4684 if ((InBuffer == NULL) || (OutBuffer == NULL))
4687 bzero(OutBuffer,smb_size);
4688 if (!send_login(InBuffer,OutBuffer,True,True))
4691 if (*base_directory) do_cd(base_directory);
4693 ret=process_tar(InBuffer, OutBuffer);
4705 sprintf(service,"\\\\%s\\IPC$",query_host);
4707 connect_as_ipc = True;
4708 if (open_sockets(port))
4713 if (!send_login(NULL,NULL,True,True))
4717 if (!browse_host(True)) {
4721 if (!list_servers(workgroup)) {
4723 list_servers(workgroup);
4736 if (open_sockets(port))
4738 pstring inbuf,outbuf;
4739 bzero(outbuf,smb_size);
4740 if (!send_session_request(inbuf,outbuf))
4743 send_message(inbuf,outbuf);
4751 if (open_sockets(port))
4753 if (!process(base_directory))
4767 /* error code stuff - put together by Merik Karman
4768 merik@blackadder.dsh.oz.au */
4777 /* Dos Error Messages */
4778 err_code_struct dos_msgs[] = {
4779 {"ERRbadfunc",1,"Invalid function."},
4780 {"ERRbadfile",2,"File not found."},
4781 {"ERRbadpath",3,"Directory invalid."},
4782 {"ERRnofids",4,"No file descriptors available"},
4783 {"ERRnoaccess",5,"Access denied."},
4784 {"ERRbadfid",6,"Invalid file handle."},
4785 {"ERRbadmcb",7,"Memory control blocks destroyed."},
4786 {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
4787 {"ERRbadmem",9,"Invalid memory block address."},
4788 {"ERRbadenv",10,"Invalid environment."},
4789 {"ERRbadformat",11,"Invalid format."},
4790 {"ERRbadaccess",12,"Invalid open mode."},
4791 {"ERRbaddata",13,"Invalid data."},
4792 {"ERR",14,"reserved."},
4793 {"ERRbaddrive",15,"Invalid drive specified."},
4794 {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
4795 {"ERRdiffdevice",17,"Not same device."},
4796 {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
4797 {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
4798 {"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."},
4799 {"ERRnosuchshare", 67, "You specified an invalid share name"},
4800 {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
4801 {"ERRbadpipe",230,"Pipe invalid."},
4802 {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
4803 {"ERRpipeclosing",232,"Pipe close in progress."},
4804 {"ERRnotconnected",233,"No process on other end of pipe."},
4805 {"ERRmoredata",234,"There is more data to be returned."},
4806 {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
4809 /* Server Error Messages */
4810 err_code_struct server_msgs[] = {
4811 {"ERRerror",1,"Non-specific error code."},
4812 {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
4813 {"ERRbadtype",3,"reserved."},
4814 {"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."},
4815 {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
4816 {"ERRinvnetname",6,"Invalid network name in tree connect."},
4817 {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
4818 {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
4819 {"ERRqtoobig",50,"Print queue full -- no space."},
4820 {"ERRqeof",51,"EOF on print queue dump."},
4821 {"ERRinvpfid",52,"Invalid print file FID."},
4822 {"ERRsmbcmd",64,"The server did not recognize the command received."},
4823 {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
4824 {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
4825 {"ERRreserved",68,"reserved."},
4826 {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
4827 {"ERRreserved",70,"reserved."},
4828 {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
4829 {"ERRpaused",81,"Server is paused."},
4830 {"ERRmsgoff",82,"Not receiving messages."},
4831 {"ERRnoroom",83,"No room to buffer message."},
4832 {"ERRrmuns",87,"Too many remote user names."},
4833 {"ERRtimeout",88,"Operation timed out."},
4834 {"ERRnoresource",89,"No resources currently available for request."},
4835 {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
4836 {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
4837 {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
4838 {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
4839 {"ERRcontmpx",252,"Continue in MPX mode."},
4840 {"ERRreserved",253,"reserved."},
4841 {"ERRreserved",254,"reserved."},
4842 {"ERRnosupport",0xFFFF,"Function not supported."},
4845 /* Hard Error Messages */
4846 err_code_struct hard_msgs[] = {
4847 {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
4848 {"ERRbadunit",20,"Unknown unit."},
4849 {"ERRnotready",21,"Drive not ready."},
4850 {"ERRbadcmd",22,"Unknown command."},
4851 {"ERRdata",23,"Data error (CRC)."},
4852 {"ERRbadreq",24,"Bad request structure length."},
4853 {"ERRseek",25 ,"Seek error."},
4854 {"ERRbadmedia",26,"Unknown media type."},
4855 {"ERRbadsector",27,"Sector not found."},
4856 {"ERRnopaper",28,"Printer out of paper."},
4857 {"ERRwrite",29,"Write fault."},
4858 {"ERRread",30,"Read fault."},
4859 {"ERRgeneral",31,"General failure."},
4860 {"ERRbadshare",32,"An open conflicts with an existing open."},
4861 {"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."},
4862 {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
4863 {"ERRFCBUnavail",35,"No FCBs are available to process request."},
4864 {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
4872 err_code_struct *err_msgs;
4875 {0x01,"ERRDOS",dos_msgs},
4876 {0x02,"ERRSRV",server_msgs},
4877 {0x03,"ERRHRD",hard_msgs},
4878 {0x04,"ERRXOS",NULL},
4879 {0xE1,"ERRRMX1",NULL},
4880 {0xE2,"ERRRMX2",NULL},
4881 {0xE3,"ERRRMX3",NULL},
4882 {0xFF,"ERRCMD",NULL},
4886 /****************************************************************************
4887 return a SMB error string from a SMB buffer
4888 ****************************************************************************/
4889 char *smb_errstr(char *inbuf)
4892 int class = CVAL(inbuf,smb_rcls);
4893 int num = SVAL(inbuf,smb_err);
4896 for (i=0;err_classes[i].class;i++)
4897 if (err_classes[i].code == class)
4899 if (err_classes[i].err_msgs)
4901 err_code_struct *err = err_classes[i].err_msgs;
4902 for (j=0;err[j].name;j++)
4903 if (num == err[j].code)
4906 sprintf(ret,"%s - %s (%s)",err_classes[i].class,
4907 err[j].name,err[j].message);
4909 sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
4914 sprintf(ret,"%s - %d",err_classes[i].class,num);
4918 sprintf(ret,"Error: Unknown error (%d,%d)",class,num);