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.
30 pstring cur_dir = "\\";
32 extern pstring service;
33 extern pstring desthost;
34 extern pstring global_myname;
35 extern pstring myhostname;
36 extern pstring password;
37 extern pstring username;
38 extern pstring workgroup;
42 extern BOOL connect_as_printer;
43 extern BOOL connect_as_ipc;
44 extern struct in_addr ipzero;
46 extern BOOL doencrypt;
48 extern pstring user_socket_options;
50 static int process_tok(fstring tok);
51 static void cmd_help(char *dum_in, char *dum_out);
53 /* 30 second timeout on most commands */
54 #define CLIENT_TIMEOUT (30*1000)
55 #define SHORT_TIMEOUT (5*1000)
57 /* value for unused fid field in trans2 secondary request */
58 #define FID_UNUSED (0xFFFF)
62 extern int max_protocol;
65 time_t newer_than = 0;
66 int archive_level = 0;
68 extern pstring debugf;
69 extern int DEBUGLEVEL;
71 BOOL translation = False;
83 static int interpret_long_filename(int level,char *p,file_info *finfo);
84 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo);
85 static int interpret_short_filename(char *p,file_info *finfo);
86 static BOOL do_this_one(file_info *finfo);
88 /* clitar bits insert */
91 extern BOOL tar_reset;
103 BOOL recurse = False;
104 BOOL lowercase = False;
106 struct in_addr dest_ip;
108 #define SEPARATORS " \t\n\r"
110 BOOL abort_mget = True;
114 extern BOOL readbraw_supported ;
115 extern BOOL writebraw_supported;
117 pstring fileselection = "";
119 extern file_info def_finfo;
122 int get_total_size = 0;
123 int get_total_time_ms = 0;
124 int put_total_size = 0;
125 int put_total_time_ms = 0;
134 #define CNV_LANG(s) dos_to_unix(s,False)
135 #define CNV_INPUT(s) unix_to_dos(s,True)
137 /****************************************************************************
138 send an SMBclose on an SMB file handle
139 ****************************************************************************/
140 static void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
142 bzero(outbuf,smb_size);
143 set_message(outbuf,3,0,True);
145 CVAL (outbuf,smb_com) = SMBclose;
146 SSVAL(outbuf,smb_tid,c_num);
147 cli_setup_pkt(outbuf);
148 SSVAL (outbuf,smb_vwv0, f_num);
149 SIVALS(outbuf,smb_vwv1, -1);
151 send_smb(clnt_fd, outbuf);
152 client_receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
156 /****************************************************************************
157 write to a local file with CR/LF->LF translation if appropriate. return the
158 number taken from the buffer. This may not equal the number written.
159 ****************************************************************************/
160 static int writefile(int f, char *b, int n)
165 return(write(f,b,n));
170 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
174 if (write(f, b, 1) != 1)
185 /****************************************************************************
186 read from a file with LF->CR/LF translation if appropriate. return the
187 number read. read approx n bytes.
188 ****************************************************************************/
189 static int readfile(char *b, int size, int n, FILE *f)
194 if (!translation || (size != 1))
195 return(fread(b,size,n,f));
200 if ((c = getc(f)) == EOF)
205 if (c == '\n') /* change all LFs to CR/LF */
219 /****************************************************************************
220 read from a file with print translation. return the number read. read approx n
222 ****************************************************************************/
223 static int printread(FILE *f,char *b,int n)
227 i = readfile(b,1, n-1,f);
236 /****************************************************************************
237 check for existance of a dir
238 ****************************************************************************/
239 static BOOL chkpath(char *path,BOOL report)
242 pstring inbuf,outbuf;
246 trim_string(path2,NULL,"\\");
247 if (!*path2) *path2 = '\\';
249 bzero(outbuf,smb_size);
250 set_message(outbuf,0,4 + strlen(path2),True);
251 SCVAL(outbuf,smb_com,SMBchkpth);
252 SSVAL(outbuf,smb_tid,cnum);
253 cli_setup_pkt(outbuf);
261 /* this little bit of code can be used to extract NT error codes.
262 Just feed a bunch of "cd foo" commands to smbclient then watch
263 in netmon (tridge) */
265 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
266 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
271 send_smb(Client,outbuf);
272 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
274 if (report && CVAL(inbuf,smb_rcls) != 0)
275 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
277 return(CVAL(inbuf,smb_rcls) == 0);
281 /****************************************************************************
283 ****************************************************************************/
284 static void send_message(char *inbuf,char *outbuf)
291 /* send a SMBsendstrt command */
292 bzero(outbuf,smb_size);
293 set_message(outbuf,0,0,True);
294 CVAL(outbuf,smb_com) = SMBsendstrt;
295 SSVAL(outbuf,smb_tid,cnum);
300 p = skip_string(p,1);
303 p = skip_string(p,1);
305 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
307 send_smb(Client,outbuf);
310 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
312 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
316 grp_id = SVAL(inbuf,smb_vwv0);
318 printf("Connected. Type your message, ending it with a Control-D\n");
320 while (!feof(stdin) && total_len < 1600)
322 int maxlen = MIN(1600 - total_len,127);
329 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
336 CVAL(outbuf,smb_com) = SMBsendtxt;
338 set_message(outbuf,1,l+3,True);
340 SSVAL(outbuf,smb_vwv0,grp_id);
347 send_smb(Client,outbuf);
350 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
352 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
359 if (total_len >= 1600)
360 printf("the message was truncated to 1600 bytes ");
362 printf("sent %d bytes ",total_len);
364 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
366 CVAL(outbuf,smb_com) = SMBsendend;
367 set_message(outbuf,1,0,False);
368 SSVAL(outbuf,smb_vwv0,grp_id);
370 send_smb(Client,outbuf);
373 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
375 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
382 /****************************************************************************
383 check the space on a device
384 ****************************************************************************/
385 static void do_dskattr(void)
387 pstring inbuf,outbuf;
389 bzero(outbuf,smb_size);
390 set_message(outbuf,0,0,True);
391 CVAL(outbuf,smb_com) = SMBdskattr;
392 SSVAL(outbuf,smb_tid,cnum);
393 cli_setup_pkt(outbuf);
395 send_smb(Client,outbuf);
396 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
398 if (CVAL(inbuf,smb_rcls) != 0)
399 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
401 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
402 SVAL(inbuf,smb_vwv0),
403 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
404 SVAL(inbuf,smb_vwv3)));
407 /****************************************************************************
409 ****************************************************************************/
410 static void cmd_pwd(char *dum_in, char *dum_out)
412 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
413 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
417 /****************************************************************************
418 change directory - inner section
419 ****************************************************************************/
420 static void do_cd(char *newdir)
426 /* Save the current directory in case the
427 new directory is invalid */
428 pstrcpy(saved_dir, cur_dir);
433 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
434 pstrcat(cur_dir, "\\");
436 dos_clean_name(cur_dir);
437 pstrcpy(dname,cur_dir);
438 pstrcat(cur_dir,"\\");
439 dos_clean_name(cur_dir);
441 if (!strequal(cur_dir,"\\"))
442 if (!chkpath(dname,True))
443 pstrcpy(cur_dir,saved_dir);
445 pstrcpy(cd_path,cur_dir);
448 /****************************************************************************
450 ****************************************************************************/
451 static void cmd_cd(char *inbuf,char *outbuf)
455 if (next_token(NULL,buf,NULL,sizeof(buf)))
458 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
462 /****************************************************************************
463 display info about a file
464 ****************************************************************************/
465 static void display_finfo(file_info *finfo)
467 if (do_this_one(finfo)) {
468 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
469 #ifdef LARGE_SMB_OFF_T
470 DEBUG(0,(" %-30s%7.7s%.0f %s",
471 CNV_LANG(finfo->name),
472 attrib_string(finfo->mode),
474 asctime(LocalTime(&t))));
475 #else /* LARGE_SMB_OFF_T */
476 DEBUG(0,(" %-30s%7.7s%10d %s",
477 CNV_LANG(finfo->name),
478 attrib_string(finfo->mode),
480 asctime(LocalTime(&t))));
481 #endif /* LARGE_SMB_OFF_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)(file_info *),BOOL recurse_dir, BOOL dirstoo)
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 pstrcpy(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 pstrcpy(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 /* pstrcpy(mask,p+ff_lastname+94); */
600 pstrcpy(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, dirstoo);
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)(file_info *),BOOL recurse_dir, BOOL dirstoo)
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 client_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 client_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,dirstoo);
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)(file_info *),BOOL recurse_dir, BOOL dirstoo)
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,dirstoo) > 0)
811 expand_mask(Mask,False);
812 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo);
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 pstrcpy(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 pstrcpy(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 pstrcpy(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 pstrcpy(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 pstrcpy(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
987 RJS, 4-Apr-1998, dirstoo added to allow caller to indicate that directories
988 should be processed as well.
989 ****************************************************************************/
990 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo)
993 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
994 !mask_match(finfo->name,fileselection,False,False)) &&
995 !(recurse_dir && (strequal(finfo->name,".") ||
996 strequal(finfo->name,".."))))
998 if (recurse_dir && (finfo->mode & aDIR))
1003 if (fn && dirstoo && do_this_one(finfo)) { /* Do dirs, RJS */
1007 pstrcpy(sav_dir,cur_dir);
1008 pstrcat(cur_dir,finfo->name);
1009 pstrcat(cur_dir,"\\");
1010 pstrcpy(mask2,cur_dir);
1013 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1018 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1020 do_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1022 pstrcpy(cur_dir,sav_dir);
1026 if (fn && do_this_one(finfo))
1033 /****************************************************************************
1034 get a directory listing
1035 ****************************************************************************/
1036 static void cmd_dir(char *inbuf,char *outbuf)
1038 int attribute = aDIR | aSYSTEM | aHIDDEN;
1044 pstrcpy(mask,cur_dir);
1045 if(mask[strlen(mask)-1]!='\\')
1048 if (next_token(NULL,buf,NULL,sizeof(buf)))
1059 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse,False);
1063 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1068 /****************************************************************************
1069 get a file from rname to lname
1070 ****************************************************************************/
1071 static void do_get(char *rname,char *lname,file_info *finfo1)
1076 BOOL newhandle = False;
1077 char *inbuf,*outbuf;
1079 BOOL close_done = False;
1080 BOOL ignore_close_error = False;
1084 struct timeval tp_start;
1085 GetTimeOfDay(&tp_start);
1096 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1097 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1099 if (!inbuf || !outbuf)
1101 DEBUG(0,("out of memory\n"));
1105 bzero(outbuf,smb_size);
1106 set_message(outbuf,15,1 + strlen(rname),True);
1108 CVAL(outbuf,smb_com) = SMBopenX;
1109 SSVAL(outbuf,smb_tid,cnum);
1110 cli_setup_pkt(outbuf);
1112 SSVAL(outbuf,smb_vwv0,0xFF);
1113 SSVAL(outbuf,smb_vwv2,1); /* return additional info */
1114 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1115 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1116 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1117 SSVAL(outbuf,smb_vwv8,1);
1118 SSVAL(outbuf,smb_vwv11,0xffff);
1119 SSVAL(outbuf,smb_vwv12,0xffff);
1121 p = smb_buf(outbuf);
1123 p = skip_string(p,1);
1125 /* do a chained openX with a readX? */
1129 DEBUG(3,("Chaining readX wth openX\n"));
1130 SSVAL(outbuf,smb_vwv0,SMBreadX);
1131 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1134 SSVAL(p,smb_wct,10);
1135 SSVAL(p,smb_vwv0,0xFF);
1136 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1137 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1138 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1142 if(!strcmp(lname,"-"))
1143 handle = fileno(stdout);
1146 handle = creat(lname,0644);
1151 DEBUG(0,("Error opening local file %s\n",lname));
1152 free(inbuf);free(outbuf);
1156 send_smb(Client,outbuf);
1157 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1159 if (CVAL(inbuf,smb_rcls) != 0)
1161 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1162 SVAL(inbuf,smb_err) == ERRnoresource &&
1163 cli_reopen_connection(inbuf,outbuf))
1165 do_get(rname,lname,finfo1);
1168 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1171 free(inbuf);free(outbuf);
1175 pstrcpy(finfo.name,rname);
1179 finfo.mode = SVAL(inbuf,smb_vwv3);
1180 /* these times arrive as LOCAL time, using the DST offset
1181 corresponding to that time, we convert them to GMT */
1182 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1183 finfo.atime = finfo.ctime = finfo.mtime;
1184 finfo.size = IVAL(inbuf,smb_vwv6);
1187 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1189 fnum = SVAL(inbuf,smb_vwv2);
1191 /* we might have got some data from a chained readX */
1192 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1194 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1195 datalen = SVAL(p,smb_vwv5);
1196 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1205 #ifdef LARGE_SMB_OFF_T
1206 DEBUG(2,("getting file %s of size %.0f bytes as %s ",
1207 CNV_LANG(finfo.name),
1210 #else /* LARGE_SMB_OFF_T */
1211 DEBUG(2,("getting file %s of size %d bytes as %s ",
1212 CNV_LANG(finfo.name),
1215 #endif /* LARGE_SMB_OFF_T */
1217 while (nread < finfo.size && !close_done)
1220 static BOOL can_chain_close = True;
1224 #ifdef LARGE_SMB_OFF_T
1225 DEBUG(3,("nread=%d max_xmit=%d fsize=%.0f\n",nread,max_xmit,(double)finfo.size));
1226 #else /* LARGE_SMB_OFF_T */
1227 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,
1229 #endif /* LARGE_SMB_OFF_T */
1231 /* 3 possible read types. readbraw if a large block is required.
1232 readX + close if not much left and read if neither is supported */
1234 /* we might have already read some data from a chained readX */
1235 if (dataptr && datalen>0)
1238 /* if we can finish now then readX+close */
1239 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1240 ((finfo.size - nread) <
1241 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1244 /* if we support readraw then use that */
1245 if (method<0 && readbraw_supported)
1248 /* if we can then use readX */
1249 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1260 /* use readX + close */
1261 bzero(outbuf,smb_size);
1262 set_message(outbuf,10,0,True);
1263 CVAL(outbuf,smb_com) = SMBreadX;
1264 SSVAL(outbuf,smb_tid,cnum);
1265 cli_setup_pkt(outbuf);
1269 CVAL(outbuf,smb_vwv0) = SMBclose;
1270 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1273 CVAL(outbuf,smb_vwv0) = 0xFF;
1275 SSVAL(outbuf,smb_vwv2,fnum);
1276 SIVAL(outbuf,smb_vwv3,nread);
1277 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1278 SSVAL(outbuf,smb_vwv6,0);
1279 SIVAL(outbuf,smb_vwv7,0);
1280 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1284 p = smb_buf(outbuf);
1291 /* now set the total packet length */
1292 smb_setlen(outbuf,smb_len(outbuf)+9);
1295 send_smb(Client,outbuf);
1296 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1298 if (CVAL(inbuf,smb_rcls) != 0)
1300 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1305 SVAL(inbuf,smb_vwv0) != SMBclose)
1307 /* NOTE: WfWg sometimes just ignores the chained
1308 command! This seems to break the spec? */
1309 DEBUG(3,("Rejected chained close?\n"));
1311 can_chain_close = False;
1312 ignore_close_error = True;
1315 datalen = SVAL(inbuf,smb_vwv5);
1316 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1322 static int readbraw_size = BUFFER_SIZE;
1325 bzero(outbuf,smb_size);
1326 set_message(outbuf,8,0,True);
1327 CVAL(outbuf,smb_com) = SMBreadbraw;
1328 SSVAL(outbuf,smb_tid,cnum);
1329 cli_setup_pkt(outbuf);
1330 SSVAL(outbuf,smb_vwv0,fnum);
1331 SIVAL(outbuf,smb_vwv1,nread);
1332 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1333 SSVAL(outbuf,smb_vwv4,0);
1334 SIVALS(outbuf,smb_vwv5,-1);
1335 send_smb(Client,outbuf);
1337 /* Now read the raw data into the buffer and write it */
1338 if(read_smb_length(Client,inbuf,0) == -1) {
1339 DEBUG(0,("Failed to read length in readbraw\n"));
1343 /* Even though this is not an smb message, smb_len
1344 returns the generic length of an smb message */
1345 datalen = smb_len(inbuf);
1349 /* we got a readbraw error */
1350 DEBUG(4,("readbraw error - reducing size\n"));
1351 readbraw_size = (readbraw_size * 9) / 10;
1353 if (readbraw_size < max_xmit)
1355 DEBUG(0,("disabling readbraw\n"));
1356 readbraw_supported = False;
1363 if(read_data(Client,inbuf,datalen) != datalen) {
1364 DEBUG(0,("Failed to read data in readbraw\n"));
1372 /* we've already read some data with a chained readX */
1376 /* use plain read */
1377 bzero(outbuf,smb_size);
1378 set_message(outbuf,5,0,True);
1379 CVAL(outbuf,smb_com) = SMBread;
1380 SSVAL(outbuf,smb_tid,cnum);
1381 cli_setup_pkt(outbuf);
1383 SSVAL(outbuf,smb_vwv0,fnum);
1384 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1385 SIVAL(outbuf,smb_vwv2,nread);
1386 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1388 send_smb(Client,outbuf);
1389 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1391 if (CVAL(inbuf,smb_rcls) != 0)
1393 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1397 datalen = SVAL(inbuf,smb_vwv0);
1398 dataptr = smb_buf(inbuf) + 3;
1402 if (writefile(handle,dataptr,datalen) != datalen)
1404 DEBUG(0,("Error writing local file\n"));
1411 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1423 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1425 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1427 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1430 free(inbuf);free(outbuf);
1438 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1439 bzero(outbuf,smb_size);
1440 set_message(outbuf,8,strlen(rname)+4,True);
1441 CVAL(outbuf,smb_com) = SMBsetatr;
1442 SSVAL(outbuf,smb_tid,cnum);
1443 cli_setup_pkt(outbuf);
1444 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1445 SIVALS(outbuf,smb_vwv1,0);
1446 p = smb_buf(outbuf);
1452 send_smb(Client,outbuf);
1453 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1457 struct timeval tp_end;
1460 GetTimeOfDay(&tp_end);
1462 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1463 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1464 get_total_time_ms += this_time;
1465 get_total_size += finfo.size;
1467 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1468 finfo.size / (1.024*this_time + 1.0e-4),
1469 get_total_size / (1.024*get_total_time_ms)));
1472 free(inbuf);free(outbuf);
1476 /****************************************************************************
1478 ****************************************************************************/
1479 static void cmd_get(char *dum_in, char *dum_out)
1485 pstrcpy(rname,cur_dir);
1486 pstrcat(rname,"\\");
1488 p = rname + strlen(rname);
1490 if (!next_token(NULL,p,NULL,sizeof(rname)-strlen(rname))) {
1491 DEBUG(0,("get <filename>\n"));
1495 dos_clean_name(rname);
1497 next_token(NULL,lname,NULL,sizeof(lname));
1499 do_get(rname,lname,NULL);
1503 /****************************************************************************
1504 do a mget operation on one file
1505 ****************************************************************************/
1506 static void do_mget(file_info *finfo)
1511 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1516 DEBUG(0,("mget aborted\n"));
1520 if (finfo->mode & aDIR)
1521 slprintf(quest,sizeof(pstring)-1,
1522 "Get directory %s? ",CNV_LANG(finfo->name));
1524 slprintf(quest,sizeof(pstring)-1,
1525 "Get file %s? ",CNV_LANG(finfo->name));
1527 if (prompt && !yesno(quest)) return;
1529 if (finfo->mode & aDIR)
1531 pstring saved_curdir;
1533 char *inbuf,*outbuf;
1535 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1536 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1538 if (!inbuf || !outbuf)
1540 DEBUG(0,("out of memory\n"));
1544 pstrcpy(saved_curdir,cur_dir);
1546 pstrcat(cur_dir,finfo->name);
1547 pstrcat(cur_dir,"\\");
1549 unix_format(finfo->name);
1552 strlower(finfo->name);
1554 if (!directory_exist(finfo->name,NULL) &&
1555 dos_mkdir(finfo->name,0777) != 0)
1557 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1558 pstrcpy(cur_dir,saved_curdir);
1559 free(inbuf);free(outbuf);
1563 if (dos_chdir(finfo->name) != 0)
1565 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1566 pstrcpy(cur_dir,saved_curdir);
1567 free(inbuf);free(outbuf);
1572 pstrcpy(mget_mask,cur_dir);
1573 pstrcat(mget_mask,"*");
1575 do_dir((char *)inbuf,(char *)outbuf,
1576 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False, False);
1578 pstrcpy(cur_dir,saved_curdir);
1579 free(inbuf);free(outbuf);
1583 pstrcpy(rname,cur_dir);
1584 pstrcat(rname,finfo->name);
1585 do_get(rname,finfo->name,finfo);
1589 /****************************************************************************
1590 view the file using the pager
1591 ****************************************************************************/
1592 static void cmd_more(char *dum_in, char *dum_out)
1594 fstring rname,lname,tmpname,pager_cmd;
1597 fstrcpy(rname,cur_dir);
1598 fstrcat(rname,"\\");
1601 "%s/smbmore.%d",tmpdir(),(int)getpid());
1602 fstrcpy(lname,tmpname);
1604 if (!next_token(NULL,rname+strlen(rname),NULL,sizeof(rname)-strlen(rname))) {
1605 DEBUG(0,("more <filename>\n"));
1608 dos_clean_name(rname);
1610 do_get(rname,lname,NULL);
1612 pager=getenv("PAGER");
1614 slprintf(pager_cmd,sizeof(pager_cmd)-1,
1615 "%s %s",(pager? pager:PAGER), tmpname);
1622 /****************************************************************************
1624 ****************************************************************************/
1625 static void cmd_mget(char *inbuf,char *outbuf)
1627 int attribute = aSYSTEM | aHIDDEN;
1639 while (next_token(NULL,p,NULL,sizeof(buf)))
1641 pstrcpy(mget_mask,cur_dir);
1642 if(mget_mask[strlen(mget_mask)-1]!='\\')
1643 pstrcat(mget_mask,"\\");
1646 pstrcpy(mget_mask,p);
1648 pstrcat(mget_mask,p);
1649 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1654 pstrcpy(mget_mask,cur_dir);
1655 if(mget_mask[strlen(mget_mask)-1]!='\\')
1656 pstrcat(mget_mask,"\\");
1657 pstrcat(mget_mask,"*");
1658 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1662 /****************************************************************************
1663 make a directory of name "name"
1664 ****************************************************************************/
1665 static BOOL do_mkdir(char *name)
1668 char *inbuf,*outbuf;
1670 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1671 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1673 if (!inbuf || !outbuf)
1675 DEBUG(0,("out of memory\n"));
1679 bzero(outbuf,smb_size);
1680 set_message(outbuf,0,2 + strlen(name),True);
1682 CVAL(outbuf,smb_com) = SMBmkdir;
1683 SSVAL(outbuf,smb_tid,cnum);
1684 cli_setup_pkt(outbuf);
1687 p = smb_buf(outbuf);
1691 send_smb(Client,outbuf);
1692 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1694 if (CVAL(inbuf,smb_rcls) != 0)
1696 DEBUG(0,("%s making remote directory %s\n",
1697 smb_errstr(inbuf),CNV_LANG(name)));
1699 free(inbuf);free(outbuf);
1703 free(inbuf);free(outbuf);
1708 /****************************************************************************
1710 ****************************************************************************/
1711 static void cmd_mkdir(char *inbuf,char *outbuf)
1717 pstrcpy(mask,cur_dir);
1719 if (!next_token(NULL,p,NULL,sizeof(buf)))
1722 DEBUG(0,("mkdir <dirname>\n"));
1734 trim_string(ddir,".",NULL);
1735 p = strtok(ddir,"/\\");
1739 if (!chkpath(ddir2,False))
1743 pstrcat(ddir2,"\\");
1744 p = strtok(NULL,"/\\");
1752 /*******************************************************************
1753 write to a file using writebraw
1754 ********************************************************************/
1755 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1760 bzero(outbuf,smb_size);
1761 bzero(inbuf,smb_size);
1762 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1764 CVAL(outbuf,smb_com) = SMBwritebraw;
1765 SSVAL(outbuf,smb_tid,cnum);
1766 cli_setup_pkt(outbuf);
1768 SSVAL(outbuf,smb_vwv0,fnum);
1769 SSVAL(outbuf,smb_vwv1,n);
1770 SIVAL(outbuf,smb_vwv3,pos);
1771 SSVAL(outbuf,smb_vwv7,1);
1773 send_smb(Client,outbuf);
1775 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1778 _smb_setlen(buf-4,n); /* HACK! XXXX */
1780 if (write_socket(Client,buf-4,n+4) != n+4)
1783 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1784 DEBUG(0,("Error writing remote file (2)\n"));
1787 return(SVAL(inbuf,smb_vwv0));
1792 /*******************************************************************
1794 ********************************************************************/
1795 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1799 if (writebraw_supported && n > (max_xmit-200))
1800 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1802 bzero(outbuf,smb_size);
1803 bzero(inbuf,smb_size);
1804 set_message(outbuf,5,n + 3,True);
1806 CVAL(outbuf,smb_com) = SMBwrite;
1807 SSVAL(outbuf,smb_tid,cnum);
1808 cli_setup_pkt(outbuf);
1810 SSVAL(outbuf,smb_vwv0,fnum);
1811 SSVAL(outbuf,smb_vwv1,n);
1812 SIVAL(outbuf,smb_vwv2,pos);
1813 SSVAL(outbuf,smb_vwv4,0);
1814 CVAL(smb_buf(outbuf),0) = 1;
1815 SSVAL(smb_buf(outbuf),1,n);
1817 memcpy(smb_buf(outbuf)+3,buf,n);
1819 send_smb(Client,outbuf);
1820 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1822 if (CVAL(inbuf,smb_rcls) != 0) {
1823 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1826 return(SVAL(inbuf,smb_vwv0));
1831 /****************************************************************************
1833 ****************************************************************************/
1834 static void do_put(char *rname,char *lname,file_info *finfo)
1840 char *inbuf,*outbuf;
1841 time_t close_time = finfo->mtime;
1843 static int maxwrite=0;
1845 struct timeval tp_start;
1846 GetTimeOfDay(&tp_start);
1848 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1849 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1851 if (!inbuf || !outbuf)
1853 DEBUG(0,("out of memory\n"));
1857 bzero(outbuf,smb_size);
1858 set_message(outbuf,3,2 + strlen(rname),True);
1860 if (finfo->mtime == 0 || finfo->mtime == -1)
1861 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1863 CVAL(outbuf,smb_com) = SMBcreate;
1864 SSVAL(outbuf,smb_tid,cnum);
1865 cli_setup_pkt(outbuf);
1867 SSVAL(outbuf,smb_vwv0,finfo->mode);
1868 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1870 p = smb_buf(outbuf);
1874 send_smb(Client,outbuf);
1875 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1877 if (CVAL(inbuf,smb_rcls) != 0)
1879 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1881 free(inbuf);free(outbuf);if (buf) free(buf);
1885 /* allow files to be piped into smbclient
1886 jdblair 24.jun.98 */
1887 if (!strcmp(lname, "-")) {
1889 /* size of file is not known */
1892 f = fopen(lname,"r");
1897 DEBUG(0,("Error opening local file %s\n",lname));
1898 free(inbuf);free(outbuf);
1903 fnum = SVAL(inbuf,smb_vwv0);
1904 if (finfo->size < 0)
1905 finfo->size = file_size(lname);
1907 #ifdef LARGE_SMB_OFF_T
1908 DEBUG(1,("putting file %s of size %.0f bytes as %s ",lname,(double)finfo->size,CNV_LANG(rname)));
1909 #else /* LARGE_SMB_OFF_T */
1910 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,
1911 (int)finfo->size,CNV_LANG(rname)));
1912 #endif /* LARGE_SMB_OFF_T */
1915 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1917 /* This is a rewrite of the read/write loop that doesn't require the input
1918 file to be of a known length. This allows the stream pointer 'f' to
1921 Rather than reallocing the read buffer every loop to keep it the min
1922 necessary length this look uses a fixed length buffer and just tests
1923 for eof on the file stream at the top of each loop.
1924 jdblair, 24.jun.98 */
1926 buf = (char *)malloc(maxwrite+4);
1932 fseek(f,nread,SEEK_SET);
1933 if ((n = readfile(buf+4,1,n,f)) < 1)
1935 DEBUG(0,("Error reading local file\n"));
1939 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1943 DEBUG(0,("Error writing file\n"));
1954 bzero(outbuf,smb_size);
1955 set_message(outbuf,3,0,True);
1956 CVAL(outbuf,smb_com) = SMBclose;
1957 SSVAL(outbuf,smb_tid,cnum);
1958 cli_setup_pkt(outbuf);
1960 SSVAL(outbuf,smb_vwv0,fnum);
1961 put_dos_date3(outbuf,smb_vwv1,close_time);
1963 send_smb(Client,outbuf);
1964 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1966 if (CVAL(inbuf,smb_rcls) != 0)
1968 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1970 free(inbuf);free(outbuf);
1977 free(inbuf);free(outbuf);
1981 struct timeval tp_end;
1984 GetTimeOfDay(&tp_end);
1986 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1987 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1988 put_total_time_ms += this_time;
1989 put_total_size += finfo->size;
1991 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1992 finfo->size / (1.024*this_time + 1.0e-4),
1993 put_total_size / (1.024*put_total_time_ms)));
1999 /****************************************************************************
2001 ****************************************************************************/
2002 static void cmd_put(char *dum_in, char *dum_out)
2011 pstrcpy(rname,cur_dir);
2012 pstrcat(rname,"\\");
2015 if (!next_token(NULL,p,NULL,sizeof(buf)))
2017 DEBUG(0,("put <filename>\n"));
2022 if (next_token(NULL,p,NULL,sizeof(buf)))
2025 pstrcat(rname,lname);
2027 dos_clean_name(rname);
2031 /* allow '-' to represent stdin
2032 jdblair, 24.jun.98 */
2033 if (!file_exist(lname,&st) &&
2034 (strcmp(lname,"-"))) {
2035 DEBUG(0,("%s does not exist\n",lname));
2038 finfo.mtime = st.st_mtime;
2041 do_put(rname,lname,&finfo);
2044 /****************************************************************************
2045 seek in a directory/file list until you get something that doesn't start with
2047 ****************************************************************************/
2048 static BOOL seek_list(FILE *f,char *name)
2053 if (fscanf(f,"%s",s) != 1) return(False);
2054 trim_string(s,"./",NULL);
2055 if (strncmp(s,name,strlen(name)) != 0)
2066 /****************************************************************************
2067 set the file selection mask
2068 ****************************************************************************/
2069 static void cmd_select(char *dum_in, char *dum_out)
2071 pstrcpy(fileselection,"");
2072 next_token(NULL,fileselection,NULL,sizeof(fileselection));
2076 /****************************************************************************
2078 ****************************************************************************/
2079 static void cmd_mput(char *dum_in, char *dum_out)
2090 while (next_token(NULL,p,NULL,sizeof(buf)))
2097 slprintf(tmpname,sizeof(pstring)-1,
2098 "%s/ls.smb.%d",tmpdir(),(int)getpid());
2100 slprintf(cmd,sizeof(pstring)-1,
2101 "find . -name \"%s\" -print > %s",p,tmpname);
2103 slprintf(cmd,sizeof(pstring)-1,
2104 "/bin/ls %s > %s",p,tmpname);
2107 f = fopen(tmpname,"r");
2114 if (fscanf(f,"%s",lname) != 1) break;
2115 trim_string(lname,"./",NULL);
2119 /* check if it's a directory */
2120 if (directory_exist(lname,&st))
2122 if (!recurse) continue;
2123 slprintf(quest,sizeof(pstring)-1,
2124 "Put directory %s? ",lname);
2125 if (prompt && !yesno(quest))
2128 if (!seek_list(f,lname))
2133 pstrcpy(rname,cur_dir);
2134 pstrcat(rname,lname);
2135 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2137 if (!seek_list(f,lname))
2146 slprintf(quest,sizeof(quest)-1,
2147 "Put file %s? ",lname);
2148 if (prompt && !yesno(quest)) continue;
2150 pstrcpy(rname,cur_dir);
2151 pstrcat(rname,lname);
2155 /* null size so do_put knows to ignore it */
2158 /* set the date on the file */
2159 finfo.mtime = st.st_mtime;
2161 do_put(rname,lname,&finfo);
2168 /****************************************************************************
2170 ****************************************************************************/
2171 static void do_cancel(int job)
2173 char *rparam = NULL;
2179 bzero(param,sizeof(param));
2182 SSVAL(p,0,81); /* DosPrintJobDel() */
2185 p = skip_string(p,1);
2187 p = skip_string(p,1);
2191 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2197 int res = SVAL(rparam,0);
2200 printf("Job %d cancelled\n",job);
2202 printf("Error %d calcelling job %d\n",res,job);
2206 printf("Server refused cancel request\n");
2208 if (rparam) free(rparam);
2209 if (rdata) free(rdata);
2215 /****************************************************************************
2217 ****************************************************************************/
2218 static void cmd_cancel(char *inbuf,char *outbuf )
2223 if (!connect_as_printer)
2225 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2226 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2229 if (!next_token(NULL,buf,NULL,sizeof(buf))) {
2230 printf("cancel <jobid> ...\n");
2236 } while (next_token(NULL,buf,NULL,sizeof(buf)));
2242 /****************************************************************************
2244 ****************************************************************************/
2245 static void cmd_print(char *inbuf,char *outbuf )
2254 if (!connect_as_printer)
2256 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2257 DEBUG(0,("Trying to print without -P may fail\n"));
2260 if (!next_token(NULL,lname,NULL, sizeof(lname)))
2262 DEBUG(0,("print <filename>\n"));
2266 pstrcpy(rname,lname);
2267 p = strrchr(rname,'/');
2272 pstrcpy(rname,tname);
2275 if ((int)strlen(rname) > 14)
2278 if (strequal(lname,"-"))
2281 pstrcpy(rname,"stdin");
2284 dos_clean_name(rname);
2286 bzero(outbuf,smb_size);
2287 set_message(outbuf,2,2 + strlen(rname),True);
2289 CVAL(outbuf,smb_com) = SMBsplopen;
2290 SSVAL(outbuf,smb_tid,cnum);
2291 cli_setup_pkt(outbuf);
2293 SSVAL(outbuf,smb_vwv0,0);
2294 SSVAL(outbuf,smb_vwv1,printmode);
2296 p = smb_buf(outbuf);
2300 send_smb(Client,outbuf);
2301 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2303 if (CVAL(inbuf,smb_rcls) != 0)
2305 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2310 f = fopen(lname,"r");
2313 DEBUG(0,("Error opening local file %s\n",lname));
2318 fnum = SVAL(inbuf,smb_vwv0);
2320 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2326 bzero(outbuf,smb_size);
2327 set_message(outbuf,1,3,True);
2329 /* for some strange reason the OS/2 print server can't handle large
2330 packets when printing. weird */
2331 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2334 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2336 n = readfile(smb_buf(outbuf)+3,1,n,f);
2339 DEBUG(0,("read gave %d\n",n));
2343 smb_setlen(outbuf,smb_len(outbuf) + n);
2345 CVAL(outbuf,smb_com) = SMBsplwr;
2346 SSVAL(outbuf,smb_tid,cnum);
2347 cli_setup_pkt(outbuf);
2349 SSVAL(outbuf,smb_vwv0,fnum);
2350 SSVAL(outbuf,smb_vwv1,n+3);
2351 CVAL(smb_buf(outbuf),0) = 1;
2352 SSVAL(smb_buf(outbuf),1,n);
2354 send_smb(Client,outbuf);
2355 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2357 if (CVAL(inbuf,smb_rcls) != 0)
2359 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2366 DEBUG(2,("%d bytes printed\n",nread));
2368 bzero(outbuf,smb_size);
2369 set_message(outbuf,1,0,True);
2370 CVAL(outbuf,smb_com) = SMBsplclose;
2371 SSVAL(outbuf,smb_tid,cnum);
2372 cli_setup_pkt(outbuf);
2374 SSVAL(outbuf,smb_vwv0,fnum);
2376 send_smb(Client,outbuf);
2377 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2379 if (CVAL(inbuf,smb_rcls) != 0)
2381 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2391 /****************************************************************************
2392 show a print queue - this is deprecated as it uses the old smb that
2393 has limited support - the correct call is the cmd_p_queue_4() after this.
2394 ****************************************************************************/
2395 static void cmd_queue(char *inbuf,char *outbuf )
2400 bzero(outbuf,smb_size);
2401 set_message(outbuf,2,0,True);
2403 CVAL(outbuf,smb_com) = SMBsplretq;
2404 SSVAL(outbuf,smb_tid,cnum);
2405 cli_setup_pkt(outbuf);
2407 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2408 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2410 send_smb(Client,outbuf);
2411 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2413 if (CVAL(inbuf,smb_rcls) != 0)
2415 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2419 count = SVAL(inbuf,smb_vwv0);
2420 p = smb_buf(inbuf) + 3;
2423 DEBUG(0,("No entries in the print queue\n"));
2430 DEBUG(0,("Job Name Size Status\n"));
2436 case 0x01: safe_strcpy(status,"held or stopped", sizeof(status)-1); break;
2437 case 0x02: safe_strcpy(status,"printing",sizeof(status)-1); break;
2438 case 0x03: safe_strcpy(status,"awaiting print", sizeof(status)-1); break;
2439 case 0x04: safe_strcpy(status,"in intercept",sizeof(status)-1); break;
2440 case 0x05: safe_strcpy(status,"file had error",sizeof(status)-1); break;
2441 case 0x06: safe_strcpy(status,"printer error",sizeof(status)-1); break;
2442 default: safe_strcpy(status,"unknown",sizeof(status)-1); break;
2445 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2446 SVAL(p,5),p+12,IVAL(p,7),status));
2454 /****************************************************************************
2455 show information about a print queue
2456 ****************************************************************************/
2457 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2459 char *rparam = NULL;
2466 if (!connect_as_printer)
2468 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2469 DEBUG(0,("Trying to print without -P may fail\n"));
2472 bzero(param,sizeof(param));
2475 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2477 pstrcpy(p,"zWrLeh"); /* parameter description? */
2478 p = skip_string(p,1);
2479 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
2480 p = skip_string(p,1);
2481 pstrcpy(p,strrchr(service,'\\')+1); /* name of queue */
2482 p = skip_string(p,1);
2483 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2484 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2486 pstrcpy(p,""); /* subformat */
2487 p = skip_string(p,1);
2489 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2490 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2497 result_code = SVAL(rparam,0);
2498 converter = SVAL(rparam,2); /* conversion factor */
2500 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2502 if (result_code == 0) /* if no error, */
2512 fstring PrinterName;
2514 fstrcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2515 strlower(PrinterName); /* in lower case */
2517 p = rdata; /* received data */
2518 for( i = 0; i < SVAL(rparam,4); ++i)
2521 Priority = SVAL(p,2);
2522 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2524 Priority = SVAL(p,2);
2525 JobTime = make_unix_date3( p + 12);
2526 JobTimeStr = asctime(LocalTime( &JobTime));
2528 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2531 printf("%s-%u %s priority %u %s %s %u bytes\n",
2532 PrinterName, JobId, UserName,
2533 Priority, JobTimeStr, JobName, Size);
2535 #if 0 /* DEBUG code */
2536 printf("Job Id: \"%u\"\n", SVAL(p,0));
2537 printf("Priority: \"%u\"\n", SVAL(p,2));
2539 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2540 printf("Position: \"%u\"\n", SVAL(p,8));
2541 printf("Status: \"%u\"\n", SVAL(p,10));
2543 JobTime = make_unix_date3( p + 12);
2544 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2545 printf("date: \"%u\"\n", SVAL(p,12));
2547 printf("Size: \"%u\"\n", SVAL(p,16));
2548 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2549 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2550 #endif /* DEBUG CODE */
2555 else /* cli_call_api() failed */
2557 printf("Failed, error = %d\n", result_code);
2560 /* If any parameters or data were returned, free the storage. */
2561 if(rparam) free(rparam);
2562 if(rdata) free(rdata);
2567 /****************************************************************************
2568 show information about a print queue
2569 ****************************************************************************/
2570 static void cmd_qinfo(char *inbuf,char *outbuf )
2572 char *rparam = NULL;
2579 bzero(param,sizeof(param));
2582 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2584 pstrcpy(p,"zWrLh"); /* parameter description? */
2585 p = skip_string(p,1);
2586 pstrcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2587 p = skip_string(p,1);
2588 pstrcpy(p,strrchr(service,'\\')+1); /* name of queue */
2589 p = skip_string(p,1);
2590 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2591 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2593 pstrcpy(p,""); /* subformat */
2594 p = skip_string(p,1);
2596 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2597 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2604 result_code = SVAL(rparam,0);
2605 converter = SVAL(rparam,2); /* conversion factor */
2607 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2609 if (result_code == 0) /* if no error, */
2611 p = rdata; /* received data */
2613 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2614 printf("Priority: %u\n", SVAL(p,4) );
2615 printf("Start time: %u\n", SVAL(p,6) );
2616 printf("Until time: %u\n", SVAL(p,8) );
2617 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2618 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2619 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2620 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2621 printf("Status: %u\n", SVAL(p,28) );
2622 printf("Jobs: %u\n", SVAL(p,30) );
2623 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2624 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2626 /* Dump the driver data */
2631 ddptr = rdata + SVAL(p,40) - converter;
2632 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2633 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2635 for(x=8; x < count; x+=16)
2637 for(y=0; y < 16; y++)
2640 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2644 for(y=0; y < 16 && (x+y) < count; y++)
2646 c = CVAL(ddptr,(x+y));
2652 fputc('\n', stdout);
2658 else /* cli_call_api() failed */
2660 printf("Failed, error = %d\n", result_code);
2663 /* If any parameters or data were returned, free the storage. */
2664 if(rparam) free(rparam);
2665 if(rdata) free(rdata);
2670 /****************************************************************************
2672 ****************************************************************************/
2673 static void do_del(file_info *finfo)
2676 char *inbuf,*outbuf;
2679 pstrcpy(mask,cur_dir);
2680 pstrcat(mask,finfo->name);
2682 if (finfo->mode & aDIR)
2685 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2686 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2688 if (!inbuf || !outbuf)
2690 DEBUG(0,("out of memory\n"));
2694 bzero(outbuf,smb_size);
2695 set_message(outbuf,1,2 + strlen(mask),True);
2697 CVAL(outbuf,smb_com) = SMBunlink;
2698 SSVAL(outbuf,smb_tid,cnum);
2699 cli_setup_pkt(outbuf);
2701 SSVAL(outbuf,smb_vwv0,0);
2703 p = smb_buf(outbuf);
2707 send_smb(Client,outbuf);
2708 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2710 if (CVAL(inbuf,smb_rcls) != 0)
2711 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2713 free(inbuf);free(outbuf);
2717 /****************************************************************************
2719 ****************************************************************************/
2720 static void cmd_del(char *inbuf,char *outbuf )
2724 int attribute = aSYSTEM | aHIDDEN;
2729 pstrcpy(mask,cur_dir);
2731 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2733 DEBUG(0,("del <filename>\n"));
2738 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False,False);
2742 /****************************************************************************
2744 ****************************************************************************/
2745 static void cmd_rmdir(char *inbuf,char *outbuf )
2751 pstrcpy(mask,cur_dir);
2753 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2755 DEBUG(0,("rmdir <dirname>\n"));
2760 bzero(outbuf,smb_size);
2761 set_message(outbuf,0,2 + strlen(mask),True);
2763 CVAL(outbuf,smb_com) = SMBrmdir;
2764 SSVAL(outbuf,smb_tid,cnum);
2765 cli_setup_pkt(outbuf);
2768 p = smb_buf(outbuf);
2772 send_smb(Client,outbuf);
2773 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2775 if (CVAL(inbuf,smb_rcls) != 0)
2777 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2783 /****************************************************************************
2785 ****************************************************************************/
2786 static void cmd_rename(char *inbuf,char *outbuf )
2792 pstrcpy(src,cur_dir);
2793 pstrcpy(dest,cur_dir);
2795 if (!next_token(NULL,buf,NULL,sizeof(buf)) ||
2796 !next_token(NULL,buf2,NULL, sizeof(buf2)))
2798 DEBUG(0,("rename <src> <dest>\n"));
2804 bzero(outbuf,smb_size);
2805 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2807 CVAL(outbuf,smb_com) = SMBmv;
2808 SSVAL(outbuf,smb_tid,cnum);
2809 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2810 cli_setup_pkt(outbuf);
2812 p = smb_buf(outbuf);
2815 p = skip_string(p,1);
2819 send_smb(Client,outbuf);
2820 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2822 if (CVAL(inbuf,smb_rcls) != 0)
2824 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2831 /****************************************************************************
2832 toggle the prompt flag
2833 ****************************************************************************/
2834 static void cmd_prompt(char *dum_in, char *dum_out)
2837 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2841 /****************************************************************************
2842 set the newer than time
2843 ****************************************************************************/
2844 static void cmd_newer(char *dum_in, char *dum_out)
2848 SMB_STRUCT_STAT sbuf;
2850 ok = next_token(NULL,buf,NULL,sizeof(buf));
2851 if (ok && (dos_stat(buf,&sbuf) == 0))
2853 newer_than = sbuf.st_mtime;
2854 DEBUG(1,("Getting files newer than %s",
2855 asctime(LocalTime(&newer_than))));
2860 if (ok && newer_than == 0)
2861 DEBUG(0,("Error setting newer-than time\n"));
2864 /****************************************************************************
2865 set the archive level
2866 ****************************************************************************/
2867 static void cmd_archive(char *dum_in, char *dum_out)
2871 if (next_token(NULL,buf,NULL,sizeof(buf))) {
2872 archive_level = atoi(buf);
2874 DEBUG(0,("Archive level is %d\n",archive_level));
2877 /****************************************************************************
2878 toggle the lowercaseflag
2879 ****************************************************************************/
2880 static void cmd_lowercase(char *dum_in, char *dum_out)
2882 lowercase = !lowercase;
2883 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2889 /****************************************************************************
2890 toggle the recurse flag
2891 ****************************************************************************/
2892 static void cmd_recurse(char *dum_in, char *dum_out)
2895 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2898 /****************************************************************************
2899 toggle the translate flag
2900 ****************************************************************************/
2901 static void cmd_translate(char *dum_in, char *dum_out)
2903 translation = !translation;
2904 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2905 translation?"on":"off"));
2909 /****************************************************************************
2910 do a printmode command
2911 ****************************************************************************/
2912 static void cmd_printmode(char *dum_in, char *dum_out)
2917 if (next_token(NULL,buf,NULL,sizeof(buf)))
2919 if (strequal(buf,"text"))
2923 if (strequal(buf,"graphics"))
2926 printmode = atoi(buf);
2933 fstrcpy(mode,"text");
2936 fstrcpy(mode,"graphics");
2939 slprintf(mode,sizeof(mode)-1,"%d",printmode);
2943 DEBUG(2,("the printmode is now %s\n",mode));
2946 /****************************************************************************
2948 ****************************************************************************/
2949 static void cmd_lcd(char *dum_in, char *dum_out)
2954 if (next_token(NULL,buf,NULL,sizeof(buf)))
2956 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2960 /****************************************************************************
2961 try and browse available connections on a host
2962 ****************************************************************************/
2963 static BOOL browse_host(BOOL sort)
2965 char *rparam = NULL;
2972 /* now send a SMBtrans command with api RNetShareEnum */
2974 SSVAL(p,0,0); /* api number */
2977 p = skip_string(p,1);
2978 pstrcpy(p,"B13BWz");
2979 p = skip_string(p,1);
2981 SSVAL(p,2,BUFFER_SIZE);
2984 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2990 int res = SVAL(rparam,0);
2991 int converter=SVAL(rparam,2);
2993 BOOL long_share_name=False;
2995 if (res == 0 || res == ERRmoredata)
2997 count=SVAL(rparam,4);
3002 printf("\n\tSharename Type Comment\n");
3003 printf("\t--------- ---- -------\n");
3007 qsort(p,count,20,QSORT_CAST StrCaseCmp);
3009 for (i=0;i<count;i++)
3012 int type = SVAL(p,14);
3013 int comment_offset = IVAL(p,16) & 0xFFFF;
3019 case STYPE_DISKTREE:
3020 fstrcpy(typestr,"Disk"); break;
3022 fstrcpy(typestr,"Printer"); break;
3024 fstrcpy(typestr,"Device"); break;
3026 fstrcpy(typestr,"IPC"); break;
3029 printf("\t%-15.15s%-10.10s%s\n",
3031 comment_offset?rdata+comment_offset-converter:"");
3033 if (strlen(sname)>8) long_share_name=True;
3038 if (long_share_name) {
3039 printf("\nNOTE: There were share names longer than 8 chars.\n\
3040 On older clients these may not be accessible or may give browsing errors\n");
3043 if(res == ERRmoredata)
3044 printf("\nNOTE: More data was available, the list was truncated.\n");
3048 if (rparam) free(rparam);
3049 if (rdata) free(rdata);
3055 /****************************************************************************
3056 get some server info
3057 ****************************************************************************/
3058 static void server_info(void)
3060 char *rparam = NULL;
3066 bzero(param,sizeof(param));
3069 SSVAL(p,0,63); /* NetServerGetInfo()? */
3072 p = skip_string(p,1);
3073 pstrcpy(p,"zzzBBzz");
3074 p = skip_string(p,1);
3075 SSVAL(p,0,10); /* level 10 */
3079 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3085 int res = SVAL(rparam,0);
3086 int converter=SVAL(rparam,2);
3092 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3093 rdata+SVAL(p,0)-converter,
3094 rdata+SVAL(p,4)-converter,
3095 rdata+SVAL(p,8)-converter,
3096 rdata+SVAL(p,14)-converter);
3100 if (rparam) free(rparam);
3101 if (rdata) free(rdata);
3107 /****************************************************************************
3108 try and browse available connections on a host
3109 ****************************************************************************/
3110 static BOOL list_servers(char *wk_grp)
3112 char *rparam = NULL;
3120 BOOL generic_request = False;
3123 if (strequal(wk_grp,"WORKGROUP")) {
3124 /* we won't specify a workgroup */
3125 generic_request = True;
3128 /* now send a SMBtrans command with api ServerEnum? */
3130 SSVAL(p,0,0x68); /* api number */
3133 pstrcpy(p,generic_request?"WrLehDO":"WrLehDz");
3134 p = skip_string(p,1);
3136 pstrcpy(p,"B16BBDz");
3138 p = skip_string(p,1);
3140 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3146 if (!generic_request) {
3148 p = skip_string(p,1);
3151 /* first ask for a list of servers in this workgroup */
3152 SIVAL(svtype_p,0,SV_TYPE_ALL);
3154 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3155 8, BUFFER_SIZE - SAFETY_MARGIN,
3160 int res = SVAL(rparam,0);
3161 int converter=SVAL(rparam,2);
3164 if (res == 0 || res == ERRmoredata) {
3166 count=SVAL(rparam,4);
3169 printf("\n\nThis machine has a browse list:\n");
3170 printf("\n\tServer Comment\n");
3171 printf("\t--------- -------\n");
3174 for (i=0;i<count;i++) {
3176 int comment_offset = IVAL(p2,22) & 0xFFFF;
3177 printf("\t%-16.16s %s\n", sname,
3178 comment_offset?rdata+comment_offset-converter:"");
3184 if(res == ERRmoredata)
3185 printf("\nNOTE: More data was available, the list was truncated.\n");
3189 if (rparam) {free(rparam); rparam = NULL;}
3190 if (rdata) {free(rdata); rdata = NULL;}
3192 /* now ask for a list of workgroups */
3193 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3195 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3196 8, BUFFER_SIZE - SAFETY_MARGIN,
3201 int res = SVAL(rparam,0);
3202 int converter=SVAL(rparam,2);
3205 if (res == 0 || res == ERRmoredata) {
3207 count=SVAL(rparam,4);
3210 printf("\n\nThis machine has a workgroup list:\n");
3211 printf("\n\tWorkgroup Master\n");
3212 printf("\t--------- -------\n");
3215 for (i=0;i<count;i++) {
3217 int comment_offset = IVAL(p2,22) & 0xFFFF;
3218 printf("\t%-16.16s %s\n", sname,
3219 comment_offset?rdata+comment_offset-converter:"");
3225 if(res == ERRmoredata)
3226 printf("\nNOTE: More data was available, the list was truncated.\n");
3230 if (rparam) free(rparam);
3231 if (rdata) free(rdata);
3237 /* This defines the commands supported by this client */
3241 void (*fn)(char *, char *);
3245 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3246 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3247 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3248 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3249 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3250 {"get",cmd_get,"<remote name> [local name] get a file"},
3251 {"mget",cmd_mget,"<mask> get all the matching files"},
3252 {"put",cmd_put,"<local name> [remote name] put a file"},
3253 {"mput",cmd_mput,"<mask> put all matching files"},
3254 {"rename",cmd_rename,"<src> <dest> rename some files"},
3255 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3256 {"mask",cmd_select,"<mask> mask all filenames against this"},
3257 {"del",cmd_del,"<mask> delete all matching files"},
3258 {"rm",cmd_del,"<mask> delete all matching files"},
3259 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3260 {"md",cmd_mkdir,"<directory> make a directory"},
3261 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
3262 {"rd",cmd_rmdir,"<directory> remove a directory"},
3263 {"pq",cmd_p_queue_4,"enumerate the print queue"},
3264 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
3265 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
3266 {"translate",cmd_translate,"toggle text translation for printing"},
3267 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
3268 {"print",cmd_print,"<file name> print a file"},
3269 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
3270 {"queue",cmd_queue,"show the print queue"},
3271 {"qinfo",cmd_qinfo,"show print queue information"},
3272 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
3273 {"quit",cli_send_logout,"logoff the server"},
3274 {"q",cli_send_logout,"logoff the server"},
3275 {"exit",cli_send_logout,"logoff the server"},
3276 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
3277 {"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"},
3278 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3279 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
3280 {"tarmode",cmd_tarmode,
3281 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3282 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
3283 {"help",cmd_help,"[command] give help on a command"},
3284 {"?",cmd_help,"[command] give help on a command"},
3285 {"!",NULL,"run a shell command on the local system"},
3290 /*******************************************************************
3291 lookup a command string in the list of commands, including
3293 ******************************************************************/
3294 static int process_tok(fstring tok)
3296 int i = 0, matches = 0;
3298 int tok_len = strlen(tok);
3300 while (commands[i].fn != NULL)
3302 if (strequal(commands[i].name,tok))
3308 else if (strnequal(commands[i].name, tok, tok_len))
3318 else if (matches == 1)
3324 /****************************************************************************
3326 ****************************************************************************/
3327 static void cmd_help(char *dum_in, char *dum_out)
3332 if (next_token(NULL,buf,NULL,sizeof(buf)))
3334 if ((i = process_tok(buf)) >= 0)
3335 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3338 while (commands[i].description)
3340 for (j=0; commands[i].description && (j<5); j++) {
3341 DEBUG(0,("%-15s",commands[i].name));
3350 /****************************************************************************
3351 wait for keyboard activity, swallowing network packets
3352 ****************************************************************************/
3353 static void wait_keyboard(char *buffer)
3357 struct timeval timeout;
3363 FD_SET(Client,&fds);
3364 FD_SET(fileno(stdin),&fds);
3366 timeout.tv_sec = 20;
3367 timeout.tv_usec = 0;
3368 selrtn = sys_select(MAX(Client,fileno(stdin))+1,&fds,&timeout);
3370 if (FD_ISSET(fileno(stdin),&fds))
3373 /* We deliberately use receive_smb instead of
3374 client_receive_smb as we want to receive
3375 session keepalives and then drop them here.
3377 if (FD_ISSET(Client,&fds))
3378 receive_smb(Client,buffer,0);
3380 chkpath("\\",False);
3385 /****************************************************************************
3386 process commands from the client
3387 ****************************************************************************/
3388 static BOOL process(char *base_directory)
3393 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3394 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3396 if ((InBuffer == NULL) || (OutBuffer == NULL))
3399 bzero(OutBuffer,smb_size);
3401 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3404 if (*base_directory) do_cd(base_directory);
3407 if (cmd[0] != '\0') while (cmd[0] != '\0')
3413 if ((p = strchr(cmd, ';')) == 0)
3415 strncpy(line, cmd, 999);
3421 if (p - cmd > 999) p = cmd + 999;
3422 strncpy(line, cmd, p - cmd);
3423 line[p - cmd] = '\0';
3427 /* input language code to internal one */
3430 /* and get the first part of the command */
3433 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
3436 if ((i = process_tok(tok)) >= 0)
3437 commands[i].fn(InBuffer,OutBuffer);
3439 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3441 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3443 else while (!feof(stdin))
3448 bzero(OutBuffer,smb_size);
3450 /* display a prompt */
3451 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3454 wait_keyboard(InBuffer);
3456 /* and get a response */
3457 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,sizeof(tok))) 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)));
3484 cli_send_logout(InBuffer,OutBuffer);
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-R name resolve order use these name resolution services only\n"));
3508 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3509 DEBUG(0,("\t-U username set the network username\n"));
3510 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3511 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3512 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3513 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
3514 DEBUG(0,("\t-D directory start from directory\n"));
3518 /****************************************************************************
3520 ****************************************************************************/
3521 int main(int argc,char *argv[])
3523 fstring base_directory;
3524 char *pname = argv[0];
3525 int port = SMB_PORT;
3528 extern char *optarg;
3531 BOOL message = False;
3532 BOOL nt_domain_logon = False;
3533 BOOL explicit_user = False;
3534 extern char tar_type;
3535 static pstring servicesf = CONFIGFILE;
3537 pstring new_name_resolve_order;
3541 pstrcpy(term_code, KANJI);
3547 *base_directory = 0;
3549 *new_name_resolve_order = 0;
3553 setup_logging(pname,True);
3556 charset_initialise();
3558 if(!get_myname(myhostname,NULL))
3560 DEBUG(0,("Failed to get my hostname.\n"));
3563 if (!lp_load(servicesf,True,False,False)) {
3564 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3567 codepage_initialise(lp_client_code_page());
3569 interpret_coding_system(term_code);
3575 pstrcpy(workgroup,lp_workgroup());
3587 pstrcpy(username,getenv("USER"));
3589 /* modification to support userid%passwd syntax in the USER var
3590 25.Aug.97, jdblair@uab.edu */
3592 if ((p=strchr(username,'%')))
3595 pstrcpy(password,p+1);
3597 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3602 /* modification to support PASSWD environmental var
3603 25.Aug.97, jdblair@uab.edu */
3605 if (getenv("PASSWD")) {
3606 pstrcpy(password,getenv("PASSWD"));
3610 if (*username == 0 && getenv("LOGNAME"))
3612 pstrcpy(username,getenv("LOGNAME"));
3622 if (*argv[1] != '-')
3625 pstrcpy(service,argv[1]);
3626 /* Convert any '/' characters in the service name to '\' characters */
3627 string_replace( service, '/','\\');
3631 if (count_chars(service,'\\') < 3)
3634 printf("\n%s: Not enough '\\' characters in service\n",service);
3639 if (count_chars(service,'\\') > 3)
3642 printf("\n%s: Too many '\\' characters in service\n",service);
3647 if (argc > 1 && (*argv[1] != '-'))
3650 pstrcpy(password,argv[1]);
3651 memset(argv[1],'X',strlen(argv[1]));
3658 getopt(argc, argv,"s:B:O:R:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
3662 max_protocol = interpret_protocol(optarg,max_protocol);
3665 pstrcpy(user_socket_options,optarg);
3668 pstrcpy(new_name_resolve_order, optarg);
3671 pstrcpy(desthost,optarg);
3673 nt_domain_logon = True;
3676 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3677 pstrcpy(desthost,optarg);
3682 iface_set_default(NULL,optarg,NULL);
3685 pstrcpy(base_directory,optarg);
3688 if (!tar_parseargs(argc, argv, optarg, optind)) {
3694 pstrcpy(scope,optarg);
3698 pstrcpy(query_host,optarg);
3705 explicit_user = True;
3706 pstrcpy(username,optarg);
3707 if ((lp=strchr(username,'%')))
3710 pstrcpy(password,lp+1);
3712 memset(strchr(optarg,'%')+1,'X',strlen(password));
3718 pstrcpy(workgroup,optarg);
3725 dest_ip = *interpret_addr2(optarg);
3726 if (zero_ip(dest_ip)) exit(1);
3731 pstrcpy(global_myname,optarg);
3738 connect_as_printer = True;
3744 DEBUGLEVEL = atoi(optarg);
3747 slprintf(debugf,sizeof(debugf)-1, "%s.client",optarg);
3750 port = atoi(optarg);
3761 pstrcpy(servicesf, optarg);
3764 pstrcpy(term_code, optarg);
3771 get_myname((*global_myname)?NULL:global_myname,NULL);
3772 strupper(global_myname);
3774 if(*new_name_resolve_order)
3775 lp_set_name_resolve_order(new_name_resolve_order);
3777 if (!tar_type && !*query_host && !*service && !message)
3784 DEBUG( 3, ( "Client started (version %s).\n", VERSION ) );
3789 if (cli_open_sockets(port)) {
3790 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3791 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3794 if ((InBuffer == NULL) || (OutBuffer == NULL))
3797 bzero(OutBuffer,smb_size);
3798 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3801 if (*base_directory) do_cd(base_directory);
3803 ret=process_tar(InBuffer, OutBuffer);
3805 cli_send_logout(InBuffer, OutBuffer);
3812 if (*query_host && !nt_domain_logon)
3815 slprintf(service,sizeof(service)-1,
3816 "\\\\%s\\IPC$",query_host);
3818 connect_as_ipc = True;
3819 if (cli_open_sockets(port))
3824 if (!cli_send_login(NULL,NULL,True,True,NULL))
3828 if (!browse_host(True)) {
3832 if (!list_servers(workgroup)) {
3834 list_servers(workgroup);
3837 cli_send_logout(NULL,NULL);
3847 if (cli_open_sockets(port))
3849 pstring inbuf,outbuf;
3850 bzero(outbuf,smb_size);
3851 if (!cli_send_session_request(inbuf,outbuf))
3854 send_message(inbuf,outbuf);
3862 if (cli_open_sockets(port))
3864 if (!process(base_directory))