Fixed up more possibly uninitialized variables.
[Samba/gbeck.git] / source3 / client / client.c
blob5d3f497ab1e6cdd90a5b80076be02b73147018ea
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB client
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.
22 #define NO_SYSLOG
24 #include "includes.h"
26 #ifndef REGISTER
27 #define REGISTER 0
28 #endif
30 pstring cur_dir = "\\";
31 pstring cd_path = "";
32 extern pstring service;
33 extern pstring desthost;
34 extern pstring global_myname;
35 extern pstring myhostname;
36 extern pstring password;
37 extern pstring username;
38 extern pstring workgroup;
39 char *cmdstr="";
40 extern BOOL got_pass;
41 extern BOOL no_pass;
42 extern BOOL connect_as_printer;
43 extern BOOL connect_as_ipc;
44 extern struct in_addr ipzero;
46 extern BOOL doencrypt;
48 extern pstring user_socket_options;
50 static int process_tok(fstring tok);
51 static void cmd_help(char *dum_in, char *dum_out);
53 /* 30 second timeout on most commands */
54 #define CLIENT_TIMEOUT (30*1000)
55 #define SHORT_TIMEOUT (5*1000)
57 /* value for unused fid field in trans2 secondary request */
58 #define FID_UNUSED (0xFFFF)
60 extern int name_type;
62 extern int max_protocol;
65 time_t newer_than = 0;
66 int archive_level = 0;
68 extern pstring debugf;
69 extern int DEBUGLEVEL;
71 BOOL translation = False;
73 extern int cnum;
74 extern int mid;
75 extern int pid;
76 extern int tid;
77 extern int gid;
78 extern int uid;
80 extern BOOL have_ip;
81 extern int max_xmit;
83 static int interpret_long_filename(int level,char *p,file_info *finfo);
84 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo);
85 static int interpret_short_filename(char *p,file_info *finfo);
86 static BOOL do_this_one(file_info *finfo);
88 /* clitar bits insert */
89 extern int blocksize;
90 extern BOOL tar_inc;
91 extern BOOL tar_reset;
92 /* clitar bits end */
95 int myumask = 0755;
97 extern pstring scope;
99 BOOL prompt = True;
101 int printmode = 1;
103 BOOL recurse = False;
104 BOOL lowercase = False;
106 struct in_addr dest_ip;
108 #define SEPARATORS " \t\n\r"
110 BOOL abort_mget = True;
112 extern int Protocol;
114 extern BOOL readbraw_supported ;
115 extern BOOL writebraw_supported;
117 pstring fileselection = "";
119 extern file_info def_finfo;
121 /* timing globals */
122 int get_total_size = 0;
123 int get_total_time_ms = 0;
124 int put_total_size = 0;
125 int put_total_time_ms = 0;
127 /* totals globals */
128 int dir_total = 0;
130 extern int Client;
132 #define USENMB
134 #define CNV_LANG(s) dos_to_unix(s,False)
135 #define CNV_INPUT(s) unix_to_dos(s,True)
137 /****************************************************************************
138 send an SMBclose on an SMB file handle
139 ****************************************************************************/
140 static void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
142 bzero(outbuf,smb_size);
143 set_message(outbuf,3,0,True);
145 CVAL (outbuf,smb_com) = SMBclose;
146 SSVAL(outbuf,smb_tid,c_num);
147 cli_setup_pkt(outbuf);
148 SSVAL (outbuf,smb_vwv0, f_num);
149 SIVALS(outbuf,smb_vwv1, -1);
151 send_smb(clnt_fd, outbuf);
152 client_receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
156 /****************************************************************************
157 write to a local file with CR/LF->LF translation if appropriate. return the
158 number taken from the buffer. This may not equal the number written.
159 ****************************************************************************/
160 static int writefile(int f, char *b, int n)
162 int i;
164 if (!translation)
165 return(write(f,b,n));
167 i = 0;
168 while (i < n)
170 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
172 b++;i++;
174 if (write(f, b, 1) != 1)
176 break;
178 b++;
179 i++;
182 return(i);
185 /****************************************************************************
186 read from a file with LF->CR/LF translation if appropriate. return the
187 number read. read approx n bytes.
188 ****************************************************************************/
189 static int readfile(char *b, int size, int n, FILE *f)
191 int i;
192 int c;
194 if (!translation || (size != 1))
195 return(fread(b,size,n,f));
197 i = 0;
198 while (i < n)
200 if ((c = getc(f)) == EOF)
202 break;
205 if (c == '\n') /* change all LFs to CR/LF */
207 b[i++] = '\r';
208 n++;
211 if(i < n)
212 b[i++] = c;
215 return(i);
219 /****************************************************************************
220 read from a file with print translation. return the number read. read approx n
221 bytes.
222 ****************************************************************************/
223 static int printread(FILE *f,char *b,int n)
225 int i;
227 i = readfile(b,1, n-1,f);
228 #if FORMFEED
229 if (feof(f) && i>0)
230 b[i++] = '\014';
231 #endif
233 return(i);
236 /****************************************************************************
237 check for existance of a dir
238 ****************************************************************************/
239 static BOOL chkpath(char *path,BOOL report)
241 fstring path2;
242 pstring inbuf,outbuf;
243 char *p;
245 fstrcpy(path2,path);
246 trim_string(path2,NULL,"\\");
247 if (!*path2) *path2 = '\\';
249 bzero(outbuf,smb_size);
250 set_message(outbuf,0,4 + strlen(path2),True);
251 SCVAL(outbuf,smb_com,SMBchkpth);
252 SSVAL(outbuf,smb_tid,cnum);
253 cli_setup_pkt(outbuf);
255 p = smb_buf(outbuf);
256 *p++ = 4;
257 fstrcpy(p,path2);
259 #if 0
261 /* this little bit of code can be used to extract NT error codes.
262 Just feed a bunch of "cd foo" commands to smbclient then watch
263 in netmon (tridge) */
264 static int code=0;
265 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
266 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
267 code++;
269 #endif
271 send_smb(Client,outbuf);
272 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
274 if (report && CVAL(inbuf,smb_rcls) != 0)
275 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
277 return(CVAL(inbuf,smb_rcls) == 0);
281 /****************************************************************************
282 send a message
283 ****************************************************************************/
284 static void send_message(char *inbuf,char *outbuf)
286 int total_len = 0;
288 char *p;
289 int grp_id;
291 /* send a SMBsendstrt command */
292 bzero(outbuf,smb_size);
293 set_message(outbuf,0,0,True);
294 CVAL(outbuf,smb_com) = SMBsendstrt;
295 SSVAL(outbuf,smb_tid,cnum);
297 p = smb_buf(outbuf);
298 *p++ = 4;
299 pstrcpy(p,username);
300 p = skip_string(p,1);
301 *p++ = 4;
302 pstrcpy(p,desthost);
303 p = skip_string(p,1);
305 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
307 send_smb(Client,outbuf);
310 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
312 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
313 return;
316 grp_id = SVAL(inbuf,smb_vwv0);
318 printf("Connected. Type your message, ending it with a Control-D\n");
320 while (!feof(stdin) && total_len < 1600)
322 int maxlen = MIN(1600 - total_len,127);
323 pstring msg;
324 int l=0;
325 int c;
327 bzero(msg,smb_size);
329 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
331 if (c == '\n')
332 msg[l++] = '\r';
333 msg[l] = c;
336 CVAL(outbuf,smb_com) = SMBsendtxt;
338 set_message(outbuf,1,l+3,True);
340 SSVAL(outbuf,smb_vwv0,grp_id);
342 p = smb_buf(outbuf);
343 *p = 1;
344 SSVAL(p,1,l);
345 memcpy(p+3,msg,l);
347 send_smb(Client,outbuf);
350 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
352 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
353 return;
356 total_len += l;
359 if (total_len >= 1600)
360 printf("the message was truncated to 1600 bytes ");
361 else
362 printf("sent %d bytes ",total_len);
364 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
366 CVAL(outbuf,smb_com) = SMBsendend;
367 set_message(outbuf,1,0,False);
368 SSVAL(outbuf,smb_vwv0,grp_id);
370 send_smb(Client,outbuf);
373 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
375 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
376 return;
382 /****************************************************************************
383 check the space on a device
384 ****************************************************************************/
385 static void do_dskattr(void)
387 pstring inbuf,outbuf;
389 bzero(outbuf,smb_size);
390 set_message(outbuf,0,0,True);
391 CVAL(outbuf,smb_com) = SMBdskattr;
392 SSVAL(outbuf,smb_tid,cnum);
393 cli_setup_pkt(outbuf);
395 send_smb(Client,outbuf);
396 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
398 if (CVAL(inbuf,smb_rcls) != 0)
399 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
401 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
402 SVAL(inbuf,smb_vwv0),
403 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
404 SVAL(inbuf,smb_vwv3)));
407 /****************************************************************************
408 show cd/pwd
409 ****************************************************************************/
410 static void cmd_pwd(char *dum_in, char *dum_out)
412 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
413 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
417 /****************************************************************************
418 change directory - inner section
419 ****************************************************************************/
420 static void do_cd(char *newdir)
422 char *p = newdir;
423 pstring saved_dir;
424 pstring dname;
426 /* Save the current directory in case the
427 new directory is invalid */
428 pstrcpy(saved_dir, cur_dir);
429 if (*p == '\\')
430 pstrcpy(cur_dir,p);
431 else
432 pstrcat(cur_dir,p);
433 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
434 pstrcat(cur_dir, "\\");
436 dos_clean_name(cur_dir);
437 pstrcpy(dname,cur_dir);
438 pstrcat(cur_dir,"\\");
439 dos_clean_name(cur_dir);
441 if (!strequal(cur_dir,"\\"))
442 if (!chkpath(dname,True))
443 pstrcpy(cur_dir,saved_dir);
445 pstrcpy(cd_path,cur_dir);
448 /****************************************************************************
449 change directory
450 ****************************************************************************/
451 static void cmd_cd(char *inbuf,char *outbuf)
453 fstring buf;
455 if (next_token(NULL,buf,NULL,sizeof(buf)))
456 do_cd(buf);
457 else
458 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
462 /****************************************************************************
463 display info about a file
464 ****************************************************************************/
465 static void display_finfo(file_info *finfo)
467 if (do_this_one(finfo)) {
468 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
469 DEBUG(0,(" %-30s%7.7s%.0f %s",
470 CNV_LANG(finfo->name),
471 attrib_string(finfo->mode),
472 (double)finfo->size,
473 asctime(LocalTime(&t))));
474 dir_total += finfo->size;
479 /****************************************************************************
480 calculate size of a file
481 ****************************************************************************/
482 static void do_du(file_info *finfo)
484 if (do_this_one(finfo)) {
485 dir_total += finfo->size;
490 /****************************************************************************
491 do a directory listing, calling fn on each file found. Use the TRANSACT2
492 call for long filenames
493 ****************************************************************************/
494 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
496 int max_matches = 512;
497 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
498 char *p;
499 pstring mask;
500 file_info finfo;
501 int i;
502 char *dirlist = NULL;
503 int dirlist_len = 0;
504 int total_received = 0;
505 BOOL First = True;
506 char *resp_data=NULL;
507 char *resp_param=NULL;
508 int resp_data_len = 0;
509 int resp_param_len=0;
511 int ff_resume_key = 0;
512 int ff_searchcount=0;
513 int ff_eos=0;
514 int ff_lastname=0;
515 int ff_dir_handle=0;
516 int loop_count = 0;
518 uint16 setup;
519 pstring param;
521 pstrcpy(mask,Mask);
523 while (ff_eos == 0)
525 loop_count++;
526 if (loop_count > 200)
528 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
529 break;
532 if (First)
534 setup = TRANSACT2_FINDFIRST;
535 SSVAL(param,0,attribute); /* attribute */
536 SSVAL(param,2,max_matches); /* max count */
537 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
538 SSVAL(param,6,info_level);
539 SIVAL(param,8,0);
540 pstrcpy(param+12,mask);
542 else
544 setup = TRANSACT2_FINDNEXT;
545 SSVAL(param,0,ff_dir_handle);
546 SSVAL(param,2,max_matches); /* max count */
547 SSVAL(param,4,info_level);
548 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
549 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
550 pstrcpy(param+12,mask);
552 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
553 ff_dir_handle,ff_resume_key,ff_lastname,mask));
555 /* ??? original code added 1 pad byte after param */
557 cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
558 NULL,param,&setup,
559 0,12+strlen(mask)+1,1,
560 BUFFER_SIZE,10,0);
562 if (!cli_receive_trans_response(inbuf,SMBtrans2,
563 &resp_data_len,&resp_param_len,
564 &resp_data,&resp_param))
566 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
567 break;
570 /* parse out some important return info */
571 p = resp_param;
572 if (First)
574 ff_dir_handle = SVAL(p,0);
575 ff_searchcount = SVAL(p,2);
576 ff_eos = SVAL(p,4);
577 ff_lastname = SVAL(p,8);
579 else
581 ff_searchcount = SVAL(p,0);
582 ff_eos = SVAL(p,2);
583 ff_lastname = SVAL(p,6);
586 if (ff_searchcount == 0)
587 break;
589 /* point to the data bytes */
590 p = resp_data;
592 /* we might need the lastname for continuations */
593 if (ff_lastname > 0)
595 switch(info_level)
597 case 260:
598 ff_resume_key =0;
599 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
600 /* pstrcpy(mask,p+ff_lastname+94); */
601 break;
602 case 1:
603 pstrcpy(mask,p + ff_lastname + 1);
604 ff_resume_key = 0;
605 break;
608 else
609 pstrcpy(mask,"");
611 /* and add them to the dirlist pool */
612 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
614 if (!dirlist)
616 DEBUG(0,("Failed to expand dirlist\n"));
617 break;
620 /* put in a length for the last entry, to ensure we can chain entries
621 into the next packet */
623 char *p2;
624 for (p2=p,i=0;i<(ff_searchcount-1);i++)
625 p2 += interpret_long_filename(info_level,p2,NULL);
626 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
629 /* grab the data for later use */
630 memcpy(dirlist+dirlist_len,p,resp_data_len);
631 dirlist_len += resp_data_len;
633 total_received += ff_searchcount;
635 if (resp_data) free(resp_data); resp_data = NULL;
636 if (resp_param) free(resp_param); resp_param = NULL;
638 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
639 ff_searchcount,ff_eos,ff_resume_key));
641 First = False;
644 if (!fn)
645 for (p=dirlist,i=0;i<total_received;i++)
647 p += interpret_long_filename(info_level,p,&finfo);
648 display_finfo(&finfo);
651 for (p=dirlist,i=0;i<total_received;i++)
653 p += interpret_long_filename(info_level,p,&finfo);
654 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True, dirstoo);
657 /* free up the dirlist buffer */
658 if (dirlist) free(dirlist);
659 return(total_received);
663 /****************************************************************************
664 do a directory listing, calling fn on each file found
665 ****************************************************************************/
666 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
668 char *p;
669 int received = 0;
670 BOOL first = True;
671 char status[21];
672 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
673 int num_received = 0;
674 int i;
675 char *dirlist = NULL;
676 pstring mask;
677 file_info finfo;
679 finfo = def_finfo;
681 bzero(status,21);
683 pstrcpy(mask,Mask);
685 while (1)
687 bzero(outbuf,smb_size);
688 if (first)
689 set_message(outbuf,2,5 + strlen(mask),True);
690 else
691 set_message(outbuf,2,5 + 21,True);
693 #if FFIRST
694 if (Protocol >= PROTOCOL_LANMAN1)
695 CVAL(outbuf,smb_com) = SMBffirst;
696 else
697 #endif
698 CVAL(outbuf,smb_com) = SMBsearch;
700 SSVAL(outbuf,smb_tid,cnum);
701 cli_setup_pkt(outbuf);
703 SSVAL(outbuf,smb_vwv0,num_asked);
704 SSVAL(outbuf,smb_vwv1,attribute);
706 p = smb_buf(outbuf);
707 *p++ = 4;
709 if (first)
710 pstrcpy(p,mask);
711 else
712 pstrcpy(p,"");
713 p += strlen(p) + 1;
715 *p++ = 5;
716 if (first)
717 SSVAL(p,0,0);
718 else
720 SSVAL(p,0,21);
721 p += 2;
722 memcpy(p,status,21);
725 send_smb(Client,outbuf);
726 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
728 received = SVAL(inbuf,smb_vwv0);
730 DEBUG(5,("dir received %d\n",received));
732 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
734 if (received <= 0) break;
736 first = False;
738 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
740 if (!dirlist)
741 return 0;
743 p = smb_buf(inbuf) + 3;
745 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
746 p,received*DIR_STRUCT_SIZE);
748 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
750 num_received += received;
752 if (CVAL(inbuf,smb_rcls) != 0) break;
755 #if FFIRST
756 if (!first && Protocol >= PROTOCOL_LANMAN1)
758 bzero(outbuf,smb_size);
759 CVAL(outbuf,smb_com) = SMBfclose;
761 SSVAL(outbuf,smb_tid,cnum);
762 cli_setup_pkt(outbuf);
764 p = smb_buf(outbuf);
765 *p++ = 4;
767 pstrcpy(p,"");
768 p += strlen(p) + 1;
770 *p++ = 5;
771 SSVAL(p,0,21);
772 p += 2;
773 memcpy(p,status,21);
775 send_smb(Client,outbuf);
776 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
778 if (CVAL(inbuf,smb_rcls) != 0)
779 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
781 #endif
783 if (!fn)
784 for (p=dirlist,i=0;i<num_received;i++)
786 p += interpret_short_filename(p,&finfo);
787 display_finfo(&finfo);
790 for (p=dirlist,i=0;i<num_received;i++)
792 p += interpret_short_filename(p,&finfo);
793 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False,dirstoo);
796 if (dirlist) free(dirlist);
797 return(num_received);
802 /****************************************************************************
803 do a directory listing, calling fn on each file found
804 ****************************************************************************/
805 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
807 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
808 if (Protocol >= PROTOCOL_LANMAN2)
810 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo) > 0)
811 return;
814 expand_mask(Mask,False);
815 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo);
816 return;
819 /*******************************************************************
820 decide if a file should be operated on
821 ********************************************************************/
822 static BOOL do_this_one(file_info *finfo)
824 if (finfo->mode & aDIR) return(True);
826 if (newer_than && finfo->mtime < newer_than)
827 return(False);
829 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
830 return(False);
832 return(True);
836 /*****************************************************************************
837 Convert a character pointer in a cli_call_api() response to a form we can use.
838 This function contains code to prevent core dumps if the server returns
839 invalid data.
840 *****************************************************************************/
841 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
843 if( datap == 0 ) /* turn NULL pointers */
844 { /* into zero length strings */
845 return "";
847 else
849 unsigned int offset = datap - converter;
851 if( offset >= rdrcnt )
853 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
854 return "<ERROR>";
856 else
858 return &rdata[offset];
863 /****************************************************************************
864 interpret a short filename structure
865 The length of the structure is returned
866 ****************************************************************************/
867 static int interpret_short_filename(char *p,file_info *finfo)
869 finfo->mode = CVAL(p,21);
871 /* this date is converted to GMT by make_unix_date */
872 finfo->ctime = make_unix_date(p+22);
873 finfo->mtime = finfo->atime = finfo->ctime;
874 finfo->size = IVAL(p,26);
875 pstrcpy(finfo->name,p+30);
877 return(DIR_STRUCT_SIZE);
880 /****************************************************************************
881 interpret a long filename structure - this is mostly guesses at the moment
882 The length of the structure is returned
883 The structure of a long filename depends on the info level. 260 is used
884 by NT and 2 is used by OS/2
885 ****************************************************************************/
886 static int interpret_long_filename(int level,char *p,file_info *finfo)
888 if (finfo)
889 memcpy(finfo,&def_finfo,sizeof(*finfo));
891 switch (level)
893 case 1: /* OS/2 understands this */
894 if (finfo)
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 pstrcpy(finfo->name,p+27);
904 return(28 + CVAL(p,26));
906 case 2: /* this is what OS/2 uses mostly */
907 if (finfo)
909 /* these dates are converted to GMT by make_unix_date */
910 finfo->ctime = make_unix_date2(p+4);
911 finfo->atime = make_unix_date2(p+8);
912 finfo->mtime = make_unix_date2(p+12);
913 finfo->size = IVAL(p,16);
914 finfo->mode = CVAL(p,24);
915 pstrcpy(finfo->name,p+31);
917 return(32 + CVAL(p,30));
919 /* levels 3 and 4 are untested */
920 case 3:
921 if (finfo)
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 pstrcpy(finfo->name,p+33);
931 return(SVAL(p,4)+4);
933 case 4:
934 if (finfo)
936 /* these dates are probably like the other ones */
937 finfo->ctime = make_unix_date2(p+8);
938 finfo->atime = make_unix_date2(p+12);
939 finfo->mtime = make_unix_date2(p+16);
940 finfo->size = IVAL(p,20);
941 finfo->mode = CVAL(p,28);
942 pstrcpy(finfo->name,p+37);
944 return(SVAL(p,4)+4);
946 case 260: /* NT uses this, but also accepts 2 */
947 if (finfo)
949 int ret = SVAL(p,0);
950 int namelen;
951 p += 4; /* next entry offset */
952 p += 4; /* fileindex */
954 /* these dates appear to arrive in a weird way. It seems to
955 be localtime plus the serverzone given in the initial
956 connect. This is GMT when DST is not in effect and one
957 hour from GMT otherwise. Can this really be right??
959 I suppose this could be called kludge-GMT. Is is the GMT
960 you get by using the current DST setting on a different
961 localtime. It will be cheap to calculate, I suppose, as
962 no DST tables will be needed */
964 finfo->ctime = interpret_long_date(p); p += 8;
965 finfo->atime = interpret_long_date(p); p += 8;
966 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
967 finfo->size = IVAL(p,0); p += 8;
968 p += 8; /* alloc size */
969 finfo->mode = CVAL(p,0); p += 4;
970 namelen = IVAL(p,0); p += 4;
971 p += 4; /* EA size */
972 p += 2; /* short name len? */
973 p += 24; /* short name? */
974 StrnCpy(finfo->name,p,namelen);
975 return(ret);
977 return(SVAL(p,0));
980 DEBUG(1,("Unknown long filename format %d\n",level));
981 return(SVAL(p,0));
987 /****************************************************************************
988 act on the files in a dir listing
990 RJS, 4-Apr-1998, dirstoo added to allow caller to indicate that directories
991 should be processed as well.
992 ****************************************************************************/
993 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo)
996 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
997 !mask_match(finfo->name,fileselection,False,False)) &&
998 !(recurse_dir && (strequal(finfo->name,".") ||
999 strequal(finfo->name,".."))))
1001 if (recurse_dir && (finfo->mode & aDIR))
1003 pstring mask2;
1004 pstring sav_dir;
1006 if (fn && dirstoo && do_this_one(finfo)) { /* Do dirs, RJS */
1007 fn(finfo);
1010 pstrcpy(sav_dir,cur_dir);
1011 pstrcat(cur_dir,finfo->name);
1012 pstrcat(cur_dir,"\\");
1013 pstrcpy(mask2,cur_dir);
1015 if (!fn)
1016 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1018 pstrcat(mask2,"*");
1020 if (longdir)
1021 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1022 else
1023 do_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1025 pstrcpy(cur_dir,sav_dir);
1027 else
1029 if (fn && do_this_one(finfo))
1030 fn(finfo);
1036 /****************************************************************************
1037 get a directory listing
1038 ****************************************************************************/
1039 static void cmd_dir(char *inbuf,char *outbuf)
1041 int attribute = aDIR | aSYSTEM | aHIDDEN;
1042 pstring mask;
1043 fstring buf;
1044 char *p=buf;
1046 dir_total = 0;
1047 pstrcpy(mask,cur_dir);
1048 if(mask[strlen(mask)-1]!='\\')
1049 pstrcat(mask,"\\");
1051 if (next_token(NULL,buf,NULL,sizeof(buf)))
1053 if (*p == '\\')
1054 pstrcpy(mask,p);
1055 else
1056 pstrcat(mask,p);
1058 else {
1059 pstrcat(mask,"*");
1062 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse,False);
1064 do_dskattr();
1066 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1070 /****************************************************************************
1071 get a directory listing
1072 ****************************************************************************/
1073 static void cmd_du(char *inbuf,char *outbuf)
1075 int attribute = aDIR | aSYSTEM | aHIDDEN;
1076 pstring mask;
1077 fstring buf;
1078 char *p=buf;
1080 dir_total = 0;
1081 pstrcpy(mask,cur_dir);
1082 if(mask[strlen(mask)-1]!='\\')
1083 pstrcat(mask,"\\");
1085 if (next_token(NULL,buf,NULL,sizeof(buf)))
1087 if (*p == '\\')
1088 pstrcpy(mask,p);
1089 else
1090 pstrcat(mask,p);
1092 else {
1093 pstrcat(mask,"*");
1096 do_dir(inbuf,outbuf,mask,attribute,do_du,recurse,False);
1098 do_dskattr();
1100 DEBUG(0, ("Total number of bytes: %d\n", dir_total));
1103 /****************************************************************************
1104 get a file from rname to lname
1105 ****************************************************************************/
1106 static void do_get(char *rname,char *lname,file_info *finfo1)
1108 int handle=0,fnum;
1109 uint32 nread=0;
1110 char *p;
1111 BOOL newhandle = False;
1112 char *inbuf,*outbuf;
1113 file_info finfo;
1114 BOOL close_done = False;
1115 BOOL ignore_close_error = False;
1116 char *dataptr=NULL;
1117 int datalen=0;
1119 struct timeval tp_start;
1120 GetTimeOfDay(&tp_start);
1122 if (finfo1)
1123 finfo = *finfo1;
1124 else
1125 finfo = def_finfo;
1127 if (lowercase)
1128 strlower(lname);
1131 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1132 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1134 if (!inbuf || !outbuf)
1136 DEBUG(0,("out of memory\n"));
1137 return;
1140 bzero(outbuf,smb_size);
1141 set_message(outbuf,15,1 + strlen(rname),True);
1143 CVAL(outbuf,smb_com) = SMBopenX;
1144 SSVAL(outbuf,smb_tid,cnum);
1145 cli_setup_pkt(outbuf);
1147 SSVAL(outbuf,smb_vwv0,0xFF);
1148 SSVAL(outbuf,smb_vwv2,1); /* return additional info */
1149 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1150 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1151 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1152 SSVAL(outbuf,smb_vwv8,1);
1153 SSVAL(outbuf,smb_vwv11,0xffff);
1154 SSVAL(outbuf,smb_vwv12,0xffff);
1156 p = smb_buf(outbuf);
1157 pstrcpy(p,rname);
1158 p = skip_string(p,1);
1160 /* do a chained openX with a readX? */
1161 #if 1
1162 if (finfo.size > 0)
1164 DEBUG(3,("Chaining readX wth openX\n"));
1165 SSVAL(outbuf,smb_vwv0,SMBreadX);
1166 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1167 bzero(p,200);
1168 p -= smb_wct;
1169 SCVAL(p,smb_wct,10);
1170 SSVAL(p,smb_vwv0,0xFF);
1171 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1172 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1173 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1175 #endif
1177 if(!strcmp(lname,"-"))
1178 handle = fileno(stdout);
1179 else
1181 handle = creat(lname,0644);
1182 newhandle = True;
1184 if (handle < 0)
1186 DEBUG(0,("Error opening local file %s\n",lname));
1187 free(inbuf);free(outbuf);
1188 return;
1191 send_smb(Client,outbuf);
1192 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1194 if (CVAL(inbuf,smb_rcls) != 0)
1196 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1197 SVAL(inbuf,smb_err) == ERRnoresource &&
1198 cli_reopen_connection(inbuf,outbuf))
1200 do_get(rname,lname,finfo1);
1201 return;
1203 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1204 if(newhandle)
1205 close(handle);
1206 free(inbuf);free(outbuf);
1207 return;
1210 pstrcpy(finfo.name,rname);
1212 if (!finfo1)
1214 finfo.mode = SVAL(inbuf,smb_vwv3);
1215 /* these times arrive as LOCAL time, using the DST offset
1216 corresponding to that time, we convert them to GMT */
1217 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1218 finfo.atime = finfo.ctime = finfo.mtime;
1219 finfo.size = IVAL(inbuf,smb_vwv6);
1222 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1224 fnum = SVAL(inbuf,smb_vwv2);
1226 /* we might have got some data from a chained readX */
1227 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1229 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1230 datalen = SVAL(p,smb_vwv5);
1231 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1233 else
1235 dataptr = NULL;
1236 datalen = 0;
1240 DEBUG(2,("getting file %s of size %.0f bytes as %s ",
1241 CNV_LANG(finfo.name),
1242 (double)finfo.size,
1243 lname));
1245 while (nread < finfo.size && !close_done)
1247 int method = -1;
1248 static BOOL can_chain_close = True;
1250 p=NULL;
1252 DEBUG(3,("nread=%d max_xmit=%d fsize=%.0f\n",nread,max_xmit,(double)finfo.size));
1254 /* 3 possible read types. readbraw if a large block is required.
1255 readX + close if not much left and read if neither is supported */
1257 /* we might have already read some data from a chained readX */
1258 if (dataptr && datalen>0)
1259 method=3;
1261 /* if we can finish now then readX+close */
1262 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1263 ((finfo.size - nread) <
1264 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1265 method = 0;
1267 /* if we support readraw then use that */
1268 if (method<0 && readbraw_supported)
1269 method = 1;
1271 /* if we can then use readX */
1272 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1273 method = 2;
1275 switch (method)
1277 /* use readX */
1278 case 0:
1279 case 2:
1280 if (method == 0)
1281 close_done = True;
1283 /* use readX + close */
1284 bzero(outbuf,smb_size);
1285 set_message(outbuf,10,0,True);
1286 CVAL(outbuf,smb_com) = SMBreadX;
1287 SSVAL(outbuf,smb_tid,cnum);
1288 cli_setup_pkt(outbuf);
1290 if (close_done)
1292 CVAL(outbuf,smb_vwv0) = SMBclose;
1293 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1295 else
1296 CVAL(outbuf,smb_vwv0) = 0xFF;
1298 SSVAL(outbuf,smb_vwv2,fnum);
1299 SIVAL(outbuf,smb_vwv3,nread);
1300 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1301 SSVAL(outbuf,smb_vwv6,0);
1302 SIVAL(outbuf,smb_vwv7,0);
1303 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1305 if (close_done)
1307 p = smb_buf(outbuf);
1308 bzero(p,9);
1310 CVAL(p,0) = 3;
1311 SSVAL(p,1,fnum);
1312 SIVALS(p,3,-1);
1314 /* now set the total packet length */
1315 smb_setlen(outbuf,smb_len(outbuf)+9);
1318 send_smb(Client,outbuf);
1319 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1321 if (CVAL(inbuf,smb_rcls) != 0)
1323 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1324 break;
1327 if (close_done &&
1328 SVAL(inbuf,smb_vwv0) != SMBclose)
1330 /* NOTE: WfWg sometimes just ignores the chained
1331 command! This seems to break the spec? */
1332 DEBUG(3,("Rejected chained close?\n"));
1333 close_done = False;
1334 can_chain_close = False;
1335 ignore_close_error = True;
1338 datalen = SVAL(inbuf,smb_vwv5);
1339 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1340 break;
1342 /* use readbraw */
1343 case 1:
1345 static int readbraw_size = BUFFER_SIZE;
1347 extern int Client;
1348 bzero(outbuf,smb_size);
1349 set_message(outbuf,8,0,True);
1350 CVAL(outbuf,smb_com) = SMBreadbraw;
1351 SSVAL(outbuf,smb_tid,cnum);
1352 cli_setup_pkt(outbuf);
1353 SSVAL(outbuf,smb_vwv0,fnum);
1354 SIVAL(outbuf,smb_vwv1,nread);
1355 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1356 SSVAL(outbuf,smb_vwv4,0);
1357 SIVALS(outbuf,smb_vwv5,-1);
1358 send_smb(Client,outbuf);
1360 /* Now read the raw data into the buffer and write it */
1361 if(read_smb_length(Client,inbuf,0) == -1) {
1362 DEBUG(0,("Failed to read length in readbraw\n"));
1363 exit(1);
1366 /* Even though this is not an smb message, smb_len
1367 returns the generic length of an smb message */
1368 datalen = smb_len(inbuf);
1370 if (datalen == 0)
1372 /* we got a readbraw error */
1373 DEBUG(4,("readbraw error - reducing size\n"));
1374 readbraw_size = (readbraw_size * 9) / 10;
1376 if (readbraw_size < max_xmit)
1378 DEBUG(0,("disabling readbraw\n"));
1379 readbraw_supported = False;
1382 dataptr=NULL;
1383 continue;
1386 if(read_data(Client,inbuf,datalen) != datalen) {
1387 DEBUG(0,("Failed to read data in readbraw\n"));
1388 exit(1);
1390 dataptr = inbuf;
1392 break;
1394 case 3:
1395 /* we've already read some data with a chained readX */
1396 break;
1398 default:
1399 /* use plain read */
1400 bzero(outbuf,smb_size);
1401 set_message(outbuf,5,0,True);
1402 CVAL(outbuf,smb_com) = SMBread;
1403 SSVAL(outbuf,smb_tid,cnum);
1404 cli_setup_pkt(outbuf);
1406 SSVAL(outbuf,smb_vwv0,fnum);
1407 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1408 SIVAL(outbuf,smb_vwv2,nread);
1409 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1411 send_smb(Client,outbuf);
1412 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1414 if (CVAL(inbuf,smb_rcls) != 0)
1416 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1417 break;
1420 datalen = SVAL(inbuf,smb_vwv0);
1421 dataptr = smb_buf(inbuf) + 3;
1422 break;
1425 if (writefile(handle,dataptr,datalen) != datalen)
1427 DEBUG(0,("Error writing local file\n"));
1428 break;
1431 nread += datalen;
1432 if (datalen == 0)
1434 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1435 break;
1438 dataptr=NULL;
1439 datalen=0;
1444 if (!close_done)
1446 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1448 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1450 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1451 if(newhandle)
1452 close(handle);
1453 free(inbuf);free(outbuf);
1454 return;
1458 if(newhandle)
1459 close(handle);
1461 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1462 bzero(outbuf,smb_size);
1463 set_message(outbuf,8,strlen(rname)+4,True);
1464 CVAL(outbuf,smb_com) = SMBsetatr;
1465 SSVAL(outbuf,smb_tid,cnum);
1466 cli_setup_pkt(outbuf);
1467 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1468 SIVALS(outbuf,smb_vwv1,0);
1469 p = smb_buf(outbuf);
1470 *p++ = 4;
1471 pstrcpy(p,rname);
1472 p += strlen(p)+1;
1473 *p++ = 4;
1474 *p = 0;
1475 send_smb(Client,outbuf);
1476 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1480 struct timeval tp_end;
1481 int this_time;
1483 GetTimeOfDay(&tp_end);
1484 this_time =
1485 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1486 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1487 get_total_time_ms += this_time;
1488 get_total_size += finfo.size;
1490 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1491 finfo.size / (1.024*this_time + 1.0e-4),
1492 get_total_size / (1.024*get_total_time_ms)));
1495 free(inbuf);free(outbuf);
1499 /****************************************************************************
1500 get a file
1501 ****************************************************************************/
1502 static void cmd_get(char *dum_in, char *dum_out)
1504 pstring lname;
1505 pstring rname;
1506 char *p;
1508 pstrcpy(rname,cur_dir);
1509 pstrcat(rname,"\\");
1511 p = rname + strlen(rname);
1513 if (!next_token(NULL,p,NULL,sizeof(rname)-strlen(rname))) {
1514 DEBUG(0,("get <filename>\n"));
1515 return;
1517 pstrcpy(lname,p);
1518 dos_clean_name(rname);
1520 next_token(NULL,lname,NULL,sizeof(lname));
1522 do_get(rname,lname,NULL);
1526 /****************************************************************************
1527 do a mget operation on one file
1528 ****************************************************************************/
1529 static void do_mget(file_info *finfo)
1531 pstring rname;
1532 pstring quest;
1534 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1535 return;
1537 if (abort_mget)
1539 DEBUG(0,("mget aborted\n"));
1540 return;
1543 if (finfo->mode & aDIR)
1544 slprintf(quest,sizeof(pstring)-1,
1545 "Get directory %s? ",CNV_LANG(finfo->name));
1546 else
1547 slprintf(quest,sizeof(pstring)-1,
1548 "Get file %s? ",CNV_LANG(finfo->name));
1550 if (prompt && !yesno(quest)) return;
1552 if (finfo->mode & aDIR)
1554 pstring saved_curdir;
1555 pstring mget_mask;
1556 char *inbuf,*outbuf;
1558 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1559 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1561 if (!inbuf || !outbuf)
1563 DEBUG(0,("out of memory\n"));
1564 return;
1567 pstrcpy(saved_curdir,cur_dir);
1569 pstrcat(cur_dir,finfo->name);
1570 pstrcat(cur_dir,"\\");
1572 unix_format(finfo->name);
1574 if (lowercase)
1575 strlower(finfo->name);
1577 if (!directory_exist(finfo->name,NULL) &&
1578 dos_mkdir(finfo->name,0777) != 0)
1580 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1581 pstrcpy(cur_dir,saved_curdir);
1582 free(inbuf);free(outbuf);
1583 return;
1586 if (dos_chdir(finfo->name) != 0)
1588 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1589 pstrcpy(cur_dir,saved_curdir);
1590 free(inbuf);free(outbuf);
1591 return;
1595 pstrcpy(mget_mask,cur_dir);
1596 pstrcat(mget_mask,"*");
1598 do_dir((char *)inbuf,(char *)outbuf,
1599 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False, False);
1600 chdir("..");
1601 pstrcpy(cur_dir,saved_curdir);
1602 free(inbuf);free(outbuf);
1604 else
1606 pstrcpy(rname,cur_dir);
1607 pstrcat(rname,finfo->name);
1608 do_get(rname,finfo->name,finfo);
1612 /****************************************************************************
1613 view the file using the pager
1614 ****************************************************************************/
1615 static void cmd_more(char *dum_in, char *dum_out)
1617 fstring rname,lname,tmpname,pager_cmd;
1618 char *pager;
1620 fstrcpy(rname,cur_dir);
1621 fstrcat(rname,"\\");
1622 slprintf(tmpname,
1623 sizeof(fstring)-1,
1624 "%s/smbmore.%d",tmpdir(),(int)getpid());
1625 fstrcpy(lname,tmpname);
1627 if (!next_token(NULL,rname+strlen(rname),NULL,sizeof(rname)-strlen(rname))) {
1628 DEBUG(0,("more <filename>\n"));
1629 return;
1631 dos_clean_name(rname);
1633 do_get(rname,lname,NULL);
1635 pager=getenv("PAGER");
1637 slprintf(pager_cmd,sizeof(pager_cmd)-1,
1638 "%s %s",(pager? pager:PAGER), tmpname);
1639 system(pager_cmd);
1640 unlink(tmpname);
1645 /****************************************************************************
1646 do a mget command
1647 ****************************************************************************/
1648 static void cmd_mget(char *inbuf,char *outbuf)
1650 int attribute = aSYSTEM | aHIDDEN;
1651 pstring mget_mask;
1652 fstring buf;
1653 char *p=buf;
1655 *mget_mask = 0;
1657 if (recurse)
1658 attribute |= aDIR;
1660 abort_mget = False;
1662 while (next_token(NULL,p,NULL,sizeof(buf)))
1664 pstrcpy(mget_mask,cur_dir);
1665 if(mget_mask[strlen(mget_mask)-1]!='\\')
1666 pstrcat(mget_mask,"\\");
1668 if (*p == '\\')
1669 pstrcpy(mget_mask,p);
1670 else
1671 pstrcat(mget_mask,p);
1672 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1675 if (! *mget_mask)
1677 pstrcpy(mget_mask,cur_dir);
1678 if(mget_mask[strlen(mget_mask)-1]!='\\')
1679 pstrcat(mget_mask,"\\");
1680 pstrcat(mget_mask,"*");
1681 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1685 /****************************************************************************
1686 make a directory of name "name"
1687 ****************************************************************************/
1688 static BOOL do_mkdir(char *name)
1690 char *p;
1691 char *inbuf,*outbuf;
1693 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1694 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1696 if (!inbuf || !outbuf)
1698 DEBUG(0,("out of memory\n"));
1699 return False;
1702 bzero(outbuf,smb_size);
1703 set_message(outbuf,0,2 + strlen(name),True);
1705 CVAL(outbuf,smb_com) = SMBmkdir;
1706 SSVAL(outbuf,smb_tid,cnum);
1707 cli_setup_pkt(outbuf);
1710 p = smb_buf(outbuf);
1711 *p++ = 4;
1712 pstrcpy(p,name);
1714 send_smb(Client,outbuf);
1715 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1717 if (CVAL(inbuf,smb_rcls) != 0)
1719 DEBUG(0,("%s making remote directory %s\n",
1720 smb_errstr(inbuf),CNV_LANG(name)));
1722 free(inbuf);free(outbuf);
1723 return(False);
1726 free(inbuf);free(outbuf);
1727 return(True);
1731 /****************************************************************************
1732 make a directory
1733 ****************************************************************************/
1734 static void cmd_mkdir(char *inbuf,char *outbuf)
1736 pstring mask;
1737 fstring buf;
1738 char *p=buf;
1740 pstrcpy(mask,cur_dir);
1742 if (!next_token(NULL,p,NULL,sizeof(buf)))
1744 if (!recurse)
1745 DEBUG(0,("mkdir <dirname>\n"));
1746 return;
1748 pstrcat(mask,p);
1750 if (recurse)
1752 pstring ddir;
1753 pstring ddir2;
1754 *ddir2 = 0;
1756 pstrcpy(ddir,mask);
1757 trim_string(ddir,".",NULL);
1758 p = strtok(ddir,"/\\");
1759 while (p)
1761 pstrcat(ddir2,p);
1762 if (!chkpath(ddir2,False))
1764 do_mkdir(ddir2);
1766 pstrcat(ddir2,"\\");
1767 p = strtok(NULL,"/\\");
1770 else
1771 do_mkdir(mask);
1775 /*******************************************************************
1776 write to a file using writebraw
1777 ********************************************************************/
1778 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1780 extern int Client;
1781 pstring inbuf;
1783 bzero(outbuf,smb_size);
1784 bzero(inbuf,smb_size);
1785 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1787 CVAL(outbuf,smb_com) = SMBwritebraw;
1788 SSVAL(outbuf,smb_tid,cnum);
1789 cli_setup_pkt(outbuf);
1791 SSVAL(outbuf,smb_vwv0,fnum);
1792 SSVAL(outbuf,smb_vwv1,n);
1793 SIVAL(outbuf,smb_vwv3,pos);
1794 SSVAL(outbuf,smb_vwv7,1);
1796 send_smb(Client,outbuf);
1798 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1799 return(0);
1801 _smb_setlen(buf-4,n); /* HACK! XXXX */
1803 if (write_socket(Client,buf-4,n+4) != n+4)
1804 return(0);
1806 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1807 DEBUG(0,("Error writing remote file (2)\n"));
1808 return(0);
1810 return(SVAL(inbuf,smb_vwv0));
1815 /*******************************************************************
1816 write to a file
1817 ********************************************************************/
1818 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1820 pstring inbuf;
1822 if (writebraw_supported && n > (max_xmit-200))
1823 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1825 bzero(outbuf,smb_size);
1826 bzero(inbuf,smb_size);
1827 set_message(outbuf,5,n + 3,True);
1829 CVAL(outbuf,smb_com) = SMBwrite;
1830 SSVAL(outbuf,smb_tid,cnum);
1831 cli_setup_pkt(outbuf);
1833 SSVAL(outbuf,smb_vwv0,fnum);
1834 SSVAL(outbuf,smb_vwv1,n);
1835 SIVAL(outbuf,smb_vwv2,pos);
1836 SSVAL(outbuf,smb_vwv4,0);
1837 CVAL(smb_buf(outbuf),0) = 1;
1838 SSVAL(smb_buf(outbuf),1,n);
1840 memcpy(smb_buf(outbuf)+3,buf,n);
1842 send_smb(Client,outbuf);
1843 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1845 if (CVAL(inbuf,smb_rcls) != 0) {
1846 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1847 return(0);
1849 return(SVAL(inbuf,smb_vwv0));
1854 /****************************************************************************
1855 put a single file
1856 ****************************************************************************/
1857 static void do_put(char *rname,char *lname,file_info *finfo)
1859 int fnum;
1860 FILE *f;
1861 int nread=0;
1862 char *p;
1863 char *inbuf,*outbuf;
1864 time_t close_time = finfo->mtime;
1865 char *buf=NULL;
1866 static int maxwrite=0;
1868 struct timeval tp_start;
1869 GetTimeOfDay(&tp_start);
1871 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1872 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1874 if (!inbuf || !outbuf)
1876 DEBUG(0,("out of memory\n"));
1877 return;
1880 bzero(outbuf,smb_size);
1881 set_message(outbuf,3,2 + strlen(rname),True);
1883 if (finfo->mtime == 0 || finfo->mtime == -1)
1884 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1886 CVAL(outbuf,smb_com) = SMBcreate;
1887 SSVAL(outbuf,smb_tid,cnum);
1888 cli_setup_pkt(outbuf);
1890 SSVAL(outbuf,smb_vwv0,finfo->mode);
1891 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1893 p = smb_buf(outbuf);
1894 *p++ = 4;
1895 pstrcpy(p,rname);
1897 send_smb(Client,outbuf);
1898 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1900 if (CVAL(inbuf,smb_rcls) != 0)
1902 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1904 free(inbuf);free(outbuf);if (buf) free(buf);
1905 return;
1908 /* allow files to be piped into smbclient
1909 jdblair 24.jun.98 */
1910 if (!strcmp(lname, "-")) {
1911 f = stdin;
1912 /* size of file is not known */
1913 finfo->size = 0;
1914 } else {
1915 f = fopen(lname,"r");
1918 if (!f)
1920 DEBUG(0,("Error opening local file %s\n",lname));
1921 free(inbuf);free(outbuf);
1922 return;
1926 fnum = SVAL(inbuf,smb_vwv0);
1927 if (finfo->size < 0)
1928 finfo->size = file_size(lname);
1930 DEBUG(1,("putting file %s of size %.0f bytes as %s ",lname,(double)finfo->size,CNV_LANG(rname)));
1932 if (!maxwrite)
1933 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1935 /* This is a rewrite of the read/write loop that doesn't require the input
1936 file to be of a known length. This allows the stream pointer 'f' to
1937 refer to stdin.
1939 Rather than reallocing the read buffer every loop to keep it the min
1940 necessary length this look uses a fixed length buffer and just tests
1941 for eof on the file stream at the top of each loop.
1942 jdblair, 24.jun.98 */
1944 buf = (char *)malloc(maxwrite+4);
1945 while (! feof(f) )
1947 int n = maxwrite;
1948 int ret;
1950 fseek(f,nread,SEEK_SET);
1951 if ((n = readfile(buf+4,1,n,f)) < 1)
1953 DEBUG(0,("Error reading local file\n"));
1954 break;
1957 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1959 if (n != ret) {
1960 if (!maxwrite) {
1961 DEBUG(0,("Error writing file\n"));
1962 break;
1963 } else {
1964 maxwrite /= 2;
1965 continue;
1969 nread += n;
1972 bzero(outbuf,smb_size);
1973 set_message(outbuf,3,0,True);
1974 CVAL(outbuf,smb_com) = SMBclose;
1975 SSVAL(outbuf,smb_tid,cnum);
1976 cli_setup_pkt(outbuf);
1978 SSVAL(outbuf,smb_vwv0,fnum);
1979 put_dos_date3(outbuf,smb_vwv1,close_time);
1981 send_smb(Client,outbuf);
1982 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1984 if (CVAL(inbuf,smb_rcls) != 0)
1986 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1987 fclose(f);
1988 free(inbuf);free(outbuf);
1989 if (buf) free(buf);
1990 return;
1994 fclose(f);
1995 free(inbuf);free(outbuf);
1996 if (buf) free(buf);
1999 struct timeval tp_end;
2000 int this_time;
2002 GetTimeOfDay(&tp_end);
2003 this_time =
2004 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
2005 (tp_end.tv_usec - tp_start.tv_usec)/1000;
2006 put_total_time_ms += this_time;
2007 put_total_size += finfo->size;
2009 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
2010 finfo->size / (1.024*this_time + 1.0e-4),
2011 put_total_size / (1.024*put_total_time_ms)));
2017 /****************************************************************************
2018 put a file
2019 ****************************************************************************/
2020 static void cmd_put(char *dum_in, char *dum_out)
2022 pstring lname;
2023 pstring rname;
2024 fstring buf;
2025 char *p=buf;
2026 file_info finfo;
2027 finfo = def_finfo;
2029 pstrcpy(rname,cur_dir);
2030 pstrcat(rname,"\\");
2033 if (!next_token(NULL,p,NULL,sizeof(buf)))
2035 DEBUG(0,("put <filename>\n"));
2036 return;
2038 pstrcpy(lname,p);
2040 if (next_token(NULL,p,NULL,sizeof(buf)))
2041 pstrcat(rname,p);
2042 else
2043 pstrcat(rname,lname);
2045 dos_clean_name(rname);
2048 SMB_STRUCT_STAT st;
2049 /* allow '-' to represent stdin
2050 jdblair, 24.jun.98 */
2051 if (!file_exist(lname,&st) &&
2052 (strcmp(lname,"-"))) {
2053 DEBUG(0,("%s does not exist\n",lname));
2054 return;
2056 finfo.mtime = st.st_mtime;
2059 do_put(rname,lname,&finfo);
2062 /****************************************************************************
2063 seek in a directory/file list until you get something that doesn't start with
2064 the specified name
2065 ****************************************************************************/
2066 static BOOL seek_list(FILE *f,char *name)
2068 pstring s;
2069 while (!feof(f))
2071 if (fscanf(f,"%s",s) != 1) return(False);
2072 trim_string(s,"./",NULL);
2073 if (strncmp(s,name,strlen(name)) != 0)
2075 pstrcpy(name,s);
2076 return(True);
2080 return(False);
2084 /****************************************************************************
2085 set the file selection mask
2086 ****************************************************************************/
2087 static void cmd_select(char *dum_in, char *dum_out)
2089 pstrcpy(fileselection,"");
2090 next_token(NULL,fileselection,NULL,sizeof(fileselection));
2094 /****************************************************************************
2095 mput some files
2096 ****************************************************************************/
2097 static void cmd_mput(char *dum_in, char *dum_out)
2099 pstring lname;
2100 pstring rname;
2101 file_info finfo;
2102 fstring buf;
2103 char *p=buf;
2105 finfo = def_finfo;
2108 while (next_token(NULL,p,NULL,sizeof(buf)))
2110 SMB_STRUCT_STAT st;
2111 pstring cmd;
2112 pstring tmpname;
2113 FILE *f;
2115 slprintf(tmpname,sizeof(pstring)-1,
2116 "%s/ls.smb.%d",tmpdir(),(int)getpid());
2117 if (recurse)
2118 slprintf(cmd,sizeof(pstring)-1,
2119 "find . -name \"%s\" -print > %s",p,tmpname);
2120 else
2121 slprintf(cmd,sizeof(pstring)-1,
2122 "/bin/ls %s > %s",p,tmpname);
2123 system(cmd);
2125 f = fopen(tmpname,"r");
2126 if (!f) continue;
2128 while (!feof(f))
2130 pstring quest;
2132 if (fscanf(f,"%s",lname) != 1) break;
2133 trim_string(lname,"./",NULL);
2135 again1:
2137 /* check if it's a directory */
2138 if (directory_exist(lname,&st))
2140 if (!recurse) continue;
2141 slprintf(quest,sizeof(pstring)-1,
2142 "Put directory %s? ",lname);
2143 if (prompt && !yesno(quest))
2145 pstrcat(lname,"/");
2146 if (!seek_list(f,lname))
2147 break;
2148 goto again1;
2151 pstrcpy(rname,cur_dir);
2152 pstrcat(rname,lname);
2153 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2154 pstrcat(lname,"/");
2155 if (!seek_list(f,lname))
2156 break;
2157 goto again1;
2160 continue;
2162 else
2164 slprintf(quest,sizeof(quest)-1,
2165 "Put file %s? ",lname);
2166 if (prompt && !yesno(quest)) continue;
2168 pstrcpy(rname,cur_dir);
2169 pstrcat(rname,lname);
2171 dos_format(rname);
2173 /* null size so do_put knows to ignore it */
2174 finfo.size = -1;
2176 /* set the date on the file */
2177 finfo.mtime = st.st_mtime;
2179 do_put(rname,lname,&finfo);
2181 fclose(f);
2182 unlink(tmpname);
2186 /****************************************************************************
2187 cancel a print job
2188 ****************************************************************************/
2189 static void do_cancel(int job)
2191 char *rparam = NULL;
2192 char *rdata = NULL;
2193 char *p;
2194 int rdrcnt,rprcnt;
2195 pstring param;
2197 bzero(param,sizeof(param));
2199 p = param;
2200 SSVAL(p,0,81); /* DosPrintJobDel() */
2201 p += 2;
2202 pstrcpy(p,"W");
2203 p = skip_string(p,1);
2204 pstrcpy(p,"");
2205 p = skip_string(p,1);
2206 SSVAL(p,0,job);
2207 p += 2;
2209 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2210 6, 1000,
2211 &rprcnt,&rdrcnt,
2212 param,NULL, NULL,
2213 &rparam,&rdata))
2215 int res = SVAL(rparam,0);
2217 if (!res)
2218 printf("Job %d cancelled\n",job);
2219 else
2220 printf("Error %d calcelling job %d\n",res,job);
2221 return;
2223 else
2224 printf("Server refused cancel request\n");
2226 if (rparam) free(rparam);
2227 if (rdata) free(rdata);
2229 return;
2233 /****************************************************************************
2234 cancel a print job
2235 ****************************************************************************/
2236 static void cmd_cancel(char *inbuf,char *outbuf )
2238 fstring buf;
2239 int job;
2241 if (!connect_as_printer)
2243 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2244 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2247 if (!next_token(NULL,buf,NULL,sizeof(buf))) {
2248 printf("cancel <jobid> ...\n");
2249 return;
2251 do {
2252 job = atoi(buf);
2253 do_cancel(job);
2254 } while (next_token(NULL,buf,NULL,sizeof(buf)));
2260 /****************************************************************************
2261 print a file
2262 ****************************************************************************/
2263 static void cmd_print(char *inbuf,char *outbuf )
2265 int fnum;
2266 FILE *f = NULL;
2267 uint32 nread=0;
2268 pstring lname;
2269 pstring rname;
2270 char *p;
2272 if (!connect_as_printer)
2274 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2275 DEBUG(0,("Trying to print without -P may fail\n"));
2278 if (!next_token(NULL,lname,NULL, sizeof(lname)))
2280 DEBUG(0,("print <filename>\n"));
2281 return;
2284 pstrcpy(rname,lname);
2285 p = strrchr(rname,'/');
2286 if (p)
2288 pstring tname;
2289 pstrcpy(tname,p+1);
2290 pstrcpy(rname,tname);
2293 if ((int)strlen(rname) > 14)
2294 rname[14] = 0;
2296 if (strequal(lname,"-"))
2298 f = stdin;
2299 pstrcpy(rname,"stdin");
2302 dos_clean_name(rname);
2304 bzero(outbuf,smb_size);
2305 set_message(outbuf,2,2 + strlen(rname),True);
2307 CVAL(outbuf,smb_com) = SMBsplopen;
2308 SSVAL(outbuf,smb_tid,cnum);
2309 cli_setup_pkt(outbuf);
2311 SSVAL(outbuf,smb_vwv0,0);
2312 SSVAL(outbuf,smb_vwv1,printmode);
2314 p = smb_buf(outbuf);
2315 *p++ = 4;
2316 pstrcpy(p,rname);
2318 send_smb(Client,outbuf);
2319 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2321 if (CVAL(inbuf,smb_rcls) != 0)
2323 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2324 return;
2327 if (!f)
2328 f = fopen(lname,"r");
2329 if (!f)
2331 DEBUG(0,("Error opening local file %s\n",lname));
2332 return;
2336 fnum = SVAL(inbuf,smb_vwv0);
2338 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2340 while (!feof(f))
2342 int n;
2344 bzero(outbuf,smb_size);
2345 set_message(outbuf,1,3,True);
2347 /* for some strange reason the OS/2 print server can't handle large
2348 packets when printing. weird */
2349 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2351 if (translation)
2352 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2353 else
2354 n = readfile(smb_buf(outbuf)+3,1,n,f);
2355 if (n <= 0)
2357 DEBUG(0,("read gave %d\n",n));
2358 break;
2361 smb_setlen(outbuf,smb_len(outbuf) + n);
2363 CVAL(outbuf,smb_com) = SMBsplwr;
2364 SSVAL(outbuf,smb_tid,cnum);
2365 cli_setup_pkt(outbuf);
2367 SSVAL(outbuf,smb_vwv0,fnum);
2368 SSVAL(outbuf,smb_vwv1,n+3);
2369 CVAL(smb_buf(outbuf),0) = 1;
2370 SSVAL(smb_buf(outbuf),1,n);
2372 send_smb(Client,outbuf);
2373 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2375 if (CVAL(inbuf,smb_rcls) != 0)
2377 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2378 break;
2381 nread += n;
2384 DEBUG(2,("%d bytes printed\n",nread));
2386 bzero(outbuf,smb_size);
2387 set_message(outbuf,1,0,True);
2388 CVAL(outbuf,smb_com) = SMBsplclose;
2389 SSVAL(outbuf,smb_tid,cnum);
2390 cli_setup_pkt(outbuf);
2392 SSVAL(outbuf,smb_vwv0,fnum);
2394 send_smb(Client,outbuf);
2395 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2397 if (CVAL(inbuf,smb_rcls) != 0)
2399 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2400 if (f != stdin)
2401 fclose(f);
2402 return;
2405 if (f != stdin)
2406 fclose(f);
2409 /****************************************************************************
2410 show a print queue - this is deprecated as it uses the old smb that
2411 has limited support - the correct call is the cmd_p_queue_4() after this.
2412 ****************************************************************************/
2413 static void cmd_queue(char *inbuf,char *outbuf )
2415 int count;
2416 char *p;
2418 bzero(outbuf,smb_size);
2419 set_message(outbuf,2,0,True);
2421 CVAL(outbuf,smb_com) = SMBsplretq;
2422 SSVAL(outbuf,smb_tid,cnum);
2423 cli_setup_pkt(outbuf);
2425 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2426 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2428 send_smb(Client,outbuf);
2429 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2431 if (CVAL(inbuf,smb_rcls) != 0)
2433 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2434 return;
2437 count = SVAL(inbuf,smb_vwv0);
2438 p = smb_buf(inbuf) + 3;
2439 if (count <= 0)
2441 DEBUG(0,("No entries in the print queue\n"));
2442 return;
2446 char status[20];
2448 DEBUG(0,("Job Name Size Status\n"));
2450 while (count--)
2452 switch (CVAL(p,4))
2454 case 0x01: safe_strcpy(status,"held or stopped", sizeof(status)-1); break;
2455 case 0x02: safe_strcpy(status,"printing",sizeof(status)-1); break;
2456 case 0x03: safe_strcpy(status,"awaiting print", sizeof(status)-1); break;
2457 case 0x04: safe_strcpy(status,"in intercept",sizeof(status)-1); break;
2458 case 0x05: safe_strcpy(status,"file had error",sizeof(status)-1); break;
2459 case 0x06: safe_strcpy(status,"printer error",sizeof(status)-1); break;
2460 default: safe_strcpy(status,"unknown",sizeof(status)-1); break;
2463 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2464 SVAL(p,5),p+12,IVAL(p,7),status));
2465 p += 28;
2472 /****************************************************************************
2473 show information about a print queue
2474 ****************************************************************************/
2475 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2477 char *rparam = NULL;
2478 char *rdata = NULL;
2479 char *p;
2480 int rdrcnt, rprcnt;
2481 pstring param;
2482 int result_code=0;
2484 if (!connect_as_printer)
2486 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2487 DEBUG(0,("Trying to print without -P may fail\n"));
2490 bzero(param,sizeof(param));
2492 p = param;
2493 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2494 p += 2;
2495 pstrcpy(p,"zWrLeh"); /* parameter description? */
2496 p = skip_string(p,1);
2497 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
2498 p = skip_string(p,1);
2499 pstrcpy(p,strrchr(service,'\\')+1); /* name of queue */
2500 p = skip_string(p,1);
2501 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2502 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2503 p += 4;
2504 pstrcpy(p,""); /* subformat */
2505 p = skip_string(p,1);
2507 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2508 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2509 10, 4096,
2510 &rprcnt, &rdrcnt,
2511 param, NULL, NULL,
2512 &rparam, &rdata) )
2514 int converter;
2515 result_code = SVAL(rparam,0);
2516 converter = SVAL(rparam,2); /* conversion factor */
2518 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2520 if (result_code == 0) /* if no error, */
2522 int i;
2523 uint16 JobId;
2524 uint16 Priority;
2525 uint32 Size;
2526 char *UserName;
2527 char *JobName;
2528 char *JobTimeStr;
2529 time_t JobTime;
2530 fstring PrinterName;
2532 fstrcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2533 strlower(PrinterName); /* in lower case */
2535 p = rdata; /* received data */
2536 for( i = 0; i < SVAL(rparam,4); ++i)
2538 JobId = SVAL(p,0);
2539 Priority = SVAL(p,2);
2540 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2541 strlower(UserName);
2542 Priority = SVAL(p,2);
2543 JobTime = make_unix_date3( p + 12);
2544 JobTimeStr = asctime(LocalTime( &JobTime));
2545 Size = IVAL(p,16);
2546 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2549 printf("%s-%u %s priority %u %s %s %u bytes\n",
2550 PrinterName, JobId, UserName,
2551 Priority, JobTimeStr, JobName, Size);
2553 #if 0 /* DEBUG code */
2554 printf("Job Id: \"%u\"\n", SVAL(p,0));
2555 printf("Priority: \"%u\"\n", SVAL(p,2));
2557 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2558 printf("Position: \"%u\"\n", SVAL(p,8));
2559 printf("Status: \"%u\"\n", SVAL(p,10));
2561 JobTime = make_unix_date3( p + 12);
2562 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2563 printf("date: \"%u\"\n", SVAL(p,12));
2565 printf("Size: \"%u\"\n", SVAL(p,16));
2566 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2567 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2568 #endif /* DEBUG CODE */
2569 p += 28;
2573 else /* cli_call_api() failed */
2575 printf("Failed, error = %d\n", result_code);
2578 /* If any parameters or data were returned, free the storage. */
2579 if(rparam) free(rparam);
2580 if(rdata) free(rdata);
2582 return;
2585 /****************************************************************************
2586 show information about a print queue
2587 ****************************************************************************/
2588 static void cmd_qinfo(char *inbuf,char *outbuf )
2590 char *rparam = NULL;
2591 char *rdata = NULL;
2592 char *p;
2593 int rdrcnt, rprcnt;
2594 pstring param;
2595 int result_code=0;
2597 bzero(param,sizeof(param));
2599 p = param;
2600 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2601 p += 2;
2602 pstrcpy(p,"zWrLh"); /* parameter description? */
2603 p = skip_string(p,1);
2604 pstrcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2605 p = skip_string(p,1);
2606 pstrcpy(p,strrchr(service,'\\')+1); /* name of queue */
2607 p = skip_string(p,1);
2608 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2609 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2610 p += 4;
2611 pstrcpy(p,""); /* subformat */
2612 p = skip_string(p,1);
2614 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2615 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2616 10, 4096,
2617 &rprcnt, &rdrcnt,
2618 param, NULL, NULL,
2619 &rparam, &rdata) )
2621 int converter;
2622 result_code = SVAL(rparam,0);
2623 converter = SVAL(rparam,2); /* conversion factor */
2625 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2627 if (result_code == 0) /* if no error, */
2629 p = rdata; /* received data */
2631 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2632 printf("Priority: %u\n", SVAL(p,4) );
2633 printf("Start time: %u\n", SVAL(p,6) );
2634 printf("Until time: %u\n", SVAL(p,8) );
2635 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2636 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2637 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2638 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2639 printf("Status: %u\n", SVAL(p,28) );
2640 printf("Jobs: %u\n", SVAL(p,30) );
2641 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2642 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2644 /* Dump the driver data */
2646 int count, x, y, c;
2647 char *ddptr;
2649 ddptr = rdata + SVAL(p,40) - converter;
2650 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2651 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2653 for(x=8; x < count; x+=16)
2655 for(y=0; y < 16; y++)
2657 if( (x+y) < count )
2658 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2659 else
2660 fputs(" ", stdout);
2662 for(y=0; y < 16 && (x+y) < count; y++)
2664 c = CVAL(ddptr,(x+y));
2665 if(isprint(c))
2666 fputc(c, stdout);
2667 else
2668 fputc('.', stdout);
2670 fputc('\n', stdout);
2676 else /* cli_call_api() failed */
2678 printf("Failed, error = %d\n", result_code);
2681 /* If any parameters or data were returned, free the storage. */
2682 if(rparam) free(rparam);
2683 if(rdata) free(rdata);
2685 return;
2688 /****************************************************************************
2689 delete some files
2690 ****************************************************************************/
2691 static void do_del(file_info *finfo)
2693 char *p;
2694 char *inbuf,*outbuf;
2695 pstring mask;
2697 pstrcpy(mask,cur_dir);
2698 pstrcat(mask,finfo->name);
2700 if (finfo->mode & aDIR)
2701 return;
2703 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2704 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2706 if (!inbuf || !outbuf)
2708 DEBUG(0,("out of memory\n"));
2709 return;
2712 bzero(outbuf,smb_size);
2713 set_message(outbuf,1,2 + strlen(mask),True);
2715 CVAL(outbuf,smb_com) = SMBunlink;
2716 SSVAL(outbuf,smb_tid,cnum);
2717 cli_setup_pkt(outbuf);
2719 SSVAL(outbuf,smb_vwv0,0);
2721 p = smb_buf(outbuf);
2722 *p++ = 4;
2723 pstrcpy(p,mask);
2725 send_smb(Client,outbuf);
2726 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2728 if (CVAL(inbuf,smb_rcls) != 0)
2729 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2731 free(inbuf);free(outbuf);
2735 /****************************************************************************
2736 delete some files
2737 ****************************************************************************/
2738 static void cmd_del(char *inbuf,char *outbuf )
2740 pstring mask;
2741 fstring buf;
2742 int attribute = aSYSTEM | aHIDDEN;
2744 if (recurse)
2745 attribute |= aDIR;
2747 pstrcpy(mask,cur_dir);
2749 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2751 DEBUG(0,("del <filename>\n"));
2752 return;
2754 pstrcat(mask,buf);
2756 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False,False);
2760 /****************************************************************************
2761 remove a directory
2762 ****************************************************************************/
2763 static void cmd_rmdir(char *inbuf,char *outbuf )
2765 pstring mask;
2766 fstring buf;
2767 char *p;
2769 pstrcpy(mask,cur_dir);
2771 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2773 DEBUG(0,("rmdir <dirname>\n"));
2774 return;
2776 pstrcat(mask,buf);
2778 bzero(outbuf,smb_size);
2779 set_message(outbuf,0,2 + strlen(mask),True);
2781 CVAL(outbuf,smb_com) = SMBrmdir;
2782 SSVAL(outbuf,smb_tid,cnum);
2783 cli_setup_pkt(outbuf);
2786 p = smb_buf(outbuf);
2787 *p++ = 4;
2788 pstrcpy(p,mask);
2790 send_smb(Client,outbuf);
2791 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2793 if (CVAL(inbuf,smb_rcls) != 0)
2795 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2796 return;
2801 /****************************************************************************
2802 rename some files
2803 ****************************************************************************/
2804 static void cmd_rename(char *inbuf,char *outbuf )
2806 pstring src,dest;
2807 fstring buf,buf2;
2808 char *p;
2810 pstrcpy(src,cur_dir);
2811 pstrcpy(dest,cur_dir);
2813 if (!next_token(NULL,buf,NULL,sizeof(buf)) ||
2814 !next_token(NULL,buf2,NULL, sizeof(buf2)))
2816 DEBUG(0,("rename <src> <dest>\n"));
2817 return;
2819 pstrcat(src,buf);
2820 pstrcat(dest,buf2);
2822 bzero(outbuf,smb_size);
2823 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2825 CVAL(outbuf,smb_com) = SMBmv;
2826 SSVAL(outbuf,smb_tid,cnum);
2827 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2828 cli_setup_pkt(outbuf);
2830 p = smb_buf(outbuf);
2831 *p++ = 4;
2832 pstrcpy(p,src);
2833 p = skip_string(p,1);
2834 *p++ = 4;
2835 pstrcpy(p,dest);
2837 send_smb(Client,outbuf);
2838 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2840 if (CVAL(inbuf,smb_rcls) != 0)
2842 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2843 return;
2849 /****************************************************************************
2850 toggle the prompt flag
2851 ****************************************************************************/
2852 static void cmd_prompt(char *dum_in, char *dum_out)
2854 prompt = !prompt;
2855 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2859 /****************************************************************************
2860 set the newer than time
2861 ****************************************************************************/
2862 static void cmd_newer(char *dum_in, char *dum_out)
2864 fstring buf;
2865 BOOL ok;
2866 SMB_STRUCT_STAT sbuf;
2868 ok = next_token(NULL,buf,NULL,sizeof(buf));
2869 if (ok && (dos_stat(buf,&sbuf) == 0))
2871 newer_than = sbuf.st_mtime;
2872 DEBUG(1,("Getting files newer than %s",
2873 asctime(LocalTime(&newer_than))));
2875 else
2876 newer_than = 0;
2878 if (ok && newer_than == 0)
2879 DEBUG(0,("Error setting newer-than time\n"));
2882 /****************************************************************************
2883 set the archive level
2884 ****************************************************************************/
2885 static void cmd_archive(char *dum_in, char *dum_out)
2887 fstring buf;
2889 if (next_token(NULL,buf,NULL,sizeof(buf))) {
2890 archive_level = atoi(buf);
2891 } else
2892 DEBUG(0,("Archive level is %d\n",archive_level));
2895 /****************************************************************************
2896 toggle the lowercaseflag
2897 ****************************************************************************/
2898 static void cmd_lowercase(char *dum_in, char *dum_out)
2900 lowercase = !lowercase;
2901 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2907 /****************************************************************************
2908 toggle the recurse flag
2909 ****************************************************************************/
2910 static void cmd_recurse(char *dum_in, char *dum_out)
2912 recurse = !recurse;
2913 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2916 /****************************************************************************
2917 toggle the translate flag
2918 ****************************************************************************/
2919 static void cmd_translate(char *dum_in, char *dum_out)
2921 translation = !translation;
2922 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2923 translation?"on":"off"));
2927 /****************************************************************************
2928 do a printmode command
2929 ****************************************************************************/
2930 static void cmd_printmode(char *dum_in, char *dum_out)
2932 fstring buf;
2933 fstring mode;
2935 if (next_token(NULL,buf,NULL,sizeof(buf)))
2937 if (strequal(buf,"text"))
2938 printmode = 0;
2939 else
2941 if (strequal(buf,"graphics"))
2942 printmode = 1;
2943 else
2944 printmode = atoi(buf);
2948 switch(printmode)
2950 case 0:
2951 fstrcpy(mode,"text");
2952 break;
2953 case 1:
2954 fstrcpy(mode,"graphics");
2955 break;
2956 default:
2957 slprintf(mode,sizeof(mode)-1,"%d",printmode);
2958 break;
2961 DEBUG(2,("the printmode is now %s\n",mode));
2964 /****************************************************************************
2965 do the lcd command
2966 ****************************************************************************/
2967 static void cmd_lcd(char *dum_in, char *dum_out)
2969 fstring buf;
2970 pstring d;
2972 if (next_token(NULL,buf,NULL,sizeof(buf)))
2973 dos_chdir(buf);
2974 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2978 /****************************************************************************
2979 try and browse available connections on a host
2980 ****************************************************************************/
2981 static BOOL browse_host(BOOL sort)
2983 char *rparam = NULL;
2984 char *rdata = NULL;
2985 char *p;
2986 int rdrcnt,rprcnt;
2987 pstring param;
2988 int count = -1;
2990 /* now send a SMBtrans command with api RNetShareEnum */
2991 p = param;
2992 SSVAL(p,0,0); /* api number */
2993 p += 2;
2994 pstrcpy(p,"WrLeh");
2995 p = skip_string(p,1);
2996 pstrcpy(p,"B13BWz");
2997 p = skip_string(p,1);
2998 SSVAL(p,0,1);
2999 SSVAL(p,2,BUFFER_SIZE);
3000 p += 4;
3002 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3003 1024, BUFFER_SIZE,
3004 &rprcnt,&rdrcnt,
3005 param,NULL, NULL,
3006 &rparam,&rdata))
3008 int res = SVAL(rparam,0);
3009 int converter=SVAL(rparam,2);
3010 int i;
3011 BOOL long_share_name=False;
3013 if (res == 0 || res == ERRmoredata)
3015 count=SVAL(rparam,4);
3016 p = rdata;
3018 if (count > 0)
3020 printf("\n\tSharename Type Comment\n");
3021 printf("\t--------- ---- -------\n");
3024 if (sort)
3025 qsort(p,count,20,QSORT_CAST StrCaseCmp);
3027 for (i=0;i<count;i++)
3029 char *sname = p;
3030 int type = SVAL(p,14);
3031 int comment_offset = IVAL(p,16) & 0xFFFF;
3032 fstring typestr;
3033 *typestr=0;
3035 switch (type)
3037 case STYPE_DISKTREE:
3038 fstrcpy(typestr,"Disk"); break;
3039 case STYPE_PRINTQ:
3040 fstrcpy(typestr,"Printer"); break;
3041 case STYPE_DEVICE:
3042 fstrcpy(typestr,"Device"); break;
3043 case STYPE_IPC:
3044 fstrcpy(typestr,"IPC"); break;
3047 printf("\t%-15.15s%-10.10s%s\n",
3048 sname, typestr,
3049 comment_offset?rdata+comment_offset-converter:"");
3051 if (strlen(sname)>8) long_share_name=True;
3053 p += 20;
3056 if (long_share_name) {
3057 printf("\nNOTE: There were share names longer than 8 chars.\n\
3058 On older clients these may not be accessible or may give browsing errors\n");
3061 if(res == ERRmoredata)
3062 printf("\nNOTE: More data was available, the list was truncated.\n");
3066 if (rparam) free(rparam);
3067 if (rdata) free(rdata);
3069 return(count>0);
3073 /****************************************************************************
3074 get some server info
3075 ****************************************************************************/
3076 static void server_info(void)
3078 char *rparam = NULL;
3079 char *rdata = NULL;
3080 char *p;
3081 int rdrcnt,rprcnt;
3082 pstring param;
3084 bzero(param,sizeof(param));
3086 p = param;
3087 SSVAL(p,0,63); /* NetServerGetInfo()? */
3088 p += 2;
3089 pstrcpy(p,"WrLh");
3090 p = skip_string(p,1);
3091 pstrcpy(p,"zzzBBzz");
3092 p = skip_string(p,1);
3093 SSVAL(p,0,10); /* level 10 */
3094 SSVAL(p,2,1000);
3095 p += 6;
3097 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3098 6, 1000,
3099 &rprcnt,&rdrcnt,
3100 param,NULL, NULL,
3101 &rparam,&rdata))
3103 int res = SVAL(rparam,0);
3104 int converter=SVAL(rparam,2);
3106 if (res == 0)
3108 p = rdata;
3110 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3111 rdata+SVAL(p,0)-converter,
3112 rdata+SVAL(p,4)-converter,
3113 rdata+SVAL(p,8)-converter,
3114 rdata+SVAL(p,14)-converter);
3118 if (rparam) free(rparam);
3119 if (rdata) free(rdata);
3121 return;
3125 /****************************************************************************
3126 try and browse available connections on a host
3127 ****************************************************************************/
3128 static BOOL list_servers(char *wk_grp)
3130 char *rparam = NULL;
3131 char *rdata = NULL;
3132 int rdrcnt,rprcnt;
3133 char *p,*svtype_p;
3134 pstring param;
3135 int uLevel = 1;
3136 int count = 0;
3137 BOOL ok = False;
3138 BOOL generic_request = False;
3141 if (strequal(wk_grp,"WORKGROUP")) {
3142 /* we won't specify a workgroup */
3143 generic_request = True;
3146 /* now send a SMBtrans command with api ServerEnum? */
3147 p = param;
3148 SSVAL(p,0,0x68); /* api number */
3149 p += 2;
3151 pstrcpy(p,generic_request?"WrLehDO":"WrLehDz");
3152 p = skip_string(p,1);
3154 pstrcpy(p,"B16BBDz");
3156 p = skip_string(p,1);
3157 SSVAL(p,0,uLevel);
3158 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3159 p += 4;
3161 svtype_p = p;
3162 p += 4;
3164 if (!generic_request) {
3165 pstrcpy(p, wk_grp);
3166 p = skip_string(p,1);
3169 /* first ask for a list of servers in this workgroup */
3170 SIVAL(svtype_p,0,SV_TYPE_ALL);
3172 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3173 8, BUFFER_SIZE - SAFETY_MARGIN,
3174 &rprcnt,&rdrcnt,
3175 param,NULL, NULL,
3176 &rparam,&rdata))
3178 int res = SVAL(rparam,0);
3179 int converter=SVAL(rparam,2);
3180 int i;
3182 if (res == 0 || res == ERRmoredata) {
3183 char *p2 = rdata;
3184 count=SVAL(rparam,4);
3186 if (count > 0) {
3187 printf("\n\nThis machine has a browse list:\n");
3188 printf("\n\tServer Comment\n");
3189 printf("\t--------- -------\n");
3192 for (i=0;i<count;i++) {
3193 char *sname = p2;
3194 int comment_offset = IVAL(p2,22) & 0xFFFF;
3195 printf("\t%-16.16s %s\n", sname,
3196 comment_offset?rdata+comment_offset-converter:"");
3198 ok=True;
3199 p2 += 26;
3202 if(res == ERRmoredata)
3203 printf("\nNOTE: More data was available, the list was truncated.\n");
3207 if (rparam) {free(rparam); rparam = NULL;}
3208 if (rdata) {free(rdata); rdata = NULL;}
3210 /* now ask for a list of workgroups */
3211 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3213 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3214 8, BUFFER_SIZE - SAFETY_MARGIN,
3215 &rprcnt,&rdrcnt,
3216 param,NULL, NULL,
3217 &rparam,&rdata))
3219 int res = SVAL(rparam,0);
3220 int converter=SVAL(rparam,2);
3221 int i;
3223 if (res == 0 || res == ERRmoredata) {
3224 char *p2 = rdata;
3225 count=SVAL(rparam,4);
3227 if (count > 0) {
3228 printf("\n\nThis machine has a workgroup list:\n");
3229 printf("\n\tWorkgroup Master\n");
3230 printf("\t--------- -------\n");
3233 for (i=0;i<count;i++) {
3234 char *sname = p2;
3235 int comment_offset = IVAL(p2,22) & 0xFFFF;
3236 printf("\t%-16.16s %s\n", sname,
3237 comment_offset?rdata+comment_offset-converter:"");
3239 ok=True;
3240 p2 += 26;
3243 if(res == ERRmoredata)
3244 printf("\nNOTE: More data was available, the list was truncated.\n");
3248 if (rparam) free(rparam);
3249 if (rdata) free(rdata);
3251 return(ok);
3255 /* Some constants for completing filename arguments */
3257 #define COMPL_NONE 0 /* No completions */
3258 #define COMPL_REMOTE 1 /* Complete remote filename */
3259 #define COMPL_LOCAL 2 /* Complete local filename */
3261 /* This defines the commands supported by this client */
3262 struct
3264 char *name;
3265 void (*fn)(char *, char *);
3266 char *description;
3267 char compl_args[2]; /* Completion argument info */
3268 } commands[] =
3270 {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3271 {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3272 {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3273 {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
3274 {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
3275 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
3276 {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
3277 {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
3278 {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
3279 {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
3280 {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
3281 {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},
3282 {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
3283 {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
3284 {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
3285 {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
3286 {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
3287 {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
3288 {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
3289 {"pq",cmd_p_queue_4,"enumerate the print queue",{COMPL_NONE,COMPL_NONE}},
3290 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
3291 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},
3292 {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
3293 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},
3294 {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
3295 {"printmode",cmd_printmode,"<graphics or text> set the print mode",{COMPL_NONE,COMPL_NONE}},
3296 {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}},
3297 {"qinfo",cmd_qinfo,"show print queue information",{COMPL_NONE,COMPL_NONE}},
3298 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
3299 {"quit",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3300 {"q",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3301 {"exit",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3302 {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
3303 {"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}},
3304 {"tar",cmd_tar,"tar <c|x>[IXbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
3305 {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
3306 {"tarmode",cmd_tarmode,
3307 "<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
3308 {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
3309 {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
3310 {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
3311 {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
3312 {"",NULL,NULL,{COMPL_NONE,COMPL_NONE}}
3316 /*******************************************************************
3317 lookup a command string in the list of commands, including
3318 abbreviations
3319 ******************************************************************/
3320 static int process_tok(fstring tok)
3322 int i = 0, matches = 0;
3323 int cmd=0;
3324 int tok_len = strlen(tok);
3326 while (commands[i].fn != NULL)
3328 if (strequal(commands[i].name,tok))
3330 matches = 1;
3331 cmd = i;
3332 break;
3334 else if (strnequal(commands[i].name, tok, tok_len))
3336 matches++;
3337 cmd = i;
3339 i++;
3342 if (matches == 0)
3343 return(-1);
3344 else if (matches == 1)
3345 return(cmd);
3346 else
3347 return(-2);
3350 /****************************************************************************
3351 help
3352 ****************************************************************************/
3353 static void cmd_help(char *dum_in, char *dum_out)
3355 int i=0,j;
3356 fstring buf;
3358 if (next_token(NULL,buf,NULL,sizeof(buf)))
3360 if ((i = process_tok(buf)) >= 0)
3361 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3363 else
3364 while (commands[i].description)
3366 for (j=0; commands[i].description && (j<5); j++) {
3367 DEBUG(0,("%-15s",commands[i].name));
3368 i++;
3370 DEBUG(0,("\n"));
3374 #ifdef 0
3376 /****************************************************************************
3377 wait for keyboard activity, swallowing network packets
3378 ****************************************************************************/
3379 static void wait_keyboard(char *buffer)
3381 fd_set fds;
3382 int selrtn;
3383 struct timeval timeout;
3385 while (1)
3387 extern int Client;
3388 FD_ZERO(&fds);
3389 FD_SET(Client,&fds);
3390 FD_SET(fileno(stdin),&fds);
3392 timeout.tv_sec = 20;
3393 timeout.tv_usec = 0;
3394 selrtn = sys_select(MAX(Client,fileno(stdin))+1,&fds,&timeout);
3396 if (FD_ISSET(fileno(stdin),&fds))
3397 return;
3399 /* We deliberately use receive_smb instead of
3400 client_receive_smb as we want to receive
3401 session keepalives and then drop them here.
3403 if (FD_ISSET(Client,&fds))
3404 receive_smb(Client,buffer,0);
3406 chkpath("\\",False);
3409 #endif
3410 #ifdef HAVE_LIBREADLINE
3412 /****************************************************************************
3413 completion routines for GNU Readline
3414 ****************************************************************************/
3416 /* To avoid filename completion being activated when no valid
3417 completions are found, we assign this stub completion function
3418 to the rl_completion_entry_function variable. */
3420 char *complete_cmd_null(char *text, int state)
3422 return NULL;
3425 /* Argh. This is starting to get ugly. We need to be able to pass data
3426 back from the do_dir() iterator function. */
3428 static int compl_state;
3429 static char *compl_text;
3430 static pstring result;
3432 /* Iterator function for do_dir() */
3434 void complete_process_file(file_info *f)
3436 /* Do we have a partial match? */
3438 if ((compl_state >= 0) && (strncmp(compl_text, f->name,
3439 strlen(compl_text)) == 0)) {
3441 /* Return filename if we have made enough matches */
3443 if (compl_state == 0) {
3444 pstrcpy(result, f->name);
3445 compl_state = -1;
3447 return;
3449 compl_state--;
3453 /* Complete a remote file */
3455 char *complete_remote_file(char *text, int state)
3457 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3458 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3459 int attribute = aDIR | aSYSTEM | aHIDDEN;
3460 pstring mask;
3462 if ((InBuffer == NULL) || (OutBuffer == NULL))
3463 return(NULL);
3465 /* Create dir mask */
3467 pstrcpy(mask, cur_dir);
3468 pstrcat(mask, "*");
3470 /* Initialise static vars for filename match */
3472 compl_text = text;
3473 compl_state = state;
3474 result[0] = '\0';
3476 /* Iterate over all files in directory */
3478 do_dir(InBuffer, OutBuffer, mask, attribute, complete_process_file, False,
3479 True);
3481 /* Clean up */
3483 free(InBuffer);
3484 free(OutBuffer);
3486 /* Return matched filename */
3488 if (result[0] != '\0') {
3489 return strdup(result); /* Readline will dispose of strings */
3490 } else {
3491 return NULL;
3495 /* Complete a smbclient command */
3497 char *complete_cmd(char *text, int state)
3499 static int cmd_index;
3500 char *name;
3502 /* Initialise */
3504 if (state == 0) {
3505 cmd_index = 0;
3508 /* Return the next name which partially matches the list of commands */
3510 while (strlen(name = commands[cmd_index++].name) > 0) {
3511 if (strncmp(name, text, strlen(text)) == 0) {
3512 return strdup(name);
3516 return NULL;
3519 /* Main completion function for smbclient. Work out which word we are
3520 trying to complete and call the appropriate function. */
3522 char **completion_fn(char *text, int start, int end)
3524 int i, num_words, cmd_index;
3525 char lastch = ' ';
3527 /* If we are at the start of a word, we are completing a smbclient
3528 command. */
3530 if (start == 0) {
3531 return completion_matches(text, complete_cmd);
3534 /* Count # of words in command */
3536 num_words = 0;
3537 for (i = 0; i <= end; i++) {
3538 if ((rl_line_buffer[i] != ' ') && (lastch == ' '))
3539 num_words++;
3540 lastch = rl_line_buffer[i];
3543 if (rl_line_buffer[end] == ' ')
3544 num_words++;
3546 /* Work out which command we are completing for */
3548 for (cmd_index = 0; strcmp(commands[cmd_index].name, "") != 0;
3549 cmd_index++) {
3551 /* Check each command in array */
3553 if (strncmp(rl_line_buffer, commands[cmd_index].name,
3554 strlen(commands[cmd_index].name)) == 0) {
3556 /* Call appropriate completion function */
3558 if ((num_words == 2) || (num_words == 3)) {
3559 switch (commands[cmd_index].compl_args[num_words - 2]) {
3561 case COMPL_REMOTE:
3562 return completion_matches(text, complete_remote_file);
3563 break;
3565 case COMPL_LOCAL:
3566 return completion_matches(text, filename_completion_function);
3567 break;
3569 default:
3570 /* An invalid completion type */
3571 break;
3575 /* We're either completing an argument > 3 or found an invalid
3576 completion type. Either way do nothing about it. */
3578 break;
3582 return NULL;
3585 #endif /* HAVE_LIBREADLINE */
3587 /****************************************************************************
3588 process commands from the client
3589 ****************************************************************************/
3590 static BOOL process(char *base_directory)
3592 pstring line;
3593 char *cmd;
3595 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3596 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3598 if ((InBuffer == NULL) || (OutBuffer == NULL))
3599 return(False);
3601 bzero(OutBuffer,smb_size);
3603 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3604 return(False);
3606 if (*base_directory) do_cd(base_directory);
3608 cmd = cmdstr;
3609 if (cmd[0] != '\0') while (cmd[0] != '\0')
3611 char *p;
3612 fstring tok;
3613 int i;
3615 if ((p = strchr(cmd, ';')) == 0)
3617 strncpy(line, cmd, 999);
3618 line[1000] = '\0';
3619 cmd += strlen(cmd);
3621 else
3623 if (p - cmd > 999) p = cmd + 999;
3624 strncpy(line, cmd, p - cmd);
3625 line[p - cmd] = '\0';
3626 cmd = p + 1;
3629 /* input language code to internal one */
3630 CNV_INPUT (line);
3632 /* and get the first part of the command */
3634 char *ptr = line;
3635 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
3638 if ((i = process_tok(tok)) >= 0)
3639 commands[i].fn(InBuffer,OutBuffer);
3640 else if (i == -2)
3641 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3642 else
3643 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3645 else while (!feof(stdin))
3647 fstring tok;
3648 int i;
3650 bzero(OutBuffer,smb_size);
3652 #ifdef HAVE_LIBREADLINE
3655 pstring prompt;
3657 /* Read input using GNU Readline */
3659 slprintf(prompt, sizeof(prompt) - 1, "smb: %s> ", CNV_LANG(cur_dir));
3660 if (!readline(prompt))
3661 break;
3663 /* Copy read line to samba buffer */
3665 pstrcpy(line, rl_line_buffer);
3666 pstrcat(line, "\n");
3668 /* Add line to history */
3670 if (strlen(line) > 0)
3671 add_history(line);
3674 #else
3676 /* display a prompt */
3677 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3678 dbgflush( );
3680 wait_keyboard(InBuffer);
3682 /* and get a response */
3683 if (!fgets(line,1000,stdin))
3684 break;
3686 #endif
3688 /* input language code to internal one */
3689 CNV_INPUT (line);
3691 /* special case - first char is ! */
3692 if (*line == '!')
3694 system(line + 1);
3695 continue;
3698 /* and get the first part of the command */
3700 char *ptr = line;
3701 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
3704 if ((i = process_tok(tok)) >= 0)
3705 commands[i].fn(InBuffer,OutBuffer);
3706 else if (i == -2)
3707 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3708 else
3709 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3712 cli_send_logout(InBuffer,OutBuffer);
3713 return(True);
3716 /****************************************************************************
3717 usage on the program
3718 ****************************************************************************/
3719 static void usage(char *pname)
3721 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3722 pname));
3724 DEBUG(0,("\nVersion %s\n",VERSION));
3725 DEBUG(0,("\t-p port connect to the specified port\n"));
3726 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3727 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3728 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3729 DEBUG(0,("\t-N don't ask for a password\n"));
3730 DEBUG(0,("\t-P connect to service as a printer\n"));
3731 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3732 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3733 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3734 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3735 DEBUG(0,("\t-R name resolve order use these name resolution services only\n"));
3736 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3737 DEBUG(0,("\t-U username set the network username\n"));
3738 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3739 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3740 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3741 DEBUG(0,("\t-T<c|x>IXgbNan command line tar\n"));
3742 DEBUG(0,("\t-D directory start from directory\n"));
3743 DEBUG(0,("\n"));
3746 /****************************************************************************
3747 main program
3748 ****************************************************************************/
3749 int main(int argc,char *argv[])
3751 fstring base_directory;
3752 char *pname = argv[0];
3753 int port = SMB_PORT;
3754 int opt;
3755 extern FILE *dbf;
3756 extern char *optarg;
3757 extern int optind;
3758 pstring query_host;
3759 BOOL message = False;
3760 BOOL nt_domain_logon = False;
3761 BOOL explicit_user = False;
3762 extern char tar_type;
3763 static pstring servicesf = CONFIGFILE;
3764 pstring term_code;
3765 pstring new_name_resolve_order;
3766 char *p;
3768 #ifdef KANJI
3769 pstrcpy(term_code, KANJI);
3770 #else /* KANJI */
3771 *term_code = 0;
3772 #endif /* KANJI */
3774 *query_host = 0;
3775 *base_directory = 0;
3777 *new_name_resolve_order = 0;
3779 DEBUGLEVEL = 2;
3781 setup_logging(pname,True);
3783 TimeInit();
3784 charset_initialise();
3786 if(!get_myname(myhostname,NULL))
3788 DEBUG(0,("Failed to get my hostname.\n"));
3791 if (!lp_load(servicesf,True,False,False)) {
3792 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3795 codepage_initialise(lp_client_code_page());
3797 interpret_coding_system(term_code);
3799 #ifdef WITH_SSL
3800 sslutil_init(0);
3801 #endif
3803 pstrcpy(workgroup,lp_workgroup());
3805 load_interfaces();
3806 pid = getpid();
3807 uid = getuid();
3808 gid = getgid();
3809 mid = pid + 100;
3810 myumask = umask(0);
3811 umask(myumask);
3813 if (getenv("USER"))
3815 pstrcpy(username,getenv("USER"));
3817 /* modification to support userid%passwd syntax in the USER var
3818 25.Aug.97, jdblair@uab.edu */
3820 if ((p=strchr(username,'%')))
3822 *p = 0;
3823 pstrcpy(password,p+1);
3824 got_pass = True;
3825 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3827 strupper(username);
3830 /* modification to support PASSWD environmental var
3831 25.Aug.97, jdblair@uab.edu */
3833 if (getenv("PASSWD")) {
3834 pstrcpy(password,getenv("PASSWD"));
3835 got_pass = True;
3838 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
3839 int fd = -1;
3840 BOOL close_it = False;
3841 pstring spec;
3842 char pass[128];
3844 if ((p = getenv("PASSWD_FD")) != NULL) {
3845 pstrcpy(spec, "descriptor ");
3846 pstrcat(spec, p);
3847 sscanf(p, "%d", &fd);
3848 close_it = False;
3849 } else if ((p = getenv("PASSWD_FILE")) != NULL) {
3850 fd = open(p, O_RDONLY);
3851 pstrcpy(spec, p);
3852 if (fd < 0) {
3853 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
3854 spec, strerror(errno));
3855 exit(1);
3857 close_it = True;
3859 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
3860 p && p - pass < sizeof(pass);) {
3861 switch (read(fd, p, 1)) {
3862 case 1:
3863 if (*p != '\n' && *p != '\0') {
3864 *++p = '\0'; /* advance p, and null-terminate pass */
3865 break;
3867 case 0:
3868 if (p - pass) {
3869 *p = '\0'; /* null-terminate it, just in case... */
3870 p = NULL; /* then force the loop condition to become false */
3871 break;
3872 } else {
3873 fprintf(stderr, "Error reading password from file %s: %s\n",
3874 spec, "empty password\n");
3875 exit(1);
3878 default:
3879 fprintf(stderr, "Error reading password from file %s: %s\n",
3880 spec, strerror(errno));
3881 exit(1);
3884 pstrcpy(password, pass);
3885 got_pass = True;
3886 if (close_it)
3887 close(fd);
3890 if (*username == 0 && getenv("LOGNAME"))
3892 pstrcpy(username,getenv("LOGNAME"));
3893 strupper(username);
3896 if (argc < 2)
3898 usage(pname);
3899 exit(1);
3902 if (*argv[1] != '-')
3905 pstrcpy(service,argv[1]);
3906 /* Convert any '/' characters in the service name to '\' characters */
3907 string_replace( service, '/','\\');
3908 argc--;
3909 argv++;
3911 if (count_chars(service,'\\') < 3)
3913 usage(pname);
3914 printf("\n%s: Not enough '\\' characters in service\n",service);
3915 exit(1);
3919 if (count_chars(service,'\\') > 3)
3921 usage(pname);
3922 printf("\n%s: Too many '\\' characters in service\n",service);
3923 exit(1);
3927 if (argc > 1 && (*argv[1] != '-'))
3929 got_pass = True;
3930 pstrcpy(password,argv[1]);
3931 memset(argv[1],'X',strlen(argv[1]));
3932 argc--;
3933 argv++;
3937 while ((opt =
3938 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)
3939 switch (opt)
3941 case 'm':
3942 max_protocol = interpret_protocol(optarg,max_protocol);
3943 break;
3944 case 'O':
3945 pstrcpy(user_socket_options,optarg);
3946 break;
3947 case 'R':
3948 pstrcpy(new_name_resolve_order, optarg);
3949 break;
3950 case 'S':
3951 pstrcpy(desthost,optarg);
3952 strupper(desthost);
3953 nt_domain_logon = True;
3954 break;
3955 case 'M':
3956 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3957 pstrcpy(desthost,optarg);
3958 strupper(desthost);
3959 message = True;
3960 break;
3961 case 'B':
3962 iface_set_default(NULL,optarg,NULL);
3963 break;
3964 case 'D':
3965 pstrcpy(base_directory,optarg);
3966 break;
3967 case 'T':
3968 if (!tar_parseargs(argc, argv, optarg, optind)) {
3969 usage(pname);
3970 exit(1);
3972 break;
3973 case 'i':
3974 pstrcpy(scope,optarg);
3975 break;
3976 case 'L':
3977 got_pass = True;
3978 pstrcpy(query_host,optarg);
3979 if(!explicit_user)
3980 *username = '\0';
3981 break;
3982 case 'U':
3984 char *lp;
3985 explicit_user = True;
3986 pstrcpy(username,optarg);
3987 if ((lp=strchr(username,'%')))
3989 *lp = 0;
3990 pstrcpy(password,lp+1);
3991 got_pass = True;
3992 memset(strchr(optarg,'%')+1,'X',strlen(password));
3996 break;
3997 case 'W':
3998 pstrcpy(workgroup,optarg);
3999 break;
4000 case 'E':
4001 dbf = stderr;
4002 break;
4003 case 'I':
4005 dest_ip = *interpret_addr2(optarg);
4006 if (zero_ip(dest_ip)) exit(1);
4007 have_ip = True;
4009 break;
4010 case 'n':
4011 pstrcpy(global_myname,optarg);
4012 break;
4013 case 'N':
4014 got_pass = True;
4015 no_pass = True;
4016 break;
4017 case 'P':
4018 connect_as_printer = True;
4019 break;
4020 case 'd':
4021 if (*optarg == 'A')
4022 DEBUGLEVEL = 10000;
4023 else
4024 DEBUGLEVEL = atoi(optarg);
4025 break;
4026 case 'l':
4027 slprintf(debugf,sizeof(debugf)-1, "%s.client",optarg);
4028 break;
4029 case 'p':
4030 port = atoi(optarg);
4031 break;
4032 case 'c':
4033 cmdstr = optarg;
4034 got_pass = True;
4035 break;
4036 case 'h':
4037 usage(pname);
4038 exit(0);
4039 break;
4040 case 's':
4041 pstrcpy(servicesf, optarg);
4042 break;
4043 case 't':
4044 pstrcpy(term_code, optarg);
4045 break;
4046 default:
4047 usage(pname);
4048 exit(1);
4051 get_myname((*global_myname)?NULL:global_myname,NULL);
4052 strupper(global_myname);
4054 if(*new_name_resolve_order)
4055 lp_set_name_resolve_order(new_name_resolve_order);
4057 if (!tar_type && !*query_host && !*service && !message)
4059 usage(pname);
4060 exit(1);
4063 #ifdef HAVE_LIBREADLINE
4065 /* Initialise GNU Readline */
4067 rl_readline_name = "smbclient";
4068 rl_attempted_completion_function = completion_fn;
4069 rl_completion_entry_function = (Function *)complete_cmd_null;
4071 /* Initialise history list */
4073 using_history();
4075 #endif /* HAVE_LIBREADLINE */
4077 DEBUG( 3, ( "Client started (version %s).\n", VERSION ) );
4079 if (tar_type) {
4080 recurse=True;
4082 if (cli_open_sockets(port)) {
4083 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4084 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4085 int ret;
4087 if ((InBuffer == NULL) || (OutBuffer == NULL))
4088 return(1);
4090 bzero(OutBuffer,smb_size);
4091 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
4092 return(False);
4094 if (*base_directory) do_cd(base_directory);
4096 ret=process_tar(InBuffer, OutBuffer);
4098 cli_send_logout(InBuffer, OutBuffer);
4099 close_sockets();
4100 return(ret);
4101 } else
4102 return(1);
4105 if (*query_host && !nt_domain_logon)
4107 int ret = 0;
4108 slprintf(service,sizeof(service)-1,
4109 "\\\\%s\\IPC$",query_host);
4110 strupper(service);
4111 connect_as_ipc = True;
4112 if (cli_open_sockets(port))
4114 #if 0
4115 *username = 0;
4116 #endif
4117 if (!cli_send_login(NULL,NULL,True,True,NULL))
4118 return(1);
4120 server_info();
4121 if (!browse_host(True)) {
4122 sleep(1);
4123 browse_host(True);
4125 if (!list_servers(workgroup)) {
4126 sleep(1);
4127 list_servers(workgroup);
4130 cli_send_logout(NULL,NULL);
4131 close_sockets();
4134 return(ret);
4137 if (message)
4139 int ret = 0;
4140 if (cli_open_sockets(port))
4142 pstring inbuf,outbuf;
4143 bzero(outbuf,smb_size);
4144 if (!cli_send_session_request(inbuf,outbuf))
4145 return(1);
4147 send_message(inbuf,outbuf);
4149 close_sockets();
4152 return(ret);
4155 if (cli_open_sockets(port))
4157 if (!process(base_directory))
4159 close_sockets();
4160 return(1);
4162 close_sockets();
4164 else
4165 return(1);
4167 return(0);