Added E Jay Berkenbilt's fixes
[Samba/gbeck.git] / source3 / client / client.c
blobc4f763db7786f4077506371fa7f5606ff707ffc4
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 BOOL in_client;
33 extern pstring service;
34 extern pstring desthost;
35 extern pstring global_myname;
36 extern pstring myhostname;
37 extern pstring password;
38 extern pstring username;
39 extern pstring workgroup;
40 char *cmdstr="";
41 extern BOOL got_pass;
42 extern BOOL no_pass;
43 extern BOOL connect_as_printer;
44 extern BOOL connect_as_ipc;
45 extern struct in_addr ipzero;
47 extern BOOL doencrypt;
49 extern pstring user_socket_options;
51 static int process_tok(fstring tok);
52 static void cmd_help(char *dum_in, char *dum_out);
54 /* 30 second timeout on most commands */
55 #define CLIENT_TIMEOUT (30*1000)
56 #define SHORT_TIMEOUT (5*1000)
58 /* value for unused fid field in trans2 secondary request */
59 #define FID_UNUSED (0xFFFF)
61 extern int name_type;
63 extern int max_protocol;
66 time_t newer_than = 0;
67 int archive_level = 0;
69 extern pstring debugf;
70 extern int DEBUGLEVEL;
72 BOOL translation = False;
74 extern uint16 cnum;
75 extern uint16 mid;
76 extern uint16 pid;
77 extern uint16 vuid;
79 extern BOOL have_ip;
80 extern int max_xmit;
82 static int interpret_long_filename(int level,char *p,file_info *finfo);
83 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo);
84 static int interpret_short_filename(char *p,file_info *finfo);
85 static BOOL do_this_one(file_info *finfo);
87 /* clitar bits insert */
88 extern int blocksize;
89 extern BOOL tar_inc;
90 extern BOOL tar_reset;
91 /* clitar bits end */
94 mode_t myumask = 0755;
96 extern pstring scope;
98 BOOL prompt = True;
100 int printmode = 1;
102 BOOL recurse = False;
103 BOOL lowercase = False;
105 struct in_addr dest_ip;
107 #define SEPARATORS " \t\n\r"
109 BOOL abort_mget = True;
111 extern int Protocol;
113 extern BOOL readbraw_supported ;
114 extern BOOL writebraw_supported;
116 pstring fileselection = "";
118 extern file_info def_finfo;
120 /* timing globals */
121 int get_total_size = 0;
122 int get_total_time_ms = 0;
123 int put_total_size = 0;
124 int put_total_time_ms = 0;
126 /* totals globals */
127 int dir_total = 0;
129 extern int Client;
131 #define USENMB
133 #define CNV_LANG(s) dos_to_unix(s,False)
134 #define CNV_INPUT(s) unix_to_dos(s,True)
136 /****************************************************************************
137 send an SMBclose on an SMB file handle
138 ****************************************************************************/
139 static void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
141 bzero(outbuf,smb_size);
142 set_message(outbuf,3,0,True);
144 CVAL (outbuf,smb_com) = SMBclose;
145 SSVAL(outbuf,smb_tid,c_num);
146 cli_setup_pkt(outbuf);
147 SSVAL (outbuf,smb_vwv0, f_num);
148 SIVALS(outbuf,smb_vwv1, -1);
150 send_smb(clnt_fd, outbuf);
151 client_receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
155 /****************************************************************************
156 write to a local file with CR/LF->LF translation if appropriate. return the
157 number taken from the buffer. This may not equal the number written.
158 ****************************************************************************/
159 static int writefile(int f, char *b, int n)
161 int i;
163 if (!translation)
164 return(write(f,b,n));
166 i = 0;
167 while (i < n)
169 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
171 b++;i++;
173 if (write(f, b, 1) != 1)
175 break;
177 b++;
178 i++;
181 return(i);
184 /****************************************************************************
185 read from a file with LF->CR/LF translation if appropriate. return the
186 number read. read approx n bytes.
187 ****************************************************************************/
188 static int readfile(char *b, int size, int n, FILE *f)
190 int i;
191 int c;
193 if (!translation || (size != 1))
194 return(fread(b,size,n,f));
196 i = 0;
197 while (i < n)
199 if ((c = getc(f)) == EOF)
201 break;
204 if (c == '\n') /* change all LFs to CR/LF */
206 b[i++] = '\r';
207 n++;
210 if(i < n)
211 b[i++] = c;
214 return(i);
218 /****************************************************************************
219 read from a file with print translation. return the number read. read approx n
220 bytes.
221 ****************************************************************************/
222 static int printread(FILE *f,char *b,int n)
224 int i;
226 i = readfile(b,1, n-1,f);
227 #if FORMFEED
228 if (feof(f) && i>0)
229 b[i++] = '\014';
230 #endif
232 return(i);
235 /****************************************************************************
236 check for existance of a dir
237 ****************************************************************************/
238 static BOOL chkpath(char *path,BOOL report)
240 fstring path2;
241 pstring inbuf,outbuf;
242 char *p;
244 fstrcpy(path2,path);
245 trim_string(path2,NULL,"\\");
246 if (!*path2) *path2 = '\\';
248 bzero(outbuf,smb_size);
249 set_message(outbuf,0,4 + strlen(path2),True);
250 SCVAL(outbuf,smb_com,SMBchkpth);
251 SSVAL(outbuf,smb_tid,cnum);
252 cli_setup_pkt(outbuf);
254 p = smb_buf(outbuf);
255 *p++ = 4;
256 fstrcpy(p,path2);
258 #if 0
260 /* this little bit of code can be used to extract NT error codes.
261 Just feed a bunch of "cd foo" commands to smbclient then watch
262 in netmon (tridge) */
263 static int code=0;
264 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
265 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
266 code++;
268 #endif
270 send_smb(Client,outbuf);
271 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
273 if (report && CVAL(inbuf,smb_rcls) != 0)
274 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
276 return(CVAL(inbuf,smb_rcls) == 0);
280 /****************************************************************************
281 send a message
282 ****************************************************************************/
283 static void send_message(char *inbuf,char *outbuf)
285 int total_len = 0;
287 char *p;
288 int grp_id;
290 /* send a SMBsendstrt command */
291 bzero(outbuf,smb_size);
292 set_message(outbuf,0,0,True);
293 CVAL(outbuf,smb_com) = SMBsendstrt;
294 SSVAL(outbuf,smb_tid,cnum);
296 p = smb_buf(outbuf);
297 *p++ = 4;
298 pstrcpy(p,username);
299 p = skip_string(p,1);
300 *p++ = 4;
301 pstrcpy(p,desthost);
302 p = skip_string(p,1);
304 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
306 send_smb(Client,outbuf);
309 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
311 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
312 return;
315 grp_id = SVAL(inbuf,smb_vwv0);
317 printf("Connected. Type your message, ending it with a Control-D\n");
319 while (!feof(stdin) && total_len < 1600)
321 int maxlen = MIN(1600 - total_len,127);
322 pstring msg;
323 int l=0;
324 int c;
326 bzero(msg,smb_size);
328 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
330 if (c == '\n')
331 msg[l++] = '\r';
332 msg[l] = c;
335 CVAL(outbuf,smb_com) = SMBsendtxt;
337 set_message(outbuf,1,l+3,True);
339 SSVAL(outbuf,smb_vwv0,grp_id);
341 p = smb_buf(outbuf);
342 *p = 1;
343 SSVAL(p,1,l);
344 memcpy(p+3,msg,l);
346 send_smb(Client,outbuf);
349 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
351 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
352 return;
355 total_len += l;
358 if (total_len >= 1600)
359 printf("the message was truncated to 1600 bytes ");
360 else
361 printf("sent %d bytes ",total_len);
363 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
365 CVAL(outbuf,smb_com) = SMBsendend;
366 set_message(outbuf,1,0,False);
367 SSVAL(outbuf,smb_vwv0,grp_id);
369 send_smb(Client,outbuf);
372 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
374 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
375 return;
381 /****************************************************************************
382 check the space on a device
383 ****************************************************************************/
384 static void do_dskattr(void)
386 pstring inbuf,outbuf;
388 bzero(outbuf,smb_size);
389 set_message(outbuf,0,0,True);
390 CVAL(outbuf,smb_com) = SMBdskattr;
391 SSVAL(outbuf,smb_tid,cnum);
392 cli_setup_pkt(outbuf);
394 send_smb(Client,outbuf);
395 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
397 if (CVAL(inbuf,smb_rcls) != 0)
398 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
400 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
401 SVAL(inbuf,smb_vwv0),
402 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
403 SVAL(inbuf,smb_vwv3)));
406 /****************************************************************************
407 show cd/pwd
408 ****************************************************************************/
409 static void cmd_pwd(char *dum_in, char *dum_out)
411 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
412 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
416 /****************************************************************************
417 change directory - inner section
418 ****************************************************************************/
419 static void do_cd(char *newdir)
421 char *p = newdir;
422 pstring saved_dir;
423 pstring dname;
425 dos_format(newdir);
427 /* Save the current directory in case the
428 new directory is invalid */
429 pstrcpy(saved_dir, cur_dir);
430 if (*p == '\\')
431 pstrcpy(cur_dir,p);
432 else
433 pstrcat(cur_dir,p);
434 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
435 pstrcat(cur_dir, "\\");
437 dos_clean_name(cur_dir);
438 pstrcpy(dname,cur_dir);
439 pstrcat(cur_dir,"\\");
440 dos_clean_name(cur_dir);
442 if (!strequal(cur_dir,"\\"))
443 if (!chkpath(dname,True))
444 pstrcpy(cur_dir,saved_dir);
446 pstrcpy(cd_path,cur_dir);
449 /****************************************************************************
450 change directory
451 ****************************************************************************/
452 static void cmd_cd(char *inbuf,char *outbuf)
454 fstring buf;
456 if (next_token(NULL,buf,NULL,sizeof(buf)))
457 do_cd(buf);
458 else
459 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
463 /****************************************************************************
464 display info about a file
465 ****************************************************************************/
466 static void display_finfo(file_info *finfo)
468 if (do_this_one(finfo)) {
469 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
470 DEBUG(0,(" %-30s%7.7s%.0f %s",
471 CNV_LANG(finfo->name),
472 attrib_string(finfo->mode),
473 (double)finfo->size,
474 asctime(LocalTime(&t))));
475 dir_total += finfo->size;
480 /****************************************************************************
481 calculate size of a file
482 ****************************************************************************/
483 static void do_du(file_info *finfo)
485 if (do_this_one(finfo)) {
486 dir_total += finfo->size;
491 /****************************************************************************
492 do a directory listing, calling fn on each file found. Use the TRANSACT2
493 call for long filenames
494 ****************************************************************************/
495 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
497 int max_matches = 512;
498 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
499 char *p;
500 pstring mask;
501 file_info finfo;
502 int i;
503 char *dirlist = NULL;
504 int dirlist_len = 0;
505 int total_received = 0;
506 BOOL First = True;
507 char *resp_data=NULL;
508 char *resp_param=NULL;
509 int resp_data_len = 0;
510 int resp_param_len=0;
512 int ff_resume_key = 0;
513 int ff_searchcount=0;
514 int ff_eos=0;
515 int ff_lastname=0;
516 int ff_dir_handle=0;
517 int loop_count = 0;
519 uint16 setup;
520 pstring param;
522 pstrcpy(mask,Mask);
524 while (ff_eos == 0)
526 loop_count++;
527 if (loop_count > 200)
529 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
530 break;
533 if (First)
535 setup = TRANSACT2_FINDFIRST;
536 SSVAL(param,0,attribute); /* attribute */
537 SSVAL(param,2,max_matches); /* max count */
538 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
539 SSVAL(param,6,info_level);
540 SIVAL(param,8,0);
541 pstrcpy(param+12,mask);
543 else
545 setup = TRANSACT2_FINDNEXT;
546 SSVAL(param,0,ff_dir_handle);
547 SSVAL(param,2,max_matches); /* max count */
548 SSVAL(param,4,info_level);
549 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
550 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
551 pstrcpy(param+12,mask);
553 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
554 ff_dir_handle,ff_resume_key,ff_lastname,mask));
556 /* ??? original code added 1 pad byte after param */
558 cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
559 NULL,param,&setup,
560 0,12+strlen(mask)+1,1,
561 BUFFER_SIZE,10,0);
563 if (!cli_receive_trans_response(inbuf,SMBtrans2,
564 &resp_data_len,&resp_param_len,
565 &resp_data,&resp_param))
567 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
568 break;
571 /* parse out some important return info */
572 p = resp_param;
573 if (First)
575 ff_dir_handle = SVAL(p,0);
576 ff_searchcount = SVAL(p,2);
577 ff_eos = SVAL(p,4);
578 ff_lastname = SVAL(p,8);
580 else
582 ff_searchcount = SVAL(p,0);
583 ff_eos = SVAL(p,2);
584 ff_lastname = SVAL(p,6);
587 if (ff_searchcount == 0)
588 break;
590 /* point to the data bytes */
591 p = resp_data;
593 /* we might need the lastname for continuations */
594 if (ff_lastname > 0)
596 switch(info_level)
598 case 260:
599 ff_resume_key =0;
600 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
601 /* pstrcpy(mask,p+ff_lastname+94); */
602 break;
603 case 1:
604 pstrcpy(mask,p + ff_lastname + 1);
605 ff_resume_key = 0;
606 break;
609 else
610 pstrcpy(mask,"");
612 /* and add them to the dirlist pool */
613 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
615 if (!dirlist)
617 DEBUG(0,("Failed to expand dirlist\n"));
618 break;
621 /* put in a length for the last entry, to ensure we can chain entries
622 into the next packet */
624 char *p2;
625 for (p2=p,i=0;i<(ff_searchcount-1);i++)
626 p2 += interpret_long_filename(info_level,p2,NULL);
627 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
630 /* grab the data for later use */
631 memcpy(dirlist+dirlist_len,p,resp_data_len);
632 dirlist_len += resp_data_len;
634 total_received += ff_searchcount;
636 if (resp_data) free(resp_data); resp_data = NULL;
637 if (resp_param) free(resp_param); resp_param = NULL;
639 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
640 ff_searchcount,ff_eos,ff_resume_key));
642 First = False;
645 if (!fn)
646 for (p=dirlist,i=0;i<total_received;i++)
648 p += interpret_long_filename(info_level,p,&finfo);
649 display_finfo(&finfo);
652 for (p=dirlist,i=0;i<total_received;i++)
654 p += interpret_long_filename(info_level,p,&finfo);
655 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True, dirstoo);
658 /* free up the dirlist buffer */
659 if (dirlist) free(dirlist);
660 return(total_received);
664 /****************************************************************************
665 do a directory listing, calling fn on each file found
666 ****************************************************************************/
667 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
669 char *p;
670 int received = 0;
671 BOOL first = True;
672 char status[21];
673 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
674 int num_received = 0;
675 int i;
676 char *dirlist = NULL;
677 pstring mask;
678 file_info finfo;
680 finfo = def_finfo;
682 bzero(status,21);
684 pstrcpy(mask,Mask);
686 while (1)
688 bzero(outbuf,smb_size);
689 if (first)
690 set_message(outbuf,2,5 + strlen(mask),True);
691 else
692 set_message(outbuf,2,5 + 21,True);
694 #if FFIRST
695 if (Protocol >= PROTOCOL_LANMAN1)
696 CVAL(outbuf,smb_com) = SMBffirst;
697 else
698 #endif
699 CVAL(outbuf,smb_com) = SMBsearch;
701 SSVAL(outbuf,smb_tid,cnum);
702 cli_setup_pkt(outbuf);
704 SSVAL(outbuf,smb_vwv0,num_asked);
705 SSVAL(outbuf,smb_vwv1,attribute);
707 p = smb_buf(outbuf);
708 *p++ = 4;
710 if (first)
711 pstrcpy(p,mask);
712 else
713 pstrcpy(p,"");
714 p += strlen(p) + 1;
716 *p++ = 5;
717 if (first)
718 SSVAL(p,0,0);
719 else
721 SSVAL(p,0,21);
722 p += 2;
723 memcpy(p,status,21);
726 send_smb(Client,outbuf);
727 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
729 received = SVAL(inbuf,smb_vwv0);
731 DEBUG(5,("dir received %d\n",received));
733 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
735 if (received <= 0) break;
737 first = False;
739 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
741 if (!dirlist)
742 return 0;
744 p = smb_buf(inbuf) + 3;
746 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
747 p,received*DIR_STRUCT_SIZE);
749 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
751 num_received += received;
753 if (CVAL(inbuf,smb_rcls) != 0) break;
756 #if FFIRST
757 if (!first && Protocol >= PROTOCOL_LANMAN1)
759 bzero(outbuf,smb_size);
760 CVAL(outbuf,smb_com) = SMBfclose;
762 SSVAL(outbuf,smb_tid,cnum);
763 cli_setup_pkt(outbuf);
765 p = smb_buf(outbuf);
766 *p++ = 4;
768 pstrcpy(p,"");
769 p += strlen(p) + 1;
771 *p++ = 5;
772 SSVAL(p,0,21);
773 p += 2;
774 memcpy(p,status,21);
776 send_smb(Client,outbuf);
777 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
779 if (CVAL(inbuf,smb_rcls) != 0)
780 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
782 #endif
784 if (!fn)
785 for (p=dirlist,i=0;i<num_received;i++)
787 p += interpret_short_filename(p,&finfo);
788 display_finfo(&finfo);
791 for (p=dirlist,i=0;i<num_received;i++)
793 p += interpret_short_filename(p,&finfo);
794 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False,dirstoo);
797 if (dirlist) free(dirlist);
798 return(num_received);
803 /****************************************************************************
804 do a directory listing, calling fn on each file found
805 ****************************************************************************/
806 void do_dir(char *inbuf,char *outbuf,char *mask,int attribute,void (*fn)(file_info *),BOOL recurse_dir, BOOL dirstoo)
808 dos_format(mask);
809 DEBUG(5,("do_dir(%s,%x,%s)\n",mask,attribute,BOOLSTR(recurse_dir)));
810 if (Protocol >= PROTOCOL_LANMAN2)
812 if (do_long_dir(inbuf,outbuf,mask,attribute,fn,recurse_dir,dirstoo) > 0)
813 return;
816 expand_mask(mask,False);
817 do_short_dir(inbuf,outbuf,mask,attribute,fn,recurse_dir,dirstoo);
818 return;
821 /*******************************************************************
822 decide if a file should be operated on
823 ********************************************************************/
824 static BOOL do_this_one(file_info *finfo)
826 if (finfo->mode & aDIR) return(True);
828 if (newer_than && finfo->mtime < newer_than)
829 return(False);
831 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
832 return(False);
834 return(True);
838 /*****************************************************************************
839 Convert a character pointer in a cli_call_api() response to a form we can use.
840 This function contains code to prevent core dumps if the server returns
841 invalid data.
842 *****************************************************************************/
843 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
845 if( datap == 0 ) /* turn NULL pointers */
846 { /* into zero length strings */
847 return "";
849 else
851 unsigned int offset = datap - converter;
853 if( offset >= rdrcnt )
855 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
856 return "<ERROR>";
858 else
860 return &rdata[offset];
865 /****************************************************************************
866 interpret a short filename structure
867 The length of the structure is returned
868 ****************************************************************************/
869 static int interpret_short_filename(char *p,file_info *finfo)
871 finfo->mode = CVAL(p,21);
873 /* this date is converted to GMT by make_unix_date */
874 finfo->ctime = make_unix_date(p+22);
875 finfo->mtime = finfo->atime = finfo->ctime;
876 finfo->size = IVAL(p,26);
877 pstrcpy(finfo->name,p+30);
879 return(DIR_STRUCT_SIZE);
882 /****************************************************************************
883 interpret a long filename structure - this is mostly guesses at the moment
884 The length of the structure is returned
885 The structure of a long filename depends on the info level. 260 is used
886 by NT and 2 is used by OS/2
887 ****************************************************************************/
888 static int interpret_long_filename(int level,char *p,file_info *finfo)
890 if (finfo)
891 memcpy(finfo,&def_finfo,sizeof(*finfo));
893 switch (level)
895 case 1: /* OS/2 understands this */
896 if (finfo)
898 /* these dates are converted to GMT by make_unix_date */
899 finfo->ctime = make_unix_date2(p+4);
900 finfo->atime = make_unix_date2(p+8);
901 finfo->mtime = make_unix_date2(p+12);
902 finfo->size = IVAL(p,16);
903 finfo->mode = CVAL(p,24);
904 pstrcpy(finfo->name,p+27);
906 return(28 + CVAL(p,26));
908 case 2: /* this is what OS/2 uses mostly */
909 if (finfo)
911 /* these dates are converted to GMT by make_unix_date */
912 finfo->ctime = make_unix_date2(p+4);
913 finfo->atime = make_unix_date2(p+8);
914 finfo->mtime = make_unix_date2(p+12);
915 finfo->size = IVAL(p,16);
916 finfo->mode = CVAL(p,24);
917 pstrcpy(finfo->name,p+31);
919 return(32 + CVAL(p,30));
921 /* levels 3 and 4 are untested */
922 case 3:
923 if (finfo)
925 /* these dates are probably like the other ones */
926 finfo->ctime = make_unix_date2(p+8);
927 finfo->atime = make_unix_date2(p+12);
928 finfo->mtime = make_unix_date2(p+16);
929 finfo->size = IVAL(p,20);
930 finfo->mode = CVAL(p,28);
931 pstrcpy(finfo->name,p+33);
933 return(SVAL(p,4)+4);
935 case 4:
936 if (finfo)
938 /* these dates are probably like the other ones */
939 finfo->ctime = make_unix_date2(p+8);
940 finfo->atime = make_unix_date2(p+12);
941 finfo->mtime = make_unix_date2(p+16);
942 finfo->size = IVAL(p,20);
943 finfo->mode = CVAL(p,28);
944 pstrcpy(finfo->name,p+37);
946 return(SVAL(p,4)+4);
948 case 260: /* NT uses this, but also accepts 2 */
949 if (finfo)
951 int ret = SVAL(p,0);
952 int namelen;
953 p += 4; /* next entry offset */
954 p += 4; /* fileindex */
956 /* these dates appear to arrive in a weird way. It seems to
957 be localtime plus the serverzone given in the initial
958 connect. This is GMT when DST is not in effect and one
959 hour from GMT otherwise. Can this really be right??
961 I suppose this could be called kludge-GMT. Is is the GMT
962 you get by using the current DST setting on a different
963 localtime. It will be cheap to calculate, I suppose, as
964 no DST tables will be needed */
966 finfo->ctime = interpret_long_date(p); p += 8;
967 finfo->atime = interpret_long_date(p); p += 8;
968 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
969 finfo->size = IVAL(p,0); p += 8;
970 p += 8; /* alloc size */
971 finfo->mode = CVAL(p,0); p += 4;
972 namelen = IVAL(p,0); p += 4;
973 p += 4; /* EA size */
974 p += 2; /* short name len? */
975 p += 24; /* short name? */
976 StrnCpy(finfo->name,p,namelen);
977 return(ret);
979 return(SVAL(p,0));
982 DEBUG(1,("Unknown long filename format %d\n",level));
983 return(SVAL(p,0));
989 /****************************************************************************
990 act on the files in a dir listing
992 RJS, 4-Apr-1998, dirstoo added to allow caller to indicate that directories
993 should be processed as well.
994 ****************************************************************************/
995 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(file_info *),BOOL longdir, BOOL dirstoo)
998 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
999 !mask_match(finfo->name,fileselection,False,False)) &&
1000 !(recurse_dir && (strequal(finfo->name,".") ||
1001 strequal(finfo->name,".."))))
1003 if (recurse_dir && (finfo->mode & aDIR))
1005 pstring mask2;
1006 pstring sav_dir;
1008 if (fn && dirstoo && do_this_one(finfo)) { /* Do dirs, RJS */
1009 fn(finfo);
1012 pstrcpy(sav_dir,cur_dir);
1013 pstrcat(cur_dir,finfo->name);
1014 pstrcat(cur_dir,"\\");
1015 pstrcpy(mask2,cur_dir);
1017 if (!fn)
1018 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1020 pstrcat(mask2,"*");
1022 if (longdir)
1023 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1024 else
1025 do_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
1027 pstrcpy(cur_dir,sav_dir);
1029 else
1031 if (fn && do_this_one(finfo))
1032 fn(finfo);
1038 /****************************************************************************
1039 get a directory listing
1040 ****************************************************************************/
1041 static void cmd_dir(char *inbuf,char *outbuf)
1043 int attribute = aDIR | aSYSTEM | aHIDDEN;
1044 pstring mask;
1045 fstring buf;
1046 char *p=buf;
1048 dir_total = 0;
1049 pstrcpy(mask,cur_dir);
1050 if(mask[strlen(mask)-1]!='\\')
1051 pstrcat(mask,"\\");
1053 if (next_token(NULL,buf,NULL,sizeof(buf))) {
1054 dos_format(p);
1055 if (*p == '\\')
1056 pstrcpy(mask,p);
1057 else
1058 pstrcat(mask,p);
1060 else {
1061 pstrcat(mask,"*");
1064 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse,False);
1066 do_dskattr();
1068 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1072 /****************************************************************************
1073 get a directory listing
1074 ****************************************************************************/
1075 static void cmd_du(char *inbuf,char *outbuf)
1077 int attribute = aDIR | aSYSTEM | aHIDDEN;
1078 pstring mask;
1079 fstring buf;
1080 char *p=buf;
1082 dir_total = 0;
1083 pstrcpy(mask,cur_dir);
1084 if(mask[strlen(mask)-1]!='\\')
1085 pstrcat(mask,"\\");
1087 if (next_token(NULL,buf,NULL,sizeof(buf)))
1089 dos_format(p);
1090 if (*p == '\\')
1091 pstrcpy(mask,p);
1092 else
1093 pstrcat(mask,p);
1095 else {
1096 pstrcat(mask,"*");
1099 do_dir(inbuf,outbuf,mask,attribute,do_du,recurse,False);
1101 do_dskattr();
1103 DEBUG(0, ("Total number of bytes: %d\n", dir_total));
1106 /****************************************************************************
1107 get a file from rname to lname
1108 ****************************************************************************/
1109 static void do_get(char *rname,char *lname,file_info *finfo1)
1111 int handle=0,fnum;
1112 uint32 nread=0;
1113 char *p;
1114 BOOL newhandle = False;
1115 char *inbuf,*outbuf;
1116 file_info finfo;
1117 BOOL close_done = False;
1118 BOOL ignore_close_error = False;
1119 char *dataptr=NULL;
1120 int datalen=0;
1122 struct timeval tp_start;
1123 GetTimeOfDay(&tp_start);
1125 if (finfo1)
1126 finfo = *finfo1;
1127 else
1128 finfo = def_finfo;
1130 if (lowercase)
1131 strlower(lname);
1134 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1135 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1137 if (!inbuf || !outbuf)
1139 DEBUG(0,("out of memory\n"));
1140 return;
1143 bzero(outbuf,smb_size);
1144 set_message(outbuf,15,1 + strlen(rname),True);
1146 CVAL(outbuf,smb_com) = SMBopenX;
1147 SSVAL(outbuf,smb_tid,cnum);
1148 cli_setup_pkt(outbuf);
1150 SSVAL(outbuf,smb_vwv0,0xFF);
1151 SSVAL(outbuf,smb_vwv2,1); /* return additional info */
1152 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1153 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1154 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1155 SSVAL(outbuf,smb_vwv8,1);
1156 SSVAL(outbuf,smb_vwv11,0xffff);
1157 SSVAL(outbuf,smb_vwv12,0xffff);
1159 p = smb_buf(outbuf);
1160 pstrcpy(p,rname);
1161 p = skip_string(p,1);
1163 /* do a chained openX with a readX? */
1164 #if 1
1165 if (finfo.size > 0)
1167 DEBUG(3,("Chaining readX wth openX\n"));
1168 SSVAL(outbuf,smb_vwv0,SMBreadX);
1169 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1170 bzero(p,200);
1171 p -= smb_wct;
1172 SCVAL(p,smb_wct,10);
1173 SSVAL(p,smb_vwv0,0xFF);
1174 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1175 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1176 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1178 #endif
1180 if(!strcmp(lname,"-"))
1181 handle = fileno(stdout);
1182 else
1184 handle = creat(lname,0644);
1185 newhandle = True;
1187 if (handle < 0)
1189 DEBUG(0,("Error opening local file %s\n",lname));
1190 free(inbuf);free(outbuf);
1191 return;
1194 send_smb(Client,outbuf);
1195 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1197 if (CVAL(inbuf,smb_rcls) != 0)
1199 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1200 SVAL(inbuf,smb_err) == ERRnoresource &&
1201 cli_reopen_connection(inbuf,outbuf))
1203 do_get(rname,lname,finfo1);
1204 return;
1206 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1207 if(newhandle)
1208 close(handle);
1209 free(inbuf);free(outbuf);
1210 return;
1213 pstrcpy(finfo.name,rname);
1215 if (!finfo1)
1217 finfo.mode = SVAL(inbuf,smb_vwv3);
1218 /* these times arrive as LOCAL time, using the DST offset
1219 corresponding to that time, we convert them to GMT */
1220 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1221 finfo.atime = finfo.ctime = finfo.mtime;
1222 finfo.size = IVAL(inbuf,smb_vwv6);
1225 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1227 fnum = SVAL(inbuf,smb_vwv2);
1229 /* we might have got some data from a chained readX */
1230 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1232 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1233 datalen = SVAL(p,smb_vwv5);
1234 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1236 else
1238 dataptr = NULL;
1239 datalen = 0;
1243 DEBUG(2,("getting file %s of size %.0f bytes as %s ",
1244 CNV_LANG(finfo.name),
1245 (double)finfo.size,
1246 lname));
1248 while (nread < finfo.size && !close_done)
1250 int method = -1;
1251 static BOOL can_chain_close = True;
1253 p=NULL;
1255 DEBUG(3,("nread=%d max_xmit=%d fsize=%.0f\n",nread,max_xmit,(double)finfo.size));
1257 /* 3 possible read types. readbraw if a large block is required.
1258 readX + close if not much left and read if neither is supported */
1260 /* we might have already read some data from a chained readX */
1261 if (dataptr && datalen>0)
1262 method=3;
1264 /* if we can finish now then readX+close */
1265 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1266 ((finfo.size - nread) <
1267 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1268 method = 0;
1270 /* if we support readraw then use that */
1271 if (method<0 && readbraw_supported)
1272 method = 1;
1274 /* if we can then use readX */
1275 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1276 method = 2;
1278 switch (method)
1280 /* use readX */
1281 case 0:
1282 case 2:
1283 if (method == 0)
1284 close_done = True;
1286 /* use readX + close */
1287 bzero(outbuf,smb_size);
1288 set_message(outbuf,10,0,True);
1289 CVAL(outbuf,smb_com) = SMBreadX;
1290 SSVAL(outbuf,smb_tid,cnum);
1291 cli_setup_pkt(outbuf);
1293 if (close_done)
1295 CVAL(outbuf,smb_vwv0) = SMBclose;
1296 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1298 else
1299 CVAL(outbuf,smb_vwv0) = 0xFF;
1301 SSVAL(outbuf,smb_vwv2,fnum);
1302 SIVAL(outbuf,smb_vwv3,nread);
1303 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1304 SSVAL(outbuf,smb_vwv6,0);
1305 SIVAL(outbuf,smb_vwv7,0);
1306 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1308 if (close_done)
1310 p = smb_buf(outbuf);
1311 bzero(p,9);
1313 CVAL(p,0) = 3;
1314 SSVAL(p,1,fnum);
1315 SIVALS(p,3,-1);
1317 /* now set the total packet length */
1318 smb_setlen(outbuf,smb_len(outbuf)+9);
1321 send_smb(Client,outbuf);
1322 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1324 if (CVAL(inbuf,smb_rcls) != 0)
1326 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1327 break;
1330 if (close_done &&
1331 SVAL(inbuf,smb_vwv0) != SMBclose)
1333 /* NOTE: WfWg sometimes just ignores the chained
1334 command! This seems to break the spec? */
1335 DEBUG(3,("Rejected chained close?\n"));
1336 close_done = False;
1337 can_chain_close = False;
1338 ignore_close_error = True;
1341 datalen = SVAL(inbuf,smb_vwv5);
1342 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1343 break;
1345 /* use readbraw */
1346 case 1:
1348 static int readbraw_size = BUFFER_SIZE;
1350 extern int Client;
1351 bzero(outbuf,smb_size);
1352 set_message(outbuf,8,0,True);
1353 CVAL(outbuf,smb_com) = SMBreadbraw;
1354 SSVAL(outbuf,smb_tid,cnum);
1355 cli_setup_pkt(outbuf);
1356 SSVAL(outbuf,smb_vwv0,fnum);
1357 SIVAL(outbuf,smb_vwv1,nread);
1358 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1359 SSVAL(outbuf,smb_vwv4,0);
1360 SIVALS(outbuf,smb_vwv5,-1);
1361 send_smb(Client,outbuf);
1363 /* Now read the raw data into the buffer and write it */
1364 if(read_smb_length(Client,inbuf,0) == -1) {
1365 DEBUG(0,("Failed to read length in readbraw\n"));
1366 exit(1);
1369 /* Even though this is not an smb message, smb_len
1370 returns the generic length of an smb message */
1371 datalen = smb_len(inbuf);
1373 if (datalen == 0)
1375 /* we got a readbraw error */
1376 DEBUG(4,("readbraw error - reducing size\n"));
1377 readbraw_size = (readbraw_size * 9) / 10;
1379 if (readbraw_size < max_xmit)
1381 DEBUG(0,("disabling readbraw\n"));
1382 readbraw_supported = False;
1385 dataptr=NULL;
1386 continue;
1389 if(read_data(Client,inbuf,datalen) != datalen) {
1390 DEBUG(0,("Failed to read data in readbraw\n"));
1391 exit(1);
1393 dataptr = inbuf;
1395 break;
1397 case 3:
1398 /* we've already read some data with a chained readX */
1399 break;
1401 default:
1402 /* use plain read */
1403 bzero(outbuf,smb_size);
1404 set_message(outbuf,5,0,True);
1405 CVAL(outbuf,smb_com) = SMBread;
1406 SSVAL(outbuf,smb_tid,cnum);
1407 cli_setup_pkt(outbuf);
1409 SSVAL(outbuf,smb_vwv0,fnum);
1410 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1411 SIVAL(outbuf,smb_vwv2,nread);
1412 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1414 send_smb(Client,outbuf);
1415 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1417 if (CVAL(inbuf,smb_rcls) != 0)
1419 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1420 break;
1423 datalen = SVAL(inbuf,smb_vwv0);
1424 dataptr = smb_buf(inbuf) + 3;
1425 break;
1428 if (writefile(handle,dataptr,datalen) != datalen)
1430 DEBUG(0,("Error writing local file\n"));
1431 break;
1434 nread += datalen;
1435 if (datalen == 0)
1437 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1438 break;
1441 dataptr=NULL;
1442 datalen=0;
1447 if (!close_done)
1449 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1451 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1453 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1454 if(newhandle)
1455 close(handle);
1456 free(inbuf);free(outbuf);
1457 return;
1461 if(newhandle)
1462 close(handle);
1464 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1465 bzero(outbuf,smb_size);
1466 set_message(outbuf,8,strlen(rname)+4,True);
1467 CVAL(outbuf,smb_com) = SMBsetatr;
1468 SSVAL(outbuf,smb_tid,cnum);
1469 cli_setup_pkt(outbuf);
1470 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1471 SIVALS(outbuf,smb_vwv1,0);
1472 p = smb_buf(outbuf);
1473 *p++ = 4;
1474 pstrcpy(p,rname);
1475 p += strlen(p)+1;
1476 *p++ = 4;
1477 *p = 0;
1478 send_smb(Client,outbuf);
1479 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1483 struct timeval tp_end;
1484 int this_time;
1486 GetTimeOfDay(&tp_end);
1487 this_time =
1488 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1489 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1490 get_total_time_ms += this_time;
1491 get_total_size += finfo.size;
1493 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1494 finfo.size / (1.024*this_time + 1.0e-4),
1495 get_total_size / (1.024*get_total_time_ms)));
1498 free(inbuf);free(outbuf);
1502 /****************************************************************************
1503 get a file
1504 ****************************************************************************/
1505 static void cmd_get(char *dum_in, char *dum_out)
1507 pstring lname;
1508 pstring rname;
1509 char *p;
1511 pstrcpy(rname,cur_dir);
1512 pstrcat(rname,"\\");
1514 p = rname + strlen(rname);
1516 if (!next_token(NULL,p,NULL,sizeof(rname)-strlen(rname))) {
1517 DEBUG(0,("get <filename>\n"));
1518 return;
1520 pstrcpy(lname,p);
1521 dos_clean_name(rname);
1523 next_token(NULL,lname,NULL,sizeof(lname));
1525 do_get(rname,lname,NULL);
1529 /****************************************************************************
1530 do a mget operation on one file
1531 ****************************************************************************/
1532 static void do_mget(file_info *finfo)
1534 pstring rname;
1535 pstring quest;
1537 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1538 return;
1540 if (abort_mget)
1542 DEBUG(0,("mget aborted\n"));
1543 return;
1546 if (finfo->mode & aDIR)
1547 slprintf(quest,sizeof(pstring)-1,
1548 "Get directory %s? ",CNV_LANG(finfo->name));
1549 else
1550 slprintf(quest,sizeof(pstring)-1,
1551 "Get file %s? ",CNV_LANG(finfo->name));
1553 if (prompt && !yesno(quest)) return;
1555 if (finfo->mode & aDIR)
1557 pstring saved_curdir;
1558 pstring mget_mask;
1559 char *inbuf,*outbuf;
1561 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1562 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1564 if (!inbuf || !outbuf)
1566 DEBUG(0,("out of memory\n"));
1567 return;
1570 pstrcpy(saved_curdir,cur_dir);
1572 pstrcat(cur_dir,finfo->name);
1573 pstrcat(cur_dir,"\\");
1575 unix_format(finfo->name);
1577 if (lowercase)
1578 strlower(finfo->name);
1580 if (!directory_exist(finfo->name,NULL) &&
1581 dos_mkdir(finfo->name,0777) != 0)
1583 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1584 pstrcpy(cur_dir,saved_curdir);
1585 free(inbuf);free(outbuf);
1586 return;
1589 if (dos_chdir(finfo->name) != 0)
1591 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1592 pstrcpy(cur_dir,saved_curdir);
1593 free(inbuf);free(outbuf);
1594 return;
1598 pstrcpy(mget_mask,cur_dir);
1599 pstrcat(mget_mask,"*");
1601 do_dir((char *)inbuf,(char *)outbuf,
1602 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False, False);
1603 chdir("..");
1604 pstrcpy(cur_dir,saved_curdir);
1605 free(inbuf);free(outbuf);
1607 else
1609 pstrcpy(rname,cur_dir);
1610 pstrcat(rname,finfo->name);
1611 do_get(rname,finfo->name,finfo);
1615 /****************************************************************************
1616 view the file using the pager
1617 ****************************************************************************/
1618 static void cmd_more(char *dum_in, char *dum_out)
1620 fstring rname,lname,tmpname,pager_cmd;
1621 char *pager;
1623 fstrcpy(rname,cur_dir);
1624 fstrcat(rname,"\\");
1625 slprintf(tmpname,
1626 sizeof(fstring)-1,
1627 "%s/smbmore.%d",tmpdir(),(int)getpid());
1628 fstrcpy(lname,tmpname);
1630 if (!next_token(NULL,rname+strlen(rname),NULL,sizeof(rname)-strlen(rname))) {
1631 DEBUG(0,("more <filename>\n"));
1632 return;
1634 dos_clean_name(rname);
1636 do_get(rname,lname,NULL);
1638 pager=getenv("PAGER");
1640 slprintf(pager_cmd,sizeof(pager_cmd)-1,
1641 "%s %s",(pager? pager:PAGER), tmpname);
1642 system(pager_cmd);
1643 unlink(tmpname);
1648 /****************************************************************************
1649 do a mget command
1650 ****************************************************************************/
1651 static void cmd_mget(char *inbuf,char *outbuf)
1653 int attribute = aSYSTEM | aHIDDEN;
1654 pstring mget_mask;
1655 fstring buf;
1656 char *p=buf;
1658 *mget_mask = 0;
1660 if (recurse)
1661 attribute |= aDIR;
1663 abort_mget = False;
1665 while (next_token(NULL,p,NULL,sizeof(buf)))
1667 pstrcpy(mget_mask,cur_dir);
1668 if(mget_mask[strlen(mget_mask)-1]!='\\')
1669 pstrcat(mget_mask,"\\");
1671 if (*p == '\\')
1672 pstrcpy(mget_mask,p);
1673 else
1674 pstrcat(mget_mask,p);
1675 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1678 if (! *mget_mask)
1680 pstrcpy(mget_mask,cur_dir);
1681 if(mget_mask[strlen(mget_mask)-1]!='\\')
1682 pstrcat(mget_mask,"\\");
1683 pstrcat(mget_mask,"*");
1684 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
1688 /****************************************************************************
1689 make a directory of name "name"
1690 ****************************************************************************/
1691 static BOOL do_mkdir(char *name)
1693 char *p;
1694 char *inbuf,*outbuf;
1696 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1697 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1699 if (!inbuf || !outbuf)
1701 DEBUG(0,("out of memory\n"));
1702 return False;
1705 bzero(outbuf,smb_size);
1706 set_message(outbuf,0,2 + strlen(name),True);
1708 CVAL(outbuf,smb_com) = SMBmkdir;
1709 SSVAL(outbuf,smb_tid,cnum);
1710 cli_setup_pkt(outbuf);
1713 p = smb_buf(outbuf);
1714 *p++ = 4;
1715 pstrcpy(p,name);
1717 send_smb(Client,outbuf);
1718 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1720 if (CVAL(inbuf,smb_rcls) != 0)
1722 DEBUG(0,("%s making remote directory %s\n",
1723 smb_errstr(inbuf),CNV_LANG(name)));
1725 free(inbuf);free(outbuf);
1726 return(False);
1729 free(inbuf);free(outbuf);
1730 return(True);
1734 /****************************************************************************
1735 make a directory
1736 ****************************************************************************/
1737 static void cmd_mkdir(char *inbuf,char *outbuf)
1739 pstring mask;
1740 fstring buf;
1741 char *p=buf;
1743 pstrcpy(mask,cur_dir);
1745 if (!next_token(NULL,p,NULL,sizeof(buf)))
1747 if (!recurse)
1748 DEBUG(0,("mkdir <dirname>\n"));
1749 return;
1751 pstrcat(mask,p);
1753 if (recurse)
1755 pstring ddir;
1756 pstring ddir2;
1757 *ddir2 = 0;
1759 pstrcpy(ddir,mask);
1760 trim_string(ddir,".",NULL);
1761 p = strtok(ddir,"/\\");
1762 while (p)
1764 pstrcat(ddir2,p);
1765 if (!chkpath(ddir2,False))
1767 do_mkdir(ddir2);
1769 pstrcat(ddir2,"\\");
1770 p = strtok(NULL,"/\\");
1773 else
1774 do_mkdir(mask);
1778 /*******************************************************************
1779 write to a file using writebraw
1780 ********************************************************************/
1781 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1783 extern int Client;
1784 pstring inbuf;
1786 bzero(outbuf,smb_size);
1787 bzero(inbuf,smb_size);
1788 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1790 CVAL(outbuf,smb_com) = SMBwritebraw;
1791 SSVAL(outbuf,smb_tid,cnum);
1792 cli_setup_pkt(outbuf);
1794 SSVAL(outbuf,smb_vwv0,fnum);
1795 SSVAL(outbuf,smb_vwv1,n);
1796 SIVAL(outbuf,smb_vwv3,pos);
1797 SSVAL(outbuf,smb_vwv7,1);
1799 send_smb(Client,outbuf);
1801 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1802 return(0);
1804 _smb_setlen(buf-4,n); /* HACK! XXXX */
1806 if (write_socket(Client,buf-4,n+4) != n+4)
1807 return(0);
1809 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1810 DEBUG(0,("Error writing remote file (2)\n"));
1811 return(0);
1813 return(SVAL(inbuf,smb_vwv0));
1818 /*******************************************************************
1819 write to a file
1820 ********************************************************************/
1821 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1823 pstring inbuf;
1825 if (writebraw_supported && n > (max_xmit-200))
1826 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1828 bzero(outbuf,smb_size);
1829 bzero(inbuf,smb_size);
1830 set_message(outbuf,5,n + 3,True);
1832 CVAL(outbuf,smb_com) = SMBwrite;
1833 SSVAL(outbuf,smb_tid,cnum);
1834 cli_setup_pkt(outbuf);
1836 SSVAL(outbuf,smb_vwv0,fnum);
1837 SSVAL(outbuf,smb_vwv1,n);
1838 SIVAL(outbuf,smb_vwv2,pos);
1839 SSVAL(outbuf,smb_vwv4,0);
1840 CVAL(smb_buf(outbuf),0) = 1;
1841 SSVAL(smb_buf(outbuf),1,n);
1843 memcpy(smb_buf(outbuf)+3,buf,n);
1845 send_smb(Client,outbuf);
1846 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1848 if (CVAL(inbuf,smb_rcls) != 0) {
1849 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1850 return(0);
1852 return(SVAL(inbuf,smb_vwv0));
1857 /****************************************************************************
1858 put a single file
1859 ****************************************************************************/
1860 static void do_put(char *rname,char *lname,file_info *finfo)
1862 int fnum;
1863 FILE *f;
1864 int nread=0;
1865 char *p;
1866 char *inbuf,*outbuf;
1867 time_t close_time = finfo->mtime;
1868 char *buf=NULL;
1869 static int maxwrite=0;
1871 struct timeval tp_start;
1872 GetTimeOfDay(&tp_start);
1874 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1875 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1877 if (!inbuf || !outbuf)
1879 DEBUG(0,("out of memory\n"));
1880 return;
1883 bzero(outbuf,smb_size);
1884 set_message(outbuf,3,2 + strlen(rname),True);
1886 if (finfo->mtime == 0 || finfo->mtime == -1)
1887 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1889 CVAL(outbuf,smb_com) = SMBcreate;
1890 SSVAL(outbuf,smb_tid,cnum);
1891 cli_setup_pkt(outbuf);
1893 SSVAL(outbuf,smb_vwv0,finfo->mode);
1894 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1896 p = smb_buf(outbuf);
1897 *p++ = 4;
1898 pstrcpy(p,rname);
1900 send_smb(Client,outbuf);
1901 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1903 if (CVAL(inbuf,smb_rcls) != 0)
1905 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1907 free(inbuf);free(outbuf);if (buf) free(buf);
1908 return;
1911 /* allow files to be piped into smbclient
1912 jdblair 24.jun.98 */
1913 if (!strcmp(lname, "-")) {
1914 f = stdin;
1915 /* size of file is not known */
1916 finfo->size = 0;
1917 } else {
1918 f = fopen(lname,"r");
1921 if (!f)
1923 DEBUG(0,("Error opening local file %s\n",lname));
1924 free(inbuf);free(outbuf);
1925 return;
1929 fnum = SVAL(inbuf,smb_vwv0);
1930 if (finfo->size < 0)
1931 finfo->size = file_size(lname);
1933 DEBUG(1,("putting file %s of size %.0f bytes as %s ",lname,(double)finfo->size,CNV_LANG(rname)));
1935 if (!maxwrite)
1936 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1938 /* This is a rewrite of the read/write loop that doesn't require the input
1939 file to be of a known length. This allows the stream pointer 'f' to
1940 refer to stdin.
1942 Rather than reallocing the read buffer every loop to keep it the min
1943 necessary length this look uses a fixed length buffer and just tests
1944 for eof on the file stream at the top of each loop.
1945 jdblair, 24.jun.98 */
1947 buf = (char *)malloc(maxwrite+4);
1948 while (! feof(f) )
1950 int n = maxwrite;
1951 int ret;
1953 fseek(f,nread,SEEK_SET);
1954 if ((n = readfile(buf+4,1,n,f)) < 1)
1956 DEBUG(0,("Error reading local file\n"));
1957 break;
1960 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1962 if (n != ret) {
1963 if (!maxwrite) {
1964 DEBUG(0,("Error writing file\n"));
1965 break;
1966 } else {
1967 maxwrite /= 2;
1968 continue;
1972 nread += n;
1975 bzero(outbuf,smb_size);
1976 set_message(outbuf,3,0,True);
1977 CVAL(outbuf,smb_com) = SMBclose;
1978 SSVAL(outbuf,smb_tid,cnum);
1979 cli_setup_pkt(outbuf);
1981 SSVAL(outbuf,smb_vwv0,fnum);
1982 put_dos_date3(outbuf,smb_vwv1,close_time);
1984 send_smb(Client,outbuf);
1985 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1987 if (CVAL(inbuf,smb_rcls) != 0)
1989 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1990 fclose(f);
1991 free(inbuf);free(outbuf);
1992 if (buf) free(buf);
1993 return;
1997 fclose(f);
1998 free(inbuf);free(outbuf);
1999 if (buf) free(buf);
2002 struct timeval tp_end;
2003 int this_time;
2005 GetTimeOfDay(&tp_end);
2006 this_time =
2007 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
2008 (tp_end.tv_usec - tp_start.tv_usec)/1000;
2009 put_total_time_ms += this_time;
2010 put_total_size += finfo->size;
2012 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
2013 finfo->size / (1.024*this_time + 1.0e-4),
2014 put_total_size / (1.024*put_total_time_ms)));
2020 /****************************************************************************
2021 put a file
2022 ****************************************************************************/
2023 static void cmd_put(char *dum_in, char *dum_out)
2025 pstring lname;
2026 pstring rname;
2027 fstring buf;
2028 char *p=buf;
2029 file_info finfo;
2030 finfo = def_finfo;
2032 pstrcpy(rname,cur_dir);
2033 pstrcat(rname,"\\");
2036 if (!next_token(NULL,p,NULL,sizeof(buf)))
2038 DEBUG(0,("put <filename>\n"));
2039 return;
2041 pstrcpy(lname,p);
2043 if (next_token(NULL,p,NULL,sizeof(buf)))
2044 pstrcat(rname,p);
2045 else
2046 pstrcat(rname,lname);
2048 dos_clean_name(rname);
2051 SMB_STRUCT_STAT st;
2052 /* allow '-' to represent stdin
2053 jdblair, 24.jun.98 */
2054 if (!file_exist(lname,&st) &&
2055 (strcmp(lname,"-"))) {
2056 DEBUG(0,("%s does not exist\n",lname));
2057 return;
2059 finfo.mtime = st.st_mtime;
2062 do_put(rname,lname,&finfo);
2065 /****************************************************************************
2066 seek in a directory/file list until you get something that doesn't start with
2067 the specified name
2068 ****************************************************************************/
2069 static BOOL seek_list(FILE *f,char *name)
2071 pstring s;
2072 while (!feof(f))
2074 if (fscanf(f,"%s",s) != 1) return(False);
2075 trim_string(s,"./",NULL);
2076 if (strncmp(s,name,strlen(name)) != 0)
2078 pstrcpy(name,s);
2079 return(True);
2083 return(False);
2087 /****************************************************************************
2088 set the file selection mask
2089 ****************************************************************************/
2090 static void cmd_select(char *dum_in, char *dum_out)
2092 pstrcpy(fileselection,"");
2093 next_token(NULL,fileselection,NULL,sizeof(fileselection));
2097 /****************************************************************************
2098 mput some files
2099 ****************************************************************************/
2100 static void cmd_mput(char *dum_in, char *dum_out)
2102 pstring lname;
2103 pstring rname;
2104 file_info finfo;
2105 fstring buf;
2106 char *p=buf;
2108 finfo = def_finfo;
2111 while (next_token(NULL,p,NULL,sizeof(buf)))
2113 SMB_STRUCT_STAT st;
2114 pstring cmd;
2115 pstring tmpname;
2116 FILE *f;
2118 slprintf(tmpname,sizeof(pstring)-1,
2119 "%s/ls.smb.%d",tmpdir(),(int)getpid());
2120 if (recurse)
2121 slprintf(cmd,sizeof(pstring)-1,
2122 "find . -name \"%s\" -print > %s",p,tmpname);
2123 else
2124 slprintf(cmd,sizeof(pstring)-1,
2125 "/bin/ls %s > %s",p,tmpname);
2126 system(cmd);
2128 f = fopen(tmpname,"r");
2129 if (!f) continue;
2131 while (!feof(f))
2133 pstring quest;
2135 if (fscanf(f,"%s",lname) != 1) break;
2136 trim_string(lname,"./",NULL);
2138 again1:
2140 /* check if it's a directory */
2141 if (directory_exist(lname,&st))
2143 if (!recurse) continue;
2144 slprintf(quest,sizeof(pstring)-1,
2145 "Put directory %s? ",lname);
2146 if (prompt && !yesno(quest))
2148 pstrcat(lname,"/");
2149 if (!seek_list(f,lname))
2150 break;
2151 goto again1;
2154 pstrcpy(rname,cur_dir);
2155 pstrcat(rname,lname);
2156 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2157 pstrcat(lname,"/");
2158 if (!seek_list(f,lname))
2159 break;
2160 goto again1;
2163 continue;
2165 else
2167 slprintf(quest,sizeof(quest)-1,
2168 "Put file %s? ",lname);
2169 if (prompt && !yesno(quest)) continue;
2171 pstrcpy(rname,cur_dir);
2172 pstrcat(rname,lname);
2174 dos_format(rname);
2176 /* null size so do_put knows to ignore it */
2177 finfo.size = -1;
2179 /* set the date on the file */
2180 finfo.mtime = st.st_mtime;
2182 do_put(rname,lname,&finfo);
2184 fclose(f);
2185 unlink(tmpname);
2189 /****************************************************************************
2190 cancel a print job
2191 ****************************************************************************/
2192 static void do_cancel(int job)
2194 char *rparam = NULL;
2195 char *rdata = NULL;
2196 char *p;
2197 int rdrcnt,rprcnt;
2198 pstring param;
2200 bzero(param,sizeof(param));
2202 p = param;
2203 SSVAL(p,0,81); /* DosPrintJobDel() */
2204 p += 2;
2205 pstrcpy(p,"W");
2206 p = skip_string(p,1);
2207 pstrcpy(p,"");
2208 p = skip_string(p,1);
2209 SSVAL(p,0,job);
2210 p += 2;
2212 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2213 6, 1000,
2214 &rprcnt,&rdrcnt,
2215 param,NULL, NULL,
2216 &rparam,&rdata))
2218 int res = SVAL(rparam,0);
2220 if (!res)
2221 printf("Job %d cancelled\n",job);
2222 else
2223 printf("Error %d calcelling job %d\n",res,job);
2224 return;
2226 else
2227 printf("Server refused cancel request\n");
2229 if (rparam) free(rparam);
2230 if (rdata) free(rdata);
2232 return;
2236 /****************************************************************************
2237 cancel a print job
2238 ****************************************************************************/
2239 static void cmd_cancel(char *inbuf,char *outbuf )
2241 fstring buf;
2242 int job;
2244 if (!connect_as_printer)
2246 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2247 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2250 if (!next_token(NULL,buf,NULL,sizeof(buf))) {
2251 printf("cancel <jobid> ...\n");
2252 return;
2254 do {
2255 job = atoi(buf);
2256 do_cancel(job);
2257 } while (next_token(NULL,buf,NULL,sizeof(buf)));
2263 /****************************************************************************
2264 print a file
2265 ****************************************************************************/
2266 static void cmd_print(char *inbuf,char *outbuf )
2268 int fnum;
2269 FILE *f = NULL;
2270 uint32 nread=0;
2271 pstring lname;
2272 pstring rname;
2273 char *p;
2275 if (!connect_as_printer)
2277 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2278 DEBUG(0,("Trying to print without -P may fail\n"));
2281 if (!next_token(NULL,lname,NULL, sizeof(lname)))
2283 DEBUG(0,("print <filename>\n"));
2284 return;
2287 pstrcpy(rname,lname);
2288 p = strrchr(rname,'/');
2289 if (p)
2291 pstring tname;
2292 pstrcpy(tname,p+1);
2293 pstrcpy(rname,tname);
2296 if ((int)strlen(rname) > 14)
2297 rname[14] = 0;
2299 if (strequal(lname,"-"))
2301 f = stdin;
2302 pstrcpy(rname,"stdin");
2305 dos_clean_name(rname);
2307 bzero(outbuf,smb_size);
2308 set_message(outbuf,2,2 + strlen(rname),True);
2310 CVAL(outbuf,smb_com) = SMBsplopen;
2311 SSVAL(outbuf,smb_tid,cnum);
2312 cli_setup_pkt(outbuf);
2314 SSVAL(outbuf,smb_vwv0,0);
2315 SSVAL(outbuf,smb_vwv1,printmode);
2317 p = smb_buf(outbuf);
2318 *p++ = 4;
2319 pstrcpy(p,rname);
2321 send_smb(Client,outbuf);
2322 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2324 if (CVAL(inbuf,smb_rcls) != 0)
2326 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2327 return;
2330 if (!f)
2331 f = fopen(lname,"r");
2332 if (!f)
2334 DEBUG(0,("Error opening local file %s\n",lname));
2335 return;
2339 fnum = SVAL(inbuf,smb_vwv0);
2341 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2343 while (!feof(f))
2345 int n;
2347 bzero(outbuf,smb_size);
2348 set_message(outbuf,1,3,True);
2350 /* for some strange reason the OS/2 print server can't handle large
2351 packets when printing. weird */
2352 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2354 if (translation)
2355 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2356 else
2357 n = readfile(smb_buf(outbuf)+3,1,n,f);
2358 if (n <= 0)
2360 DEBUG(0,("read gave %d\n",n));
2361 break;
2364 smb_setlen(outbuf,smb_len(outbuf) + n);
2366 CVAL(outbuf,smb_com) = SMBsplwr;
2367 SSVAL(outbuf,smb_tid,cnum);
2368 cli_setup_pkt(outbuf);
2370 SSVAL(outbuf,smb_vwv0,fnum);
2371 SSVAL(outbuf,smb_vwv1,n+3);
2372 CVAL(smb_buf(outbuf),0) = 1;
2373 SSVAL(smb_buf(outbuf),1,n);
2375 send_smb(Client,outbuf);
2376 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2378 if (CVAL(inbuf,smb_rcls) != 0)
2380 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2381 break;
2384 nread += n;
2387 DEBUG(2,("%d bytes printed\n",nread));
2389 bzero(outbuf,smb_size);
2390 set_message(outbuf,1,0,True);
2391 CVAL(outbuf,smb_com) = SMBsplclose;
2392 SSVAL(outbuf,smb_tid,cnum);
2393 cli_setup_pkt(outbuf);
2395 SSVAL(outbuf,smb_vwv0,fnum);
2397 send_smb(Client,outbuf);
2398 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2400 if (CVAL(inbuf,smb_rcls) != 0)
2402 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2403 if (f != stdin)
2404 fclose(f);
2405 return;
2408 if (f != stdin)
2409 fclose(f);
2412 /****************************************************************************
2413 show a print queue - this is deprecated as it uses the old smb that
2414 has limited support - the correct call is the cmd_p_queue_4() after this.
2415 ****************************************************************************/
2416 static void cmd_queue(char *inbuf,char *outbuf )
2418 int count;
2419 char *p;
2421 bzero(outbuf,smb_size);
2422 set_message(outbuf,2,0,True);
2424 CVAL(outbuf,smb_com) = SMBsplretq;
2425 SSVAL(outbuf,smb_tid,cnum);
2426 cli_setup_pkt(outbuf);
2428 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2429 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2431 send_smb(Client,outbuf);
2432 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2434 if (CVAL(inbuf,smb_rcls) != 0)
2436 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2437 return;
2440 count = SVAL(inbuf,smb_vwv0);
2441 p = smb_buf(inbuf) + 3;
2442 if (count <= 0)
2444 DEBUG(0,("No entries in the print queue\n"));
2445 return;
2449 char status[20];
2451 DEBUG(0,("Job Name Size Status\n"));
2453 while (count--)
2455 switch (CVAL(p,4))
2457 case 0x01: safe_strcpy(status,"held or stopped", sizeof(status)-1); break;
2458 case 0x02: safe_strcpy(status,"printing",sizeof(status)-1); break;
2459 case 0x03: safe_strcpy(status,"awaiting print", sizeof(status)-1); break;
2460 case 0x04: safe_strcpy(status,"in intercept",sizeof(status)-1); break;
2461 case 0x05: safe_strcpy(status,"file had error",sizeof(status)-1); break;
2462 case 0x06: safe_strcpy(status,"printer error",sizeof(status)-1); break;
2463 default: safe_strcpy(status,"unknown",sizeof(status)-1); break;
2466 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2467 SVAL(p,5),p+12,IVAL(p,7),status));
2468 p += 28;
2475 /****************************************************************************
2476 show information about a print queue
2477 ****************************************************************************/
2478 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2480 char *rparam = NULL;
2481 char *rdata = NULL;
2482 char *p;
2483 int rdrcnt, rprcnt;
2484 pstring param;
2485 int result_code=0;
2487 if (!connect_as_printer)
2489 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2490 DEBUG(0,("Trying to print without -P may fail\n"));
2493 bzero(param,sizeof(param));
2495 p = param;
2496 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2497 p += 2;
2498 pstrcpy(p,"zWrLeh"); /* parameter description? */
2499 p = skip_string(p,1);
2500 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
2501 p = skip_string(p,1);
2502 pstrcpy(p,strrchr(service,'\\')+1); /* name of queue */
2503 p = skip_string(p,1);
2504 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2505 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2506 p += 4;
2507 pstrcpy(p,""); /* subformat */
2508 p = skip_string(p,1);
2510 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2511 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2512 10, 4096,
2513 &rprcnt, &rdrcnt,
2514 param, NULL, NULL,
2515 &rparam, &rdata) )
2517 int converter;
2518 result_code = SVAL(rparam,0);
2519 converter = SVAL(rparam,2); /* conversion factor */
2521 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2523 if (result_code == 0) /* if no error, */
2525 int i;
2526 uint16 JobId;
2527 uint16 Priority;
2528 uint32 Size;
2529 char *UserName;
2530 char *JobName;
2531 char *JobTimeStr;
2532 time_t JobTime;
2533 fstring PrinterName;
2535 fstrcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2536 strlower(PrinterName); /* in lower case */
2538 p = rdata; /* received data */
2539 for( i = 0; i < SVAL(rparam,4); ++i)
2541 JobId = SVAL(p,0);
2542 Priority = SVAL(p,2);
2543 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2544 strlower(UserName);
2545 Priority = SVAL(p,2);
2546 JobTime = make_unix_date3( p + 12);
2547 JobTimeStr = asctime(LocalTime( &JobTime));
2548 Size = IVAL(p,16);
2549 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2552 printf("%s-%u %s priority %u %s %s %u bytes\n",
2553 PrinterName, JobId, UserName,
2554 Priority, JobTimeStr, JobName, Size);
2556 #if 0 /* DEBUG code */
2557 printf("Job Id: \"%u\"\n", SVAL(p,0));
2558 printf("Priority: \"%u\"\n", SVAL(p,2));
2560 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2561 printf("Position: \"%u\"\n", SVAL(p,8));
2562 printf("Status: \"%u\"\n", SVAL(p,10));
2564 JobTime = make_unix_date3( p + 12);
2565 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2566 printf("date: \"%u\"\n", SVAL(p,12));
2568 printf("Size: \"%u\"\n", SVAL(p,16));
2569 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2570 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2571 #endif /* DEBUG CODE */
2572 p += 28;
2576 else /* cli_call_api() failed */
2578 printf("Failed, error = %d\n", result_code);
2581 /* If any parameters or data were returned, free the storage. */
2582 if(rparam) free(rparam);
2583 if(rdata) free(rdata);
2585 return;
2588 /****************************************************************************
2589 show information about a print queue
2590 ****************************************************************************/
2591 static void cmd_qinfo(char *inbuf,char *outbuf )
2593 char *rparam = NULL;
2594 char *rdata = NULL;
2595 char *p;
2596 int rdrcnt, rprcnt;
2597 pstring param;
2598 int result_code=0;
2600 bzero(param,sizeof(param));
2602 p = param;
2603 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2604 p += 2;
2605 pstrcpy(p,"zWrLh"); /* parameter description? */
2606 p = skip_string(p,1);
2607 pstrcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2608 p = skip_string(p,1);
2609 pstrcpy(p,strrchr(service,'\\')+1); /* name of queue */
2610 p = skip_string(p,1);
2611 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2612 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2613 p += 4;
2614 pstrcpy(p,""); /* subformat */
2615 p = skip_string(p,1);
2617 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2618 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2619 10, 4096,
2620 &rprcnt, &rdrcnt,
2621 param, NULL, NULL,
2622 &rparam, &rdata) )
2624 int converter;
2625 result_code = SVAL(rparam,0);
2626 converter = SVAL(rparam,2); /* conversion factor */
2628 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2630 if (result_code == 0) /* if no error, */
2632 p = rdata; /* received data */
2634 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2635 printf("Priority: %u\n", SVAL(p,4) );
2636 printf("Start time: %u\n", SVAL(p,6) );
2637 printf("Until time: %u\n", SVAL(p,8) );
2638 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2639 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2640 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2641 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2642 printf("Status: %u\n", SVAL(p,28) );
2643 printf("Jobs: %u\n", SVAL(p,30) );
2644 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2645 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2647 /* Dump the driver data */
2649 int count, x, y, c;
2650 char *ddptr;
2652 ddptr = rdata + SVAL(p,40) - converter;
2653 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2654 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2656 for(x=8; x < count; x+=16)
2658 for(y=0; y < 16; y++)
2660 if( (x+y) < count )
2661 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2662 else
2663 fputs(" ", stdout);
2665 for(y=0; y < 16 && (x+y) < count; y++)
2667 c = CVAL(ddptr,(x+y));
2668 if(isprint(c))
2669 fputc(c, stdout);
2670 else
2671 fputc('.', stdout);
2673 fputc('\n', stdout);
2679 else /* cli_call_api() failed */
2681 printf("Failed, error = %d\n", result_code);
2684 /* If any parameters or data were returned, free the storage. */
2685 if(rparam) free(rparam);
2686 if(rdata) free(rdata);
2688 return;
2691 /****************************************************************************
2692 delete some files
2693 ****************************************************************************/
2694 static void do_del(file_info *finfo)
2696 char *p;
2697 char *inbuf,*outbuf;
2698 pstring mask;
2700 pstrcpy(mask,cur_dir);
2701 pstrcat(mask,finfo->name);
2703 if (finfo->mode & aDIR)
2704 return;
2706 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2707 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2709 if (!inbuf || !outbuf)
2711 DEBUG(0,("out of memory\n"));
2712 return;
2715 bzero(outbuf,smb_size);
2716 set_message(outbuf,1,2 + strlen(mask),True);
2718 CVAL(outbuf,smb_com) = SMBunlink;
2719 SSVAL(outbuf,smb_tid,cnum);
2720 cli_setup_pkt(outbuf);
2722 SSVAL(outbuf,smb_vwv0,0);
2724 p = smb_buf(outbuf);
2725 *p++ = 4;
2726 pstrcpy(p,mask);
2728 send_smb(Client,outbuf);
2729 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2731 if (CVAL(inbuf,smb_rcls) != 0)
2732 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2734 free(inbuf);free(outbuf);
2738 /****************************************************************************
2739 delete some files
2740 ****************************************************************************/
2741 static void cmd_del(char *inbuf,char *outbuf )
2743 pstring mask;
2744 fstring buf;
2745 int attribute = aSYSTEM | aHIDDEN;
2747 if (recurse)
2748 attribute |= aDIR;
2750 pstrcpy(mask,cur_dir);
2752 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2754 DEBUG(0,("del <filename>\n"));
2755 return;
2757 pstrcat(mask,buf);
2759 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False,False);
2763 /****************************************************************************
2764 remove a directory
2765 ****************************************************************************/
2766 static void cmd_rmdir(char *inbuf,char *outbuf )
2768 pstring mask;
2769 fstring buf;
2770 char *p;
2772 pstrcpy(mask,cur_dir);
2774 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2776 DEBUG(0,("rmdir <dirname>\n"));
2777 return;
2779 pstrcat(mask,buf);
2781 bzero(outbuf,smb_size);
2782 set_message(outbuf,0,2 + strlen(mask),True);
2784 CVAL(outbuf,smb_com) = SMBrmdir;
2785 SSVAL(outbuf,smb_tid,cnum);
2786 cli_setup_pkt(outbuf);
2789 p = smb_buf(outbuf);
2790 *p++ = 4;
2791 pstrcpy(p,mask);
2793 send_smb(Client,outbuf);
2794 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2796 if (CVAL(inbuf,smb_rcls) != 0)
2798 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2799 return;
2804 /****************************************************************************
2805 rename some files
2806 ****************************************************************************/
2807 static void cmd_rename(char *inbuf,char *outbuf )
2809 pstring src,dest;
2810 fstring buf,buf2;
2811 char *p;
2813 pstrcpy(src,cur_dir);
2814 pstrcpy(dest,cur_dir);
2816 if (!next_token(NULL,buf,NULL,sizeof(buf)) ||
2817 !next_token(NULL,buf2,NULL, sizeof(buf2)))
2819 DEBUG(0,("rename <src> <dest>\n"));
2820 return;
2822 pstrcat(src,buf);
2823 pstrcat(dest,buf2);
2825 bzero(outbuf,smb_size);
2826 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2828 CVAL(outbuf,smb_com) = SMBmv;
2829 SSVAL(outbuf,smb_tid,cnum);
2830 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2831 cli_setup_pkt(outbuf);
2833 p = smb_buf(outbuf);
2834 *p++ = 4;
2835 pstrcpy(p,src);
2836 p = skip_string(p,1);
2837 *p++ = 4;
2838 pstrcpy(p,dest);
2840 send_smb(Client,outbuf);
2841 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2843 if (CVAL(inbuf,smb_rcls) != 0)
2845 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2846 return;
2852 /****************************************************************************
2853 toggle the prompt flag
2854 ****************************************************************************/
2855 static void cmd_prompt(char *dum_in, char *dum_out)
2857 prompt = !prompt;
2858 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2862 /****************************************************************************
2863 set the newer than time
2864 ****************************************************************************/
2865 static void cmd_newer(char *dum_in, char *dum_out)
2867 fstring buf;
2868 BOOL ok;
2869 SMB_STRUCT_STAT sbuf;
2871 ok = next_token(NULL,buf,NULL,sizeof(buf));
2872 if (ok && (dos_stat(buf,&sbuf) == 0))
2874 newer_than = sbuf.st_mtime;
2875 DEBUG(1,("Getting files newer than %s",
2876 asctime(LocalTime(&newer_than))));
2878 else
2879 newer_than = 0;
2881 if (ok && newer_than == 0)
2882 DEBUG(0,("Error setting newer-than time\n"));
2885 /****************************************************************************
2886 set the archive level
2887 ****************************************************************************/
2888 static void cmd_archive(char *dum_in, char *dum_out)
2890 fstring buf;
2892 if (next_token(NULL,buf,NULL,sizeof(buf))) {
2893 archive_level = atoi(buf);
2894 } else
2895 DEBUG(0,("Archive level is %d\n",archive_level));
2898 /****************************************************************************
2899 toggle the lowercaseflag
2900 ****************************************************************************/
2901 static void cmd_lowercase(char *dum_in, char *dum_out)
2903 lowercase = !lowercase;
2904 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2910 /****************************************************************************
2911 toggle the recurse flag
2912 ****************************************************************************/
2913 static void cmd_recurse(char *dum_in, char *dum_out)
2915 recurse = !recurse;
2916 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2919 /****************************************************************************
2920 toggle the translate flag
2921 ****************************************************************************/
2922 static void cmd_translate(char *dum_in, char *dum_out)
2924 translation = !translation;
2925 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2926 translation?"on":"off"));
2930 /****************************************************************************
2931 do a printmode command
2932 ****************************************************************************/
2933 static void cmd_printmode(char *dum_in, char *dum_out)
2935 fstring buf;
2936 fstring mode;
2938 if (next_token(NULL,buf,NULL,sizeof(buf)))
2940 if (strequal(buf,"text"))
2941 printmode = 0;
2942 else
2944 if (strequal(buf,"graphics"))
2945 printmode = 1;
2946 else
2947 printmode = atoi(buf);
2951 switch(printmode)
2953 case 0:
2954 fstrcpy(mode,"text");
2955 break;
2956 case 1:
2957 fstrcpy(mode,"graphics");
2958 break;
2959 default:
2960 slprintf(mode,sizeof(mode)-1,"%d",printmode);
2961 break;
2964 DEBUG(2,("the printmode is now %s\n",mode));
2967 /****************************************************************************
2968 do the lcd command
2969 ****************************************************************************/
2970 static void cmd_lcd(char *dum_in, char *dum_out)
2972 fstring buf;
2973 pstring d;
2975 if (next_token(NULL,buf,NULL,sizeof(buf)))
2976 dos_chdir(buf);
2977 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2981 /****************************************************************************
2982 try and browse available connections on a host
2983 ****************************************************************************/
2984 static BOOL browse_host(BOOL sort)
2986 char *rparam = NULL;
2987 char *rdata = NULL;
2988 char *p;
2989 int rdrcnt,rprcnt;
2990 pstring param;
2991 int count = -1;
2993 /* now send a SMBtrans command with api RNetShareEnum */
2994 p = param;
2995 SSVAL(p,0,0); /* api number */
2996 p += 2;
2997 pstrcpy(p,"WrLeh");
2998 p = skip_string(p,1);
2999 pstrcpy(p,"B13BWz");
3000 p = skip_string(p,1);
3001 SSVAL(p,0,1);
3002 SSVAL(p,2,BUFFER_SIZE);
3003 p += 4;
3005 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3006 1024, BUFFER_SIZE,
3007 &rprcnt,&rdrcnt,
3008 param,NULL, NULL,
3009 &rparam,&rdata))
3011 int res = SVAL(rparam,0);
3012 int converter=SVAL(rparam,2);
3013 int i;
3014 BOOL long_share_name=False;
3016 if (res == 0 || res == ERRmoredata)
3018 count=SVAL(rparam,4);
3019 p = rdata;
3021 if (count > 0)
3023 printf("\n\tSharename Type Comment\n");
3024 printf("\t--------- ---- -------\n");
3027 if (sort)
3028 qsort(p,count,20,QSORT_CAST StrCaseCmp);
3030 for (i=0;i<count;i++)
3032 char *sname = p;
3033 int type = SVAL(p,14);
3034 int comment_offset = IVAL(p,16) & 0xFFFF;
3035 fstring typestr;
3036 *typestr=0;
3038 switch (type)
3040 case STYPE_DISKTREE:
3041 fstrcpy(typestr,"Disk"); break;
3042 case STYPE_PRINTQ:
3043 fstrcpy(typestr,"Printer"); break;
3044 case STYPE_DEVICE:
3045 fstrcpy(typestr,"Device"); break;
3046 case STYPE_IPC:
3047 fstrcpy(typestr,"IPC"); break;
3050 printf("\t%-15.15s%-10.10s%s\n",
3051 sname, typestr,
3052 comment_offset?rdata+comment_offset-converter:"");
3054 if (strlen(sname)>8) long_share_name=True;
3056 p += 20;
3059 if (long_share_name) {
3060 printf("\nNOTE: There were share names longer than 8 chars.\n\
3061 On older clients these may not be accessible or may give browsing errors\n");
3064 if(res == ERRmoredata)
3065 printf("\nNOTE: More data was available, the list was truncated.\n");
3069 if (rparam) free(rparam);
3070 if (rdata) free(rdata);
3072 return(count>0);
3076 /****************************************************************************
3077 get some server info
3078 ****************************************************************************/
3079 static void server_info(void)
3081 char *rparam = NULL;
3082 char *rdata = NULL;
3083 char *p;
3084 int rdrcnt,rprcnt;
3085 pstring param;
3087 bzero(param,sizeof(param));
3089 p = param;
3090 SSVAL(p,0,63); /* NetServerGetInfo()? */
3091 p += 2;
3092 pstrcpy(p,"WrLh");
3093 p = skip_string(p,1);
3094 pstrcpy(p,"zzzBBzz");
3095 p = skip_string(p,1);
3096 SSVAL(p,0,10); /* level 10 */
3097 SSVAL(p,2,1000);
3098 p += 6;
3100 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3101 6, 1000,
3102 &rprcnt,&rdrcnt,
3103 param,NULL, NULL,
3104 &rparam,&rdata))
3106 int res = SVAL(rparam,0);
3107 int converter=SVAL(rparam,2);
3109 if (res == 0)
3111 p = rdata;
3113 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3114 rdata+SVAL(p,0)-converter,
3115 rdata+SVAL(p,4)-converter,
3116 rdata+SVAL(p,8)-converter,
3117 rdata+SVAL(p,14)-converter);
3121 if (rparam) free(rparam);
3122 if (rdata) free(rdata);
3124 return;
3128 /****************************************************************************
3129 try and browse available connections on a host
3130 ****************************************************************************/
3131 static BOOL list_servers(char *wk_grp)
3133 char *rparam = NULL;
3134 char *rdata = NULL;
3135 int rdrcnt,rprcnt;
3136 char *p,*svtype_p;
3137 pstring param;
3138 int uLevel = 1;
3139 int count = 0;
3140 BOOL ok = False;
3141 BOOL generic_request = False;
3144 if (strequal(wk_grp,"WORKGROUP")) {
3145 /* we won't specify a workgroup */
3146 generic_request = True;
3149 /* now send a SMBtrans command with api ServerEnum? */
3150 p = param;
3151 SSVAL(p,0,0x68); /* api number */
3152 p += 2;
3154 pstrcpy(p,generic_request?"WrLehDO":"WrLehDz");
3155 p = skip_string(p,1);
3157 pstrcpy(p,"B16BBDz");
3159 p = skip_string(p,1);
3160 SSVAL(p,0,uLevel);
3161 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3162 p += 4;
3164 svtype_p = p;
3165 p += 4;
3167 if (!generic_request) {
3168 pstrcpy(p, wk_grp);
3169 p = skip_string(p,1);
3172 /* first ask for a list of servers in this workgroup */
3173 SIVAL(svtype_p,0,SV_TYPE_ALL);
3175 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3176 8, BUFFER_SIZE - SAFETY_MARGIN,
3177 &rprcnt,&rdrcnt,
3178 param,NULL, NULL,
3179 &rparam,&rdata))
3181 int res = SVAL(rparam,0);
3182 int converter=SVAL(rparam,2);
3183 int i;
3185 if (res == 0 || res == ERRmoredata) {
3186 char *p2 = rdata;
3187 count=SVAL(rparam,4);
3189 if (count > 0) {
3190 printf("\n\nThis machine has a browse list:\n");
3191 printf("\n\tServer Comment\n");
3192 printf("\t--------- -------\n");
3195 for (i=0;i<count;i++) {
3196 char *sname = p2;
3197 int comment_offset = IVAL(p2,22) & 0xFFFF;
3198 printf("\t%-16.16s %s\n", sname,
3199 comment_offset?rdata+comment_offset-converter:"");
3201 ok=True;
3202 p2 += 26;
3205 if(res == ERRmoredata)
3206 printf("\nNOTE: More data was available, the list was truncated.\n");
3210 if (rparam) {free(rparam); rparam = NULL;}
3211 if (rdata) {free(rdata); rdata = NULL;}
3213 /* now ask for a list of workgroups */
3214 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3216 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3217 8, BUFFER_SIZE - SAFETY_MARGIN,
3218 &rprcnt,&rdrcnt,
3219 param,NULL, NULL,
3220 &rparam,&rdata))
3222 int res = SVAL(rparam,0);
3223 int converter=SVAL(rparam,2);
3224 int i;
3226 if (res == 0 || res == ERRmoredata) {
3227 char *p2 = rdata;
3228 count=SVAL(rparam,4);
3230 if (count > 0) {
3231 printf("\n\nThis machine has a workgroup list:\n");
3232 printf("\n\tWorkgroup Master\n");
3233 printf("\t--------- -------\n");
3236 for (i=0;i<count;i++) {
3237 char *sname = p2;
3238 int comment_offset = IVAL(p2,22) & 0xFFFF;
3239 printf("\t%-16.16s %s\n", sname,
3240 comment_offset?rdata+comment_offset-converter:"");
3242 ok=True;
3243 p2 += 26;
3246 if(res == ERRmoredata)
3247 printf("\nNOTE: More data was available, the list was truncated.\n");
3251 if (rparam) free(rparam);
3252 if (rdata) free(rdata);
3254 return(ok);
3258 /* Some constants for completing filename arguments */
3260 #define COMPL_NONE 0 /* No completions */
3261 #define COMPL_REMOTE 1 /* Complete remote filename */
3262 #define COMPL_LOCAL 2 /* Complete local filename */
3264 /* This defines the commands supported by this client */
3265 struct
3267 char *name;
3268 void (*fn)(char *, char *);
3269 char *description;
3270 char compl_args[2]; /* Completion argument info */
3271 } commands[] =
3273 {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3274 {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3275 {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3276 {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
3277 {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
3278 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
3279 {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
3280 {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
3281 {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
3282 {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
3283 {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
3284 {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},
3285 {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
3286 {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
3287 {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
3288 {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
3289 {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
3290 {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
3291 {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
3292 {"pq",cmd_p_queue_4,"enumerate the print queue",{COMPL_NONE,COMPL_NONE}},
3293 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
3294 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},
3295 {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
3296 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},
3297 {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
3298 {"printmode",cmd_printmode,"<graphics or text> set the print mode",{COMPL_NONE,COMPL_NONE}},
3299 {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}},
3300 {"qinfo",cmd_qinfo,"show print queue information",{COMPL_NONE,COMPL_NONE}},
3301 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
3302 {"quit",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3303 {"q",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3304 {"exit",cli_send_logout,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3305 {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
3306 {"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}},
3307 {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
3308 {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
3309 {"tarmode",cmd_tarmode,
3310 "<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
3311 {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
3312 {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
3313 {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
3314 {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
3315 {"",NULL,NULL,{COMPL_NONE,COMPL_NONE}}
3319 /*******************************************************************
3320 lookup a command string in the list of commands, including
3321 abbreviations
3322 ******************************************************************/
3323 static int process_tok(fstring tok)
3325 int i = 0, matches = 0;
3326 int cmd=0;
3327 int tok_len = strlen(tok);
3329 while (commands[i].fn != NULL)
3331 if (strequal(commands[i].name,tok))
3333 matches = 1;
3334 cmd = i;
3335 break;
3337 else if (strnequal(commands[i].name, tok, tok_len))
3339 matches++;
3340 cmd = i;
3342 i++;
3345 if (matches == 0)
3346 return(-1);
3347 else if (matches == 1)
3348 return(cmd);
3349 else
3350 return(-2);
3353 /****************************************************************************
3354 help
3355 ****************************************************************************/
3356 static void cmd_help(char *dum_in, char *dum_out)
3358 int i=0,j;
3359 fstring buf;
3361 if (next_token(NULL,buf,NULL,sizeof(buf)))
3363 if ((i = process_tok(buf)) >= 0)
3364 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3366 else
3367 while (commands[i].description)
3369 for (j=0; commands[i].description && (j<5); j++) {
3370 DEBUG(0,("%-15s",commands[i].name));
3371 i++;
3373 DEBUG(0,("\n"));
3377 #ifndef HAVE_LIBREADLINE
3379 /****************************************************************************
3380 wait for keyboard activity, swallowing network packets
3381 ****************************************************************************/
3382 static void wait_keyboard(char *buffer)
3384 fd_set fds;
3385 struct timeval timeout;
3387 while (1)
3389 extern int Client;
3390 FD_ZERO(&fds);
3391 FD_SET(Client,&fds);
3392 FD_SET(fileno(stdin),&fds);
3394 timeout.tv_sec = 20;
3395 timeout.tv_usec = 0;
3396 sys_select(MAX(Client,fileno(stdin))+1,&fds,&timeout);
3398 if (FD_ISSET(fileno(stdin),&fds))
3399 return;
3401 /* We deliberately use receive_smb instead of
3402 client_receive_smb as we want to receive
3403 session keepalives and then drop them here.
3405 if (FD_ISSET(Client,&fds))
3406 receive_smb(Client,buffer,0);
3408 chkpath("\\",False);
3412 #else /* if HAVE_LIBREADLINE */
3414 /****************************************************************************
3415 completion routines for GNU Readline
3416 ****************************************************************************/
3418 /* To avoid filename completion being activated when no valid
3419 completions are found, we assign this stub completion function
3420 to the rl_completion_entry_function variable. */
3422 char *complete_cmd_null(char *text, int state)
3424 return NULL;
3427 /* Argh. This is starting to get ugly. We need to be able to pass data
3428 back from the do_dir() iterator function. */
3430 static int compl_state;
3431 static char *compl_text;
3432 static pstring result;
3434 /* Iterator function for do_dir() */
3436 void complete_process_file(file_info *f)
3438 /* Do we have a partial match? */
3440 if ((compl_state >= 0) && (strncmp(compl_text, f->name,
3441 strlen(compl_text)) == 0)) {
3443 /* Return filename if we have made enough matches */
3445 if (compl_state == 0) {
3446 pstrcpy(result, f->name);
3447 compl_state = -1;
3449 return;
3451 compl_state--;
3455 /* Complete a remote file */
3457 char *complete_remote_file(char *text, int state)
3459 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3460 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3461 int attribute = aDIR | aSYSTEM | aHIDDEN;
3462 pstring mask;
3464 if ((InBuffer == NULL) || (OutBuffer == NULL))
3465 return(NULL);
3467 /* Create dir mask */
3469 pstrcpy(mask, cur_dir);
3470 pstrcat(mask, "*");
3472 /* Initialise static vars for filename match */
3474 compl_text = text;
3475 compl_state = state;
3476 result[0] = '\0';
3478 /* Iterate over all files in directory */
3480 do_dir(InBuffer, OutBuffer, mask, attribute, complete_process_file, False,
3481 True);
3483 /* Clean up */
3485 free(InBuffer);
3486 free(OutBuffer);
3488 /* Return matched filename */
3490 if (result[0] != '\0') {
3491 return strdup(result); /* Readline will dispose of strings */
3492 } else {
3493 return NULL;
3497 /* Complete a smbclient command */
3499 char *complete_cmd(char *text, int state)
3501 static int cmd_index;
3502 char *name;
3504 /* Initialise */
3506 if (state == 0) {
3507 cmd_index = 0;
3510 /* Return the next name which partially matches the list of commands */
3512 while (strlen(name = commands[cmd_index++].name) > 0) {
3513 if (strncmp(name, text, strlen(text)) == 0) {
3514 return strdup(name);
3518 return NULL;
3521 /* Main completion function for smbclient. Work out which word we are
3522 trying to complete and call the appropriate function. */
3524 char **completion_fn(char *text, int start, int end)
3526 int i, num_words, cmd_index;
3527 char lastch = ' ';
3529 /* If we are at the start of a word, we are completing a smbclient
3530 command. */
3532 if (start == 0) {
3533 return completion_matches(text, complete_cmd);
3536 /* Count # of words in command */
3538 num_words = 0;
3539 for (i = 0; i <= end; i++) {
3540 if ((rl_line_buffer[i] != ' ') && (lastch == ' '))
3541 num_words++;
3542 lastch = rl_line_buffer[i];
3545 if (rl_line_buffer[end] == ' ')
3546 num_words++;
3548 /* Work out which command we are completing for */
3550 for (cmd_index = 0; strcmp(commands[cmd_index].name, "") != 0;
3551 cmd_index++) {
3553 /* Check each command in array */
3555 if (strncmp(rl_line_buffer, commands[cmd_index].name,
3556 strlen(commands[cmd_index].name)) == 0) {
3558 /* Call appropriate completion function */
3560 if ((num_words == 2) || (num_words == 3)) {
3561 switch (commands[cmd_index].compl_args[num_words - 2]) {
3563 case COMPL_REMOTE:
3564 return completion_matches(text, complete_remote_file);
3565 break;
3567 case COMPL_LOCAL:
3568 return completion_matches(text, filename_completion_function);
3569 break;
3571 default:
3572 /* An invalid completion type */
3573 break;
3577 /* We're either completing an argument > 3 or found an invalid
3578 completion type. Either way do nothing about it. */
3580 break;
3584 return NULL;
3587 #endif /* HAVE_LIBREADLINE */
3589 /****************************************************************************
3590 process commands from the client
3591 ****************************************************************************/
3592 static BOOL process(char *base_directory)
3594 pstring line;
3595 char *cmd;
3597 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3598 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3600 if ((InBuffer == NULL) || (OutBuffer == NULL))
3601 return(False);
3603 bzero(OutBuffer,smb_size);
3605 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3606 return(False);
3608 if (*base_directory) do_cd(base_directory);
3610 cmd = cmdstr;
3611 if (cmd[0] != '\0') while (cmd[0] != '\0')
3613 char *p;
3614 fstring tok;
3615 int i;
3617 if ((p = strchr(cmd, ';')) == 0)
3619 strncpy(line, cmd, 999);
3620 line[1000] = '\0';
3621 cmd += strlen(cmd);
3623 else
3625 if (p - cmd > 999) p = cmd + 999;
3626 strncpy(line, cmd, p - cmd);
3627 line[p - cmd] = '\0';
3628 cmd = p + 1;
3631 /* input language code to internal one */
3632 CNV_INPUT (line);
3634 /* and get the first part of the command */
3636 char *ptr = line;
3637 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
3640 if ((i = process_tok(tok)) >= 0)
3641 commands[i].fn(InBuffer,OutBuffer);
3642 else if (i == -2)
3643 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3644 else
3645 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3647 else while (!feof(stdin))
3649 fstring tok;
3650 int i;
3652 bzero(OutBuffer,smb_size);
3654 #ifdef HAVE_LIBREADLINE
3657 pstring prompt;
3659 /* Read input using GNU Readline */
3661 slprintf(prompt, sizeof(prompt) - 1, "smb: %s> ", CNV_LANG(cur_dir));
3662 if (!readline(prompt))
3663 break;
3665 /* Copy read line to samba buffer */
3667 pstrcpy(line, rl_line_buffer);
3668 pstrcat(line, "\n");
3670 /* Add line to history */
3672 if (strlen(line) > 0)
3673 add_history(line);
3676 #else
3678 /* display a prompt */
3679 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3680 dbgflush( );
3682 wait_keyboard(InBuffer);
3684 /* and get a response */
3685 if (!fgets(line,1000,stdin))
3686 break;
3688 #endif
3690 /* input language code to internal one */
3691 CNV_INPUT (line);
3693 /* special case - first char is ! */
3694 if (*line == '!')
3696 system(line + 1);
3697 continue;
3700 /* and get the first part of the command */
3702 char *ptr = line;
3703 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue;
3706 if ((i = process_tok(tok)) >= 0)
3707 commands[i].fn(InBuffer,OutBuffer);
3708 else if (i == -2)
3709 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3710 else
3711 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3714 cli_send_logout(InBuffer,OutBuffer);
3715 return(True);
3718 /****************************************************************************
3719 usage on the program
3720 ****************************************************************************/
3721 static void usage(char *pname)
3723 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3724 pname));
3726 DEBUG(0,("\nVersion %s\n",VERSION));
3727 DEBUG(0,("\t-p port connect to the specified port\n"));
3728 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3729 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3730 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3731 DEBUG(0,("\t-N don't ask for a password\n"));
3732 DEBUG(0,("\t-P connect to service as a printer\n"));
3733 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3734 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3735 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3736 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3737 DEBUG(0,("\t-R name resolve order use these name resolution services only\n"));
3738 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3739 DEBUG(0,("\t-U username set the network username\n"));
3740 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3741 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3742 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3743 DEBUG(0,("\t-T<c|x>IXFqgbNan command line tar\n"));
3744 DEBUG(0,("\t-D directory start from directory\n"));
3745 DEBUG(0,("\n"));
3748 /****************************************************************************
3749 main program
3750 ****************************************************************************/
3751 int main(int argc,char *argv[])
3753 fstring base_directory;
3754 char *pname = argv[0];
3755 int port = SMB_PORT;
3756 int opt;
3757 extern FILE *dbf;
3758 extern char *optarg;
3759 extern int optind;
3760 pstring query_host;
3761 BOOL message = False;
3762 BOOL nt_domain_logon = False;
3763 BOOL explicit_user = False;
3764 extern char tar_type;
3765 static pstring servicesf = CONFIGFILE;
3766 pstring term_code;
3767 pstring new_name_resolve_order;
3768 char *p;
3770 #ifdef KANJI
3771 pstrcpy(term_code, KANJI);
3772 #else /* KANJI */
3773 *term_code = 0;
3774 #endif /* KANJI */
3776 *query_host = 0;
3777 *base_directory = 0;
3779 *new_name_resolve_order = 0;
3781 DEBUGLEVEL = 2;
3783 setup_logging(pname,True);
3785 TimeInit();
3786 charset_initialise();
3788 if(!get_myname(myhostname,NULL))
3790 DEBUG(0,("Failed to get my hostname.\n"));
3793 in_client = True;
3795 if (!lp_load(servicesf,True,False,False)) {
3796 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3799 codepage_initialise(lp_client_code_page());
3801 interpret_coding_system(term_code);
3803 #ifdef WITH_SSL
3804 sslutil_init(0);
3805 #endif
3807 pstrcpy(workgroup,lp_workgroup());
3809 load_interfaces();
3810 pid = (uint16)getpid();
3811 vuid = (uint16)getuid();
3812 mid = pid + 100;
3813 myumask = umask(0);
3814 umask(myumask);
3816 if (getenv("USER"))
3818 pstrcpy(username,getenv("USER"));
3820 /* modification to support userid%passwd syntax in the USER var
3821 25.Aug.97, jdblair@uab.edu */
3823 if ((p=strchr(username,'%')))
3825 *p = 0;
3826 pstrcpy(password,p+1);
3827 got_pass = True;
3828 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3830 strupper(username);
3833 /* modification to support PASSWD environmental var
3834 25.Aug.97, jdblair@uab.edu */
3836 if (getenv("PASSWD")) {
3837 pstrcpy(password,getenv("PASSWD"));
3838 got_pass = True;
3841 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
3842 int fd = -1;
3843 BOOL close_it = False;
3844 pstring spec;
3845 char pass[128];
3847 if ((p = getenv("PASSWD_FD")) != NULL) {
3848 pstrcpy(spec, "descriptor ");
3849 pstrcat(spec, p);
3850 sscanf(p, "%d", &fd);
3851 close_it = False;
3852 } else if ((p = getenv("PASSWD_FILE")) != NULL) {
3853 fd = open(p, O_RDONLY);
3854 pstrcpy(spec, p);
3855 if (fd < 0) {
3856 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
3857 spec, strerror(errno));
3858 exit(1);
3860 close_it = True;
3862 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
3863 p && p - pass < sizeof(pass);) {
3864 switch (read(fd, p, 1)) {
3865 case 1:
3866 if (*p != '\n' && *p != '\0') {
3867 *++p = '\0'; /* advance p, and null-terminate pass */
3868 break;
3870 case 0:
3871 if (p - pass) {
3872 *p = '\0'; /* null-terminate it, just in case... */
3873 p = NULL; /* then force the loop condition to become false */
3874 break;
3875 } else {
3876 fprintf(stderr, "Error reading password from file %s: %s\n",
3877 spec, "empty password\n");
3878 exit(1);
3881 default:
3882 fprintf(stderr, "Error reading password from file %s: %s\n",
3883 spec, strerror(errno));
3884 exit(1);
3887 pstrcpy(password, pass);
3888 got_pass = True;
3889 if (close_it)
3890 close(fd);
3893 if (*username == 0 && getenv("LOGNAME"))
3895 pstrcpy(username,getenv("LOGNAME"));
3896 strupper(username);
3899 if (argc < 2)
3901 usage(pname);
3902 exit(1);
3905 if (*argv[1] != '-')
3908 pstrcpy(service,argv[1]);
3909 /* Convert any '/' characters in the service name to '\' characters */
3910 string_replace( service, '/','\\');
3911 argc--;
3912 argv++;
3914 if (count_chars(service,'\\') < 3)
3916 usage(pname);
3917 printf("\n%s: Not enough '\\' characters in service\n",service);
3918 exit(1);
3922 if (count_chars(service,'\\') > 3)
3924 usage(pname);
3925 printf("\n%s: Too many '\\' characters in service\n",service);
3926 exit(1);
3930 if (argc > 1 && (*argv[1] != '-'))
3932 got_pass = True;
3933 pstrcpy(password,argv[1]);
3934 memset(argv[1],'X',strlen(argv[1]));
3935 argc--;
3936 argv++;
3940 while ((opt =
3941 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)
3942 switch (opt)
3944 case 'm':
3945 max_protocol = interpret_protocol(optarg,max_protocol);
3946 break;
3947 case 'O':
3948 pstrcpy(user_socket_options,optarg);
3949 break;
3950 case 'R':
3951 pstrcpy(new_name_resolve_order, optarg);
3952 break;
3953 case 'S':
3954 pstrcpy(desthost,optarg);
3955 strupper(desthost);
3956 nt_domain_logon = True;
3957 break;
3958 case 'M':
3959 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3960 pstrcpy(desthost,optarg);
3961 strupper(desthost);
3962 message = True;
3963 break;
3964 case 'B':
3965 iface_set_default(NULL,optarg,NULL);
3966 break;
3967 case 'D':
3968 pstrcpy(base_directory,optarg);
3969 break;
3970 case 'T':
3971 if (!tar_parseargs(argc, argv, optarg, optind)) {
3972 usage(pname);
3973 exit(1);
3975 break;
3976 case 'i':
3977 pstrcpy(scope,optarg);
3978 break;
3979 case 'L':
3980 got_pass = True;
3981 pstrcpy(query_host,optarg);
3982 if(!explicit_user)
3983 *username = '\0';
3984 break;
3985 case 'U':
3987 char *lp;
3988 explicit_user = True;
3989 pstrcpy(username,optarg);
3990 if ((lp=strchr(username,'%')))
3992 *lp = 0;
3993 pstrcpy(password,lp+1);
3994 got_pass = True;
3995 memset(strchr(optarg,'%')+1,'X',strlen(password));
3999 break;
4000 case 'W':
4001 pstrcpy(workgroup,optarg);
4002 break;
4003 case 'E':
4004 dbf = stderr;
4005 break;
4006 case 'I':
4008 dest_ip = *interpret_addr2(optarg);
4009 if (zero_ip(dest_ip)) exit(1);
4010 have_ip = True;
4012 break;
4013 case 'n':
4014 pstrcpy(global_myname,optarg);
4015 break;
4016 case 'N':
4017 got_pass = True;
4018 no_pass = True;
4019 break;
4020 case 'P':
4021 connect_as_printer = True;
4022 break;
4023 case 'd':
4024 if (*optarg == 'A')
4025 DEBUGLEVEL = 10000;
4026 else
4027 DEBUGLEVEL = atoi(optarg);
4028 break;
4029 case 'l':
4030 slprintf(debugf,sizeof(debugf)-1, "%s.client",optarg);
4031 break;
4032 case 'p':
4033 port = atoi(optarg);
4034 break;
4035 case 'c':
4036 cmdstr = optarg;
4037 got_pass = True;
4038 break;
4039 case 'h':
4040 usage(pname);
4041 exit(0);
4042 break;
4043 case 's':
4044 pstrcpy(servicesf, optarg);
4045 break;
4046 case 't':
4047 pstrcpy(term_code, optarg);
4048 break;
4049 default:
4050 usage(pname);
4051 exit(1);
4054 get_myname((*global_myname)?NULL:global_myname,NULL);
4055 strupper(global_myname);
4057 if(*new_name_resolve_order)
4058 lp_set_name_resolve_order(new_name_resolve_order);
4060 if (!tar_type && !*query_host && !*service && !message)
4062 usage(pname);
4063 exit(1);
4066 #ifdef HAVE_LIBREADLINE
4068 /* Initialise GNU Readline */
4070 rl_readline_name = "smbclient";
4071 rl_attempted_completion_function = completion_fn;
4072 rl_completion_entry_function = (Function *)complete_cmd_null;
4074 /* Initialise history list */
4076 using_history();
4078 #endif /* HAVE_LIBREADLINE */
4080 DEBUG( 3, ( "Client started (version %s).\n", VERSION ) );
4082 if (tar_type) {
4083 recurse=True;
4085 if (cli_open_sockets(port)) {
4086 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4087 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4088 int ret;
4090 if ((InBuffer == NULL) || (OutBuffer == NULL))
4091 return(1);
4093 bzero(OutBuffer,smb_size);
4094 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
4095 return(False);
4097 if (*base_directory) do_cd(base_directory);
4099 ret=process_tar(InBuffer, OutBuffer);
4101 cli_send_logout(InBuffer, OutBuffer);
4102 close_sockets();
4103 return(ret);
4104 } else
4105 return(1);
4108 if (*query_host && !nt_domain_logon)
4110 int ret = 0;
4111 slprintf(service,sizeof(service)-1,
4112 "\\\\%s\\IPC$",query_host);
4113 strupper(service);
4114 connect_as_ipc = True;
4115 if (cli_open_sockets(port))
4117 #if 0
4118 *username = 0;
4119 #endif
4120 if (!cli_send_login(NULL,NULL,True,True,NULL))
4121 return(1);
4123 server_info();
4124 if (!browse_host(True)) {
4125 sleep(1);
4126 browse_host(True);
4128 if (!list_servers(workgroup)) {
4129 sleep(1);
4130 list_servers(workgroup);
4133 cli_send_logout(NULL,NULL);
4134 close_sockets();
4137 return(ret);
4140 if (message)
4142 int ret = 0;
4143 if (cli_open_sockets(port))
4145 pstring inbuf,outbuf;
4146 bzero(outbuf,smb_size);
4147 if (!cli_send_session_request(inbuf,outbuf))
4148 return(1);
4150 send_message(inbuf,outbuf);
4152 close_sockets();
4155 return(ret);
4158 if (cli_open_sockets(port))
4160 if (!process(base_directory))
4162 close_sockets();
4163 return(1);
4165 close_sockets();
4167 else
4168 return(1);
4170 return(0);