2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 pstring cur_dir = "\\";
34 extern pstring service;
35 extern pstring desthost;
36 extern pstring 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 static BOOL setup_term_code(char *code)
134 interpret_coding_system(code);
137 #define CNV_LANG(s) dos2unix_format(s,False)
138 #define CNV_INPUT(s) unix2dos_format(s,True)
140 /****************************************************************************
141 send an SMBclose on an SMB file handle
142 ****************************************************************************/
143 void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
145 bzero(outbuf,smb_size);
146 set_message(outbuf,3,0,True);
148 CVAL (outbuf,smb_com) = SMBclose;
149 SSVAL(outbuf,smb_tid,c_num);
150 cli_setup_pkt(outbuf);
151 SSVAL (outbuf,smb_vwv0, f_num);
152 SIVALS(outbuf,smb_vwv1, -1);
154 send_smb(clnt_fd, outbuf);
155 client_receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
158 /****************************************************************************
159 write to a local file with CR/LF->LF translation if appropriate. return the
160 number taken from the buffer. This may not equal the number written.
161 ****************************************************************************/
162 static int writefile(int f, char *b, int n)
167 return(write(f,b,n));
172 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
176 if (write(f, b, 1) != 1)
187 /****************************************************************************
188 read from a file with LF->CR/LF translation if appropriate. return the
189 number read. read approx n bytes.
190 ****************************************************************************/
191 static int readfile(char *b, int size, int n, FILE *f)
196 if (!translation || (size != 1))
197 return(fread(b,size,n,f));
202 if ((c = getc(f)) == EOF)
207 if (c == '\n') /* change all LFs to CR/LF */
221 /****************************************************************************
222 read from a file with print translation. return the number read. read approx n
224 ****************************************************************************/
225 static int printread(FILE *f,char *b,int n)
229 i = readfile(b,1, n-1,f);
238 /****************************************************************************
239 check for existance of a dir
240 ****************************************************************************/
241 static BOOL chkpath(char *path,BOOL report)
244 pstring inbuf,outbuf;
248 trim_string(path2,NULL,"\\");
249 if (!*path2) *path2 = '\\';
251 bzero(outbuf,smb_size);
252 set_message(outbuf,0,4 + strlen(path2),True);
253 SCVAL(outbuf,smb_com,SMBchkpth);
254 SSVAL(outbuf,smb_tid,cnum);
255 cli_setup_pkt(outbuf);
263 /* this little bit of code can be used to extract NT error codes.
264 Just feed a bunch of "cd foo" commands to smbclient then watch
265 in netmon (tridge) */
267 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
268 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
273 send_smb(Client,outbuf);
274 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
276 if (report && CVAL(inbuf,smb_rcls) != 0)
277 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
279 return(CVAL(inbuf,smb_rcls) == 0);
283 /****************************************************************************
285 ****************************************************************************/
286 static void send_message(char *inbuf,char *outbuf)
293 /* send a SMBsendstrt command */
294 bzero(outbuf,smb_size);
295 set_message(outbuf,0,0,True);
296 CVAL(outbuf,smb_com) = SMBsendstrt;
297 SSVAL(outbuf,smb_tid,cnum);
302 p = skip_string(p,1);
305 p = skip_string(p,1);
307 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
309 send_smb(Client,outbuf);
312 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
314 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
318 grp_id = SVAL(inbuf,smb_vwv0);
320 printf("Connected. Type your message, ending it with a Control-D\n");
322 while (!feof(stdin) && total_len < 1600)
324 int maxlen = MIN(1600 - total_len,127);
331 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
338 CVAL(outbuf,smb_com) = SMBsendtxt;
340 set_message(outbuf,1,l+3,True);
342 SSVAL(outbuf,smb_vwv0,grp_id);
349 send_smb(Client,outbuf);
352 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
354 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
361 if (total_len >= 1600)
362 printf("the message was truncated to 1600 bytes ");
364 printf("sent %d bytes ",total_len);
366 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
368 CVAL(outbuf,smb_com) = SMBsendend;
369 set_message(outbuf,1,0,False);
370 SSVAL(outbuf,smb_vwv0,grp_id);
372 send_smb(Client,outbuf);
375 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
377 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
384 /****************************************************************************
385 check the space on a device
386 ****************************************************************************/
387 static void do_dskattr(void)
389 pstring inbuf,outbuf;
391 bzero(outbuf,smb_size);
392 set_message(outbuf,0,0,True);
393 CVAL(outbuf,smb_com) = SMBdskattr;
394 SSVAL(outbuf,smb_tid,cnum);
395 cli_setup_pkt(outbuf);
397 send_smb(Client,outbuf);
398 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
400 if (CVAL(inbuf,smb_rcls) != 0)
401 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
403 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
404 SVAL(inbuf,smb_vwv0),
405 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
406 SVAL(inbuf,smb_vwv3)));
409 /****************************************************************************
411 ****************************************************************************/
412 static void cmd_pwd(void)
414 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
415 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
419 /****************************************************************************
420 change directory - inner section
421 ****************************************************************************/
422 static void do_cd(char *newdir)
428 /* Save the current directory in case the
429 new directory is invalid */
430 strcpy(saved_dir, cur_dir);
435 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
436 strcat(cur_dir, "\\");
438 dos_clean_name(cur_dir);
439 strcpy(dname,cur_dir);
440 strcat(cur_dir,"\\");
441 dos_clean_name(cur_dir);
443 if (!strequal(cur_dir,"\\"))
444 if (!chkpath(dname,True))
445 strcpy(cur_dir,saved_dir);
447 strcpy(cd_path,cur_dir);
450 /****************************************************************************
452 ****************************************************************************/
453 static void cmd_cd(char *inbuf,char *outbuf)
457 if (next_token(NULL,buf,NULL))
460 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
464 /****************************************************************************
465 display info about a file
466 ****************************************************************************/
467 static void display_finfo(file_info *finfo)
469 if (do_this_one(finfo)) {
470 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
471 DEBUG(0,(" %-30s%7.7s%10d %s",
472 CNV_LANG(finfo->name),
473 attrib_string(finfo->mode),
475 asctime(LocalTime(&t))));
476 dir_total += finfo->size;
481 /****************************************************************************
482 do a directory listing, calling fn on each file found. Use the TRANSACT2
483 call for long filenames
484 ****************************************************************************/
485 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
487 int max_matches = 512;
488 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
493 char *dirlist = NULL;
495 int total_received = 0;
497 char *resp_data=NULL;
498 char *resp_param=NULL;
499 int resp_data_len = 0;
500 int resp_param_len=0;
502 int ff_resume_key = 0;
503 int ff_searchcount=0;
517 if (loop_count > 200)
519 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
525 setup = TRANSACT2_FINDFIRST;
526 SSVAL(param,0,attribute); /* attribute */
527 SSVAL(param,2,max_matches); /* max count */
528 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
529 SSVAL(param,6,info_level);
531 strcpy(param+12,mask);
535 setup = TRANSACT2_FINDNEXT;
536 SSVAL(param,0,ff_dir_handle);
537 SSVAL(param,2,max_matches); /* max count */
538 SSVAL(param,4,info_level);
539 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
540 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
541 strcpy(param+12,mask);
543 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
544 ff_dir_handle,ff_resume_key,ff_lastname,mask));
546 /* ??? original code added 1 pad byte after param */
548 cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
550 0,12+strlen(mask)+1,1,
553 if (!cli_receive_trans_response(inbuf,SMBtrans2,
554 &resp_data_len,&resp_param_len,
555 &resp_data,&resp_param))
557 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
561 /* parse out some important return info */
565 ff_dir_handle = SVAL(p,0);
566 ff_searchcount = SVAL(p,2);
568 ff_lastname = SVAL(p,8);
572 ff_searchcount = SVAL(p,0);
574 ff_lastname = SVAL(p,6);
577 if (ff_searchcount == 0)
580 /* point to the data bytes */
583 /* we might need the lastname for continuations */
590 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
591 /* strcpy(mask,p+ff_lastname+94); */
594 strcpy(mask,p + ff_lastname + 1);
602 /* and add them to the dirlist pool */
603 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
607 DEBUG(0,("Failed to expand dirlist\n"));
611 /* put in a length for the last entry, to ensure we can chain entries
612 into the next packet */
615 for (p2=p,i=0;i<(ff_searchcount-1);i++)
616 p2 += interpret_long_filename(info_level,p2,NULL);
617 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
620 /* grab the data for later use */
621 memcpy(dirlist+dirlist_len,p,resp_data_len);
622 dirlist_len += resp_data_len;
624 total_received += ff_searchcount;
626 if (resp_data) free(resp_data); resp_data = NULL;
627 if (resp_param) free(resp_param); resp_param = NULL;
629 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
630 ff_searchcount,ff_eos,ff_resume_key));
636 for (p=dirlist,i=0;i<total_received;i++)
638 p += interpret_long_filename(info_level,p,&finfo);
639 display_finfo(&finfo);
642 for (p=dirlist,i=0;i<total_received;i++)
644 p += interpret_long_filename(info_level,p,&finfo);
645 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
648 /* free up the dirlist buffer */
649 if (dirlist) free(dirlist);
650 return(total_received);
654 /****************************************************************************
655 do a directory listing, calling fn on each file found
656 ****************************************************************************/
657 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
663 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
664 int num_received = 0;
666 char *dirlist = NULL;
678 bzero(outbuf,smb_size);
680 set_message(outbuf,2,5 + strlen(mask),True);
682 set_message(outbuf,2,5 + 21,True);
685 if (Protocol >= PROTOCOL_LANMAN1)
686 CVAL(outbuf,smb_com) = SMBffirst;
689 CVAL(outbuf,smb_com) = SMBsearch;
691 SSVAL(outbuf,smb_tid,cnum);
692 cli_setup_pkt(outbuf);
694 SSVAL(outbuf,smb_vwv0,num_asked);
695 SSVAL(outbuf,smb_vwv1,attribute);
716 send_smb(Client,outbuf);
717 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
719 received = SVAL(inbuf,smb_vwv0);
721 DEBUG(5,("dir received %d\n",received));
723 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
725 if (received <= 0) break;
729 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
734 p = smb_buf(inbuf) + 3;
736 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
737 p,received*DIR_STRUCT_SIZE);
739 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
741 num_received += received;
743 if (CVAL(inbuf,smb_rcls) != 0) break;
747 if (!first && Protocol >= PROTOCOL_LANMAN1)
749 bzero(outbuf,smb_size);
750 CVAL(outbuf,smb_com) = SMBfclose;
752 SSVAL(outbuf,smb_tid,cnum);
753 cli_setup_pkt(outbuf);
766 send_smb(Client,outbuf);
767 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
769 if (CVAL(inbuf,smb_rcls) != 0)
770 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
775 for (p=dirlist,i=0;i<num_received;i++)
777 p += interpret_short_filename(p,&finfo);
778 display_finfo(&finfo);
781 for (p=dirlist,i=0;i<num_received;i++)
783 p += interpret_short_filename(p,&finfo);
784 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
787 if (dirlist) free(dirlist);
788 return(num_received);
793 /****************************************************************************
794 do a directory listing, calling fn on each file found
795 ****************************************************************************/
796 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
798 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
799 if (Protocol >= PROTOCOL_LANMAN2)
801 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
805 expand_mask(Mask,False);
806 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
810 /*******************************************************************
811 decide if a file should be operated on
812 ********************************************************************/
813 static BOOL do_this_one(file_info *finfo)
815 if (finfo->mode & aDIR) return(True);
817 if (newer_than && finfo->mtime < newer_than)
820 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
827 /*****************************************************************************
828 Convert a character pointer in a cli_call_api() response to a form we can use.
829 This function contains code to prevent core dumps if the server returns
831 *****************************************************************************/
832 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
834 if( datap == 0 ) /* turn NULL pointers */
835 { /* into zero length strings */
840 unsigned int offset = datap - converter;
842 if( offset >= rdrcnt )
844 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
849 return &rdata[offset];
854 /****************************************************************************
855 interpret a short filename structure
856 The length of the structure is returned
857 ****************************************************************************/
858 static int interpret_short_filename(char *p,file_info *finfo)
860 finfo->mode = CVAL(p,21);
862 /* this date is converted to GMT by make_unix_date */
863 finfo->ctime = make_unix_date(p+22);
864 finfo->mtime = finfo->atime = finfo->ctime;
865 finfo->size = IVAL(p,26);
866 strcpy(finfo->name,p+30);
868 return(DIR_STRUCT_SIZE);
871 /****************************************************************************
872 interpret a long filename structure - this is mostly guesses at the moment
873 The length of the structure is returned
874 The structure of a long filename depends on the info level. 260 is used
875 by NT and 2 is used by OS/2
876 ****************************************************************************/
877 static int interpret_long_filename(int level,char *p,file_info *finfo)
880 memcpy(finfo,&def_finfo,sizeof(*finfo));
884 case 1: /* OS/2 understands this */
887 /* these dates are converted to GMT by make_unix_date */
888 finfo->ctime = make_unix_date2(p+4);
889 finfo->atime = make_unix_date2(p+8);
890 finfo->mtime = make_unix_date2(p+12);
891 finfo->size = IVAL(p,16);
892 finfo->mode = CVAL(p,24);
893 strcpy(finfo->name,p+27);
895 return(28 + CVAL(p,26));
897 case 2: /* this is what OS/2 uses mostly */
900 /* these dates are converted to GMT by make_unix_date */
901 finfo->ctime = make_unix_date2(p+4);
902 finfo->atime = make_unix_date2(p+8);
903 finfo->mtime = make_unix_date2(p+12);
904 finfo->size = IVAL(p,16);
905 finfo->mode = CVAL(p,24);
906 strcpy(finfo->name,p+31);
908 return(32 + CVAL(p,30));
910 /* levels 3 and 4 are untested */
914 /* these dates are probably like the other ones */
915 finfo->ctime = make_unix_date2(p+8);
916 finfo->atime = make_unix_date2(p+12);
917 finfo->mtime = make_unix_date2(p+16);
918 finfo->size = IVAL(p,20);
919 finfo->mode = CVAL(p,28);
920 strcpy(finfo->name,p+33);
927 /* these dates are probably like the other ones */
928 finfo->ctime = make_unix_date2(p+8);
929 finfo->atime = make_unix_date2(p+12);
930 finfo->mtime = make_unix_date2(p+16);
931 finfo->size = IVAL(p,20);
932 finfo->mode = CVAL(p,28);
933 strcpy(finfo->name,p+37);
937 case 260: /* NT uses this, but also accepts 2 */
942 p += 4; /* next entry offset */
943 p += 4; /* fileindex */
945 /* these dates appear to arrive in a weird way. It seems to
946 be localtime plus the serverzone given in the initial
947 connect. This is GMT when DST is not in effect and one
948 hour from GMT otherwise. Can this really be right??
950 I suppose this could be called kludge-GMT. Is is the GMT
951 you get by using the current DST setting on a different
952 localtime. It will be cheap to calculate, I suppose, as
953 no DST tables will be needed */
955 finfo->ctime = interpret_long_date(p); p += 8;
956 finfo->atime = interpret_long_date(p); p += 8;
957 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
958 finfo->size = IVAL(p,0); p += 8;
959 p += 8; /* alloc size */
960 finfo->mode = CVAL(p,0); p += 4;
961 namelen = IVAL(p,0); p += 4;
962 p += 4; /* EA size */
963 p += 2; /* short name len? */
964 p += 24; /* short name? */
965 StrnCpy(finfo->name,p,namelen);
971 DEBUG(1,("Unknown long filename format %d\n",level));
978 /****************************************************************************
979 act on the files in a dir listing
980 ****************************************************************************/
981 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
984 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
985 !mask_match(finfo->name,fileselection,False,False)) &&
986 !(recurse_dir && (strequal(finfo->name,".") ||
987 strequal(finfo->name,".."))))
989 if (recurse_dir && (finfo->mode & aDIR))
993 strcpy(sav_dir,cur_dir);
994 strcat(cur_dir,finfo->name);
995 strcat(cur_dir,"\\");
996 strcpy(mask2,cur_dir);
999 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1004 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);
1006 do_dir(inbuf,outbuf,mask2,attribute,fn,True);
1008 strcpy(cur_dir,sav_dir);
1012 if (fn && do_this_one(finfo))
1019 /****************************************************************************
1020 get a directory listing
1021 ****************************************************************************/
1022 static void cmd_dir(char *inbuf,char *outbuf)
1024 int attribute = aDIR | aSYSTEM | aHIDDEN;
1030 strcpy(mask,cur_dir);
1031 if(mask[strlen(mask)-1]!='\\')
1034 if (next_token(NULL,buf,NULL))
1045 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1049 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1054 /****************************************************************************
1055 get a file from rname to lname
1056 ****************************************************************************/
1057 static void do_get(char *rname,char *lname,file_info *finfo1)
1062 BOOL newhandle = False;
1063 char *inbuf,*outbuf;
1065 BOOL close_done = False;
1066 BOOL ignore_close_error = False;
1070 struct timeval tp_start;
1071 GetTimeOfDay(&tp_start);
1082 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1083 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1085 if (!inbuf || !outbuf)
1087 DEBUG(0,("out of memory\n"));
1091 bzero(outbuf,smb_size);
1092 set_message(outbuf,15,1 + strlen(rname),True);
1094 CVAL(outbuf,smb_com) = SMBopenX;
1095 SSVAL(outbuf,smb_tid,cnum);
1096 cli_setup_pkt(outbuf);
1098 SSVAL(outbuf,smb_vwv0,0xFF);
1099 SSVAL(outbuf,smb_vwv2,1); /* return additional info */
1100 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1101 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1102 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1103 SSVAL(outbuf,smb_vwv8,1);
1104 SSVAL(outbuf,smb_vwv11,0xffff);
1105 SSVAL(outbuf,smb_vwv12,0xffff);
1107 p = smb_buf(outbuf);
1109 p = skip_string(p,1);
1111 /* do a chained openX with a readX? */
1115 DEBUG(3,("Chaining readX wth openX\n"));
1116 SSVAL(outbuf,smb_vwv0,SMBreadX);
1117 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1120 SSVAL(p,smb_wct,10);
1121 SSVAL(p,smb_vwv0,0xFF);
1122 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1123 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1124 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1128 if(!strcmp(lname,"-"))
1129 handle = fileno(stdout);
1132 handle = creat(lname,0644);
1137 DEBUG(0,("Error opening local file %s\n",lname));
1138 free(inbuf);free(outbuf);
1142 send_smb(Client,outbuf);
1143 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1145 if (CVAL(inbuf,smb_rcls) != 0)
1147 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1148 SVAL(inbuf,smb_err) == ERRnoresource &&
1149 cli_reopen_connection(inbuf,outbuf))
1151 do_get(rname,lname,finfo1);
1154 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1157 free(inbuf);free(outbuf);
1161 strcpy(finfo.name,rname);
1165 finfo.mode = SVAL(inbuf,smb_vwv3);
1166 /* these times arrive as LOCAL time, using the DST offset
1167 corresponding to that time, we convert them to GMT */
1168 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1169 finfo.atime = finfo.ctime = finfo.mtime;
1170 finfo.size = IVAL(inbuf,smb_vwv6);
1173 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1175 fnum = SVAL(inbuf,smb_vwv2);
1177 /* we might have got some data from a chained readX */
1178 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1180 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1181 datalen = SVAL(p,smb_vwv5);
1182 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1191 DEBUG(2,("getting file %s of size %d bytes as %s ",
1192 CNV_LANG(finfo.name),
1196 while (nread < finfo.size && !close_done)
1199 static BOOL can_chain_close = True;
1203 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1205 /* 3 possible read types. readbraw if a large block is required.
1206 readX + close if not much left and read if neither is supported */
1208 /* we might have already read some data from a chained readX */
1209 if (dataptr && datalen>0)
1212 /* if we can finish now then readX+close */
1213 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1214 ((finfo.size - nread) <
1215 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1218 /* if we support readraw then use that */
1219 if (method<0 && readbraw_supported)
1222 /* if we can then use readX */
1223 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1234 /* use readX + close */
1235 bzero(outbuf,smb_size);
1236 set_message(outbuf,10,0,True);
1237 CVAL(outbuf,smb_com) = SMBreadX;
1238 SSVAL(outbuf,smb_tid,cnum);
1239 cli_setup_pkt(outbuf);
1243 CVAL(outbuf,smb_vwv0) = SMBclose;
1244 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1247 CVAL(outbuf,smb_vwv0) = 0xFF;
1249 SSVAL(outbuf,smb_vwv2,fnum);
1250 SIVAL(outbuf,smb_vwv3,nread);
1251 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1252 SSVAL(outbuf,smb_vwv6,0);
1253 SIVAL(outbuf,smb_vwv7,0);
1254 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1258 p = smb_buf(outbuf);
1265 /* now set the total packet length */
1266 smb_setlen(outbuf,smb_len(outbuf)+9);
1269 send_smb(Client,outbuf);
1270 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1272 if (CVAL(inbuf,smb_rcls) != 0)
1274 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1279 SVAL(inbuf,smb_vwv0) != SMBclose)
1281 /* NOTE: WfWg sometimes just ignores the chained
1282 command! This seems to break the spec? */
1283 DEBUG(3,("Rejected chained close?\n"));
1285 can_chain_close = False;
1286 ignore_close_error = True;
1289 datalen = SVAL(inbuf,smb_vwv5);
1290 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1296 static int readbraw_size = BUFFER_SIZE;
1299 bzero(outbuf,smb_size);
1300 set_message(outbuf,8,0,True);
1301 CVAL(outbuf,smb_com) = SMBreadbraw;
1302 SSVAL(outbuf,smb_tid,cnum);
1303 cli_setup_pkt(outbuf);
1304 SSVAL(outbuf,smb_vwv0,fnum);
1305 SIVAL(outbuf,smb_vwv1,nread);
1306 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1307 SSVAL(outbuf,smb_vwv4,0);
1308 SIVALS(outbuf,smb_vwv5,-1);
1309 send_smb(Client,outbuf);
1311 /* Now read the raw data into the buffer and write it */
1312 if(read_smb_length(Client,inbuf,0) == -1) {
1313 DEBUG(0,("Failed to read length in readbraw\n"));
1317 /* Even though this is not an smb message, smb_len
1318 returns the generic length of an smb message */
1319 datalen = smb_len(inbuf);
1323 /* we got a readbraw error */
1324 DEBUG(4,("readbraw error - reducing size\n"));
1325 readbraw_size = (readbraw_size * 9) / 10;
1327 if (readbraw_size < max_xmit)
1329 DEBUG(0,("disabling readbraw\n"));
1330 readbraw_supported = False;
1337 if(read_data(Client,inbuf,datalen) != datalen) {
1338 DEBUG(0,("Failed to read data in readbraw\n"));
1346 /* we've already read some data with a chained readX */
1350 /* use plain read */
1351 bzero(outbuf,smb_size);
1352 set_message(outbuf,5,0,True);
1353 CVAL(outbuf,smb_com) = SMBread;
1354 SSVAL(outbuf,smb_tid,cnum);
1355 cli_setup_pkt(outbuf);
1357 SSVAL(outbuf,smb_vwv0,fnum);
1358 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1359 SIVAL(outbuf,smb_vwv2,nread);
1360 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1362 send_smb(Client,outbuf);
1363 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1365 if (CVAL(inbuf,smb_rcls) != 0)
1367 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1371 datalen = SVAL(inbuf,smb_vwv0);
1372 dataptr = smb_buf(inbuf) + 3;
1376 if (writefile(handle,dataptr,datalen) != datalen)
1378 DEBUG(0,("Error writing local file\n"));
1385 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1397 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1399 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1401 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1404 free(inbuf);free(outbuf);
1412 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1413 bzero(outbuf,smb_size);
1414 set_message(outbuf,8,strlen(rname)+4,True);
1415 CVAL(outbuf,smb_com) = SMBsetatr;
1416 SSVAL(outbuf,smb_tid,cnum);
1417 cli_setup_pkt(outbuf);
1418 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1419 SIVALS(outbuf,smb_vwv1,0);
1420 p = smb_buf(outbuf);
1426 send_smb(Client,outbuf);
1427 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1431 struct timeval tp_end;
1434 GetTimeOfDay(&tp_end);
1436 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1437 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1438 get_total_time_ms += this_time;
1439 get_total_size += finfo.size;
1441 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1442 finfo.size / (1.024*this_time + 1.0e-4),
1443 get_total_size / (1.024*get_total_time_ms)));
1446 free(inbuf);free(outbuf);
1450 /****************************************************************************
1452 ****************************************************************************/
1453 static void cmd_get(void)
1459 strcpy(rname,cur_dir);
1462 p = rname + strlen(rname);
1464 if (!next_token(NULL,p,NULL)) {
1465 DEBUG(0,("get <filename>\n"));
1469 dos_clean_name(rname);
1471 next_token(NULL,lname,NULL);
1473 do_get(rname,lname,NULL);
1477 /****************************************************************************
1478 do a mget operation on one file
1479 ****************************************************************************/
1480 static void do_mget(file_info *finfo)
1485 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1490 DEBUG(0,("mget aborted\n"));
1494 if (finfo->mode & aDIR)
1495 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1497 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1499 if (prompt && !yesno(quest)) return;
1501 if (finfo->mode & aDIR)
1503 pstring saved_curdir;
1505 char *inbuf,*outbuf;
1507 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1508 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1510 if (!inbuf || !outbuf)
1512 DEBUG(0,("out of memory\n"));
1516 strcpy(saved_curdir,cur_dir);
1518 strcat(cur_dir,finfo->name);
1519 strcat(cur_dir,"\\");
1521 unix_format(finfo->name);
1524 strlower(finfo->name);
1526 if (!directory_exist(finfo->name,NULL) &&
1527 sys_mkdir(finfo->name,0777) != 0)
1529 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1530 strcpy(cur_dir,saved_curdir);
1531 free(inbuf);free(outbuf);
1535 if (sys_chdir(finfo->name) != 0)
1537 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1538 strcpy(cur_dir,saved_curdir);
1539 free(inbuf);free(outbuf);
1544 strcpy(mget_mask,cur_dir);
1545 strcat(mget_mask,"*");
1547 do_dir((char *)inbuf,(char *)outbuf,
1548 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1550 strcpy(cur_dir,saved_curdir);
1551 free(inbuf);free(outbuf);
1555 strcpy(rname,cur_dir);
1556 strcat(rname,finfo->name);
1557 do_get(rname,finfo->name,finfo);
1561 /****************************************************************************
1562 view the file using the pager
1563 ****************************************************************************/
1564 static void cmd_more(void)
1566 fstring rname,lname,tmpname,pager_cmd;
1569 strcpy(rname,cur_dir);
1571 sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1572 strcpy(lname,tmpname);
1574 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1575 DEBUG(0,("more <filename>\n"));
1578 dos_clean_name(rname);
1580 do_get(rname,lname,NULL);
1582 pager=getenv("PAGER");
1583 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1590 /****************************************************************************
1592 ****************************************************************************/
1593 static void cmd_mget(char *inbuf,char *outbuf)
1595 int attribute = aSYSTEM | aHIDDEN;
1607 while (next_token(NULL,p,NULL))
1609 strcpy(mget_mask,cur_dir);
1610 if(mget_mask[strlen(mget_mask)-1]!='\\')
1611 strcat(mget_mask,"\\");
1614 strcpy(mget_mask,p);
1616 strcat(mget_mask,p);
1617 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1622 strcpy(mget_mask,cur_dir);
1623 if(mget_mask[strlen(mget_mask)-1]!='\\')
1624 strcat(mget_mask,"\\");
1625 strcat(mget_mask,"*");
1626 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1630 /****************************************************************************
1631 make a directory of name "name"
1632 ****************************************************************************/
1633 static BOOL do_mkdir(char *name)
1636 char *inbuf,*outbuf;
1638 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1639 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1641 if (!inbuf || !outbuf)
1643 DEBUG(0,("out of memory\n"));
1647 bzero(outbuf,smb_size);
1648 set_message(outbuf,0,2 + strlen(name),True);
1650 CVAL(outbuf,smb_com) = SMBmkdir;
1651 SSVAL(outbuf,smb_tid,cnum);
1652 cli_setup_pkt(outbuf);
1655 p = smb_buf(outbuf);
1659 send_smb(Client,outbuf);
1660 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1662 if (CVAL(inbuf,smb_rcls) != 0)
1664 DEBUG(0,("%s making remote directory %s\n",
1665 smb_errstr(inbuf),CNV_LANG(name)));
1667 free(inbuf);free(outbuf);
1671 free(inbuf);free(outbuf);
1676 /****************************************************************************
1678 ****************************************************************************/
1679 static void cmd_mkdir(char *inbuf,char *outbuf)
1685 strcpy(mask,cur_dir);
1687 if (!next_token(NULL,p,NULL))
1690 DEBUG(0,("mkdir <dirname>\n"));
1702 trim_string(ddir,".",NULL);
1703 p = strtok(ddir,"/\\");
1707 if (!chkpath(ddir2,False))
1712 p = strtok(NULL,"/\\");
1720 /*******************************************************************
1721 write to a file using writebraw
1722 ********************************************************************/
1723 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1728 bzero(outbuf,smb_size);
1729 bzero(inbuf,smb_size);
1730 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1732 CVAL(outbuf,smb_com) = SMBwritebraw;
1733 SSVAL(outbuf,smb_tid,cnum);
1734 cli_setup_pkt(outbuf);
1736 SSVAL(outbuf,smb_vwv0,fnum);
1737 SSVAL(outbuf,smb_vwv1,n);
1738 SIVAL(outbuf,smb_vwv3,pos);
1739 SSVAL(outbuf,smb_vwv7,1);
1741 send_smb(Client,outbuf);
1743 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1746 _smb_setlen(buf-4,n); /* HACK! XXXX */
1748 if (write_socket(Client,buf-4,n+4) != n+4)
1751 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1752 DEBUG(0,("Error writing remote file (2)\n"));
1755 return(SVAL(inbuf,smb_vwv0));
1760 /*******************************************************************
1762 ********************************************************************/
1763 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1767 if (writebraw_supported && n > (max_xmit-200))
1768 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1770 bzero(outbuf,smb_size);
1771 bzero(inbuf,smb_size);
1772 set_message(outbuf,5,n + 3,True);
1774 CVAL(outbuf,smb_com) = SMBwrite;
1775 SSVAL(outbuf,smb_tid,cnum);
1776 cli_setup_pkt(outbuf);
1778 SSVAL(outbuf,smb_vwv0,fnum);
1779 SSVAL(outbuf,smb_vwv1,n);
1780 SIVAL(outbuf,smb_vwv2,pos);
1781 SSVAL(outbuf,smb_vwv4,0);
1782 CVAL(smb_buf(outbuf),0) = 1;
1783 SSVAL(smb_buf(outbuf),1,n);
1785 memcpy(smb_buf(outbuf)+3,buf,n);
1787 send_smb(Client,outbuf);
1788 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1790 if (CVAL(inbuf,smb_rcls) != 0) {
1791 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1794 return(SVAL(inbuf,smb_vwv0));
1799 /****************************************************************************
1801 ****************************************************************************/
1802 static void do_put(char *rname,char *lname,file_info *finfo)
1808 char *inbuf,*outbuf;
1809 time_t close_time = finfo->mtime;
1811 static int maxwrite=0;
1813 struct timeval tp_start;
1814 GetTimeOfDay(&tp_start);
1816 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1817 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1819 if (!inbuf || !outbuf)
1821 DEBUG(0,("out of memory\n"));
1825 bzero(outbuf,smb_size);
1826 set_message(outbuf,3,2 + strlen(rname),True);
1828 if (finfo->mtime == 0 || finfo->mtime == -1)
1829 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1831 CVAL(outbuf,smb_com) = SMBcreate;
1832 SSVAL(outbuf,smb_tid,cnum);
1833 cli_setup_pkt(outbuf);
1835 SSVAL(outbuf,smb_vwv0,finfo->mode);
1836 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1838 p = smb_buf(outbuf);
1842 send_smb(Client,outbuf);
1843 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1845 if (CVAL(inbuf,smb_rcls) != 0)
1847 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1849 free(inbuf);free(outbuf);if (buf) free(buf);
1853 f = fopen(lname,"r");
1857 DEBUG(0,("Error opening local file %s\n",lname));
1858 free(inbuf);free(outbuf);
1863 fnum = SVAL(inbuf,smb_vwv0);
1864 if (finfo->size < 0)
1865 finfo->size = file_size(lname);
1867 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1870 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1872 while (nread < finfo->size)
1877 n = MIN(n,finfo->size - nread);
1879 buf = (char *)Realloc(buf,n+4);
1881 fseek(f,nread,SEEK_SET);
1882 if ((n = readfile(buf+4,1,n,f)) < 1)
1884 DEBUG(0,("Error reading local file\n"));
1888 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1892 DEBUG(0,("Error writing file\n"));
1905 bzero(outbuf,smb_size);
1906 set_message(outbuf,3,0,True);
1907 CVAL(outbuf,smb_com) = SMBclose;
1908 SSVAL(outbuf,smb_tid,cnum);
1909 cli_setup_pkt(outbuf);
1911 SSVAL(outbuf,smb_vwv0,fnum);
1912 put_dos_date3(outbuf,smb_vwv1,close_time);
1914 send_smb(Client,outbuf);
1915 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1917 if (CVAL(inbuf,smb_rcls) != 0)
1919 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1921 free(inbuf);free(outbuf);
1928 free(inbuf);free(outbuf);
1932 struct timeval tp_end;
1935 GetTimeOfDay(&tp_end);
1937 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1938 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1939 put_total_time_ms += this_time;
1940 put_total_size += finfo->size;
1942 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1943 finfo->size / (1.024*this_time + 1.0e-4),
1944 put_total_size / (1.024*put_total_time_ms)));
1950 /****************************************************************************
1952 ****************************************************************************/
1953 static void cmd_put(void)
1962 strcpy(rname,cur_dir);
1966 if (!next_token(NULL,p,NULL))
1968 DEBUG(0,("put <filename>\n"));
1973 if (next_token(NULL,p,NULL))
1976 strcat(rname,lname);
1978 dos_clean_name(rname);
1982 if (!file_exist(lname,&st)) {
1983 DEBUG(0,("%s does not exist\n",lname));
1986 finfo.mtime = st.st_mtime;
1989 do_put(rname,lname,&finfo);
1992 /****************************************************************************
1993 seek in a directory/file list until you get something that doesn't start with
1995 ****************************************************************************/
1996 static BOOL seek_list(FILE *f,char *name)
2001 if (fscanf(f,"%s",s) != 1) return(False);
2002 trim_string(s,"./",NULL);
2003 if (strncmp(s,name,strlen(name)) != 0)
2014 /****************************************************************************
2015 set the file selection mask
2016 ****************************************************************************/
2017 static void cmd_select(void)
2019 strcpy(fileselection,"");
2020 next_token(NULL,fileselection,NULL);
2024 /****************************************************************************
2026 ****************************************************************************/
2027 static void cmd_mput(void)
2038 while (next_token(NULL,p,NULL))
2045 sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2047 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2049 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2052 f = fopen(tmpname,"r");
2059 if (fscanf(f,"%s",lname) != 1) break;
2060 trim_string(lname,"./",NULL);
2064 /* check if it's a directory */
2065 if (directory_exist(lname,&st))
2067 if (!recurse) continue;
2068 sprintf(quest,"Put directory %s? ",lname);
2069 if (prompt && !yesno(quest))
2072 if (!seek_list(f,lname))
2077 strcpy(rname,cur_dir);
2078 strcat(rname,lname);
2079 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2081 if (!seek_list(f,lname))
2090 sprintf(quest,"Put file %s? ",lname);
2091 if (prompt && !yesno(quest)) continue;
2093 strcpy(rname,cur_dir);
2094 strcat(rname,lname);
2098 /* null size so do_put knows to ignore it */
2101 /* set the date on the file */
2102 finfo.mtime = st.st_mtime;
2104 do_put(rname,lname,&finfo);
2111 /****************************************************************************
2113 ****************************************************************************/
2114 static void do_cancel(int job)
2116 char *rparam = NULL;
2122 bzero(param,sizeof(param));
2125 SSVAL(p,0,81); /* DosPrintJobDel() */
2128 p = skip_string(p,1);
2130 p = skip_string(p,1);
2134 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2140 int res = SVAL(rparam,0);
2143 printf("Job %d cancelled\n",job);
2145 printf("Error %d calcelling job %d\n",res,job);
2149 printf("Server refused cancel request\n");
2151 if (rparam) free(rparam);
2152 if (rdata) free(rdata);
2158 /****************************************************************************
2160 ****************************************************************************/
2161 static void cmd_cancel(char *inbuf,char *outbuf )
2166 if (!connect_as_printer)
2168 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2169 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2172 if (!next_token(NULL,buf,NULL)) {
2173 printf("cancel <jobid> ...\n");
2179 } while (next_token(NULL,buf,NULL));
2185 /****************************************************************************
2187 ****************************************************************************/
2188 static void cmd_print(char *inbuf,char *outbuf )
2197 if (!connect_as_printer)
2199 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2200 DEBUG(0,("Trying to print without -P may fail\n"));
2203 if (!next_token(NULL,lname,NULL))
2205 DEBUG(0,("print <filename>\n"));
2209 strcpy(rname,lname);
2210 p = strrchr(rname,'/');
2215 strcpy(rname,tname);
2218 if ((int)strlen(rname) > 14)
2221 if (strequal(lname,"-"))
2224 strcpy(rname,"stdin");
2227 dos_clean_name(rname);
2229 bzero(outbuf,smb_size);
2230 set_message(outbuf,2,2 + strlen(rname),True);
2232 CVAL(outbuf,smb_com) = SMBsplopen;
2233 SSVAL(outbuf,smb_tid,cnum);
2234 cli_setup_pkt(outbuf);
2236 SSVAL(outbuf,smb_vwv0,0);
2237 SSVAL(outbuf,smb_vwv1,printmode);
2239 p = smb_buf(outbuf);
2243 send_smb(Client,outbuf);
2244 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2246 if (CVAL(inbuf,smb_rcls) != 0)
2248 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2253 f = fopen(lname,"r");
2256 DEBUG(0,("Error opening local file %s\n",lname));
2261 fnum = SVAL(inbuf,smb_vwv0);
2263 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2269 bzero(outbuf,smb_size);
2270 set_message(outbuf,1,3,True);
2272 /* for some strange reason the OS/2 print server can't handle large
2273 packets when printing. weird */
2274 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2277 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2279 n = readfile(smb_buf(outbuf)+3,1,n,f);
2282 DEBUG(0,("read gave %d\n",n));
2286 smb_setlen(outbuf,smb_len(outbuf) + n);
2288 CVAL(outbuf,smb_com) = SMBsplwr;
2289 SSVAL(outbuf,smb_tid,cnum);
2290 cli_setup_pkt(outbuf);
2292 SSVAL(outbuf,smb_vwv0,fnum);
2293 SSVAL(outbuf,smb_vwv1,n+3);
2294 CVAL(smb_buf(outbuf),0) = 1;
2295 SSVAL(smb_buf(outbuf),1,n);
2297 send_smb(Client,outbuf);
2298 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2300 if (CVAL(inbuf,smb_rcls) != 0)
2302 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2309 DEBUG(2,("%d bytes printed\n",nread));
2311 bzero(outbuf,smb_size);
2312 set_message(outbuf,1,0,True);
2313 CVAL(outbuf,smb_com) = SMBsplclose;
2314 SSVAL(outbuf,smb_tid,cnum);
2315 cli_setup_pkt(outbuf);
2317 SSVAL(outbuf,smb_vwv0,fnum);
2319 send_smb(Client,outbuf);
2320 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2322 if (CVAL(inbuf,smb_rcls) != 0)
2324 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2334 /****************************************************************************
2335 show a print queue - this is deprecated as it uses the old smb that
2336 has limited support - the correct call is the cmd_p_queue_4() after this.
2337 ****************************************************************************/
2338 static void cmd_queue(char *inbuf,char *outbuf )
2343 bzero(outbuf,smb_size);
2344 set_message(outbuf,2,0,True);
2346 CVAL(outbuf,smb_com) = SMBsplretq;
2347 SSVAL(outbuf,smb_tid,cnum);
2348 cli_setup_pkt(outbuf);
2350 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2351 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2353 send_smb(Client,outbuf);
2354 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2356 if (CVAL(inbuf,smb_rcls) != 0)
2358 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2362 count = SVAL(inbuf,smb_vwv0);
2363 p = smb_buf(inbuf) + 3;
2366 DEBUG(0,("No entries in the print queue\n"));
2373 DEBUG(0,("Job Name Size Status\n"));
2379 case 0x01: sprintf(status,"held or stopped"); break;
2380 case 0x02: sprintf(status,"printing"); break;
2381 case 0x03: sprintf(status,"awaiting print"); break;
2382 case 0x04: sprintf(status,"in intercept"); break;
2383 case 0x05: sprintf(status,"file had error"); break;
2384 case 0x06: sprintf(status,"printer error"); break;
2385 default: sprintf(status,"unknown"); break;
2388 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2389 SVAL(p,5),p+12,IVAL(p,7),status));
2397 /****************************************************************************
2398 show information about a print queue
2399 ****************************************************************************/
2400 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2402 char *rparam = NULL;
2409 if (!connect_as_printer)
2411 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2412 DEBUG(0,("Trying to print without -P may fail\n"));
2415 bzero(param,sizeof(param));
2418 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2420 strcpy(p,"zWrLeh"); /* parameter description? */
2421 p = skip_string(p,1);
2422 strcpy(p,"WWzWWDDzz"); /* returned data format */
2423 p = skip_string(p,1);
2424 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2425 p = skip_string(p,1);
2426 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2427 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2429 strcpy(p,""); /* subformat */
2430 p = skip_string(p,1);
2432 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2433 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2440 result_code = SVAL(rparam,0);
2441 converter = SVAL(rparam,2); /* conversion factor */
2443 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2445 if (result_code == 0) /* if no error, */
2455 char PrinterName[20];
2457 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2458 strlower(PrinterName); /* in lower case */
2460 p = rdata; /* received data */
2461 for( i = 0; i < SVAL(rparam,4); ++i)
2464 Priority = SVAL(p,2);
2465 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2467 Priority = SVAL(p,2);
2468 JobTime = make_unix_date3( p + 12);
2469 JobTimeStr = asctime(LocalTime( &JobTime));
2471 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2474 printf("%s-%u %s priority %u %s %s %u bytes\n",
2475 PrinterName, JobId, UserName,
2476 Priority, JobTimeStr, JobName, Size);
2478 #if 0 /* DEBUG code */
2479 printf("Job Id: \"%u\"\n", SVAL(p,0));
2480 printf("Priority: \"%u\"\n", SVAL(p,2));
2482 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2483 printf("Position: \"%u\"\n", SVAL(p,8));
2484 printf("Status: \"%u\"\n", SVAL(p,10));
2486 JobTime = make_unix_date3( p + 12);
2487 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2488 printf("date: \"%u\"\n", SVAL(p,12));
2490 printf("Size: \"%u\"\n", SVAL(p,16));
2491 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2492 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2493 #endif /* DEBUG CODE */
2498 else /* cli_call_api() failed */
2500 printf("Failed, error = %d\n", result_code);
2503 /* If any parameters or data were returned, free the storage. */
2504 if(rparam) free(rparam);
2505 if(rdata) free(rdata);
2510 /****************************************************************************
2511 show information about a print queue
2512 ****************************************************************************/
2513 static void cmd_qinfo(char *inbuf,char *outbuf )
2515 char *rparam = NULL;
2522 bzero(param,sizeof(param));
2525 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2527 strcpy(p,"zWrLh"); /* parameter description? */
2528 p = skip_string(p,1);
2529 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2530 p = skip_string(p,1);
2531 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2532 p = skip_string(p,1);
2533 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2534 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2536 strcpy(p,""); /* subformat */
2537 p = skip_string(p,1);
2539 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2540 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2547 result_code = SVAL(rparam,0);
2548 converter = SVAL(rparam,2); /* conversion factor */
2550 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2552 if (result_code == 0) /* if no error, */
2554 p = rdata; /* received data */
2556 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2557 printf("Priority: %u\n", SVAL(p,4) );
2558 printf("Start time: %u\n", SVAL(p,6) );
2559 printf("Until time: %u\n", SVAL(p,8) );
2560 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2561 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2562 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2563 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2564 printf("Status: %u\n", SVAL(p,28) );
2565 printf("Jobs: %u\n", SVAL(p,30) );
2566 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2567 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2569 /* Dump the driver data */
2574 ddptr = rdata + SVAL(p,40) - converter;
2575 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2576 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2578 for(x=8; x < count; x+=16)
2580 for(y=0; y < 16; y++)
2583 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2587 for(y=0; y < 16 && (x+y) < count; y++)
2589 c = CVAL(ddptr,(x+y));
2595 fputc('\n', stdout);
2601 else /* cli_call_api() failed */
2603 printf("Failed, error = %d\n", result_code);
2606 /* If any parameters or data were returned, free the storage. */
2607 if(rparam) free(rparam);
2608 if(rdata) free(rdata);
2613 /****************************************************************************
2615 ****************************************************************************/
2616 static void do_del(file_info *finfo)
2619 char *inbuf,*outbuf;
2622 strcpy(mask,cur_dir);
2623 strcat(mask,finfo->name);
2625 if (finfo->mode & aDIR)
2628 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2629 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2631 if (!inbuf || !outbuf)
2633 DEBUG(0,("out of memory\n"));
2637 bzero(outbuf,smb_size);
2638 set_message(outbuf,1,2 + strlen(mask),True);
2640 CVAL(outbuf,smb_com) = SMBunlink;
2641 SSVAL(outbuf,smb_tid,cnum);
2642 cli_setup_pkt(outbuf);
2644 SSVAL(outbuf,smb_vwv0,0);
2646 p = smb_buf(outbuf);
2650 send_smb(Client,outbuf);
2651 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2653 if (CVAL(inbuf,smb_rcls) != 0)
2654 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2656 free(inbuf);free(outbuf);
2660 /****************************************************************************
2662 ****************************************************************************/
2663 static void cmd_del(char *inbuf,char *outbuf )
2667 int attribute = aSYSTEM | aHIDDEN;
2672 strcpy(mask,cur_dir);
2674 if (!next_token(NULL,buf,NULL))
2676 DEBUG(0,("del <filename>\n"));
2681 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2685 /****************************************************************************
2687 ****************************************************************************/
2688 static void cmd_rmdir(char *inbuf,char *outbuf )
2694 strcpy(mask,cur_dir);
2696 if (!next_token(NULL,buf,NULL))
2698 DEBUG(0,("rmdir <dirname>\n"));
2703 bzero(outbuf,smb_size);
2704 set_message(outbuf,0,2 + strlen(mask),True);
2706 CVAL(outbuf,smb_com) = SMBrmdir;
2707 SSVAL(outbuf,smb_tid,cnum);
2708 cli_setup_pkt(outbuf);
2711 p = smb_buf(outbuf);
2715 send_smb(Client,outbuf);
2716 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2718 if (CVAL(inbuf,smb_rcls) != 0)
2720 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2726 /****************************************************************************
2728 ****************************************************************************/
2729 static void cmd_rename(char *inbuf,char *outbuf )
2735 strcpy(src,cur_dir);
2736 strcpy(dest,cur_dir);
2738 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2740 DEBUG(0,("rename <src> <dest>\n"));
2746 bzero(outbuf,smb_size);
2747 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2749 CVAL(outbuf,smb_com) = SMBmv;
2750 SSVAL(outbuf,smb_tid,cnum);
2751 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2752 cli_setup_pkt(outbuf);
2754 p = smb_buf(outbuf);
2757 p = skip_string(p,1);
2761 send_smb(Client,outbuf);
2762 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2764 if (CVAL(inbuf,smb_rcls) != 0)
2766 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2773 /****************************************************************************
2774 toggle the prompt flag
2775 ****************************************************************************/
2776 static void cmd_prompt(void)
2779 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2783 /****************************************************************************
2784 set the newer than time
2785 ****************************************************************************/
2786 static void cmd_newer(void)
2792 ok = next_token(NULL,buf,NULL);
2793 if (ok && (sys_stat(buf,&sbuf) == 0))
2795 newer_than = sbuf.st_mtime;
2796 DEBUG(1,("Getting files newer than %s",
2797 asctime(LocalTime(&newer_than))));
2802 if (ok && newer_than == 0)
2803 DEBUG(0,("Error setting newer-than time\n"));
2806 /****************************************************************************
2807 set the archive level
2808 ****************************************************************************/
2809 static void cmd_archive(void)
2813 if (next_token(NULL,buf,NULL)) {
2814 archive_level = atoi(buf);
2816 DEBUG(0,("Archive level is %d\n",archive_level));
2819 /****************************************************************************
2820 toggle the lowercaseflag
2821 ****************************************************************************/
2822 static void cmd_lowercase(void)
2824 lowercase = !lowercase;
2825 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2831 /****************************************************************************
2832 toggle the recurse flag
2833 ****************************************************************************/
2834 static void cmd_recurse(void)
2837 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2840 /****************************************************************************
2841 toggle the translate flag
2842 ****************************************************************************/
2843 static void cmd_translate(void)
2845 translation = !translation;
2846 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2847 translation?"on":"off"));
2851 /****************************************************************************
2852 do a printmode command
2853 ****************************************************************************/
2854 static void cmd_printmode(void)
2859 if (next_token(NULL,buf,NULL))
2861 if (strequal(buf,"text"))
2865 if (strequal(buf,"graphics"))
2868 printmode = atoi(buf);
2875 strcpy(mode,"text");
2878 strcpy(mode,"graphics");
2881 sprintf(mode,"%d",printmode);
2885 DEBUG(2,("the printmode is now %s\n",mode));
2888 /****************************************************************************
2890 ****************************************************************************/
2891 static void cmd_lcd(void)
2896 if (next_token(NULL,buf,NULL))
2898 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2902 /****************************************************************************
2903 try and browse available connections on a host
2904 ****************************************************************************/
2905 static BOOL browse_host(BOOL sort)
2908 /* If strcasecmp is already defined, remove it. */
2911 #endif /* strcasecmp */
2912 #define strcasecmp StrCaseCmp
2913 #endif /* NOSTRCASECMP */
2915 extern int strcasecmp();
2917 char *rparam = NULL;
2924 /* now send a SMBtrans command with api RNetShareEnum */
2926 SSVAL(p,0,0); /* api number */
2929 p = skip_string(p,1);
2931 p = skip_string(p,1);
2933 SSVAL(p,2,BUFFER_SIZE);
2936 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2942 int res = SVAL(rparam,0);
2943 int converter=SVAL(rparam,2);
2945 BOOL long_share_name=False;
2949 count=SVAL(rparam,4);
2954 printf("\n\tSharename Type Comment\n");
2955 printf("\t--------- ---- -------\n");
2959 qsort(p,count,20,QSORT_CAST strcasecmp);
2961 for (i=0;i<count;i++)
2964 int type = SVAL(p,14);
2965 int comment_offset = IVAL(p,16) & 0xFFFF;
2971 case STYPE_DISKTREE:
2972 strcpy(typestr,"Disk"); break;
2974 strcpy(typestr,"Printer"); break;
2976 strcpy(typestr,"Device"); break;
2978 strcpy(typestr,"IPC"); break;
2981 printf("\t%-15.15s%-10.10s%s\n",
2984 comment_offset?rdata+comment_offset-converter:"");
2986 if (strlen(sname)>8) long_share_name=True;
2991 if (long_share_name) {
2992 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
2997 if (rparam) free(rparam);
2998 if (rdata) free(rdata);
3004 /****************************************************************************
3005 get some server info
3006 ****************************************************************************/
3007 static void server_info()
3009 char *rparam = NULL;
3015 bzero(param,sizeof(param));
3018 SSVAL(p,0,63); /* NetServerGetInfo()? */
3021 p = skip_string(p,1);
3022 strcpy(p,"zzzBBzz");
3023 p = skip_string(p,1);
3024 SSVAL(p,0,10); /* level 10 */
3028 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3034 int res = SVAL(rparam,0);
3035 int converter=SVAL(rparam,2);
3041 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3042 rdata+SVAL(p,0)-converter,
3043 rdata+SVAL(p,4)-converter,
3044 rdata+SVAL(p,8)-converter,
3045 rdata+SVAL(p,14)-converter);
3049 if (rparam) free(rparam);
3050 if (rdata) free(rdata);
3056 /****************************************************************************
3057 try and browse available connections on a host
3058 ****************************************************************************/
3059 static BOOL list_servers(char *wk_grp)
3061 char *rparam = NULL;
3069 BOOL generic_request = False;
3072 if (strequal(wk_grp,"WORKGROUP")) {
3073 /* we won't specify a workgroup */
3074 generic_request = True;
3077 /* now send a SMBtrans command with api ServerEnum? */
3079 SSVAL(p,0,0x68); /* api number */
3082 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3083 p = skip_string(p,1);
3085 strcpy(p,"B16BBDz");
3087 p = skip_string(p,1);
3089 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3095 if (!generic_request) {
3097 p = skip_string(p,1);
3100 /* first ask for a list of servers in this workgroup */
3101 SIVAL(svtype_p,0,SV_TYPE_ALL);
3103 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3104 8, BUFFER_SIZE - SAFETY_MARGIN,
3109 int res = SVAL(rparam,0);
3110 int converter=SVAL(rparam,2);
3115 count=SVAL(rparam,4);
3118 printf("\n\nThis machine has a browse list:\n");
3119 printf("\n\tServer Comment\n");
3120 printf("\t--------- -------\n");
3123 for (i=0;i<count;i++) {
3125 int comment_offset = IVAL(p2,22) & 0xFFFF;
3126 printf("\t%-16.16s %s\n",
3128 comment_offset?rdata+comment_offset-converter:"");
3136 if (rparam) {free(rparam); rparam = NULL;}
3137 if (rdata) {free(rdata); rdata = NULL;}
3139 /* now ask for a list of workgroups */
3140 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3142 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3143 8, BUFFER_SIZE - SAFETY_MARGIN,
3148 int res = SVAL(rparam,0);
3149 int converter=SVAL(rparam,2);
3154 count=SVAL(rparam,4);
3157 printf("\n\nThis machine has a workgroup list:\n");
3158 printf("\n\tWorkgroup Master\n");
3159 printf("\t--------- -------\n");
3162 for (i=0;i<count;i++) {
3164 int comment_offset = IVAL(p2,22) & 0xFFFF;
3165 printf("\t%-16.16s %s\n",
3167 comment_offset?rdata+comment_offset-converter:"");
3175 if (rparam) free(rparam);
3176 if (rdata) free(rdata);
3182 /* This defines the commands supported by this client */
3190 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3191 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3192 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3193 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3194 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3195 {"get",cmd_get,"<remote name> [local name] get a file"},
3196 {"mget",cmd_mget,"<mask> get all the matching files"},
3197 {"put",cmd_put,"<local name> [remote name] put a file"},
3198 {"mput",cmd_mput,"<mask> put all matching files"},
3199 {"rename",cmd_rename,"<src> <dest> rename some files"},
3200 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3201 {"mask",cmd_select,"<mask> mask all filenames against this"},
3202 {"del",cmd_del,"<mask> delete all matching files"},
3203 {"rm",cmd_del,"<mask> delete all matching files"},
3204 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3205 {"md",cmd_mkdir,"<directory> make a directory"},
3206 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
3207 {"rd",cmd_rmdir,"<directory> remove a directory"},
3208 {"pq",cmd_p_queue_4,"enumerate the print queue"},
3209 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
3210 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
3211 {"translate",cmd_translate,"toggle text translation for printing"},
3212 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
3213 {"print",cmd_print,"<file name> print a file"},
3214 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
3215 {"queue",cmd_queue,"show the print queue"},
3216 {"qinfo",cmd_qinfo,"show print queue information"},
3217 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
3218 {"quit",cli_send_logout,"logoff the server"},
3219 {"q",cli_send_logout,"logoff the server"},
3220 {"exit",cli_send_logout,"logoff the server"},
3221 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
3222 {"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"},
3223 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3224 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
3225 {"tarmode",cmd_tarmode,
3226 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3227 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
3228 {"help",cmd_help,"[command] give help on a command"},
3229 {"?",cmd_help,"[command] give help on a command"},
3230 {"!",NULL,"run a shell command on the local system"},
3235 /*******************************************************************
3236 lookup a command string in the list of commands, including
3238 ******************************************************************/
3239 static int process_tok(fstring tok)
3241 int i = 0, matches = 0;
3243 int tok_len = strlen(tok);
3245 while (commands[i].fn != NULL)
3247 if (strequal(commands[i].name,tok))
3253 else if (strnequal(commands[i].name, tok, tok_len))
3263 else if (matches == 1)
3269 /****************************************************************************
3271 ****************************************************************************/
3277 if (next_token(NULL,buf,NULL))
3279 if ((i = process_tok(buf)) >= 0)
3280 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3283 while (commands[i].description)
3285 for (j=0; commands[i].description && (j<5); j++) {
3286 DEBUG(0,("%-15s",commands[i].name));
3293 /****************************************************************************
3294 wait for keyboard activity, swallowing network packets
3295 ****************************************************************************/
3297 static char wait_keyboard(char *buffer)
3299 static void wait_keyboard(char *buffer)
3304 struct timeval timeout;
3314 FD_SET(Client,&fds);
3316 FD_SET(fileno(stdin),&fds);
3319 timeout.tv_sec = 20;
3320 timeout.tv_usec = 0;
3324 selrtn = sys_select(&fds,&timeout);
3327 if (FD_ISSET(fileno(stdin),&fds))
3334 set_blocking(fileno(stdin), False);
3335 readret = read_data( fileno(stdin), &ch, 1);
3336 set_blocking(fileno(stdin), True);
3339 if (errno != EAGAIN)
3341 /* should crash here */
3342 DEBUG(1,("readchar stdin failed\n"));
3345 else if (readret != 0)
3352 /* We deliberately use receive_smb instead of
3353 client_receive_smb as we want to receive
3354 session keepalives and then drop them here.
3356 if (FD_ISSET(Client,&fds))
3357 receive_smb(Client,buffer,0);
3364 chkpath("\\",False);
3367 chkpath("\\",False);
3373 /****************************************************************************
3374 process commands from the client
3375 ****************************************************************************/
3376 static BOOL process(char *base_directory)
3382 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3383 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3385 if ((InBuffer == NULL) || (OutBuffer == NULL))
3388 bzero(OutBuffer,smb_size);
3390 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3393 if (*base_directory) do_cd(base_directory);
3396 if (cmd[0] != '\0') while (cmd[0] != '\0')
3402 if ((p = strchr(cmd, ';')) == 0)
3404 strncpy(line, cmd, 999);
3410 if (p - cmd > 999) p = cmd + 999;
3411 strncpy(line, cmd, p - cmd);
3412 line[p - cmd] = '\0';
3416 /* input language code to internal one */
3419 /* and get the first part of the command */
3422 if (!next_token(&ptr,tok,NULL)) continue;
3425 if ((i = process_tok(tok)) >= 0)
3426 commands[i].fn(InBuffer,OutBuffer);
3428 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3430 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3432 else while (!feof(stdin))
3437 bzero(OutBuffer,smb_size);
3439 /* display a prompt */
3440 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3444 line[0] = wait_keyboard(InBuffer);
3445 /* this might not be such a good idea... */
3446 if ( line[0] == EOF)
3449 wait_keyboard(InBuffer);
3452 /* and get a response */
3454 fgets( &line[1],999, stdin);
3456 if (!fgets(line,1000,stdin))
3460 /* input language code to internal one */
3463 /* special case - first char is ! */
3470 /* and get the first part of the command */
3473 if (!next_token(&ptr,tok,NULL)) continue;
3476 if ((i = process_tok(tok)) >= 0)
3477 commands[i].fn(InBuffer,OutBuffer);
3479 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3481 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3488 /****************************************************************************
3489 usage on the program
3490 ****************************************************************************/
3491 static void usage(char *pname)
3493 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3496 DEBUG(0,("\nVersion %s\n",VERSION));
3497 DEBUG(0,("\t-p port connect to the specified port\n"));
3498 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3499 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3500 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3501 DEBUG(0,("\t-N don't ask for a password\n"));
3502 DEBUG(0,("\t-P connect to service as a printer\n"));
3503 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3504 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3505 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3506 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3507 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3508 DEBUG(0,("\t-U username set the network username\n"));
3509 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3510 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3511 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3512 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
3513 DEBUG(0,("\t-D directory start from directory\n"));
3517 /****************************************************************************
3519 ****************************************************************************/
3520 int main(int argc,char *argv[])
3522 fstring base_directory;
3523 char *pname = argv[0];
3524 int port = SMB_PORT;
3527 extern char *optarg;
3530 BOOL message = False;
3531 BOOL nt_domain_logon = False;
3532 extern char tar_type;
3533 static pstring servicesf = CONFIGFILE;
3538 strcpy(term_code, KANJI);
3544 *base_directory = 0;
3548 setup_logging(pname,True);
3551 charset_initialise();
3562 strcpy(username,getenv("USER"));
3564 /* modification to support userid%passwd syntax in the USER var
3565 25.Aug.97, jdblair@uab.edu */
3567 if ((p=strchr(username,'%')))
3570 strcpy(password,p+1);
3572 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3577 /* modification to support PASSWD environmental var
3578 25.Aug.97, jdblair@uab.edu */
3580 if (getenv("PASSWD"))
3581 strcpy(password,getenv("PASSWD"));
3583 if (*username == 0 && getenv("LOGNAME"))
3585 strcpy(username,getenv("LOGNAME"));
3595 if (*argv[1] != '-')
3598 strcpy(service,argv[1]);
3599 /* Convert any '/' characters in the service name to '\' characters */
3600 string_replace( service, '/','\\');
3604 if (count_chars(service,'\\') < 3)
3607 printf("\n%s: Not enough '\\' characters in service\n",service);
3612 if (count_chars(service,'\\') > 3)
3615 printf("\n%s: Too many '\\' characters in service\n",service);
3620 if (argc > 1 && (*argv[1] != '-'))
3623 strcpy(password,argv[1]);
3624 memset(argv[1],'X',strlen(argv[1]));
3631 getopt(argc, argv,"s:B:O:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
3635 max_protocol = interpret_protocol(optarg,max_protocol);
3638 strcpy(user_socket_options,optarg);
3641 strcpy(desthost,optarg);
3643 nt_domain_logon = True;
3646 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3647 strcpy(desthost,optarg);
3652 iface_set_default(NULL,optarg,NULL);
3655 strcpy(base_directory,optarg);
3658 if (!tar_parseargs(argc, argv, optarg, optind)) {
3664 strcpy(scope,optarg);
3668 strcpy(query_host,optarg);
3673 strcpy(username,optarg);
3674 if ((lp=strchr(username,'%')))
3677 strcpy(password,lp+1);
3679 memset(strchr(optarg,'%')+1,'X',strlen(password));
3685 strcpy(workgroup,optarg);
3692 dest_ip = *interpret_addr2(optarg);
3693 if (zero_ip(dest_ip)) exit(1);
3698 strcpy(myname,optarg);
3704 connect_as_printer = True;
3710 DEBUGLEVEL = atoi(optarg);
3713 sprintf(debugf,"%s.client",optarg);
3716 port = atoi(optarg);
3727 strcpy(servicesf, optarg);
3730 strcpy(term_code, optarg);
3737 if (!tar_type && !*query_host && !*service && !message)
3744 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
3746 if(!get_myname(myhostname,NULL))
3748 DEBUG(0,("Failed to get my hostname.\n"));
3751 if (!lp_load(servicesf,True)) {
3752 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3755 codepage_initialise(lp_client_code_page());
3757 if(lp_client_code_page() == KANJI_CODEPAGE)
3759 if (!setup_term_code (term_code))
3761 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
3767 if (*workgroup == 0)
3768 strcpy(workgroup,lp_workgroup());
3771 get_myname((*myname)?NULL:myname,NULL);
3777 if (cli_open_sockets(port)) {
3778 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3779 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3782 if ((InBuffer == NULL) || (OutBuffer == NULL))
3785 bzero(OutBuffer,smb_size);
3786 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3789 if (*base_directory) do_cd(base_directory);
3791 ret=process_tar(InBuffer, OutBuffer);
3800 if (*query_host && !nt_domain_logon)
3803 sprintf(service,"\\\\%s\\IPC$",query_host);
3805 connect_as_ipc = True;
3806 if (cli_open_sockets(port))
3811 if (!cli_send_login(NULL,NULL,True,True,NULL))
3815 if (!browse_host(True)) {
3819 if (!list_servers(workgroup)) {
3821 list_servers(workgroup);
3834 if (cli_open_sockets(port))
3836 pstring inbuf,outbuf;
3837 bzero(outbuf,smb_size);
3838 if (!cli_send_session_request(inbuf,outbuf))
3841 send_message(inbuf,outbuf);
3851 if (nt_domain_logon)
3854 sprintf(service,"\\\\%s\\IPC$",query_host);
3856 connect_as_ipc = True;
3858 DEBUG(5,("NT Domain Logon. Service: %s\n", service));
3860 if (cli_open_sockets(port))
3862 if (!cli_send_login(NULL,NULL,True,True,NULL)) return(1);
3864 do_nt_login(desthost, myhostname, Client, cnum);
3874 if (cli_open_sockets(port))
3876 if (!process(base_directory))