2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 pstring cur_dir = "\\";
34 extern pstring service;
35 extern pstring desthost;
36 extern pstring myname;
37 extern pstring myhostname;
38 extern pstring password;
39 extern pstring username;
40 extern pstring workgroup;
44 extern BOOL connect_as_printer;
45 extern BOOL connect_as_ipc;
46 extern struct in_addr ipzero;
48 extern BOOL doencrypt;
50 extern pstring user_socket_options;
52 /* 30 second timeout on most commands */
53 #define CLIENT_TIMEOUT (30*1000)
54 #define SHORT_TIMEOUT (5*1000)
56 /* value for unused fid field in trans2 secondary request */
57 #define FID_UNUSED (0xFFFF)
61 extern int max_protocol;
64 time_t newer_than = 0;
65 int archive_level = 0;
67 extern pstring debugf;
68 extern int DEBUGLEVEL;
70 BOOL translation = False;
82 static int interpret_long_filename(int level,char *p,file_info *finfo);
83 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir);
84 static int interpret_short_filename(char *p,file_info *finfo);
85 static BOOL do_this_one(file_info *finfo);
87 /* clitar bits insert */
90 extern BOOL tar_reset;
102 BOOL recurse = False;
103 BOOL lowercase = False;
105 struct in_addr dest_ip;
107 #define SEPARATORS " \t\n\r"
109 BOOL abort_mget = True;
113 extern BOOL readbraw_supported ;
114 extern BOOL writebraw_supported;
116 pstring fileselection = "";
118 extern file_info def_finfo;
121 int get_total_size = 0;
122 int get_total_time_ms = 0;
123 int put_total_size = 0;
124 int put_total_time_ms = 0;
133 #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 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);
154 /****************************************************************************
155 write to a local file with CR/LF->LF translation if appropriate. return the
156 number taken from the buffer. This may not equal the number written.
157 ****************************************************************************/
158 static int writefile(int f, char *b, int n)
163 return(write(f,b,n));
168 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
172 if (write(f, b, 1) != 1)
183 /****************************************************************************
184 read from a file with LF->CR/LF translation if appropriate. return the
185 number read. read approx n bytes.
186 ****************************************************************************/
187 static int readfile(char *b, int size, int n, FILE *f)
192 if (!translation || (size != 1))
193 return(fread(b,size,n,f));
198 if ((c = getc(f)) == EOF)
203 if (c == '\n') /* change all LFs to CR/LF */
217 /****************************************************************************
218 read from a file with print translation. return the number read. read approx n
220 ****************************************************************************/
221 static int printread(FILE *f,char *b,int n)
225 i = readfile(b,1, n-1,f);
234 /****************************************************************************
235 check for existance of a dir
236 ****************************************************************************/
237 static BOOL chkpath(char *path,BOOL report)
240 pstring inbuf,outbuf;
244 trim_string(path2,NULL,"\\");
245 if (!*path2) *path2 = '\\';
247 bzero(outbuf,smb_size);
248 set_message(outbuf,0,4 + strlen(path2),True);
249 SCVAL(outbuf,smb_com,SMBchkpth);
250 SSVAL(outbuf,smb_tid,cnum);
251 cli_setup_pkt(outbuf);
259 /* this little bit of code can be used to extract NT error codes.
260 Just feed a bunch of "cd foo" commands to smbclient then watch
261 in netmon (tridge) */
263 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
264 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
269 send_smb(Client,outbuf);
270 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
272 if (report && CVAL(inbuf,smb_rcls) != 0)
273 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
275 return(CVAL(inbuf,smb_rcls) == 0);
279 /****************************************************************************
281 ****************************************************************************/
282 static void send_message(char *inbuf,char *outbuf)
289 /* send a SMBsendstrt command */
290 bzero(outbuf,smb_size);
291 set_message(outbuf,0,0,True);
292 CVAL(outbuf,smb_com) = SMBsendstrt;
293 SSVAL(outbuf,smb_tid,cnum);
298 p = skip_string(p,1);
301 p = skip_string(p,1);
303 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
305 send_smb(Client,outbuf);
308 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
310 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
314 grp_id = SVAL(inbuf,smb_vwv0);
316 printf("Connected. Type your message, ending it with a Control-D\n");
318 while (!feof(stdin) && total_len < 1600)
320 int maxlen = MIN(1600 - total_len,127);
327 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
334 CVAL(outbuf,smb_com) = SMBsendtxt;
336 set_message(outbuf,1,l+3,True);
338 SSVAL(outbuf,smb_vwv0,grp_id);
345 send_smb(Client,outbuf);
348 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
350 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
357 if (total_len >= 1600)
358 printf("the message was truncated to 1600 bytes ");
360 printf("sent %d bytes ",total_len);
362 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
364 CVAL(outbuf,smb_com) = SMBsendend;
365 set_message(outbuf,1,0,False);
366 SSVAL(outbuf,smb_vwv0,grp_id);
368 send_smb(Client,outbuf);
371 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
373 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
380 /****************************************************************************
381 check the space on a device
382 ****************************************************************************/
383 static void do_dskattr(void)
385 pstring inbuf,outbuf;
387 bzero(outbuf,smb_size);
388 set_message(outbuf,0,0,True);
389 CVAL(outbuf,smb_com) = SMBdskattr;
390 SSVAL(outbuf,smb_tid,cnum);
391 cli_setup_pkt(outbuf);
393 send_smb(Client,outbuf);
394 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
396 if (CVAL(inbuf,smb_rcls) != 0)
397 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
399 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
400 SVAL(inbuf,smb_vwv0),
401 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
402 SVAL(inbuf,smb_vwv3)));
405 /****************************************************************************
407 ****************************************************************************/
408 static void cmd_pwd(void)
410 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
411 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
415 /****************************************************************************
416 change directory - inner section
417 ****************************************************************************/
418 static void do_cd(char *newdir)
424 /* Save the current directory in case the
425 new directory is invalid */
426 strcpy(saved_dir, cur_dir);
431 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
432 strcat(cur_dir, "\\");
434 dos_clean_name(cur_dir);
435 strcpy(dname,cur_dir);
436 strcat(cur_dir,"\\");
437 dos_clean_name(cur_dir);
439 if (!strequal(cur_dir,"\\"))
440 if (!chkpath(dname,True))
441 strcpy(cur_dir,saved_dir);
443 strcpy(cd_path,cur_dir);
446 /****************************************************************************
448 ****************************************************************************/
449 static void cmd_cd(char *inbuf,char *outbuf)
453 if (next_token(NULL,buf,NULL))
456 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
460 /****************************************************************************
461 display info about a file
462 ****************************************************************************/
463 static void display_finfo(file_info *finfo)
465 if (do_this_one(finfo)) {
466 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
467 DEBUG(0,(" %-30s%7.7s%10d %s",
468 CNV_LANG(finfo->name),
469 attrib_string(finfo->mode),
471 asctime(LocalTime(&t))));
472 dir_total += finfo->size;
477 /****************************************************************************
478 do a directory listing, calling fn on each file found. Use the TRANSACT2
479 call for long filenames
480 ****************************************************************************/
481 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
483 int max_matches = 512;
484 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
489 char *dirlist = NULL;
491 int total_received = 0;
493 char *resp_data=NULL;
494 char *resp_param=NULL;
495 int resp_data_len = 0;
496 int resp_param_len=0;
498 int ff_resume_key = 0;
499 int ff_searchcount=0;
513 if (loop_count > 200)
515 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
521 setup = TRANSACT2_FINDFIRST;
522 SSVAL(param,0,attribute); /* attribute */
523 SSVAL(param,2,max_matches); /* max count */
524 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
525 SSVAL(param,6,info_level);
527 strcpy(param+12,mask);
531 setup = TRANSACT2_FINDNEXT;
532 SSVAL(param,0,ff_dir_handle);
533 SSVAL(param,2,max_matches); /* max count */
534 SSVAL(param,4,info_level);
535 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
536 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
537 strcpy(param+12,mask);
539 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
540 ff_dir_handle,ff_resume_key,ff_lastname,mask));
542 /* ??? original code added 1 pad byte after param */
544 cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
546 0,12+strlen(mask)+1,1,
549 if (!cli_receive_trans_response(inbuf,SMBtrans2,
550 &resp_data_len,&resp_param_len,
551 &resp_data,&resp_param))
553 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
557 /* parse out some important return info */
561 ff_dir_handle = SVAL(p,0);
562 ff_searchcount = SVAL(p,2);
564 ff_lastname = SVAL(p,8);
568 ff_searchcount = SVAL(p,0);
570 ff_lastname = SVAL(p,6);
573 if (ff_searchcount == 0)
576 /* point to the data bytes */
579 /* we might need the lastname for continuations */
586 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
587 /* strcpy(mask,p+ff_lastname+94); */
590 strcpy(mask,p + ff_lastname + 1);
598 /* and add them to the dirlist pool */
599 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
603 DEBUG(0,("Failed to expand dirlist\n"));
607 /* put in a length for the last entry, to ensure we can chain entries
608 into the next packet */
611 for (p2=p,i=0;i<(ff_searchcount-1);i++)
612 p2 += interpret_long_filename(info_level,p2,NULL);
613 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
616 /* grab the data for later use */
617 memcpy(dirlist+dirlist_len,p,resp_data_len);
618 dirlist_len += resp_data_len;
620 total_received += ff_searchcount;
622 if (resp_data) free(resp_data); resp_data = NULL;
623 if (resp_param) free(resp_param); resp_param = NULL;
625 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
626 ff_searchcount,ff_eos,ff_resume_key));
632 for (p=dirlist,i=0;i<total_received;i++)
634 p += interpret_long_filename(info_level,p,&finfo);
635 display_finfo(&finfo);
638 for (p=dirlist,i=0;i<total_received;i++)
640 p += interpret_long_filename(info_level,p,&finfo);
641 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
644 /* free up the dirlist buffer */
645 if (dirlist) free(dirlist);
646 return(total_received);
650 /****************************************************************************
651 do a directory listing, calling fn on each file found
652 ****************************************************************************/
653 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
659 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
660 int num_received = 0;
662 char *dirlist = NULL;
674 bzero(outbuf,smb_size);
676 set_message(outbuf,2,5 + strlen(mask),True);
678 set_message(outbuf,2,5 + 21,True);
681 if (Protocol >= PROTOCOL_LANMAN1)
682 CVAL(outbuf,smb_com) = SMBffirst;
685 CVAL(outbuf,smb_com) = SMBsearch;
687 SSVAL(outbuf,smb_tid,cnum);
688 cli_setup_pkt(outbuf);
690 SSVAL(outbuf,smb_vwv0,num_asked);
691 SSVAL(outbuf,smb_vwv1,attribute);
712 send_smb(Client,outbuf);
713 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
715 received = SVAL(inbuf,smb_vwv0);
717 DEBUG(5,("dir received %d\n",received));
719 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
721 if (received <= 0) break;
725 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
730 p = smb_buf(inbuf) + 3;
732 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
733 p,received*DIR_STRUCT_SIZE);
735 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
737 num_received += received;
739 if (CVAL(inbuf,smb_rcls) != 0) break;
743 if (!first && Protocol >= PROTOCOL_LANMAN1)
745 bzero(outbuf,smb_size);
746 CVAL(outbuf,smb_com) = SMBfclose;
748 SSVAL(outbuf,smb_tid,cnum);
749 cli_setup_pkt(outbuf);
762 send_smb(Client,outbuf);
763 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
765 if (CVAL(inbuf,smb_rcls) != 0)
766 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
771 for (p=dirlist,i=0;i<num_received;i++)
773 p += interpret_short_filename(p,&finfo);
774 display_finfo(&finfo);
777 for (p=dirlist,i=0;i<num_received;i++)
779 p += interpret_short_filename(p,&finfo);
780 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
783 if (dirlist) free(dirlist);
784 return(num_received);
789 /****************************************************************************
790 do a directory listing, calling fn on each file found
791 ****************************************************************************/
792 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
794 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
795 if (Protocol >= PROTOCOL_LANMAN2)
797 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
801 expand_mask(Mask,False);
802 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
806 /*******************************************************************
807 decide if a file should be operated on
808 ********************************************************************/
809 static BOOL do_this_one(file_info *finfo)
811 if (finfo->mode & aDIR) return(True);
813 if (newer_than && finfo->mtime < newer_than)
816 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
823 /*****************************************************************************
824 Convert a character pointer in a cli_call_api() response to a form we can use.
825 This function contains code to prevent core dumps if the server returns
827 *****************************************************************************/
828 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
830 if( datap == 0 ) /* turn NULL pointers */
831 { /* into zero length strings */
836 unsigned int offset = datap - converter;
838 if( offset >= rdrcnt )
840 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
845 return &rdata[offset];
850 /****************************************************************************
851 interpret a short filename structure
852 The length of the structure is returned
853 ****************************************************************************/
854 static int interpret_short_filename(char *p,file_info *finfo)
856 finfo->mode = CVAL(p,21);
858 /* this date is converted to GMT by make_unix_date */
859 finfo->ctime = make_unix_date(p+22);
860 finfo->mtime = finfo->atime = finfo->ctime;
861 finfo->size = IVAL(p,26);
862 strcpy(finfo->name,p+30);
864 return(DIR_STRUCT_SIZE);
867 /****************************************************************************
868 interpret a long filename structure - this is mostly guesses at the moment
869 The length of the structure is returned
870 The structure of a long filename depends on the info level. 260 is used
871 by NT and 2 is used by OS/2
872 ****************************************************************************/
873 static int interpret_long_filename(int level,char *p,file_info *finfo)
876 memcpy(finfo,&def_finfo,sizeof(*finfo));
880 case 1: /* OS/2 understands this */
883 /* these dates are converted to GMT by make_unix_date */
884 finfo->ctime = make_unix_date2(p+4);
885 finfo->atime = make_unix_date2(p+8);
886 finfo->mtime = make_unix_date2(p+12);
887 finfo->size = IVAL(p,16);
888 finfo->mode = CVAL(p,24);
889 strcpy(finfo->name,p+27);
891 return(28 + CVAL(p,26));
893 case 2: /* this is what OS/2 uses mostly */
896 /* these dates are converted to GMT by make_unix_date */
897 finfo->ctime = make_unix_date2(p+4);
898 finfo->atime = make_unix_date2(p+8);
899 finfo->mtime = make_unix_date2(p+12);
900 finfo->size = IVAL(p,16);
901 finfo->mode = CVAL(p,24);
902 strcpy(finfo->name,p+31);
904 return(32 + CVAL(p,30));
906 /* levels 3 and 4 are untested */
910 /* these dates are probably like the other ones */
911 finfo->ctime = make_unix_date2(p+8);
912 finfo->atime = make_unix_date2(p+12);
913 finfo->mtime = make_unix_date2(p+16);
914 finfo->size = IVAL(p,20);
915 finfo->mode = CVAL(p,28);
916 strcpy(finfo->name,p+33);
923 /* these dates are probably like the other ones */
924 finfo->ctime = make_unix_date2(p+8);
925 finfo->atime = make_unix_date2(p+12);
926 finfo->mtime = make_unix_date2(p+16);
927 finfo->size = IVAL(p,20);
928 finfo->mode = CVAL(p,28);
929 strcpy(finfo->name,p+37);
933 case 260: /* NT uses this, but also accepts 2 */
938 p += 4; /* next entry offset */
939 p += 4; /* fileindex */
941 /* these dates appear to arrive in a weird way. It seems to
942 be localtime plus the serverzone given in the initial
943 connect. This is GMT when DST is not in effect and one
944 hour from GMT otherwise. Can this really be right??
946 I suppose this could be called kludge-GMT. Is is the GMT
947 you get by using the current DST setting on a different
948 localtime. It will be cheap to calculate, I suppose, as
949 no DST tables will be needed */
951 finfo->ctime = interpret_long_date(p); p += 8;
952 finfo->atime = interpret_long_date(p); p += 8;
953 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
954 finfo->size = IVAL(p,0); p += 8;
955 p += 8; /* alloc size */
956 finfo->mode = CVAL(p,0); p += 4;
957 namelen = IVAL(p,0); p += 4;
958 p += 4; /* EA size */
959 p += 2; /* short name len? */
960 p += 24; /* short name? */
961 StrnCpy(finfo->name,p,namelen);
967 DEBUG(1,("Unknown long filename format %d\n",level));
974 /****************************************************************************
975 act on the files in a dir listing
976 ****************************************************************************/
977 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
980 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
981 !mask_match(finfo->name,fileselection,False,False)) &&
982 !(recurse_dir && (strequal(finfo->name,".") ||
983 strequal(finfo->name,".."))))
985 if (recurse_dir && (finfo->mode & aDIR))
989 strcpy(sav_dir,cur_dir);
990 strcat(cur_dir,finfo->name);
991 strcat(cur_dir,"\\");
992 strcpy(mask2,cur_dir);
995 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1000 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);
1002 do_dir(inbuf,outbuf,mask2,attribute,fn,True);
1004 strcpy(cur_dir,sav_dir);
1008 if (fn && do_this_one(finfo))
1015 /****************************************************************************
1016 get a directory listing
1017 ****************************************************************************/
1018 static void cmd_dir(char *inbuf,char *outbuf)
1020 int attribute = aDIR | aSYSTEM | aHIDDEN;
1026 strcpy(mask,cur_dir);
1027 if(mask[strlen(mask)-1]!='\\')
1030 if (next_token(NULL,buf,NULL))
1041 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1045 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1050 /****************************************************************************
1051 get a file from rname to lname
1052 ****************************************************************************/
1053 static void do_get(char *rname,char *lname,file_info *finfo1)
1058 BOOL newhandle = False;
1059 char *inbuf,*outbuf;
1061 BOOL close_done = False;
1062 BOOL ignore_close_error = False;
1066 struct timeval tp_start;
1067 GetTimeOfDay(&tp_start);
1078 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1079 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1081 if (!inbuf || !outbuf)
1083 DEBUG(0,("out of memory\n"));
1087 bzero(outbuf,smb_size);
1088 set_message(outbuf,15,1 + strlen(rname),True);
1090 CVAL(outbuf,smb_com) = SMBopenX;
1091 SSVAL(outbuf,smb_tid,cnum);
1092 cli_setup_pkt(outbuf);
1094 SSVAL(outbuf,smb_vwv0,0xFF);
1095 SSVAL(outbuf,smb_vwv2,1); /* return additional info */
1096 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1097 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1098 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1099 SSVAL(outbuf,smb_vwv8,1);
1100 SSVAL(outbuf,smb_vwv11,0xffff);
1101 SSVAL(outbuf,smb_vwv12,0xffff);
1103 p = smb_buf(outbuf);
1105 p = skip_string(p,1);
1107 /* do a chained openX with a readX? */
1111 DEBUG(3,("Chaining readX wth openX\n"));
1112 SSVAL(outbuf,smb_vwv0,SMBreadX);
1113 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1116 SSVAL(p,smb_wct,10);
1117 SSVAL(p,smb_vwv0,0xFF);
1118 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1119 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1120 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1124 if(!strcmp(lname,"-"))
1125 handle = fileno(stdout);
1128 handle = creat(lname,0644);
1133 DEBUG(0,("Error opening local file %s\n",lname));
1134 free(inbuf);free(outbuf);
1138 send_smb(Client,outbuf);
1139 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1141 if (CVAL(inbuf,smb_rcls) != 0)
1143 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1144 SVAL(inbuf,smb_err) == ERRnoresource &&
1145 cli_reopen_connection(inbuf,outbuf))
1147 do_get(rname,lname,finfo1);
1150 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1153 free(inbuf);free(outbuf);
1157 strcpy(finfo.name,rname);
1161 finfo.mode = SVAL(inbuf,smb_vwv3);
1162 /* these times arrive as LOCAL time, using the DST offset
1163 corresponding to that time, we convert them to GMT */
1164 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1165 finfo.atime = finfo.ctime = finfo.mtime;
1166 finfo.size = IVAL(inbuf,smb_vwv6);
1169 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1171 fnum = SVAL(inbuf,smb_vwv2);
1173 /* we might have got some data from a chained readX */
1174 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1176 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1177 datalen = SVAL(p,smb_vwv5);
1178 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1187 DEBUG(2,("getting file %s of size %d bytes as %s ",
1188 CNV_LANG(finfo.name),
1192 while (nread < finfo.size && !close_done)
1195 static BOOL can_chain_close = True;
1199 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1201 /* 3 possible read types. readbraw if a large block is required.
1202 readX + close if not much left and read if neither is supported */
1204 /* we might have already read some data from a chained readX */
1205 if (dataptr && datalen>0)
1208 /* if we can finish now then readX+close */
1209 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1210 ((finfo.size - nread) <
1211 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1214 /* if we support readraw then use that */
1215 if (method<0 && readbraw_supported)
1218 /* if we can then use readX */
1219 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1230 /* use readX + close */
1231 bzero(outbuf,smb_size);
1232 set_message(outbuf,10,0,True);
1233 CVAL(outbuf,smb_com) = SMBreadX;
1234 SSVAL(outbuf,smb_tid,cnum);
1235 cli_setup_pkt(outbuf);
1239 CVAL(outbuf,smb_vwv0) = SMBclose;
1240 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1243 CVAL(outbuf,smb_vwv0) = 0xFF;
1245 SSVAL(outbuf,smb_vwv2,fnum);
1246 SIVAL(outbuf,smb_vwv3,nread);
1247 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1248 SSVAL(outbuf,smb_vwv6,0);
1249 SIVAL(outbuf,smb_vwv7,0);
1250 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1254 p = smb_buf(outbuf);
1261 /* now set the total packet length */
1262 smb_setlen(outbuf,smb_len(outbuf)+9);
1265 send_smb(Client,outbuf);
1266 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1268 if (CVAL(inbuf,smb_rcls) != 0)
1270 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1275 SVAL(inbuf,smb_vwv0) != SMBclose)
1277 /* NOTE: WfWg sometimes just ignores the chained
1278 command! This seems to break the spec? */
1279 DEBUG(3,("Rejected chained close?\n"));
1281 can_chain_close = False;
1282 ignore_close_error = True;
1285 datalen = SVAL(inbuf,smb_vwv5);
1286 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1292 static int readbraw_size = BUFFER_SIZE;
1295 bzero(outbuf,smb_size);
1296 set_message(outbuf,8,0,True);
1297 CVAL(outbuf,smb_com) = SMBreadbraw;
1298 SSVAL(outbuf,smb_tid,cnum);
1299 cli_setup_pkt(outbuf);
1300 SSVAL(outbuf,smb_vwv0,fnum);
1301 SIVAL(outbuf,smb_vwv1,nread);
1302 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1303 SSVAL(outbuf,smb_vwv4,0);
1304 SIVALS(outbuf,smb_vwv5,-1);
1305 send_smb(Client,outbuf);
1307 /* Now read the raw data into the buffer and write it */
1308 if(read_smb_length(Client,inbuf,0) == -1) {
1309 DEBUG(0,("Failed to read length in readbraw\n"));
1313 /* Even though this is not an smb message, smb_len
1314 returns the generic length of an smb message */
1315 datalen = smb_len(inbuf);
1319 /* we got a readbraw error */
1320 DEBUG(4,("readbraw error - reducing size\n"));
1321 readbraw_size = (readbraw_size * 9) / 10;
1323 if (readbraw_size < max_xmit)
1325 DEBUG(0,("disabling readbraw\n"));
1326 readbraw_supported = False;
1333 if(read_data(Client,inbuf,datalen) != datalen) {
1334 DEBUG(0,("Failed to read data in readbraw\n"));
1342 /* we've already read some data with a chained readX */
1346 /* use plain read */
1347 bzero(outbuf,smb_size);
1348 set_message(outbuf,5,0,True);
1349 CVAL(outbuf,smb_com) = SMBread;
1350 SSVAL(outbuf,smb_tid,cnum);
1351 cli_setup_pkt(outbuf);
1353 SSVAL(outbuf,smb_vwv0,fnum);
1354 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1355 SIVAL(outbuf,smb_vwv2,nread);
1356 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1358 send_smb(Client,outbuf);
1359 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1361 if (CVAL(inbuf,smb_rcls) != 0)
1363 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1367 datalen = SVAL(inbuf,smb_vwv0);
1368 dataptr = smb_buf(inbuf) + 3;
1372 if (writefile(handle,dataptr,datalen) != datalen)
1374 DEBUG(0,("Error writing local file\n"));
1381 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1393 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1395 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1397 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1400 free(inbuf);free(outbuf);
1408 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1409 bzero(outbuf,smb_size);
1410 set_message(outbuf,8,strlen(rname)+4,True);
1411 CVAL(outbuf,smb_com) = SMBsetatr;
1412 SSVAL(outbuf,smb_tid,cnum);
1413 cli_setup_pkt(outbuf);
1414 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1415 SIVALS(outbuf,smb_vwv1,0);
1416 p = smb_buf(outbuf);
1422 send_smb(Client,outbuf);
1423 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1427 struct timeval tp_end;
1430 GetTimeOfDay(&tp_end);
1432 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1433 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1434 get_total_time_ms += this_time;
1435 get_total_size += finfo.size;
1437 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1438 finfo.size / (1.024*this_time + 1.0e-4),
1439 get_total_size / (1.024*get_total_time_ms)));
1442 free(inbuf);free(outbuf);
1446 /****************************************************************************
1448 ****************************************************************************/
1449 static void cmd_get(void)
1455 strcpy(rname,cur_dir);
1458 p = rname + strlen(rname);
1460 if (!next_token(NULL,p,NULL)) {
1461 DEBUG(0,("get <filename>\n"));
1465 dos_clean_name(rname);
1467 next_token(NULL,lname,NULL);
1469 do_get(rname,lname,NULL);
1473 /****************************************************************************
1474 do a mget operation on one file
1475 ****************************************************************************/
1476 static void do_mget(file_info *finfo)
1481 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1486 DEBUG(0,("mget aborted\n"));
1490 if (finfo->mode & aDIR)
1491 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1493 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1495 if (prompt && !yesno(quest)) return;
1497 if (finfo->mode & aDIR)
1499 pstring saved_curdir;
1501 char *inbuf,*outbuf;
1503 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1504 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1506 if (!inbuf || !outbuf)
1508 DEBUG(0,("out of memory\n"));
1512 strcpy(saved_curdir,cur_dir);
1514 strcat(cur_dir,finfo->name);
1515 strcat(cur_dir,"\\");
1517 unix_format(finfo->name);
1520 strlower(finfo->name);
1522 if (!directory_exist(finfo->name,NULL) &&
1523 sys_mkdir(finfo->name,0777) != 0)
1525 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1526 strcpy(cur_dir,saved_curdir);
1527 free(inbuf);free(outbuf);
1531 if (sys_chdir(finfo->name) != 0)
1533 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1534 strcpy(cur_dir,saved_curdir);
1535 free(inbuf);free(outbuf);
1540 strcpy(mget_mask,cur_dir);
1541 strcat(mget_mask,"*");
1543 do_dir((char *)inbuf,(char *)outbuf,
1544 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1546 strcpy(cur_dir,saved_curdir);
1547 free(inbuf);free(outbuf);
1551 strcpy(rname,cur_dir);
1552 strcat(rname,finfo->name);
1553 do_get(rname,finfo->name,finfo);
1557 /****************************************************************************
1558 view the file using the pager
1559 ****************************************************************************/
1560 static void cmd_more(void)
1562 fstring rname,lname,tmpname,pager_cmd;
1565 strcpy(rname,cur_dir);
1567 sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1568 strcpy(lname,tmpname);
1570 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1571 DEBUG(0,("more <filename>\n"));
1574 dos_clean_name(rname);
1576 do_get(rname,lname,NULL);
1578 pager=getenv("PAGER");
1579 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1586 /****************************************************************************
1588 ****************************************************************************/
1589 static void cmd_mget(char *inbuf,char *outbuf)
1591 int attribute = aSYSTEM | aHIDDEN;
1603 while (next_token(NULL,p,NULL))
1605 strcpy(mget_mask,cur_dir);
1606 if(mget_mask[strlen(mget_mask)-1]!='\\')
1607 strcat(mget_mask,"\\");
1610 strcpy(mget_mask,p);
1612 strcat(mget_mask,p);
1613 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1618 strcpy(mget_mask,cur_dir);
1619 if(mget_mask[strlen(mget_mask)-1]!='\\')
1620 strcat(mget_mask,"\\");
1621 strcat(mget_mask,"*");
1622 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1626 /****************************************************************************
1627 make a directory of name "name"
1628 ****************************************************************************/
1629 static BOOL do_mkdir(char *name)
1632 char *inbuf,*outbuf;
1634 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1635 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1637 if (!inbuf || !outbuf)
1639 DEBUG(0,("out of memory\n"));
1643 bzero(outbuf,smb_size);
1644 set_message(outbuf,0,2 + strlen(name),True);
1646 CVAL(outbuf,smb_com) = SMBmkdir;
1647 SSVAL(outbuf,smb_tid,cnum);
1648 cli_setup_pkt(outbuf);
1651 p = smb_buf(outbuf);
1655 send_smb(Client,outbuf);
1656 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1658 if (CVAL(inbuf,smb_rcls) != 0)
1660 DEBUG(0,("%s making remote directory %s\n",
1661 smb_errstr(inbuf),CNV_LANG(name)));
1663 free(inbuf);free(outbuf);
1667 free(inbuf);free(outbuf);
1672 /****************************************************************************
1674 ****************************************************************************/
1675 static void cmd_mkdir(char *inbuf,char *outbuf)
1681 strcpy(mask,cur_dir);
1683 if (!next_token(NULL,p,NULL))
1686 DEBUG(0,("mkdir <dirname>\n"));
1698 trim_string(ddir,".",NULL);
1699 p = strtok(ddir,"/\\");
1703 if (!chkpath(ddir2,False))
1708 p = strtok(NULL,"/\\");
1716 /*******************************************************************
1717 write to a file using writebraw
1718 ********************************************************************/
1719 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1724 bzero(outbuf,smb_size);
1725 bzero(inbuf,smb_size);
1726 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1728 CVAL(outbuf,smb_com) = SMBwritebraw;
1729 SSVAL(outbuf,smb_tid,cnum);
1730 cli_setup_pkt(outbuf);
1732 SSVAL(outbuf,smb_vwv0,fnum);
1733 SSVAL(outbuf,smb_vwv1,n);
1734 SIVAL(outbuf,smb_vwv3,pos);
1735 SSVAL(outbuf,smb_vwv7,1);
1737 send_smb(Client,outbuf);
1739 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1742 _smb_setlen(buf-4,n); /* HACK! XXXX */
1744 if (write_socket(Client,buf-4,n+4) != n+4)
1747 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1748 DEBUG(0,("Error writing remote file (2)\n"));
1751 return(SVAL(inbuf,smb_vwv0));
1756 /*******************************************************************
1758 ********************************************************************/
1759 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1763 if (writebraw_supported && n > (max_xmit-200))
1764 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1766 bzero(outbuf,smb_size);
1767 bzero(inbuf,smb_size);
1768 set_message(outbuf,5,n + 3,True);
1770 CVAL(outbuf,smb_com) = SMBwrite;
1771 SSVAL(outbuf,smb_tid,cnum);
1772 cli_setup_pkt(outbuf);
1774 SSVAL(outbuf,smb_vwv0,fnum);
1775 SSVAL(outbuf,smb_vwv1,n);
1776 SIVAL(outbuf,smb_vwv2,pos);
1777 SSVAL(outbuf,smb_vwv4,0);
1778 CVAL(smb_buf(outbuf),0) = 1;
1779 SSVAL(smb_buf(outbuf),1,n);
1781 memcpy(smb_buf(outbuf)+3,buf,n);
1783 send_smb(Client,outbuf);
1784 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1786 if (CVAL(inbuf,smb_rcls) != 0) {
1787 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1790 return(SVAL(inbuf,smb_vwv0));
1795 /****************************************************************************
1797 ****************************************************************************/
1798 static void do_put(char *rname,char *lname,file_info *finfo)
1804 char *inbuf,*outbuf;
1805 time_t close_time = finfo->mtime;
1807 static int maxwrite=0;
1809 struct timeval tp_start;
1810 GetTimeOfDay(&tp_start);
1812 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1813 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1815 if (!inbuf || !outbuf)
1817 DEBUG(0,("out of memory\n"));
1821 bzero(outbuf,smb_size);
1822 set_message(outbuf,3,2 + strlen(rname),True);
1824 if (finfo->mtime == 0 || finfo->mtime == -1)
1825 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1827 CVAL(outbuf,smb_com) = SMBcreate;
1828 SSVAL(outbuf,smb_tid,cnum);
1829 cli_setup_pkt(outbuf);
1831 SSVAL(outbuf,smb_vwv0,finfo->mode);
1832 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1834 p = smb_buf(outbuf);
1838 send_smb(Client,outbuf);
1839 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1841 if (CVAL(inbuf,smb_rcls) != 0)
1843 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1845 free(inbuf);free(outbuf);if (buf) free(buf);
1849 f = fopen(lname,"r");
1853 DEBUG(0,("Error opening local file %s\n",lname));
1854 free(inbuf);free(outbuf);
1859 fnum = SVAL(inbuf,smb_vwv0);
1860 if (finfo->size < 0)
1861 finfo->size = file_size(lname);
1863 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1866 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1868 while (nread < finfo->size)
1873 n = MIN(n,finfo->size - nread);
1875 buf = (char *)Realloc(buf,n+4);
1877 fseek(f,nread,SEEK_SET);
1878 if ((n = readfile(buf+4,1,n,f)) < 1)
1880 DEBUG(0,("Error reading local file\n"));
1884 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1888 DEBUG(0,("Error writing file\n"));
1901 bzero(outbuf,smb_size);
1902 set_message(outbuf,3,0,True);
1903 CVAL(outbuf,smb_com) = SMBclose;
1904 SSVAL(outbuf,smb_tid,cnum);
1905 cli_setup_pkt(outbuf);
1907 SSVAL(outbuf,smb_vwv0,fnum);
1908 put_dos_date3(outbuf,smb_vwv1,close_time);
1910 send_smb(Client,outbuf);
1911 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1913 if (CVAL(inbuf,smb_rcls) != 0)
1915 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1917 free(inbuf);free(outbuf);
1924 free(inbuf);free(outbuf);
1928 struct timeval tp_end;
1931 GetTimeOfDay(&tp_end);
1933 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1934 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1935 put_total_time_ms += this_time;
1936 put_total_size += finfo->size;
1938 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1939 finfo->size / (1.024*this_time + 1.0e-4),
1940 put_total_size / (1.024*put_total_time_ms)));
1946 /****************************************************************************
1948 ****************************************************************************/
1949 static void cmd_put(void)
1958 strcpy(rname,cur_dir);
1962 if (!next_token(NULL,p,NULL))
1964 DEBUG(0,("put <filename>\n"));
1969 if (next_token(NULL,p,NULL))
1972 strcat(rname,lname);
1974 dos_clean_name(rname);
1978 if (!file_exist(lname,&st)) {
1979 DEBUG(0,("%s does not exist\n",lname));
1982 finfo.mtime = st.st_mtime;
1985 do_put(rname,lname,&finfo);
1988 /****************************************************************************
1989 seek in a directory/file list until you get something that doesn't start with
1991 ****************************************************************************/
1992 static BOOL seek_list(FILE *f,char *name)
1997 if (fscanf(f,"%s",s) != 1) return(False);
1998 trim_string(s,"./",NULL);
1999 if (strncmp(s,name,strlen(name)) != 0)
2010 /****************************************************************************
2011 set the file selection mask
2012 ****************************************************************************/
2013 static void cmd_select(void)
2015 strcpy(fileselection,"");
2016 next_token(NULL,fileselection,NULL);
2020 /****************************************************************************
2022 ****************************************************************************/
2023 static void cmd_mput(void)
2034 while (next_token(NULL,p,NULL))
2041 sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2043 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2045 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2048 f = fopen(tmpname,"r");
2055 if (fscanf(f,"%s",lname) != 1) break;
2056 trim_string(lname,"./",NULL);
2060 /* check if it's a directory */
2061 if (directory_exist(lname,&st))
2063 if (!recurse) continue;
2064 sprintf(quest,"Put directory %s? ",lname);
2065 if (prompt && !yesno(quest))
2068 if (!seek_list(f,lname))
2073 strcpy(rname,cur_dir);
2074 strcat(rname,lname);
2075 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2077 if (!seek_list(f,lname))
2086 sprintf(quest,"Put file %s? ",lname);
2087 if (prompt && !yesno(quest)) continue;
2089 strcpy(rname,cur_dir);
2090 strcat(rname,lname);
2094 /* null size so do_put knows to ignore it */
2097 /* set the date on the file */
2098 finfo.mtime = st.st_mtime;
2100 do_put(rname,lname,&finfo);
2107 /****************************************************************************
2109 ****************************************************************************/
2110 static void do_cancel(int job)
2112 char *rparam = NULL;
2118 bzero(param,sizeof(param));
2121 SSVAL(p,0,81); /* DosPrintJobDel() */
2124 p = skip_string(p,1);
2126 p = skip_string(p,1);
2130 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2136 int res = SVAL(rparam,0);
2139 printf("Job %d cancelled\n",job);
2141 printf("Error %d calcelling job %d\n",res,job);
2145 printf("Server refused cancel request\n");
2147 if (rparam) free(rparam);
2148 if (rdata) free(rdata);
2154 /****************************************************************************
2156 ****************************************************************************/
2157 static void cmd_cancel(char *inbuf,char *outbuf )
2162 if (!connect_as_printer)
2164 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2165 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2168 if (!next_token(NULL,buf,NULL)) {
2169 printf("cancel <jobid> ...\n");
2175 } while (next_token(NULL,buf,NULL));
2181 /****************************************************************************
2183 ****************************************************************************/
2184 static void cmd_print(char *inbuf,char *outbuf )
2193 if (!connect_as_printer)
2195 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2196 DEBUG(0,("Trying to print without -P may fail\n"));
2199 if (!next_token(NULL,lname,NULL))
2201 DEBUG(0,("print <filename>\n"));
2205 strcpy(rname,lname);
2206 p = strrchr(rname,'/');
2211 strcpy(rname,tname);
2214 if ((int)strlen(rname) > 14)
2217 if (strequal(lname,"-"))
2220 strcpy(rname,"stdin");
2223 dos_clean_name(rname);
2225 bzero(outbuf,smb_size);
2226 set_message(outbuf,2,2 + strlen(rname),True);
2228 CVAL(outbuf,smb_com) = SMBsplopen;
2229 SSVAL(outbuf,smb_tid,cnum);
2230 cli_setup_pkt(outbuf);
2232 SSVAL(outbuf,smb_vwv0,0);
2233 SSVAL(outbuf,smb_vwv1,printmode);
2235 p = smb_buf(outbuf);
2239 send_smb(Client,outbuf);
2240 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2242 if (CVAL(inbuf,smb_rcls) != 0)
2244 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2249 f = fopen(lname,"r");
2252 DEBUG(0,("Error opening local file %s\n",lname));
2257 fnum = SVAL(inbuf,smb_vwv0);
2259 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2265 bzero(outbuf,smb_size);
2266 set_message(outbuf,1,3,True);
2268 /* for some strange reason the OS/2 print server can't handle large
2269 packets when printing. weird */
2270 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2273 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2275 n = readfile(smb_buf(outbuf)+3,1,n,f);
2278 DEBUG(0,("read gave %d\n",n));
2282 smb_setlen(outbuf,smb_len(outbuf) + n);
2284 CVAL(outbuf,smb_com) = SMBsplwr;
2285 SSVAL(outbuf,smb_tid,cnum);
2286 cli_setup_pkt(outbuf);
2288 SSVAL(outbuf,smb_vwv0,fnum);
2289 SSVAL(outbuf,smb_vwv1,n+3);
2290 CVAL(smb_buf(outbuf),0) = 1;
2291 SSVAL(smb_buf(outbuf),1,n);
2293 send_smb(Client,outbuf);
2294 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2296 if (CVAL(inbuf,smb_rcls) != 0)
2298 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2305 DEBUG(2,("%d bytes printed\n",nread));
2307 bzero(outbuf,smb_size);
2308 set_message(outbuf,1,0,True);
2309 CVAL(outbuf,smb_com) = SMBsplclose;
2310 SSVAL(outbuf,smb_tid,cnum);
2311 cli_setup_pkt(outbuf);
2313 SSVAL(outbuf,smb_vwv0,fnum);
2315 send_smb(Client,outbuf);
2316 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2318 if (CVAL(inbuf,smb_rcls) != 0)
2320 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2330 /****************************************************************************
2331 show a print queue - this is deprecated as it uses the old smb that
2332 has limited support - the correct call is the cmd_p_queue_4() after this.
2333 ****************************************************************************/
2334 static void cmd_queue(char *inbuf,char *outbuf )
2339 bzero(outbuf,smb_size);
2340 set_message(outbuf,2,0,True);
2342 CVAL(outbuf,smb_com) = SMBsplretq;
2343 SSVAL(outbuf,smb_tid,cnum);
2344 cli_setup_pkt(outbuf);
2346 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2347 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2349 send_smb(Client,outbuf);
2350 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2352 if (CVAL(inbuf,smb_rcls) != 0)
2354 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2358 count = SVAL(inbuf,smb_vwv0);
2359 p = smb_buf(inbuf) + 3;
2362 DEBUG(0,("No entries in the print queue\n"));
2369 DEBUG(0,("Job Name Size Status\n"));
2375 case 0x01: sprintf(status,"held or stopped"); break;
2376 case 0x02: sprintf(status,"printing"); break;
2377 case 0x03: sprintf(status,"awaiting print"); break;
2378 case 0x04: sprintf(status,"in intercept"); break;
2379 case 0x05: sprintf(status,"file had error"); break;
2380 case 0x06: sprintf(status,"printer error"); break;
2381 default: sprintf(status,"unknown"); break;
2384 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2385 SVAL(p,5),p+12,IVAL(p,7),status));
2393 /****************************************************************************
2394 show information about a print queue
2395 ****************************************************************************/
2396 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2398 char *rparam = NULL;
2405 if (!connect_as_printer)
2407 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2408 DEBUG(0,("Trying to print without -P may fail\n"));
2411 bzero(param,sizeof(param));
2414 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2416 strcpy(p,"zWrLeh"); /* parameter description? */
2417 p = skip_string(p,1);
2418 strcpy(p,"WWzWWDDzz"); /* returned data format */
2419 p = skip_string(p,1);
2420 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2421 p = skip_string(p,1);
2422 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2423 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2425 strcpy(p,""); /* subformat */
2426 p = skip_string(p,1);
2428 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2429 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2436 result_code = SVAL(rparam,0);
2437 converter = SVAL(rparam,2); /* conversion factor */
2439 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2441 if (result_code == 0) /* if no error, */
2451 char PrinterName[20];
2453 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2454 strlower(PrinterName); /* in lower case */
2456 p = rdata; /* received data */
2457 for( i = 0; i < SVAL(rparam,4); ++i)
2460 Priority = SVAL(p,2);
2461 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2463 Priority = SVAL(p,2);
2464 JobTime = make_unix_date3( p + 12);
2465 JobTimeStr = asctime(LocalTime( &JobTime));
2467 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2470 printf("%s-%u %s priority %u %s %s %u bytes\n",
2471 PrinterName, JobId, UserName,
2472 Priority, JobTimeStr, JobName, Size);
2474 #if 0 /* DEBUG code */
2475 printf("Job Id: \"%u\"\n", SVAL(p,0));
2476 printf("Priority: \"%u\"\n", SVAL(p,2));
2478 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2479 printf("Position: \"%u\"\n", SVAL(p,8));
2480 printf("Status: \"%u\"\n", SVAL(p,10));
2482 JobTime = make_unix_date3( p + 12);
2483 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2484 printf("date: \"%u\"\n", SVAL(p,12));
2486 printf("Size: \"%u\"\n", SVAL(p,16));
2487 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2488 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2489 #endif /* DEBUG CODE */
2494 else /* cli_call_api() failed */
2496 printf("Failed, error = %d\n", result_code);
2499 /* If any parameters or data were returned, free the storage. */
2500 if(rparam) free(rparam);
2501 if(rdata) free(rdata);
2506 /****************************************************************************
2507 show information about a print queue
2508 ****************************************************************************/
2509 static void cmd_qinfo(char *inbuf,char *outbuf )
2511 char *rparam = NULL;
2518 bzero(param,sizeof(param));
2521 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2523 strcpy(p,"zWrLh"); /* parameter description? */
2524 p = skip_string(p,1);
2525 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2526 p = skip_string(p,1);
2527 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2528 p = skip_string(p,1);
2529 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2530 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2532 strcpy(p,""); /* subformat */
2533 p = skip_string(p,1);
2535 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2536 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2543 result_code = SVAL(rparam,0);
2544 converter = SVAL(rparam,2); /* conversion factor */
2546 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2548 if (result_code == 0) /* if no error, */
2550 p = rdata; /* received data */
2552 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2553 printf("Priority: %u\n", SVAL(p,4) );
2554 printf("Start time: %u\n", SVAL(p,6) );
2555 printf("Until time: %u\n", SVAL(p,8) );
2556 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2557 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2558 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2559 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2560 printf("Status: %u\n", SVAL(p,28) );
2561 printf("Jobs: %u\n", SVAL(p,30) );
2562 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2563 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2565 /* Dump the driver data */
2570 ddptr = rdata + SVAL(p,40) - converter;
2571 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2572 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2574 for(x=8; x < count; x+=16)
2576 for(y=0; y < 16; y++)
2579 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2583 for(y=0; y < 16 && (x+y) < count; y++)
2585 c = CVAL(ddptr,(x+y));
2591 fputc('\n', stdout);
2597 else /* cli_call_api() failed */
2599 printf("Failed, error = %d\n", result_code);
2602 /* If any parameters or data were returned, free the storage. */
2603 if(rparam) free(rparam);
2604 if(rdata) free(rdata);
2609 /****************************************************************************
2611 ****************************************************************************/
2612 static void do_del(file_info *finfo)
2615 char *inbuf,*outbuf;
2618 strcpy(mask,cur_dir);
2619 strcat(mask,finfo->name);
2621 if (finfo->mode & aDIR)
2624 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2625 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2627 if (!inbuf || !outbuf)
2629 DEBUG(0,("out of memory\n"));
2633 bzero(outbuf,smb_size);
2634 set_message(outbuf,1,2 + strlen(mask),True);
2636 CVAL(outbuf,smb_com) = SMBunlink;
2637 SSVAL(outbuf,smb_tid,cnum);
2638 cli_setup_pkt(outbuf);
2640 SSVAL(outbuf,smb_vwv0,0);
2642 p = smb_buf(outbuf);
2646 send_smb(Client,outbuf);
2647 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2649 if (CVAL(inbuf,smb_rcls) != 0)
2650 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2652 free(inbuf);free(outbuf);
2656 /****************************************************************************
2658 ****************************************************************************/
2659 static void cmd_del(char *inbuf,char *outbuf )
2663 int attribute = aSYSTEM | aHIDDEN;
2668 strcpy(mask,cur_dir);
2670 if (!next_token(NULL,buf,NULL))
2672 DEBUG(0,("del <filename>\n"));
2677 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2681 /****************************************************************************
2683 ****************************************************************************/
2684 static void cmd_rmdir(char *inbuf,char *outbuf )
2690 strcpy(mask,cur_dir);
2692 if (!next_token(NULL,buf,NULL))
2694 DEBUG(0,("rmdir <dirname>\n"));
2699 bzero(outbuf,smb_size);
2700 set_message(outbuf,0,2 + strlen(mask),True);
2702 CVAL(outbuf,smb_com) = SMBrmdir;
2703 SSVAL(outbuf,smb_tid,cnum);
2704 cli_setup_pkt(outbuf);
2707 p = smb_buf(outbuf);
2711 send_smb(Client,outbuf);
2712 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2714 if (CVAL(inbuf,smb_rcls) != 0)
2716 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2722 /****************************************************************************
2724 ****************************************************************************/
2725 static void cmd_rename(char *inbuf,char *outbuf )
2731 strcpy(src,cur_dir);
2732 strcpy(dest,cur_dir);
2734 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2736 DEBUG(0,("rename <src> <dest>\n"));
2742 bzero(outbuf,smb_size);
2743 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2745 CVAL(outbuf,smb_com) = SMBmv;
2746 SSVAL(outbuf,smb_tid,cnum);
2747 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2748 cli_setup_pkt(outbuf);
2750 p = smb_buf(outbuf);
2753 p = skip_string(p,1);
2757 send_smb(Client,outbuf);
2758 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2760 if (CVAL(inbuf,smb_rcls) != 0)
2762 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2769 /****************************************************************************
2770 toggle the prompt flag
2771 ****************************************************************************/
2772 static void cmd_prompt(void)
2775 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2779 /****************************************************************************
2780 set the newer than time
2781 ****************************************************************************/
2782 static void cmd_newer(void)
2788 ok = next_token(NULL,buf,NULL);
2789 if (ok && (sys_stat(buf,&sbuf) == 0))
2791 newer_than = sbuf.st_mtime;
2792 DEBUG(1,("Getting files newer than %s",
2793 asctime(LocalTime(&newer_than))));
2798 if (ok && newer_than == 0)
2799 DEBUG(0,("Error setting newer-than time\n"));
2802 /****************************************************************************
2803 set the archive level
2804 ****************************************************************************/
2805 static void cmd_archive(void)
2809 if (next_token(NULL,buf,NULL)) {
2810 archive_level = atoi(buf);
2812 DEBUG(0,("Archive level is %d\n",archive_level));
2815 /****************************************************************************
2816 toggle the lowercaseflag
2817 ****************************************************************************/
2818 static void cmd_lowercase(void)
2820 lowercase = !lowercase;
2821 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2827 /****************************************************************************
2828 toggle the recurse flag
2829 ****************************************************************************/
2830 static void cmd_recurse(void)
2833 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2836 /****************************************************************************
2837 toggle the translate flag
2838 ****************************************************************************/
2839 static void cmd_translate(void)
2841 translation = !translation;
2842 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2843 translation?"on":"off"));
2847 /****************************************************************************
2848 do a printmode command
2849 ****************************************************************************/
2850 static void cmd_printmode(void)
2855 if (next_token(NULL,buf,NULL))
2857 if (strequal(buf,"text"))
2861 if (strequal(buf,"graphics"))
2864 printmode = atoi(buf);
2871 strcpy(mode,"text");
2874 strcpy(mode,"graphics");
2877 sprintf(mode,"%d",printmode);
2881 DEBUG(2,("the printmode is now %s\n",mode));
2884 /****************************************************************************
2886 ****************************************************************************/
2887 static void cmd_lcd(void)
2892 if (next_token(NULL,buf,NULL))
2894 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2898 /****************************************************************************
2899 try and browse available connections on a host
2900 ****************************************************************************/
2901 static BOOL browse_host(BOOL sort)
2904 /* If strcasecmp is already defined, remove it. */
2907 #endif /* strcasecmp */
2908 #define strcasecmp StrCaseCmp
2909 #endif /* NOSTRCASECMP */
2911 extern int strcasecmp();
2913 char *rparam = NULL;
2920 /* now send a SMBtrans command with api RNetShareEnum */
2922 SSVAL(p,0,0); /* api number */
2925 p = skip_string(p,1);
2927 p = skip_string(p,1);
2929 SSVAL(p,2,BUFFER_SIZE);
2932 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2938 int res = SVAL(rparam,0);
2939 int converter=SVAL(rparam,2);
2941 BOOL long_share_name=False;
2945 count=SVAL(rparam,4);
2950 printf("\n\tSharename Type Comment\n");
2951 printf("\t--------- ---- -------\n");
2955 qsort(p,count,20,QSORT_CAST strcasecmp);
2957 for (i=0;i<count;i++)
2960 int type = SVAL(p,14);
2961 int comment_offset = IVAL(p,16) & 0xFFFF;
2967 case STYPE_DISKTREE:
2968 strcpy(typestr,"Disk"); break;
2970 strcpy(typestr,"Printer"); break;
2972 strcpy(typestr,"Device"); break;
2974 strcpy(typestr,"IPC"); break;
2977 printf("\t%-15.15s%-10.10s%s\n",
2980 comment_offset?rdata+comment_offset-converter:"");
2982 if (strlen(sname)>8) long_share_name=True;
2987 if (long_share_name) {
2988 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
2993 if (rparam) free(rparam);
2994 if (rdata) free(rdata);
3000 /****************************************************************************
3001 get some server info
3002 ****************************************************************************/
3003 static void server_info()
3005 char *rparam = NULL;
3011 bzero(param,sizeof(param));
3014 SSVAL(p,0,63); /* NetServerGetInfo()? */
3017 p = skip_string(p,1);
3018 strcpy(p,"zzzBBzz");
3019 p = skip_string(p,1);
3020 SSVAL(p,0,10); /* level 10 */
3024 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3030 int res = SVAL(rparam,0);
3031 int converter=SVAL(rparam,2);
3037 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3038 rdata+SVAL(p,0)-converter,
3039 rdata+SVAL(p,4)-converter,
3040 rdata+SVAL(p,8)-converter,
3041 rdata+SVAL(p,14)-converter);
3045 if (rparam) free(rparam);
3046 if (rdata) free(rdata);
3052 /****************************************************************************
3053 try and browse available connections on a host
3054 ****************************************************************************/
3055 static BOOL list_servers(char *wk_grp)
3057 char *rparam = NULL;
3065 BOOL generic_request = False;
3068 if (strequal(wk_grp,"WORKGROUP")) {
3069 /* we won't specify a workgroup */
3070 generic_request = True;
3073 /* now send a SMBtrans command with api ServerEnum? */
3075 SSVAL(p,0,0x68); /* api number */
3078 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3079 p = skip_string(p,1);
3081 strcpy(p,"B16BBDz");
3083 p = skip_string(p,1);
3085 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3091 if (!generic_request) {
3093 p = skip_string(p,1);
3096 /* first ask for a list of servers in this workgroup */
3097 SIVAL(svtype_p,0,SV_TYPE_ALL);
3099 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3100 8, BUFFER_SIZE - SAFETY_MARGIN,
3105 int res = SVAL(rparam,0);
3106 int converter=SVAL(rparam,2);
3111 count=SVAL(rparam,4);
3114 printf("\n\nThis machine has a browse list:\n");
3115 printf("\n\tServer Comment\n");
3116 printf("\t--------- -------\n");
3119 for (i=0;i<count;i++) {
3121 int comment_offset = IVAL(p2,22) & 0xFFFF;
3122 printf("\t%-16.16s %s\n",
3124 comment_offset?rdata+comment_offset-converter:"");
3132 if (rparam) {free(rparam); rparam = NULL;}
3133 if (rdata) {free(rdata); rdata = NULL;}
3135 /* now ask for a list of workgroups */
3136 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3138 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3139 8, BUFFER_SIZE - SAFETY_MARGIN,
3144 int res = SVAL(rparam,0);
3145 int converter=SVAL(rparam,2);
3150 count=SVAL(rparam,4);
3153 printf("\n\nThis machine has a workgroup list:\n");
3154 printf("\n\tWorkgroup Master\n");
3155 printf("\t--------- -------\n");
3158 for (i=0;i<count;i++) {
3160 int comment_offset = IVAL(p2,22) & 0xFFFF;
3161 printf("\t%-16.16s %s\n",
3163 comment_offset?rdata+comment_offset-converter:"");
3171 if (rparam) free(rparam);
3172 if (rdata) free(rdata);
3178 /* This defines the commands supported by this client */
3186 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3187 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3188 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3189 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3190 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3191 {"get",cmd_get,"<remote name> [local name] get a file"},
3192 {"mget",cmd_mget,"<mask> get all the matching files"},
3193 {"put",cmd_put,"<local name> [remote name] put a file"},
3194 {"mput",cmd_mput,"<mask> put all matching files"},
3195 {"rename",cmd_rename,"<src> <dest> rename some files"},
3196 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3197 {"mask",cmd_select,"<mask> mask all filenames against this"},
3198 {"del",cmd_del,"<mask> delete all matching files"},
3199 {"rm",cmd_del,"<mask> delete all matching files"},
3200 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3201 {"md",cmd_mkdir,"<directory> make a directory"},
3202 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
3203 {"rd",cmd_rmdir,"<directory> remove a directory"},
3204 {"pq",cmd_p_queue_4,"enumerate the print queue"},
3205 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
3206 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
3207 {"translate",cmd_translate,"toggle text translation for printing"},
3208 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
3209 {"print",cmd_print,"<file name> print a file"},
3210 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
3211 {"queue",cmd_queue,"show the print queue"},
3212 {"qinfo",cmd_qinfo,"show print queue information"},
3213 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
3214 {"quit",cli_send_logout,"logoff the server"},
3215 {"q",cli_send_logout,"logoff the server"},
3216 {"exit",cli_send_logout,"logoff the server"},
3217 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
3218 {"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"},
3219 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3220 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
3221 {"tarmode",cmd_tarmode,
3222 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3223 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
3224 {"help",cmd_help,"[command] give help on a command"},
3225 {"?",cmd_help,"[command] give help on a command"},
3226 {"!",NULL,"run a shell command on the local system"},
3231 /*******************************************************************
3232 lookup a command string in the list of commands, including
3234 ******************************************************************/
3235 static int process_tok(fstring tok)
3237 int i = 0, matches = 0;
3239 int tok_len = strlen(tok);
3241 while (commands[i].fn != NULL)
3243 if (strequal(commands[i].name,tok))
3249 else if (strnequal(commands[i].name, tok, tok_len))
3259 else if (matches == 1)
3265 /****************************************************************************
3267 ****************************************************************************/
3273 if (next_token(NULL,buf,NULL))
3275 if ((i = process_tok(buf)) >= 0)
3276 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3279 while (commands[i].description)
3281 for (j=0; commands[i].description && (j<5); j++) {
3282 DEBUG(0,("%-15s",commands[i].name));
3289 /****************************************************************************
3290 wait for keyboard activity, swallowing network packets
3291 ****************************************************************************/
3293 static char wait_keyboard(char *buffer)
3295 static void wait_keyboard(char *buffer)
3300 struct timeval timeout;
3310 FD_SET(Client,&fds);
3312 FD_SET(fileno(stdin),&fds);
3315 timeout.tv_sec = 20;
3316 timeout.tv_usec = 0;
3320 selrtn = sys_select(&fds,&timeout);
3323 if (FD_ISSET(fileno(stdin),&fds))
3330 set_blocking(fileno(stdin), False);
3331 readret = read_data( fileno(stdin), &ch, 1);
3332 set_blocking(fileno(stdin), True);
3335 if (errno != EAGAIN)
3337 /* should crash here */
3338 DEBUG(1,("readchar stdin failed\n"));
3341 else if (readret != 0)
3348 /* We deliberately use receive_smb instead of
3349 client_receive_smb as we want to receive
3350 session keepalives and then drop them here.
3352 if (FD_ISSET(Client,&fds))
3353 receive_smb(Client,buffer,0);
3360 chkpath("\\",False);
3363 chkpath("\\",False);
3369 /****************************************************************************
3370 process commands from the client
3371 ****************************************************************************/
3372 static BOOL process(char *base_directory)
3378 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3379 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3381 if ((InBuffer == NULL) || (OutBuffer == NULL))
3384 bzero(OutBuffer,smb_size);
3386 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3389 if (*base_directory) do_cd(base_directory);
3392 if (cmd[0] != '\0') while (cmd[0] != '\0')
3398 if ((p = strchr(cmd, ';')) == 0)
3400 strncpy(line, cmd, 999);
3406 if (p - cmd > 999) p = cmd + 999;
3407 strncpy(line, cmd, p - cmd);
3408 line[p - cmd] = '\0';
3412 /* input language code to internal one */
3415 /* and get the first part of the command */
3418 if (!next_token(&ptr,tok,NULL)) continue;
3421 if ((i = process_tok(tok)) >= 0)
3422 commands[i].fn(InBuffer,OutBuffer);
3424 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3426 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3428 else while (!feof(stdin))
3433 bzero(OutBuffer,smb_size);
3435 /* display a prompt */
3436 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3440 line[0] = wait_keyboard(InBuffer);
3441 /* this might not be such a good idea... */
3442 if ( line[0] == EOF)
3445 wait_keyboard(InBuffer);
3448 /* and get a response */
3450 fgets( &line[1],999, stdin);
3452 if (!fgets(line,1000,stdin))
3456 /* input language code to internal one */
3459 /* special case - first char is ! */
3466 /* and get the first part of the command */
3469 if (!next_token(&ptr,tok,NULL)) continue;
3472 if ((i = process_tok(tok)) >= 0)
3473 commands[i].fn(InBuffer,OutBuffer);
3475 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3477 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3484 /****************************************************************************
3485 usage on the program
3486 ****************************************************************************/
3487 static void usage(char *pname)
3489 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3492 DEBUG(0,("\nVersion %s\n",VERSION));
3493 DEBUG(0,("\t-p port connect to the specified port\n"));
3494 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3495 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3496 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3497 DEBUG(0,("\t-N don't ask for a password\n"));
3498 DEBUG(0,("\t-P connect to service as a printer\n"));
3499 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3500 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3501 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3502 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3503 DEBUG(0,("\t-R name resolve order use these name resolution services only\n"));
3504 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3505 DEBUG(0,("\t-U username set the network username\n"));
3506 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3507 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3508 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3509 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
3510 DEBUG(0,("\t-D directory start from directory\n"));
3514 /****************************************************************************
3516 ****************************************************************************/
3517 int main(int argc,char *argv[])
3519 fstring base_directory;
3520 char *pname = argv[0];
3521 int port = SMB_PORT;
3524 extern char *optarg;
3527 BOOL message = False;
3528 BOOL nt_domain_logon = False;
3529 extern char tar_type;
3530 static pstring servicesf = CONFIGFILE;
3532 pstring new_name_resolve_order;
3534 int save_debuglevel = -1;
3537 strcpy(term_code, KANJI);
3543 *base_directory = 0;
3545 *new_name_resolve_order = 0;
3549 setup_logging(pname,True);
3552 charset_initialise();
3563 strcpy(username,getenv("USER"));
3565 /* modification to support userid%passwd syntax in the USER var
3566 25.Aug.97, jdblair@uab.edu */
3568 if ((p=strchr(username,'%')))
3571 strcpy(password,p+1);
3573 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3578 /* modification to support PASSWD environmental var
3579 25.Aug.97, jdblair@uab.edu */
3581 if (getenv("PASSWD"))
3582 strcpy(password,getenv("PASSWD"));
3584 if (*username == 0 && getenv("LOGNAME"))
3586 strcpy(username,getenv("LOGNAME"));
3596 if (*argv[1] != '-')
3599 strcpy(service,argv[1]);
3600 /* Convert any '/' characters in the service name to '\' characters */
3601 string_replace( service, '/','\\');
3605 if (count_chars(service,'\\') < 3)
3608 printf("\n%s: Not enough '\\' characters in service\n",service);
3613 if (count_chars(service,'\\') > 3)
3616 printf("\n%s: Too many '\\' characters in service\n",service);
3621 if (argc > 1 && (*argv[1] != '-'))
3624 strcpy(password,argv[1]);
3625 memset(argv[1],'X',strlen(argv[1]));
3632 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)
3636 max_protocol = interpret_protocol(optarg,max_protocol);
3639 strcpy(user_socket_options,optarg);
3642 pstrcpy(new_name_resolve_order, optarg);
3645 strcpy(desthost,optarg);
3647 nt_domain_logon = True;
3650 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3651 strcpy(desthost,optarg);
3656 iface_set_default(NULL,optarg,NULL);
3659 strcpy(base_directory,optarg);
3662 if (!tar_parseargs(argc, argv, optarg, optind)) {
3668 strcpy(scope,optarg);
3672 strcpy(query_host,optarg);
3677 strcpy(username,optarg);
3678 if ((lp=strchr(username,'%')))
3681 strcpy(password,lp+1);
3683 memset(strchr(optarg,'%')+1,'X',strlen(password));
3689 strcpy(workgroup,optarg);
3696 dest_ip = *interpret_addr2(optarg);
3697 if (zero_ip(dest_ip)) exit(1);
3702 strcpy(myname,optarg);
3709 connect_as_printer = True;
3713 save_debuglevel = DEBUGLEVEL = 10000;
3715 save_debuglevel = DEBUGLEVEL = atoi(optarg);
3718 sprintf(debugf,"%s.client",optarg);
3721 port = atoi(optarg);
3732 strcpy(servicesf, optarg);
3735 strcpy(term_code, optarg);
3742 if (!tar_type && !*query_host && !*service && !message)
3749 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
3751 if(!get_myname(myhostname,NULL))
3753 DEBUG(0,("Failed to get my hostname.\n"));
3756 if (!lp_load(servicesf,True,False,False)) {
3757 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3761 * We need to reset the global debuglevel here, as
3762 * lp_load will reset it from smb.conf.
3765 if(save_debuglevel != -1)
3766 DEBUGLEVEL = save_debuglevel;
3768 codepage_initialise(lp_client_code_page());
3770 interpret_coding_system(term_code);
3772 if (*workgroup == 0)
3773 strcpy(workgroup,lp_workgroup());
3776 get_myname((*myname)?NULL:myname,NULL);
3779 if(*new_name_resolve_order)
3780 lp_set_name_resolve_order(new_name_resolve_order);
3785 if (cli_open_sockets(port)) {
3786 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3787 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3790 if ((InBuffer == NULL) || (OutBuffer == NULL))
3793 bzero(OutBuffer,smb_size);
3794 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3797 if (*base_directory) do_cd(base_directory);
3799 ret=process_tar(InBuffer, OutBuffer);
3808 if (*query_host && !nt_domain_logon)
3811 sprintf(service,"\\\\%s\\IPC$",query_host);
3813 connect_as_ipc = True;
3814 if (cli_open_sockets(port))
3819 if (!cli_send_login(NULL,NULL,True,True,NULL))
3823 if (!browse_host(True)) {
3827 if (!list_servers(workgroup)) {
3829 list_servers(workgroup);
3842 if (cli_open_sockets(port))
3844 pstring inbuf,outbuf;
3845 bzero(outbuf,smb_size);
3846 if (!cli_send_session_request(inbuf,outbuf))
3849 send_message(inbuf,outbuf);
3857 if (cli_open_sockets(port))
3859 if (!process(base_directory))