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 /* now we've got a connection - send a tcon message */
3417 bzero(outbuf,smb_size);
3419 if (strncmp(service,"\\\\",2) != 0)
3421 DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
3422 DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
3429 int passlen = strlen(pass)+1;
3433 if (doencrypt && *pass) {
3435 SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
3438 /* if in user level security then don't send a password now */
3439 if ((sec_mode & 1)) {
3440 strcpy(pword, ""); passlen=1;
3443 if (Protocol <= PROTOCOL_COREPLUS) {
3444 set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
3445 CVAL(outbuf,smb_com) = SMBtcon;
3448 p = smb_buf(outbuf);
3451 p = skip_string(p,1);
3453 memcpy(p,pword,passlen);
3459 set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
3460 CVAL(outbuf,smb_com) = SMBtconX;
3463 SSVAL(outbuf,smb_vwv0,0xFF);
3464 SSVAL(outbuf,smb_vwv3,passlen);
3466 p = smb_buf(outbuf);
3467 memcpy(p,pword,passlen);
3470 p = skip_string(p,1);
3475 send_smb(Client,outbuf);
3476 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
3478 /* trying again with a blank password */
3479 if (CVAL(inbuf,smb_rcls) != 0 &&
3480 (int)strlen(pass) > 0 &&
3482 Protocol >= PROTOCOL_LANMAN1)
3484 DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
3489 if (CVAL(inbuf,smb_rcls) != 0)
3491 DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
3492 DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
3493 DEBUG(0,("Some servers insist that these be in uppercase\n"));
3503 if (Protocol <= PROTOCOL_COREPLUS) {
3504 max_xmit = SVAL(inbuf,smb_vwv0);
3506 cnum = SVAL(inbuf,smb_vwv1);
3509 max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
3511 max_xmit = BUFFER_SIZE - 4;
3513 cnum = SVAL(inbuf,smb_tid);
3516 DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
3527 /****************************************************************************
3528 send a logout command
3529 ****************************************************************************/
3530 static void send_logout(void )
3532 pstring inbuf,outbuf;
3534 bzero(outbuf,smb_size);
3535 set_message(outbuf,0,0,True);
3536 CVAL(outbuf,smb_com) = SMBtdis;
3537 SSVAL(outbuf,smb_tid,cnum);
3540 send_smb(Client,outbuf);
3541 receive_smb(Client,inbuf,SHORT_TIMEOUT);
3543 if (CVAL(inbuf,smb_rcls) != 0)
3545 DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
3557 /****************************************************************************
3559 ****************************************************************************/
3560 static BOOL call_api(int prcnt,int drcnt,
3561 int mprcnt,int mdrcnt,
3562 int *rprcnt,int *rdrcnt,
3563 char *param,char *data,
3564 char **rparam,char **rdata)
3566 static char *inbuf=NULL;
3567 static char *outbuf=NULL;
3569 if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3570 if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3572 send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
3577 return (receive_trans_response(inbuf,SMBtrans,
3582 /****************************************************************************
3583 send a SMB trans or trans2 request
3584 ****************************************************************************/
3585 static BOOL send_trans_request(char *outbuf,int trans,
3586 char *name,int fid,int flags,
3587 char *data,char *param,uint16 *setup,
3588 int ldata,int lparam,int lsetup,
3589 int mdata,int mparam,int msetup)
3592 int this_ldata,this_lparam;
3593 int tot_data=0,tot_param=0;
3594 char *outdata,*outparam;
3598 this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
3599 this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
3601 bzero(outbuf,smb_size);
3602 set_message(outbuf,14+lsetup,0,True);
3603 CVAL(outbuf,smb_com) = trans;
3604 SSVAL(outbuf,smb_tid,cnum);
3607 outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
3608 outdata = outparam+this_lparam;
3610 /* primary request */
3611 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3612 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3613 SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */
3614 SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */
3615 SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */
3616 SSVAL(outbuf,smb_flags,flags); /* flags */
3617 SIVAL(outbuf,smb_timeout,0); /* timeout */
3618 SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
3619 SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
3620 SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */
3621 SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
3622 SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */
3623 for (i=0;i<lsetup;i++) /* setup[] */
3624 SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
3625 p = smb_buf(outbuf);
3626 if (trans==SMBtrans)
3627 strcpy(p,name); /* name[] */
3630 *p++ = 0; /* put in a null smb_name */
3631 *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */
3633 if (this_lparam) /* param[] */
3634 memcpy(outparam,param,this_lparam);
3635 if (this_ldata) /* data[] */
3636 memcpy(outdata,data,this_ldata);
3637 set_message(outbuf,14+lsetup, /* wcnt, bcc */
3638 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3641 send_smb(Client,outbuf);
3643 if (this_ldata < ldata || this_lparam < lparam)
3645 /* receive interim response */
3646 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
3648 DEBUG(0,("%s request failed (%s)\n",
3649 trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
3653 tot_data = this_ldata;
3654 tot_param = this_lparam;
3656 while (tot_data < ldata || tot_param < lparam)
3658 this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
3659 this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
3661 set_message(outbuf,trans==SMBtrans?8:9,0,True);
3662 CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
3664 outparam = smb_buf(outbuf);
3665 outdata = outparam+this_lparam;
3667 /* secondary request */
3668 SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
3669 SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
3670 SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
3671 SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
3672 SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */
3673 SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */
3674 SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
3675 SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */
3676 if (trans==SMBtrans2)
3677 SSVAL(outbuf,smb_sfid,fid); /* fid */
3678 if (this_lparam) /* param[] */
3679 memcpy(outparam,param,this_lparam);
3680 if (this_ldata) /* data[] */
3681 memcpy(outdata,data,this_ldata);
3682 set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
3683 PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
3686 send_smb(Client,outbuf);
3688 tot_data += this_ldata;
3689 tot_param += this_lparam;
3696 /****************************************************************************
3697 try and browse available connections on a host
3698 ****************************************************************************/
3699 static BOOL browse_host(BOOL sort)
3702 /* If strcasecmp is already defined, remove it. */
3705 #endif /* strcasecmp */
3706 #define strcasecmp StrCaseCmp
3707 #endif /* NOSTRCASECMP */
3709 extern int strcasecmp();
3711 char *rparam = NULL;
3718 /* now send a SMBtrans command with api RNetShareEnum */
3720 SSVAL(p,0,0); /* api number */
3723 p = skip_string(p,1);
3725 p = skip_string(p,1);
3727 SSVAL(p,2,BUFFER_SIZE);
3730 if (call_api(PTR_DIFF(p,param),0,
3736 int res = SVAL(rparam,0);
3737 int converter=SVAL(rparam,2);
3739 BOOL long_share_name=False;
3743 count=SVAL(rparam,4);
3748 printf("\n\tSharename Type Comment\n");
3749 printf("\t--------- ---- -------\n");
3753 qsort(p,count,20,QSORT_CAST strcasecmp);
3755 for (i=0;i<count;i++)
3758 int type = SVAL(p,14);
3759 int comment_offset = IVAL(p,16) & 0xFFFF;
3765 case STYPE_DISKTREE:
3766 strcpy(typestr,"Disk"); break;
3768 strcpy(typestr,"Printer"); break;
3770 strcpy(typestr,"Device"); break;
3772 strcpy(typestr,"IPC"); break;
3775 printf("\t%-15.15s%-10.10s%s\n",
3778 comment_offset?rdata+comment_offset-converter:"");
3780 if (strlen(sname)>8) long_share_name=True;
3785 if (long_share_name) {
3786 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3791 if (rparam) free(rparam);
3792 if (rdata) free(rdata);
3798 /****************************************************************************
3799 get some server info
3800 ****************************************************************************/
3801 static void server_info()
3803 char *rparam = NULL;
3809 bzero(param,sizeof(param));
3812 SSVAL(p,0,63); /* NetServerGetInfo()? */
3815 p = skip_string(p,1);
3816 strcpy(p,"zzzBBzz");
3817 p = skip_string(p,1);
3818 SSVAL(p,0,10); /* level 10 */
3822 if (call_api(PTR_DIFF(p,param),0,
3828 int res = SVAL(rparam,0);
3829 int converter=SVAL(rparam,2);
3835 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3836 rdata+SVAL(p,0)-converter,
3837 rdata+SVAL(p,4)-converter,
3838 rdata+SVAL(p,8)-converter,
3839 rdata+SVAL(p,14)-converter);
3843 if (rparam) free(rparam);
3844 if (rdata) free(rdata);
3850 /****************************************************************************
3851 try and browse available connections on a host
3852 ****************************************************************************/
3853 static BOOL list_servers(char *wk_grp)
3855 char *rparam = NULL;
3863 BOOL generic_request = False;
3866 if (strequal(wk_grp,"WORKGROUP")) {
3867 /* we won't specify a workgroup */
3868 generic_request = True;
3871 /* now send a SMBtrans command with api ServerEnum? */
3873 SSVAL(p,0,0x68); /* api number */
3876 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3877 p = skip_string(p,1);
3879 strcpy(p,"B16BBDz");
3881 p = skip_string(p,1);
3883 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3889 if (!generic_request) {
3891 p = skip_string(p,1);
3894 /* first ask for a list of servers in this workgroup */
3895 SIVAL(svtype_p,0,SV_TYPE_ALL);
3897 if (call_api(PTR_DIFF(p+4,param),0,
3898 8,BUFFER_SIZE - SAFETY_MARGIN,
3903 int res = SVAL(rparam,0);
3904 int converter=SVAL(rparam,2);
3909 count=SVAL(rparam,4);
3912 printf("\n\nThis machine has a browse list:\n");
3913 printf("\n\tServer Comment\n");
3914 printf("\t--------- -------\n");
3917 for (i=0;i<count;i++) {
3919 int comment_offset = IVAL(p2,22) & 0xFFFF;
3920 printf("\t%-16.16s %s\n",
3922 comment_offset?rdata+comment_offset-converter:"");
3930 if (rparam) {free(rparam); rparam = NULL;}
3931 if (rdata) {free(rdata); rdata = NULL;}
3933 /* now ask for a list of workgroups */
3934 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3936 if (call_api(PTR_DIFF(p+4,param),0,
3937 8,BUFFER_SIZE - SAFETY_MARGIN,
3942 int res = SVAL(rparam,0);
3943 int converter=SVAL(rparam,2);
3948 count=SVAL(rparam,4);
3951 printf("\n\nThis machine has a workgroup list:\n");
3952 printf("\n\tWorkgroup Master\n");
3953 printf("\t--------- -------\n");
3956 for (i=0;i<count;i++) {
3958 int comment_offset = IVAL(p2,22) & 0xFFFF;
3959 printf("\t%-16.16s %s\n",
3961 comment_offset?rdata+comment_offset-converter:"");
3969 if (rparam) free(rparam);
3970 if (rdata) free(rdata);
3976 /* This defines the commands supported by this client */
3984 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3985 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3986 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3987 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3988 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3989 {"get",cmd_get,"<remote name> [local name] get a file"},
3990 {"mget",cmd_mget,"<mask> get all the matching files"},
3991 {"put",cmd_put,"<local name> [remote name] put a file"},
3992 {"mput",cmd_mput,"<mask> put all matching files"},
3993 {"rename",cmd_rename,"<src> <dest> rename some files"},
3994 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3995 {"mask",cmd_select,"<mask> mask all filenames against this"},
3996 {"del",cmd_del,"<mask> delete all matching files"},
3997 {"rm",cmd_del,"<mask> delete all matching files"},
3998 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3999 {"md",cmd_mkdir,"<directory> make a directory"},
4000 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
4001 {"rd",cmd_rmdir,"<directory> remove a directory"},
4002 {"pq",cmd_p_queue_4,"enumerate the print queue"},
4003 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
4004 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
4005 {"translate",cmd_translate,"toggle text translation for printing"},
4006 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
4007 {"print",cmd_print,"<file name> print a file"},
4008 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
4009 {"queue",cmd_queue,"show the print queue"},
4010 {"qinfo",cmd_qinfo,"show print queue information"},
4011 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
4012 {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
4013 {"quit",send_logout,"logoff the server"},
4014 {"q",send_logout,"logoff the server"},
4015 {"exit",send_logout,"logoff the server"},
4016 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
4017 {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit"},
4018 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
4019 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
4020 {"tarmode",cmd_tarmode,
4021 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
4022 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
4023 {"help",cmd_help,"[command] give help on a command"},
4024 {"?",cmd_help,"[command] give help on a command"},
4025 {"!",NULL,"run a shell command on the local system"},
4030 /*******************************************************************
4031 lookup a command string in the list of commands, including
4033 ******************************************************************/
4034 static int process_tok(fstring tok)
4036 int i = 0, matches = 0;
4038 int tok_len = strlen(tok);
4040 while (commands[i].fn != NULL)
4042 if (strequal(commands[i].name,tok))
4048 else if (strnequal(commands[i].name, tok, tok_len+1))
4058 else if (matches == 1)
4064 /****************************************************************************
4066 ****************************************************************************/
4072 if (next_token(NULL,buf,NULL))
4074 if ((i = process_tok(buf)) >= 0)
4075 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
4078 while (commands[i].description)
4080 for (j=0; commands[i].description && (j<5); j++) {
4081 DEBUG(0,("%-15s",commands[i].name));
4088 /****************************************************************************
4089 open the client sockets
4090 ****************************************************************************/
4091 static BOOL open_sockets(int port )
4093 static int last_port;
4101 if (port == 0) port=last_port;
4112 strcpy(service2,service);
4113 host = strtok(service2,"\\/");
4115 DEBUG(0,("Badly formed host name\n"));
4118 strcpy(desthost,host);
4122 get_myname(myname,NULL);
4126 DEBUG(3,("Opening sockets\n"));
4132 if ((hp = Get_Hostbyname(host))) {
4133 putip((char *)&dest_ip,(char *)hp->h_addr);
4137 /* Try and resolve the name with the netbios server */
4140 if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
4141 interpret_addr(lp_socket_address()))) != -1) {
4142 set_socket_options(bcast, "SO_BROADCAST");
4144 if (name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
4152 DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
4158 Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
4162 DEBUG(3,("Connected\n"));
4164 set_socket_options(Client,user_socket_options);
4169 /****************************************************************************
4170 wait for keyboard activity, swallowing network packets
4171 ****************************************************************************/
4173 static char wait_keyboard(char *buffer)
4175 static void wait_keyboard(char *buffer)
4180 struct timeval timeout;
4190 FD_SET(Client,&fds);
4192 FD_SET(fileno(stdin),&fds);
4195 timeout.tv_sec = 20;
4196 timeout.tv_usec = 0;
4200 selrtn = sys_select(&fds,&timeout);
4203 if (FD_ISSET(fileno(stdin),&fds))
4210 set_blocking(fileno(stdin), False);
4211 readret = read_data( fileno(stdin), &ch, 1);
4212 set_blocking(fileno(stdin), True);
4215 if (errno != EAGAIN)
4217 /* should crash here */
4218 DEBUG(1,("readchar stdin failed\n"));
4221 else if (readret != 0)
4227 if (FD_ISSET(Client,&fds))
4228 receive_smb(Client,buffer,0);
4235 chkpath("\\",False);
4238 chkpath("\\",False);
4244 /****************************************************************************
4245 close and open the connection again
4246 ****************************************************************************/
4247 BOOL reopen_connection(char *inbuf,char *outbuf)
4249 static int open_count=0;
4253 if (open_count>5) return(False);
4255 DEBUG(1,("Trying to re-open connection\n"));
4257 set_message(outbuf,0,0,True);
4258 SCVAL(outbuf,smb_com,SMBtdis);
4259 SSVAL(outbuf,smb_tid,cnum);
4262 send_smb(Client,outbuf);
4263 receive_smb(Client,inbuf,SHORT_TIMEOUT);
4266 if (!open_sockets(0)) return(False);
4268 return(send_login(inbuf,outbuf,True,True));
4271 /****************************************************************************
4272 process commands from the client
4273 ****************************************************************************/
4274 static BOOL process(char *base_directory)
4280 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4281 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4283 if ((InBuffer == NULL) || (OutBuffer == NULL))
4286 bzero(OutBuffer,smb_size);
4288 if (!send_login(InBuffer,OutBuffer,True,True))
4291 if (*base_directory) do_cd(base_directory);
4294 if (cmd[0] != '\0') while (cmd[0] != '\0')
4300 if ((p = strchr(cmd, ';')) == 0)
4302 strncpy(line, cmd, 999);
4308 if (p - cmd > 999) p = cmd + 999;
4309 strncpy(line, cmd, p - cmd);
4310 line[p - cmd] = '\0';
4314 /* input language code to internal one */
4317 /* and get the first part of the command */
4320 if (!next_token(&ptr,tok,NULL)) continue;
4323 if ((i = process_tok(tok)) >= 0)
4324 commands[i].fn(InBuffer,OutBuffer);
4326 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4328 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4330 else while (!feof(stdin))
4335 bzero(OutBuffer,smb_size);
4337 /* display a prompt */
4338 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
4342 line[0] = wait_keyboard(InBuffer);
4343 /* this might not be such a good idea... */
4344 if ( line[0] == EOF)
4347 wait_keyboard(InBuffer);
4350 /* and get a response */
4352 fgets( &line[1],999, stdin);
4354 if (!fgets(line,1000,stdin))
4358 /* input language code to internal one */
4361 /* special case - first char is ! */
4368 /* and get the first part of the command */
4371 if (!next_token(&ptr,tok,NULL)) continue;
4374 if ((i = process_tok(tok)) >= 0)
4375 commands[i].fn(InBuffer,OutBuffer);
4377 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
4379 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
4387 /****************************************************************************
4388 usage on the program
4389 ****************************************************************************/
4390 static void usage(char *pname)
4392 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
4395 DEBUG(0,("\nVersion %s\n",VERSION));
4396 DEBUG(0,("\t-p port listen on the specified port\n"));
4397 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
4398 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
4399 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
4400 DEBUG(0,("\t-N don't ask for a password\n"));
4401 DEBUG(0,("\t-P connect to service as a printer\n"));
4402 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
4403 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
4404 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
4405 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
4406 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
4407 DEBUG(0,("\t-U username set the network username\n"));
4408 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
4409 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
4410 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
4411 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
4412 DEBUG(0,("\t-D directory start from directory\n"));
4416 /****************************************************************************
4418 ****************************************************************************/
4419 int main(int argc,char *argv[])
4421 fstring base_directory;
4422 char *pname = argv[0];
4423 int port = SMB_PORT;
4426 extern char *optarg;
4429 BOOL message = False;
4430 extern char tar_type;
4431 static pstring servicesf = CONFIGFILE;
4436 strcpy(term_code, KANJI);
4442 *base_directory = 0;
4446 setup_logging(pname,True);
4449 charset_initialise();
4460 strcpy(username,getenv("USER"));
4462 /* modification to support userid%passwd syntax in the USER var
4463 25.Aug.97, jdblair@uab.edu */
4465 if ((p=strchr(username,'%')))
4468 strcpy(password,p+1);
4470 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
4475 /* modification to support PASSWD environmental var
4476 25.Aug.97, jdblair@uab.edu */
4478 if (getenv("PASSWD"))
4479 strcpy(password,getenv("PASSWD"));
4481 if (*username == 0 && getenv("LOGNAME"))
4483 strcpy(username,getenv("LOGNAME"));
4493 if (*argv[1] != '-')
4496 strcpy(service,argv[1]);
4497 /* Convert any '/' characters in the service name to '\' characters */
4498 string_replace( service, '/','\\');
4502 if (count_chars(service,'\\') < 3)
4505 printf("\n%s: Not enough '\\' characters in service\n",service);
4510 if (count_chars(service,'\\') > 3)
4513 printf("\n%s: Too many '\\' characters in service\n",service);
4518 if (argc > 1 && (*argv[1] != '-'))
4521 strcpy(password,argv[1]);
4522 memset(argv[1],'X',strlen(argv[1]));
4529 getopt(argc, argv,"s:B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
4533 max_protocol = interpret_protocol(optarg,max_protocol);
4536 strcpy(user_socket_options,optarg);
4539 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
4540 strcpy(desthost,optarg);
4545 iface_set_default(NULL,optarg,NULL);
4548 strcpy(base_directory,optarg);
4551 if (!tar_parseargs(argc, argv, optarg, optind)) {
4557 strcpy(scope,optarg);
4561 strcpy(query_host,optarg);
4566 strcpy(username,optarg);
4567 if ((lp=strchr(username,'%')))
4570 strcpy(password,lp+1);
4572 memset(strchr(optarg,'%')+1,'X',strlen(password));
4578 strcpy(workgroup,optarg);
4585 dest_ip = *interpret_addr2(optarg);
4586 if (zero_ip(dest_ip)) exit(1);
4591 strcpy(myname,optarg);
4597 connect_as_printer = True;
4603 DEBUGLEVEL = atoi(optarg);
4606 sprintf(debugf,"%s.client",optarg);
4609 port = atoi(optarg);
4620 strcpy(servicesf, optarg);
4623 strcpy(term_code, optarg);
4630 if (!tar_type && !*query_host && !*service && !message)
4637 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
4639 if(!get_myname(myhostname,NULL))
4641 DEBUG(0,("Failed to get my hostname.\n"));
4644 if (!lp_load(servicesf,True)) {
4645 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
4648 codepage_initialise(lp_client_code_page());
4650 if(lp_client_code_page() == KANJI_CODEPAGE)
4652 if (!setup_term_code (term_code))
4654 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
4660 if (*workgroup == 0)
4661 strcpy(workgroup,lp_workgroup());
4664 get_myname(*myname?NULL:myname,NULL);
4670 if (open_sockets(port)) {
4671 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4672 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4675 if ((InBuffer == NULL) || (OutBuffer == NULL))
4678 bzero(OutBuffer,smb_size);
4679 if (!send_login(InBuffer,OutBuffer,True,True))
4682 if (*base_directory) do_cd(base_directory);
4684 ret=process_tar(InBuffer, OutBuffer);
4696 sprintf(service,"\\\\%s\\IPC$",query_host);
4698 connect_as_ipc = True;
4699 if (open_sockets(port))
4704 if (!send_login(NULL,NULL,True,True))
4708 if (!browse_host(True)) {
4712 if (!list_servers(workgroup)) {
4714 list_servers(workgroup);
4727 if (open_sockets(port))
4729 pstring inbuf,outbuf;
4730 bzero(outbuf,smb_size);
4731 if (!send_session_request(inbuf,outbuf))
4734 send_message(inbuf,outbuf);
4742 if (open_sockets(port))
4744 if (!process(base_directory))
4758 /* error code stuff - put together by Merik Karman
4759 merik@blackadder.dsh.oz.au */
4768 /* Dos Error Messages */
4769 err_code_struct dos_msgs[] = {
4770 {"ERRbadfunc",1,"Invalid function."},
4771 {"ERRbadfile",2,"File not found."},
4772 {"ERRbadpath",3,"Directory invalid."},
4773 {"ERRnofids",4,"No file descriptors available"},
4774 {"ERRnoaccess",5,"Access denied."},
4775 {"ERRbadfid",6,"Invalid file handle."},
4776 {"ERRbadmcb",7,"Memory control blocks destroyed."},
4777 {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
4778 {"ERRbadmem",9,"Invalid memory block address."},
4779 {"ERRbadenv",10,"Invalid environment."},
4780 {"ERRbadformat",11,"Invalid format."},
4781 {"ERRbadaccess",12,"Invalid open mode."},
4782 {"ERRbaddata",13,"Invalid data."},
4783 {"ERR",14,"reserved."},
4784 {"ERRbaddrive",15,"Invalid drive specified."},
4785 {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
4786 {"ERRdiffdevice",17,"Not same device."},
4787 {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
4788 {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
4789 {"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."},
4790 {"ERRnosuchshare", 67, "You specified an invalid share name"},
4791 {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
4792 {"ERRbadpipe",230,"Pipe invalid."},
4793 {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
4794 {"ERRpipeclosing",232,"Pipe close in progress."},
4795 {"ERRnotconnected",233,"No process on other end of pipe."},
4796 {"ERRmoredata",234,"There is more data to be returned."},
4797 {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
4800 /* Server Error Messages */
4801 err_code_struct server_msgs[] = {
4802 {"ERRerror",1,"Non-specific error code."},
4803 {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
4804 {"ERRbadtype",3,"reserved."},
4805 {"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."},
4806 {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
4807 {"ERRinvnetname",6,"Invalid network name in tree connect."},
4808 {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
4809 {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
4810 {"ERRqtoobig",50,"Print queue full -- no space."},
4811 {"ERRqeof",51,"EOF on print queue dump."},
4812 {"ERRinvpfid",52,"Invalid print file FID."},
4813 {"ERRsmbcmd",64,"The server did not recognize the command received."},
4814 {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
4815 {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
4816 {"ERRreserved",68,"reserved."},
4817 {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
4818 {"ERRreserved",70,"reserved."},
4819 {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
4820 {"ERRpaused",81,"Server is paused."},
4821 {"ERRmsgoff",82,"Not receiving messages."},
4822 {"ERRnoroom",83,"No room to buffer message."},
4823 {"ERRrmuns",87,"Too many remote user names."},
4824 {"ERRtimeout",88,"Operation timed out."},
4825 {"ERRnoresource",89,"No resources currently available for request."},
4826 {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
4827 {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
4828 {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
4829 {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
4830 {"ERRcontmpx",252,"Continue in MPX mode."},
4831 {"ERRreserved",253,"reserved."},
4832 {"ERRreserved",254,"reserved."},
4833 {"ERRnosupport",0xFFFF,"Function not supported."},
4836 /* Hard Error Messages */
4837 err_code_struct hard_msgs[] = {
4838 {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
4839 {"ERRbadunit",20,"Unknown unit."},
4840 {"ERRnotready",21,"Drive not ready."},
4841 {"ERRbadcmd",22,"Unknown command."},
4842 {"ERRdata",23,"Data error (CRC)."},
4843 {"ERRbadreq",24,"Bad request structure length."},
4844 {"ERRseek",25 ,"Seek error."},
4845 {"ERRbadmedia",26,"Unknown media type."},
4846 {"ERRbadsector",27,"Sector not found."},
4847 {"ERRnopaper",28,"Printer out of paper."},
4848 {"ERRwrite",29,"Write fault."},
4849 {"ERRread",30,"Read fault."},
4850 {"ERRgeneral",31,"General failure."},
4851 {"ERRbadshare",32,"An open conflicts with an existing open."},
4852 {"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."},
4853 {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
4854 {"ERRFCBUnavail",35,"No FCBs are available to process request."},
4855 {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
4863 err_code_struct *err_msgs;
4866 {0x01,"ERRDOS",dos_msgs},
4867 {0x02,"ERRSRV",server_msgs},
4868 {0x03,"ERRHRD",hard_msgs},
4869 {0x04,"ERRXOS",NULL},
4870 {0xE1,"ERRRMX1",NULL},
4871 {0xE2,"ERRRMX2",NULL},
4872 {0xE3,"ERRRMX3",NULL},
4873 {0xFF,"ERRCMD",NULL},
4877 /****************************************************************************
4878 return a SMB error string from a SMB buffer
4879 ****************************************************************************/
4880 char *smb_errstr(char *inbuf)
4883 int class = CVAL(inbuf,smb_rcls);
4884 int num = SVAL(inbuf,smb_err);
4887 for (i=0;err_classes[i].class;i++)
4888 if (err_classes[i].code == class)
4890 if (err_classes[i].err_msgs)
4892 err_code_struct *err = err_classes[i].err_msgs;
4893 for (j=0;err[j].name;j++)
4894 if (num == err[j].code)
4897 sprintf(ret,"%s - %s (%s)",err_classes[i].class,
4898 err[j].name,err[j].message);
4900 sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
4905 sprintf(ret,"%s - %d",err_classes[i].class,num);
4909 sprintf(ret,"Error: Unknown error (%d,%d)",class,num);