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 extern BOOL in_client;
31 pstring cur_dir = "\\";
33 extern pstring service;
34 extern pstring desthost;
35 extern pstring global_myname;
36 extern pstring myhostname;
37 extern pstring password;
38 extern pstring username;
39 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 static int process_tok(fstring tok);
52 static void cmd_help(char *dum_in, char *dum_out);
54 /* 30 second timeout on most commands */
55 #define CLIENT_TIMEOUT (30*1000)
56 #define SHORT_TIMEOUT (5*1000)
58 /* value for unused fid field in trans2 secondary request */
59 #define FID_UNUSED (0xFFFF)
63 extern int max_protocol;
66 time_t newer_than = 0;
67 int archive_level = 0;
69 extern pstring debugf;
70 extern int DEBUGLEVEL;
72 BOOL translation = False;
82 static int interpret_long_filename(int level,char *p,file_info *finfo);
83 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo);
84 static int interpret_short_filename(char *p,file_info *finfo);
85 static BOOL do_this_one(file_info *finfo);
87 /* clitar bits insert */
90 extern BOOL tar_reset;
94 mode_t myumask = 0755;
102 BOOL recurse = False;
103 BOOL lowercase = False;
105 struct in_addr dest_ip;
107 #define SEPARATORS " \t\n\r"
109 BOOL abort_mget = True;
113 extern BOOL readbraw_supported ;
114 extern BOOL writebraw_supported;
116 pstring fileselection = "";
118 extern file_info def_finfo;
121 int get_total_size = 0;
122 int get_total_time_ms = 0;
123 int put_total_size = 0;
124 int put_total_time_ms = 0;
133 #define CNV_LANG(s) dos_to_unix(s,False)
134 #define CNV_INPUT(s) unix_to_dos(s,True)
136 /****************************************************************************
137 send an SMBclose on an SMB file handle
138 ****************************************************************************/
139 static void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
141 bzero(outbuf,smb_size);
142 set_message(outbuf,3,0,True);
144 CVAL (outbuf,smb_com) = SMBclose;
145 SSVAL(outbuf,smb_tid,c_num);
146 cli_setup_pkt(outbuf);
147 SSVAL (outbuf,smb_vwv0, f_num);
148 SIVALS(outbuf,smb_vwv1, -1);
150 send_smb(clnt_fd, outbuf);
151 client_receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
155 /****************************************************************************
156 write to a local file with CR/LF->LF translation if appropriate. return the
157 number taken from the buffer. This may not equal the number written.
158 ****************************************************************************/
159 static int writefile(int f, char *b, int n)
164 return(write(f,b,n));
169 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
173 if (write(f, b, 1) != 1)
184 /****************************************************************************
185 read from a file with LF->CR/LF translation if appropriate. return the
186 number read. read approx n bytes.
187 ****************************************************************************/
188 static int readfile(char *b, int size, int n, FILE *f)
193 if (!translation || (size != 1))
194 return(fread(b,size,n,f));
199 if ((c = getc(f)) == EOF)
204 if (c == '\n') /* change all LFs to CR/LF */
218 /****************************************************************************
219 read from a file with print translation. return the number read. read approx n
221 ****************************************************************************/
222 static int printread(FILE *f,char *b,int n)
226 i = readfile(b,1, n-1,f);
235 /****************************************************************************
236 check for existance of a dir
237 ****************************************************************************/
238 static BOOL chkpath(char *path,BOOL report)
241 pstring inbuf,outbuf;
245 trim_string(path2,NULL,"\\");
246 if (!*path2) *path2 = '\\';
248 bzero(outbuf,smb_size);
249 set_message(outbuf,0,4 + strlen(path2),True);
250 SCVAL(outbuf,smb_com,SMBchkpth);
251 SSVAL(outbuf,smb_tid,cnum);
252 cli_setup_pkt(outbuf);
260 /* this little bit of code can be used to extract NT error codes.
261 Just feed a bunch of "cd foo" commands to smbclient then watch
262 in netmon (tridge) */
264 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
265 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
270 send_smb(Client,outbuf);
271 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
273 if (report && CVAL(inbuf,smb_rcls) != 0)
274 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
276 return(CVAL(inbuf,smb_rcls) == 0);
280 /****************************************************************************
282 ****************************************************************************/
283 static void send_message(char *inbuf,char *outbuf)
290 /* send a SMBsendstrt command */
291 bzero(outbuf,smb_size);
292 set_message(outbuf,0,0,True);
293 CVAL(outbuf,smb_com) = SMBsendstrt;
294 SSVAL(outbuf,smb_tid,cnum);
299 p = skip_string(p,1);
302 p = skip_string(p,1);
304 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
306 send_smb(Client,outbuf);
309 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
311 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
315 grp_id = SVAL(inbuf,smb_vwv0);
317 printf("Connected. Type your message, ending it with a Control-D\n");
319 while (!feof(stdin) && total_len < 1600)
321 int maxlen = MIN(1600 - total_len,127);
328 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
335 CVAL(outbuf,smb_com) = SMBsendtxt;
337 set_message(outbuf,1,l+3,True);
339 SSVAL(outbuf,smb_vwv0,grp_id);
346 send_smb(Client,outbuf);
349 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
351 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
358 if (total_len >= 1600)
359 printf("the message was truncated to 1600 bytes ");
361 printf("sent %d bytes ",total_len);
363 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
365 CVAL(outbuf,smb_com) = SMBsendend;
366 set_message(outbuf,1,0,False);
367 SSVAL(outbuf,smb_vwv0,grp_id);
369 send_smb(Client,outbuf);
372 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
374 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
381 /****************************************************************************
382 check the space on a device
383 ****************************************************************************/
384 static void do_dskattr(void)
386 pstring inbuf,outbuf;
388 bzero(outbuf,smb_size);
389 set_message(outbuf,0,0,True);
390 CVAL(outbuf,smb_com) = SMBdskattr;
391 SSVAL(outbuf,smb_tid,cnum);
392 cli_setup_pkt(outbuf);
394 send_smb(Client,outbuf);
395 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
397 if (CVAL(inbuf,smb_rcls) != 0)
398 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
400 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
401 SVAL(inbuf,smb_vwv0),
402 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
403 SVAL(inbuf,smb_vwv3)));
406 /****************************************************************************
408 ****************************************************************************/
409 static void cmd_pwd(char *dum_in, char *dum_out)
411 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
412 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
416 /****************************************************************************
417 change directory - inner section
418 ****************************************************************************/
419 static void do_cd(char *newdir)
427 /* Save the current directory in case the
428 new directory is invalid */
429 pstrcpy(saved_dir, cur_dir);
434 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
435 pstrcat(cur_dir, "\\");
437 dos_clean_name(cur_dir);
438 pstrcpy(dname,cur_dir);
439 pstrcat(cur_dir,"\\");
440 dos_clean_name(cur_dir);
442 if (!strequal(cur_dir,"\\"))
443 if (!chkpath(dname,True))
444 pstrcpy(cur_dir,saved_dir);
446 pstrcpy(cd_path,cur_dir);
449 /****************************************************************************
451 ****************************************************************************/
452 static void cmd_cd(char *inbuf,char *outbuf)
456 if (next_token(NULL,buf,NULL,sizeof(buf)))
459 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
463 /****************************************************************************
464 display info about a file
465 ****************************************************************************/
466 static void display_finfo(file_info *finfo)
468 if (do_this_one(finfo)) {
469 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
470 DEBUG(0,(" %-30s%7.7s%.0f %s",
471 CNV_LANG(finfo->name),
472 attrib_string(finfo->mode),
474 asctime(LocalTime(&t))));
475 dir_total += finfo->size;
480 /****************************************************************************
481 calculate size of a file
482 ****************************************************************************/
483 static void do_du(file_info *finfo)
485 if (do_this_one(finfo)) {
486 dir_total += finfo->size;
491 /****************************************************************************
492 do a directory listing, calling fn on each file found. Use the TRANSACT2
493 call for long filenames
494 ****************************************************************************/
495 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
497 int max_matches = 512;
498 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
503 char *dirlist = NULL;
505 int total_received = 0;
507 char *resp_data=NULL;
508 char *resp_param=NULL;
509 int resp_data_len = 0;
510 int resp_param_len=0;
512 int ff_resume_key = 0;
513 int ff_searchcount=0;
527 if (loop_count > 200)
529 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
535 setup = TRANSACT2_FINDFIRST;
536 SSVAL(param,0,attribute); /* attribute */
537 SSVAL(param,2,max_matches); /* max count */
538 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
539 SSVAL(param,6,info_level);
541 pstrcpy(param+12,mask);
545 setup = TRANSACT2_FINDNEXT;
546 SSVAL(param,0,ff_dir_handle);
547 SSVAL(param,2,max_matches); /* max count */
548 SSVAL(param,4,info_level);
549 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
550 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
551 pstrcpy(param+12,mask);
553 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
554 ff_dir_handle,ff_resume_key,ff_lastname,mask));
556 /* ??? original code added 1 pad byte after param */
558 cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
560 0,12+strlen(mask)+1,1,
563 if (!cli_receive_trans_response(inbuf,SMBtrans2,
564 &resp_data_len,&resp_param_len,
565 &resp_data,&resp_param))
567 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
571 /* parse out some important return info */
575 ff_dir_handle = SVAL(p,0);
576 ff_searchcount = SVAL(p,2);
578 ff_lastname = SVAL(p,8);
582 ff_searchcount = SVAL(p,0);
584 ff_lastname = SVAL(p,6);
587 if (ff_searchcount == 0)
590 /* point to the data bytes */
593 /* we might need the lastname for continuations */
600 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
601 /* pstrcpy(mask,p+ff_lastname+94); */
604 pstrcpy(mask,p + ff_lastname + 1);
612 /* and add them to the dirlist pool */
613 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
617 DEBUG(0,("Failed to expand dirlist\n"));
621 /* put in a length for the last entry, to ensure we can chain entries
622 into the next packet */
625 for (p2=p,i=0;i<(ff_searchcount-1);i++)
626 p2 += interpret_long_filename(info_level,p2,NULL);
627 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
630 /* grab the data for later use */
631 memcpy(dirlist+dirlist_len,p,resp_data_len);
632 dirlist_len += resp_data_len;
634 total_received += ff_searchcount;
636 if (resp_data) free(resp_data); resp_data = NULL;
637 if (resp_param) free(resp_param); resp_param = NULL;
639 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
640 ff_searchcount,ff_eos,ff_resume_key));
646 for (p=dirlist,i=0;i<total_received;i++)
648 p += interpret_long_filename(info_level,p,&finfo);
649 display_finfo(&finfo);
652 for (p=dirlist,i=0;i<total_received;i++)
654 p += interpret_long_filename(info_level,p,&finfo);
655 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True, dirstoo);
658 /* free up the dirlist buffer */
659 if (dirlist) free(dirlist);
660 return(total_received);
664 /****************************************************************************
665 do a directory listing, calling fn on each file found
666 ****************************************************************************/
667 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
673 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
674 int num_received = 0;
676 char *dirlist = NULL;
688 bzero(outbuf,smb_size);
690 set_message(outbuf,2,5 + strlen(mask),True);
692 set_message(outbuf,2,5 + 21,True);
695 if (Protocol >= PROTOCOL_LANMAN1)
696 CVAL(outbuf,smb_com) = SMBffirst;
699 CVAL(outbuf,smb_com) = SMBsearch;
701 SSVAL(outbuf,smb_tid,cnum);
702 cli_setup_pkt(outbuf);
704 SSVAL(outbuf,smb_vwv0,num_asked);
705 SSVAL(outbuf,smb_vwv1,attribute);
726 send_smb(Client,outbuf);
727 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
729 received = SVAL(inbuf,smb_vwv0);
731 DEBUG(5,("dir received %d\n",received));
733 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
735 if (received <= 0) break;
739 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
744 p = smb_buf(inbuf) + 3;
746 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
747 p,received*DIR_STRUCT_SIZE);
749 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
751 num_received += received;
753 if (CVAL(inbuf,smb_rcls) != 0) break;
757 if (!first && Protocol >= PROTOCOL_LANMAN1)
759 bzero(outbuf,smb_size);
760 CVAL(outbuf,smb_com) = SMBfclose;
762 SSVAL(outbuf,smb_tid,cnum);
763 cli_setup_pkt(outbuf);
776 send_smb(Client,outbuf);
777 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
779 if (CVAL(inbuf,smb_rcls) != 0)
780 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
785 for (p=dirlist,i=0;i<num_received;i++)
787 p += interpret_short_filename(p,&finfo);
788 display_finfo(&finfo);
791 for (p=dirlist,i=0;i<num_received;i++)
793 p += interpret_short_filename(p,&finfo);
794 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False,dirstoo);
797 if (dirlist) free(dirlist);
798 return(num_received);
803 /****************************************************************************
804 do a directory listing, calling fn on each file found
805 ****************************************************************************/
806 void do_dir(char *inbuf,char *outbuf,char *mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
809 DEBUG(5,("do_dir(%s,%x,%s)\n",mask,attribute,BOOLSTR(recurse_dir)));
810 if (Protocol >= PROTOCOL_LANMAN2)
812 if (do_long_dir(inbuf,outbuf,mask,attribute,fn,recurse_dir,dirstoo) > 0)
816 expand_mask(mask,False);
817 do_short_dir(inbuf,outbuf,mask,attribute,fn,recurse_dir,dirstoo);
821 /*******************************************************************
822 decide if a file should be operated on
823 ********************************************************************/
824 static BOOL do_this_one(file_info *finfo)
826 if (finfo->mode & aDIR) return(True);
828 if (newer_than && finfo->mtime < newer_than)
831 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
838 /*****************************************************************************
839 Convert a character pointer in a cli_call_api() response to a form we can use.
840 This function contains code to prevent core dumps if the server returns
842 *****************************************************************************/
843 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
845 if( datap == 0 ) /* turn NULL pointers */
846 { /* into zero length strings */
851 unsigned int offset = datap - converter;
853 if( offset >= rdrcnt )
855 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
860 return &rdata[offset];
865 /****************************************************************************
866 interpret a short filename structure
867 The length of the structure is returned
868 ****************************************************************************/
869 static int interpret_short_filename(char *p,file_info *finfo)
871 finfo->mode = CVAL(p,21);
873 /* this date is converted to GMT by make_unix_date */
874 finfo->ctime = make_unix_date(p+22);
875 finfo->mtime = finfo->atime = finfo->ctime;
876 finfo->size = IVAL(p,26);
877 pstrcpy(finfo->name,p+30);
879 return(DIR_STRUCT_SIZE);
882 /****************************************************************************
883 interpret a long filename structure - this is mostly guesses at the moment
884 The length of the structure is returned
885 The structure of a long filename depends on the info level. 260 is used
886 by NT and 2 is used by OS/2
887 ****************************************************************************/
888 static int interpret_long_filename(int level,char *p,file_info *finfo)
891 memcpy(finfo,&def_finfo,sizeof(*finfo));
895 case 1: /* OS/2 understands this */
898 /* these dates are converted to GMT by make_unix_date */
899 finfo->ctime = make_unix_date2(p+4);
900 finfo->atime = make_unix_date2(p+8);
901 finfo->mtime = make_unix_date2(p+12);
902 finfo->size = IVAL(p,16);
903 finfo->mode = CVAL(p,24);
904 pstrcpy(finfo->name,p+27);
906 return(28 + CVAL(p,26));
908 case 2: /* this is what OS/2 uses mostly */
911 /* these dates are converted to GMT by make_unix_date */
912 finfo->ctime = make_unix_date2(p+4);
913 finfo->atime = make_unix_date2(p+8);
914 finfo->mtime = make_unix_date2(p+12);
915 finfo->size = IVAL(p,16);
916 finfo->mode = CVAL(p,24);
917 pstrcpy(finfo->name,p+31);
919 return(32 + CVAL(p,30));
921 /* levels 3 and 4 are untested */
925 /* these dates are probably like the other ones */
926 finfo->ctime = make_unix_date2(p+8);
927 finfo->atime = make_unix_date2(p+12);
928 finfo->mtime = make_unix_date2(p+16);
929 finfo->size = IVAL(p,20);
930 finfo->mode = CVAL(p,28);
931 pstrcpy(finfo->name,p+33);
938 /* these dates are probably like the other ones */
939 finfo->ctime = make_unix_date2(p+8);
940 finfo->atime = make_unix_date2(p+12);
941 finfo->mtime = make_unix_date2(p+16);
942 finfo->size = IVAL(p,20);
943 finfo->mode = CVAL(p,28);
944 pstrcpy(finfo->name,p+37);
948 case 260: /* NT uses this, but also accepts 2 */
953 p += 4; /* next entry offset */
954 p += 4; /* fileindex */
956 /* these dates appear to arrive in a weird way. It seems to
957 be localtime plus the serverzone given in the initial
958 connect. This is GMT when DST is not in effect and one
959 hour from GMT otherwise. Can this really be right??
961 I suppose this could be called kludge-GMT. Is is the GMT
962 you get by using the current DST setting on a different
963 localtime. It will be cheap to calculate, I suppose, as
964 no DST tables will be needed */
966 finfo->ctime = interpret_long_date(p); p += 8;
967 finfo->atime = interpret_long_date(p); p += 8;
968 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
969 finfo->size = IVAL(p,0); p += 8;
970 p += 8; /* alloc size */
971 finfo->mode = CVAL(p,0); p += 4;
972 namelen = IVAL(p,0); p += 4;
973 p += 4; /* EA size */
974 p += 2; /* short name len? */
975 p += 24; /* short name? */
976 StrnCpy(finfo->name,p,namelen);
982 DEBUG(1,("Unknown long filename format %d\n",level));
989 /****************************************************************************
990 act on the files in a dir listing
992 RJS, 4-Apr-1998, dirstoo added to allow caller to indicate that directories
993 should be processed as well.
994 ****************************************************************************/
995 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo)
998 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
999 !mask_match(finfo->name,fileselection,False,False)) &&
1000 !(recurse_dir && (strequal(finfo->name,".") ||
1001 strequal(finfo->name,".."))))
1003 if (recurse_dir && (finfo->mode & aDIR))
1008 if (fn && dirstoo && do_this_one(finfo)) { /* Do dirs, RJS */
1012 pstrcpy(sav_dir,cur_dir);
1013 pstrcat(cur_dir,finfo->name);
1014 pstrcat(cur_dir,"\\");
1015 pstrcpy(mask2,cur_dir);
1018 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1023 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1025 do_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1027 pstrcpy(cur_dir,sav_dir);
1031 if (fn && do_this_one(finfo))
1038 /****************************************************************************
1039 get a directory listing
1040 ****************************************************************************/
1041 static void cmd_dir(char *inbuf,char *outbuf)
1043 int attribute = aDIR | aSYSTEM | aHIDDEN;
1049 pstrcpy(mask,cur_dir);
1050 if(mask[strlen(mask)-1]!='\\')
1053 if (next_token(NULL,buf,NULL,sizeof(buf))) {
1064 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse,False);
1068 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1072 /****************************************************************************
1073 get a directory listing
1074 ****************************************************************************/
1075 static void cmd_du(char *inbuf,char *outbuf)
1077 int attribute = aDIR | aSYSTEM | aHIDDEN;
1083 pstrcpy(mask,cur_dir);
1084 if(mask[strlen(mask)-1]!='\\')
1087 if (next_token(NULL,buf,NULL,sizeof(buf)))
1099 do_dir(inbuf,outbuf,mask,attribute,do_du,recurse,False);
1103 DEBUG(0, ("Total number of bytes: %d\n", dir_total));
1106 /****************************************************************************
1107 get a file from rname to lname
1108 ****************************************************************************/
1109 static void do_get(char *rname,char *lname,file_info *finfo1)
1114 BOOL newhandle = False;
1115 char *inbuf,*outbuf;
1117 BOOL close_done = False;
1118 BOOL ignore_close_error = False;
1122 struct timeval tp_start;
1123 GetTimeOfDay(&tp_start);
1134 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1135 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1137 if (!inbuf || !outbuf)
1139 DEBUG(0,("out of memory\n"));
1143 bzero(outbuf,smb_size);
1144 set_message(outbuf,15,1 + strlen(rname),True);
1146 CVAL(outbuf,smb_com) = SMBopenX;
1147 SSVAL(outbuf,smb_tid,cnum);
1148 cli_setup_pkt(outbuf);
1150 SSVAL(outbuf,smb_vwv0,0xFF);
1151 SSVAL(outbuf,smb_vwv2,1); /* return additional info */
1152 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1153 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1154 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1155 SSVAL(outbuf,smb_vwv8,1);
1156 SSVAL(outbuf,smb_vwv11,0xffff);
1157 SSVAL(outbuf,smb_vwv12,0xffff);
1159 p = smb_buf(outbuf);
1161 p = skip_string(p,1);
1163 /* do a chained openX with a readX? */
1167 DEBUG(3,("Chaining readX wth openX\n"));
1168 SSVAL(outbuf,smb_vwv0,SMBreadX);
1169 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1172 SCVAL(p,smb_wct,10);
1173 SSVAL(p,smb_vwv0,0xFF);
1174 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1175 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1176 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1180 if(!strcmp(lname,"-"))
1181 handle = fileno(stdout);
1184 handle = creat(lname,0644);
1189 DEBUG(0,("Error opening local file %s\n",lname));
1190 free(inbuf);free(outbuf);
1194 send_smb(Client,outbuf);
1195 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1197 if (CVAL(inbuf,smb_rcls) != 0)
1199 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1200 SVAL(inbuf,smb_err) == ERRnoresource &&
1201 cli_reopen_connection(inbuf,outbuf))
1203 do_get(rname,lname,finfo1);
1206 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1212 free(inbuf);free(outbuf);
1216 pstrcpy(finfo.name,rname);
1220 finfo.mode = SVAL(inbuf,smb_vwv3);
1221 /* these times arrive as LOCAL time, using the DST offset
1222 corresponding to that time, we convert them to GMT */
1223 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1224 finfo.atime = finfo.ctime = finfo.mtime;
1225 finfo.size = IVAL(inbuf,smb_vwv6);
1228 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1230 fnum = SVAL(inbuf,smb_vwv2);
1232 /* we might have got some data from a chained readX */
1233 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1235 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1236 datalen = SVAL(p,smb_vwv5);
1237 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1246 DEBUG(2,("getting file %s of size %.0f bytes as %s ",
1247 CNV_LANG(finfo.name),
1251 while (nread < finfo.size && !close_done)
1254 static BOOL can_chain_close = True;
1258 DEBUG(3,("nread=%d max_xmit=%d fsize=%.0f\n",nread,max_xmit,(double)finfo.size));
1260 /* 3 possible read types. readbraw if a large block is required.
1261 readX + close if not much left and read if neither is supported */
1263 /* we might have already read some data from a chained readX */
1264 if (dataptr && datalen>0)
1267 /* if we can finish now then readX+close */
1268 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1269 ((finfo.size - nread) <
1270 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1273 /* if we support readraw then use that */
1274 if (method<0 && readbraw_supported)
1277 /* if we can then use readX */
1278 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1289 /* use readX + close */
1290 bzero(outbuf,smb_size);
1291 set_message(outbuf,10,0,True);
1292 CVAL(outbuf,smb_com) = SMBreadX;
1293 SSVAL(outbuf,smb_tid,cnum);
1294 cli_setup_pkt(outbuf);
1298 CVAL(outbuf,smb_vwv0) = SMBclose;
1299 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1302 CVAL(outbuf,smb_vwv0) = 0xFF;
1304 SSVAL(outbuf,smb_vwv2,fnum);
1305 SIVAL(outbuf,smb_vwv3,nread);
1306 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1307 SSVAL(outbuf,smb_vwv6,0);
1308 SIVAL(outbuf,smb_vwv7,0);
1309 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1313 p = smb_buf(outbuf);
1320 /* now set the total packet length */
1321 smb_setlen(outbuf,smb_len(outbuf)+9);
1324 send_smb(Client,outbuf);
1325 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1327 if (CVAL(inbuf,smb_rcls) != 0)
1329 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1334 SVAL(inbuf,smb_vwv0) != SMBclose)
1336 /* NOTE: WfWg sometimes just ignores the chained
1337 command! This seems to break the spec? */
1338 DEBUG(3,("Rejected chained close?\n"));
1340 can_chain_close = False;
1341 ignore_close_error = True;
1344 datalen = SVAL(inbuf,smb_vwv5);
1345 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1351 static int readbraw_size = BUFFER_SIZE;
1354 bzero(outbuf,smb_size);
1355 set_message(outbuf,8,0,True);
1356 CVAL(outbuf,smb_com) = SMBreadbraw;
1357 SSVAL(outbuf,smb_tid,cnum);
1358 cli_setup_pkt(outbuf);
1359 SSVAL(outbuf,smb_vwv0,fnum);
1360 SIVAL(outbuf,smb_vwv1,nread);
1361 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1362 SSVAL(outbuf,smb_vwv4,0);
1363 SIVALS(outbuf,smb_vwv5,-1);
1364 send_smb(Client,outbuf);
1366 /* Now read the raw data into the buffer and write it */
1367 if(read_smb_length(Client,inbuf,0) == -1) {
1368 DEBUG(0,("Failed to read length in readbraw\n"));
1372 /* Even though this is not an smb message, smb_len
1373 returns the generic length of an smb message */
1374 datalen = smb_len(inbuf);
1378 /* we got a readbraw error */
1379 DEBUG(4,("readbraw error - reducing size\n"));
1380 readbraw_size = (readbraw_size * 9) / 10;
1382 if (readbraw_size < max_xmit)
1384 DEBUG(0,("disabling readbraw\n"));
1385 readbraw_supported = False;
1392 if(read_data(Client,inbuf,datalen) != datalen) {
1393 DEBUG(0,("Failed to read data in readbraw\n"));
1401 /* we've already read some data with a chained readX */
1405 /* use plain read */
1406 bzero(outbuf,smb_size);
1407 set_message(outbuf,5,0,True);
1408 CVAL(outbuf,smb_com) = SMBread;
1409 SSVAL(outbuf,smb_tid,cnum);
1410 cli_setup_pkt(outbuf);
1412 SSVAL(outbuf,smb_vwv0,fnum);
1413 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1414 SIVAL(outbuf,smb_vwv2,nread);
1415 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1417 send_smb(Client,outbuf);
1418 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1420 if (CVAL(inbuf,smb_rcls) != 0)
1422 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1426 datalen = SVAL(inbuf,smb_vwv0);
1427 dataptr = smb_buf(inbuf) + 3;
1431 if (writefile(handle,dataptr,datalen) != datalen)
1433 DEBUG(0,("Error writing local file\n"));
1440 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1452 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1454 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1456 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1459 free(inbuf);free(outbuf);
1467 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1468 bzero(outbuf,smb_size);
1469 set_message(outbuf,8,strlen(rname)+4,True);
1470 CVAL(outbuf,smb_com) = SMBsetatr;
1471 SSVAL(outbuf,smb_tid,cnum);
1472 cli_setup_pkt(outbuf);
1473 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1474 SIVALS(outbuf,smb_vwv1,0);
1475 p = smb_buf(outbuf);
1481 send_smb(Client,outbuf);
1482 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1486 struct timeval tp_end;
1489 GetTimeOfDay(&tp_end);
1491 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1492 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1493 get_total_time_ms += this_time;
1494 get_total_size += finfo.size;
1496 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1497 finfo.size / (1.024*this_time + 1.0e-4),
1498 get_total_size / (1.024*get_total_time_ms)));
1501 free(inbuf);free(outbuf);
1505 /****************************************************************************
1507 ****************************************************************************/
1508 static void cmd_get(char *dum_in, char *dum_out)
1514 pstrcpy(rname,cur_dir);
1515 pstrcat(rname,"\\");
1517 p = rname + strlen(rname);
1519 if (!next_token(NULL,p,NULL,sizeof(rname)-strlen(rname))) {
1520 DEBUG(0,("get <filename>\n"));
1524 dos_clean_name(rname);
1526 next_token(NULL,lname,NULL,sizeof(lname));
1528 do_get(rname,lname,NULL);
1532 /****************************************************************************
1533 do a mget operation on one file
1534 ****************************************************************************/
1535 static void do_mget(file_info *finfo)
1540 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1545 DEBUG(0,("mget aborted\n"));
1549 if (finfo->mode & aDIR)
1550 slprintf(quest,sizeof(pstring)-1,
1551 "Get directory %s? ",CNV_LANG(finfo->name));
1553 slprintf(quest,sizeof(pstring)-1,
1554 "Get file %s? ",CNV_LANG(finfo->name));
1556 if (prompt && !yesno(quest)) return;
1558 if (finfo->mode & aDIR)
1560 pstring saved_curdir;
1562 char *inbuf,*outbuf;
1564 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1565 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1567 if (!inbuf || !outbuf)
1569 DEBUG(0,("out of memory\n"));
1573 pstrcpy(saved_curdir,cur_dir);
1575 pstrcat(cur_dir,finfo->name);
1576 pstrcat(cur_dir,"\\");
1578 unix_format(finfo->name);
1581 strlower(finfo->name);
1583 if (!directory_exist(finfo->name,NULL) &&
1584 dos_mkdir(finfo->name,0777) != 0)
1586 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1587 pstrcpy(cur_dir,saved_curdir);
1588 free(inbuf);free(outbuf);
1592 if (dos_chdir(finfo->name) != 0)
1594 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1595 pstrcpy(cur_dir,saved_curdir);
1596 free(inbuf);free(outbuf);
1601 pstrcpy(mget_mask,cur_dir);
1602 pstrcat(mget_mask,"*");
1604 do_dir((char *)inbuf,(char *)outbuf,
1605 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False, False);
1607 pstrcpy(cur_dir,saved_curdir);
1608 free(inbuf);free(outbuf);
1612 pstrcpy(rname,cur_dir);
1613 pstrcat(rname,finfo->name);
1614 do_get(rname,finfo->name,finfo);
1618 /****************************************************************************
1619 view the file using the pager
1620 ****************************************************************************/
1621 static void cmd_more(char *dum_in, char *dum_out)
1623 fstring rname,lname,tmpname,pager_cmd;
1626 fstrcpy(rname,cur_dir);
1627 fstrcat(rname,"\\");
1630 "%s/smbmore.%d",tmpdir(),(int)getpid());
1631 fstrcpy(lname,tmpname);
1633 if (!next_token(NULL,rname+strlen(rname),NULL,sizeof(rname)-strlen(rname))) {
1634 DEBUG(0,("more <filename>\n"));
1637 dos_clean_name(rname);
1639 do_get(rname,lname,NULL);
1641 pager=getenv("PAGER");
1643 slprintf(pager_cmd,sizeof(pager_cmd)-1,
1644 "%s %s",(pager? pager:PAGER), tmpname);
1651 /****************************************************************************
1653 ****************************************************************************/
1654 static void cmd_mget(char *inbuf,char *outbuf)
1656 int attribute = aSYSTEM | aHIDDEN;
1668 while (next_token(NULL,p,NULL,sizeof(buf)))
1670 pstrcpy(mget_mask,cur_dir);
1671 if(mget_mask[strlen(mget_mask)-1]!='\\')
1672 pstrcat(mget_mask,"\\");
1675 pstrcpy(mget_mask,p);
1677 pstrcat(mget_mask,p);
1678 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1683 pstrcpy(mget_mask,cur_dir);
1684 if(mget_mask[strlen(mget_mask)-1]!='\\')
1685 pstrcat(mget_mask,"\\");
1686 pstrcat(mget_mask,"*");
1687 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1691 /****************************************************************************
1692 make a directory of name "name"
1693 ****************************************************************************/
1694 static BOOL do_mkdir(char *name)
1697 char *inbuf,*outbuf;
1699 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1700 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1702 if (!inbuf || !outbuf)
1704 DEBUG(0,("out of memory\n"));
1708 bzero(outbuf,smb_size);
1709 set_message(outbuf,0,2 + strlen(name),True);
1711 CVAL(outbuf,smb_com) = SMBmkdir;
1712 SSVAL(outbuf,smb_tid,cnum);
1713 cli_setup_pkt(outbuf);
1716 p = smb_buf(outbuf);
1720 send_smb(Client,outbuf);
1721 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1723 if (CVAL(inbuf,smb_rcls) != 0)
1725 DEBUG(0,("%s making remote directory %s\n",
1726 smb_errstr(inbuf),CNV_LANG(name)));
1728 free(inbuf);free(outbuf);
1732 free(inbuf);free(outbuf);
1737 /****************************************************************************
1739 ****************************************************************************/
1740 static void cmd_mkdir(char *inbuf,char *outbuf)
1746 pstrcpy(mask,cur_dir);
1748 if (!next_token(NULL,p,NULL,sizeof(buf)))
1751 DEBUG(0,("mkdir <dirname>\n"));
1763 trim_string(ddir,".",NULL);
1764 p = strtok(ddir,"/\\");
1768 if (!chkpath(ddir2,False))
1772 pstrcat(ddir2,"\\");
1773 p = strtok(NULL,"/\\");
1781 /*******************************************************************
1782 write to a file using writebraw
1783 ********************************************************************/
1784 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1789 bzero(outbuf,smb_size);
1790 bzero(inbuf,smb_size);
1791 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1793 CVAL(outbuf,smb_com) = SMBwritebraw;
1794 SSVAL(outbuf,smb_tid,cnum);
1795 cli_setup_pkt(outbuf);
1797 SSVAL(outbuf,smb_vwv0,fnum);
1798 SSVAL(outbuf,smb_vwv1,n);
1799 SIVAL(outbuf,smb_vwv3,pos);
1800 SSVAL(outbuf,smb_vwv7,1);
1802 send_smb(Client,outbuf);
1804 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1807 _smb_setlen(buf-4,n); /* HACK! XXXX */
1809 if (write_socket(Client,buf-4,n+4) != n+4)
1812 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1813 DEBUG(0,("Error writing remote file (2)\n"));
1816 return(SVAL(inbuf,smb_vwv0));
1821 /*******************************************************************
1823 ********************************************************************/
1824 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1828 if (writebraw_supported && n > (max_xmit-200))
1829 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1831 bzero(outbuf,smb_size);
1832 bzero(inbuf,smb_size);
1833 set_message(outbuf,5,n + 3,True);
1835 CVAL(outbuf,smb_com) = SMBwrite;
1836 SSVAL(outbuf,smb_tid,cnum);
1837 cli_setup_pkt(outbuf);
1839 SSVAL(outbuf,smb_vwv0,fnum);
1840 SSVAL(outbuf,smb_vwv1,n);
1841 SIVAL(outbuf,smb_vwv2,pos);
1842 SSVAL(outbuf,smb_vwv4,0);
1843 CVAL(smb_buf(outbuf),0) = 1;
1844 SSVAL(smb_buf(outbuf),1,n);
1846 memcpy(smb_buf(outbuf)+3,buf,n);
1848 send_smb(Client,outbuf);
1849 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1851 if (CVAL(inbuf,smb_rcls) != 0) {
1852 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1855 return(SVAL(inbuf,smb_vwv0));
1860 /****************************************************************************
1862 ****************************************************************************/
1863 static void do_put(char *rname,char *lname,file_info *finfo)
1869 char *inbuf,*outbuf;
1870 time_t close_time = finfo->mtime;
1872 static int maxwrite=0;
1874 struct timeval tp_start;
1875 GetTimeOfDay(&tp_start);
1877 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1878 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1880 if (!inbuf || !outbuf)
1882 DEBUG(0,("out of memory\n"));
1886 bzero(outbuf,smb_size);
1887 set_message(outbuf,3,2 + strlen(rname),True);
1889 if (finfo->mtime == 0 || finfo->mtime == -1)
1890 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1892 CVAL(outbuf,smb_com) = SMBcreate;
1893 SSVAL(outbuf,smb_tid,cnum);
1894 cli_setup_pkt(outbuf);
1896 SSVAL(outbuf,smb_vwv0,finfo->mode);
1897 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1899 p = smb_buf(outbuf);
1903 send_smb(Client,outbuf);
1904 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1906 if (CVAL(inbuf,smb_rcls) != 0)
1908 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1910 free(inbuf);free(outbuf);if (buf) free(buf);
1914 /* allow files to be piped into smbclient
1915 jdblair 24.jun.98 */
1916 if (!strcmp(lname, "-")) {
1918 /* size of file is not known */
1921 f = fopen(lname,"r");
1926 DEBUG(0,("Error opening local file %s\n",lname));
1927 free(inbuf);free(outbuf);
1932 fnum = SVAL(inbuf,smb_vwv0);
1933 if (finfo->size < 0)
1934 finfo->size = file_size(lname);
1936 DEBUG(1,("putting file %s of size %.0f bytes as %s ",lname,(double)finfo->size,CNV_LANG(rname)));
1939 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1941 /* This is a rewrite of the read/write loop that doesn't require the input
1942 file to be of a known length. This allows the stream pointer 'f' to
1945 Rather than reallocing the read buffer every loop to keep it the min
1946 necessary length this look uses a fixed length buffer and just tests
1947 for eof on the file stream at the top of each loop.
1948 jdblair, 24.jun.98 */
1950 buf = (char *)malloc(maxwrite+4);
1956 if ((n = readfile(buf+4,1,n,f)) < 1)
1958 DEBUG(0,("Error reading local file\n"));
1962 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1966 DEBUG(0,("Error writing file\n"));
1969 fseek(f,nread,SEEK_SET);
1978 bzero(outbuf,smb_size);
1979 set_message(outbuf,3,0,True);
1980 CVAL(outbuf,smb_com) = SMBclose;
1981 SSVAL(outbuf,smb_tid,cnum);
1982 cli_setup_pkt(outbuf);
1984 SSVAL(outbuf,smb_vwv0,fnum);
1985 put_dos_date3(outbuf,smb_vwv1,close_time);
1987 send_smb(Client,outbuf);
1988 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1990 if (CVAL(inbuf,smb_rcls) != 0)
1992 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1994 free(inbuf);free(outbuf);
2001 free(inbuf);free(outbuf);
2005 struct timeval tp_end;
2008 GetTimeOfDay(&tp_end);
2010 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
2011 (tp_end.tv_usec - tp_start.tv_usec)/1000;
2012 put_total_time_ms += this_time;
2013 put_total_size += finfo->size;
2015 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
2016 finfo->size / (1.024*this_time + 1.0e-4),
2017 put_total_size / (1.024*put_total_time_ms)));
2023 /****************************************************************************
2025 ****************************************************************************/
2026 static void cmd_put(char *dum_in, char *dum_out)
2035 pstrcpy(rname,cur_dir);
2036 pstrcat(rname,"\\");
2039 if (!next_token(NULL,p,NULL,sizeof(buf)))
2041 DEBUG(0,("put <filename>\n"));
2046 if (next_token(NULL,p,NULL,sizeof(buf)))
2049 pstrcat(rname,lname);
2051 dos_clean_name(rname);
2055 /* allow '-' to represent stdin
2056 jdblair, 24.jun.98 */
2057 if (!file_exist(lname,&st) &&
2058 (strcmp(lname,"-"))) {
2059 DEBUG(0,("%s does not exist\n",lname));
2062 finfo.mtime = st.st_mtime;
2065 do_put(rname,lname,&finfo);
2068 /****************************************************************************
2069 seek in a directory/file list until you get something that doesn't start with
2071 ****************************************************************************/
2072 static BOOL seek_list(FILE *f,char *name)
2077 if (fscanf(f,"%s",s) != 1) return(False);
2078 trim_string(s,"./",NULL);
2079 if (strncmp(s,name,strlen(name)) != 0)
2090 /****************************************************************************
2091 set the file selection mask
2092 ****************************************************************************/
2093 static void cmd_select(char *dum_in, char *dum_out)
2095 pstrcpy(fileselection,"");
2096 next_token(NULL,fileselection,NULL,sizeof(fileselection));
2100 /****************************************************************************
2102 ****************************************************************************/
2103 static void cmd_mput(char *dum_in, char *dum_out)
2114 while (next_token(NULL,p,NULL,sizeof(buf)))
2121 slprintf(tmpname,sizeof(pstring)-1,
2122 "%s/ls.smb.%d",tmpdir(),(int)getpid());
2124 slprintf(cmd,sizeof(pstring)-1,
2125 "find . -name \"%s\" -print > %s",p,tmpname);
2127 slprintf(cmd,sizeof(pstring)-1,
2128 "/bin/ls %s > %s",p,tmpname);
2131 f = fopen(tmpname,"r");
2138 if (fscanf(f,"%s",lname) != 1) break;
2139 trim_string(lname,"./",NULL);
2143 /* check if it's a directory */
2144 if (directory_exist(lname,&st))
2146 if (!recurse) continue;
2147 slprintf(quest,sizeof(pstring)-1,
2148 "Put directory %s? ",lname);
2149 if (prompt && !yesno(quest))
2152 if (!seek_list(f,lname))
2157 pstrcpy(rname,cur_dir);
2158 pstrcat(rname,lname);
2159 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2161 if (!seek_list(f,lname))
2170 slprintf(quest,sizeof(quest)-1,
2171 "Put file %s? ",lname);
2172 if (prompt && !yesno(quest)) continue;
2174 pstrcpy(rname,cur_dir);
2175 pstrcat(rname,lname);
2179 /* null size so do_put knows to ignore it */
2182 /* set the date on the file */
2183 finfo.mtime = st.st_mtime;
2185 do_put(rname,lname,&finfo);
2192 /****************************************************************************
2194 ****************************************************************************/
2195 static void do_cancel(int job)
2197 char *rparam = NULL;
2203 bzero(param,sizeof(param));
2206 SSVAL(p,0,81); /* DosPrintJobDel() */
2209 p = skip_string(p,1);
2211 p = skip_string(p,1);
2215 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2221 int res = SVAL(rparam,0);
2224 printf("Job %d cancelled\n",job);
2226 printf("Error %d calcelling job %d\n",res,job);
2230 printf("Server refused cancel request\n");
2232 if (rparam) free(rparam);
2233 if (rdata) free(rdata);
2239 /****************************************************************************
2241 ****************************************************************************/
2242 static void cmd_cancel(char *inbuf,char *outbuf )
2247 if (!connect_as_printer)
2249 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2250 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2253 if (!next_token(NULL,buf,NULL,sizeof(buf))) {
2254 printf("cancel <jobid> ...\n");
2260 } while (next_token(NULL,buf,NULL,sizeof(buf)));
2266 /****************************************************************************
2268 ****************************************************************************/
2269 static void cmd_print(char *inbuf,char *outbuf )
2278 if (!connect_as_printer)
2280 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2281 DEBUG(0,("Trying to print without -P may fail\n"));
2284 if (!next_token(NULL,lname,NULL, sizeof(lname)))
2286 DEBUG(0,("print <filename>\n"));
2290 pstrcpy(rname,lname);
2291 p = strrchr(rname,'/');
2296 pstrcpy(rname,tname);
2299 if ((int)strlen(rname) > 14)
2302 if (strequal(lname,"-"))
2305 pstrcpy(rname,"stdin");
2308 dos_clean_name(rname);
2310 bzero(outbuf,smb_size);
2311 set_message(outbuf,2,2 + strlen(rname),True);
2313 CVAL(outbuf,smb_com) = SMBsplopen;
2314 SSVAL(outbuf,smb_tid,cnum);
2315 cli_setup_pkt(outbuf);
2317 SSVAL(outbuf,smb_vwv0,0);
2318 SSVAL(outbuf,smb_vwv1,printmode);
2320 p = smb_buf(outbuf);
2324 send_smb(Client,outbuf);
2325 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2327 if (CVAL(inbuf,smb_rcls) != 0)
2329 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2334 f = fopen(lname,"r");
2337 DEBUG(0,("Error opening local file %s\n",lname));
2342 fnum = SVAL(inbuf,smb_vwv0);
2344 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2350 bzero(outbuf,smb_size);
2351 set_message(outbuf,1,3,True);
2353 /* for some strange reason the OS/2 print server can't handle large
2354 packets when printing. weird */
2355 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2358 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2360 n = readfile(smb_buf(outbuf)+3,1,n,f);
2363 DEBUG(0,("read gave %d\n",n));
2367 smb_setlen(outbuf,smb_len(outbuf) + n);
2369 CVAL(outbuf,smb_com) = SMBsplwr;
2370 SSVAL(outbuf,smb_tid,cnum);
2371 cli_setup_pkt(outbuf);
2373 SSVAL(outbuf,smb_vwv0,fnum);
2374 SSVAL(outbuf,smb_vwv1,n+3);
2375 CVAL(smb_buf(outbuf),0) = 1;
2376 SSVAL(smb_buf(outbuf),1,n);
2378 send_smb(Client,outbuf);
2379 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2381 if (CVAL(inbuf,smb_rcls) != 0)
2383 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2390 DEBUG(2,("%d bytes printed\n",nread));
2392 bzero(outbuf,smb_size);
2393 set_message(outbuf,1,0,True);
2394 CVAL(outbuf,smb_com) = SMBsplclose;
2395 SSVAL(outbuf,smb_tid,cnum);
2396 cli_setup_pkt(outbuf);
2398 SSVAL(outbuf,smb_vwv0,fnum);
2400 send_smb(Client,outbuf);
2401 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2403 if (CVAL(inbuf,smb_rcls) != 0)
2405 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2415 /****************************************************************************
2416 show a print queue - this is deprecated as it uses the old smb that
2417 has limited support - the correct call is the cmd_p_queue_4() after this.
2418 ****************************************************************************/
2419 static void cmd_queue(char *inbuf,char *outbuf )
2424 bzero(outbuf,smb_size);
2425 set_message(outbuf,2,0,True);
2427 CVAL(outbuf,smb_com) = SMBsplretq;
2428 SSVAL(outbuf,smb_tid,cnum);
2429 cli_setup_pkt(outbuf);
2431 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2432 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2434 send_smb(Client,outbuf);
2435 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2437 if (CVAL(inbuf,smb_rcls) != 0)
2439 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2443 count = SVAL(inbuf,smb_vwv0);
2444 p = smb_buf(inbuf) + 3;
2447 DEBUG(0,("No entries in the print queue\n"));
2454 DEBUG(0,("Job Name Size Status\n"));
2460 case 0x01: safe_strcpy(status,"held or stopped", sizeof(status)-1); break;
2461 case 0x02: safe_strcpy(status,"printing",sizeof(status)-1); break;
2462 case 0x03: safe_strcpy(status,"awaiting print", sizeof(status)-1); break;
2463 case 0x04: safe_strcpy(status,"in intercept",sizeof(status)-1); break;
2464 case 0x05: safe_strcpy(status,"file had error",sizeof(status)-1); break;
2465 case 0x06: safe_strcpy(status,"printer error",sizeof(status)-1); break;
2466 default: safe_strcpy(status,"unknown",sizeof(status)-1); break;
2469 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2470 SVAL(p,5),p+12,IVAL(p,7),status));
2478 /****************************************************************************
2479 show information about a print queue
2480 ****************************************************************************/
2481 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2483 char *rparam = NULL;
2490 if (!connect_as_printer)
2492 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2493 DEBUG(0,("Trying to print without -P may fail\n"));
2496 bzero(param,sizeof(param));
2499 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2501 pstrcpy(p,"zWrLeh"); /* parameter description? */
2502 p = skip_string(p,1);
2503 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
2504 p = skip_string(p,1);
2505 pstrcpy(p,strrchr(service,'\\')+1); /* name of queue */
2506 p = skip_string(p,1);
2507 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2508 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2510 pstrcpy(p,""); /* subformat */
2511 p = skip_string(p,1);
2513 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2514 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2521 result_code = SVAL(rparam,0);
2522 converter = SVAL(rparam,2); /* conversion factor */
2524 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2526 if (result_code == 0) /* if no error, */
2536 fstring PrinterName;
2538 fstrcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2539 strlower(PrinterName); /* in lower case */
2541 p = rdata; /* received data */
2542 for( i = 0; i < SVAL(rparam,4); ++i)
2545 Priority = SVAL(p,2);
2546 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2548 Priority = SVAL(p,2);
2549 JobTime = make_unix_date3( p + 12);
2550 JobTimeStr = asctime(LocalTime( &JobTime));
2552 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2555 printf("%s-%u %s priority %u %s %s %u bytes\n",
2556 PrinterName, JobId, UserName,
2557 Priority, JobTimeStr, JobName, Size);
2559 #if 0 /* DEBUG code */
2560 printf("Job Id: \"%u\"\n", SVAL(p,0));
2561 printf("Priority: \"%u\"\n", SVAL(p,2));
2563 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2564 printf("Position: \"%u\"\n", SVAL(p,8));
2565 printf("Status: \"%u\"\n", SVAL(p,10));
2567 JobTime = make_unix_date3( p + 12);
2568 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2569 printf("date: \"%u\"\n", SVAL(p,12));
2571 printf("Size: \"%u\"\n", SVAL(p,16));
2572 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2573 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2574 #endif /* DEBUG CODE */
2579 else /* cli_call_api() failed */
2581 printf("Failed, error = %d\n", result_code);
2584 /* If any parameters or data were returned, free the storage. */
2585 if(rparam) free(rparam);
2586 if(rdata) free(rdata);
2591 /****************************************************************************
2592 show information about a print queue
2593 ****************************************************************************/
2594 static void cmd_qinfo(char *inbuf,char *outbuf )
2596 char *rparam = NULL;
2603 bzero(param,sizeof(param));
2606 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2608 pstrcpy(p,"zWrLh"); /* parameter description? */
2609 p = skip_string(p,1);
2610 pstrcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2611 p = skip_string(p,1);
2612 pstrcpy(p,strrchr(service,'\\')+1); /* name of queue */
2613 p = skip_string(p,1);
2614 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2615 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2617 pstrcpy(p,""); /* subformat */
2618 p = skip_string(p,1);
2620 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2621 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2628 result_code = SVAL(rparam,0);
2629 converter = SVAL(rparam,2); /* conversion factor */
2631 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2633 if (result_code == 0) /* if no error, */
2635 p = rdata; /* received data */
2637 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2638 printf("Priority: %u\n", SVAL(p,4) );
2639 printf("Start time: %u\n", SVAL(p,6) );
2640 printf("Until time: %u\n", SVAL(p,8) );
2641 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2642 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2643 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2644 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2645 printf("Status: %u\n", SVAL(p,28) );
2646 printf("Jobs: %u\n", SVAL(p,30) );
2647 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2648 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2650 /* Dump the driver data */
2655 ddptr = rdata + SVAL(p,40) - converter;
2656 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2657 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2659 for(x=8; x < count; x+=16)
2661 for(y=0; y < 16; y++)
2664 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2668 for(y=0; y < 16 && (x+y) < count; y++)
2670 c = CVAL(ddptr,(x+y));
2676 fputc('\n', stdout);
2682 else /* cli_call_api() failed */
2684 printf("Failed, error = %d\n", result_code);
2687 /* If any parameters or data were returned, free the storage. */
2688 if(rparam) free(rparam);
2689 if(rdata) free(rdata);
2694 /****************************************************************************
2696 ****************************************************************************/
2697 static void do_del(file_info *finfo)
2700 char *inbuf,*outbuf;
2703 pstrcpy(mask,cur_dir);
2704 pstrcat(mask,finfo->name);
2706 if (finfo->mode & aDIR)
2709 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2710 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2712 if (!inbuf || !outbuf)
2714 DEBUG(0,("out of memory\n"));
2718 bzero(outbuf,smb_size);
2719 set_message(outbuf,1,2 + strlen(mask),True);
2721 CVAL(outbuf,smb_com) = SMBunlink;
2722 SSVAL(outbuf,smb_tid,cnum);
2723 cli_setup_pkt(outbuf);
2725 SSVAL(outbuf,smb_vwv0,0);
2727 p = smb_buf(outbuf);
2731 send_smb(Client,outbuf);
2732 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2734 if (CVAL(inbuf,smb_rcls) != 0)
2735 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2737 free(inbuf);free(outbuf);
2741 /****************************************************************************
2743 ****************************************************************************/
2744 static void cmd_del(char *inbuf,char *outbuf )
2748 int attribute = aSYSTEM | aHIDDEN;
2753 pstrcpy(mask,cur_dir);
2755 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2757 DEBUG(0,("del <filename>\n"));
2762 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False,False);
2766 /****************************************************************************
2768 ****************************************************************************/
2769 static void cmd_rmdir(char *inbuf,char *outbuf )
2775 pstrcpy(mask,cur_dir);
2777 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2779 DEBUG(0,("rmdir <dirname>\n"));
2784 bzero(outbuf,smb_size);
2785 set_message(outbuf,0,2 + strlen(mask),True);
2787 CVAL(outbuf,smb_com) = SMBrmdir;
2788 SSVAL(outbuf,smb_tid,cnum);
2789 cli_setup_pkt(outbuf);
2792 p = smb_buf(outbuf);
2796 send_smb(Client,outbuf);
2797 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2799 if (CVAL(inbuf,smb_rcls) != 0)
2801 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2807 /****************************************************************************
2809 ****************************************************************************/
2810 static void cmd_rename(char *inbuf,char *outbuf )
2816 pstrcpy(src,cur_dir);
2817 pstrcpy(dest,cur_dir);
2819 if (!next_token(NULL,buf,NULL,sizeof(buf)) ||
2820 !next_token(NULL,buf2,NULL, sizeof(buf2)))
2822 DEBUG(0,("rename <src> <dest>\n"));
2828 bzero(outbuf,smb_size);
2829 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2831 CVAL(outbuf,smb_com) = SMBmv;
2832 SSVAL(outbuf,smb_tid,cnum);
2833 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2834 cli_setup_pkt(outbuf);
2836 p = smb_buf(outbuf);
2839 p = skip_string(p,1);
2843 send_smb(Client,outbuf);
2844 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2846 if (CVAL(inbuf,smb_rcls) != 0)
2848 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2855 /****************************************************************************
2856 toggle the prompt flag
2857 ****************************************************************************/
2858 static void cmd_prompt(char *dum_in, char *dum_out)
2861 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2865 /****************************************************************************
2866 set the newer than time
2867 ****************************************************************************/
2868 static void cmd_newer(char *dum_in, char *dum_out)
2872 SMB_STRUCT_STAT sbuf;
2874 ok = next_token(NULL,buf,NULL,sizeof(buf));
2875 if (ok && (dos_stat(buf,&sbuf) == 0))
2877 newer_than = sbuf.st_mtime;
2878 DEBUG(1,("Getting files newer than %s",
2879 asctime(LocalTime(&newer_than))));
2884 if (ok && newer_than == 0)
2885 DEBUG(0,("Error setting newer-than time\n"));
2888 /****************************************************************************
2889 set the archive level
2890 ****************************************************************************/
2891 static void cmd_archive(char *dum_in, char *dum_out)
2895 if (next_token(NULL,buf,NULL,sizeof(buf))) {
2896 archive_level = atoi(buf);
2898 DEBUG(0,("Archive level is %d\n",archive_level));
2901 /****************************************************************************
2902 toggle the lowercaseflag
2903 ****************************************************************************/
2904 static void cmd_lowercase(char *dum_in, char *dum_out)
2906 lowercase = !lowercase;
2907 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2913 /****************************************************************************
2914 toggle the recurse flag
2915 ****************************************************************************/
2916 static void cmd_recurse(char *dum_in, char *dum_out)
2919 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2922 /****************************************************************************
2923 toggle the translate flag
2924 ****************************************************************************/
2925 static void cmd_translate(char *dum_in, char *dum_out)
2927 translation = !translation;
2928 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2929 translation?"on":"off"));
2933 /****************************************************************************
2934 do a printmode command
2935 ****************************************************************************/
2936 static void cmd_printmode(char *dum_in, char *dum_out)
2941 if (next_token(NULL,buf,NULL,sizeof(buf)))
2943 if (strequal(buf,"text"))
2947 if (strequal(buf,"graphics"))
2950 printmode = atoi(buf);
2957 fstrcpy(mode,"text");
2960 fstrcpy(mode,"graphics");
2963 slprintf(mode,sizeof(mode)-1,"%d",printmode);
2967 DEBUG(2,("the printmode is now %s\n",mode));
2970 /****************************************************************************
2972 ****************************************************************************/
2973 static void cmd_lcd(char *dum_in, char *dum_out)
2978 if (next_token(NULL,buf,NULL,sizeof(buf)))
2980 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2984 /****************************************************************************
2985 try and browse available connections on a host
2986 ****************************************************************************/
2987 static BOOL browse_host(BOOL sort)
2989 char *rparam = NULL;
2996 /* now send a SMBtrans command with api RNetShareEnum */
2998 SSVAL(p,0,0); /* api number */
3001 p = skip_string(p,1);
3002 pstrcpy(p,"B13BWz");
3003 p = skip_string(p,1);
3005 SSVAL(p,2,BUFFER_SIZE);
3008 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3014 int res = SVAL(rparam,0);
3015 int converter=SVAL(rparam,2);
3017 BOOL long_share_name=False;
3019 if (res == 0 || res == ERRmoredata)
3021 count=SVAL(rparam,4);
3026 printf("\n\tSharename Type Comment\n");
3027 printf("\t--------- ---- -------\n");
3031 qsort(p,count,20,QSORT_CAST StrCaseCmp);
3033 for (i=0;i<count;i++)
3036 int type = SVAL(p,14);
3037 int comment_offset = IVAL(p,16) & 0xFFFF;
3043 case STYPE_DISKTREE:
3044 fstrcpy(typestr,"Disk"); break;
3046 fstrcpy(typestr,"Printer"); break;
3048 fstrcpy(typestr,"Device"); break;
3050 fstrcpy(typestr,"IPC"); break;
3053 printf("\t%-15.15s%-10.10s%s\n",
3055 comment_offset?rdata+comment_offset-converter:"");
3057 if (strlen(sname)>8) long_share_name=True;
3062 if (long_share_name) {
3063 printf("\nNOTE: There were share names longer than 8 chars.\n\
3064 On older clients these may not be accessible or may give browsing errors\n");
3067 if(res == ERRmoredata)
3068 printf("\nNOTE: More data was available, the list was truncated.\n");
3072 if (rparam) free(rparam);
3073 if (rdata) free(rdata);
3079 /****************************************************************************
3080 get some server info
3081 ****************************************************************************/
3082 static void server_info(void)
3084 char *rparam = NULL;
3090 bzero(param,sizeof(param));
3093 SSVAL(p,0,63); /* NetServerGetInfo()? */
3096 p = skip_string(p,1);
3097 pstrcpy(p,"zzzBBzz");
3098 p = skip_string(p,1);
3099 SSVAL(p,0,10); /* level 10 */
3103 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3109 int res = SVAL(rparam,0);
3110 int converter=SVAL(rparam,2);
3116 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3117 rdata+SVAL(p,0)-converter,
3118 rdata+SVAL(p,4)-converter,
3119 rdata+SVAL(p,8)-converter,
3120 rdata+SVAL(p,14)-converter);
3124 if (rparam) free(rparam);
3125 if (rdata) free(rdata);
3131 /****************************************************************************
3132 try and browse available connections on a host
3133 ****************************************************************************/
3134 static BOOL list_servers(char *wk_grp)
3136 char *rparam = NULL;
3144 BOOL generic_request = False;
3147 if (strequal(wk_grp,"WORKGROUP")) {
3148 /* we won't specify a workgroup */
3149 generic_request = True;
3152 /* now send a SMBtrans command with api ServerEnum? */
3154 SSVAL(p,0,0x68); /* api number */
3157 pstrcpy(p,generic_request?"WrLehDO":"WrLehDz");
3158 p = skip_string(p,1);
3160 pstrcpy(p,"B16BBDz");
3162 p = skip_string(p,1);
3164 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3170 if (!generic_request) {
3172 p = skip_string(p,1);
3175 /* first ask for a list of servers in this workgroup */
3176 SIVAL(svtype_p,0,SV_TYPE_ALL);
3178 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3179 8, BUFFER_SIZE - SAFETY_MARGIN,
3184 int res = SVAL(rparam,0);
3185 int converter=SVAL(rparam,2);
3188 if (res == 0 || res == ERRmoredata) {
3190 count=SVAL(rparam,4);
3193 printf("\n\nThis machine has a browse list:\n");
3194 printf("\n\tServer Comment\n");
3195 printf("\t--------- -------\n");
3198 for (i=0;i<count;i++) {
3200 int comment_offset = IVAL(p2,22) & 0xFFFF;
3201 printf("\t%-16.16s %s\n", sname,
3202 comment_offset?rdata+comment_offset-converter:"");
3208 if(res == ERRmoredata)
3209 printf("\nNOTE: More data was available, the list was truncated.\n");
3213 if (rparam) {free(rparam); rparam = NULL;}
3214 if (rdata) {free(rdata); rdata = NULL;}
3216 /* now ask for a list of workgroups */
3217 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3219 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3220 8, BUFFER_SIZE - SAFETY_MARGIN,
3225 int res = SVAL(rparam,0);
3226 int converter=SVAL(rparam,2);
3229 if (res == 0 || res == ERRmoredata) {
3231 count=SVAL(rparam,4);
3234 printf("\n\nThis machine has a workgroup list:\n");
3235 printf("\n\tWorkgroup Master\n");
3236 printf("\t--------- -------\n");
3239 for (i=0;i<count;i++) {
3241 int comment_offset = IVAL(p2,22) & 0xFFFF;
3242 printf("\t%-16.16s %s\n", sname,
3243 comment_offset?rdata+comment_offset-converter:"");
3249 if(res == ERRmoredata)
3250 printf("\nNOTE: More data was available, the list was truncated.\n");
3254 if (rparam) free(rparam);
3255 if (rdata) free(rdata);
3261 /* Some constants for completing filename arguments */
3263 #define COMPL_NONE 0 /* No completions */
3264 #define COMPL_REMOTE 1 /* Complete remote filename */
3265 #define COMPL_LOCAL 2 /* Complete local filename */
3267 /* This defines the commands supported by this client */
3271 void (*fn)(char *, char *);
3273 char compl_args[2]; /* Completion argument info */
3276 {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3277 {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3278 {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3279 {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
3280 {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
3281 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
3282 {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
3283 {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
3284 {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
3285 {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
3286 {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
3287 {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},
3288 {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
3289 {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
3290 {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
3291 {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
3292 {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
3293 {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
3294 {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
3295 {"pq",cmd_p_queue_4,"enumerate the print queue",{COMPL_NONE,COMPL_NONE}},
3296 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
3297 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},
3298 {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
3299 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},
3300 {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
3301 {"printmode",cmd_printmode,"<graphics or text> set the print mode",{COMPL_NONE,COMPL_NONE}},
3302 {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}},
3303 {"qinfo",cmd_qinfo,"show print queue information",{COMPL_NONE,COMPL_NONE}},
3304 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
3305 {"quit",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3306 {"q",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3307 {"exit",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3308 {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
3309 {"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",{COMPL_NONE,COMPL_NONE}},
3310 {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
3311 {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
3312 {"tarmode",cmd_tarmode,
3313 "<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
3314 {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
3315 {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
3316 {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
3317 {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
3318 {"",NULL,NULL,{COMPL_NONE,COMPL_NONE}}
3322 /*******************************************************************
3323 lookup a command string in the list of commands, including
3325 ******************************************************************/
3326 static int process_tok(fstring tok)
3328 int i = 0, matches = 0;
3330 int tok_len = strlen(tok);
3332 while (commands[i].fn != NULL)
3334 if (strequal(commands[i].name,tok))
3340 else if (strnequal(commands[i].name, tok, tok_len))
3350 else if (matches == 1)
3356 /****************************************************************************
3358 ****************************************************************************/
3359 static void cmd_help(char *dum_in, char *dum_out)
3364 if (next_token(NULL,buf,NULL,sizeof(buf)))
3366 if ((i = process_tok(buf)) >= 0)
3367 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3370 while (commands[i].description)
3372 for (j=0; commands[i].description && (j<5); j++) {
3373 DEBUG(0,("%-15s",commands[i].name));
3380 #ifndef HAVE_LIBREADLINE
3382 /****************************************************************************
3383 wait for keyboard activity, swallowing network packets
3384 ****************************************************************************/
3385 static void wait_keyboard(char *buffer)
3388 struct timeval timeout;
3394 FD_SET(Client,&fds);
3395 FD_SET(fileno(stdin),&fds);
3397 timeout.tv_sec = 20;
3398 timeout.tv_usec = 0;
3399 sys_select(MAX(Client,fileno(stdin))+1,&fds,&timeout);
3401 if (FD_ISSET(fileno(stdin),&fds))
3404 /* We deliberately use receive_smb instead of
3405 client_receive_smb as we want to receive
3406 session keepalives and then drop them here.
3408 if (FD_ISSET(Client,&fds))
3409 receive_smb(Client,buffer,0);
3411 chkpath("\\",False);
3415 #else /* if HAVE_LIBREADLINE */
3417 /****************************************************************************
3418 completion routines for GNU Readline
3419 ****************************************************************************/
3421 /* To avoid filename completion being activated when no valid
3422 completions are found, we assign this stub completion function
3423 to the rl_completion_entry_function variable. */
3425 char *complete_cmd_null(char *text, int state)
3430 /* Argh. This is starting to get ugly. We need to be able to pass data
3431 back from the do_dir() iterator function. */
3433 static int compl_state;
3434 static char *compl_text;
3435 static pstring result;
3437 /* Iterator function for do_dir() */
3439 void complete_process_file(file_info *f)
3441 /* Do we have a partial match? */
3443 if ((compl_state >= 0) && (strncmp(compl_text, f->name,
3444 strlen(compl_text)) == 0)) {
3446 /* Return filename if we have made enough matches */
3448 if (compl_state == 0) {
3449 pstrcpy(result, f->name);
3458 /* Complete a remote file */
3460 char *complete_remote_file(char *text, int state)
3462 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3463 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3464 int attribute = aDIR | aSYSTEM | aHIDDEN;
3467 if ((InBuffer == NULL) || (OutBuffer == NULL))
3470 /* Create dir mask */
3472 pstrcpy(mask, cur_dir);
3475 /* Initialise static vars for filename match */
3478 compl_state = state;
3481 /* Iterate over all files in directory */
3483 do_dir(InBuffer, OutBuffer, mask, attribute, complete_process_file, False,
3491 /* Return matched filename */
3493 if (result[0] != '\0') {
3494 return strdup(result); /* Readline will dispose of strings */
3500 /* Complete a smbclient command */
3502 char *complete_cmd(char *text, int state)
3504 static int cmd_index;
3513 /* Return the next name which partially matches the list of commands */
3515 while (strlen(name = commands[cmd_index++].name) > 0) {
3516 if (strncmp(name, text, strlen(text)) == 0) {
3517 return strdup(name);
3524 /* Main completion function for smbclient. Work out which word we are
3525 trying to complete and call the appropriate function. */
3527 char **completion_fn(char *text, int start, int end)
3529 int i, num_words, cmd_index;
3532 /* If we are at the start of a word, we are completing a smbclient
3536 return completion_matches(text, complete_cmd);
3539 /* Count # of words in command */
3542 for (i = 0; i <= end; i++) {
3543 if ((rl_line_buffer[i] != ' ') && (lastch == ' '))
3545 lastch = rl_line_buffer[i];
3548 if (rl_line_buffer[end] == ' ')
3551 /* Work out which command we are completing for */
3553 for (cmd_index = 0; strcmp(commands[cmd_index].name, "") != 0;
3556 /* Check each command in array */
3558 if (strncmp(rl_line_buffer, commands[cmd_index].name,
3559 strlen(commands[cmd_index].name)) == 0) {
3561 /* Call appropriate completion function */
3563 if ((num_words == 2) || (num_words == 3)) {
3564 switch (commands[cmd_index].compl_args[num_words - 2]) {
3567 return completion_matches(text, complete_remote_file);
3571 return completion_matches(text, filename_completion_function);
3575 /* An invalid completion type */
3580 /* We're either completing an argument > 3 or found an invalid
3581 completion type. Either way do nothing about it. */
3590 #endif /* HAVE_LIBREADLINE */
3592 /****************************************************************************
3593 process commands from the client
3594 ****************************************************************************/
3595 static BOOL process(char *base_directory)
3600 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3601 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3603 if ((InBuffer == NULL) || (OutBuffer == NULL))
3606 bzero(OutBuffer,smb_size);
3608 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3611 if (*base_directory) do_cd(base_directory);
3614 if (cmd[0] != '\0') while (cmd[0] != '\0')
3620 if ((p = strchr(cmd, ';')) == 0)
3622 strncpy(line, cmd, 999);
3628 if (p - cmd > 999) p = cmd + 999;
3629 strncpy(line, cmd, p - cmd);
3630 line[p - cmd] = '\0';
3634 /* input language code to internal one */
3637 /* and get the first part of the command */
3640 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
3643 if ((i = process_tok(tok)) >= 0)
3644 commands[i].fn(InBuffer,OutBuffer);
3646 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3648 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3650 else while (!feof(stdin))
3655 bzero(OutBuffer,smb_size);
3657 #ifdef HAVE_LIBREADLINE
3662 /* Read input using GNU Readline */
3664 slprintf(promptline,
3665 sizeof(promptline) - 1, "smb: %s> ", CNV_LANG(cur_dir));
3666 if (!readline(promptline))
3669 /* Copy read line to samba buffer */
3671 pstrcpy(line, rl_line_buffer);
3672 pstrcat(line, "\n");
3674 /* Add line to history */
3676 if (strlen(line) > 0)
3682 /* display a prompt */
3683 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3686 wait_keyboard(InBuffer);
3688 /* and get a response */
3689 if (!fgets(line,1000,stdin))
3694 /* input language code to internal one */
3697 /* special case - first char is ! */
3704 /* and get the first part of the command */
3707 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
3710 if ((i = process_tok(tok)) >= 0)
3711 commands[i].fn(InBuffer,OutBuffer);
3713 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3715 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3718 cli_send_logout(InBuffer,OutBuffer);
3722 /****************************************************************************
3723 usage on the program
3724 ****************************************************************************/
3725 static void usage(char *pname)
3727 DEBUG(0,("Usage: %s service <password> ", pname));
3729 DEBUG(0,("\nVersion %s\n",VERSION));
3730 DEBUG(0,("\t-s smb.conf pathname to smb.conf file\n"));
3731 DEBUG(0,("\t-B IP addr broadcast IP address to use\n"));
3732 DEBUG(0,("\t-O socket_options socket options to use\n"));
3733 DEBUG(0,("\t-R name resolve order use these name resolution services only\n"));
3734 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3735 DEBUG(0,("\t-i scope use this NetBIOS scope\n"));
3736 DEBUG(0,("\t-N don't ask for a password\n"));
3737 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3738 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3739 DEBUG(0,("\t-P connect to service as a printer\n"));
3740 DEBUG(0,("\t-p port connect to the specified port\n"));
3741 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3742 DEBUG(0,("\t-h Print this help message.\n"));
3743 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3744 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3745 DEBUG(0,("\t-U username set the network username\n"));
3746 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3747 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3748 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3749 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3750 DEBUG(0,("\t-T<c|x>IXFqgbNan command line tar\n"));
3751 DEBUG(0,("\t-D directory start from directory\n"));
3752 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3756 /****************************************************************************
3758 ****************************************************************************/
3759 int main(int argc,char *argv[])
3761 fstring base_directory;
3762 char *pname = argv[0];
3763 int port = SMB_PORT;
3766 extern char *optarg;
3769 BOOL message = False;
3770 BOOL explicit_user = False;
3771 extern char tar_type;
3772 static pstring servicesf = CONFIGFILE;
3774 pstring new_name_resolve_order;
3778 pstrcpy(term_code, KANJI);
3784 *base_directory = 0;
3786 *new_name_resolve_order = 0;
3790 setup_logging(pname,True);
3793 charset_initialise();
3795 if(!get_myname(myhostname,NULL))
3797 DEBUG(0,("Failed to get my hostname.\n"));
3800 in_client = True; /* Make sure that we tell lp_load we are */
3802 if (!lp_load(servicesf,True,False,False)) {
3803 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3806 codepage_initialise(lp_client_code_page());
3808 interpret_coding_system(term_code);
3814 pstrcpy(workgroup,lp_workgroup());
3817 pid = (uint16)getpid();
3818 vuid = (uint16)getuid();
3825 pstrcpy(username,getenv("USER"));
3827 /* modification to support userid%passwd syntax in the USER var
3828 25.Aug.97, jdblair@uab.edu */
3830 if ((p=strchr(username,'%')))
3833 pstrcpy(password,p+1);
3835 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3840 /* modification to support PASSWD environmental var
3841 25.Aug.97, jdblair@uab.edu */
3843 if (getenv("PASSWD")) {
3844 pstrcpy(password,getenv("PASSWD"));
3848 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
3850 BOOL close_it = False;
3854 if ((p = getenv("PASSWD_FD")) != NULL) {
3855 pstrcpy(spec, "descriptor ");
3857 sscanf(p, "%d", &fd);
3859 } else if ((p = getenv("PASSWD_FILE")) != NULL) {
3860 fd = open(p, O_RDONLY);
3863 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
3864 spec, strerror(errno));
3869 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
3870 p && p - pass < sizeof(pass);) {
3871 switch (read(fd, p, 1)) {
3873 if (*p != '\n' && *p != '\0') {
3874 *++p = '\0'; /* advance p, and null-terminate pass */
3879 *p = '\0'; /* null-terminate it, just in case... */
3880 p = NULL; /* then force the loop condition to become false */
3883 fprintf(stderr, "Error reading password from file %s: %s\n",
3884 spec, "empty password\n");
3889 fprintf(stderr, "Error reading password from file %s: %s\n",
3890 spec, strerror(errno));
3894 pstrcpy(password, pass);
3900 if (*username == 0 && getenv("LOGNAME"))
3902 pstrcpy(username,getenv("LOGNAME"));
3908 pstrcpy(username,"GUEST");
3917 if (*argv[1] != '-')
3920 pstrcpy(service,argv[1]);
3921 /* Convert any '/' characters in the service name to '\' characters */
3922 string_replace( service, '/','\\');
3926 if (count_chars(service,'\\') < 3)
3929 printf("\n%s: Not enough '\\' characters in service\n",service);
3934 if (count_chars(service,'\\') > 3)
3937 printf("\n%s: Too many '\\' characters in service\n",service);
3942 if (argc > 1 && (*argv[1] != '-'))
3945 pstrcpy(password,argv[1]);
3946 memset(argv[1],'X',strlen(argv[1]));
3953 getopt(argc, argv,"s:B:O:R:M:i:Nn:d:Pp:l:hI:EU:L:t:m:W:T:D:c:")) != EOF)
3957 pstrcpy(servicesf, optarg);
3960 iface_set_default(NULL,optarg,NULL);
3963 pstrcpy(user_socket_options,optarg);
3966 pstrcpy(new_name_resolve_order, optarg);
3969 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3970 pstrcpy(desthost,optarg);
3974 #if 0 /* This option doesn't seem to do anything - JRA. */
3976 pstrcpy(desthost,optarg);
3978 nt_domain_logon = True;
3982 pstrcpy(scope,optarg);
3989 pstrcpy(global_myname,optarg);
3995 DEBUGLEVEL = atoi(optarg);
3998 connect_as_printer = True;
4001 port = atoi(optarg);
4004 slprintf(debugf,sizeof(debugf)-1, "%s.client",optarg);
4012 dest_ip = *interpret_addr2(optarg);
4013 if (zero_ip(dest_ip))
4024 explicit_user = True;
4025 pstrcpy(username,optarg);
4026 if ((lp=strchr(username,'%')))
4029 pstrcpy(password,lp+1);
4031 memset(strchr(optarg,'%')+1,'X',strlen(password));
4037 pstrcpy(query_host,optarg);
4042 pstrcpy(term_code, optarg);
4045 max_protocol = interpret_protocol(optarg,max_protocol);
4048 pstrcpy(workgroup,optarg);
4051 if (!tar_parseargs(argc, argv, optarg, optind)) {
4057 pstrcpy(base_directory,optarg);
4068 get_myname((*global_myname)?NULL:global_myname,NULL);
4069 strupper(global_myname);
4071 if(*new_name_resolve_order)
4072 lp_set_name_resolve_order(new_name_resolve_order);
4074 if (!tar_type && !*query_host && !*service && !message)
4080 #ifdef HAVE_LIBREADLINE
4082 /* Initialise GNU Readline */
4084 rl_readline_name = "smbclient";
4085 rl_attempted_completion_function = completion_fn;
4086 rl_completion_entry_function = (Function *)complete_cmd_null;
4088 /* Initialise history list */
4092 #endif /* HAVE_LIBREADLINE */
4094 DEBUG( 3, ( "Client started (version %s).\n", VERSION ) );
4099 if (cli_open_sockets(port)) {
4100 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4101 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4104 if ((InBuffer == NULL) || (OutBuffer == NULL))
4107 bzero(OutBuffer,smb_size);
4108 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
4111 if (*base_directory) do_cd(base_directory);
4113 ret=process_tar(InBuffer, OutBuffer);
4115 cli_send_logout(InBuffer, OutBuffer);
4122 if ((p=strchr(query_host,'#'))) {
4125 sscanf(p, "%x", &name_type);
4128 #if 0 /* This seemed to be used with the unknown -S option. JRA */
4129 if (*query_host && !nt_domain_logon)
4135 slprintf(service,sizeof(service)-1,
4136 "\\\\%s\\IPC$",query_host);
4138 connect_as_ipc = True;
4139 if (cli_open_sockets(port))
4144 if (!cli_send_login(NULL,NULL,True,True,NULL))
4148 if (!browse_host(True)) {
4152 if (!list_servers(workgroup)) {
4154 list_servers(workgroup);
4157 cli_send_logout(NULL,NULL);
4167 if (cli_open_sockets(port))
4169 pstring inbuf,outbuf;
4170 bzero(outbuf,smb_size);
4171 if (!cli_send_session_request(inbuf,outbuf))
4174 send_message(inbuf,outbuf);
4182 if (cli_open_sockets(port))
4184 if (!process(base_directory))