2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1998
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 = "\\";
34 extern pstring service;
35 extern pstring desthost;
36 extern pstring global_myname;
37 extern pstring myhostname;
38 extern pstring password;
39 extern pstring username;
40 extern pstring workgroup;
44 extern BOOL connect_as_printer;
45 extern BOOL connect_as_ipc;
46 extern struct in_addr ipzero;
48 extern BOOL doencrypt;
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 extern int max_protocol;
64 time_t newer_than = 0;
65 int archive_level = 0;
67 extern pstring debugf;
68 extern int DEBUGLEVEL;
70 BOOL translation = False;
82 static int interpret_long_filename(int level,char *p,file_info *finfo);
83 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo);
84 static int interpret_short_filename(char *p,file_info *finfo);
85 static BOOL do_this_one(file_info *finfo);
87 /* clitar bits insert */
90 extern BOOL tar_reset;
102 BOOL recurse = False;
103 BOOL lowercase = False;
105 struct in_addr dest_ip;
107 #define SEPARATORS " \t\n\r"
109 BOOL abort_mget = True;
113 extern BOOL readbraw_supported ;
114 extern BOOL writebraw_supported;
116 pstring fileselection = "";
118 extern file_info def_finfo;
121 int get_total_size = 0;
122 int get_total_time_ms = 0;
123 int put_total_size = 0;
124 int put_total_time_ms = 0;
133 #define CNV_LANG(s) dos_to_unix(s,False)
134 #define CNV_INPUT(s) unix_to_dos(s,True)
136 /****************************************************************************
137 send an SMBclose on an SMB file handle
138 ****************************************************************************/
139 void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
141 bzero(outbuf,smb_size);
142 set_message(outbuf,3,0,True);
144 CVAL (outbuf,smb_com) = SMBclose;
145 SSVAL(outbuf,smb_tid,c_num);
146 cli_setup_pkt(outbuf);
147 SSVAL (outbuf,smb_vwv0, f_num);
148 SIVALS(outbuf,smb_vwv1, -1);
150 send_smb(clnt_fd, outbuf);
151 client_receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
154 /****************************************************************************
155 write to a local file with CR/LF->LF translation if appropriate. return the
156 number taken from the buffer. This may not equal the number written.
157 ****************************************************************************/
158 static int writefile(int f, char *b, int n)
163 return(write(f,b,n));
168 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
172 if (write(f, b, 1) != 1)
183 /****************************************************************************
184 read from a file with LF->CR/LF translation if appropriate. return the
185 number read. read approx n bytes.
186 ****************************************************************************/
187 static int readfile(char *b, int size, int n, FILE *f)
192 if (!translation || (size != 1))
193 return(fread(b,size,n,f));
198 if ((c = getc(f)) == EOF)
203 if (c == '\n') /* change all LFs to CR/LF */
217 /****************************************************************************
218 read from a file with print translation. return the number read. read approx n
220 ****************************************************************************/
221 static int printread(FILE *f,char *b,int n)
225 i = readfile(b,1, n-1,f);
234 /****************************************************************************
235 check for existance of a dir
236 ****************************************************************************/
237 static BOOL chkpath(char *path,BOOL report)
240 pstring inbuf,outbuf;
244 trim_string(path2,NULL,"\\");
245 if (!*path2) *path2 = '\\';
247 bzero(outbuf,smb_size);
248 set_message(outbuf,0,4 + strlen(path2),True);
249 SCVAL(outbuf,smb_com,SMBchkpth);
250 SSVAL(outbuf,smb_tid,cnum);
251 cli_setup_pkt(outbuf);
259 /* this little bit of code can be used to extract NT error codes.
260 Just feed a bunch of "cd foo" commands to smbclient then watch
261 in netmon (tridge) */
263 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
264 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
269 send_smb(Client,outbuf);
270 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
272 if (report && CVAL(inbuf,smb_rcls) != 0)
273 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
275 return(CVAL(inbuf,smb_rcls) == 0);
279 /****************************************************************************
281 ****************************************************************************/
282 static void send_message(char *inbuf,char *outbuf)
289 /* send a SMBsendstrt command */
290 bzero(outbuf,smb_size);
291 set_message(outbuf,0,0,True);
292 CVAL(outbuf,smb_com) = SMBsendstrt;
293 SSVAL(outbuf,smb_tid,cnum);
298 p = skip_string(p,1);
301 p = skip_string(p,1);
303 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
305 send_smb(Client,outbuf);
308 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
310 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
314 grp_id = SVAL(inbuf,smb_vwv0);
316 printf("Connected. Type your message, ending it with a Control-D\n");
318 while (!feof(stdin) && total_len < 1600)
320 int maxlen = MIN(1600 - total_len,127);
327 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
334 CVAL(outbuf,smb_com) = SMBsendtxt;
336 set_message(outbuf,1,l+3,True);
338 SSVAL(outbuf,smb_vwv0,grp_id);
345 send_smb(Client,outbuf);
348 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
350 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
357 if (total_len >= 1600)
358 printf("the message was truncated to 1600 bytes ");
360 printf("sent %d bytes ",total_len);
362 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
364 CVAL(outbuf,smb_com) = SMBsendend;
365 set_message(outbuf,1,0,False);
366 SSVAL(outbuf,smb_vwv0,grp_id);
368 send_smb(Client,outbuf);
371 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
373 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
380 /****************************************************************************
381 check the space on a device
382 ****************************************************************************/
383 static void do_dskattr(void)
385 pstring inbuf,outbuf;
387 bzero(outbuf,smb_size);
388 set_message(outbuf,0,0,True);
389 CVAL(outbuf,smb_com) = SMBdskattr;
390 SSVAL(outbuf,smb_tid,cnum);
391 cli_setup_pkt(outbuf);
393 send_smb(Client,outbuf);
394 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
396 if (CVAL(inbuf,smb_rcls) != 0)
397 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
399 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
400 SVAL(inbuf,smb_vwv0),
401 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
402 SVAL(inbuf,smb_vwv3)));
405 /****************************************************************************
407 ****************************************************************************/
408 static void cmd_pwd(char *dum_in, char *dum_out)
410 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
411 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
415 /****************************************************************************
416 change directory - inner section
417 ****************************************************************************/
418 static void do_cd(char *newdir)
424 /* Save the current directory in case the
425 new directory is invalid */
426 strcpy(saved_dir, cur_dir);
431 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
432 strcat(cur_dir, "\\");
434 dos_clean_name(cur_dir);
435 strcpy(dname,cur_dir);
436 strcat(cur_dir,"\\");
437 dos_clean_name(cur_dir);
439 if (!strequal(cur_dir,"\\"))
440 if (!chkpath(dname,True))
441 strcpy(cur_dir,saved_dir);
443 strcpy(cd_path,cur_dir);
446 /****************************************************************************
448 ****************************************************************************/
449 static void cmd_cd(char *inbuf,char *outbuf)
453 if (next_token(NULL,buf,NULL))
456 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
460 /****************************************************************************
461 display info about a file
462 ****************************************************************************/
463 static void display_finfo(file_info *finfo)
465 if (do_this_one(finfo)) {
466 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
467 DEBUG(0,(" %-30s%7.7s%10d %s",
468 CNV_LANG(finfo->name),
469 attrib_string(finfo->mode),
471 asctime(LocalTime(&t))));
472 dir_total += finfo->size;
477 /****************************************************************************
478 do a directory listing, calling fn on each file found. Use the TRANSACT2
479 call for long filenames
480 ****************************************************************************/
481 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
483 int max_matches = 512;
484 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
489 char *dirlist = NULL;
491 int total_received = 0;
493 char *resp_data=NULL;
494 char *resp_param=NULL;
495 int resp_data_len = 0;
496 int resp_param_len=0;
498 int ff_resume_key = 0;
499 int ff_searchcount=0;
513 if (loop_count > 200)
515 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
521 setup = TRANSACT2_FINDFIRST;
522 SSVAL(param,0,attribute); /* attribute */
523 SSVAL(param,2,max_matches); /* max count */
524 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
525 SSVAL(param,6,info_level);
527 strcpy(param+12,mask);
531 setup = TRANSACT2_FINDNEXT;
532 SSVAL(param,0,ff_dir_handle);
533 SSVAL(param,2,max_matches); /* max count */
534 SSVAL(param,4,info_level);
535 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
536 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
537 strcpy(param+12,mask);
539 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
540 ff_dir_handle,ff_resume_key,ff_lastname,mask));
542 /* ??? original code added 1 pad byte after param */
544 cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
546 0,12+strlen(mask)+1,1,
549 if (!cli_receive_trans_response(inbuf,SMBtrans2,
550 &resp_data_len,&resp_param_len,
551 &resp_data,&resp_param))
553 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
557 /* parse out some important return info */
561 ff_dir_handle = SVAL(p,0);
562 ff_searchcount = SVAL(p,2);
564 ff_lastname = SVAL(p,8);
568 ff_searchcount = SVAL(p,0);
570 ff_lastname = SVAL(p,6);
573 if (ff_searchcount == 0)
576 /* point to the data bytes */
579 /* we might need the lastname for continuations */
586 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
587 /* strcpy(mask,p+ff_lastname+94); */
590 strcpy(mask,p + ff_lastname + 1);
598 /* and add them to the dirlist pool */
599 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
603 DEBUG(0,("Failed to expand dirlist\n"));
607 /* put in a length for the last entry, to ensure we can chain entries
608 into the next packet */
611 for (p2=p,i=0;i<(ff_searchcount-1);i++)
612 p2 += interpret_long_filename(info_level,p2,NULL);
613 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
616 /* grab the data for later use */
617 memcpy(dirlist+dirlist_len,p,resp_data_len);
618 dirlist_len += resp_data_len;
620 total_received += ff_searchcount;
622 if (resp_data) free(resp_data); resp_data = NULL;
623 if (resp_param) free(resp_param); resp_param = NULL;
625 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
626 ff_searchcount,ff_eos,ff_resume_key));
632 for (p=dirlist,i=0;i<total_received;i++)
634 p += interpret_long_filename(info_level,p,&finfo);
635 display_finfo(&finfo);
638 for (p=dirlist,i=0;i<total_received;i++)
640 p += interpret_long_filename(info_level,p,&finfo);
641 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True, dirstoo);
644 /* free up the dirlist buffer */
645 if (dirlist) free(dirlist);
646 return(total_received);
650 /****************************************************************************
651 do a directory listing, calling fn on each file found
652 ****************************************************************************/
653 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
659 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
660 int num_received = 0;
662 char *dirlist = NULL;
674 bzero(outbuf,smb_size);
676 set_message(outbuf,2,5 + strlen(mask),True);
678 set_message(outbuf,2,5 + 21,True);
681 if (Protocol >= PROTOCOL_LANMAN1)
682 CVAL(outbuf,smb_com) = SMBffirst;
685 CVAL(outbuf,smb_com) = SMBsearch;
687 SSVAL(outbuf,smb_tid,cnum);
688 cli_setup_pkt(outbuf);
690 SSVAL(outbuf,smb_vwv0,num_asked);
691 SSVAL(outbuf,smb_vwv1,attribute);
712 send_smb(Client,outbuf);
713 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
715 received = SVAL(inbuf,smb_vwv0);
717 DEBUG(5,("dir received %d\n",received));
719 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
721 if (received <= 0) break;
725 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
730 p = smb_buf(inbuf) + 3;
732 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
733 p,received*DIR_STRUCT_SIZE);
735 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
737 num_received += received;
739 if (CVAL(inbuf,smb_rcls) != 0) break;
743 if (!first && Protocol >= PROTOCOL_LANMAN1)
745 bzero(outbuf,smb_size);
746 CVAL(outbuf,smb_com) = SMBfclose;
748 SSVAL(outbuf,smb_tid,cnum);
749 cli_setup_pkt(outbuf);
762 send_smb(Client,outbuf);
763 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
765 if (CVAL(inbuf,smb_rcls) != 0)
766 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
771 for (p=dirlist,i=0;i<num_received;i++)
773 p += interpret_short_filename(p,&finfo);
774 display_finfo(&finfo);
777 for (p=dirlist,i=0;i<num_received;i++)
779 p += interpret_short_filename(p,&finfo);
780 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False,dirstoo);
783 if (dirlist) free(dirlist);
784 return(num_received);
789 /****************************************************************************
790 do a directory listing, calling fn on each file found
791 ****************************************************************************/
792 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
794 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
795 if (Protocol >= PROTOCOL_LANMAN2)
797 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo) > 0)
801 expand_mask(Mask,False);
802 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo);
806 /*******************************************************************
807 decide if a file should be operated on
808 ********************************************************************/
809 static BOOL do_this_one(file_info *finfo)
811 if (finfo->mode & aDIR) return(True);
813 if (newer_than && finfo->mtime < newer_than)
816 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
823 /*****************************************************************************
824 Convert a character pointer in a cli_call_api() response to a form we can use.
825 This function contains code to prevent core dumps if the server returns
827 *****************************************************************************/
828 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
830 if( datap == 0 ) /* turn NULL pointers */
831 { /* into zero length strings */
836 unsigned int offset = datap - converter;
838 if( offset >= rdrcnt )
840 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
845 return &rdata[offset];
850 /****************************************************************************
851 interpret a short filename structure
852 The length of the structure is returned
853 ****************************************************************************/
854 static int interpret_short_filename(char *p,file_info *finfo)
856 finfo->mode = CVAL(p,21);
858 /* this date is converted to GMT by make_unix_date */
859 finfo->ctime = make_unix_date(p+22);
860 finfo->mtime = finfo->atime = finfo->ctime;
861 finfo->size = IVAL(p,26);
862 strcpy(finfo->name,p+30);
864 return(DIR_STRUCT_SIZE);
867 /****************************************************************************
868 interpret a long filename structure - this is mostly guesses at the moment
869 The length of the structure is returned
870 The structure of a long filename depends on the info level. 260 is used
871 by NT and 2 is used by OS/2
872 ****************************************************************************/
873 static int interpret_long_filename(int level,char *p,file_info *finfo)
876 memcpy(finfo,&def_finfo,sizeof(*finfo));
880 case 1: /* OS/2 understands this */
883 /* these dates are converted to GMT by make_unix_date */
884 finfo->ctime = make_unix_date2(p+4);
885 finfo->atime = make_unix_date2(p+8);
886 finfo->mtime = make_unix_date2(p+12);
887 finfo->size = IVAL(p,16);
888 finfo->mode = CVAL(p,24);
889 strcpy(finfo->name,p+27);
891 return(28 + CVAL(p,26));
893 case 2: /* this is what OS/2 uses mostly */
896 /* these dates are converted to GMT by make_unix_date */
897 finfo->ctime = make_unix_date2(p+4);
898 finfo->atime = make_unix_date2(p+8);
899 finfo->mtime = make_unix_date2(p+12);
900 finfo->size = IVAL(p,16);
901 finfo->mode = CVAL(p,24);
902 strcpy(finfo->name,p+31);
904 return(32 + CVAL(p,30));
906 /* levels 3 and 4 are untested */
910 /* these dates are probably like the other ones */
911 finfo->ctime = make_unix_date2(p+8);
912 finfo->atime = make_unix_date2(p+12);
913 finfo->mtime = make_unix_date2(p+16);
914 finfo->size = IVAL(p,20);
915 finfo->mode = CVAL(p,28);
916 strcpy(finfo->name,p+33);
923 /* these dates are probably like the other ones */
924 finfo->ctime = make_unix_date2(p+8);
925 finfo->atime = make_unix_date2(p+12);
926 finfo->mtime = make_unix_date2(p+16);
927 finfo->size = IVAL(p,20);
928 finfo->mode = CVAL(p,28);
929 strcpy(finfo->name,p+37);
933 case 260: /* NT uses this, but also accepts 2 */
938 p += 4; /* next entry offset */
939 p += 4; /* fileindex */
941 /* these dates appear to arrive in a weird way. It seems to
942 be localtime plus the serverzone given in the initial
943 connect. This is GMT when DST is not in effect and one
944 hour from GMT otherwise. Can this really be right??
946 I suppose this could be called kludge-GMT. Is is the GMT
947 you get by using the current DST setting on a different
948 localtime. It will be cheap to calculate, I suppose, as
949 no DST tables will be needed */
951 finfo->ctime = interpret_long_date(p); p += 8;
952 finfo->atime = interpret_long_date(p); p += 8;
953 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
954 finfo->size = IVAL(p,0); p += 8;
955 p += 8; /* alloc size */
956 finfo->mode = CVAL(p,0); p += 4;
957 namelen = IVAL(p,0); p += 4;
958 p += 4; /* EA size */
959 p += 2; /* short name len? */
960 p += 24; /* short name? */
961 StrnCpy(finfo->name,p,namelen);
967 DEBUG(1,("Unknown long filename format %d\n",level));
974 /****************************************************************************
975 act on the files in a dir listing
977 RJS, 4-Apr-1998, dirstoo added to allow caller to indicate that directories
978 should be processed as well.
979 ****************************************************************************/
980 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo)
983 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
984 !mask_match(finfo->name,fileselection,False,False)) &&
985 !(recurse_dir && (strequal(finfo->name,".") ||
986 strequal(finfo->name,".."))))
988 if (recurse_dir && (finfo->mode & aDIR))
993 if (fn && dirstoo && do_this_one(finfo)) { /* Do dirs, RJS */
997 strcpy(sav_dir,cur_dir);
998 strcat(cur_dir,finfo->name);
999 strcat(cur_dir,"\\");
1000 strcpy(mask2,cur_dir);
1003 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1008 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1010 do_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1012 strcpy(cur_dir,sav_dir);
1016 if (fn && do_this_one(finfo))
1023 /****************************************************************************
1024 get a directory listing
1025 ****************************************************************************/
1026 static void cmd_dir(char *inbuf,char *outbuf)
1028 int attribute = aDIR | aSYSTEM | aHIDDEN;
1034 strcpy(mask,cur_dir);
1035 if(mask[strlen(mask)-1]!='\\')
1038 if (next_token(NULL,buf,NULL))
1049 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse,False);
1053 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1058 /****************************************************************************
1059 get a file from rname to lname
1060 ****************************************************************************/
1061 static void do_get(char *rname,char *lname,file_info *finfo1)
1066 BOOL newhandle = False;
1067 char *inbuf,*outbuf;
1069 BOOL close_done = False;
1070 BOOL ignore_close_error = False;
1074 struct timeval tp_start;
1075 GetTimeOfDay(&tp_start);
1086 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1087 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1089 if (!inbuf || !outbuf)
1091 DEBUG(0,("out of memory\n"));
1095 bzero(outbuf,smb_size);
1096 set_message(outbuf,15,1 + strlen(rname),True);
1098 CVAL(outbuf,smb_com) = SMBopenX;
1099 SSVAL(outbuf,smb_tid,cnum);
1100 cli_setup_pkt(outbuf);
1102 SSVAL(outbuf,smb_vwv0,0xFF);
1103 SSVAL(outbuf,smb_vwv2,1); /* return additional info */
1104 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1105 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1106 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1107 SSVAL(outbuf,smb_vwv8,1);
1108 SSVAL(outbuf,smb_vwv11,0xffff);
1109 SSVAL(outbuf,smb_vwv12,0xffff);
1111 p = smb_buf(outbuf);
1113 p = skip_string(p,1);
1115 /* do a chained openX with a readX? */
1119 DEBUG(3,("Chaining readX wth openX\n"));
1120 SSVAL(outbuf,smb_vwv0,SMBreadX);
1121 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1124 SSVAL(p,smb_wct,10);
1125 SSVAL(p,smb_vwv0,0xFF);
1126 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1127 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1128 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1132 if(!strcmp(lname,"-"))
1133 handle = fileno(stdout);
1136 handle = creat(lname,0644);
1141 DEBUG(0,("Error opening local file %s\n",lname));
1142 free(inbuf);free(outbuf);
1146 send_smb(Client,outbuf);
1147 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1149 if (CVAL(inbuf,smb_rcls) != 0)
1151 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1152 SVAL(inbuf,smb_err) == ERRnoresource &&
1153 cli_reopen_connection(inbuf,outbuf))
1155 do_get(rname,lname,finfo1);
1158 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1161 free(inbuf);free(outbuf);
1165 strcpy(finfo.name,rname);
1169 finfo.mode = SVAL(inbuf,smb_vwv3);
1170 /* these times arrive as LOCAL time, using the DST offset
1171 corresponding to that time, we convert them to GMT */
1172 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1173 finfo.atime = finfo.ctime = finfo.mtime;
1174 finfo.size = IVAL(inbuf,smb_vwv6);
1177 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1179 fnum = SVAL(inbuf,smb_vwv2);
1181 /* we might have got some data from a chained readX */
1182 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1184 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1185 datalen = SVAL(p,smb_vwv5);
1186 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1195 DEBUG(2,("getting file %s of size %d bytes as %s ",
1196 CNV_LANG(finfo.name),
1200 while (nread < finfo.size && !close_done)
1203 static BOOL can_chain_close = True;
1207 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1209 /* 3 possible read types. readbraw if a large block is required.
1210 readX + close if not much left and read if neither is supported */
1212 /* we might have already read some data from a chained readX */
1213 if (dataptr && datalen>0)
1216 /* if we can finish now then readX+close */
1217 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1218 ((finfo.size - nread) <
1219 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1222 /* if we support readraw then use that */
1223 if (method<0 && readbraw_supported)
1226 /* if we can then use readX */
1227 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1238 /* use readX + close */
1239 bzero(outbuf,smb_size);
1240 set_message(outbuf,10,0,True);
1241 CVAL(outbuf,smb_com) = SMBreadX;
1242 SSVAL(outbuf,smb_tid,cnum);
1243 cli_setup_pkt(outbuf);
1247 CVAL(outbuf,smb_vwv0) = SMBclose;
1248 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1251 CVAL(outbuf,smb_vwv0) = 0xFF;
1253 SSVAL(outbuf,smb_vwv2,fnum);
1254 SIVAL(outbuf,smb_vwv3,nread);
1255 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1256 SSVAL(outbuf,smb_vwv6,0);
1257 SIVAL(outbuf,smb_vwv7,0);
1258 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1262 p = smb_buf(outbuf);
1269 /* now set the total packet length */
1270 smb_setlen(outbuf,smb_len(outbuf)+9);
1273 send_smb(Client,outbuf);
1274 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1276 if (CVAL(inbuf,smb_rcls) != 0)
1278 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1283 SVAL(inbuf,smb_vwv0) != SMBclose)
1285 /* NOTE: WfWg sometimes just ignores the chained
1286 command! This seems to break the spec? */
1287 DEBUG(3,("Rejected chained close?\n"));
1289 can_chain_close = False;
1290 ignore_close_error = True;
1293 datalen = SVAL(inbuf,smb_vwv5);
1294 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1300 static int readbraw_size = BUFFER_SIZE;
1303 bzero(outbuf,smb_size);
1304 set_message(outbuf,8,0,True);
1305 CVAL(outbuf,smb_com) = SMBreadbraw;
1306 SSVAL(outbuf,smb_tid,cnum);
1307 cli_setup_pkt(outbuf);
1308 SSVAL(outbuf,smb_vwv0,fnum);
1309 SIVAL(outbuf,smb_vwv1,nread);
1310 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1311 SSVAL(outbuf,smb_vwv4,0);
1312 SIVALS(outbuf,smb_vwv5,-1);
1313 send_smb(Client,outbuf);
1315 /* Now read the raw data into the buffer and write it */
1316 if(read_smb_length(Client,inbuf,0) == -1) {
1317 DEBUG(0,("Failed to read length in readbraw\n"));
1321 /* Even though this is not an smb message, smb_len
1322 returns the generic length of an smb message */
1323 datalen = smb_len(inbuf);
1327 /* we got a readbraw error */
1328 DEBUG(4,("readbraw error - reducing size\n"));
1329 readbraw_size = (readbraw_size * 9) / 10;
1331 if (readbraw_size < max_xmit)
1333 DEBUG(0,("disabling readbraw\n"));
1334 readbraw_supported = False;
1341 if(read_data(Client,inbuf,datalen) != datalen) {
1342 DEBUG(0,("Failed to read data in readbraw\n"));
1350 /* we've already read some data with a chained readX */
1354 /* use plain read */
1355 bzero(outbuf,smb_size);
1356 set_message(outbuf,5,0,True);
1357 CVAL(outbuf,smb_com) = SMBread;
1358 SSVAL(outbuf,smb_tid,cnum);
1359 cli_setup_pkt(outbuf);
1361 SSVAL(outbuf,smb_vwv0,fnum);
1362 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1363 SIVAL(outbuf,smb_vwv2,nread);
1364 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1366 send_smb(Client,outbuf);
1367 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1369 if (CVAL(inbuf,smb_rcls) != 0)
1371 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1375 datalen = SVAL(inbuf,smb_vwv0);
1376 dataptr = smb_buf(inbuf) + 3;
1380 if (writefile(handle,dataptr,datalen) != datalen)
1382 DEBUG(0,("Error writing local file\n"));
1389 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1401 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1403 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1405 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1408 free(inbuf);free(outbuf);
1416 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1417 bzero(outbuf,smb_size);
1418 set_message(outbuf,8,strlen(rname)+4,True);
1419 CVAL(outbuf,smb_com) = SMBsetatr;
1420 SSVAL(outbuf,smb_tid,cnum);
1421 cli_setup_pkt(outbuf);
1422 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1423 SIVALS(outbuf,smb_vwv1,0);
1424 p = smb_buf(outbuf);
1430 send_smb(Client,outbuf);
1431 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1435 struct timeval tp_end;
1438 GetTimeOfDay(&tp_end);
1440 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1441 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1442 get_total_time_ms += this_time;
1443 get_total_size += finfo.size;
1445 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1446 finfo.size / (1.024*this_time + 1.0e-4),
1447 get_total_size / (1.024*get_total_time_ms)));
1450 free(inbuf);free(outbuf);
1454 /****************************************************************************
1456 ****************************************************************************/
1457 static void cmd_get(char *dum_in, char *dum_out)
1463 strcpy(rname,cur_dir);
1466 p = rname + strlen(rname);
1468 if (!next_token(NULL,p,NULL)) {
1469 DEBUG(0,("get <filename>\n"));
1473 dos_clean_name(rname);
1475 next_token(NULL,lname,NULL);
1477 do_get(rname,lname,NULL);
1481 /****************************************************************************
1482 do a mget operation on one file
1483 ****************************************************************************/
1484 static void do_mget(file_info *finfo)
1489 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1494 DEBUG(0,("mget aborted\n"));
1498 if (finfo->mode & aDIR)
1499 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1501 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1503 if (prompt && !yesno(quest)) return;
1505 if (finfo->mode & aDIR)
1507 pstring saved_curdir;
1509 char *inbuf,*outbuf;
1511 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1512 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1514 if (!inbuf || !outbuf)
1516 DEBUG(0,("out of memory\n"));
1520 strcpy(saved_curdir,cur_dir);
1522 strcat(cur_dir,finfo->name);
1523 strcat(cur_dir,"\\");
1525 unix_format(finfo->name);
1528 strlower(finfo->name);
1530 if (!directory_exist(finfo->name,NULL) &&
1531 sys_mkdir(finfo->name,0777) != 0)
1533 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1534 strcpy(cur_dir,saved_curdir);
1535 free(inbuf);free(outbuf);
1539 if (sys_chdir(finfo->name) != 0)
1541 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1542 strcpy(cur_dir,saved_curdir);
1543 free(inbuf);free(outbuf);
1548 strcpy(mget_mask,cur_dir);
1549 strcat(mget_mask,"*");
1551 do_dir((char *)inbuf,(char *)outbuf,
1552 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False, False);
1554 strcpy(cur_dir,saved_curdir);
1555 free(inbuf);free(outbuf);
1559 strcpy(rname,cur_dir);
1560 strcat(rname,finfo->name);
1561 do_get(rname,finfo->name,finfo);
1565 /****************************************************************************
1566 view the file using the pager
1567 ****************************************************************************/
1568 static void cmd_more(char *dum_in, char *dum_out)
1570 fstring rname,lname,tmpname,pager_cmd;
1573 strcpy(rname,cur_dir);
1575 sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1576 strcpy(lname,tmpname);
1578 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1579 DEBUG(0,("more <filename>\n"));
1582 dos_clean_name(rname);
1584 do_get(rname,lname,NULL);
1586 pager=getenv("PAGER");
1587 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1594 /****************************************************************************
1596 ****************************************************************************/
1597 static void cmd_mget(char *inbuf,char *outbuf)
1599 int attribute = aSYSTEM | aHIDDEN;
1611 while (next_token(NULL,p,NULL))
1613 strcpy(mget_mask,cur_dir);
1614 if(mget_mask[strlen(mget_mask)-1]!='\\')
1615 strcat(mget_mask,"\\");
1618 strcpy(mget_mask,p);
1620 strcat(mget_mask,p);
1621 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1626 strcpy(mget_mask,cur_dir);
1627 if(mget_mask[strlen(mget_mask)-1]!='\\')
1628 strcat(mget_mask,"\\");
1629 strcat(mget_mask,"*");
1630 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1634 /****************************************************************************
1635 make a directory of name "name"
1636 ****************************************************************************/
1637 static BOOL do_mkdir(char *name)
1640 char *inbuf,*outbuf;
1642 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1643 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1645 if (!inbuf || !outbuf)
1647 DEBUG(0,("out of memory\n"));
1651 bzero(outbuf,smb_size);
1652 set_message(outbuf,0,2 + strlen(name),True);
1654 CVAL(outbuf,smb_com) = SMBmkdir;
1655 SSVAL(outbuf,smb_tid,cnum);
1656 cli_setup_pkt(outbuf);
1659 p = smb_buf(outbuf);
1663 send_smb(Client,outbuf);
1664 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1666 if (CVAL(inbuf,smb_rcls) != 0)
1668 DEBUG(0,("%s making remote directory %s\n",
1669 smb_errstr(inbuf),CNV_LANG(name)));
1671 free(inbuf);free(outbuf);
1675 free(inbuf);free(outbuf);
1680 /****************************************************************************
1682 ****************************************************************************/
1683 static void cmd_mkdir(char *inbuf,char *outbuf)
1689 strcpy(mask,cur_dir);
1691 if (!next_token(NULL,p,NULL))
1694 DEBUG(0,("mkdir <dirname>\n"));
1706 trim_string(ddir,".",NULL);
1707 p = strtok(ddir,"/\\");
1711 if (!chkpath(ddir2,False))
1716 p = strtok(NULL,"/\\");
1724 /*******************************************************************
1725 write to a file using writebraw
1726 ********************************************************************/
1727 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1732 bzero(outbuf,smb_size);
1733 bzero(inbuf,smb_size);
1734 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1736 CVAL(outbuf,smb_com) = SMBwritebraw;
1737 SSVAL(outbuf,smb_tid,cnum);
1738 cli_setup_pkt(outbuf);
1740 SSVAL(outbuf,smb_vwv0,fnum);
1741 SSVAL(outbuf,smb_vwv1,n);
1742 SIVAL(outbuf,smb_vwv3,pos);
1743 SSVAL(outbuf,smb_vwv7,1);
1745 send_smb(Client,outbuf);
1747 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1750 _smb_setlen(buf-4,n); /* HACK! XXXX */
1752 if (write_socket(Client,buf-4,n+4) != n+4)
1755 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1756 DEBUG(0,("Error writing remote file (2)\n"));
1759 return(SVAL(inbuf,smb_vwv0));
1764 /*******************************************************************
1766 ********************************************************************/
1767 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1771 if (writebraw_supported && n > (max_xmit-200))
1772 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1774 bzero(outbuf,smb_size);
1775 bzero(inbuf,smb_size);
1776 set_message(outbuf,5,n + 3,True);
1778 CVAL(outbuf,smb_com) = SMBwrite;
1779 SSVAL(outbuf,smb_tid,cnum);
1780 cli_setup_pkt(outbuf);
1782 SSVAL(outbuf,smb_vwv0,fnum);
1783 SSVAL(outbuf,smb_vwv1,n);
1784 SIVAL(outbuf,smb_vwv2,pos);
1785 SSVAL(outbuf,smb_vwv4,0);
1786 CVAL(smb_buf(outbuf),0) = 1;
1787 SSVAL(smb_buf(outbuf),1,n);
1789 memcpy(smb_buf(outbuf)+3,buf,n);
1791 send_smb(Client,outbuf);
1792 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1794 if (CVAL(inbuf,smb_rcls) != 0) {
1795 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1798 return(SVAL(inbuf,smb_vwv0));
1803 /****************************************************************************
1805 ****************************************************************************/
1806 static void do_put(char *rname,char *lname,file_info *finfo)
1812 char *inbuf,*outbuf;
1813 time_t close_time = finfo->mtime;
1815 static int maxwrite=0;
1817 struct timeval tp_start;
1818 GetTimeOfDay(&tp_start);
1820 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1821 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1823 if (!inbuf || !outbuf)
1825 DEBUG(0,("out of memory\n"));
1829 bzero(outbuf,smb_size);
1830 set_message(outbuf,3,2 + strlen(rname),True);
1832 if (finfo->mtime == 0 || finfo->mtime == -1)
1833 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1835 CVAL(outbuf,smb_com) = SMBcreate;
1836 SSVAL(outbuf,smb_tid,cnum);
1837 cli_setup_pkt(outbuf);
1839 SSVAL(outbuf,smb_vwv0,finfo->mode);
1840 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1842 p = smb_buf(outbuf);
1846 send_smb(Client,outbuf);
1847 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1849 if (CVAL(inbuf,smb_rcls) != 0)
1851 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1853 free(inbuf);free(outbuf);if (buf) free(buf);
1857 f = fopen(lname,"r");
1861 DEBUG(0,("Error opening local file %s\n",lname));
1862 free(inbuf);free(outbuf);
1867 fnum = SVAL(inbuf,smb_vwv0);
1868 if (finfo->size < 0)
1869 finfo->size = file_size(lname);
1871 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1874 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1876 while (nread < finfo->size)
1881 n = MIN(n,finfo->size - nread);
1883 buf = (char *)Realloc(buf,n+4);
1885 fseek(f,nread,SEEK_SET);
1886 if ((n = readfile(buf+4,1,n,f)) < 1)
1888 DEBUG(0,("Error reading local file\n"));
1892 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1896 DEBUG(0,("Error writing file\n"));
1909 bzero(outbuf,smb_size);
1910 set_message(outbuf,3,0,True);
1911 CVAL(outbuf,smb_com) = SMBclose;
1912 SSVAL(outbuf,smb_tid,cnum);
1913 cli_setup_pkt(outbuf);
1915 SSVAL(outbuf,smb_vwv0,fnum);
1916 put_dos_date3(outbuf,smb_vwv1,close_time);
1918 send_smb(Client,outbuf);
1919 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1921 if (CVAL(inbuf,smb_rcls) != 0)
1923 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1925 free(inbuf);free(outbuf);
1932 free(inbuf);free(outbuf);
1936 struct timeval tp_end;
1939 GetTimeOfDay(&tp_end);
1941 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1942 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1943 put_total_time_ms += this_time;
1944 put_total_size += finfo->size;
1946 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1947 finfo->size / (1.024*this_time + 1.0e-4),
1948 put_total_size / (1.024*put_total_time_ms)));
1954 /****************************************************************************
1956 ****************************************************************************/
1957 static void cmd_put(char *dum_in, char *dum_out)
1966 strcpy(rname,cur_dir);
1970 if (!next_token(NULL,p,NULL))
1972 DEBUG(0,("put <filename>\n"));
1977 if (next_token(NULL,p,NULL))
1980 strcat(rname,lname);
1982 dos_clean_name(rname);
1986 if (!file_exist(lname,&st)) {
1987 DEBUG(0,("%s does not exist\n",lname));
1990 finfo.mtime = st.st_mtime;
1993 do_put(rname,lname,&finfo);
1996 /****************************************************************************
1997 seek in a directory/file list until you get something that doesn't start with
1999 ****************************************************************************/
2000 static BOOL seek_list(FILE *f,char *name)
2005 if (fscanf(f,"%s",s) != 1) return(False);
2006 trim_string(s,"./",NULL);
2007 if (strncmp(s,name,strlen(name)) != 0)
2018 /****************************************************************************
2019 set the file selection mask
2020 ****************************************************************************/
2021 static void cmd_select(char *dum_in, char *dum_out)
2023 strcpy(fileselection,"");
2024 next_token(NULL,fileselection,NULL);
2028 /****************************************************************************
2030 ****************************************************************************/
2031 static void cmd_mput(char *dum_in, char *dum_out)
2042 while (next_token(NULL,p,NULL))
2049 sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2051 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2053 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2056 f = fopen(tmpname,"r");
2063 if (fscanf(f,"%s",lname) != 1) break;
2064 trim_string(lname,"./",NULL);
2068 /* check if it's a directory */
2069 if (directory_exist(lname,&st))
2071 if (!recurse) continue;
2072 sprintf(quest,"Put directory %s? ",lname);
2073 if (prompt && !yesno(quest))
2076 if (!seek_list(f,lname))
2081 strcpy(rname,cur_dir);
2082 strcat(rname,lname);
2083 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2085 if (!seek_list(f,lname))
2094 sprintf(quest,"Put file %s? ",lname);
2095 if (prompt && !yesno(quest)) continue;
2097 strcpy(rname,cur_dir);
2098 strcat(rname,lname);
2102 /* null size so do_put knows to ignore it */
2105 /* set the date on the file */
2106 finfo.mtime = st.st_mtime;
2108 do_put(rname,lname,&finfo);
2115 /****************************************************************************
2117 ****************************************************************************/
2118 static void do_cancel(int job)
2120 char *rparam = NULL;
2126 bzero(param,sizeof(param));
2129 SSVAL(p,0,81); /* DosPrintJobDel() */
2132 p = skip_string(p,1);
2134 p = skip_string(p,1);
2138 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2144 int res = SVAL(rparam,0);
2147 printf("Job %d cancelled\n",job);
2149 printf("Error %d calcelling job %d\n",res,job);
2153 printf("Server refused cancel request\n");
2155 if (rparam) free(rparam);
2156 if (rdata) free(rdata);
2162 /****************************************************************************
2164 ****************************************************************************/
2165 static void cmd_cancel(char *inbuf,char *outbuf )
2170 if (!connect_as_printer)
2172 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2173 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2176 if (!next_token(NULL,buf,NULL)) {
2177 printf("cancel <jobid> ...\n");
2183 } while (next_token(NULL,buf,NULL));
2189 /****************************************************************************
2191 ****************************************************************************/
2192 static void cmd_print(char *inbuf,char *outbuf )
2201 if (!connect_as_printer)
2203 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2204 DEBUG(0,("Trying to print without -P may fail\n"));
2207 if (!next_token(NULL,lname,NULL))
2209 DEBUG(0,("print <filename>\n"));
2213 strcpy(rname,lname);
2214 p = strrchr(rname,'/');
2219 strcpy(rname,tname);
2222 if ((int)strlen(rname) > 14)
2225 if (strequal(lname,"-"))
2228 strcpy(rname,"stdin");
2231 dos_clean_name(rname);
2233 bzero(outbuf,smb_size);
2234 set_message(outbuf,2,2 + strlen(rname),True);
2236 CVAL(outbuf,smb_com) = SMBsplopen;
2237 SSVAL(outbuf,smb_tid,cnum);
2238 cli_setup_pkt(outbuf);
2240 SSVAL(outbuf,smb_vwv0,0);
2241 SSVAL(outbuf,smb_vwv1,printmode);
2243 p = smb_buf(outbuf);
2247 send_smb(Client,outbuf);
2248 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2250 if (CVAL(inbuf,smb_rcls) != 0)
2252 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2257 f = fopen(lname,"r");
2260 DEBUG(0,("Error opening local file %s\n",lname));
2265 fnum = SVAL(inbuf,smb_vwv0);
2267 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2273 bzero(outbuf,smb_size);
2274 set_message(outbuf,1,3,True);
2276 /* for some strange reason the OS/2 print server can't handle large
2277 packets when printing. weird */
2278 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2281 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2283 n = readfile(smb_buf(outbuf)+3,1,n,f);
2286 DEBUG(0,("read gave %d\n",n));
2290 smb_setlen(outbuf,smb_len(outbuf) + n);
2292 CVAL(outbuf,smb_com) = SMBsplwr;
2293 SSVAL(outbuf,smb_tid,cnum);
2294 cli_setup_pkt(outbuf);
2296 SSVAL(outbuf,smb_vwv0,fnum);
2297 SSVAL(outbuf,smb_vwv1,n+3);
2298 CVAL(smb_buf(outbuf),0) = 1;
2299 SSVAL(smb_buf(outbuf),1,n);
2301 send_smb(Client,outbuf);
2302 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2304 if (CVAL(inbuf,smb_rcls) != 0)
2306 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2313 DEBUG(2,("%d bytes printed\n",nread));
2315 bzero(outbuf,smb_size);
2316 set_message(outbuf,1,0,True);
2317 CVAL(outbuf,smb_com) = SMBsplclose;
2318 SSVAL(outbuf,smb_tid,cnum);
2319 cli_setup_pkt(outbuf);
2321 SSVAL(outbuf,smb_vwv0,fnum);
2323 send_smb(Client,outbuf);
2324 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2326 if (CVAL(inbuf,smb_rcls) != 0)
2328 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2338 /****************************************************************************
2339 show a print queue - this is deprecated as it uses the old smb that
2340 has limited support - the correct call is the cmd_p_queue_4() after this.
2341 ****************************************************************************/
2342 static void cmd_queue(char *inbuf,char *outbuf )
2347 bzero(outbuf,smb_size);
2348 set_message(outbuf,2,0,True);
2350 CVAL(outbuf,smb_com) = SMBsplretq;
2351 SSVAL(outbuf,smb_tid,cnum);
2352 cli_setup_pkt(outbuf);
2354 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2355 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2357 send_smb(Client,outbuf);
2358 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2360 if (CVAL(inbuf,smb_rcls) != 0)
2362 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2366 count = SVAL(inbuf,smb_vwv0);
2367 p = smb_buf(inbuf) + 3;
2370 DEBUG(0,("No entries in the print queue\n"));
2377 DEBUG(0,("Job Name Size Status\n"));
2383 case 0x01: sprintf(status,"held or stopped"); break;
2384 case 0x02: sprintf(status,"printing"); break;
2385 case 0x03: sprintf(status,"awaiting print"); break;
2386 case 0x04: sprintf(status,"in intercept"); break;
2387 case 0x05: sprintf(status,"file had error"); break;
2388 case 0x06: sprintf(status,"printer error"); break;
2389 default: sprintf(status,"unknown"); break;
2392 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2393 SVAL(p,5),p+12,IVAL(p,7),status));
2401 /****************************************************************************
2402 show information about a print queue
2403 ****************************************************************************/
2404 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2406 char *rparam = NULL;
2413 if (!connect_as_printer)
2415 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2416 DEBUG(0,("Trying to print without -P may fail\n"));
2419 bzero(param,sizeof(param));
2422 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2424 strcpy(p,"zWrLeh"); /* parameter description? */
2425 p = skip_string(p,1);
2426 strcpy(p,"WWzWWDDzz"); /* returned data format */
2427 p = skip_string(p,1);
2428 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2429 p = skip_string(p,1);
2430 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2431 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2433 strcpy(p,""); /* subformat */
2434 p = skip_string(p,1);
2436 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2437 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2444 result_code = SVAL(rparam,0);
2445 converter = SVAL(rparam,2); /* conversion factor */
2447 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2449 if (result_code == 0) /* if no error, */
2459 char PrinterName[20];
2461 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2462 strlower(PrinterName); /* in lower case */
2464 p = rdata; /* received data */
2465 for( i = 0; i < SVAL(rparam,4); ++i)
2468 Priority = SVAL(p,2);
2469 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2471 Priority = SVAL(p,2);
2472 JobTime = make_unix_date3( p + 12);
2473 JobTimeStr = asctime(LocalTime( &JobTime));
2475 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2478 printf("%s-%u %s priority %u %s %s %u bytes\n",
2479 PrinterName, JobId, UserName,
2480 Priority, JobTimeStr, JobName, Size);
2482 #if 0 /* DEBUG code */
2483 printf("Job Id: \"%u\"\n", SVAL(p,0));
2484 printf("Priority: \"%u\"\n", SVAL(p,2));
2486 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2487 printf("Position: \"%u\"\n", SVAL(p,8));
2488 printf("Status: \"%u\"\n", SVAL(p,10));
2490 JobTime = make_unix_date3( p + 12);
2491 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2492 printf("date: \"%u\"\n", SVAL(p,12));
2494 printf("Size: \"%u\"\n", SVAL(p,16));
2495 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2496 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2497 #endif /* DEBUG CODE */
2502 else /* cli_call_api() failed */
2504 printf("Failed, error = %d\n", result_code);
2507 /* If any parameters or data were returned, free the storage. */
2508 if(rparam) free(rparam);
2509 if(rdata) free(rdata);
2514 /****************************************************************************
2515 show information about a print queue
2516 ****************************************************************************/
2517 static void cmd_qinfo(char *inbuf,char *outbuf )
2519 char *rparam = NULL;
2526 bzero(param,sizeof(param));
2529 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2531 strcpy(p,"zWrLh"); /* parameter description? */
2532 p = skip_string(p,1);
2533 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2534 p = skip_string(p,1);
2535 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2536 p = skip_string(p,1);
2537 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2538 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2540 strcpy(p,""); /* subformat */
2541 p = skip_string(p,1);
2543 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2544 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2551 result_code = SVAL(rparam,0);
2552 converter = SVAL(rparam,2); /* conversion factor */
2554 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2556 if (result_code == 0) /* if no error, */
2558 p = rdata; /* received data */
2560 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2561 printf("Priority: %u\n", SVAL(p,4) );
2562 printf("Start time: %u\n", SVAL(p,6) );
2563 printf("Until time: %u\n", SVAL(p,8) );
2564 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2565 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2566 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2567 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2568 printf("Status: %u\n", SVAL(p,28) );
2569 printf("Jobs: %u\n", SVAL(p,30) );
2570 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2571 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2573 /* Dump the driver data */
2578 ddptr = rdata + SVAL(p,40) - converter;
2579 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2580 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2582 for(x=8; x < count; x+=16)
2584 for(y=0; y < 16; y++)
2587 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2591 for(y=0; y < 16 && (x+y) < count; y++)
2593 c = CVAL(ddptr,(x+y));
2599 fputc('\n', stdout);
2605 else /* cli_call_api() failed */
2607 printf("Failed, error = %d\n", result_code);
2610 /* If any parameters or data were returned, free the storage. */
2611 if(rparam) free(rparam);
2612 if(rdata) free(rdata);
2617 /****************************************************************************
2619 ****************************************************************************/
2620 static void do_del(file_info *finfo)
2623 char *inbuf,*outbuf;
2626 strcpy(mask,cur_dir);
2627 strcat(mask,finfo->name);
2629 if (finfo->mode & aDIR)
2632 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2633 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2635 if (!inbuf || !outbuf)
2637 DEBUG(0,("out of memory\n"));
2641 bzero(outbuf,smb_size);
2642 set_message(outbuf,1,2 + strlen(mask),True);
2644 CVAL(outbuf,smb_com) = SMBunlink;
2645 SSVAL(outbuf,smb_tid,cnum);
2646 cli_setup_pkt(outbuf);
2648 SSVAL(outbuf,smb_vwv0,0);
2650 p = smb_buf(outbuf);
2654 send_smb(Client,outbuf);
2655 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2657 if (CVAL(inbuf,smb_rcls) != 0)
2658 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2660 free(inbuf);free(outbuf);
2664 /****************************************************************************
2666 ****************************************************************************/
2667 static void cmd_del(char *inbuf,char *outbuf )
2671 int attribute = aSYSTEM | aHIDDEN;
2676 strcpy(mask,cur_dir);
2678 if (!next_token(NULL,buf,NULL))
2680 DEBUG(0,("del <filename>\n"));
2685 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False,False);
2689 /****************************************************************************
2691 ****************************************************************************/
2692 static void cmd_rmdir(char *inbuf,char *outbuf )
2698 strcpy(mask,cur_dir);
2700 if (!next_token(NULL,buf,NULL))
2702 DEBUG(0,("rmdir <dirname>\n"));
2707 bzero(outbuf,smb_size);
2708 set_message(outbuf,0,2 + strlen(mask),True);
2710 CVAL(outbuf,smb_com) = SMBrmdir;
2711 SSVAL(outbuf,smb_tid,cnum);
2712 cli_setup_pkt(outbuf);
2715 p = smb_buf(outbuf);
2719 send_smb(Client,outbuf);
2720 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2722 if (CVAL(inbuf,smb_rcls) != 0)
2724 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2730 /****************************************************************************
2732 ****************************************************************************/
2733 static void cmd_rename(char *inbuf,char *outbuf )
2739 strcpy(src,cur_dir);
2740 strcpy(dest,cur_dir);
2742 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2744 DEBUG(0,("rename <src> <dest>\n"));
2750 bzero(outbuf,smb_size);
2751 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2753 CVAL(outbuf,smb_com) = SMBmv;
2754 SSVAL(outbuf,smb_tid,cnum);
2755 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2756 cli_setup_pkt(outbuf);
2758 p = smb_buf(outbuf);
2761 p = skip_string(p,1);
2765 send_smb(Client,outbuf);
2766 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2768 if (CVAL(inbuf,smb_rcls) != 0)
2770 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2777 /****************************************************************************
2778 toggle the prompt flag
2779 ****************************************************************************/
2780 static void cmd_prompt(char *dum_in, char *dum_out)
2783 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2787 /****************************************************************************
2788 set the newer than time
2789 ****************************************************************************/
2790 static void cmd_newer(char *dum_in, char *dum_out)
2796 ok = next_token(NULL,buf,NULL);
2797 if (ok && (sys_stat(buf,&sbuf) == 0))
2799 newer_than = sbuf.st_mtime;
2800 DEBUG(1,("Getting files newer than %s",
2801 asctime(LocalTime(&newer_than))));
2806 if (ok && newer_than == 0)
2807 DEBUG(0,("Error setting newer-than time\n"));
2810 /****************************************************************************
2811 set the archive level
2812 ****************************************************************************/
2813 static void cmd_archive(char *dum_in, char *dum_out)
2817 if (next_token(NULL,buf,NULL)) {
2818 archive_level = atoi(buf);
2820 DEBUG(0,("Archive level is %d\n",archive_level));
2823 /****************************************************************************
2824 toggle the lowercaseflag
2825 ****************************************************************************/
2826 static void cmd_lowercase(char *dum_in, char *dum_out)
2828 lowercase = !lowercase;
2829 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2835 /****************************************************************************
2836 toggle the recurse flag
2837 ****************************************************************************/
2838 static void cmd_recurse(char *dum_in, char *dum_out)
2841 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2844 /****************************************************************************
2845 toggle the translate flag
2846 ****************************************************************************/
2847 static void cmd_translate(char *dum_in, char *dum_out)
2849 translation = !translation;
2850 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2851 translation?"on":"off"));
2855 /****************************************************************************
2856 do a printmode command
2857 ****************************************************************************/
2858 static void cmd_printmode(char *dum_in, char *dum_out)
2863 if (next_token(NULL,buf,NULL))
2865 if (strequal(buf,"text"))
2869 if (strequal(buf,"graphics"))
2872 printmode = atoi(buf);
2879 strcpy(mode,"text");
2882 strcpy(mode,"graphics");
2885 sprintf(mode,"%d",printmode);
2889 DEBUG(2,("the printmode is now %s\n",mode));
2892 /****************************************************************************
2894 ****************************************************************************/
2895 static void cmd_lcd(char *dum_in, char *dum_out)
2900 if (next_token(NULL,buf,NULL))
2902 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2906 /****************************************************************************
2907 try and browse available connections on a host
2908 ****************************************************************************/
2909 static BOOL browse_host(BOOL sort)
2912 /* If strcasecmp is already defined, remove it. */
2915 #endif /* strcasecmp */
2916 #define strcasecmp StrCaseCmp
2917 #endif /* NOSTRCASECMP */
2919 char *rparam = NULL;
2926 /* now send a SMBtrans command with api RNetShareEnum */
2928 SSVAL(p,0,0); /* api number */
2931 p = skip_string(p,1);
2933 p = skip_string(p,1);
2935 SSVAL(p,2,BUFFER_SIZE);
2938 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2944 int res = SVAL(rparam,0);
2945 int converter=SVAL(rparam,2);
2947 BOOL long_share_name=False;
2951 count=SVAL(rparam,4);
2956 printf("\n\tSharename Type Comment\n");
2957 printf("\t--------- ---- -------\n");
2961 qsort(p,count,20,QSORT_CAST strcasecmp);
2963 for (i=0;i<count;i++)
2966 int type = SVAL(p,14);
2967 int comment_offset = IVAL(p,16) & 0xFFFF;
2973 case STYPE_DISKTREE:
2974 strcpy(typestr,"Disk"); break;
2976 strcpy(typestr,"Printer"); break;
2978 strcpy(typestr,"Device"); break;
2980 strcpy(typestr,"IPC"); break;
2983 printf("\t%-15.15s%-10.10s%s\n",
2986 comment_offset?rdata+comment_offset-converter:"");
2988 if (strlen(sname)>8) long_share_name=True;
2993 if (long_share_name) {
2994 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
2999 if (rparam) free(rparam);
3000 if (rdata) free(rdata);
3006 /****************************************************************************
3007 get some server info
3008 ****************************************************************************/
3009 static void server_info(void)
3011 char *rparam = NULL;
3017 bzero(param,sizeof(param));
3020 SSVAL(p,0,63); /* NetServerGetInfo()? */
3023 p = skip_string(p,1);
3024 strcpy(p,"zzzBBzz");
3025 p = skip_string(p,1);
3026 SSVAL(p,0,10); /* level 10 */
3030 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3036 int res = SVAL(rparam,0);
3037 int converter=SVAL(rparam,2);
3043 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3044 rdata+SVAL(p,0)-converter,
3045 rdata+SVAL(p,4)-converter,
3046 rdata+SVAL(p,8)-converter,
3047 rdata+SVAL(p,14)-converter);
3051 if (rparam) free(rparam);
3052 if (rdata) free(rdata);
3058 /****************************************************************************
3059 try and browse available connections on a host
3060 ****************************************************************************/
3061 static BOOL list_servers(char *wk_grp)
3063 char *rparam = NULL;
3071 BOOL generic_request = False;
3074 if (strequal(wk_grp,"WORKGROUP")) {
3075 /* we won't specify a workgroup */
3076 generic_request = True;
3079 /* now send a SMBtrans command with api ServerEnum? */
3081 SSVAL(p,0,0x68); /* api number */
3084 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3085 p = skip_string(p,1);
3087 strcpy(p,"B16BBDz");
3089 p = skip_string(p,1);
3091 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3097 if (!generic_request) {
3099 p = skip_string(p,1);
3102 /* first ask for a list of servers in this workgroup */
3103 SIVAL(svtype_p,0,SV_TYPE_ALL);
3105 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3106 8, BUFFER_SIZE - SAFETY_MARGIN,
3111 int res = SVAL(rparam,0);
3112 int converter=SVAL(rparam,2);
3117 count=SVAL(rparam,4);
3120 printf("\n\nThis machine has a browse list:\n");
3121 printf("\n\tServer Comment\n");
3122 printf("\t--------- -------\n");
3125 for (i=0;i<count;i++) {
3127 int comment_offset = IVAL(p2,22) & 0xFFFF;
3128 printf("\t%-16.16s %s\n",
3130 comment_offset?rdata+comment_offset-converter:"");
3138 if (rparam) {free(rparam); rparam = NULL;}
3139 if (rdata) {free(rdata); rdata = NULL;}
3141 /* now ask for a list of workgroups */
3142 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3144 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3145 8, BUFFER_SIZE - SAFETY_MARGIN,
3150 int res = SVAL(rparam,0);
3151 int converter=SVAL(rparam,2);
3156 count=SVAL(rparam,4);
3159 printf("\n\nThis machine has a workgroup list:\n");
3160 printf("\n\tWorkgroup Master\n");
3161 printf("\t--------- -------\n");
3164 for (i=0;i<count;i++) {
3166 int comment_offset = IVAL(p2,22) & 0xFFFF;
3167 printf("\t%-16.16s %s\n",
3169 comment_offset?rdata+comment_offset-converter:"");
3177 if (rparam) free(rparam);
3178 if (rdata) free(rdata);
3184 /* This defines the commands supported by this client */
3188 void (*fn)(char *, char *);
3192 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3193 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3194 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3195 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3196 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3197 {"get",cmd_get,"<remote name> [local name] get a file"},
3198 {"mget",cmd_mget,"<mask> get all the matching files"},
3199 {"put",cmd_put,"<local name> [remote name] put a file"},
3200 {"mput",cmd_mput,"<mask> put all matching files"},
3201 {"rename",cmd_rename,"<src> <dest> rename some files"},
3202 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3203 {"mask",cmd_select,"<mask> mask all filenames against this"},
3204 {"del",cmd_del,"<mask> delete all matching files"},
3205 {"rm",cmd_del,"<mask> delete all matching files"},
3206 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3207 {"md",cmd_mkdir,"<directory> make a directory"},
3208 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
3209 {"rd",cmd_rmdir,"<directory> remove a directory"},
3210 {"pq",cmd_p_queue_4,"enumerate the print queue"},
3211 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
3212 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
3213 {"translate",cmd_translate,"toggle text translation for printing"},
3214 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
3215 {"print",cmd_print,"<file name> print a file"},
3216 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
3217 {"queue",cmd_queue,"show the print queue"},
3218 {"qinfo",cmd_qinfo,"show print queue information"},
3219 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
3220 {"quit",cli_send_logout,"logoff the server"},
3221 {"q",cli_send_logout,"logoff the server"},
3222 {"exit",cli_send_logout,"logoff the server"},
3223 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
3224 {"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"},
3225 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3226 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
3227 {"tarmode",cmd_tarmode,
3228 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3229 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
3230 {"help",cmd_help,"[command] give help on a command"},
3231 {"?",cmd_help,"[command] give help on a command"},
3232 {"!",NULL,"run a shell command on the local system"},
3237 /*******************************************************************
3238 lookup a command string in the list of commands, including
3240 ******************************************************************/
3241 static int process_tok(fstring tok)
3243 int i = 0, matches = 0;
3245 int tok_len = strlen(tok);
3247 while (commands[i].fn != NULL)
3249 if (strequal(commands[i].name,tok))
3255 else if (strnequal(commands[i].name, tok, tok_len))
3265 else if (matches == 1)
3271 /****************************************************************************
3273 ****************************************************************************/
3274 void cmd_help(char *dum_in, char *dum_out)
3279 if (next_token(NULL,buf,NULL))
3281 if ((i = process_tok(buf)) >= 0)
3282 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3285 while (commands[i].description)
3287 for (j=0; commands[i].description && (j<5); j++) {
3288 DEBUG(0,("%-15s",commands[i].name));
3295 /****************************************************************************
3296 wait for keyboard activity, swallowing network packets
3297 ****************************************************************************/
3299 static char wait_keyboard(char *buffer)
3301 static void wait_keyboard(char *buffer)
3306 struct timeval timeout;
3316 FD_SET(Client,&fds);
3318 FD_SET(fileno(stdin),&fds);
3321 timeout.tv_sec = 20;
3322 timeout.tv_usec = 0;
3326 selrtn = sys_select(&fds,&timeout);
3329 if (FD_ISSET(fileno(stdin),&fds))
3336 set_blocking(fileno(stdin), False);
3337 readret = read_data( fileno(stdin), &ch, 1);
3338 set_blocking(fileno(stdin), True);
3341 if (errno != EAGAIN)
3343 /* should crash here */
3344 DEBUG(1,("readchar stdin failed\n"));
3347 else if (readret != 0)
3354 /* We deliberately use receive_smb instead of
3355 client_receive_smb as we want to receive
3356 session keepalives and then drop them here.
3358 if (FD_ISSET(Client,&fds))
3359 receive_smb(Client,buffer,0);
3366 chkpath("\\",False);
3369 chkpath("\\",False);
3375 /****************************************************************************
3376 process commands from the client
3377 ****************************************************************************/
3378 static BOOL process(char *base_directory)
3384 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3385 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3387 if ((InBuffer == NULL) || (OutBuffer == NULL))
3390 bzero(OutBuffer,smb_size);
3392 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3395 if (*base_directory) do_cd(base_directory);
3398 if (cmd[0] != '\0') while (cmd[0] != '\0')
3404 if ((p = strchr(cmd, ';')) == 0)
3406 strncpy(line, cmd, 999);
3412 if (p - cmd > 999) p = cmd + 999;
3413 strncpy(line, cmd, p - cmd);
3414 line[p - cmd] = '\0';
3418 /* input language code to internal one */
3421 /* and get the first part of the command */
3424 if (!next_token(&ptr,tok,NULL)) continue;
3427 if ((i = process_tok(tok)) >= 0)
3428 commands[i].fn(InBuffer,OutBuffer);
3430 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3432 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3434 else while (!feof(stdin))
3439 bzero(OutBuffer,smb_size);
3441 /* display a prompt */
3442 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3446 line[0] = wait_keyboard(InBuffer);
3447 /* this might not be such a good idea... */
3448 if ( line[0] == EOF)
3451 wait_keyboard(InBuffer);
3454 /* and get a response */
3456 fgets( &line[1],999, stdin);
3458 if (!fgets(line,1000,stdin))
3462 /* input language code to internal one */
3465 /* special case - first char is ! */
3472 /* and get the first part of the command */
3475 if (!next_token(&ptr,tok,NULL)) continue;
3478 if ((i = process_tok(tok)) >= 0)
3479 commands[i].fn(InBuffer,OutBuffer);
3481 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3483 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3486 cli_send_logout(InBuffer,OutBuffer);
3490 /****************************************************************************
3491 usage on the program
3492 ****************************************************************************/
3493 static void usage(char *pname)
3495 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3498 DEBUG(0,("\nVersion %s\n",VERSION));
3499 DEBUG(0,("\t-p port connect to the specified port\n"));
3500 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3501 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3502 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3503 DEBUG(0,("\t-N don't ask for a password\n"));
3504 DEBUG(0,("\t-P connect to service as a printer\n"));
3505 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3506 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3507 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3508 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3509 DEBUG(0,("\t-R name resolve order use these name resolution services only\n"));
3510 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3511 DEBUG(0,("\t-U username set the network username\n"));
3512 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3513 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3514 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3515 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
3516 DEBUG(0,("\t-D directory start from directory\n"));
3520 /****************************************************************************
3522 ****************************************************************************/
3523 int main(int argc,char *argv[])
3525 fstring base_directory;
3526 char *pname = argv[0];
3527 int port = SMB_PORT;
3530 extern char *optarg;
3533 BOOL message = False;
3534 BOOL nt_domain_logon = False;
3535 extern char tar_type;
3536 static pstring servicesf = CONFIGFILE;
3538 pstring new_name_resolve_order;
3540 int save_debuglevel = -1;
3543 strcpy(term_code, KANJI);
3549 *base_directory = 0;
3551 *new_name_resolve_order = 0;
3555 setup_logging(pname,True);
3558 charset_initialise();
3569 strcpy(username,getenv("USER"));
3571 /* modification to support userid%passwd syntax in the USER var
3572 25.Aug.97, jdblair@uab.edu */
3574 if ((p=strchr(username,'%')))
3577 strcpy(password,p+1);
3579 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3584 /* modification to support PASSWD environmental var
3585 25.Aug.97, jdblair@uab.edu */
3587 if (getenv("PASSWD"))
3588 strcpy(password,getenv("PASSWD"));
3590 if (*username == 0 && getenv("LOGNAME"))
3592 strcpy(username,getenv("LOGNAME"));
3602 if (*argv[1] != '-')
3605 strcpy(service,argv[1]);
3606 /* Convert any '/' characters in the service name to '\' characters */
3607 string_replace( service, '/','\\');
3611 if (count_chars(service,'\\') < 3)
3614 printf("\n%s: Not enough '\\' characters in service\n",service);
3619 if (count_chars(service,'\\') > 3)
3622 printf("\n%s: Too many '\\' characters in service\n",service);
3627 if (argc > 1 && (*argv[1] != '-'))
3630 strcpy(password,argv[1]);
3631 memset(argv[1],'X',strlen(argv[1]));
3638 getopt(argc, argv,"s:B:O:R:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
3642 max_protocol = interpret_protocol(optarg,max_protocol);
3645 strcpy(user_socket_options,optarg);
3648 pstrcpy(new_name_resolve_order, optarg);
3651 strcpy(desthost,optarg);
3653 nt_domain_logon = True;
3656 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3657 strcpy(desthost,optarg);
3662 iface_set_default(NULL,optarg,NULL);
3665 strcpy(base_directory,optarg);
3668 if (!tar_parseargs(argc, argv, optarg, optind)) {
3674 strcpy(scope,optarg);
3678 strcpy(query_host,optarg);
3683 strcpy(username,optarg);
3684 if ((lp=strchr(username,'%')))
3687 strcpy(password,lp+1);
3689 memset(strchr(optarg,'%')+1,'X',strlen(password));
3695 strcpy(workgroup,optarg);
3702 dest_ip = *interpret_addr2(optarg);
3703 if (zero_ip(dest_ip)) exit(1);
3708 strcpy(global_myname,optarg);
3715 connect_as_printer = True;
3719 save_debuglevel = DEBUGLEVEL = 10000;
3721 save_debuglevel = DEBUGLEVEL = atoi(optarg);
3724 sprintf(debugf,"%s.client",optarg);
3727 port = atoi(optarg);
3738 strcpy(servicesf, optarg);
3741 strcpy(term_code, optarg);
3748 if (!tar_type && !*query_host && !*service && !message)
3755 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
3757 if(!get_myname(myhostname,NULL))
3759 DEBUG(0,("Failed to get my hostname.\n"));
3762 if (!lp_load(servicesf,True,False,False)) {
3763 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3767 * We need to reset the global debuglevel here, as
3768 * lp_load will reset it from smb.conf.
3771 if(save_debuglevel != -1)
3772 DEBUGLEVEL = save_debuglevel;
3774 codepage_initialise(lp_client_code_page());
3776 interpret_coding_system(term_code);
3778 if (*workgroup == 0)
3779 strcpy(workgroup,lp_workgroup());
3782 get_myname((*global_myname)?NULL:global_myname,NULL);
3783 strupper(global_myname);
3785 if(*new_name_resolve_order)
3786 lp_set_name_resolve_order(new_name_resolve_order);
3791 if (cli_open_sockets(port)) {
3792 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3793 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3796 if ((InBuffer == NULL) || (OutBuffer == NULL))
3799 bzero(OutBuffer,smb_size);
3800 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3803 if (*base_directory) do_cd(base_directory);
3805 ret=process_tar(InBuffer, OutBuffer);
3807 cli_send_logout(InBuffer, OutBuffer);
3814 if (*query_host && !nt_domain_logon)
3817 sprintf(service,"\\\\%s\\IPC$",query_host);
3819 connect_as_ipc = True;
3820 if (cli_open_sockets(port))
3825 if (!cli_send_login(NULL,NULL,True,True,NULL))
3829 if (!browse_host(True)) {
3833 if (!list_servers(workgroup)) {
3835 list_servers(workgroup);
3838 cli_send_logout(NULL,NULL);
3848 if (cli_open_sockets(port))
3850 pstring inbuf,outbuf;
3851 bzero(outbuf,smb_size);
3852 if (!cli_send_session_request(inbuf,outbuf))
3855 send_message(inbuf,outbuf);
3863 if (cli_open_sockets(port))
3865 if (!process(base_directory))