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 = "\\";
34 extern pstring service;
35 extern pstring desthost;
36 extern pstring myname;
37 extern pstring myhostname;
38 extern pstring password;
39 extern pstring username;
40 extern pstring workgroup;
43 extern BOOL connect_as_printer;
44 extern BOOL connect_as_ipc;
45 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)(),BOOL longdir);
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 extern int coding_system;
134 static BOOL setup_term_code (char *code)
137 new = interpret_coding_system (code, UNKNOWN_CODE);
138 if (new != UNKNOWN_CODE) {
144 #define CNV_LANG(s) dos2unix_format(s,False)
145 #define CNV_INPUT(s) unix2dos_format(s,True)
147 /****************************************************************************
148 write to a local file with CR/LF->LF translation if appropriate. return the
149 number taken from the buffer. This may not equal the number written.
150 ****************************************************************************/
151 static int writefile(int f, char *b, int n)
156 return(write(f,b,n));
161 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
165 if (write(f, b, 1) != 1)
176 /****************************************************************************
177 read from a file with LF->CR/LF translation if appropriate. return the
178 number read. read approx n bytes.
179 ****************************************************************************/
180 static int readfile(char *b, int size, int n, FILE *f)
185 if (!translation || (size != 1))
186 return(fread(b,size,n,f));
191 if ((c = getc(f)) == EOF)
196 if (c == '\n') /* change all LFs to CR/LF */
210 /****************************************************************************
211 read from a file with print translation. return the number read. read approx n
213 ****************************************************************************/
214 static int printread(FILE *f,char *b,int n)
218 i = readfile(b,1, n-1,f);
227 /****************************************************************************
228 check for existance of a dir
229 ****************************************************************************/
230 static BOOL chkpath(char *path,BOOL report)
233 pstring inbuf,outbuf;
237 trim_string(path2,NULL,"\\");
238 if (!*path2) *path2 = '\\';
240 bzero(outbuf,smb_size);
241 set_message(outbuf,0,4 + strlen(path2),True);
242 SCVAL(outbuf,smb_com,SMBchkpth);
243 SSVAL(outbuf,smb_tid,cnum);
244 cli_setup_pkt(outbuf);
252 /* this little bit of code can be used to extract NT error codes.
253 Just feed a bunch of "cd foo" commands to smbclient then watch
254 in netmon (tridge) */
256 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
257 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
262 send_smb(Client,outbuf);
263 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
265 if (report && CVAL(inbuf,smb_rcls) != 0)
266 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
268 return(CVAL(inbuf,smb_rcls) == 0);
272 /****************************************************************************
274 ****************************************************************************/
275 static void send_message(char *inbuf,char *outbuf)
282 /* send a SMBsendstrt command */
283 bzero(outbuf,smb_size);
284 set_message(outbuf,0,0,True);
285 CVAL(outbuf,smb_com) = SMBsendstrt;
286 SSVAL(outbuf,smb_tid,cnum);
291 p = skip_string(p,1);
294 p = skip_string(p,1);
296 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
298 send_smb(Client,outbuf);
301 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
303 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
307 grp_id = SVAL(inbuf,smb_vwv0);
309 printf("Connected. Type your message, ending it with a Control-D\n");
311 while (!feof(stdin) && total_len < 1600)
313 int maxlen = MIN(1600 - total_len,127);
320 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
327 CVAL(outbuf,smb_com) = SMBsendtxt;
329 set_message(outbuf,1,l+3,True);
331 SSVAL(outbuf,smb_vwv0,grp_id);
338 send_smb(Client,outbuf);
341 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
343 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
350 if (total_len >= 1600)
351 printf("the message was truncated to 1600 bytes ");
353 printf("sent %d bytes ",total_len);
355 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
357 CVAL(outbuf,smb_com) = SMBsendend;
358 set_message(outbuf,1,0,False);
359 SSVAL(outbuf,smb_vwv0,grp_id);
361 send_smb(Client,outbuf);
364 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
366 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
373 /****************************************************************************
374 check the space on a device
375 ****************************************************************************/
376 static void do_dskattr(void)
378 pstring inbuf,outbuf;
380 bzero(outbuf,smb_size);
381 set_message(outbuf,0,0,True);
382 CVAL(outbuf,smb_com) = SMBdskattr;
383 SSVAL(outbuf,smb_tid,cnum);
384 cli_setup_pkt(outbuf);
386 send_smb(Client,outbuf);
387 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
389 if (CVAL(inbuf,smb_rcls) != 0)
390 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
392 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
393 SVAL(inbuf,smb_vwv0),
394 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
395 SVAL(inbuf,smb_vwv3)));
398 /****************************************************************************
400 ****************************************************************************/
401 static void cmd_pwd(void)
403 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
404 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
408 /****************************************************************************
409 change directory - inner section
410 ****************************************************************************/
411 static void do_cd(char *newdir)
417 /* Save the current directory in case the
418 new directory is invalid */
419 strcpy(saved_dir, cur_dir);
424 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
425 strcat(cur_dir, "\\");
427 dos_clean_name(cur_dir);
428 strcpy(dname,cur_dir);
429 strcat(cur_dir,"\\");
430 dos_clean_name(cur_dir);
432 if (!strequal(cur_dir,"\\"))
433 if (!chkpath(dname,True))
434 strcpy(cur_dir,saved_dir);
436 strcpy(cd_path,cur_dir);
439 /****************************************************************************
441 ****************************************************************************/
442 static void cmd_cd(char *inbuf,char *outbuf)
446 if (next_token(NULL,buf,NULL))
449 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
453 /****************************************************************************
454 display info about a file
455 ****************************************************************************/
456 static void display_finfo(file_info *finfo)
458 if (do_this_one(finfo)) {
459 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
460 DEBUG(0,(" %-30s%7.7s%10d %s",
461 CNV_LANG(finfo->name),
462 attrib_string(finfo->mode),
464 asctime(LocalTime(&t))));
465 dir_total += finfo->size;
470 /****************************************************************************
471 do a directory listing, calling fn on each file found. Use the TRANSACT2
472 call for long filenames
473 ****************************************************************************/
474 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
476 int max_matches = 512;
477 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
482 char *dirlist = NULL;
484 int total_received = 0;
486 char *resp_data=NULL;
487 char *resp_param=NULL;
488 int resp_data_len = 0;
489 int resp_param_len=0;
491 int ff_resume_key = 0;
492 int ff_searchcount=0;
506 if (loop_count > 200)
508 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
514 setup = TRANSACT2_FINDFIRST;
515 SSVAL(param,0,attribute); /* attribute */
516 SSVAL(param,2,max_matches); /* max count */
517 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
518 SSVAL(param,6,info_level);
520 strcpy(param+12,mask);
524 setup = TRANSACT2_FINDNEXT;
525 SSVAL(param,0,ff_dir_handle);
526 SSVAL(param,2,max_matches); /* max count */
527 SSVAL(param,4,info_level);
528 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
529 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
530 strcpy(param+12,mask);
532 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
533 ff_dir_handle,ff_resume_key,ff_lastname,mask));
535 /* ??? original code added 1 pad byte after param */
537 cli_send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
539 0,12+strlen(mask)+1,1,
542 if (!cli_receive_trans_response(inbuf,SMBtrans2,
543 &resp_data_len,&resp_param_len,
544 &resp_data,&resp_param))
546 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
550 /* parse out some important return info */
554 ff_dir_handle = SVAL(p,0);
555 ff_searchcount = SVAL(p,2);
557 ff_lastname = SVAL(p,8);
561 ff_searchcount = SVAL(p,0);
563 ff_lastname = SVAL(p,6);
566 if (ff_searchcount == 0)
569 /* point to the data bytes */
572 /* we might need the lastname for continuations */
579 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
580 /* strcpy(mask,p+ff_lastname+94); */
583 strcpy(mask,p + ff_lastname + 1);
591 /* and add them to the dirlist pool */
592 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
596 DEBUG(0,("Failed to expand dirlist\n"));
600 /* put in a length for the last entry, to ensure we can chain entries
601 into the next packet */
604 for (p2=p,i=0;i<(ff_searchcount-1);i++)
605 p2 += interpret_long_filename(info_level,p2,NULL);
606 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
609 /* grab the data for later use */
610 memcpy(dirlist+dirlist_len,p,resp_data_len);
611 dirlist_len += resp_data_len;
613 total_received += ff_searchcount;
615 if (resp_data) free(resp_data); resp_data = NULL;
616 if (resp_param) free(resp_param); resp_param = NULL;
618 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
619 ff_searchcount,ff_eos,ff_resume_key));
625 for (p=dirlist,i=0;i<total_received;i++)
627 p += interpret_long_filename(info_level,p,&finfo);
628 display_finfo(&finfo);
631 for (p=dirlist,i=0;i<total_received;i++)
633 p += interpret_long_filename(info_level,p,&finfo);
634 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
637 /* free up the dirlist buffer */
638 if (dirlist) free(dirlist);
639 return(total_received);
643 /****************************************************************************
644 do a directory listing, calling fn on each file found
645 ****************************************************************************/
646 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
652 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
653 int num_received = 0;
655 char *dirlist = NULL;
667 bzero(outbuf,smb_size);
669 set_message(outbuf,2,5 + strlen(mask),True);
671 set_message(outbuf,2,5 + 21,True);
674 if (Protocol >= PROTOCOL_LANMAN1)
675 CVAL(outbuf,smb_com) = SMBffirst;
678 CVAL(outbuf,smb_com) = SMBsearch;
680 SSVAL(outbuf,smb_tid,cnum);
681 cli_setup_pkt(outbuf);
683 SSVAL(outbuf,smb_vwv0,num_asked);
684 SSVAL(outbuf,smb_vwv1,attribute);
705 send_smb(Client,outbuf);
706 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
708 received = SVAL(inbuf,smb_vwv0);
710 DEBUG(5,("dir received %d\n",received));
712 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
714 if (received <= 0) break;
718 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
723 p = smb_buf(inbuf) + 3;
725 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
726 p,received*DIR_STRUCT_SIZE);
728 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
730 num_received += received;
732 if (CVAL(inbuf,smb_rcls) != 0) break;
736 if (!first && Protocol >= PROTOCOL_LANMAN1)
738 bzero(outbuf,smb_size);
739 CVAL(outbuf,smb_com) = SMBfclose;
741 SSVAL(outbuf,smb_tid,cnum);
742 cli_setup_pkt(outbuf);
755 send_smb(Client,outbuf);
756 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
758 if (CVAL(inbuf,smb_rcls) != 0)
759 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
764 for (p=dirlist,i=0;i<num_received;i++)
766 p += interpret_short_filename(p,&finfo);
767 display_finfo(&finfo);
770 for (p=dirlist,i=0;i<num_received;i++)
772 p += interpret_short_filename(p,&finfo);
773 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
776 if (dirlist) free(dirlist);
777 return(num_received);
782 /****************************************************************************
783 do a directory listing, calling fn on each file found
784 ****************************************************************************/
785 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
787 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
788 if (Protocol >= PROTOCOL_LANMAN2)
790 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
794 expand_mask(Mask,False);
795 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
799 /*******************************************************************
800 decide if a file should be operated on
801 ********************************************************************/
802 static BOOL do_this_one(file_info *finfo)
804 if (finfo->mode & aDIR) return(True);
806 if (newer_than && finfo->mtime < newer_than)
809 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
816 /*****************************************************************************
817 Convert a character pointer in a cli_call_api() response to a form we can use.
818 This function contains code to prevent core dumps if the server returns
820 *****************************************************************************/
821 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
823 if( datap == 0 ) /* turn NULL pointers */
824 { /* into zero length strings */
829 unsigned int offset = datap - converter;
831 if( offset >= rdrcnt )
833 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
838 return &rdata[offset];
843 /****************************************************************************
844 interpret a short filename structure
845 The length of the structure is returned
846 ****************************************************************************/
847 static int interpret_short_filename(char *p,file_info *finfo)
849 finfo->mode = CVAL(p,21);
851 /* this date is converted to GMT by make_unix_date */
852 finfo->ctime = make_unix_date(p+22);
853 finfo->mtime = finfo->atime = finfo->ctime;
854 finfo->size = IVAL(p,26);
855 strcpy(finfo->name,p+30);
857 return(DIR_STRUCT_SIZE);
860 /****************************************************************************
861 interpret a long filename structure - this is mostly guesses at the moment
862 The length of the structure is returned
863 The structure of a long filename depends on the info level. 260 is used
864 by NT and 2 is used by OS/2
865 ****************************************************************************/
866 static int interpret_long_filename(int level,char *p,file_info *finfo)
869 memcpy(finfo,&def_finfo,sizeof(*finfo));
873 case 1: /* OS/2 understands this */
876 /* these dates are converted to GMT by make_unix_date */
877 finfo->ctime = make_unix_date2(p+4);
878 finfo->atime = make_unix_date2(p+8);
879 finfo->mtime = make_unix_date2(p+12);
880 finfo->size = IVAL(p,16);
881 finfo->mode = CVAL(p,24);
882 strcpy(finfo->name,p+27);
884 return(28 + CVAL(p,26));
886 case 2: /* this is what OS/2 uses mostly */
889 /* these dates are converted to GMT by make_unix_date */
890 finfo->ctime = make_unix_date2(p+4);
891 finfo->atime = make_unix_date2(p+8);
892 finfo->mtime = make_unix_date2(p+12);
893 finfo->size = IVAL(p,16);
894 finfo->mode = CVAL(p,24);
895 strcpy(finfo->name,p+31);
897 return(32 + CVAL(p,30));
899 /* levels 3 and 4 are untested */
903 /* these dates are probably like the other ones */
904 finfo->ctime = make_unix_date2(p+8);
905 finfo->atime = make_unix_date2(p+12);
906 finfo->mtime = make_unix_date2(p+16);
907 finfo->size = IVAL(p,20);
908 finfo->mode = CVAL(p,28);
909 strcpy(finfo->name,p+33);
916 /* these dates are probably like the other ones */
917 finfo->ctime = make_unix_date2(p+8);
918 finfo->atime = make_unix_date2(p+12);
919 finfo->mtime = make_unix_date2(p+16);
920 finfo->size = IVAL(p,20);
921 finfo->mode = CVAL(p,28);
922 strcpy(finfo->name,p+37);
926 case 260: /* NT uses this, but also accepts 2 */
931 p += 4; /* next entry offset */
932 p += 4; /* fileindex */
934 /* these dates appear to arrive in a weird way. It seems to
935 be localtime plus the serverzone given in the initial
936 connect. This is GMT when DST is not in effect and one
937 hour from GMT otherwise. Can this really be right??
939 I suppose this could be called kludge-GMT. Is is the GMT
940 you get by using the current DST setting on a different
941 localtime. It will be cheap to calculate, I suppose, as
942 no DST tables will be needed */
944 finfo->ctime = interpret_long_date(p); p += 8;
945 finfo->atime = interpret_long_date(p); p += 8;
946 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
947 finfo->size = IVAL(p,0); p += 8;
948 p += 8; /* alloc size */
949 finfo->mode = CVAL(p,0); p += 4;
950 namelen = IVAL(p,0); p += 4;
951 p += 4; /* EA size */
952 p += 2; /* short name len? */
953 p += 24; /* short name? */
954 StrnCpy(finfo->name,p,namelen);
960 DEBUG(1,("Unknown long filename format %d\n",level));
967 /****************************************************************************
968 act on the files in a dir listing
969 ****************************************************************************/
970 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
973 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
974 !mask_match(finfo->name,fileselection,False,False)) &&
975 !(recurse_dir && (strequal(finfo->name,".") ||
976 strequal(finfo->name,".."))))
978 if (recurse_dir && (finfo->mode & aDIR))
982 strcpy(sav_dir,cur_dir);
983 strcat(cur_dir,finfo->name);
984 strcat(cur_dir,"\\");
985 strcpy(mask2,cur_dir);
988 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
993 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);
995 do_dir(inbuf,outbuf,mask2,attribute,fn,True);
997 strcpy(cur_dir,sav_dir);
1001 if (fn && do_this_one(finfo))
1008 /****************************************************************************
1009 get a directory listing
1010 ****************************************************************************/
1011 static void cmd_dir(char *inbuf,char *outbuf)
1013 int attribute = aDIR | aSYSTEM | aHIDDEN;
1019 strcpy(mask,cur_dir);
1020 if(mask[strlen(mask)-1]!='\\')
1023 if (next_token(NULL,buf,NULL))
1034 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1038 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1043 /****************************************************************************
1044 get a file from rname to lname
1045 ****************************************************************************/
1046 static void do_get(char *rname,char *lname,file_info *finfo1)
1051 BOOL newhandle = False;
1052 char *inbuf,*outbuf;
1054 BOOL close_done = False;
1055 BOOL ignore_close_error = False;
1059 struct timeval tp_start;
1060 GetTimeOfDay(&tp_start);
1071 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1072 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1074 if (!inbuf || !outbuf)
1076 DEBUG(0,("out of memory\n"));
1080 bzero(outbuf,smb_size);
1081 set_message(outbuf,15,1 + strlen(rname),True);
1083 CVAL(outbuf,smb_com) = SMBopenX;
1084 SSVAL(outbuf,smb_tid,cnum);
1085 cli_setup_pkt(outbuf);
1087 SSVAL(outbuf,smb_vwv0,0xFF);
1088 SSVAL(outbuf,smb_vwv2,1);
1089 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1090 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1091 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1092 SSVAL(outbuf,smb_vwv8,1);
1094 p = smb_buf(outbuf);
1096 p = skip_string(p,1);
1098 /* do a chained openX with a readX? */
1102 DEBUG(3,("Chaining readX wth openX\n"));
1103 SSVAL(outbuf,smb_vwv0,SMBreadX);
1104 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1107 SSVAL(p,smb_wct,10);
1108 SSVAL(p,smb_vwv0,0xFF);
1109 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1110 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1111 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1115 if(!strcmp(lname,"-"))
1116 handle = fileno(stdout);
1119 handle = creat(lname,0644);
1124 DEBUG(0,("Error opening local file %s\n",lname));
1125 free(inbuf);free(outbuf);
1129 send_smb(Client,outbuf);
1130 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1132 if (CVAL(inbuf,smb_rcls) != 0)
1134 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1135 SVAL(inbuf,smb_err) == ERRnoresource &&
1136 cli_reopen_connection(inbuf,outbuf))
1138 do_get(rname,lname,finfo1);
1141 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1144 free(inbuf);free(outbuf);
1148 strcpy(finfo.name,rname);
1152 finfo.mode = SVAL(inbuf,smb_vwv3);
1153 /* these times arrive as LOCAL time, using the DST offset
1154 corresponding to that time, we convert them to GMT */
1155 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1156 finfo.atime = finfo.ctime = finfo.mtime;
1157 finfo.size = IVAL(inbuf,smb_vwv6);
1160 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1162 fnum = SVAL(inbuf,smb_vwv2);
1164 /* we might have got some data from a chained readX */
1165 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1167 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1168 datalen = SVAL(p,smb_vwv5);
1169 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1178 DEBUG(2,("getting file %s of size %d bytes as %s ",
1179 CNV_LANG(finfo.name),
1183 while (nread < finfo.size && !close_done)
1186 static BOOL can_chain_close = True;
1190 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1192 /* 3 possible read types. readbraw if a large block is required.
1193 readX + close if not much left and read if neither is supported */
1195 /* we might have already read some data from a chained readX */
1196 if (dataptr && datalen>0)
1199 /* if we can finish now then readX+close */
1200 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1201 ((finfo.size - nread) <
1202 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1205 /* if we support readraw then use that */
1206 if (method<0 && readbraw_supported)
1209 /* if we can then use readX */
1210 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1221 /* use readX + close */
1222 bzero(outbuf,smb_size);
1223 set_message(outbuf,10,0,True);
1224 CVAL(outbuf,smb_com) = SMBreadX;
1225 SSVAL(outbuf,smb_tid,cnum);
1226 cli_setup_pkt(outbuf);
1230 CVAL(outbuf,smb_vwv0) = SMBclose;
1231 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1234 CVAL(outbuf,smb_vwv0) = 0xFF;
1236 SSVAL(outbuf,smb_vwv2,fnum);
1237 SIVAL(outbuf,smb_vwv3,nread);
1238 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1239 SSVAL(outbuf,smb_vwv6,0);
1240 SIVAL(outbuf,smb_vwv7,0);
1241 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1245 p = smb_buf(outbuf);
1252 /* now set the total packet length */
1253 smb_setlen(outbuf,smb_len(outbuf)+9);
1256 send_smb(Client,outbuf);
1257 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1259 if (CVAL(inbuf,smb_rcls) != 0)
1261 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1266 SVAL(inbuf,smb_vwv0) != SMBclose)
1268 /* NOTE: WfWg sometimes just ignores the chained
1269 command! This seems to break the spec? */
1270 DEBUG(3,("Rejected chained close?\n"));
1272 can_chain_close = False;
1273 ignore_close_error = True;
1276 datalen = SVAL(inbuf,smb_vwv5);
1277 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1283 static int readbraw_size = BUFFER_SIZE;
1286 bzero(outbuf,smb_size);
1287 set_message(outbuf,8,0,True);
1288 CVAL(outbuf,smb_com) = SMBreadbraw;
1289 SSVAL(outbuf,smb_tid,cnum);
1290 cli_setup_pkt(outbuf);
1291 SSVAL(outbuf,smb_vwv0,fnum);
1292 SIVAL(outbuf,smb_vwv1,nread);
1293 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1294 SSVAL(outbuf,smb_vwv4,0);
1295 SIVALS(outbuf,smb_vwv5,-1);
1296 send_smb(Client,outbuf);
1298 /* Now read the raw data into the buffer and write it */
1299 if(read_smb_length(Client,inbuf,0) == -1) {
1300 DEBUG(0,("Failed to read length in readbraw\n"));
1304 /* Even though this is not an smb message, smb_len
1305 returns the generic length of an smb message */
1306 datalen = smb_len(inbuf);
1310 /* we got a readbraw error */
1311 DEBUG(4,("readbraw error - reducing size\n"));
1312 readbraw_size = (readbraw_size * 9) / 10;
1314 if (readbraw_size < max_xmit)
1316 DEBUG(0,("disabling readbraw\n"));
1317 readbraw_supported = False;
1324 if(read_data(Client,inbuf,datalen) != datalen) {
1325 DEBUG(0,("Failed to read data in readbraw\n"));
1333 /* we've already read some data with a chained readX */
1337 /* use plain read */
1338 bzero(outbuf,smb_size);
1339 set_message(outbuf,5,0,True);
1340 CVAL(outbuf,smb_com) = SMBread;
1341 SSVAL(outbuf,smb_tid,cnum);
1342 cli_setup_pkt(outbuf);
1344 SSVAL(outbuf,smb_vwv0,fnum);
1345 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1346 SIVAL(outbuf,smb_vwv2,nread);
1347 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1349 send_smb(Client,outbuf);
1350 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1352 if (CVAL(inbuf,smb_rcls) != 0)
1354 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1358 datalen = SVAL(inbuf,smb_vwv0);
1359 dataptr = smb_buf(inbuf) + 3;
1363 if (writefile(handle,dataptr,datalen) != datalen)
1365 DEBUG(0,("Error writing local file\n"));
1372 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1384 bzero(outbuf,smb_size);
1385 set_message(outbuf,3,0,True);
1386 CVAL(outbuf,smb_com) = SMBclose;
1387 SSVAL(outbuf,smb_tid,cnum);
1388 cli_setup_pkt(outbuf);
1390 SSVAL(outbuf,smb_vwv0,fnum);
1391 SIVALS(outbuf,smb_vwv1,-1);
1393 send_smb(Client,outbuf);
1394 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1396 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1398 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1401 free(inbuf);free(outbuf);
1409 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1410 bzero(outbuf,smb_size);
1411 set_message(outbuf,8,strlen(rname)+4,True);
1412 CVAL(outbuf,smb_com) = SMBsetatr;
1413 SSVAL(outbuf,smb_tid,cnum);
1414 cli_setup_pkt(outbuf);
1415 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1416 SIVALS(outbuf,smb_vwv1,0);
1417 p = smb_buf(outbuf);
1423 send_smb(Client,outbuf);
1424 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1428 struct timeval tp_end;
1431 GetTimeOfDay(&tp_end);
1433 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1434 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1435 get_total_time_ms += this_time;
1436 get_total_size += finfo.size;
1438 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1439 finfo.size / (1.024*this_time + 1.0e-4),
1440 get_total_size / (1.024*get_total_time_ms)));
1443 free(inbuf);free(outbuf);
1447 /****************************************************************************
1449 ****************************************************************************/
1450 static void cmd_get(void)
1456 strcpy(rname,cur_dir);
1459 p = rname + strlen(rname);
1461 if (!next_token(NULL,p,NULL)) {
1462 DEBUG(0,("get <filename>\n"));
1466 dos_clean_name(rname);
1468 next_token(NULL,lname,NULL);
1470 do_get(rname,lname,NULL);
1474 /****************************************************************************
1475 do a mget operation on one file
1476 ****************************************************************************/
1477 static void do_mget(file_info *finfo)
1482 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1487 DEBUG(0,("mget aborted\n"));
1491 if (finfo->mode & aDIR)
1492 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1494 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1496 if (prompt && !yesno(quest)) return;
1498 if (finfo->mode & aDIR)
1500 pstring saved_curdir;
1502 char *inbuf,*outbuf;
1504 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1505 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1507 if (!inbuf || !outbuf)
1509 DEBUG(0,("out of memory\n"));
1513 strcpy(saved_curdir,cur_dir);
1515 strcat(cur_dir,finfo->name);
1516 strcat(cur_dir,"\\");
1518 unix_format(finfo->name);
1521 strlower(finfo->name);
1523 if (!directory_exist(finfo->name,NULL) &&
1524 sys_mkdir(finfo->name,0777) != 0)
1526 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1527 strcpy(cur_dir,saved_curdir);
1528 free(inbuf);free(outbuf);
1532 if (sys_chdir(finfo->name) != 0)
1534 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1535 strcpy(cur_dir,saved_curdir);
1536 free(inbuf);free(outbuf);
1541 strcpy(mget_mask,cur_dir);
1542 strcat(mget_mask,"*");
1544 do_dir((char *)inbuf,(char *)outbuf,
1545 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1547 strcpy(cur_dir,saved_curdir);
1548 free(inbuf);free(outbuf);
1552 strcpy(rname,cur_dir);
1553 strcat(rname,finfo->name);
1554 do_get(rname,finfo->name,finfo);
1558 /****************************************************************************
1559 view the file using the pager
1560 ****************************************************************************/
1561 static void cmd_more(void)
1563 fstring rname,lname,tmpname,pager_cmd;
1566 strcpy(rname,cur_dir);
1568 sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1569 strcpy(lname,tmpname);
1571 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1572 DEBUG(0,("more <filename>\n"));
1575 dos_clean_name(rname);
1577 do_get(rname,lname,NULL);
1579 pager=getenv("PAGER");
1580 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1587 /****************************************************************************
1589 ****************************************************************************/
1590 static void cmd_mget(char *inbuf,char *outbuf)
1592 int attribute = aSYSTEM | aHIDDEN;
1604 while (next_token(NULL,p,NULL))
1606 strcpy(mget_mask,cur_dir);
1607 if(mget_mask[strlen(mget_mask)-1]!='\\')
1608 strcat(mget_mask,"\\");
1611 strcpy(mget_mask,p);
1613 strcat(mget_mask,p);
1614 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1619 strcpy(mget_mask,cur_dir);
1620 if(mget_mask[strlen(mget_mask)-1]!='\\')
1621 strcat(mget_mask,"\\");
1622 strcat(mget_mask,"*");
1623 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1627 /****************************************************************************
1628 make a directory of name "name"
1629 ****************************************************************************/
1630 static BOOL do_mkdir(char *name)
1633 char *inbuf,*outbuf;
1635 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1636 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1638 if (!inbuf || !outbuf)
1640 DEBUG(0,("out of memory\n"));
1644 bzero(outbuf,smb_size);
1645 set_message(outbuf,0,2 + strlen(name),True);
1647 CVAL(outbuf,smb_com) = SMBmkdir;
1648 SSVAL(outbuf,smb_tid,cnum);
1649 cli_setup_pkt(outbuf);
1652 p = smb_buf(outbuf);
1656 send_smb(Client,outbuf);
1657 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1659 if (CVAL(inbuf,smb_rcls) != 0)
1661 DEBUG(0,("%s making remote directory %s\n",
1662 smb_errstr(inbuf),CNV_LANG(name)));
1664 free(inbuf);free(outbuf);
1668 free(inbuf);free(outbuf);
1673 /****************************************************************************
1675 ****************************************************************************/
1676 static void cmd_mkdir(char *inbuf,char *outbuf)
1682 strcpy(mask,cur_dir);
1684 if (!next_token(NULL,p,NULL))
1687 DEBUG(0,("mkdir <dirname>\n"));
1699 trim_string(ddir,".",NULL);
1700 p = strtok(ddir,"/\\");
1704 if (!chkpath(ddir2,False))
1709 p = strtok(NULL,"/\\");
1717 /*******************************************************************
1718 write to a file using writebraw
1719 ********************************************************************/
1720 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1725 bzero(outbuf,smb_size);
1726 bzero(inbuf,smb_size);
1727 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1729 CVAL(outbuf,smb_com) = SMBwritebraw;
1730 SSVAL(outbuf,smb_tid,cnum);
1731 cli_setup_pkt(outbuf);
1733 SSVAL(outbuf,smb_vwv0,fnum);
1734 SSVAL(outbuf,smb_vwv1,n);
1735 SIVAL(outbuf,smb_vwv3,pos);
1736 SSVAL(outbuf,smb_vwv7,1);
1738 send_smb(Client,outbuf);
1740 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1743 _smb_setlen(buf-4,n); /* HACK! XXXX */
1745 if (write_socket(Client,buf-4,n+4) != n+4)
1748 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1749 DEBUG(0,("Error writing remote file (2)\n"));
1752 return(SVAL(inbuf,smb_vwv0));
1757 /*******************************************************************
1759 ********************************************************************/
1760 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1764 if (writebraw_supported && n > (max_xmit-200))
1765 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1767 bzero(outbuf,smb_size);
1768 bzero(inbuf,smb_size);
1769 set_message(outbuf,5,n + 3,True);
1771 CVAL(outbuf,smb_com) = SMBwrite;
1772 SSVAL(outbuf,smb_tid,cnum);
1773 cli_setup_pkt(outbuf);
1775 SSVAL(outbuf,smb_vwv0,fnum);
1776 SSVAL(outbuf,smb_vwv1,n);
1777 SIVAL(outbuf,smb_vwv2,pos);
1778 SSVAL(outbuf,smb_vwv4,0);
1779 CVAL(smb_buf(outbuf),0) = 1;
1780 SSVAL(smb_buf(outbuf),1,n);
1782 memcpy(smb_buf(outbuf)+3,buf,n);
1784 send_smb(Client,outbuf);
1785 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1787 if (CVAL(inbuf,smb_rcls) != 0) {
1788 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1791 return(SVAL(inbuf,smb_vwv0));
1796 /****************************************************************************
1798 ****************************************************************************/
1799 static void do_put(char *rname,char *lname,file_info *finfo)
1805 char *inbuf,*outbuf;
1806 time_t close_time = finfo->mtime;
1808 static int maxwrite=0;
1810 struct timeval tp_start;
1811 GetTimeOfDay(&tp_start);
1813 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1814 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1816 if (!inbuf || !outbuf)
1818 DEBUG(0,("out of memory\n"));
1822 bzero(outbuf,smb_size);
1823 set_message(outbuf,3,2 + strlen(rname),True);
1825 if (finfo->mtime == 0 || finfo->mtime == -1)
1826 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1828 CVAL(outbuf,smb_com) = SMBcreate;
1829 SSVAL(outbuf,smb_tid,cnum);
1830 cli_setup_pkt(outbuf);
1832 SSVAL(outbuf,smb_vwv0,finfo->mode);
1833 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1835 p = smb_buf(outbuf);
1839 send_smb(Client,outbuf);
1840 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1842 if (CVAL(inbuf,smb_rcls) != 0)
1844 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1846 free(inbuf);free(outbuf);if (buf) free(buf);
1850 f = fopen(lname,"r");
1854 DEBUG(0,("Error opening local file %s\n",lname));
1855 free(inbuf);free(outbuf);
1860 fnum = SVAL(inbuf,smb_vwv0);
1861 if (finfo->size < 0)
1862 finfo->size = file_size(lname);
1864 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1867 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1869 while (nread < finfo->size)
1874 n = MIN(n,finfo->size - nread);
1876 buf = (char *)Realloc(buf,n+4);
1878 fseek(f,nread,SEEK_SET);
1879 if ((n = readfile(buf+4,1,n,f)) < 1)
1881 DEBUG(0,("Error reading local file\n"));
1885 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1889 DEBUG(0,("Error writing file\n"));
1902 bzero(outbuf,smb_size);
1903 set_message(outbuf,3,0,True);
1904 CVAL(outbuf,smb_com) = SMBclose;
1905 SSVAL(outbuf,smb_tid,cnum);
1906 cli_setup_pkt(outbuf);
1908 SSVAL(outbuf,smb_vwv0,fnum);
1909 put_dos_date3(outbuf,smb_vwv1,close_time);
1911 send_smb(Client,outbuf);
1912 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1914 if (CVAL(inbuf,smb_rcls) != 0)
1916 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1918 free(inbuf);free(outbuf);
1925 free(inbuf);free(outbuf);
1929 struct timeval tp_end;
1932 GetTimeOfDay(&tp_end);
1934 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1935 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1936 put_total_time_ms += this_time;
1937 put_total_size += finfo->size;
1939 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1940 finfo->size / (1.024*this_time + 1.0e-4),
1941 put_total_size / (1.024*put_total_time_ms)));
1947 /****************************************************************************
1949 ****************************************************************************/
1950 static void cmd_put(void)
1959 strcpy(rname,cur_dir);
1963 if (!next_token(NULL,p,NULL))
1965 DEBUG(0,("put <filename>\n"));
1970 if (next_token(NULL,p,NULL))
1973 strcat(rname,lname);
1975 dos_clean_name(rname);
1979 if (!file_exist(lname,&st)) {
1980 DEBUG(0,("%s does not exist\n",lname));
1983 finfo.mtime = st.st_mtime;
1986 do_put(rname,lname,&finfo);
1989 /****************************************************************************
1990 seek in a directory/file list until you get something that doesn't start with
1992 ****************************************************************************/
1993 static BOOL seek_list(FILE *f,char *name)
1998 if (fscanf(f,"%s",s) != 1) return(False);
1999 trim_string(s,"./",NULL);
2000 if (strncmp(s,name,strlen(name)) != 0)
2011 /****************************************************************************
2012 set the file selection mask
2013 ****************************************************************************/
2014 static void cmd_select(void)
2016 strcpy(fileselection,"");
2017 next_token(NULL,fileselection,NULL);
2021 /****************************************************************************
2023 ****************************************************************************/
2024 static void cmd_mput(void)
2035 while (next_token(NULL,p,NULL))
2042 sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2044 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2046 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2049 f = fopen(tmpname,"r");
2056 if (fscanf(f,"%s",lname) != 1) break;
2057 trim_string(lname,"./",NULL);
2061 /* check if it's a directory */
2062 if (directory_exist(lname,&st))
2064 if (!recurse) continue;
2065 sprintf(quest,"Put directory %s? ",lname);
2066 if (prompt && !yesno(quest))
2069 if (!seek_list(f,lname))
2074 strcpy(rname,cur_dir);
2075 strcat(rname,lname);
2076 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2078 if (!seek_list(f,lname))
2087 sprintf(quest,"Put file %s? ",lname);
2088 if (prompt && !yesno(quest)) continue;
2090 strcpy(rname,cur_dir);
2091 strcat(rname,lname);
2095 /* null size so do_put knows to ignore it */
2098 /* set the date on the file */
2099 finfo.mtime = st.st_mtime;
2101 do_put(rname,lname,&finfo);
2108 /****************************************************************************
2110 ****************************************************************************/
2111 static void do_cancel(int job)
2113 char *rparam = NULL;
2119 bzero(param,sizeof(param));
2122 SSVAL(p,0,81); /* DosPrintJobDel() */
2125 p = skip_string(p,1);
2127 p = skip_string(p,1);
2131 if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param),0,
2137 int res = SVAL(rparam,0);
2140 printf("Job %d cancelled\n",job);
2142 printf("Error %d calcelling job %d\n",res,job);
2146 printf("Server refused cancel request\n");
2148 if (rparam) free(rparam);
2149 if (rdata) free(rdata);
2155 /****************************************************************************
2157 ****************************************************************************/
2158 static void cmd_cancel(char *inbuf,char *outbuf )
2163 if (!connect_as_printer)
2165 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2166 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2169 if (!next_token(NULL,buf,NULL)) {
2170 printf("cancel <jobid> ...\n");
2176 } while (next_token(NULL,buf,NULL));
2180 /****************************************************************************
2182 ****************************************************************************/
2183 static void cmd_stat(char *inbuf,char *outbuf)
2187 char *resp_data=NULL;
2188 char *resp_param=NULL;
2189 int resp_data_len = 0;
2190 int resp_param_len=0;
2192 uint16 setup = TRANSACT2_QPATHINFO;
2194 if (!next_token(NULL,buf,NULL)) {
2195 printf("stat <file>\n");
2200 SSVAL(param,0,4); /* level */
2205 cli_send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
2207 0,6 + strlen(p)+1,1,
2210 cli_receive_trans_response(inbuf,SMBtrans2,
2211 &resp_data_len,&resp_param_len,
2212 &resp_data,&resp_param);
2214 if (resp_data) free(resp_data); resp_data = NULL;
2215 if (resp_param) free(resp_param); resp_param = NULL;
2219 /****************************************************************************
2221 ****************************************************************************/
2222 static void cmd_print(char *inbuf,char *outbuf )
2231 if (!connect_as_printer)
2233 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2234 DEBUG(0,("Trying to print without -P may fail\n"));
2237 if (!next_token(NULL,lname,NULL))
2239 DEBUG(0,("print <filename>\n"));
2243 strcpy(rname,lname);
2244 p = strrchr(rname,'/');
2249 strcpy(rname,tname);
2252 if ((int)strlen(rname) > 14)
2255 if (strequal(lname,"-"))
2258 strcpy(rname,"stdin");
2261 dos_clean_name(rname);
2263 bzero(outbuf,smb_size);
2264 set_message(outbuf,2,2 + strlen(rname),True);
2266 CVAL(outbuf,smb_com) = SMBsplopen;
2267 SSVAL(outbuf,smb_tid,cnum);
2268 cli_setup_pkt(outbuf);
2270 SSVAL(outbuf,smb_vwv0,0);
2271 SSVAL(outbuf,smb_vwv1,printmode);
2273 p = smb_buf(outbuf);
2277 send_smb(Client,outbuf);
2278 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2280 if (CVAL(inbuf,smb_rcls) != 0)
2282 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2287 f = fopen(lname,"r");
2290 DEBUG(0,("Error opening local file %s\n",lname));
2295 fnum = SVAL(inbuf,smb_vwv0);
2297 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2303 bzero(outbuf,smb_size);
2304 set_message(outbuf,1,3,True);
2306 /* for some strange reason the OS/2 print server can't handle large
2307 packets when printing. weird */
2308 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2311 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2313 n = readfile(smb_buf(outbuf)+3,1,n,f);
2316 DEBUG(0,("read gave %d\n",n));
2320 smb_setlen(outbuf,smb_len(outbuf) + n);
2322 CVAL(outbuf,smb_com) = SMBsplwr;
2323 SSVAL(outbuf,smb_tid,cnum);
2324 cli_setup_pkt(outbuf);
2326 SSVAL(outbuf,smb_vwv0,fnum);
2327 SSVAL(outbuf,smb_vwv1,n+3);
2328 CVAL(smb_buf(outbuf),0) = 1;
2329 SSVAL(smb_buf(outbuf),1,n);
2331 send_smb(Client,outbuf);
2332 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2334 if (CVAL(inbuf,smb_rcls) != 0)
2336 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2343 DEBUG(2,("%d bytes printed\n",nread));
2345 bzero(outbuf,smb_size);
2346 set_message(outbuf,1,0,True);
2347 CVAL(outbuf,smb_com) = SMBsplclose;
2348 SSVAL(outbuf,smb_tid,cnum);
2349 cli_setup_pkt(outbuf);
2351 SSVAL(outbuf,smb_vwv0,fnum);
2353 send_smb(Client,outbuf);
2354 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2356 if (CVAL(inbuf,smb_rcls) != 0)
2358 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2368 /****************************************************************************
2369 show a print queue - this is deprecated as it uses the old smb that
2370 has limited support - the correct call is the cmd_p_queue_4() after this.
2371 ****************************************************************************/
2372 static void cmd_queue(char *inbuf,char *outbuf )
2377 bzero(outbuf,smb_size);
2378 set_message(outbuf,2,0,True);
2380 CVAL(outbuf,smb_com) = SMBsplretq;
2381 SSVAL(outbuf,smb_tid,cnum);
2382 cli_setup_pkt(outbuf);
2384 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2385 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2387 send_smb(Client,outbuf);
2388 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2390 if (CVAL(inbuf,smb_rcls) != 0)
2392 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2396 count = SVAL(inbuf,smb_vwv0);
2397 p = smb_buf(inbuf) + 3;
2400 DEBUG(0,("No entries in the print queue\n"));
2407 DEBUG(0,("Job Name Size Status\n"));
2413 case 0x01: sprintf(status,"held or stopped"); break;
2414 case 0x02: sprintf(status,"printing"); break;
2415 case 0x03: sprintf(status,"awaiting print"); break;
2416 case 0x04: sprintf(status,"in intercept"); break;
2417 case 0x05: sprintf(status,"file had error"); break;
2418 case 0x06: sprintf(status,"printer error"); break;
2419 default: sprintf(status,"unknown"); break;
2422 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2423 SVAL(p,5),p+12,IVAL(p,7),status));
2431 /****************************************************************************
2432 show information about a print queue
2433 ****************************************************************************/
2434 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2436 char *rparam = NULL;
2443 if (!connect_as_printer)
2445 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2446 DEBUG(0,("Trying to print without -P may fail\n"));
2449 bzero(param,sizeof(param));
2452 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2454 strcpy(p,"zWrLeh"); /* parameter description? */
2455 p = skip_string(p,1);
2456 strcpy(p,"WWzWWDDzz"); /* returned data format */
2457 p = skip_string(p,1);
2458 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2459 p = skip_string(p,1);
2460 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2461 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2463 strcpy(p,""); /* subformat */
2464 p = skip_string(p,1);
2466 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2467 if( cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param), 0,
2474 result_code = SVAL(rparam,0);
2475 converter = SVAL(rparam,2); /* conversion factor */
2477 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2479 if (result_code == 0) /* if no error, */
2489 char PrinterName[20];
2491 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2492 strlower(PrinterName); /* in lower case */
2494 p = rdata; /* received data */
2495 for( i = 0; i < SVAL(rparam,4); ++i)
2498 Priority = SVAL(p,2);
2499 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2501 Priority = SVAL(p,2);
2502 JobTime = make_unix_date3( p + 12);
2503 JobTimeStr = asctime(LocalTime( &JobTime));
2505 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2508 printf("%s-%u %s priority %u %s %s %u bytes\n",
2509 PrinterName, JobId, UserName,
2510 Priority, JobTimeStr, JobName, Size);
2512 #if 0 /* DEBUG code */
2513 printf("Job Id: \"%u\"\n", SVAL(p,0));
2514 printf("Priority: \"%u\"\n", SVAL(p,2));
2516 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2517 printf("Position: \"%u\"\n", SVAL(p,8));
2518 printf("Status: \"%u\"\n", SVAL(p,10));
2520 JobTime = make_unix_date3( p + 12);
2521 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2522 printf("date: \"%u\"\n", SVAL(p,12));
2524 printf("Size: \"%u\"\n", SVAL(p,16));
2525 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2526 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2527 #endif /* DEBUG CODE */
2532 else /* cli_call_api() failed */
2534 printf("Failed, error = %d\n", result_code);
2537 /* If any parameters or data were returned, free the storage. */
2538 if(rparam) free(rparam);
2539 if(rdata) free(rdata);
2544 /****************************************************************************
2545 show information about a print queue
2546 ****************************************************************************/
2547 static void cmd_qinfo(char *inbuf,char *outbuf )
2549 char *rparam = NULL;
2556 bzero(param,sizeof(param));
2559 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2561 strcpy(p,"zWrLh"); /* parameter description? */
2562 p = skip_string(p,1);
2563 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2564 p = skip_string(p,1);
2565 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2566 p = skip_string(p,1);
2567 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2568 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2570 strcpy(p,""); /* subformat */
2571 p = skip_string(p,1);
2573 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2574 if( cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param), 0,
2581 result_code = SVAL(rparam,0);
2582 converter = SVAL(rparam,2); /* conversion factor */
2584 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2586 if (result_code == 0) /* if no error, */
2588 p = rdata; /* received data */
2590 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2591 printf("Priority: %u\n", SVAL(p,4) );
2592 printf("Start time: %u\n", SVAL(p,6) );
2593 printf("Until time: %u\n", SVAL(p,8) );
2594 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2595 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2596 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2597 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2598 printf("Status: %u\n", SVAL(p,28) );
2599 printf("Jobs: %u\n", SVAL(p,30) );
2600 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2601 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2603 /* Dump the driver data */
2608 ddptr = rdata + SVAL(p,40) - converter;
2609 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2610 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2612 for(x=8; x < count; x+=16)
2614 for(y=0; y < 16; y++)
2617 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2621 for(y=0; y < 16 && (x+y) < count; y++)
2623 c = CVAL(ddptr,(x+y));
2629 fputc('\n', stdout);
2635 else /* cli_call_api() failed */
2637 printf("Failed, error = %d\n", result_code);
2640 /* If any parameters or data were returned, free the storage. */
2641 if(rparam) free(rparam);
2642 if(rdata) free(rdata);
2647 /****************************************************************************
2649 ****************************************************************************/
2650 static void do_del(file_info *finfo)
2653 char *inbuf,*outbuf;
2656 strcpy(mask,cur_dir);
2657 strcat(mask,finfo->name);
2659 if (finfo->mode & aDIR)
2662 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2663 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2665 if (!inbuf || !outbuf)
2667 DEBUG(0,("out of memory\n"));
2671 bzero(outbuf,smb_size);
2672 set_message(outbuf,1,2 + strlen(mask),True);
2674 CVAL(outbuf,smb_com) = SMBunlink;
2675 SSVAL(outbuf,smb_tid,cnum);
2676 cli_setup_pkt(outbuf);
2678 SSVAL(outbuf,smb_vwv0,0);
2680 p = smb_buf(outbuf);
2684 send_smb(Client,outbuf);
2685 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2687 if (CVAL(inbuf,smb_rcls) != 0)
2688 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2690 free(inbuf);free(outbuf);
2694 /****************************************************************************
2696 ****************************************************************************/
2697 static void cmd_del(char *inbuf,char *outbuf )
2701 int attribute = aSYSTEM | aHIDDEN;
2706 strcpy(mask,cur_dir);
2708 if (!next_token(NULL,buf,NULL))
2710 DEBUG(0,("del <filename>\n"));
2715 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2719 /****************************************************************************
2721 ****************************************************************************/
2722 static void cmd_rmdir(char *inbuf,char *outbuf )
2728 strcpy(mask,cur_dir);
2730 if (!next_token(NULL,buf,NULL))
2732 DEBUG(0,("rmdir <dirname>\n"));
2737 bzero(outbuf,smb_size);
2738 set_message(outbuf,0,2 + strlen(mask),True);
2740 CVAL(outbuf,smb_com) = SMBrmdir;
2741 SSVAL(outbuf,smb_tid,cnum);
2742 cli_setup_pkt(outbuf);
2745 p = smb_buf(outbuf);
2749 send_smb(Client,outbuf);
2750 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2752 if (CVAL(inbuf,smb_rcls) != 0)
2754 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2760 /****************************************************************************
2762 ****************************************************************************/
2763 static void cmd_rename(char *inbuf,char *outbuf )
2769 strcpy(src,cur_dir);
2770 strcpy(dest,cur_dir);
2772 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2774 DEBUG(0,("rename <src> <dest>\n"));
2780 bzero(outbuf,smb_size);
2781 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2783 CVAL(outbuf,smb_com) = SMBmv;
2784 SSVAL(outbuf,smb_tid,cnum);
2785 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2786 cli_setup_pkt(outbuf);
2788 p = smb_buf(outbuf);
2791 p = skip_string(p,1);
2795 send_smb(Client,outbuf);
2796 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2798 if (CVAL(inbuf,smb_rcls) != 0)
2800 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2807 /****************************************************************************
2808 toggle the prompt flag
2809 ****************************************************************************/
2810 static void cmd_prompt(void)
2813 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2817 /****************************************************************************
2818 set the newer than time
2819 ****************************************************************************/
2820 static void cmd_newer(void)
2826 ok = next_token(NULL,buf,NULL);
2827 if (ok && (sys_stat(buf,&sbuf) == 0))
2829 newer_than = sbuf.st_mtime;
2830 DEBUG(1,("Getting files newer than %s",
2831 asctime(LocalTime(&newer_than))));
2836 if (ok && newer_than == 0)
2837 DEBUG(0,("Error setting newer-than time\n"));
2840 /****************************************************************************
2841 set the archive level
2842 ****************************************************************************/
2843 static void cmd_archive(void)
2847 if (next_token(NULL,buf,NULL)) {
2848 archive_level = atoi(buf);
2850 DEBUG(0,("Archive level is %d\n",archive_level));
2853 /****************************************************************************
2854 toggle the lowercaseflag
2855 ****************************************************************************/
2856 static void cmd_lowercase(void)
2858 lowercase = !lowercase;
2859 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2865 /****************************************************************************
2866 toggle the recurse flag
2867 ****************************************************************************/
2868 static void cmd_recurse(void)
2871 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2874 /****************************************************************************
2875 toggle the translate flag
2876 ****************************************************************************/
2877 static void cmd_translate(void)
2879 translation = !translation;
2880 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2881 translation?"on":"off"));
2885 /****************************************************************************
2886 do a printmode command
2887 ****************************************************************************/
2888 static void cmd_printmode(void)
2893 if (next_token(NULL,buf,NULL))
2895 if (strequal(buf,"text"))
2899 if (strequal(buf,"graphics"))
2902 printmode = atoi(buf);
2909 strcpy(mode,"text");
2912 strcpy(mode,"graphics");
2915 sprintf(mode,"%d",printmode);
2919 DEBUG(2,("the printmode is now %s\n",mode));
2922 /****************************************************************************
2924 ****************************************************************************/
2925 static void cmd_lcd(void)
2930 if (next_token(NULL,buf,NULL))
2932 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2936 /****************************************************************************
2937 try and browse available connections on a host
2938 ****************************************************************************/
2939 static BOOL browse_host(BOOL sort)
2942 /* If strcasecmp is already defined, remove it. */
2945 #endif /* strcasecmp */
2946 #define strcasecmp StrCaseCmp
2947 #endif /* NOSTRCASECMP */
2949 extern int strcasecmp();
2951 char *rparam = NULL;
2958 /* now send a SMBtrans command with api RNetShareEnum */
2960 SSVAL(p,0,0); /* api number */
2963 p = skip_string(p,1);
2965 p = skip_string(p,1);
2967 SSVAL(p,2,BUFFER_SIZE);
2970 if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param),0,
2976 int res = SVAL(rparam,0);
2977 int converter=SVAL(rparam,2);
2979 BOOL long_share_name=False;
2983 count=SVAL(rparam,4);
2988 printf("\n\tSharename Type Comment\n");
2989 printf("\t--------- ---- -------\n");
2993 qsort(p,count,20,QSORT_CAST strcasecmp);
2995 for (i=0;i<count;i++)
2998 int type = SVAL(p,14);
2999 int comment_offset = IVAL(p,16) & 0xFFFF;
3005 case STYPE_DISKTREE:
3006 strcpy(typestr,"Disk"); break;
3008 strcpy(typestr,"Printer"); break;
3010 strcpy(typestr,"Device"); break;
3012 strcpy(typestr,"IPC"); break;
3015 printf("\t%-15.15s%-10.10s%s\n",
3018 comment_offset?rdata+comment_offset-converter:"");
3020 if (strlen(sname)>8) long_share_name=True;
3025 if (long_share_name) {
3026 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3031 if (rparam) free(rparam);
3032 if (rdata) free(rdata);
3038 /****************************************************************************
3039 get some server info
3040 ****************************************************************************/
3041 static void server_info()
3043 char *rparam = NULL;
3049 bzero(param,sizeof(param));
3052 SSVAL(p,0,63); /* NetServerGetInfo()? */
3055 p = skip_string(p,1);
3056 strcpy(p,"zzzBBzz");
3057 p = skip_string(p,1);
3058 SSVAL(p,0,10); /* level 10 */
3062 if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param),0,
3068 int res = SVAL(rparam,0);
3069 int converter=SVAL(rparam,2);
3075 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3076 rdata+SVAL(p,0)-converter,
3077 rdata+SVAL(p,4)-converter,
3078 rdata+SVAL(p,8)-converter,
3079 rdata+SVAL(p,14)-converter);
3083 if (rparam) free(rparam);
3084 if (rdata) free(rdata);
3090 /****************************************************************************
3091 try and browse available connections on a host
3092 ****************************************************************************/
3093 static BOOL list_servers(char *wk_grp)
3095 char *rparam = NULL;
3103 BOOL generic_request = False;
3106 if (strequal(wk_grp,"WORKGROUP")) {
3107 /* we won't specify a workgroup */
3108 generic_request = True;
3111 /* now send a SMBtrans command with api ServerEnum? */
3113 SSVAL(p,0,0x68); /* api number */
3116 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3117 p = skip_string(p,1);
3119 strcpy(p,"B16BBDz");
3121 p = skip_string(p,1);
3123 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3129 if (!generic_request) {
3131 p = skip_string(p,1);
3134 /* first ask for a list of servers in this workgroup */
3135 SIVAL(svtype_p,0,SV_TYPE_ALL);
3137 if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p+4,param),0,
3138 8,BUFFER_SIZE - SAFETY_MARGIN,
3143 int res = SVAL(rparam,0);
3144 int converter=SVAL(rparam,2);
3149 count=SVAL(rparam,4);
3152 printf("\n\nThis machine has a browse list:\n");
3153 printf("\n\tServer Comment\n");
3154 printf("\t--------- -------\n");
3157 for (i=0;i<count;i++) {
3159 int comment_offset = IVAL(p2,22) & 0xFFFF;
3160 printf("\t%-16.16s %s\n",
3162 comment_offset?rdata+comment_offset-converter:"");
3170 if (rparam) {free(rparam); rparam = NULL;}
3171 if (rdata) {free(rdata); rdata = NULL;}
3173 /* now ask for a list of workgroups */
3174 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3176 if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p+4,param),0,
3177 8,BUFFER_SIZE - SAFETY_MARGIN,
3182 int res = SVAL(rparam,0);
3183 int converter=SVAL(rparam,2);
3188 count=SVAL(rparam,4);
3191 printf("\n\nThis machine has a workgroup list:\n");
3192 printf("\n\tWorkgroup Master\n");
3193 printf("\t--------- -------\n");
3196 for (i=0;i<count;i++) {
3198 int comment_offset = IVAL(p2,22) & 0xFFFF;
3199 printf("\t%-16.16s %s\n",
3201 comment_offset?rdata+comment_offset-converter:"");
3209 if (rparam) free(rparam);
3210 if (rdata) free(rdata);
3216 /* This defines the commands supported by this client */
3224 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3225 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3226 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3227 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3228 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3229 {"get",cmd_get,"<remote name> [local name] get a file"},
3230 {"mget",cmd_mget,"<mask> get all the matching files"},
3231 {"put",cmd_put,"<local name> [remote name] put a file"},
3232 {"mput",cmd_mput,"<mask> put all matching files"},
3233 {"rename",cmd_rename,"<src> <dest> rename some files"},
3234 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3235 {"mask",cmd_select,"<mask> mask all filenames against this"},
3236 {"del",cmd_del,"<mask> delete all matching files"},
3237 {"rm",cmd_del,"<mask> delete all matching files"},
3238 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3239 {"md",cmd_mkdir,"<directory> make a directory"},
3240 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
3241 {"rd",cmd_rmdir,"<directory> remove a directory"},
3242 {"pq",cmd_p_queue_4,"enumerate the print queue"},
3243 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
3244 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
3245 {"translate",cmd_translate,"toggle text translation for printing"},
3246 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
3247 {"print",cmd_print,"<file name> print a file"},
3248 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
3249 {"queue",cmd_queue,"show the print queue"},
3250 {"qinfo",cmd_qinfo,"show print queue information"},
3251 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
3252 {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
3253 {"quit",cli_send_logout,"logoff the server"},
3254 {"q",cli_send_logout,"logoff the server"},
3255 {"exit",cli_send_logout,"logoff the server"},
3256 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
3257 {"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"},
3258 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3259 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
3260 {"tarmode",cmd_tarmode,
3261 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3262 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
3263 {"help",cmd_help,"[command] give help on a command"},
3264 {"?",cmd_help,"[command] give help on a command"},
3265 {"!",NULL,"run a shell command on the local system"},
3270 /*******************************************************************
3271 lookup a command string in the list of commands, including
3273 ******************************************************************/
3274 static int process_tok(fstring tok)
3276 int i = 0, matches = 0;
3278 int tok_len = strlen(tok);
3280 while (commands[i].fn != NULL)
3282 if (strequal(commands[i].name,tok))
3288 else if (strnequal(commands[i].name, tok, tok_len+1))
3298 else if (matches == 1)
3304 /****************************************************************************
3306 ****************************************************************************/
3312 if (next_token(NULL,buf,NULL))
3314 if ((i = process_tok(buf)) >= 0)
3315 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3318 while (commands[i].description)
3320 for (j=0; commands[i].description && (j<5); j++) {
3321 DEBUG(0,("%-15s",commands[i].name));
3328 /****************************************************************************
3329 wait for keyboard activity, swallowing network packets
3330 ****************************************************************************/
3332 static char wait_keyboard(char *buffer)
3334 static void wait_keyboard(char *buffer)
3339 struct timeval timeout;
3349 FD_SET(Client,&fds);
3351 FD_SET(fileno(stdin),&fds);
3354 timeout.tv_sec = 20;
3355 timeout.tv_usec = 0;
3359 selrtn = sys_select(&fds,&timeout);
3362 if (FD_ISSET(fileno(stdin),&fds))
3369 set_blocking(fileno(stdin), False);
3370 readret = read_data( fileno(stdin), &ch, 1);
3371 set_blocking(fileno(stdin), True);
3374 if (errno != EAGAIN)
3376 /* should crash here */
3377 DEBUG(1,("readchar stdin failed\n"));
3380 else if (readret != 0)
3386 if (FD_ISSET(Client,&fds))
3387 receive_smb(Client,buffer,0);
3394 chkpath("\\",False);
3397 chkpath("\\",False);
3403 /****************************************************************************
3404 process commands from the client
3405 ****************************************************************************/
3406 static BOOL process(char *base_directory)
3412 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3413 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3415 if ((InBuffer == NULL) || (OutBuffer == NULL))
3418 bzero(OutBuffer,smb_size);
3420 if (!cli_send_login(InBuffer,OutBuffer,True,True))
3423 if (*base_directory) do_cd(base_directory);
3426 if (cmd[0] != '\0') while (cmd[0] != '\0')
3432 if ((p = strchr(cmd, ';')) == 0)
3434 strncpy(line, cmd, 999);
3440 if (p - cmd > 999) p = cmd + 999;
3441 strncpy(line, cmd, p - cmd);
3442 line[p - cmd] = '\0';
3446 /* input language code to internal one */
3449 /* and get the first part of the command */
3452 if (!next_token(&ptr,tok,NULL)) continue;
3455 if ((i = process_tok(tok)) >= 0)
3456 commands[i].fn(InBuffer,OutBuffer);
3458 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3460 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3462 else while (!feof(stdin))
3467 bzero(OutBuffer,smb_size);
3469 /* display a prompt */
3470 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3474 line[0] = wait_keyboard(InBuffer);
3475 /* this might not be such a good idea... */
3476 if ( line[0] == EOF)
3479 wait_keyboard(InBuffer);
3482 /* and get a response */
3484 fgets( &line[1],999, stdin);
3486 if (!fgets(line,1000,stdin))
3490 /* input language code to internal one */
3493 /* special case - first char is ! */
3500 /* and get the first part of the command */
3503 if (!next_token(&ptr,tok,NULL)) continue;
3506 if ((i = process_tok(tok)) >= 0)
3507 commands[i].fn(InBuffer,OutBuffer);
3509 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3511 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3518 /****************************************************************************
3519 LSA Request Challenge on the NETLOGON pipe.
3520 ****************************************************************************/
3521 static BOOL cli_lsa_req_chal(void)
3523 char *rparam = NULL;
3528 pstring param; /* only 1024 bytes */
3533 /* create and send a MSRPC command with api LSA_REQCHAL */
3535 clnt_chal.data[0] = 0x11111111;
3536 clnt_chal.data[1] = 0x22222222;
3538 DEBUG(4,("LSA Request Challenge from %s to %s: %lx %lx\n",
3539 desthost, myhostname, clnt_chal.data[0], clnt_chal.data[1]));
3541 /* store the parameters */
3542 make_q_req_chal(&q_c, desthost, myhostname, &clnt_chal);
3544 /* turn parameters into data stream */
3545 p = lsa_io_q_req_chal(False, &q_c, param + 0x18, param, 4, 5);
3547 /* create the request RPC_HDR _after_ the main data: length is now known */
3548 create_rpc_request(call_id, LSA_REQCHAL, param, PTR_DIFF(p, param));
3550 /* send the data on \PIPE\NETLOGON */
3551 if (cli_call_api(PIPE_NETLOGON, PTR_DIFF(p, param),0,
3558 /* oh, now what??? */
3560 int res = SVAL(rparam,0);
3561 int converter=SVAL(rparam,2);
3563 BOOL long_share_name=False;
3567 count=SVAL(rparam,4);
3574 if (rparam) free(rparam);
3575 if (rdata) free(rdata);
3580 /****************************************************************************
3581 usage on the program
3582 ****************************************************************************/
3583 static void usage(char *pname)
3585 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3588 DEBUG(0,("\nVersion %s\n",VERSION));
3589 DEBUG(0,("\t-p port listen on the specified port\n"));
3590 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3591 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3592 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3593 DEBUG(0,("\t-N don't ask for a password\n"));
3594 DEBUG(0,("\t-P connect to service as a printer\n"));
3595 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3596 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3597 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3598 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3599 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3600 DEBUG(0,("\t-U username set the network username\n"));
3601 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3602 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3603 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3604 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
3605 DEBUG(0,("\t-D directory start from directory\n"));
3609 /****************************************************************************
3611 ****************************************************************************/
3612 int main(int argc,char *argv[])
3614 fstring base_directory;
3615 char *pname = argv[0];
3616 int port = SMB_PORT;
3619 extern char *optarg;
3622 BOOL message = False;
3623 BOOL nt_domain_logon = False;
3624 extern char tar_type;
3625 static pstring servicesf = CONFIGFILE;
3630 strcpy(term_code, KANJI);
3636 *base_directory = 0;
3640 setup_logging(pname,True);
3643 charset_initialise();
3654 strcpy(username,getenv("USER"));
3656 /* modification to support userid%passwd syntax in the USER var
3657 25.Aug.97, jdblair@uab.edu */
3659 if ((p=strchr(username,'%')))
3662 strcpy(password,p+1);
3664 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3669 /* modification to support PASSWD environmental var
3670 25.Aug.97, jdblair@uab.edu */
3672 if (getenv("PASSWD"))
3673 strcpy(password,getenv("PASSWD"));
3675 if (*username == 0 && getenv("LOGNAME"))
3677 strcpy(username,getenv("LOGNAME"));
3687 if (*argv[1] != '-')
3690 strcpy(service,argv[1]);
3691 /* Convert any '/' characters in the service name to '\' characters */
3692 string_replace( service, '/','\\');
3696 if (count_chars(service,'\\') < 3)
3699 printf("\n%s: Not enough '\\' characters in service\n",service);
3704 if (count_chars(service,'\\') > 3)
3707 printf("\n%s: Too many '\\' characters in service\n",service);
3712 if (argc > 1 && (*argv[1] != '-'))
3715 strcpy(password,argv[1]);
3716 memset(argv[1],'X',strlen(argv[1]));
3723 getopt(argc, argv,"s:B:O:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
3727 max_protocol = interpret_protocol(optarg,max_protocol);
3730 strcpy(user_socket_options,optarg);
3733 strcpy(desthost,optarg);
3735 nt_domain_logon = True;
3738 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3739 strcpy(desthost,optarg);
3744 iface_set_default(NULL,optarg,NULL);
3747 strcpy(base_directory,optarg);
3750 if (!tar_parseargs(argc, argv, optarg, optind)) {
3756 strcpy(scope,optarg);
3760 strcpy(query_host,optarg);
3765 strcpy(username,optarg);
3766 if ((lp=strchr(username,'%')))
3769 strcpy(password,lp+1);
3771 memset(strchr(optarg,'%')+1,'X',strlen(password));
3777 strcpy(workgroup,optarg);
3784 dest_ip = *interpret_addr2(optarg);
3785 if (zero_ip(dest_ip)) exit(1);
3790 strcpy(myname,optarg);
3796 connect_as_printer = True;
3802 DEBUGLEVEL = atoi(optarg);
3805 sprintf(debugf,"%s.client",optarg);
3808 port = atoi(optarg);
3819 strcpy(servicesf, optarg);
3822 strcpy(term_code, optarg);
3829 if (!tar_type && !*query_host && !*service && !message)
3836 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
3838 if(!get_myname(myhostname,NULL))
3840 DEBUG(0,("Failed to get my hostname.\n"));
3843 if (!lp_load(servicesf,True)) {
3844 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3847 codepage_initialise(lp_client_code_page());
3849 if(lp_client_code_page() == KANJI_CODEPAGE)
3851 if (!setup_term_code (term_code))
3853 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
3859 if (*workgroup == 0)
3860 strcpy(workgroup,lp_workgroup());
3863 get_myname((*myname)?NULL:myname,NULL);
3869 if (cli_open_sockets(port)) {
3870 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3871 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3874 if ((InBuffer == NULL) || (OutBuffer == NULL))
3877 bzero(OutBuffer,smb_size);
3878 if (!cli_send_login(InBuffer,OutBuffer,True,True))
3881 if (*base_directory) do_cd(base_directory);
3883 ret=process_tar(InBuffer, OutBuffer);
3892 if (*query_host && !nt_domain_logon)
3895 sprintf(service,"\\\\%s\\IPC$",query_host);
3897 connect_as_ipc = True;
3898 if (cli_open_sockets(port))
3903 if (!cli_send_login(NULL,NULL,True,True))
3907 if (!browse_host(True)) {
3911 if (!list_servers(workgroup)) {
3913 list_servers(workgroup);
3926 if (cli_open_sockets(port))
3928 pstring inbuf,outbuf;
3929 bzero(outbuf,smb_size);
3930 if (!cli_send_session_request(inbuf,outbuf))
3933 send_message(inbuf,outbuf);
3941 if (nt_domain_logon)
3944 sprintf(service,"\\\\%s\\IPC$",query_host);
3946 connect_as_ipc = True;
3948 DEBUG(5,("NT Domain Logon. Service: %s\n", service));
3950 if (cli_open_sockets(port))
3952 if (!cli_send_login(NULL,NULL,True,True))
3960 cli_lsa_sam_logon();
3961 cli_lsa_sam_logoff();
3970 if (cli_open_sockets(port))
3972 if (!process(base_directory))