another makeover of loadparm to support new stuff in swat and
[Samba.git] / source3 / client / client.c
blobda44f344dd896e162063a00d6d90fb4bffa2ef94
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 #ifdef SYSLOG
23 #undef SYSLOG
24 #endif
26 #include "includes.h"
28 #ifndef REGISTER
29 #define REGISTER 0
30 #endif
32 pstring cur_dir = "\\";
33 pstring cd_path = "";
34 extern pstring service;
35 extern pstring desthost;
36 extern pstring myname;
37 extern pstring myhostname;
38 extern pstring password;
39 extern pstring username;
40 extern pstring workgroup;
41 char *cmdstr="";
42 extern BOOL got_pass;
43 extern BOOL no_pass;
44 extern BOOL connect_as_printer;
45 extern BOOL connect_as_ipc;
46 extern struct in_addr ipzero;
48 extern BOOL doencrypt;
50 extern pstring user_socket_options;
52 /* 30 second timeout on most commands */
53 #define CLIENT_TIMEOUT (30*1000)
54 #define SHORT_TIMEOUT (5*1000)
56 /* value for unused fid field in trans2 secondary request */
57 #define FID_UNUSED (0xFFFF)
59 extern int name_type;
61 extern int max_protocol;
64 time_t newer_than = 0;
65 int archive_level = 0;
67 extern pstring debugf;
68 extern int DEBUGLEVEL;
70 BOOL translation = False;
72 extern int cnum;
73 extern int mid;
74 extern int pid;
75 extern int tid;
76 extern int gid;
77 extern int uid;
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)(),BOOL longdir);
84 static int interpret_short_filename(char *p,file_info *finfo);
85 static BOOL do_this_one(file_info *finfo);
87 /* clitar bits insert */
88 extern int blocksize;
89 extern BOOL tar_inc;
90 extern BOOL tar_reset;
91 /* clitar bits end */
94 int 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 void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
141 bzero(outbuf,smb_size);
142 set_message(outbuf,3,0,True);
144 CVAL (outbuf,smb_com) = SMBclose;
145 SSVAL(outbuf,smb_tid,c_num);
146 cli_setup_pkt(outbuf);
147 SSVAL (outbuf,smb_vwv0, f_num);
148 SIVALS(outbuf,smb_vwv1, -1);
150 send_smb(clnt_fd, outbuf);
151 client_receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
154 /****************************************************************************
155 write to a local file with CR/LF->LF translation if appropriate. return the
156 number taken from the buffer. This may not equal the number written.
157 ****************************************************************************/
158 static int writefile(int f, char *b, int n)
160 int i;
162 if (!translation)
163 return(write(f,b,n));
165 i = 0;
166 while (i < n)
168 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
170 b++;i++;
172 if (write(f, b, 1) != 1)
174 break;
176 b++;
177 i++;
180 return(i);
183 /****************************************************************************
184 read from a file with LF->CR/LF translation if appropriate. return the
185 number read. read approx n bytes.
186 ****************************************************************************/
187 static int readfile(char *b, int size, int n, FILE *f)
189 int i;
190 int c;
192 if (!translation || (size != 1))
193 return(fread(b,size,n,f));
195 i = 0;
196 while (i < n)
198 if ((c = getc(f)) == EOF)
200 break;
203 if (c == '\n') /* change all LFs to CR/LF */
205 b[i++] = '\r';
206 n++;
209 if(i < n)
210 b[i++] = c;
213 return(i);
217 /****************************************************************************
218 read from a file with print translation. return the number read. read approx n
219 bytes.
220 ****************************************************************************/
221 static int printread(FILE *f,char *b,int n)
223 int i;
225 i = readfile(b,1, n-1,f);
226 #if FORMFEED
227 if (feof(f) && i>0)
228 b[i++] = '\014';
229 #endif
231 return(i);
234 /****************************************************************************
235 check for existance of a dir
236 ****************************************************************************/
237 static BOOL chkpath(char *path,BOOL report)
239 fstring path2;
240 pstring inbuf,outbuf;
241 char *p;
243 strcpy(path2,path);
244 trim_string(path2,NULL,"\\");
245 if (!*path2) *path2 = '\\';
247 bzero(outbuf,smb_size);
248 set_message(outbuf,0,4 + strlen(path2),True);
249 SCVAL(outbuf,smb_com,SMBchkpth);
250 SSVAL(outbuf,smb_tid,cnum);
251 cli_setup_pkt(outbuf);
253 p = smb_buf(outbuf);
254 *p++ = 4;
255 strcpy(p,path2);
257 #if 0
259 /* this little bit of code can be used to extract NT error codes.
260 Just feed a bunch of "cd foo" commands to smbclient then watch
261 in netmon (tridge) */
262 static int code=0;
263 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
264 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
265 code++;
267 #endif
269 send_smb(Client,outbuf);
270 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
272 if (report && CVAL(inbuf,smb_rcls) != 0)
273 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
275 return(CVAL(inbuf,smb_rcls) == 0);
279 /****************************************************************************
280 send a message
281 ****************************************************************************/
282 static void send_message(char *inbuf,char *outbuf)
284 int total_len = 0;
286 char *p;
287 int grp_id;
289 /* send a SMBsendstrt command */
290 bzero(outbuf,smb_size);
291 set_message(outbuf,0,0,True);
292 CVAL(outbuf,smb_com) = SMBsendstrt;
293 SSVAL(outbuf,smb_tid,cnum);
295 p = smb_buf(outbuf);
296 *p++ = 4;
297 strcpy(p,username);
298 p = skip_string(p,1);
299 *p++ = 4;
300 strcpy(p,desthost);
301 p = skip_string(p,1);
303 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
305 send_smb(Client,outbuf);
308 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
310 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
311 return;
314 grp_id = SVAL(inbuf,smb_vwv0);
316 printf("Connected. Type your message, ending it with a Control-D\n");
318 while (!feof(stdin) && total_len < 1600)
320 int maxlen = MIN(1600 - total_len,127);
321 pstring msg;
322 int l=0;
323 int c;
325 bzero(msg,smb_size);
327 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
329 if (c == '\n')
330 msg[l++] = '\r';
331 msg[l] = c;
334 CVAL(outbuf,smb_com) = SMBsendtxt;
336 set_message(outbuf,1,l+3,True);
338 SSVAL(outbuf,smb_vwv0,grp_id);
340 p = smb_buf(outbuf);
341 *p = 1;
342 SSVAL(p,1,l);
343 memcpy(p+3,msg,l);
345 send_smb(Client,outbuf);
348 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
350 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
351 return;
354 total_len += l;
357 if (total_len >= 1600)
358 printf("the message was truncated to 1600 bytes ");
359 else
360 printf("sent %d bytes ",total_len);
362 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
364 CVAL(outbuf,smb_com) = SMBsendend;
365 set_message(outbuf,1,0,False);
366 SSVAL(outbuf,smb_vwv0,grp_id);
368 send_smb(Client,outbuf);
371 if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
373 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
374 return;
380 /****************************************************************************
381 check the space on a device
382 ****************************************************************************/
383 static void do_dskattr(void)
385 pstring inbuf,outbuf;
387 bzero(outbuf,smb_size);
388 set_message(outbuf,0,0,True);
389 CVAL(outbuf,smb_com) = SMBdskattr;
390 SSVAL(outbuf,smb_tid,cnum);
391 cli_setup_pkt(outbuf);
393 send_smb(Client,outbuf);
394 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
396 if (CVAL(inbuf,smb_rcls) != 0)
397 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
399 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
400 SVAL(inbuf,smb_vwv0),
401 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
402 SVAL(inbuf,smb_vwv3)));
405 /****************************************************************************
406 show cd/pwd
407 ****************************************************************************/
408 static void cmd_pwd(void)
410 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
411 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
415 /****************************************************************************
416 change directory - inner section
417 ****************************************************************************/
418 static void do_cd(char *newdir)
420 char *p = newdir;
421 pstring saved_dir;
422 pstring dname;
424 /* Save the current directory in case the
425 new directory is invalid */
426 strcpy(saved_dir, cur_dir);
427 if (*p == '\\')
428 strcpy(cur_dir,p);
429 else
430 strcat(cur_dir,p);
431 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
432 strcat(cur_dir, "\\");
434 dos_clean_name(cur_dir);
435 strcpy(dname,cur_dir);
436 strcat(cur_dir,"\\");
437 dos_clean_name(cur_dir);
439 if (!strequal(cur_dir,"\\"))
440 if (!chkpath(dname,True))
441 strcpy(cur_dir,saved_dir);
443 strcpy(cd_path,cur_dir);
446 /****************************************************************************
447 change directory
448 ****************************************************************************/
449 static void cmd_cd(char *inbuf,char *outbuf)
451 fstring buf;
453 if (next_token(NULL,buf,NULL))
454 do_cd(buf);
455 else
456 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
460 /****************************************************************************
461 display info about a file
462 ****************************************************************************/
463 static void display_finfo(file_info *finfo)
465 if (do_this_one(finfo)) {
466 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
467 DEBUG(0,(" %-30s%7.7s%10d %s",
468 CNV_LANG(finfo->name),
469 attrib_string(finfo->mode),
470 finfo->size,
471 asctime(LocalTime(&t))));
472 dir_total += finfo->size;
477 /****************************************************************************
478 do a directory listing, calling fn on each file found. Use the TRANSACT2
479 call for long filenames
480 ****************************************************************************/
481 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
483 int max_matches = 512;
484 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
485 char *p;
486 pstring mask;
487 file_info finfo;
488 int i;
489 char *dirlist = NULL;
490 int dirlist_len = 0;
491 int total_received = 0;
492 BOOL First = True;
493 char *resp_data=NULL;
494 char *resp_param=NULL;
495 int resp_data_len = 0;
496 int resp_param_len=0;
498 int ff_resume_key = 0;
499 int ff_searchcount=0;
500 int ff_eos=0;
501 int ff_lastname=0;
502 int ff_dir_handle=0;
503 int loop_count = 0;
505 uint16 setup;
506 pstring param;
508 strcpy(mask,Mask);
510 while (ff_eos == 0)
512 loop_count++;
513 if (loop_count > 200)
515 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
516 break;
519 if (First)
521 setup = TRANSACT2_FINDFIRST;
522 SSVAL(param,0,attribute); /* attribute */
523 SSVAL(param,2,max_matches); /* max count */
524 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
525 SSVAL(param,6,info_level);
526 SIVAL(param,8,0);
527 strcpy(param+12,mask);
529 else
531 setup = TRANSACT2_FINDNEXT;
532 SSVAL(param,0,ff_dir_handle);
533 SSVAL(param,2,max_matches); /* max count */
534 SSVAL(param,4,info_level);
535 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
536 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
537 strcpy(param+12,mask);
539 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
540 ff_dir_handle,ff_resume_key,ff_lastname,mask));
542 /* ??? original code added 1 pad byte after param */
544 cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
545 NULL,param,&setup,
546 0,12+strlen(mask)+1,1,
547 BUFFER_SIZE,10,0);
549 if (!cli_receive_trans_response(inbuf,SMBtrans2,
550 &resp_data_len,&resp_param_len,
551 &resp_data,&resp_param))
553 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
554 break;
557 /* parse out some important return info */
558 p = resp_param;
559 if (First)
561 ff_dir_handle = SVAL(p,0);
562 ff_searchcount = SVAL(p,2);
563 ff_eos = SVAL(p,4);
564 ff_lastname = SVAL(p,8);
566 else
568 ff_searchcount = SVAL(p,0);
569 ff_eos = SVAL(p,2);
570 ff_lastname = SVAL(p,6);
573 if (ff_searchcount == 0)
574 break;
576 /* point to the data bytes */
577 p = resp_data;
579 /* we might need the lastname for continuations */
580 if (ff_lastname > 0)
582 switch(info_level)
584 case 260:
585 ff_resume_key =0;
586 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
587 /* strcpy(mask,p+ff_lastname+94); */
588 break;
589 case 1:
590 strcpy(mask,p + ff_lastname + 1);
591 ff_resume_key = 0;
592 break;
595 else
596 strcpy(mask,"");
598 /* and add them to the dirlist pool */
599 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
601 if (!dirlist)
603 DEBUG(0,("Failed to expand dirlist\n"));
604 break;
607 /* put in a length for the last entry, to ensure we can chain entries
608 into the next packet */
610 char *p2;
611 for (p2=p,i=0;i<(ff_searchcount-1);i++)
612 p2 += interpret_long_filename(info_level,p2,NULL);
613 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
616 /* grab the data for later use */
617 memcpy(dirlist+dirlist_len,p,resp_data_len);
618 dirlist_len += resp_data_len;
620 total_received += ff_searchcount;
622 if (resp_data) free(resp_data); resp_data = NULL;
623 if (resp_param) free(resp_param); resp_param = NULL;
625 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
626 ff_searchcount,ff_eos,ff_resume_key));
628 First = False;
631 if (!fn)
632 for (p=dirlist,i=0;i<total_received;i++)
634 p += interpret_long_filename(info_level,p,&finfo);
635 display_finfo(&finfo);
638 for (p=dirlist,i=0;i<total_received;i++)
640 p += interpret_long_filename(info_level,p,&finfo);
641 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
644 /* free up the dirlist buffer */
645 if (dirlist) free(dirlist);
646 return(total_received);
650 /****************************************************************************
651 do a directory listing, calling fn on each file found
652 ****************************************************************************/
653 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
655 char *p;
656 int received = 0;
657 BOOL first = True;
658 char status[21];
659 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
660 int num_received = 0;
661 int i;
662 char *dirlist = NULL;
663 pstring mask;
664 file_info finfo;
666 finfo = def_finfo;
668 bzero(status,21);
670 strcpy(mask,Mask);
672 while (1)
674 bzero(outbuf,smb_size);
675 if (first)
676 set_message(outbuf,2,5 + strlen(mask),True);
677 else
678 set_message(outbuf,2,5 + 21,True);
680 #if FFIRST
681 if (Protocol >= PROTOCOL_LANMAN1)
682 CVAL(outbuf,smb_com) = SMBffirst;
683 else
684 #endif
685 CVAL(outbuf,smb_com) = SMBsearch;
687 SSVAL(outbuf,smb_tid,cnum);
688 cli_setup_pkt(outbuf);
690 SSVAL(outbuf,smb_vwv0,num_asked);
691 SSVAL(outbuf,smb_vwv1,attribute);
693 p = smb_buf(outbuf);
694 *p++ = 4;
696 if (first)
697 strcpy(p,mask);
698 else
699 strcpy(p,"");
700 p += strlen(p) + 1;
702 *p++ = 5;
703 if (first)
704 SSVAL(p,0,0);
705 else
707 SSVAL(p,0,21);
708 p += 2;
709 memcpy(p,status,21);
712 send_smb(Client,outbuf);
713 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
715 received = SVAL(inbuf,smb_vwv0);
717 DEBUG(5,("dir received %d\n",received));
719 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
721 if (received <= 0) break;
723 first = False;
725 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
727 if (!dirlist)
728 return 0;
730 p = smb_buf(inbuf) + 3;
732 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
733 p,received*DIR_STRUCT_SIZE);
735 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
737 num_received += received;
739 if (CVAL(inbuf,smb_rcls) != 0) break;
742 #if FFIRST
743 if (!first && Protocol >= PROTOCOL_LANMAN1)
745 bzero(outbuf,smb_size);
746 CVAL(outbuf,smb_com) = SMBfclose;
748 SSVAL(outbuf,smb_tid,cnum);
749 cli_setup_pkt(outbuf);
751 p = smb_buf(outbuf);
752 *p++ = 4;
754 strcpy(p,"");
755 p += strlen(p) + 1;
757 *p++ = 5;
758 SSVAL(p,0,21);
759 p += 2;
760 memcpy(p,status,21);
762 send_smb(Client,outbuf);
763 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
765 if (CVAL(inbuf,smb_rcls) != 0)
766 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
768 #endif
770 if (!fn)
771 for (p=dirlist,i=0;i<num_received;i++)
773 p += interpret_short_filename(p,&finfo);
774 display_finfo(&finfo);
777 for (p=dirlist,i=0;i<num_received;i++)
779 p += interpret_short_filename(p,&finfo);
780 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
783 if (dirlist) free(dirlist);
784 return(num_received);
789 /****************************************************************************
790 do a directory listing, calling fn on each file found
791 ****************************************************************************/
792 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
794 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
795 if (Protocol >= PROTOCOL_LANMAN2)
797 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
798 return;
801 expand_mask(Mask,False);
802 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
803 return;
806 /*******************************************************************
807 decide if a file should be operated on
808 ********************************************************************/
809 static BOOL do_this_one(file_info *finfo)
811 if (finfo->mode & aDIR) return(True);
813 if (newer_than && finfo->mtime < newer_than)
814 return(False);
816 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
817 return(False);
819 return(True);
823 /*****************************************************************************
824 Convert a character pointer in a cli_call_api() response to a form we can use.
825 This function contains code to prevent core dumps if the server returns
826 invalid data.
827 *****************************************************************************/
828 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
830 if( datap == 0 ) /* turn NULL pointers */
831 { /* into zero length strings */
832 return "";
834 else
836 unsigned int offset = datap - converter;
838 if( offset >= rdrcnt )
840 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
841 return "<ERROR>";
843 else
845 return &rdata[offset];
850 /****************************************************************************
851 interpret a short filename structure
852 The length of the structure is returned
853 ****************************************************************************/
854 static int interpret_short_filename(char *p,file_info *finfo)
856 finfo->mode = CVAL(p,21);
858 /* this date is converted to GMT by make_unix_date */
859 finfo->ctime = make_unix_date(p+22);
860 finfo->mtime = finfo->atime = finfo->ctime;
861 finfo->size = IVAL(p,26);
862 strcpy(finfo->name,p+30);
864 return(DIR_STRUCT_SIZE);
867 /****************************************************************************
868 interpret a long filename structure - this is mostly guesses at the moment
869 The length of the structure is returned
870 The structure of a long filename depends on the info level. 260 is used
871 by NT and 2 is used by OS/2
872 ****************************************************************************/
873 static int interpret_long_filename(int level,char *p,file_info *finfo)
875 if (finfo)
876 memcpy(finfo,&def_finfo,sizeof(*finfo));
878 switch (level)
880 case 1: /* OS/2 understands this */
881 if (finfo)
883 /* these dates are converted to GMT by make_unix_date */
884 finfo->ctime = make_unix_date2(p+4);
885 finfo->atime = make_unix_date2(p+8);
886 finfo->mtime = make_unix_date2(p+12);
887 finfo->size = IVAL(p,16);
888 finfo->mode = CVAL(p,24);
889 strcpy(finfo->name,p+27);
891 return(28 + CVAL(p,26));
893 case 2: /* this is what OS/2 uses mostly */
894 if (finfo)
896 /* these dates are converted to GMT by make_unix_date */
897 finfo->ctime = make_unix_date2(p+4);
898 finfo->atime = make_unix_date2(p+8);
899 finfo->mtime = make_unix_date2(p+12);
900 finfo->size = IVAL(p,16);
901 finfo->mode = CVAL(p,24);
902 strcpy(finfo->name,p+31);
904 return(32 + CVAL(p,30));
906 /* levels 3 and 4 are untested */
907 case 3:
908 if (finfo)
910 /* these dates are probably like the other ones */
911 finfo->ctime = make_unix_date2(p+8);
912 finfo->atime = make_unix_date2(p+12);
913 finfo->mtime = make_unix_date2(p+16);
914 finfo->size = IVAL(p,20);
915 finfo->mode = CVAL(p,28);
916 strcpy(finfo->name,p+33);
918 return(SVAL(p,4)+4);
920 case 4:
921 if (finfo)
923 /* these dates are probably like the other ones */
924 finfo->ctime = make_unix_date2(p+8);
925 finfo->atime = make_unix_date2(p+12);
926 finfo->mtime = make_unix_date2(p+16);
927 finfo->size = IVAL(p,20);
928 finfo->mode = CVAL(p,28);
929 strcpy(finfo->name,p+37);
931 return(SVAL(p,4)+4);
933 case 260: /* NT uses this, but also accepts 2 */
934 if (finfo)
936 int ret = SVAL(p,0);
937 int namelen;
938 p += 4; /* next entry offset */
939 p += 4; /* fileindex */
941 /* these dates appear to arrive in a weird way. It seems to
942 be localtime plus the serverzone given in the initial
943 connect. This is GMT when DST is not in effect and one
944 hour from GMT otherwise. Can this really be right??
946 I suppose this could be called kludge-GMT. Is is the GMT
947 you get by using the current DST setting on a different
948 localtime. It will be cheap to calculate, I suppose, as
949 no DST tables will be needed */
951 finfo->ctime = interpret_long_date(p); p += 8;
952 finfo->atime = interpret_long_date(p); p += 8;
953 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
954 finfo->size = IVAL(p,0); p += 8;
955 p += 8; /* alloc size */
956 finfo->mode = CVAL(p,0); p += 4;
957 namelen = IVAL(p,0); p += 4;
958 p += 4; /* EA size */
959 p += 2; /* short name len? */
960 p += 24; /* short name? */
961 StrnCpy(finfo->name,p,namelen);
962 return(ret);
964 return(SVAL(p,0));
967 DEBUG(1,("Unknown long filename format %d\n",level));
968 return(SVAL(p,0));
974 /****************************************************************************
975 act on the files in a dir listing
976 ****************************************************************************/
977 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
980 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
981 !mask_match(finfo->name,fileselection,False,False)) &&
982 !(recurse_dir && (strequal(finfo->name,".") ||
983 strequal(finfo->name,".."))))
985 if (recurse_dir && (finfo->mode & aDIR))
987 pstring mask2;
988 pstring sav_dir;
989 strcpy(sav_dir,cur_dir);
990 strcat(cur_dir,finfo->name);
991 strcat(cur_dir,"\\");
992 strcpy(mask2,cur_dir);
994 if (!fn)
995 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
997 strcat(mask2,"*");
999 if (longdir)
1000 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);
1001 else
1002 do_dir(inbuf,outbuf,mask2,attribute,fn,True);
1004 strcpy(cur_dir,sav_dir);
1006 else
1008 if (fn && do_this_one(finfo))
1009 fn(finfo);
1015 /****************************************************************************
1016 get a directory listing
1017 ****************************************************************************/
1018 static void cmd_dir(char *inbuf,char *outbuf)
1020 int attribute = aDIR | aSYSTEM | aHIDDEN;
1021 pstring mask;
1022 fstring buf;
1023 char *p=buf;
1025 dir_total = 0;
1026 strcpy(mask,cur_dir);
1027 if(mask[strlen(mask)-1]!='\\')
1028 strcat(mask,"\\");
1030 if (next_token(NULL,buf,NULL))
1032 if (*p == '\\')
1033 strcpy(mask,p);
1034 else
1035 strcat(mask,p);
1037 else {
1038 strcat(mask,"*");
1041 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1043 do_dskattr();
1045 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1050 /****************************************************************************
1051 get a file from rname to lname
1052 ****************************************************************************/
1053 static void do_get(char *rname,char *lname,file_info *finfo1)
1055 int handle=0,fnum;
1056 uint32 nread=0;
1057 char *p;
1058 BOOL newhandle = False;
1059 char *inbuf,*outbuf;
1060 file_info finfo;
1061 BOOL close_done = False;
1062 BOOL ignore_close_error = False;
1063 char *dataptr=NULL;
1064 int datalen=0;
1066 struct timeval tp_start;
1067 GetTimeOfDay(&tp_start);
1069 if (finfo1)
1070 finfo = *finfo1;
1071 else
1072 finfo = def_finfo;
1074 if (lowercase)
1075 strlower(lname);
1078 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1079 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1081 if (!inbuf || !outbuf)
1083 DEBUG(0,("out of memory\n"));
1084 return;
1087 bzero(outbuf,smb_size);
1088 set_message(outbuf,15,1 + strlen(rname),True);
1090 CVAL(outbuf,smb_com) = SMBopenX;
1091 SSVAL(outbuf,smb_tid,cnum);
1092 cli_setup_pkt(outbuf);
1094 SSVAL(outbuf,smb_vwv0,0xFF);
1095 SSVAL(outbuf,smb_vwv2,1); /* return additional info */
1096 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1097 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1098 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1099 SSVAL(outbuf,smb_vwv8,1);
1100 SSVAL(outbuf,smb_vwv11,0xffff);
1101 SSVAL(outbuf,smb_vwv12,0xffff);
1103 p = smb_buf(outbuf);
1104 strcpy(p,rname);
1105 p = skip_string(p,1);
1107 /* do a chained openX with a readX? */
1108 #if 1
1109 if (finfo.size > 0)
1111 DEBUG(3,("Chaining readX wth openX\n"));
1112 SSVAL(outbuf,smb_vwv0,SMBreadX);
1113 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1114 bzero(p,200);
1115 p -= smb_wct;
1116 SSVAL(p,smb_wct,10);
1117 SSVAL(p,smb_vwv0,0xFF);
1118 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1119 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1120 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1122 #endif
1124 if(!strcmp(lname,"-"))
1125 handle = fileno(stdout);
1126 else
1128 handle = creat(lname,0644);
1129 newhandle = True;
1131 if (handle < 0)
1133 DEBUG(0,("Error opening local file %s\n",lname));
1134 free(inbuf);free(outbuf);
1135 return;
1138 send_smb(Client,outbuf);
1139 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1141 if (CVAL(inbuf,smb_rcls) != 0)
1143 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1144 SVAL(inbuf,smb_err) == ERRnoresource &&
1145 cli_reopen_connection(inbuf,outbuf))
1147 do_get(rname,lname,finfo1);
1148 return;
1150 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1151 if(newhandle)
1152 close(handle);
1153 free(inbuf);free(outbuf);
1154 return;
1157 strcpy(finfo.name,rname);
1159 if (!finfo1)
1161 finfo.mode = SVAL(inbuf,smb_vwv3);
1162 /* these times arrive as LOCAL time, using the DST offset
1163 corresponding to that time, we convert them to GMT */
1164 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1165 finfo.atime = finfo.ctime = finfo.mtime;
1166 finfo.size = IVAL(inbuf,smb_vwv6);
1169 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1171 fnum = SVAL(inbuf,smb_vwv2);
1173 /* we might have got some data from a chained readX */
1174 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1176 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1177 datalen = SVAL(p,smb_vwv5);
1178 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1180 else
1182 dataptr = NULL;
1183 datalen = 0;
1187 DEBUG(2,("getting file %s of size %d bytes as %s ",
1188 CNV_LANG(finfo.name),
1189 finfo.size,
1190 lname));
1192 while (nread < finfo.size && !close_done)
1194 int method = -1;
1195 static BOOL can_chain_close = True;
1197 p=NULL;
1199 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1201 /* 3 possible read types. readbraw if a large block is required.
1202 readX + close if not much left and read if neither is supported */
1204 /* we might have already read some data from a chained readX */
1205 if (dataptr && datalen>0)
1206 method=3;
1208 /* if we can finish now then readX+close */
1209 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1210 ((finfo.size - nread) <
1211 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1212 method = 0;
1214 /* if we support readraw then use that */
1215 if (method<0 && readbraw_supported)
1216 method = 1;
1218 /* if we can then use readX */
1219 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1220 method = 2;
1222 switch (method)
1224 /* use readX */
1225 case 0:
1226 case 2:
1227 if (method == 0)
1228 close_done = True;
1230 /* use readX + close */
1231 bzero(outbuf,smb_size);
1232 set_message(outbuf,10,0,True);
1233 CVAL(outbuf,smb_com) = SMBreadX;
1234 SSVAL(outbuf,smb_tid,cnum);
1235 cli_setup_pkt(outbuf);
1237 if (close_done)
1239 CVAL(outbuf,smb_vwv0) = SMBclose;
1240 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1242 else
1243 CVAL(outbuf,smb_vwv0) = 0xFF;
1245 SSVAL(outbuf,smb_vwv2,fnum);
1246 SIVAL(outbuf,smb_vwv3,nread);
1247 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1248 SSVAL(outbuf,smb_vwv6,0);
1249 SIVAL(outbuf,smb_vwv7,0);
1250 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1252 if (close_done)
1254 p = smb_buf(outbuf);
1255 bzero(p,9);
1257 CVAL(p,0) = 3;
1258 SSVAL(p,1,fnum);
1259 SIVALS(p,3,-1);
1261 /* now set the total packet length */
1262 smb_setlen(outbuf,smb_len(outbuf)+9);
1265 send_smb(Client,outbuf);
1266 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1268 if (CVAL(inbuf,smb_rcls) != 0)
1270 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1271 break;
1274 if (close_done &&
1275 SVAL(inbuf,smb_vwv0) != SMBclose)
1277 /* NOTE: WfWg sometimes just ignores the chained
1278 command! This seems to break the spec? */
1279 DEBUG(3,("Rejected chained close?\n"));
1280 close_done = False;
1281 can_chain_close = False;
1282 ignore_close_error = True;
1285 datalen = SVAL(inbuf,smb_vwv5);
1286 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1287 break;
1289 /* use readbraw */
1290 case 1:
1292 static int readbraw_size = BUFFER_SIZE;
1294 extern int Client;
1295 bzero(outbuf,smb_size);
1296 set_message(outbuf,8,0,True);
1297 CVAL(outbuf,smb_com) = SMBreadbraw;
1298 SSVAL(outbuf,smb_tid,cnum);
1299 cli_setup_pkt(outbuf);
1300 SSVAL(outbuf,smb_vwv0,fnum);
1301 SIVAL(outbuf,smb_vwv1,nread);
1302 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1303 SSVAL(outbuf,smb_vwv4,0);
1304 SIVALS(outbuf,smb_vwv5,-1);
1305 send_smb(Client,outbuf);
1307 /* Now read the raw data into the buffer and write it */
1308 if(read_smb_length(Client,inbuf,0) == -1) {
1309 DEBUG(0,("Failed to read length in readbraw\n"));
1310 exit(1);
1313 /* Even though this is not an smb message, smb_len
1314 returns the generic length of an smb message */
1315 datalen = smb_len(inbuf);
1317 if (datalen == 0)
1319 /* we got a readbraw error */
1320 DEBUG(4,("readbraw error - reducing size\n"));
1321 readbraw_size = (readbraw_size * 9) / 10;
1323 if (readbraw_size < max_xmit)
1325 DEBUG(0,("disabling readbraw\n"));
1326 readbraw_supported = False;
1329 dataptr=NULL;
1330 continue;
1333 if(read_data(Client,inbuf,datalen) != datalen) {
1334 DEBUG(0,("Failed to read data in readbraw\n"));
1335 exit(1);
1337 dataptr = inbuf;
1339 break;
1341 case 3:
1342 /* we've already read some data with a chained readX */
1343 break;
1345 default:
1346 /* use plain read */
1347 bzero(outbuf,smb_size);
1348 set_message(outbuf,5,0,True);
1349 CVAL(outbuf,smb_com) = SMBread;
1350 SSVAL(outbuf,smb_tid,cnum);
1351 cli_setup_pkt(outbuf);
1353 SSVAL(outbuf,smb_vwv0,fnum);
1354 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1355 SIVAL(outbuf,smb_vwv2,nread);
1356 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1358 send_smb(Client,outbuf);
1359 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1361 if (CVAL(inbuf,smb_rcls) != 0)
1363 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1364 break;
1367 datalen = SVAL(inbuf,smb_vwv0);
1368 dataptr = smb_buf(inbuf) + 3;
1369 break;
1372 if (writefile(handle,dataptr,datalen) != datalen)
1374 DEBUG(0,("Error writing local file\n"));
1375 break;
1378 nread += datalen;
1379 if (datalen == 0)
1381 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1382 break;
1385 dataptr=NULL;
1386 datalen=0;
1391 if (!close_done)
1393 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1395 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1397 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1398 if(newhandle)
1399 close(handle);
1400 free(inbuf);free(outbuf);
1401 return;
1405 if(newhandle)
1406 close(handle);
1408 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1409 bzero(outbuf,smb_size);
1410 set_message(outbuf,8,strlen(rname)+4,True);
1411 CVAL(outbuf,smb_com) = SMBsetatr;
1412 SSVAL(outbuf,smb_tid,cnum);
1413 cli_setup_pkt(outbuf);
1414 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1415 SIVALS(outbuf,smb_vwv1,0);
1416 p = smb_buf(outbuf);
1417 *p++ = 4;
1418 strcpy(p,rname);
1419 p += strlen(p)+1;
1420 *p++ = 4;
1421 *p = 0;
1422 send_smb(Client,outbuf);
1423 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1427 struct timeval tp_end;
1428 int this_time;
1430 GetTimeOfDay(&tp_end);
1431 this_time =
1432 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1433 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1434 get_total_time_ms += this_time;
1435 get_total_size += finfo.size;
1437 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1438 finfo.size / (1.024*this_time + 1.0e-4),
1439 get_total_size / (1.024*get_total_time_ms)));
1442 free(inbuf);free(outbuf);
1446 /****************************************************************************
1447 get a file
1448 ****************************************************************************/
1449 static void cmd_get(void)
1451 pstring lname;
1452 pstring rname;
1453 char *p;
1455 strcpy(rname,cur_dir);
1456 strcat(rname,"\\");
1458 p = rname + strlen(rname);
1460 if (!next_token(NULL,p,NULL)) {
1461 DEBUG(0,("get <filename>\n"));
1462 return;
1464 strcpy(lname,p);
1465 dos_clean_name(rname);
1467 next_token(NULL,lname,NULL);
1469 do_get(rname,lname,NULL);
1473 /****************************************************************************
1474 do a mget operation on one file
1475 ****************************************************************************/
1476 static void do_mget(file_info *finfo)
1478 pstring rname;
1479 pstring quest;
1481 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1482 return;
1484 if (abort_mget)
1486 DEBUG(0,("mget aborted\n"));
1487 return;
1490 if (finfo->mode & aDIR)
1491 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1492 else
1493 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1495 if (prompt && !yesno(quest)) return;
1497 if (finfo->mode & aDIR)
1499 pstring saved_curdir;
1500 pstring mget_mask;
1501 char *inbuf,*outbuf;
1503 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1504 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1506 if (!inbuf || !outbuf)
1508 DEBUG(0,("out of memory\n"));
1509 return;
1512 strcpy(saved_curdir,cur_dir);
1514 strcat(cur_dir,finfo->name);
1515 strcat(cur_dir,"\\");
1517 unix_format(finfo->name);
1519 if (lowercase)
1520 strlower(finfo->name);
1522 if (!directory_exist(finfo->name,NULL) &&
1523 sys_mkdir(finfo->name,0777) != 0)
1525 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1526 strcpy(cur_dir,saved_curdir);
1527 free(inbuf);free(outbuf);
1528 return;
1531 if (sys_chdir(finfo->name) != 0)
1533 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1534 strcpy(cur_dir,saved_curdir);
1535 free(inbuf);free(outbuf);
1536 return;
1540 strcpy(mget_mask,cur_dir);
1541 strcat(mget_mask,"*");
1543 do_dir((char *)inbuf,(char *)outbuf,
1544 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1545 chdir("..");
1546 strcpy(cur_dir,saved_curdir);
1547 free(inbuf);free(outbuf);
1549 else
1551 strcpy(rname,cur_dir);
1552 strcat(rname,finfo->name);
1553 do_get(rname,finfo->name,finfo);
1557 /****************************************************************************
1558 view the file using the pager
1559 ****************************************************************************/
1560 static void cmd_more(void)
1562 fstring rname,lname,tmpname,pager_cmd;
1563 char *pager;
1565 strcpy(rname,cur_dir);
1566 strcat(rname,"\\");
1567 sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1568 strcpy(lname,tmpname);
1570 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1571 DEBUG(0,("more <filename>\n"));
1572 return;
1574 dos_clean_name(rname);
1576 do_get(rname,lname,NULL);
1578 pager=getenv("PAGER");
1579 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1580 system(pager_cmd);
1581 unlink(tmpname);
1586 /****************************************************************************
1587 do a mget command
1588 ****************************************************************************/
1589 static void cmd_mget(char *inbuf,char *outbuf)
1591 int attribute = aSYSTEM | aHIDDEN;
1592 pstring mget_mask;
1593 fstring buf;
1594 char *p=buf;
1596 *mget_mask = 0;
1598 if (recurse)
1599 attribute |= aDIR;
1601 abort_mget = False;
1603 while (next_token(NULL,p,NULL))
1605 strcpy(mget_mask,cur_dir);
1606 if(mget_mask[strlen(mget_mask)-1]!='\\')
1607 strcat(mget_mask,"\\");
1609 if (*p == '\\')
1610 strcpy(mget_mask,p);
1611 else
1612 strcat(mget_mask,p);
1613 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1616 if (! *mget_mask)
1618 strcpy(mget_mask,cur_dir);
1619 if(mget_mask[strlen(mget_mask)-1]!='\\')
1620 strcat(mget_mask,"\\");
1621 strcat(mget_mask,"*");
1622 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1626 /****************************************************************************
1627 make a directory of name "name"
1628 ****************************************************************************/
1629 static BOOL do_mkdir(char *name)
1631 char *p;
1632 char *inbuf,*outbuf;
1634 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1635 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1637 if (!inbuf || !outbuf)
1639 DEBUG(0,("out of memory\n"));
1640 return False;
1643 bzero(outbuf,smb_size);
1644 set_message(outbuf,0,2 + strlen(name),True);
1646 CVAL(outbuf,smb_com) = SMBmkdir;
1647 SSVAL(outbuf,smb_tid,cnum);
1648 cli_setup_pkt(outbuf);
1651 p = smb_buf(outbuf);
1652 *p++ = 4;
1653 strcpy(p,name);
1655 send_smb(Client,outbuf);
1656 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1658 if (CVAL(inbuf,smb_rcls) != 0)
1660 DEBUG(0,("%s making remote directory %s\n",
1661 smb_errstr(inbuf),CNV_LANG(name)));
1663 free(inbuf);free(outbuf);
1664 return(False);
1667 free(inbuf);free(outbuf);
1668 return(True);
1672 /****************************************************************************
1673 make a directory
1674 ****************************************************************************/
1675 static void cmd_mkdir(char *inbuf,char *outbuf)
1677 pstring mask;
1678 fstring buf;
1679 char *p=buf;
1681 strcpy(mask,cur_dir);
1683 if (!next_token(NULL,p,NULL))
1685 if (!recurse)
1686 DEBUG(0,("mkdir <dirname>\n"));
1687 return;
1689 strcat(mask,p);
1691 if (recurse)
1693 pstring ddir;
1694 pstring ddir2;
1695 *ddir2 = 0;
1697 strcpy(ddir,mask);
1698 trim_string(ddir,".",NULL);
1699 p = strtok(ddir,"/\\");
1700 while (p)
1702 strcat(ddir2,p);
1703 if (!chkpath(ddir2,False))
1705 do_mkdir(ddir2);
1707 strcat(ddir2,"\\");
1708 p = strtok(NULL,"/\\");
1711 else
1712 do_mkdir(mask);
1716 /*******************************************************************
1717 write to a file using writebraw
1718 ********************************************************************/
1719 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1721 extern int Client;
1722 pstring inbuf;
1724 bzero(outbuf,smb_size);
1725 bzero(inbuf,smb_size);
1726 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1728 CVAL(outbuf,smb_com) = SMBwritebraw;
1729 SSVAL(outbuf,smb_tid,cnum);
1730 cli_setup_pkt(outbuf);
1732 SSVAL(outbuf,smb_vwv0,fnum);
1733 SSVAL(outbuf,smb_vwv1,n);
1734 SIVAL(outbuf,smb_vwv3,pos);
1735 SSVAL(outbuf,smb_vwv7,1);
1737 send_smb(Client,outbuf);
1739 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1740 return(0);
1742 _smb_setlen(buf-4,n); /* HACK! XXXX */
1744 if (write_socket(Client,buf-4,n+4) != n+4)
1745 return(0);
1747 if (!client_receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1748 DEBUG(0,("Error writing remote file (2)\n"));
1749 return(0);
1751 return(SVAL(inbuf,smb_vwv0));
1756 /*******************************************************************
1757 write to a file
1758 ********************************************************************/
1759 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1761 pstring inbuf;
1763 if (writebraw_supported && n > (max_xmit-200))
1764 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1766 bzero(outbuf,smb_size);
1767 bzero(inbuf,smb_size);
1768 set_message(outbuf,5,n + 3,True);
1770 CVAL(outbuf,smb_com) = SMBwrite;
1771 SSVAL(outbuf,smb_tid,cnum);
1772 cli_setup_pkt(outbuf);
1774 SSVAL(outbuf,smb_vwv0,fnum);
1775 SSVAL(outbuf,smb_vwv1,n);
1776 SIVAL(outbuf,smb_vwv2,pos);
1777 SSVAL(outbuf,smb_vwv4,0);
1778 CVAL(smb_buf(outbuf),0) = 1;
1779 SSVAL(smb_buf(outbuf),1,n);
1781 memcpy(smb_buf(outbuf)+3,buf,n);
1783 send_smb(Client,outbuf);
1784 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1786 if (CVAL(inbuf,smb_rcls) != 0) {
1787 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1788 return(0);
1790 return(SVAL(inbuf,smb_vwv0));
1795 /****************************************************************************
1796 put a single file
1797 ****************************************************************************/
1798 static void do_put(char *rname,char *lname,file_info *finfo)
1800 int fnum;
1801 FILE *f;
1802 int nread=0;
1803 char *p;
1804 char *inbuf,*outbuf;
1805 time_t close_time = finfo->mtime;
1806 char *buf=NULL;
1807 static int maxwrite=0;
1809 struct timeval tp_start;
1810 GetTimeOfDay(&tp_start);
1812 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1813 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1815 if (!inbuf || !outbuf)
1817 DEBUG(0,("out of memory\n"));
1818 return;
1821 bzero(outbuf,smb_size);
1822 set_message(outbuf,3,2 + strlen(rname),True);
1824 if (finfo->mtime == 0 || finfo->mtime == -1)
1825 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1827 CVAL(outbuf,smb_com) = SMBcreate;
1828 SSVAL(outbuf,smb_tid,cnum);
1829 cli_setup_pkt(outbuf);
1831 SSVAL(outbuf,smb_vwv0,finfo->mode);
1832 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1834 p = smb_buf(outbuf);
1835 *p++ = 4;
1836 strcpy(p,rname);
1838 send_smb(Client,outbuf);
1839 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1841 if (CVAL(inbuf,smb_rcls) != 0)
1843 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1845 free(inbuf);free(outbuf);if (buf) free(buf);
1846 return;
1849 f = fopen(lname,"r");
1851 if (!f)
1853 DEBUG(0,("Error opening local file %s\n",lname));
1854 free(inbuf);free(outbuf);
1855 return;
1859 fnum = SVAL(inbuf,smb_vwv0);
1860 if (finfo->size < 0)
1861 finfo->size = file_size(lname);
1863 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1865 if (!maxwrite)
1866 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1868 while (nread < finfo->size)
1870 int n = maxwrite;
1871 int ret;
1873 n = MIN(n,finfo->size - nread);
1875 buf = (char *)Realloc(buf,n+4);
1877 fseek(f,nread,SEEK_SET);
1878 if ((n = readfile(buf+4,1,n,f)) < 1)
1880 DEBUG(0,("Error reading local file\n"));
1881 break;
1884 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1886 if (n != ret) {
1887 if (!maxwrite) {
1888 DEBUG(0,("Error writing file\n"));
1889 break;
1890 } else {
1891 maxwrite /= 2;
1892 continue;
1896 nread += n;
1901 bzero(outbuf,smb_size);
1902 set_message(outbuf,3,0,True);
1903 CVAL(outbuf,smb_com) = SMBclose;
1904 SSVAL(outbuf,smb_tid,cnum);
1905 cli_setup_pkt(outbuf);
1907 SSVAL(outbuf,smb_vwv0,fnum);
1908 put_dos_date3(outbuf,smb_vwv1,close_time);
1910 send_smb(Client,outbuf);
1911 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1913 if (CVAL(inbuf,smb_rcls) != 0)
1915 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1916 fclose(f);
1917 free(inbuf);free(outbuf);
1918 if (buf) free(buf);
1919 return;
1923 fclose(f);
1924 free(inbuf);free(outbuf);
1925 if (buf) free(buf);
1928 struct timeval tp_end;
1929 int this_time;
1931 GetTimeOfDay(&tp_end);
1932 this_time =
1933 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1934 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1935 put_total_time_ms += this_time;
1936 put_total_size += finfo->size;
1938 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1939 finfo->size / (1.024*this_time + 1.0e-4),
1940 put_total_size / (1.024*put_total_time_ms)));
1946 /****************************************************************************
1947 put a file
1948 ****************************************************************************/
1949 static void cmd_put(void)
1951 pstring lname;
1952 pstring rname;
1953 fstring buf;
1954 char *p=buf;
1955 file_info finfo;
1956 finfo = def_finfo;
1958 strcpy(rname,cur_dir);
1959 strcat(rname,"\\");
1962 if (!next_token(NULL,p,NULL))
1964 DEBUG(0,("put <filename>\n"));
1965 return;
1967 strcpy(lname,p);
1969 if (next_token(NULL,p,NULL))
1970 strcat(rname,p);
1971 else
1972 strcat(rname,lname);
1974 dos_clean_name(rname);
1977 struct stat st;
1978 if (!file_exist(lname,&st)) {
1979 DEBUG(0,("%s does not exist\n",lname));
1980 return;
1982 finfo.mtime = st.st_mtime;
1985 do_put(rname,lname,&finfo);
1988 /****************************************************************************
1989 seek in a directory/file list until you get something that doesn't start with
1990 the specified name
1991 ****************************************************************************/
1992 static BOOL seek_list(FILE *f,char *name)
1994 pstring s;
1995 while (!feof(f))
1997 if (fscanf(f,"%s",s) != 1) return(False);
1998 trim_string(s,"./",NULL);
1999 if (strncmp(s,name,strlen(name)) != 0)
2001 strcpy(name,s);
2002 return(True);
2006 return(False);
2010 /****************************************************************************
2011 set the file selection mask
2012 ****************************************************************************/
2013 static void cmd_select(void)
2015 strcpy(fileselection,"");
2016 next_token(NULL,fileselection,NULL);
2020 /****************************************************************************
2021 mput some files
2022 ****************************************************************************/
2023 static void cmd_mput(void)
2025 pstring lname;
2026 pstring rname;
2027 file_info finfo;
2028 fstring buf;
2029 char *p=buf;
2031 finfo = def_finfo;
2034 while (next_token(NULL,p,NULL))
2036 struct stat st;
2037 pstring cmd;
2038 pstring tmpname;
2039 FILE *f;
2041 sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2042 if (recurse)
2043 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2044 else
2045 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2046 system(cmd);
2048 f = fopen(tmpname,"r");
2049 if (!f) continue;
2051 while (!feof(f))
2053 pstring quest;
2055 if (fscanf(f,"%s",lname) != 1) break;
2056 trim_string(lname,"./",NULL);
2058 again1:
2060 /* check if it's a directory */
2061 if (directory_exist(lname,&st))
2063 if (!recurse) continue;
2064 sprintf(quest,"Put directory %s? ",lname);
2065 if (prompt && !yesno(quest))
2067 strcat(lname,"/");
2068 if (!seek_list(f,lname))
2069 break;
2070 goto again1;
2073 strcpy(rname,cur_dir);
2074 strcat(rname,lname);
2075 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2076 strcat(lname,"/");
2077 if (!seek_list(f,lname))
2078 break;
2079 goto again1;
2082 continue;
2084 else
2086 sprintf(quest,"Put file %s? ",lname);
2087 if (prompt && !yesno(quest)) continue;
2089 strcpy(rname,cur_dir);
2090 strcat(rname,lname);
2092 dos_format(rname);
2094 /* null size so do_put knows to ignore it */
2095 finfo.size = -1;
2097 /* set the date on the file */
2098 finfo.mtime = st.st_mtime;
2100 do_put(rname,lname,&finfo);
2102 fclose(f);
2103 unlink(tmpname);
2107 /****************************************************************************
2108 cancel a print job
2109 ****************************************************************************/
2110 static void do_cancel(int job)
2112 char *rparam = NULL;
2113 char *rdata = NULL;
2114 char *p;
2115 int rdrcnt,rprcnt;
2116 pstring param;
2118 bzero(param,sizeof(param));
2120 p = param;
2121 SSVAL(p,0,81); /* DosPrintJobDel() */
2122 p += 2;
2123 strcpy(p,"W");
2124 p = skip_string(p,1);
2125 strcpy(p,"");
2126 p = skip_string(p,1);
2127 SSVAL(p,0,job);
2128 p += 2;
2130 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2131 6, 1000,
2132 &rprcnt,&rdrcnt,
2133 param,NULL, NULL,
2134 &rparam,&rdata))
2136 int res = SVAL(rparam,0);
2138 if (!res)
2139 printf("Job %d cancelled\n",job);
2140 else
2141 printf("Error %d calcelling job %d\n",res,job);
2142 return;
2144 else
2145 printf("Server refused cancel request\n");
2147 if (rparam) free(rparam);
2148 if (rdata) free(rdata);
2150 return;
2154 /****************************************************************************
2155 cancel a print job
2156 ****************************************************************************/
2157 static void cmd_cancel(char *inbuf,char *outbuf )
2159 fstring buf;
2160 int job;
2162 if (!connect_as_printer)
2164 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2165 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2168 if (!next_token(NULL,buf,NULL)) {
2169 printf("cancel <jobid> ...\n");
2170 return;
2172 do {
2173 job = atoi(buf);
2174 do_cancel(job);
2175 } while (next_token(NULL,buf,NULL));
2181 /****************************************************************************
2182 print a file
2183 ****************************************************************************/
2184 static void cmd_print(char *inbuf,char *outbuf )
2186 int fnum;
2187 FILE *f = NULL;
2188 uint32 nread=0;
2189 pstring lname;
2190 pstring rname;
2191 char *p;
2193 if (!connect_as_printer)
2195 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2196 DEBUG(0,("Trying to print without -P may fail\n"));
2199 if (!next_token(NULL,lname,NULL))
2201 DEBUG(0,("print <filename>\n"));
2202 return;
2205 strcpy(rname,lname);
2206 p = strrchr(rname,'/');
2207 if (p)
2209 pstring tname;
2210 strcpy(tname,p+1);
2211 strcpy(rname,tname);
2214 if ((int)strlen(rname) > 14)
2215 rname[14] = 0;
2217 if (strequal(lname,"-"))
2219 f = stdin;
2220 strcpy(rname,"stdin");
2223 dos_clean_name(rname);
2225 bzero(outbuf,smb_size);
2226 set_message(outbuf,2,2 + strlen(rname),True);
2228 CVAL(outbuf,smb_com) = SMBsplopen;
2229 SSVAL(outbuf,smb_tid,cnum);
2230 cli_setup_pkt(outbuf);
2232 SSVAL(outbuf,smb_vwv0,0);
2233 SSVAL(outbuf,smb_vwv1,printmode);
2235 p = smb_buf(outbuf);
2236 *p++ = 4;
2237 strcpy(p,rname);
2239 send_smb(Client,outbuf);
2240 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2242 if (CVAL(inbuf,smb_rcls) != 0)
2244 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2245 return;
2248 if (!f)
2249 f = fopen(lname,"r");
2250 if (!f)
2252 DEBUG(0,("Error opening local file %s\n",lname));
2253 return;
2257 fnum = SVAL(inbuf,smb_vwv0);
2259 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2261 while (!feof(f))
2263 int n;
2265 bzero(outbuf,smb_size);
2266 set_message(outbuf,1,3,True);
2268 /* for some strange reason the OS/2 print server can't handle large
2269 packets when printing. weird */
2270 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2272 if (translation)
2273 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2274 else
2275 n = readfile(smb_buf(outbuf)+3,1,n,f);
2276 if (n <= 0)
2278 DEBUG(0,("read gave %d\n",n));
2279 break;
2282 smb_setlen(outbuf,smb_len(outbuf) + n);
2284 CVAL(outbuf,smb_com) = SMBsplwr;
2285 SSVAL(outbuf,smb_tid,cnum);
2286 cli_setup_pkt(outbuf);
2288 SSVAL(outbuf,smb_vwv0,fnum);
2289 SSVAL(outbuf,smb_vwv1,n+3);
2290 CVAL(smb_buf(outbuf),0) = 1;
2291 SSVAL(smb_buf(outbuf),1,n);
2293 send_smb(Client,outbuf);
2294 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2296 if (CVAL(inbuf,smb_rcls) != 0)
2298 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2299 break;
2302 nread += n;
2305 DEBUG(2,("%d bytes printed\n",nread));
2307 bzero(outbuf,smb_size);
2308 set_message(outbuf,1,0,True);
2309 CVAL(outbuf,smb_com) = SMBsplclose;
2310 SSVAL(outbuf,smb_tid,cnum);
2311 cli_setup_pkt(outbuf);
2313 SSVAL(outbuf,smb_vwv0,fnum);
2315 send_smb(Client,outbuf);
2316 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2318 if (CVAL(inbuf,smb_rcls) != 0)
2320 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2321 if (f != stdin)
2322 fclose(f);
2323 return;
2326 if (f != stdin)
2327 fclose(f);
2330 /****************************************************************************
2331 show a print queue - this is deprecated as it uses the old smb that
2332 has limited support - the correct call is the cmd_p_queue_4() after this.
2333 ****************************************************************************/
2334 static void cmd_queue(char *inbuf,char *outbuf )
2336 int count;
2337 char *p;
2339 bzero(outbuf,smb_size);
2340 set_message(outbuf,2,0,True);
2342 CVAL(outbuf,smb_com) = SMBsplretq;
2343 SSVAL(outbuf,smb_tid,cnum);
2344 cli_setup_pkt(outbuf);
2346 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2347 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2349 send_smb(Client,outbuf);
2350 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2352 if (CVAL(inbuf,smb_rcls) != 0)
2354 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2355 return;
2358 count = SVAL(inbuf,smb_vwv0);
2359 p = smb_buf(inbuf) + 3;
2360 if (count <= 0)
2362 DEBUG(0,("No entries in the print queue\n"));
2363 return;
2367 char status[20];
2369 DEBUG(0,("Job Name Size Status\n"));
2371 while (count--)
2373 switch (CVAL(p,4))
2375 case 0x01: sprintf(status,"held or stopped"); break;
2376 case 0x02: sprintf(status,"printing"); break;
2377 case 0x03: sprintf(status,"awaiting print"); break;
2378 case 0x04: sprintf(status,"in intercept"); break;
2379 case 0x05: sprintf(status,"file had error"); break;
2380 case 0x06: sprintf(status,"printer error"); break;
2381 default: sprintf(status,"unknown"); break;
2384 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2385 SVAL(p,5),p+12,IVAL(p,7),status));
2386 p += 28;
2393 /****************************************************************************
2394 show information about a print queue
2395 ****************************************************************************/
2396 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2398 char *rparam = NULL;
2399 char *rdata = NULL;
2400 char *p;
2401 int rdrcnt, rprcnt;
2402 pstring param;
2403 int result_code=0;
2405 if (!connect_as_printer)
2407 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2408 DEBUG(0,("Trying to print without -P may fail\n"));
2411 bzero(param,sizeof(param));
2413 p = param;
2414 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2415 p += 2;
2416 strcpy(p,"zWrLeh"); /* parameter description? */
2417 p = skip_string(p,1);
2418 strcpy(p,"WWzWWDDzz"); /* returned data format */
2419 p = skip_string(p,1);
2420 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2421 p = skip_string(p,1);
2422 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2423 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2424 p += 4;
2425 strcpy(p,""); /* subformat */
2426 p = skip_string(p,1);
2428 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2429 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2430 10, 4096,
2431 &rprcnt, &rdrcnt,
2432 param, NULL, NULL,
2433 &rparam, &rdata) )
2435 int converter;
2436 result_code = SVAL(rparam,0);
2437 converter = SVAL(rparam,2); /* conversion factor */
2439 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2441 if (result_code == 0) /* if no error, */
2443 int i;
2444 uint16 JobId;
2445 uint16 Priority;
2446 uint32 Size;
2447 char *UserName;
2448 char *JobName;
2449 char *JobTimeStr;
2450 time_t JobTime;
2451 char PrinterName[20];
2453 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2454 strlower(PrinterName); /* in lower case */
2456 p = rdata; /* received data */
2457 for( i = 0; i < SVAL(rparam,4); ++i)
2459 JobId = SVAL(p,0);
2460 Priority = SVAL(p,2);
2461 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2462 strlower(UserName);
2463 Priority = SVAL(p,2);
2464 JobTime = make_unix_date3( p + 12);
2465 JobTimeStr = asctime(LocalTime( &JobTime));
2466 Size = IVAL(p,16);
2467 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2470 printf("%s-%u %s priority %u %s %s %u bytes\n",
2471 PrinterName, JobId, UserName,
2472 Priority, JobTimeStr, JobName, Size);
2474 #if 0 /* DEBUG code */
2475 printf("Job Id: \"%u\"\n", SVAL(p,0));
2476 printf("Priority: \"%u\"\n", SVAL(p,2));
2478 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2479 printf("Position: \"%u\"\n", SVAL(p,8));
2480 printf("Status: \"%u\"\n", SVAL(p,10));
2482 JobTime = make_unix_date3( p + 12);
2483 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2484 printf("date: \"%u\"\n", SVAL(p,12));
2486 printf("Size: \"%u\"\n", SVAL(p,16));
2487 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2488 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2489 #endif /* DEBUG CODE */
2490 p += 28;
2494 else /* cli_call_api() failed */
2496 printf("Failed, error = %d\n", result_code);
2499 /* If any parameters or data were returned, free the storage. */
2500 if(rparam) free(rparam);
2501 if(rdata) free(rdata);
2503 return;
2506 /****************************************************************************
2507 show information about a print queue
2508 ****************************************************************************/
2509 static void cmd_qinfo(char *inbuf,char *outbuf )
2511 char *rparam = NULL;
2512 char *rdata = NULL;
2513 char *p;
2514 int rdrcnt, rprcnt;
2515 pstring param;
2516 int result_code=0;
2518 bzero(param,sizeof(param));
2520 p = param;
2521 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2522 p += 2;
2523 strcpy(p,"zWrLh"); /* parameter description? */
2524 p = skip_string(p,1);
2525 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2526 p = skip_string(p,1);
2527 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2528 p = skip_string(p,1);
2529 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2530 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2531 p += 4;
2532 strcpy(p,""); /* subformat */
2533 p = skip_string(p,1);
2535 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2536 if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
2537 10, 4096,
2538 &rprcnt, &rdrcnt,
2539 param, NULL, NULL,
2540 &rparam, &rdata) )
2542 int converter;
2543 result_code = SVAL(rparam,0);
2544 converter = SVAL(rparam,2); /* conversion factor */
2546 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2548 if (result_code == 0) /* if no error, */
2550 p = rdata; /* received data */
2552 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2553 printf("Priority: %u\n", SVAL(p,4) );
2554 printf("Start time: %u\n", SVAL(p,6) );
2555 printf("Until time: %u\n", SVAL(p,8) );
2556 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2557 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2558 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2559 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2560 printf("Status: %u\n", SVAL(p,28) );
2561 printf("Jobs: %u\n", SVAL(p,30) );
2562 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2563 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2565 /* Dump the driver data */
2567 int count, x, y, c;
2568 char *ddptr;
2570 ddptr = rdata + SVAL(p,40) - converter;
2571 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2572 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2574 for(x=8; x < count; x+=16)
2576 for(y=0; y < 16; y++)
2578 if( (x+y) < count )
2579 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2580 else
2581 fputs(" ", stdout);
2583 for(y=0; y < 16 && (x+y) < count; y++)
2585 c = CVAL(ddptr,(x+y));
2586 if(isprint(c))
2587 fputc(c, stdout);
2588 else
2589 fputc('.', stdout);
2591 fputc('\n', stdout);
2597 else /* cli_call_api() failed */
2599 printf("Failed, error = %d\n", result_code);
2602 /* If any parameters or data were returned, free the storage. */
2603 if(rparam) free(rparam);
2604 if(rdata) free(rdata);
2606 return;
2609 /****************************************************************************
2610 delete some files
2611 ****************************************************************************/
2612 static void do_del(file_info *finfo)
2614 char *p;
2615 char *inbuf,*outbuf;
2616 pstring mask;
2618 strcpy(mask,cur_dir);
2619 strcat(mask,finfo->name);
2621 if (finfo->mode & aDIR)
2622 return;
2624 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2625 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2627 if (!inbuf || !outbuf)
2629 DEBUG(0,("out of memory\n"));
2630 return;
2633 bzero(outbuf,smb_size);
2634 set_message(outbuf,1,2 + strlen(mask),True);
2636 CVAL(outbuf,smb_com) = SMBunlink;
2637 SSVAL(outbuf,smb_tid,cnum);
2638 cli_setup_pkt(outbuf);
2640 SSVAL(outbuf,smb_vwv0,0);
2642 p = smb_buf(outbuf);
2643 *p++ = 4;
2644 strcpy(p,mask);
2646 send_smb(Client,outbuf);
2647 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2649 if (CVAL(inbuf,smb_rcls) != 0)
2650 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2652 free(inbuf);free(outbuf);
2656 /****************************************************************************
2657 delete some files
2658 ****************************************************************************/
2659 static void cmd_del(char *inbuf,char *outbuf )
2661 pstring mask;
2662 fstring buf;
2663 int attribute = aSYSTEM | aHIDDEN;
2665 if (recurse)
2666 attribute |= aDIR;
2668 strcpy(mask,cur_dir);
2670 if (!next_token(NULL,buf,NULL))
2672 DEBUG(0,("del <filename>\n"));
2673 return;
2675 strcat(mask,buf);
2677 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2681 /****************************************************************************
2682 remove a directory
2683 ****************************************************************************/
2684 static void cmd_rmdir(char *inbuf,char *outbuf )
2686 pstring mask;
2687 fstring buf;
2688 char *p;
2690 strcpy(mask,cur_dir);
2692 if (!next_token(NULL,buf,NULL))
2694 DEBUG(0,("rmdir <dirname>\n"));
2695 return;
2697 strcat(mask,buf);
2699 bzero(outbuf,smb_size);
2700 set_message(outbuf,0,2 + strlen(mask),True);
2702 CVAL(outbuf,smb_com) = SMBrmdir;
2703 SSVAL(outbuf,smb_tid,cnum);
2704 cli_setup_pkt(outbuf);
2707 p = smb_buf(outbuf);
2708 *p++ = 4;
2709 strcpy(p,mask);
2711 send_smb(Client,outbuf);
2712 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2714 if (CVAL(inbuf,smb_rcls) != 0)
2716 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2717 return;
2722 /****************************************************************************
2723 rename some files
2724 ****************************************************************************/
2725 static void cmd_rename(char *inbuf,char *outbuf )
2727 pstring src,dest;
2728 fstring buf,buf2;
2729 char *p;
2731 strcpy(src,cur_dir);
2732 strcpy(dest,cur_dir);
2734 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2736 DEBUG(0,("rename <src> <dest>\n"));
2737 return;
2739 strcat(src,buf);
2740 strcat(dest,buf2);
2742 bzero(outbuf,smb_size);
2743 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2745 CVAL(outbuf,smb_com) = SMBmv;
2746 SSVAL(outbuf,smb_tid,cnum);
2747 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2748 cli_setup_pkt(outbuf);
2750 p = smb_buf(outbuf);
2751 *p++ = 4;
2752 strcpy(p,src);
2753 p = skip_string(p,1);
2754 *p++ = 4;
2755 strcpy(p,dest);
2757 send_smb(Client,outbuf);
2758 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2760 if (CVAL(inbuf,smb_rcls) != 0)
2762 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2763 return;
2769 /****************************************************************************
2770 toggle the prompt flag
2771 ****************************************************************************/
2772 static void cmd_prompt(void)
2774 prompt = !prompt;
2775 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2779 /****************************************************************************
2780 set the newer than time
2781 ****************************************************************************/
2782 static void cmd_newer(void)
2784 fstring buf;
2785 BOOL ok;
2786 struct stat sbuf;
2788 ok = next_token(NULL,buf,NULL);
2789 if (ok && (sys_stat(buf,&sbuf) == 0))
2791 newer_than = sbuf.st_mtime;
2792 DEBUG(1,("Getting files newer than %s",
2793 asctime(LocalTime(&newer_than))));
2795 else
2796 newer_than = 0;
2798 if (ok && newer_than == 0)
2799 DEBUG(0,("Error setting newer-than time\n"));
2802 /****************************************************************************
2803 set the archive level
2804 ****************************************************************************/
2805 static void cmd_archive(void)
2807 fstring buf;
2809 if (next_token(NULL,buf,NULL)) {
2810 archive_level = atoi(buf);
2811 } else
2812 DEBUG(0,("Archive level is %d\n",archive_level));
2815 /****************************************************************************
2816 toggle the lowercaseflag
2817 ****************************************************************************/
2818 static void cmd_lowercase(void)
2820 lowercase = !lowercase;
2821 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2827 /****************************************************************************
2828 toggle the recurse flag
2829 ****************************************************************************/
2830 static void cmd_recurse(void)
2832 recurse = !recurse;
2833 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2836 /****************************************************************************
2837 toggle the translate flag
2838 ****************************************************************************/
2839 static void cmd_translate(void)
2841 translation = !translation;
2842 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2843 translation?"on":"off"));
2847 /****************************************************************************
2848 do a printmode command
2849 ****************************************************************************/
2850 static void cmd_printmode(void)
2852 fstring buf;
2853 fstring mode;
2855 if (next_token(NULL,buf,NULL))
2857 if (strequal(buf,"text"))
2858 printmode = 0;
2859 else
2861 if (strequal(buf,"graphics"))
2862 printmode = 1;
2863 else
2864 printmode = atoi(buf);
2868 switch(printmode)
2870 case 0:
2871 strcpy(mode,"text");
2872 break;
2873 case 1:
2874 strcpy(mode,"graphics");
2875 break;
2876 default:
2877 sprintf(mode,"%d",printmode);
2878 break;
2881 DEBUG(2,("the printmode is now %s\n",mode));
2884 /****************************************************************************
2885 do the lcd command
2886 ****************************************************************************/
2887 static void cmd_lcd(void)
2889 fstring buf;
2890 pstring d;
2892 if (next_token(NULL,buf,NULL))
2893 sys_chdir(buf);
2894 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2898 /****************************************************************************
2899 try and browse available connections on a host
2900 ****************************************************************************/
2901 static BOOL browse_host(BOOL sort)
2903 #ifdef NOSTRCASECMP
2904 /* If strcasecmp is already defined, remove it. */
2905 #ifdef strcasecmp
2906 #undef strcasecmp
2907 #endif /* strcasecmp */
2908 #define strcasecmp StrCaseCmp
2909 #endif /* NOSTRCASECMP */
2911 extern int strcasecmp();
2913 char *rparam = NULL;
2914 char *rdata = NULL;
2915 char *p;
2916 int rdrcnt,rprcnt;
2917 pstring param;
2918 int count = -1;
2920 /* now send a SMBtrans command with api RNetShareEnum */
2921 p = param;
2922 SSVAL(p,0,0); /* api number */
2923 p += 2;
2924 strcpy(p,"WrLeh");
2925 p = skip_string(p,1);
2926 strcpy(p,"B13BWz");
2927 p = skip_string(p,1);
2928 SSVAL(p,0,1);
2929 SSVAL(p,2,BUFFER_SIZE);
2930 p += 4;
2932 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
2933 1024, BUFFER_SIZE,
2934 &rprcnt,&rdrcnt,
2935 param,NULL, NULL,
2936 &rparam,&rdata))
2938 int res = SVAL(rparam,0);
2939 int converter=SVAL(rparam,2);
2940 int i;
2941 BOOL long_share_name=False;
2943 if (res == 0)
2945 count=SVAL(rparam,4);
2946 p = rdata;
2948 if (count > 0)
2950 printf("\n\tSharename Type Comment\n");
2951 printf("\t--------- ---- -------\n");
2954 if (sort)
2955 qsort(p,count,20,QSORT_CAST strcasecmp);
2957 for (i=0;i<count;i++)
2959 char *sname = p;
2960 int type = SVAL(p,14);
2961 int comment_offset = IVAL(p,16) & 0xFFFF;
2962 fstring typestr;
2963 *typestr=0;
2965 switch (type)
2967 case STYPE_DISKTREE:
2968 strcpy(typestr,"Disk"); break;
2969 case STYPE_PRINTQ:
2970 strcpy(typestr,"Printer"); break;
2971 case STYPE_DEVICE:
2972 strcpy(typestr,"Device"); break;
2973 case STYPE_IPC:
2974 strcpy(typestr,"IPC"); break;
2977 printf("\t%-15.15s%-10.10s%s\n",
2978 sname,
2979 typestr,
2980 comment_offset?rdata+comment_offset-converter:"");
2982 if (strlen(sname)>8) long_share_name=True;
2984 p += 20;
2987 if (long_share_name) {
2988 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
2993 if (rparam) free(rparam);
2994 if (rdata) free(rdata);
2996 return(count>0);
3000 /****************************************************************************
3001 get some server info
3002 ****************************************************************************/
3003 static void server_info()
3005 char *rparam = NULL;
3006 char *rdata = NULL;
3007 char *p;
3008 int rdrcnt,rprcnt;
3009 pstring param;
3011 bzero(param,sizeof(param));
3013 p = param;
3014 SSVAL(p,0,63); /* NetServerGetInfo()? */
3015 p += 2;
3016 strcpy(p,"WrLh");
3017 p = skip_string(p,1);
3018 strcpy(p,"zzzBBzz");
3019 p = skip_string(p,1);
3020 SSVAL(p,0,10); /* level 10 */
3021 SSVAL(p,2,1000);
3022 p += 6;
3024 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
3025 6, 1000,
3026 &rprcnt,&rdrcnt,
3027 param,NULL, NULL,
3028 &rparam,&rdata))
3030 int res = SVAL(rparam,0);
3031 int converter=SVAL(rparam,2);
3033 if (res == 0)
3035 p = rdata;
3037 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3038 rdata+SVAL(p,0)-converter,
3039 rdata+SVAL(p,4)-converter,
3040 rdata+SVAL(p,8)-converter,
3041 rdata+SVAL(p,14)-converter);
3045 if (rparam) free(rparam);
3046 if (rdata) free(rdata);
3048 return;
3052 /****************************************************************************
3053 try and browse available connections on a host
3054 ****************************************************************************/
3055 static BOOL list_servers(char *wk_grp)
3057 char *rparam = NULL;
3058 char *rdata = NULL;
3059 int rdrcnt,rprcnt;
3060 char *p,*svtype_p;
3061 pstring param;
3062 int uLevel = 1;
3063 int count = 0;
3064 BOOL ok = False;
3065 BOOL generic_request = False;
3068 if (strequal(wk_grp,"WORKGROUP")) {
3069 /* we won't specify a workgroup */
3070 generic_request = True;
3073 /* now send a SMBtrans command with api ServerEnum? */
3074 p = param;
3075 SSVAL(p,0,0x68); /* api number */
3076 p += 2;
3078 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3079 p = skip_string(p,1);
3081 strcpy(p,"B16BBDz");
3083 p = skip_string(p,1);
3084 SSVAL(p,0,uLevel);
3085 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3086 p += 4;
3088 svtype_p = p;
3089 p += 4;
3091 if (!generic_request) {
3092 strcpy(p, wk_grp);
3093 p = skip_string(p,1);
3096 /* first ask for a list of servers in this workgroup */
3097 SIVAL(svtype_p,0,SV_TYPE_ALL);
3099 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3100 8, BUFFER_SIZE - SAFETY_MARGIN,
3101 &rprcnt,&rdrcnt,
3102 param,NULL, NULL,
3103 &rparam,&rdata))
3105 int res = SVAL(rparam,0);
3106 int converter=SVAL(rparam,2);
3107 int i;
3109 if (res == 0) {
3110 char *p2 = rdata;
3111 count=SVAL(rparam,4);
3113 if (count > 0) {
3114 printf("\n\nThis machine has a browse list:\n");
3115 printf("\n\tServer Comment\n");
3116 printf("\t--------- -------\n");
3119 for (i=0;i<count;i++) {
3120 char *sname = p2;
3121 int comment_offset = IVAL(p2,22) & 0xFFFF;
3122 printf("\t%-16.16s %s\n",
3123 sname,
3124 comment_offset?rdata+comment_offset-converter:"");
3126 ok=True;
3127 p2 += 26;
3132 if (rparam) {free(rparam); rparam = NULL;}
3133 if (rdata) {free(rdata); rdata = NULL;}
3135 /* now ask for a list of workgroups */
3136 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3138 if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
3139 8, BUFFER_SIZE - SAFETY_MARGIN,
3140 &rprcnt,&rdrcnt,
3141 param,NULL, NULL,
3142 &rparam,&rdata))
3144 int res = SVAL(rparam,0);
3145 int converter=SVAL(rparam,2);
3146 int i;
3148 if (res == 0) {
3149 char *p2 = rdata;
3150 count=SVAL(rparam,4);
3152 if (count > 0) {
3153 printf("\n\nThis machine has a workgroup list:\n");
3154 printf("\n\tWorkgroup Master\n");
3155 printf("\t--------- -------\n");
3158 for (i=0;i<count;i++) {
3159 char *sname = p2;
3160 int comment_offset = IVAL(p2,22) & 0xFFFF;
3161 printf("\t%-16.16s %s\n",
3162 sname,
3163 comment_offset?rdata+comment_offset-converter:"");
3165 ok=True;
3166 p2 += 26;
3171 if (rparam) free(rparam);
3172 if (rdata) free(rdata);
3174 return(ok);
3178 /* This defines the commands supported by this client */
3179 struct
3181 char *name;
3182 void (*fn)();
3183 char *description;
3184 } commands[] =
3186 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3187 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3188 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3189 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3190 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3191 {"get",cmd_get,"<remote name> [local name] get a file"},
3192 {"mget",cmd_mget,"<mask> get all the matching files"},
3193 {"put",cmd_put,"<local name> [remote name] put a file"},
3194 {"mput",cmd_mput,"<mask> put all matching files"},
3195 {"rename",cmd_rename,"<src> <dest> rename some files"},
3196 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3197 {"mask",cmd_select,"<mask> mask all filenames against this"},
3198 {"del",cmd_del,"<mask> delete all matching files"},
3199 {"rm",cmd_del,"<mask> delete all matching files"},
3200 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3201 {"md",cmd_mkdir,"<directory> make a directory"},
3202 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
3203 {"rd",cmd_rmdir,"<directory> remove a directory"},
3204 {"pq",cmd_p_queue_4,"enumerate the print queue"},
3205 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
3206 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
3207 {"translate",cmd_translate,"toggle text translation for printing"},
3208 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
3209 {"print",cmd_print,"<file name> print a file"},
3210 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
3211 {"queue",cmd_queue,"show the print queue"},
3212 {"qinfo",cmd_qinfo,"show print queue information"},
3213 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
3214 {"quit",cli_send_logout,"logoff the server"},
3215 {"q",cli_send_logout,"logoff the server"},
3216 {"exit",cli_send_logout,"logoff the server"},
3217 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
3218 {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit"},
3219 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3220 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
3221 {"tarmode",cmd_tarmode,
3222 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3223 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
3224 {"help",cmd_help,"[command] give help on a command"},
3225 {"?",cmd_help,"[command] give help on a command"},
3226 {"!",NULL,"run a shell command on the local system"},
3227 {"",NULL,NULL}
3231 /*******************************************************************
3232 lookup a command string in the list of commands, including
3233 abbreviations
3234 ******************************************************************/
3235 static int process_tok(fstring tok)
3237 int i = 0, matches = 0;
3238 int cmd=0;
3239 int tok_len = strlen(tok);
3241 while (commands[i].fn != NULL)
3243 if (strequal(commands[i].name,tok))
3245 matches = 1;
3246 cmd = i;
3247 break;
3249 else if (strnequal(commands[i].name, tok, tok_len))
3251 matches++;
3252 cmd = i;
3254 i++;
3257 if (matches == 0)
3258 return(-1);
3259 else if (matches == 1)
3260 return(cmd);
3261 else
3262 return(-2);
3265 /****************************************************************************
3266 help
3267 ****************************************************************************/
3268 void cmd_help(void)
3270 int i=0,j;
3271 fstring buf;
3273 if (next_token(NULL,buf,NULL))
3275 if ((i = process_tok(buf)) >= 0)
3276 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3278 else
3279 while (commands[i].description)
3281 for (j=0; commands[i].description && (j<5); j++) {
3282 DEBUG(0,("%-15s",commands[i].name));
3283 i++;
3285 DEBUG(0,("\n"));
3289 /****************************************************************************
3290 wait for keyboard activity, swallowing network packets
3291 ****************************************************************************/
3292 #ifdef CLIX
3293 static char wait_keyboard(char *buffer)
3294 #else
3295 static void wait_keyboard(char *buffer)
3296 #endif
3298 fd_set fds;
3299 int selrtn;
3300 struct timeval timeout;
3302 #ifdef CLIX
3303 int delay = 0;
3304 #endif
3306 while (1)
3308 extern int Client;
3309 FD_ZERO(&fds);
3310 FD_SET(Client,&fds);
3311 #ifndef CLIX
3312 FD_SET(fileno(stdin),&fds);
3313 #endif
3315 timeout.tv_sec = 20;
3316 timeout.tv_usec = 0;
3317 #ifdef CLIX
3318 timeout.tv_sec = 0;
3319 #endif
3320 selrtn = sys_select(&fds,&timeout);
3322 #ifndef CLIX
3323 if (FD_ISSET(fileno(stdin),&fds))
3324 return;
3325 #else
3327 char ch;
3328 int readret;
3330 set_blocking(fileno(stdin), False);
3331 readret = read_data( fileno(stdin), &ch, 1);
3332 set_blocking(fileno(stdin), True);
3333 if (readret == -1)
3335 if (errno != EAGAIN)
3337 /* should crash here */
3338 DEBUG(1,("readchar stdin failed\n"));
3341 else if (readret != 0)
3343 return ch;
3346 #endif
3348 /* We deliberately use receive_smb instead of
3349 client_receive_smb as we want to receive
3350 session keepalives and then drop them here.
3352 if (FD_ISSET(Client,&fds))
3353 receive_smb(Client,buffer,0);
3355 #ifdef CLIX
3356 delay++;
3357 if (delay > 100000)
3359 delay = 0;
3360 chkpath("\\",False);
3362 #else
3363 chkpath("\\",False);
3364 #endif
3369 /****************************************************************************
3370 process commands from the client
3371 ****************************************************************************/
3372 static BOOL process(char *base_directory)
3374 extern FILE *dbf;
3375 pstring line;
3376 char *cmd;
3378 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3379 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3381 if ((InBuffer == NULL) || (OutBuffer == NULL))
3382 return(False);
3384 bzero(OutBuffer,smb_size);
3386 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3387 return(False);
3389 if (*base_directory) do_cd(base_directory);
3391 cmd = cmdstr;
3392 if (cmd[0] != '\0') while (cmd[0] != '\0')
3394 char *p;
3395 fstring tok;
3396 int i;
3398 if ((p = strchr(cmd, ';')) == 0)
3400 strncpy(line, cmd, 999);
3401 line[1000] = '\0';
3402 cmd += strlen(cmd);
3404 else
3406 if (p - cmd > 999) p = cmd + 999;
3407 strncpy(line, cmd, p - cmd);
3408 line[p - cmd] = '\0';
3409 cmd = p + 1;
3412 /* input language code to internal one */
3413 CNV_INPUT (line);
3415 /* and get the first part of the command */
3417 char *ptr = line;
3418 if (!next_token(&ptr,tok,NULL)) continue;
3421 if ((i = process_tok(tok)) >= 0)
3422 commands[i].fn(InBuffer,OutBuffer);
3423 else if (i == -2)
3424 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3425 else
3426 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3428 else while (!feof(stdin))
3430 fstring tok;
3431 int i;
3433 bzero(OutBuffer,smb_size);
3435 /* display a prompt */
3436 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3437 fflush(dbf);
3439 #ifdef CLIX
3440 line[0] = wait_keyboard(InBuffer);
3441 /* this might not be such a good idea... */
3442 if ( line[0] == EOF)
3443 break;
3444 #else
3445 wait_keyboard(InBuffer);
3446 #endif
3448 /* and get a response */
3449 #ifdef CLIX
3450 fgets( &line[1],999, stdin);
3451 #else
3452 if (!fgets(line,1000,stdin))
3453 break;
3454 #endif
3456 /* input language code to internal one */
3457 CNV_INPUT (line);
3459 /* special case - first char is ! */
3460 if (*line == '!')
3462 system(line + 1);
3463 continue;
3466 /* and get the first part of the command */
3468 char *ptr = line;
3469 if (!next_token(&ptr,tok,NULL)) continue;
3472 if ((i = process_tok(tok)) >= 0)
3473 commands[i].fn(InBuffer,OutBuffer);
3474 else if (i == -2)
3475 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3476 else
3477 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3480 cli_send_logout();
3481 return(True);
3484 /****************************************************************************
3485 usage on the program
3486 ****************************************************************************/
3487 static void usage(char *pname)
3489 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3490 pname));
3492 DEBUG(0,("\nVersion %s\n",VERSION));
3493 DEBUG(0,("\t-p port connect to the specified port\n"));
3494 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3495 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3496 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3497 DEBUG(0,("\t-N don't ask for a password\n"));
3498 DEBUG(0,("\t-P connect to service as a printer\n"));
3499 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3500 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3501 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3502 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3503 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3504 DEBUG(0,("\t-U username set the network username\n"));
3505 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3506 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3507 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3508 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
3509 DEBUG(0,("\t-D directory start from directory\n"));
3510 DEBUG(0,("\n"));
3513 /****************************************************************************
3514 main program
3515 ****************************************************************************/
3516 int main(int argc,char *argv[])
3518 fstring base_directory;
3519 char *pname = argv[0];
3520 int port = SMB_PORT;
3521 int opt;
3522 extern FILE *dbf;
3523 extern char *optarg;
3524 extern int optind;
3525 pstring query_host;
3526 BOOL message = False;
3527 BOOL nt_domain_logon = False;
3528 extern char tar_type;
3529 static pstring servicesf = CONFIGFILE;
3530 pstring term_code;
3531 char *p;
3533 #ifdef KANJI
3534 strcpy(term_code, KANJI);
3535 #else /* KANJI */
3536 *term_code = 0;
3537 #endif /* KANJI */
3539 *query_host = 0;
3540 *base_directory = 0;
3542 DEBUGLEVEL = 2;
3544 setup_logging(pname,True);
3546 TimeInit();
3547 charset_initialise();
3549 pid = getpid();
3550 uid = getuid();
3551 gid = getgid();
3552 mid = pid + 100;
3553 myumask = umask(0);
3554 umask(myumask);
3556 if (getenv("USER"))
3558 strcpy(username,getenv("USER"));
3560 /* modification to support userid%passwd syntax in the USER var
3561 25.Aug.97, jdblair@uab.edu */
3563 if ((p=strchr(username,'%')))
3565 *p = 0;
3566 strcpy(password,p+1);
3567 got_pass = True;
3568 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3570 strupper(username);
3573 /* modification to support PASSWD environmental var
3574 25.Aug.97, jdblair@uab.edu */
3576 if (getenv("PASSWD"))
3577 strcpy(password,getenv("PASSWD"));
3579 if (*username == 0 && getenv("LOGNAME"))
3581 strcpy(username,getenv("LOGNAME"));
3582 strupper(username);
3585 if (argc < 2)
3587 usage(pname);
3588 exit(1);
3591 if (*argv[1] != '-')
3594 strcpy(service,argv[1]);
3595 /* Convert any '/' characters in the service name to '\' characters */
3596 string_replace( service, '/','\\');
3597 argc--;
3598 argv++;
3600 if (count_chars(service,'\\') < 3)
3602 usage(pname);
3603 printf("\n%s: Not enough '\\' characters in service\n",service);
3604 exit(1);
3608 if (count_chars(service,'\\') > 3)
3610 usage(pname);
3611 printf("\n%s: Too many '\\' characters in service\n",service);
3612 exit(1);
3616 if (argc > 1 && (*argv[1] != '-'))
3618 got_pass = True;
3619 strcpy(password,argv[1]);
3620 memset(argv[1],'X',strlen(argv[1]));
3621 argc--;
3622 argv++;
3626 while ((opt =
3627 getopt(argc, argv,"s:B:O:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
3628 switch (opt)
3630 case 'm':
3631 max_protocol = interpret_protocol(optarg,max_protocol);
3632 break;
3633 case 'O':
3634 strcpy(user_socket_options,optarg);
3635 break;
3636 case 'S':
3637 strcpy(desthost,optarg);
3638 strupper(desthost);
3639 nt_domain_logon = True;
3640 break;
3641 case 'M':
3642 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3643 strcpy(desthost,optarg);
3644 strupper(desthost);
3645 message = True;
3646 break;
3647 case 'B':
3648 iface_set_default(NULL,optarg,NULL);
3649 break;
3650 case 'D':
3651 strcpy(base_directory,optarg);
3652 break;
3653 case 'T':
3654 if (!tar_parseargs(argc, argv, optarg, optind)) {
3655 usage(pname);
3656 exit(1);
3658 break;
3659 case 'i':
3660 strcpy(scope,optarg);
3661 break;
3662 case 'L':
3663 got_pass = True;
3664 strcpy(query_host,optarg);
3665 break;
3666 case 'U':
3668 char *lp;
3669 strcpy(username,optarg);
3670 if ((lp=strchr(username,'%')))
3672 *lp = 0;
3673 strcpy(password,lp+1);
3674 got_pass = True;
3675 memset(strchr(optarg,'%')+1,'X',strlen(password));
3679 break;
3680 case 'W':
3681 strcpy(workgroup,optarg);
3682 break;
3683 case 'E':
3684 dbf = stderr;
3685 break;
3686 case 'I':
3688 dest_ip = *interpret_addr2(optarg);
3689 if (zero_ip(dest_ip)) exit(1);
3690 have_ip = True;
3692 break;
3693 case 'n':
3694 strcpy(myname,optarg);
3695 break;
3696 case 'N':
3697 got_pass = True;
3698 no_pass = True;
3699 break;
3700 case 'P':
3701 connect_as_printer = True;
3702 break;
3703 case 'd':
3704 if (*optarg == 'A')
3705 DEBUGLEVEL = 10000;
3706 else
3707 DEBUGLEVEL = atoi(optarg);
3708 break;
3709 case 'l':
3710 sprintf(debugf,"%s.client",optarg);
3711 break;
3712 case 'p':
3713 port = atoi(optarg);
3714 break;
3715 case 'c':
3716 cmdstr = optarg;
3717 got_pass = True;
3718 break;
3719 case 'h':
3720 usage(pname);
3721 exit(0);
3722 break;
3723 case 's':
3724 strcpy(servicesf, optarg);
3725 break;
3726 case 't':
3727 strcpy(term_code, optarg);
3728 break;
3729 default:
3730 usage(pname);
3731 exit(1);
3734 if (!tar_type && !*query_host && !*service && !message)
3736 usage(pname);
3737 exit(1);
3741 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
3743 if(!get_myname(myhostname,NULL))
3745 DEBUG(0,("Failed to get my hostname.\n"));
3748 if (!lp_load(servicesf,True,False,False)) {
3749 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3752 codepage_initialise(lp_client_code_page());
3754 interpret_coding_system(term_code);
3756 if (*workgroup == 0)
3757 strcpy(workgroup,lp_workgroup());
3759 load_interfaces();
3760 get_myname((*myname)?NULL:myname,NULL);
3761 strupper(myname);
3763 if (tar_type) {
3764 recurse=True;
3766 if (cli_open_sockets(port)) {
3767 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3768 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3769 int ret;
3771 if ((InBuffer == NULL) || (OutBuffer == NULL))
3772 return(1);
3774 bzero(OutBuffer,smb_size);
3775 if (!cli_send_login(InBuffer,OutBuffer,True,True,NULL))
3776 return(False);
3778 if (*base_directory) do_cd(base_directory);
3780 ret=process_tar(InBuffer, OutBuffer);
3782 cli_send_logout();
3783 close_sockets();
3784 return(ret);
3785 } else
3786 return(1);
3789 if (*query_host && !nt_domain_logon)
3791 int ret = 0;
3792 sprintf(service,"\\\\%s\\IPC$",query_host);
3793 strupper(service);
3794 connect_as_ipc = True;
3795 if (cli_open_sockets(port))
3797 #if 0
3798 *username = 0;
3799 #endif
3800 if (!cli_send_login(NULL,NULL,True,True,NULL))
3801 return(1);
3803 server_info();
3804 if (!browse_host(True)) {
3805 sleep(1);
3806 browse_host(True);
3808 if (!list_servers(workgroup)) {
3809 sleep(1);
3810 list_servers(workgroup);
3813 cli_send_logout();
3814 close_sockets();
3817 return(ret);
3820 if (message)
3822 int ret = 0;
3823 if (cli_open_sockets(port))
3825 pstring inbuf,outbuf;
3826 bzero(outbuf,smb_size);
3827 if (!cli_send_session_request(inbuf,outbuf))
3828 return(1);
3830 send_message(inbuf,outbuf);
3832 close_sockets();
3835 return(ret);
3838 #ifdef NTDOMAIN
3840 if (nt_domain_logon)
3842 int ret = 0;
3843 sprintf(service,"\\\\%s\\IPC$",query_host);
3844 strupper(service);
3845 connect_as_ipc = True;
3847 DEBUG(5,("NT Domain Logon. Service: %s\n", service));
3849 if (cli_open_sockets(port))
3851 if (!cli_send_login(NULL,NULL,True,True,NULL)) return(1);
3853 do_nt_login(desthost, myhostname, Client, cnum);
3855 cli_send_logout();
3856 close_sockets();
3859 return(ret);
3861 #endif
3863 if (cli_open_sockets(port))
3865 if (!process(base_directory))
3867 close_sockets();
3868 return(1);
3870 close_sockets();
3872 else
3873 return(1);
3875 return(0);