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;
47 extern BOOL doencrypt;
49 extern pstring user_socket_options;
51 /* 30 second timeout on most commands */
52 #define CLIENT_TIMEOUT (30*1000)
53 #define SHORT_TIMEOUT (5*1000)
55 /* value for unused fid field in trans2 secondary request */
56 #define FID_UNUSED (0xFFFF)
60 extern int max_protocol;
63 time_t newer_than = 0;
64 int archive_level = 0;
66 extern pstring debugf;
67 extern int DEBUGLEVEL;
69 BOOL translation = False;
81 static int interpret_long_filename(int level,char *p,file_info *finfo);
82 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir);
83 static int interpret_short_filename(char *p,file_info *finfo);
84 static BOOL do_this_one(file_info *finfo);
86 /* clitar bits insert */
89 extern BOOL tar_reset;
101 BOOL recurse = False;
102 BOOL lowercase = False;
104 struct in_addr dest_ip;
106 #define SEPARATORS " \t\n\r"
108 BOOL abort_mget = True;
112 extern BOOL readbraw_supported ;
113 extern BOOL writebraw_supported;
115 pstring fileselection = "";
117 extern file_info def_finfo;
120 int get_total_size = 0;
121 int get_total_time_ms = 0;
122 int put_total_size = 0;
123 int put_total_time_ms = 0;
132 extern int coding_system;
133 static BOOL setup_term_code (char *code)
136 new = interpret_coding_system (code, UNKNOWN_CODE);
137 if (new != UNKNOWN_CODE) {
143 #define CNV_LANG(s) dos2unix_format(s,False)
144 #define CNV_INPUT(s) unix2dos_format(s,True)
146 /****************************************************************************
147 send an SMBclose on an SMB file handle
148 ****************************************************************************/
149 void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
151 bzero(outbuf,smb_size);
152 set_message(outbuf,3,0,True);
154 CVAL (outbuf,smb_com) = SMBclose;
155 SSVAL(outbuf,smb_tid,c_num);
156 cli_setup_pkt(outbuf);
157 SSVAL (outbuf,smb_vwv0, f_num);
158 SIVALS(outbuf,smb_vwv1, -1);
160 send_smb(clnt_fd, outbuf);
161 receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
164 /****************************************************************************
165 write to a local file with CR/LF->LF translation if appropriate. return the
166 number taken from the buffer. This may not equal the number written.
167 ****************************************************************************/
168 static int writefile(int f, char *b, int n)
173 return(write(f,b,n));
178 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
182 if (write(f, b, 1) != 1)
193 /****************************************************************************
194 read from a file with LF->CR/LF translation if appropriate. return the
195 number read. read approx n bytes.
196 ****************************************************************************/
197 static int readfile(char *b, int size, int n, FILE *f)
202 if (!translation || (size != 1))
203 return(fread(b,size,n,f));
208 if ((c = getc(f)) == EOF)
213 if (c == '\n') /* change all LFs to CR/LF */
227 /****************************************************************************
228 read from a file with print translation. return the number read. read approx n
230 ****************************************************************************/
231 static int printread(FILE *f,char *b,int n)
235 i = readfile(b,1, n-1,f);
244 /****************************************************************************
245 check for existance of a dir
246 ****************************************************************************/
247 static BOOL chkpath(char *path,BOOL report)
250 pstring inbuf,outbuf;
254 trim_string(path2,NULL,"\\");
255 if (!*path2) *path2 = '\\';
257 bzero(outbuf,smb_size);
258 set_message(outbuf,0,4 + strlen(path2),True);
259 SCVAL(outbuf,smb_com,SMBchkpth);
260 SSVAL(outbuf,smb_tid,cnum);
261 cli_setup_pkt(outbuf);
269 /* this little bit of code can be used to extract NT error codes.
270 Just feed a bunch of "cd foo" commands to smbclient then watch
271 in netmon (tridge) */
273 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
274 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
279 send_smb(Client,outbuf);
280 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
282 if (report && CVAL(inbuf,smb_rcls) != 0)
283 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
285 return(CVAL(inbuf,smb_rcls) == 0);
289 /****************************************************************************
291 ****************************************************************************/
292 static void send_message(char *inbuf,char *outbuf)
299 /* send a SMBsendstrt command */
300 bzero(outbuf,smb_size);
301 set_message(outbuf,0,0,True);
302 CVAL(outbuf,smb_com) = SMBsendstrt;
303 SSVAL(outbuf,smb_tid,cnum);
308 p = skip_string(p,1);
311 p = skip_string(p,1);
313 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
315 send_smb(Client,outbuf);
318 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
320 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
324 grp_id = SVAL(inbuf,smb_vwv0);
326 printf("Connected. Type your message, ending it with a Control-D\n");
328 while (!feof(stdin) && total_len < 1600)
330 int maxlen = MIN(1600 - total_len,127);
337 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
344 CVAL(outbuf,smb_com) = SMBsendtxt;
346 set_message(outbuf,1,l+3,True);
348 SSVAL(outbuf,smb_vwv0,grp_id);
355 send_smb(Client,outbuf);
358 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
360 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
367 if (total_len >= 1600)
368 printf("the message was truncated to 1600 bytes ");
370 printf("sent %d bytes ",total_len);
372 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
374 CVAL(outbuf,smb_com) = SMBsendend;
375 set_message(outbuf,1,0,False);
376 SSVAL(outbuf,smb_vwv0,grp_id);
378 send_smb(Client,outbuf);
381 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
383 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
390 /****************************************************************************
391 check the space on a device
392 ****************************************************************************/
393 static void do_dskattr(void)
395 pstring inbuf,outbuf;
397 bzero(outbuf,smb_size);
398 set_message(outbuf,0,0,True);
399 CVAL(outbuf,smb_com) = SMBdskattr;
400 SSVAL(outbuf,smb_tid,cnum);
401 cli_setup_pkt(outbuf);
403 send_smb(Client,outbuf);
404 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
406 if (CVAL(inbuf,smb_rcls) != 0)
407 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
409 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
410 SVAL(inbuf,smb_vwv0),
411 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
412 SVAL(inbuf,smb_vwv3)));
415 /****************************************************************************
417 ****************************************************************************/
418 static void cmd_pwd(void)
420 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
421 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
425 /****************************************************************************
426 change directory - inner section
427 ****************************************************************************/
428 static void do_cd(char *newdir)
434 /* Save the current directory in case the
435 new directory is invalid */
436 strcpy(saved_dir, cur_dir);
441 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
442 strcat(cur_dir, "\\");
444 dos_clean_name(cur_dir);
445 strcpy(dname,cur_dir);
446 strcat(cur_dir,"\\");
447 dos_clean_name(cur_dir);
449 if (!strequal(cur_dir,"\\"))
450 if (!chkpath(dname,True))
451 strcpy(cur_dir,saved_dir);
453 strcpy(cd_path,cur_dir);
456 /****************************************************************************
458 ****************************************************************************/
459 static void cmd_cd(char *inbuf,char *outbuf)
463 if (next_token(NULL,buf,NULL))
466 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
470 /****************************************************************************
471 display info about a file
472 ****************************************************************************/
473 static void display_finfo(file_info *finfo)
475 if (do_this_one(finfo)) {
476 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
477 DEBUG(0,(" %-30s%7.7s%10d %s",
478 CNV_LANG(finfo->name),
479 attrib_string(finfo->mode),
481 asctime(LocalTime(&t))));
482 dir_total += finfo->size;
487 /****************************************************************************
488 do a directory listing, calling fn on each file found. Use the TRANSACT2
489 call for long filenames
490 ****************************************************************************/
491 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
493 int max_matches = 512;
494 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
499 char *dirlist = NULL;
501 int total_received = 0;
503 char *resp_data=NULL;
504 char *resp_param=NULL;
505 int resp_data_len = 0;
506 int resp_param_len=0;
508 int ff_resume_key = 0;
509 int ff_searchcount=0;
523 if (loop_count > 200)
525 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
531 setup = TRANSACT2_FINDFIRST;
532 SSVAL(param,0,attribute); /* attribute */
533 SSVAL(param,2,max_matches); /* max count */
534 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
535 SSVAL(param,6,info_level);
537 strcpy(param+12,mask);
541 setup = TRANSACT2_FINDNEXT;
542 SSVAL(param,0,ff_dir_handle);
543 SSVAL(param,2,max_matches); /* max count */
544 SSVAL(param,4,info_level);
545 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
546 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
547 strcpy(param+12,mask);
549 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
550 ff_dir_handle,ff_resume_key,ff_lastname,mask));
552 /* ??? original code added 1 pad byte after param */
554 cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
556 0,12+strlen(mask)+1,1,
559 if (!cli_receive_trans_response(inbuf,SMBtrans2,
560 &resp_data_len,&resp_param_len,
561 &resp_data,&resp_param))
563 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
567 /* parse out some important return info */
571 ff_dir_handle = SVAL(p,0);
572 ff_searchcount = SVAL(p,2);
574 ff_lastname = SVAL(p,8);
578 ff_searchcount = SVAL(p,0);
580 ff_lastname = SVAL(p,6);
583 if (ff_searchcount == 0)
586 /* point to the data bytes */
589 /* we might need the lastname for continuations */
596 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
597 /* strcpy(mask,p+ff_lastname+94); */
600 strcpy(mask,p + ff_lastname + 1);
608 /* and add them to the dirlist pool */
609 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
613 DEBUG(0,("Failed to expand dirlist\n"));
617 /* put in a length for the last entry, to ensure we can chain entries
618 into the next packet */
621 for (p2=p,i=0;i<(ff_searchcount-1);i++)
622 p2 += interpret_long_filename(info_level,p2,NULL);
623 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
626 /* grab the data for later use */
627 memcpy(dirlist+dirlist_len,p,resp_data_len);
628 dirlist_len += resp_data_len;
630 total_received += ff_searchcount;
632 if (resp_data) free(resp_data); resp_data = NULL;
633 if (resp_param) free(resp_param); resp_param = NULL;
635 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
636 ff_searchcount,ff_eos,ff_resume_key));
642 for (p=dirlist,i=0;i<total_received;i++)
644 p += interpret_long_filename(info_level,p,&finfo);
645 display_finfo(&finfo);
648 for (p=dirlist,i=0;i<total_received;i++)
650 p += interpret_long_filename(info_level,p,&finfo);
651 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
654 /* free up the dirlist buffer */
655 if (dirlist) free(dirlist);
656 return(total_received);
660 /****************************************************************************
661 do a directory listing, calling fn on each file found
662 ****************************************************************************/
663 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
669 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
670 int num_received = 0;
672 char *dirlist = NULL;
684 bzero(outbuf,smb_size);
686 set_message(outbuf,2,5 + strlen(mask),True);
688 set_message(outbuf,2,5 + 21,True);
691 if (Protocol >= PROTOCOL_LANMAN1)
692 CVAL(outbuf,smb_com) = SMBffirst;
695 CVAL(outbuf,smb_com) = SMBsearch;
697 SSVAL(outbuf,smb_tid,cnum);
698 cli_setup_pkt(outbuf);
700 SSVAL(outbuf,smb_vwv0,num_asked);
701 SSVAL(outbuf,smb_vwv1,attribute);
722 send_smb(Client,outbuf);
723 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
725 received = SVAL(inbuf,smb_vwv0);
727 DEBUG(5,("dir received %d\n",received));
729 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
731 if (received <= 0) break;
735 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
740 p = smb_buf(inbuf) + 3;
742 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
743 p,received*DIR_STRUCT_SIZE);
745 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
747 num_received += received;
749 if (CVAL(inbuf,smb_rcls) != 0) break;
753 if (!first && Protocol >= PROTOCOL_LANMAN1)
755 bzero(outbuf,smb_size);
756 CVAL(outbuf,smb_com) = SMBfclose;
758 SSVAL(outbuf,smb_tid,cnum);
759 cli_setup_pkt(outbuf);
772 send_smb(Client,outbuf);
773 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
775 if (CVAL(inbuf,smb_rcls) != 0)
776 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
781 for (p=dirlist,i=0;i<num_received;i++)
783 p += interpret_short_filename(p,&finfo);
784 display_finfo(&finfo);
787 for (p=dirlist,i=0;i<num_received;i++)
789 p += interpret_short_filename(p,&finfo);
790 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
793 if (dirlist) free(dirlist);
794 return(num_received);
799 /****************************************************************************
800 do a directory listing, calling fn on each file found
801 ****************************************************************************/
802 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
804 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
805 if (Protocol >= PROTOCOL_LANMAN2)
807 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
811 expand_mask(Mask,False);
812 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
816 /*******************************************************************
817 decide if a file should be operated on
818 ********************************************************************/
819 static BOOL do_this_one(file_info *finfo)
821 if (finfo->mode & aDIR) return(True);
823 if (newer_than && finfo->mtime < newer_than)
826 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
833 /*****************************************************************************
834 Convert a character pointer in a cli_call_api() response to a form we can use.
835 This function contains code to prevent core dumps if the server returns
837 *****************************************************************************/
838 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
840 if( datap == 0 ) /* turn NULL pointers */
841 { /* into zero length strings */
846 unsigned int offset = datap - converter;
848 if( offset >= rdrcnt )
850 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
855 return &rdata[offset];
860 /****************************************************************************
861 interpret a short filename structure
862 The length of the structure is returned
863 ****************************************************************************/
864 static int interpret_short_filename(char *p,file_info *finfo)
866 finfo->mode = CVAL(p,21);
868 /* this date is converted to GMT by make_unix_date */
869 finfo->ctime = make_unix_date(p+22);
870 finfo->mtime = finfo->atime = finfo->ctime;
871 finfo->size = IVAL(p,26);
872 strcpy(finfo->name,p+30);
874 return(DIR_STRUCT_SIZE);
877 /****************************************************************************
878 interpret a long filename structure - this is mostly guesses at the moment
879 The length of the structure is returned
880 The structure of a long filename depends on the info level. 260 is used
881 by NT and 2 is used by OS/2
882 ****************************************************************************/
883 static int interpret_long_filename(int level,char *p,file_info *finfo)
886 memcpy(finfo,&def_finfo,sizeof(*finfo));
890 case 1: /* OS/2 understands this */
893 /* these dates are converted to GMT by make_unix_date */
894 finfo->ctime = make_unix_date2(p+4);
895 finfo->atime = make_unix_date2(p+8);
896 finfo->mtime = make_unix_date2(p+12);
897 finfo->size = IVAL(p,16);
898 finfo->mode = CVAL(p,24);
899 strcpy(finfo->name,p+27);
901 return(28 + CVAL(p,26));
903 case 2: /* this is what OS/2 uses mostly */
906 /* these dates are converted to GMT by make_unix_date */
907 finfo->ctime = make_unix_date2(p+4);
908 finfo->atime = make_unix_date2(p+8);
909 finfo->mtime = make_unix_date2(p+12);
910 finfo->size = IVAL(p,16);
911 finfo->mode = CVAL(p,24);
912 strcpy(finfo->name,p+31);
914 return(32 + CVAL(p,30));
916 /* levels 3 and 4 are untested */
920 /* these dates are probably like the other ones */
921 finfo->ctime = make_unix_date2(p+8);
922 finfo->atime = make_unix_date2(p+12);
923 finfo->mtime = make_unix_date2(p+16);
924 finfo->size = IVAL(p,20);
925 finfo->mode = CVAL(p,28);
926 strcpy(finfo->name,p+33);
933 /* these dates are probably like the other ones */
934 finfo->ctime = make_unix_date2(p+8);
935 finfo->atime = make_unix_date2(p+12);
936 finfo->mtime = make_unix_date2(p+16);
937 finfo->size = IVAL(p,20);
938 finfo->mode = CVAL(p,28);
939 strcpy(finfo->name,p+37);
943 case 260: /* NT uses this, but also accepts 2 */
948 p += 4; /* next entry offset */
949 p += 4; /* fileindex */
951 /* these dates appear to arrive in a weird way. It seems to
952 be localtime plus the serverzone given in the initial
953 connect. This is GMT when DST is not in effect and one
954 hour from GMT otherwise. Can this really be right??
956 I suppose this could be called kludge-GMT. Is is the GMT
957 you get by using the current DST setting on a different
958 localtime. It will be cheap to calculate, I suppose, as
959 no DST tables will be needed */
961 finfo->ctime = interpret_long_date(p); p += 8;
962 finfo->atime = interpret_long_date(p); p += 8;
963 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
964 finfo->size = IVAL(p,0); p += 8;
965 p += 8; /* alloc size */
966 finfo->mode = CVAL(p,0); p += 4;
967 namelen = IVAL(p,0); p += 4;
968 p += 4; /* EA size */
969 p += 2; /* short name len? */
970 p += 24; /* short name? */
971 StrnCpy(finfo->name,p,namelen);
977 DEBUG(1,("Unknown long filename format %d\n",level));
984 /****************************************************************************
985 act on the files in a dir listing
986 ****************************************************************************/
987 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
990 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
991 !mask_match(finfo->name,fileselection,False,False)) &&
992 !(recurse_dir && (strequal(finfo->name,".") ||
993 strequal(finfo->name,".."))))
995 if (recurse_dir && (finfo->mode & aDIR))
999 strcpy(sav_dir,cur_dir);
1000 strcat(cur_dir,finfo->name);
1001 strcat(cur_dir,"\\");
1002 strcpy(mask2,cur_dir);
1005 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1010 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);
1012 do_dir(inbuf,outbuf,mask2,attribute,fn,True);
1014 strcpy(cur_dir,sav_dir);
1018 if (fn && do_this_one(finfo))
1025 /****************************************************************************
1026 get a directory listing
1027 ****************************************************************************/
1028 static void cmd_dir(char *inbuf,char *outbuf)
1030 int attribute = aDIR | aSYSTEM | aHIDDEN;
1036 strcpy(mask,cur_dir);
1037 if(mask[strlen(mask)-1]!='\\')
1040 if (next_token(NULL,buf,NULL))
1051 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1055 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1060 /****************************************************************************
1061 get a file from rname to lname
1062 ****************************************************************************/
1063 static void do_get(char *rname,char *lname,file_info *finfo1)
1068 BOOL newhandle = False;
1069 char *inbuf,*outbuf;
1071 BOOL close_done = False;
1072 BOOL ignore_close_error = False;
1076 struct timeval tp_start;
1077 GetTimeOfDay(&tp_start);
1088 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1089 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1091 if (!inbuf || !outbuf)
1093 DEBUG(0,("out of memory\n"));
1097 bzero(outbuf,smb_size);
1098 set_message(outbuf,15,1 + strlen(rname),True);
1100 CVAL(outbuf,smb_com) = SMBopenX;
1101 SSVAL(outbuf,smb_tid,cnum);
1102 cli_setup_pkt(outbuf);
1104 SSVAL(outbuf,smb_vwv0,0xFF);
1105 SSVAL(outbuf,smb_vwv2,1); /* return additional info */
1106 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1107 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1108 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1109 SSVAL(outbuf,smb_vwv8,1);
1110 SSVAL(outbuf,smb_vwv11,0xffff);
1111 SSVAL(outbuf,smb_vwv12,0xffff);
1113 p = smb_buf(outbuf);
1115 p = skip_string(p,1);
1117 /* do a chained openX with a readX? */
1121 DEBUG(3,("Chaining readX wth openX\n"));
1122 SSVAL(outbuf,smb_vwv0,SMBreadX);
1123 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1126 SSVAL(p,smb_wct,10);
1127 SSVAL(p,smb_vwv0,0xFF);
1128 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1129 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1130 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1134 if(!strcmp(lname,"-"))
1135 handle = fileno(stdout);
1138 handle = creat(lname,0644);
1143 DEBUG(0,("Error opening local file %s\n",lname));
1144 free(inbuf);free(outbuf);
1148 send_smb(Client,outbuf);
1149 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1151 if (CVAL(inbuf,smb_rcls) != 0)
1153 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1154 SVAL(inbuf,smb_err) == ERRnoresource &&
1155 cli_reopen_connection(inbuf,outbuf))
1157 do_get(rname,lname,finfo1);
1160 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1163 free(inbuf);free(outbuf);
1167 strcpy(finfo.name,rname);
1171 finfo.mode = SVAL(inbuf,smb_vwv3);
1172 /* these times arrive as LOCAL time, using the DST offset
1173 corresponding to that time, we convert them to GMT */
1174 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1175 finfo.atime = finfo.ctime = finfo.mtime;
1176 finfo.size = IVAL(inbuf,smb_vwv6);
1179 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1181 fnum = SVAL(inbuf,smb_vwv2);
1183 /* we might have got some data from a chained readX */
1184 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1186 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1187 datalen = SVAL(p,smb_vwv5);
1188 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1197 DEBUG(2,("getting file %s of size %d bytes as %s ",
1198 CNV_LANG(finfo.name),
1202 while (nread < finfo.size && !close_done)
1205 static BOOL can_chain_close = True;
1209 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1211 /* 3 possible read types. readbraw if a large block is required.
1212 readX + close if not much left and read if neither is supported */
1214 /* we might have already read some data from a chained readX */
1215 if (dataptr && datalen>0)
1218 /* if we can finish now then readX+close */
1219 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1220 ((finfo.size - nread) <
1221 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1224 /* if we support readraw then use that */
1225 if (method<0 && readbraw_supported)
1228 /* if we can then use readX */
1229 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1240 /* use readX + close */
1241 bzero(outbuf,smb_size);
1242 set_message(outbuf,10,0,True);
1243 CVAL(outbuf,smb_com) = SMBreadX;
1244 SSVAL(outbuf,smb_tid,cnum);
1245 cli_setup_pkt(outbuf);
1249 CVAL(outbuf,smb_vwv0) = SMBclose;
1250 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1253 CVAL(outbuf,smb_vwv0) = 0xFF;
1255 SSVAL(outbuf,smb_vwv2,fnum);
1256 SIVAL(outbuf,smb_vwv3,nread);
1257 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1258 SSVAL(outbuf,smb_vwv6,0);
1259 SIVAL(outbuf,smb_vwv7,0);
1260 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1264 p = smb_buf(outbuf);
1271 /* now set the total packet length */
1272 smb_setlen(outbuf,smb_len(outbuf)+9);
1275 send_smb(Client,outbuf);
1276 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1278 if (CVAL(inbuf,smb_rcls) != 0)
1280 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1285 SVAL(inbuf,smb_vwv0) != SMBclose)
1287 /* NOTE: WfWg sometimes just ignores the chained
1288 command! This seems to break the spec? */
1289 DEBUG(3,("Rejected chained close?\n"));
1291 can_chain_close = False;
1292 ignore_close_error = True;
1295 datalen = SVAL(inbuf,smb_vwv5);
1296 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1302 static int readbraw_size = BUFFER_SIZE;
1305 bzero(outbuf,smb_size);
1306 set_message(outbuf,8,0,True);
1307 CVAL(outbuf,smb_com) = SMBreadbraw;
1308 SSVAL(outbuf,smb_tid,cnum);
1309 cli_setup_pkt(outbuf);
1310 SSVAL(outbuf,smb_vwv0,fnum);
1311 SIVAL(outbuf,smb_vwv1,nread);
1312 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1313 SSVAL(outbuf,smb_vwv4,0);
1314 SIVALS(outbuf,smb_vwv5,-1);
1315 send_smb(Client,outbuf);
1317 /* Now read the raw data into the buffer and write it */
1318 if(read_smb_length(Client,inbuf,0) == -1) {
1319 DEBUG(0,("Failed to read length in readbraw\n"));
1323 /* Even though this is not an smb message, smb_len
1324 returns the generic length of an smb message */
1325 datalen = smb_len(inbuf);
1329 /* we got a readbraw error */
1330 DEBUG(4,("readbraw error - reducing size\n"));
1331 readbraw_size = (readbraw_size * 9) / 10;
1333 if (readbraw_size < max_xmit)
1335 DEBUG(0,("disabling readbraw\n"));
1336 readbraw_supported = False;
1343 if(read_data(Client,inbuf,datalen) != datalen) {
1344 DEBUG(0,("Failed to read data in readbraw\n"));
1352 /* we've already read some data with a chained readX */
1356 /* use plain read */
1357 bzero(outbuf,smb_size);
1358 set_message(outbuf,5,0,True);
1359 CVAL(outbuf,smb_com) = SMBread;
1360 SSVAL(outbuf,smb_tid,cnum);
1361 cli_setup_pkt(outbuf);
1363 SSVAL(outbuf,smb_vwv0,fnum);
1364 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1365 SIVAL(outbuf,smb_vwv2,nread);
1366 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1368 send_smb(Client,outbuf);
1369 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1371 if (CVAL(inbuf,smb_rcls) != 0)
1373 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1377 datalen = SVAL(inbuf,smb_vwv0);
1378 dataptr = smb_buf(inbuf) + 3;
1382 if (writefile(handle,dataptr,datalen) != datalen)
1384 DEBUG(0,("Error writing local file\n"));
1391 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1403 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1405 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1407 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1410 free(inbuf);free(outbuf);
1418 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1419 bzero(outbuf,smb_size);
1420 set_message(outbuf,8,strlen(rname)+4,True);
1421 CVAL(outbuf,smb_com) = SMBsetatr;
1422 SSVAL(outbuf,smb_tid,cnum);
1423 cli_setup_pkt(outbuf);
1424 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1425 SIVALS(outbuf,smb_vwv1,0);
1426 p = smb_buf(outbuf);
1432 send_smb(Client,outbuf);
1433 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1437 struct timeval tp_end;
1440 GetTimeOfDay(&tp_end);
1442 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1443 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1444 get_total_time_ms += this_time;
1445 get_total_size += finfo.size;
1447 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1448 finfo.size / (1.024*this_time + 1.0e-4),
1449 get_total_size / (1.024*get_total_time_ms)));
1452 free(inbuf);free(outbuf);
1456 /****************************************************************************
1458 ****************************************************************************/
1459 static void cmd_get(void)
1465 strcpy(rname,cur_dir);
1468 p = rname + strlen(rname);
1470 if (!next_token(NULL,p,NULL)) {
1471 DEBUG(0,("get <filename>\n"));
1475 dos_clean_name(rname);
1477 next_token(NULL,lname,NULL);
1479 do_get(rname,lname,NULL);
1483 /****************************************************************************
1484 do a mget operation on one file
1485 ****************************************************************************/
1486 static void do_mget(file_info *finfo)
1491 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1496 DEBUG(0,("mget aborted\n"));
1500 if (finfo->mode & aDIR)
1501 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1503 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1505 if (prompt && !yesno(quest)) return;
1507 if (finfo->mode & aDIR)
1509 pstring saved_curdir;
1511 char *inbuf,*outbuf;
1513 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1514 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1516 if (!inbuf || !outbuf)
1518 DEBUG(0,("out of memory\n"));
1522 strcpy(saved_curdir,cur_dir);
1524 strcat(cur_dir,finfo->name);
1525 strcat(cur_dir,"\\");
1527 unix_format(finfo->name);
1530 strlower(finfo->name);
1532 if (!directory_exist(finfo->name,NULL) &&
1533 sys_mkdir(finfo->name,0777) != 0)
1535 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1536 strcpy(cur_dir,saved_curdir);
1537 free(inbuf);free(outbuf);
1541 if (sys_chdir(finfo->name) != 0)
1543 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1544 strcpy(cur_dir,saved_curdir);
1545 free(inbuf);free(outbuf);
1550 strcpy(mget_mask,cur_dir);
1551 strcat(mget_mask,"*");
1553 do_dir((char *)inbuf,(char *)outbuf,
1554 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1556 strcpy(cur_dir,saved_curdir);
1557 free(inbuf);free(outbuf);
1561 strcpy(rname,cur_dir);
1562 strcat(rname,finfo->name);
1563 do_get(rname,finfo->name,finfo);
1567 /****************************************************************************
1568 view the file using the pager
1569 ****************************************************************************/
1570 static void cmd_more(void)
1572 fstring rname,lname,tmpname,pager_cmd;
1575 strcpy(rname,cur_dir);
1577 sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1578 strcpy(lname,tmpname);
1580 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1581 DEBUG(0,("more <filename>\n"));
1584 dos_clean_name(rname);
1586 do_get(rname,lname,NULL);
1588 pager=getenv("PAGER");
1589 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1596 /****************************************************************************
1598 ****************************************************************************/
1599 static void cmd_mget(char *inbuf,char *outbuf)
1601 int attribute = aSYSTEM | aHIDDEN;
1613 while (next_token(NULL,p,NULL))
1615 strcpy(mget_mask,cur_dir);
1616 if(mget_mask[strlen(mget_mask)-1]!='\\')
1617 strcat(mget_mask,"\\");
1620 strcpy(mget_mask,p);
1622 strcat(mget_mask,p);
1623 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1628 strcpy(mget_mask,cur_dir);
1629 if(mget_mask[strlen(mget_mask)-1]!='\\')
1630 strcat(mget_mask,"\\");
1631 strcat(mget_mask,"*");
1632 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1636 /****************************************************************************
1637 make a directory of name "name"
1638 ****************************************************************************/
1639 static BOOL do_mkdir(char *name)
1642 char *inbuf,*outbuf;
1644 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1645 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1647 if (!inbuf || !outbuf)
1649 DEBUG(0,("out of memory\n"));
1653 bzero(outbuf,smb_size);
1654 set_message(outbuf,0,2 + strlen(name),True);
1656 CVAL(outbuf,smb_com) = SMBmkdir;
1657 SSVAL(outbuf,smb_tid,cnum);
1658 cli_setup_pkt(outbuf);
1661 p = smb_buf(outbuf);
1665 send_smb(Client,outbuf);
1666 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1668 if (CVAL(inbuf,smb_rcls) != 0)
1670 DEBUG(0,("%s making remote directory %s\n",
1671 smb_errstr(inbuf),CNV_LANG(name)));
1673 free(inbuf);free(outbuf);
1677 free(inbuf);free(outbuf);
1682 /****************************************************************************
1684 ****************************************************************************/
1685 static void cmd_mkdir(char *inbuf,char *outbuf)
1691 strcpy(mask,cur_dir);
1693 if (!next_token(NULL,p,NULL))
1696 DEBUG(0,("mkdir <dirname>\n"));
1708 trim_string(ddir,".",NULL);
1709 p = strtok(ddir,"/\\");
1713 if (!chkpath(ddir2,False))
1718 p = strtok(NULL,"/\\");
1726 /*******************************************************************
1727 write to a file using writebraw
1728 ********************************************************************/
1729 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1734 bzero(outbuf,smb_size);
1735 bzero(inbuf,smb_size);
1736 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1738 CVAL(outbuf,smb_com) = SMBwritebraw;
1739 SSVAL(outbuf,smb_tid,cnum);
1740 cli_setup_pkt(outbuf);
1742 SSVAL(outbuf,smb_vwv0,fnum);
1743 SSVAL(outbuf,smb_vwv1,n);
1744 SIVAL(outbuf,smb_vwv3,pos);
1745 SSVAL(outbuf,smb_vwv7,1);
1747 send_smb(Client,outbuf);
1749 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1752 _smb_setlen(buf-4,n); /* HACK! XXXX */
1754 if (write_socket(Client,buf-4,n+4) != n+4)
1757 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1758 DEBUG(0,("Error writing remote file (2)\n"));
1761 return(SVAL(inbuf,smb_vwv0));
1766 /*******************************************************************
1768 ********************************************************************/
1769 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1773 if (writebraw_supported && n > (max_xmit-200))
1774 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1776 bzero(outbuf,smb_size);
1777 bzero(inbuf,smb_size);
1778 set_message(outbuf,5,n + 3,True);
1780 CVAL(outbuf,smb_com) = SMBwrite;
1781 SSVAL(outbuf,smb_tid,cnum);
1782 cli_setup_pkt(outbuf);
1784 SSVAL(outbuf,smb_vwv0,fnum);
1785 SSVAL(outbuf,smb_vwv1,n);
1786 SIVAL(outbuf,smb_vwv2,pos);
1787 SSVAL(outbuf,smb_vwv4,0);
1788 CVAL(smb_buf(outbuf),0) = 1;
1789 SSVAL(smb_buf(outbuf),1,n);
1791 memcpy(smb_buf(outbuf)+3,buf,n);
1793 send_smb(Client,outbuf);
1794 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1796 if (CVAL(inbuf,smb_rcls) != 0) {
1797 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1800 return(SVAL(inbuf,smb_vwv0));
1805 /****************************************************************************
1807 ****************************************************************************/
1808 static void do_put(char *rname,char *lname,file_info *finfo)
1814 char *inbuf,*outbuf;
1815 time_t close_time = finfo->mtime;
1817 static int maxwrite=0;
1819 struct timeval tp_start;
1820 GetTimeOfDay(&tp_start);
1822 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1823 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1825 if (!inbuf || !outbuf)
1827 DEBUG(0,("out of memory\n"));
1831 bzero(outbuf,smb_size);
1832 set_message(outbuf,3,2 + strlen(rname),True);
1834 if (finfo->mtime == 0 || finfo->mtime == -1)
1835 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1837 CVAL(outbuf,smb_com) = SMBcreate;
1838 SSVAL(outbuf,smb_tid,cnum);
1839 cli_setup_pkt(outbuf);
1841 SSVAL(outbuf,smb_vwv0,finfo->mode);
1842 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1844 p = smb_buf(outbuf);
1848 send_smb(Client,outbuf);
1849 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1851 if (CVAL(inbuf,smb_rcls) != 0)
1853 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1855 free(inbuf);free(outbuf);if (buf) free(buf);
1859 f = fopen(lname,"r");
1863 DEBUG(0,("Error opening local file %s\n",lname));
1864 free(inbuf);free(outbuf);
1869 fnum = SVAL(inbuf,smb_vwv0);
1870 if (finfo->size < 0)
1871 finfo->size = file_size(lname);
1873 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1876 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1878 while (nread < finfo->size)
1883 n = MIN(n,finfo->size - nread);
1885 buf = (char *)Realloc(buf,n+4);
1887 fseek(f,nread,SEEK_SET);
1888 if ((n = readfile(buf+4,1,n,f)) < 1)
1890 DEBUG(0,("Error reading local file\n"));
1894 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1898 DEBUG(0,("Error writing file\n"));
1911 bzero(outbuf,smb_size);
1912 set_message(outbuf,3,0,True);
1913 CVAL(outbuf,smb_com) = SMBclose;
1914 SSVAL(outbuf,smb_tid,cnum);
1915 cli_setup_pkt(outbuf);
1917 SSVAL(outbuf,smb_vwv0,fnum);
1918 put_dos_date3(outbuf,smb_vwv1,close_time);
1920 send_smb(Client,outbuf);
1921 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1923 if (CVAL(inbuf,smb_rcls) != 0)
1925 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1927 free(inbuf);free(outbuf);
1934 free(inbuf);free(outbuf);
1938 struct timeval tp_end;
1941 GetTimeOfDay(&tp_end);
1943 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1944 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1945 put_total_time_ms += this_time;
1946 put_total_size += finfo->size;
1948 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1949 finfo->size / (1.024*this_time + 1.0e-4),
1950 put_total_size / (1.024*put_total_time_ms)));
1956 /****************************************************************************
1958 ****************************************************************************/
1959 static void cmd_put(void)
1968 strcpy(rname,cur_dir);
1972 if (!next_token(NULL,p,NULL))
1974 DEBUG(0,("put <filename>\n"));
1979 if (next_token(NULL,p,NULL))
1982 strcat(rname,lname);
1984 dos_clean_name(rname);
1988 if (!file_exist(lname,&st)) {
1989 DEBUG(0,("%s does not exist\n",lname));
1992 finfo.mtime = st.st_mtime;
1995 do_put(rname,lname,&finfo);
1998 /****************************************************************************
1999 seek in a directory/file list until you get something that doesn't start with
2001 ****************************************************************************/
2002 static BOOL seek_list(FILE *f,char *name)
2007 if (fscanf(f,"%s",s) != 1) return(False);
2008 trim_string(s,"./",NULL);
2009 if (strncmp(s,name,strlen(name)) != 0)
2020 /****************************************************************************
2021 set the file selection mask
2022 ****************************************************************************/
2023 static void cmd_select(void)
2025 strcpy(fileselection,"");
2026 next_token(NULL,fileselection,NULL);
2030 /****************************************************************************
2032 ****************************************************************************/
2033 static void cmd_mput(void)
2044 while (next_token(NULL,p,NULL))
2051 sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2053 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2055 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2058 f = fopen(tmpname,"r");
2065 if (fscanf(f,"%s",lname) != 1) break;
2066 trim_string(lname,"./",NULL);
2070 /* check if it's a directory */
2071 if (directory_exist(lname,&st))
2073 if (!recurse) continue;
2074 sprintf(quest,"Put directory %s? ",lname);
2075 if (prompt && !yesno(quest))
2078 if (!seek_list(f,lname))
2083 strcpy(rname,cur_dir);
2084 strcat(rname,lname);
2085 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2087 if (!seek_list(f,lname))
2096 sprintf(quest,"Put file %s? ",lname);
2097 if (prompt && !yesno(quest)) continue;
2099 strcpy(rname,cur_dir);
2100 strcat(rname,lname);
2104 /* null size so do_put knows to ignore it */
2107 /* set the date on the file */
2108 finfo.mtime = st.st_mtime;
2110 do_put(rname,lname,&finfo);
2117 /****************************************************************************
2119 ****************************************************************************/
2120 static void do_cancel(int job)
2122 char *rparam = NULL;
2128 bzero(param,sizeof(param));
2131 SSVAL(p,0,81); /* DosPrintJobDel() */
2134 p = skip_string(p,1);
2136 p = skip_string(p,1);
2140 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2146 int res = SVAL(rparam,0);
2149 printf("Job %d cancelled\n",job);
2151 printf("Error %d calcelling job %d\n",res,job);
2155 printf("Server refused cancel request\n");
2157 if (rparam) free(rparam);
2158 if (rdata) free(rdata);
2164 /****************************************************************************
2166 ****************************************************************************/
2167 static void cmd_cancel(char *inbuf,char *outbuf )
2172 if (!connect_as_printer)
2174 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2175 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2178 if (!next_token(NULL,buf,NULL)) {
2179 printf("cancel <jobid> ...\n");
2185 } while (next_token(NULL,buf,NULL));
2189 /****************************************************************************
2191 ****************************************************************************/
2192 static void cmd_stat(char *inbuf,char *outbuf)
2196 char *resp_data=NULL;
2197 char *resp_param=NULL;
2198 int resp_data_len = 0;
2199 int resp_param_len=0;
2201 uint16 setup = TRANSACT2_QPATHINFO;
2203 if (!next_token(NULL,buf,NULL)) {
2204 printf("stat <file>\n");
2209 SSVAL(param,0,4); /* level */
2214 cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
2216 0,6 + strlen(p)+1,1,
2219 cli_receive_trans_response(inbuf,SMBtrans2,
2220 &resp_data_len,&resp_param_len,
2221 &resp_data,&resp_param);
2223 if (resp_data) free(resp_data); resp_data = NULL;
2224 if (resp_param) free(resp_param); resp_param = NULL;
2228 /****************************************************************************
2230 ****************************************************************************/
2231 static void cmd_print(char *inbuf,char *outbuf )
2240 if (!connect_as_printer)
2242 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2243 DEBUG(0,("Trying to print without -P may fail\n"));
2246 if (!next_token(NULL,lname,NULL))
2248 DEBUG(0,("print <filename>\n"));
2252 strcpy(rname,lname);
2253 p = strrchr(rname,'/');
2258 strcpy(rname,tname);
2261 if ((int)strlen(rname) > 14)
2264 if (strequal(lname,"-"))
2267 strcpy(rname,"stdin");
2270 dos_clean_name(rname);
2272 bzero(outbuf,smb_size);
2273 set_message(outbuf,2,2 + strlen(rname),True);
2275 CVAL(outbuf,smb_com) = SMBsplopen;
2276 SSVAL(outbuf,smb_tid,cnum);
2277 cli_setup_pkt(outbuf);
2279 SSVAL(outbuf,smb_vwv0,0);
2280 SSVAL(outbuf,smb_vwv1,printmode);
2282 p = smb_buf(outbuf);
2286 send_smb(Client,outbuf);
2287 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2289 if (CVAL(inbuf,smb_rcls) != 0)
2291 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2296 f = fopen(lname,"r");
2299 DEBUG(0,("Error opening local file %s\n",lname));
2304 fnum = SVAL(inbuf,smb_vwv0);
2306 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2312 bzero(outbuf,smb_size);
2313 set_message(outbuf,1,3,True);
2315 /* for some strange reason the OS/2 print server can't handle large
2316 packets when printing. weird */
2317 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2320 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2322 n = readfile(smb_buf(outbuf)+3,1,n,f);
2325 DEBUG(0,("read gave %d\n",n));
2329 smb_setlen(outbuf,smb_len(outbuf) + n);
2331 CVAL(outbuf,smb_com) = SMBsplwr;
2332 SSVAL(outbuf,smb_tid,cnum);
2333 cli_setup_pkt(outbuf);
2335 SSVAL(outbuf,smb_vwv0,fnum);
2336 SSVAL(outbuf,smb_vwv1,n+3);
2337 CVAL(smb_buf(outbuf),0) = 1;
2338 SSVAL(smb_buf(outbuf),1,n);
2340 send_smb(Client,outbuf);
2341 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2343 if (CVAL(inbuf,smb_rcls) != 0)
2345 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2352 DEBUG(2,("%d bytes printed\n",nread));
2354 bzero(outbuf,smb_size);
2355 set_message(outbuf,1,0,True);
2356 CVAL(outbuf,smb_com) = SMBsplclose;
2357 SSVAL(outbuf,smb_tid,cnum);
2358 cli_setup_pkt(outbuf);
2360 SSVAL(outbuf,smb_vwv0,fnum);
2362 send_smb(Client,outbuf);
2363 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2365 if (CVAL(inbuf,smb_rcls) != 0)
2367 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2377 /****************************************************************************
2378 show a print queue - this is deprecated as it uses the old smb that
2379 has limited support - the correct call is the cmd_p_queue_4() after this.
2380 ****************************************************************************/
2381 static void cmd_queue(char *inbuf,char *outbuf )
2386 bzero(outbuf,smb_size);
2387 set_message(outbuf,2,0,True);
2389 CVAL(outbuf,smb_com) = SMBsplretq;
2390 SSVAL(outbuf,smb_tid,cnum);
2391 cli_setup_pkt(outbuf);
2393 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2394 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2396 send_smb(Client,outbuf);
2397 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2399 if (CVAL(inbuf,smb_rcls) != 0)
2401 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2405 count = SVAL(inbuf,smb_vwv0);
2406 p = smb_buf(inbuf) + 3;
2409 DEBUG(0,("No entries in the print queue\n"));
2416 DEBUG(0,("Job Name Size Status\n"));
2422 case 0x01: sprintf(status,"held or stopped"); break;
2423 case 0x02: sprintf(status,"printing"); break;
2424 case 0x03: sprintf(status,"awaiting print"); break;
2425 case 0x04: sprintf(status,"in intercept"); break;
2426 case 0x05: sprintf(status,"file had error"); break;
2427 case 0x06: sprintf(status,"printer error"); break;
2428 default: sprintf(status,"unknown"); break;
2431 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2432 SVAL(p,5),p+12,IVAL(p,7),status));
2440 /****************************************************************************
2441 show information about a print queue
2442 ****************************************************************************/
2443 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2445 char *rparam = NULL;
2452 if (!connect_as_printer)
2454 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2455 DEBUG(0,("Trying to print without -P may fail\n"));
2458 bzero(param,sizeof(param));
2461 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2463 strcpy(p,"zWrLeh"); /* parameter description? */
2464 p = skip_string(p,1);
2465 strcpy(p,"WWzWWDDzz"); /* returned data format */
2466 p = skip_string(p,1);
2467 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2468 p = skip_string(p,1);
2469 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2470 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2472 strcpy(p,""); /* subformat */
2473 p = skip_string(p,1);
2475 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2476 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0,
2483 result_code = SVAL(rparam,0);
2484 converter = SVAL(rparam,2); /* conversion factor */
2486 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2488 if (result_code == 0) /* if no error, */
2498 char PrinterName[20];
2500 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2501 strlower(PrinterName); /* in lower case */
2503 p = rdata; /* received data */
2504 for( i = 0; i < SVAL(rparam,4); ++i)
2507 Priority = SVAL(p,2);
2508 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2510 Priority = SVAL(p,2);
2511 JobTime = make_unix_date3( p + 12);
2512 JobTimeStr = asctime(LocalTime( &JobTime));
2514 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2517 printf("%s-%u %s priority %u %s %s %u bytes\n",
2518 PrinterName, JobId, UserName,
2519 Priority, JobTimeStr, JobName, Size);
2521 #if 0 /* DEBUG code */
2522 printf("Job Id: \"%u\"\n", SVAL(p,0));
2523 printf("Priority: \"%u\"\n", SVAL(p,2));
2525 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2526 printf("Position: \"%u\"\n", SVAL(p,8));
2527 printf("Status: \"%u\"\n", SVAL(p,10));
2529 JobTime = make_unix_date3( p + 12);
2530 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2531 printf("date: \"%u\"\n", SVAL(p,12));
2533 printf("Size: \"%u\"\n", SVAL(p,16));
2534 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2535 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2536 #endif /* DEBUG CODE */
2541 else /* cli_call_api() failed */
2543 printf("Failed, error = %d\n", result_code);
2546 /* If any parameters or data were returned, free the storage. */
2547 if(rparam) free(rparam);
2548 if(rdata) free(rdata);
2553 /****************************************************************************
2554 show information about a print queue
2555 ****************************************************************************/
2556 static void cmd_qinfo(char *inbuf,char *outbuf )
2558 char *rparam = NULL;
2565 bzero(param,sizeof(param));
2568 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2570 strcpy(p,"zWrLh"); /* parameter description? */
2571 p = skip_string(p,1);
2572 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2573 p = skip_string(p,1);
2574 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2575 p = skip_string(p,1);
2576 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2577 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2579 strcpy(p,""); /* subformat */
2580 p = skip_string(p,1);
2582 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2583 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2590 result_code = SVAL(rparam,0);
2591 converter = SVAL(rparam,2); /* conversion factor */
2593 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2595 if (result_code == 0) /* if no error, */
2597 p = rdata; /* received data */
2599 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2600 printf("Priority: %u\n", SVAL(p,4) );
2601 printf("Start time: %u\n", SVAL(p,6) );
2602 printf("Until time: %u\n", SVAL(p,8) );
2603 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2604 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2605 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2606 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2607 printf("Status: %u\n", SVAL(p,28) );
2608 printf("Jobs: %u\n", SVAL(p,30) );
2609 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2610 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2612 /* Dump the driver data */
2617 ddptr = rdata + SVAL(p,40) - converter;
2618 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2619 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2621 for(x=8; x < count; x+=16)
2623 for(y=0; y < 16; y++)
2626 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2630 for(y=0; y < 16 && (x+y) < count; y++)
2632 c = CVAL(ddptr,(x+y));
2638 fputc('\n', stdout);
2644 else /* cli_call_api() failed */
2646 printf("Failed, error = %d\n", result_code);
2649 /* If any parameters or data were returned, free the storage. */
2650 if(rparam) free(rparam);
2651 if(rdata) free(rdata);
2656 /****************************************************************************
2658 ****************************************************************************/
2659 static void do_del(file_info *finfo)
2662 char *inbuf,*outbuf;
2665 strcpy(mask,cur_dir);
2666 strcat(mask,finfo->name);
2668 if (finfo->mode & aDIR)
2671 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2672 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2674 if (!inbuf || !outbuf)
2676 DEBUG(0,("out of memory\n"));
2680 bzero(outbuf,smb_size);
2681 set_message(outbuf,1,2 + strlen(mask),True);
2683 CVAL(outbuf,smb_com) = SMBunlink;
2684 SSVAL(outbuf,smb_tid,cnum);
2685 cli_setup_pkt(outbuf);
2687 SSVAL(outbuf,smb_vwv0,0);
2689 p = smb_buf(outbuf);
2693 send_smb(Client,outbuf);
2694 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2696 if (CVAL(inbuf,smb_rcls) != 0)
2697 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2699 free(inbuf);free(outbuf);
2703 /****************************************************************************
2705 ****************************************************************************/
2706 static void cmd_del(char *inbuf,char *outbuf )
2710 int attribute = aSYSTEM | aHIDDEN;
2715 strcpy(mask,cur_dir);
2717 if (!next_token(NULL,buf,NULL))
2719 DEBUG(0,("del <filename>\n"));
2724 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2728 /****************************************************************************
2730 ****************************************************************************/
2731 static void cmd_rmdir(char *inbuf,char *outbuf )
2737 strcpy(mask,cur_dir);
2739 if (!next_token(NULL,buf,NULL))
2741 DEBUG(0,("rmdir <dirname>\n"));
2746 bzero(outbuf,smb_size);
2747 set_message(outbuf,0,2 + strlen(mask),True);
2749 CVAL(outbuf,smb_com) = SMBrmdir;
2750 SSVAL(outbuf,smb_tid,cnum);
2751 cli_setup_pkt(outbuf);
2754 p = smb_buf(outbuf);
2758 send_smb(Client,outbuf);
2759 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2761 if (CVAL(inbuf,smb_rcls) != 0)
2763 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2769 /****************************************************************************
2771 ****************************************************************************/
2772 static void cmd_rename(char *inbuf,char *outbuf )
2778 strcpy(src,cur_dir);
2779 strcpy(dest,cur_dir);
2781 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2783 DEBUG(0,("rename <src> <dest>\n"));
2789 bzero(outbuf,smb_size);
2790 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2792 CVAL(outbuf,smb_com) = SMBmv;
2793 SSVAL(outbuf,smb_tid,cnum);
2794 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2795 cli_setup_pkt(outbuf);
2797 p = smb_buf(outbuf);
2800 p = skip_string(p,1);
2804 send_smb(Client,outbuf);
2805 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2807 if (CVAL(inbuf,smb_rcls) != 0)
2809 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2816 /****************************************************************************
2817 toggle the prompt flag
2818 ****************************************************************************/
2819 static void cmd_prompt(void)
2822 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2826 /****************************************************************************
2827 set the newer than time
2828 ****************************************************************************/
2829 static void cmd_newer(void)
2835 ok = next_token(NULL,buf,NULL);
2836 if (ok && (sys_stat(buf,&sbuf) == 0))
2838 newer_than = sbuf.st_mtime;
2839 DEBUG(1,("Getting files newer than %s",
2840 asctime(LocalTime(&newer_than))));
2845 if (ok && newer_than == 0)
2846 DEBUG(0,("Error setting newer-than time\n"));
2849 /****************************************************************************
2850 set the archive level
2851 ****************************************************************************/
2852 static void cmd_archive(void)
2856 if (next_token(NULL,buf,NULL)) {
2857 archive_level = atoi(buf);
2859 DEBUG(0,("Archive level is %d\n",archive_level));
2862 /****************************************************************************
2863 toggle the lowercaseflag
2864 ****************************************************************************/
2865 static void cmd_lowercase(void)
2867 lowercase = !lowercase;
2868 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2874 /****************************************************************************
2875 toggle the recurse flag
2876 ****************************************************************************/
2877 static void cmd_recurse(void)
2880 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2883 /****************************************************************************
2884 toggle the translate flag
2885 ****************************************************************************/
2886 static void cmd_translate(void)
2888 translation = !translation;
2889 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2890 translation?"on":"off"));
2894 /****************************************************************************
2895 do a printmode command
2896 ****************************************************************************/
2897 static void cmd_printmode(void)
2902 if (next_token(NULL,buf,NULL))
2904 if (strequal(buf,"text"))
2908 if (strequal(buf,"graphics"))
2911 printmode = atoi(buf);
2918 strcpy(mode,"text");
2921 strcpy(mode,"graphics");
2924 sprintf(mode,"%d",printmode);
2928 DEBUG(2,("the printmode is now %s\n",mode));
2931 /****************************************************************************
2933 ****************************************************************************/
2934 static void cmd_lcd(void)
2939 if (next_token(NULL,buf,NULL))
2941 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2945 /****************************************************************************
2946 try and browse available connections on a host
2947 ****************************************************************************/
2948 static BOOL browse_host(BOOL sort)
2951 /* If strcasecmp is already defined, remove it. */
2954 #endif /* strcasecmp */
2955 #define strcasecmp StrCaseCmp
2956 #endif /* NOSTRCASECMP */
2958 extern int strcasecmp();
2960 char *rparam = NULL;
2967 /* now send a SMBtrans command with api RNetShareEnum */
2969 SSVAL(p,0,0); /* api number */
2972 p = skip_string(p,1);
2974 p = skip_string(p,1);
2976 SSVAL(p,2,BUFFER_SIZE);
2979 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2985 int res = SVAL(rparam,0);
2986 int converter=SVAL(rparam,2);
2988 BOOL long_share_name=False;
2992 count=SVAL(rparam,4);
2997 printf("\n\tSharename Type Comment\n");
2998 printf("\t--------- ---- -------\n");
3002 qsort(p,count,20,QSORT_CAST strcasecmp);
3004 for (i=0;i<count;i++)
3007 int type = SVAL(p,14);
3008 int comment_offset = IVAL(p,16) & 0xFFFF;
3014 case STYPE_DISKTREE:
3015 strcpy(typestr,"Disk"); break;
3017 strcpy(typestr,"Printer"); break;
3019 strcpy(typestr,"Device"); break;
3021 strcpy(typestr,"IPC"); break;
3024 printf("\t%-15.15s%-10.10s%s\n",
3027 comment_offset?rdata+comment_offset-converter:"");
3029 if (strlen(sname)>8) long_share_name=True;
3034 if (long_share_name) {
3035 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3040 if (rparam) free(rparam);
3041 if (rdata) free(rdata);
3047 /****************************************************************************
3048 get some server info
3049 ****************************************************************************/
3050 static void server_info()
3052 char *rparam = NULL;
3058 bzero(param,sizeof(param));
3061 SSVAL(p,0,63); /* NetServerGetInfo()? */
3064 p = skip_string(p,1);
3065 strcpy(p,"zzzBBzz");
3066 p = skip_string(p,1);
3067 SSVAL(p,0,10); /* level 10 */
3071 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3077 int res = SVAL(rparam,0);
3078 int converter=SVAL(rparam,2);
3084 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3085 rdata+SVAL(p,0)-converter,
3086 rdata+SVAL(p,4)-converter,
3087 rdata+SVAL(p,8)-converter,
3088 rdata+SVAL(p,14)-converter);
3092 if (rparam) free(rparam);
3093 if (rdata) free(rdata);
3099 /****************************************************************************
3100 try and browse available connections on a host
3101 ****************************************************************************/
3102 static BOOL list_servers(char *wk_grp)
3104 char *rparam = NULL;
3112 BOOL generic_request = False;
3115 if (strequal(wk_grp,"WORKGROUP")) {
3116 /* we won't specify a workgroup */
3117 generic_request = True;
3120 /* now send a SMBtrans command with api ServerEnum? */
3122 SSVAL(p,0,0x68); /* api number */
3125 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3126 p = skip_string(p,1);
3128 strcpy(p,"B16BBDz");
3130 p = skip_string(p,1);
3132 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3138 if (!generic_request) {
3140 p = skip_string(p,1);
3143 /* first ask for a list of servers in this workgroup */
3144 SIVAL(svtype_p,0,SV_TYPE_ALL);
3146 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3147 8, BUFFER_SIZE - SAFETY_MARGIN,
3152 int res = SVAL(rparam,0);
3153 int converter=SVAL(rparam,2);
3158 count=SVAL(rparam,4);
3161 printf("\n\nThis machine has a browse list:\n");
3162 printf("\n\tServer Comment\n");
3163 printf("\t--------- -------\n");
3166 for (i=0;i<count;i++) {
3168 int comment_offset = IVAL(p2,22) & 0xFFFF;
3169 printf("\t%-16.16s %s\n",
3171 comment_offset?rdata+comment_offset-converter:"");
3179 if (rparam) {free(rparam); rparam = NULL;}
3180 if (rdata) {free(rdata); rdata = NULL;}
3182 /* now ask for a list of workgroups */
3183 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3185 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3186 8, BUFFER_SIZE - SAFETY_MARGIN,
3191 int res = SVAL(rparam,0);
3192 int converter=SVAL(rparam,2);
3197 count=SVAL(rparam,4);
3200 printf("\n\nThis machine has a workgroup list:\n");
3201 printf("\n\tWorkgroup Master\n");
3202 printf("\t--------- -------\n");
3205 for (i=0;i<count;i++) {
3207 int comment_offset = IVAL(p2,22) & 0xFFFF;
3208 printf("\t%-16.16s %s\n",
3210 comment_offset?rdata+comment_offset-converter:"");
3218 if (rparam) free(rparam);
3219 if (rdata) free(rdata);
3225 /* This defines the commands supported by this client */
3233 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3234 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3235 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3236 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3237 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3238 {"get",cmd_get,"<remote name> [local name] get a file"},
3239 {"mget",cmd_mget,"<mask> get all the matching files"},
3240 {"put",cmd_put,"<local name> [remote name] put a file"},
3241 {"mput",cmd_mput,"<mask> put all matching files"},
3242 {"rename",cmd_rename,"<src> <dest> rename some files"},
3243 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3244 {"mask",cmd_select,"<mask> mask all filenames against this"},
3245 {"del",cmd_del,"<mask> delete all matching files"},
3246 {"rm",cmd_del,"<mask> delete all matching files"},
3247 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3248 {"md",cmd_mkdir,"<directory> make a directory"},
3249 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
3250 {"rd",cmd_rmdir,"<directory> remove a directory"},
3251 {"pq",cmd_p_queue_4,"enumerate the print queue"},
3252 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
3253 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
3254 {"translate",cmd_translate,"toggle text translation for printing"},
3255 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
3256 {"print",cmd_print,"<file name> print a file"},
3257 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
3258 {"queue",cmd_queue,"show the print queue"},
3259 {"qinfo",cmd_qinfo,"show print queue information"},
3260 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
3261 {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
3262 {"quit",cli_send_logout,"logoff the server"},
3263 {"q",cli_send_logout,"logoff the server"},
3264 {"exit",cli_send_logout,"logoff the server"},
3265 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
3266 {"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"},
3267 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3268 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
3269 {"tarmode",cmd_tarmode,
3270 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3271 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
3272 {"help",cmd_help,"[command] give help on a command"},
3273 {"?",cmd_help,"[command] give help on a command"},
3274 {"!",NULL,"run a shell command on the local system"},
3279 /*******************************************************************
3280 lookup a command string in the list of commands, including
3282 ******************************************************************/
3283 static int process_tok(fstring tok)
3285 int i = 0, matches = 0;
3287 int tok_len = strlen(tok);
3289 while (commands[i].fn != NULL)
3291 if (strequal(commands[i].name,tok))
3297 else if (strnequal(commands[i].name, tok, tok_len+1))
3307 else if (matches == 1)
3313 /****************************************************************************
3315 ****************************************************************************/
3321 if (next_token(NULL,buf,NULL))
3323 if ((i = process_tok(buf)) >= 0)
3324 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3327 while (commands[i].description)
3329 for (j=0; commands[i].description && (j<5); j++) {
3330 DEBUG(0,("%-15s",commands[i].name));
3337 /****************************************************************************
3338 wait for keyboard activity, swallowing network packets
3339 ****************************************************************************/
3341 static char wait_keyboard(char *buffer)
3343 static void wait_keyboard(char *buffer)
3348 struct timeval timeout;
3358 FD_SET(Client,&fds);
3360 FD_SET(fileno(stdin),&fds);
3363 timeout.tv_sec = 20;
3364 timeout.tv_usec = 0;
3368 selrtn = sys_select(&fds,&timeout);
3371 if (FD_ISSET(fileno(stdin),&fds))
3378 set_blocking(fileno(stdin), False);
3379 readret = read_data( fileno(stdin), &ch, 1);
3380 set_blocking(fileno(stdin), True);
3383 if (errno != EAGAIN)
3385 /* should crash here */
3386 DEBUG(1,("readchar stdin failed\n"));
3389 else if (readret != 0)
3395 if (FD_ISSET(Client,&fds))
3396 receive_smb(Client,buffer,0);
3403 chkpath("\\",False);
3406 chkpath("\\",False);
3412 /****************************************************************************
3413 process commands from the client
3414 ****************************************************************************/
3415 static BOOL process(char *base_directory)
3421 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3422 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3424 if ((InBuffer == NULL) || (OutBuffer == NULL))
3427 bzero(OutBuffer,smb_size);
3429 if (!cli_send_login(InBuffer,OutBuffer,True,True))
3432 if (*base_directory) do_cd(base_directory);
3435 if (cmd[0] != '\0') while (cmd[0] != '\0')
3441 if ((p = strchr(cmd, ';')) == 0)
3443 strncpy(line, cmd, 999);
3449 if (p - cmd > 999) p = cmd + 999;
3450 strncpy(line, cmd, p - cmd);
3451 line[p - cmd] = '\0';
3455 /* input language code to internal one */
3458 /* and get the first part of the command */
3461 if (!next_token(&ptr,tok,NULL)) continue;
3464 if ((i = process_tok(tok)) >= 0)
3465 commands[i].fn(InBuffer,OutBuffer);
3467 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3469 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3471 else while (!feof(stdin))
3476 bzero(OutBuffer,smb_size);
3478 /* display a prompt */
3479 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3483 line[0] = wait_keyboard(InBuffer);
3484 /* this might not be such a good idea... */
3485 if ( line[0] == EOF)
3488 wait_keyboard(InBuffer);
3491 /* and get a response */
3493 fgets( &line[1],999, stdin);
3495 if (!fgets(line,1000,stdin))
3499 /* input language code to internal one */
3502 /* special case - first char is ! */
3509 /* and get the first part of the command */
3512 if (!next_token(&ptr,tok,NULL)) continue;
3515 if ((i = process_tok(tok)) >= 0)
3516 commands[i].fn(InBuffer,OutBuffer);
3518 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3520 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3527 /****************************************************************************
3528 usage on the program
3529 ****************************************************************************/
3530 static void usage(char *pname)
3532 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3535 DEBUG(0,("\nVersion %s\n",VERSION));
3536 DEBUG(0,("\t-p port listen on the specified port\n"));
3537 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3538 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3539 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3540 DEBUG(0,("\t-N don't ask for a password\n"));
3541 DEBUG(0,("\t-P connect to service as a printer\n"));
3542 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3543 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3544 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3545 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3546 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3547 DEBUG(0,("\t-U username set the network username\n"));
3548 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3549 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3550 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3551 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
3552 DEBUG(0,("\t-D directory start from directory\n"));
3556 /****************************************************************************
3558 ****************************************************************************/
3559 int main(int argc,char *argv[])
3561 fstring base_directory;
3562 char *pname = argv[0];
3563 int port = SMB_PORT;
3566 extern char *optarg;
3569 BOOL message = False;
3570 BOOL nt_domain_logon = False;
3571 extern char tar_type;
3572 static pstring servicesf = CONFIGFILE;
3577 strcpy(term_code, KANJI);
3583 *base_directory = 0;
3587 setup_logging(pname,True);
3590 charset_initialise();
3601 strcpy(username,getenv("USER"));
3603 /* modification to support userid%passwd syntax in the USER var
3604 25.Aug.97, jdblair@uab.edu */
3606 if ((p=strchr(username,'%')))
3609 strcpy(password,p+1);
3611 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3616 /* modification to support PASSWD environmental var
3617 25.Aug.97, jdblair@uab.edu */
3619 if (getenv("PASSWD"))
3620 strcpy(password,getenv("PASSWD"));
3622 if (*username == 0 && getenv("LOGNAME"))
3624 strcpy(username,getenv("LOGNAME"));
3634 if (*argv[1] != '-')
3637 strcpy(service,argv[1]);
3638 /* Convert any '/' characters in the service name to '\' characters */
3639 string_replace( service, '/','\\');
3643 if (count_chars(service,'\\') < 3)
3646 printf("\n%s: Not enough '\\' characters in service\n",service);
3651 if (count_chars(service,'\\') > 3)
3654 printf("\n%s: Too many '\\' characters in service\n",service);
3659 if (argc > 1 && (*argv[1] != '-'))
3662 strcpy(password,argv[1]);
3663 memset(argv[1],'X',strlen(argv[1]));
3670 getopt(argc, argv,"s:B:O:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
3674 max_protocol = interpret_protocol(optarg,max_protocol);
3677 strcpy(user_socket_options,optarg);
3680 strcpy(desthost,optarg);
3682 nt_domain_logon = True;
3685 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3686 strcpy(desthost,optarg);
3691 iface_set_default(NULL,optarg,NULL);
3694 strcpy(base_directory,optarg);
3697 if (!tar_parseargs(argc, argv, optarg, optind)) {
3703 strcpy(scope,optarg);
3707 strcpy(query_host,optarg);
3712 strcpy(username,optarg);
3713 if ((lp=strchr(username,'%')))
3716 strcpy(password,lp+1);
3718 memset(strchr(optarg,'%')+1,'X',strlen(password));
3724 strcpy(workgroup,optarg);
3731 dest_ip = *interpret_addr2(optarg);
3732 if (zero_ip(dest_ip)) exit(1);
3737 strcpy(myname,optarg);
3743 connect_as_printer = True;
3749 DEBUGLEVEL = atoi(optarg);
3752 sprintf(debugf,"%s.client",optarg);
3755 port = atoi(optarg);
3766 strcpy(servicesf, optarg);
3769 strcpy(term_code, optarg);
3776 if (!tar_type && !*query_host && !*service && !message)
3783 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
3785 if(!get_myname(myhostname,NULL))
3787 DEBUG(0,("Failed to get my hostname.\n"));
3790 if (!lp_load(servicesf,True)) {
3791 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3794 codepage_initialise(lp_client_code_page());
3796 if(lp_client_code_page() == KANJI_CODEPAGE)
3798 if (!setup_term_code (term_code))
3800 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
3806 if (*workgroup == 0)
3807 strcpy(workgroup,lp_workgroup());
3810 get_myname((*myname)?NULL:myname,NULL);
3816 if (cli_open_sockets(port)) {
3817 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3818 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3821 if ((InBuffer == NULL) || (OutBuffer == NULL))
3824 bzero(OutBuffer,smb_size);
3825 if (!cli_send_login(InBuffer,OutBuffer,True,True))
3828 if (*base_directory) do_cd(base_directory);
3830 ret=process_tar(InBuffer, OutBuffer);
3839 if (*query_host && !nt_domain_logon)
3842 sprintf(service,"\\\\%s\\IPC$",query_host);
3844 connect_as_ipc = True;
3845 if (cli_open_sockets(port))
3850 if (!cli_send_login(NULL,NULL,True,True))
3854 if (!browse_host(True)) {
3858 if (!list_servers(workgroup)) {
3860 list_servers(workgroup);
3873 if (cli_open_sockets(port))
3875 pstring inbuf,outbuf;
3876 bzero(outbuf,smb_size);
3877 if (!cli_send_session_request(inbuf,outbuf))
3880 send_message(inbuf,outbuf);
3890 if (nt_domain_logon)
3893 sprintf(service,"\\\\%s\\IPC$",query_host);
3895 connect_as_ipc = True;
3897 DEBUG(5,("NT Domain Logon. Service: %s\n", service));
3899 if (cli_open_sockets(port))
3901 if (!cli_send_login(NULL,NULL,True,True)) return(1);
3903 do_nt_login(desthost, myhostname, Client, cnum);
3913 if (cli_open_sockets(port))
3915 if (!process(base_directory))