fix some casting errors in smbencrypt and some multiply-defined errors
[Samba.git] / source / client / client.c
blob6528919051dbf59791b0ee47e3c11e96e85fe11e
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB client
5 Copyright (C) Andrew Tridgell 1994-1997
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 connect_as_printer;
44 extern BOOL connect_as_ipc;
45 extern struct in_addr ipzero;
47 extern BOOL doencrypt;
49 extern pstring user_socket_options;
51 /* 30 second timeout on most commands */
52 #define CLIENT_TIMEOUT (30*1000)
53 #define SHORT_TIMEOUT (5*1000)
55 /* value for unused fid field in trans2 secondary request */
56 #define FID_UNUSED (0xFFFF)
58 extern int name_type;
60 extern int max_protocol;
63 time_t newer_than = 0;
64 int archive_level = 0;
66 extern pstring debugf;
67 extern int DEBUGLEVEL;
69 BOOL translation = False;
71 extern int cnum;
72 extern int mid;
73 extern int pid;
74 extern int tid;
75 extern int gid;
76 extern int uid;
78 extern BOOL have_ip;
79 extern int max_xmit;
81 static int interpret_long_filename(int level,char *p,file_info *finfo);
82 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir);
83 static int interpret_short_filename(char *p,file_info *finfo);
84 static BOOL do_this_one(file_info *finfo);
86 /* clitar bits insert */
87 extern int blocksize;
88 extern BOOL tar_inc;
89 extern BOOL tar_reset;
90 /* clitar bits end */
93 int myumask = 0755;
95 extern pstring scope;
97 BOOL prompt = True;
99 int printmode = 1;
101 BOOL recurse = False;
102 BOOL lowercase = False;
104 struct in_addr dest_ip;
106 #define SEPARATORS " \t\n\r"
108 BOOL abort_mget = True;
110 extern int Protocol;
112 extern BOOL readbraw_supported ;
113 extern BOOL writebraw_supported;
115 pstring fileselection = "";
117 extern file_info def_finfo;
119 /* timing globals */
120 int get_total_size = 0;
121 int get_total_time_ms = 0;
122 int put_total_size = 0;
123 int put_total_time_ms = 0;
125 /* totals globals */
126 int dir_total = 0;
128 extern int Client;
130 #define USENMB
132 extern int coding_system;
133 static BOOL setup_term_code (char *code)
135 int new;
136 new = interpret_coding_system (code, UNKNOWN_CODE);
137 if (new != UNKNOWN_CODE) {
138 coding_system = new;
139 return True;
141 return False;
143 #define CNV_LANG(s) dos2unix_format(s,False)
144 #define CNV_INPUT(s) unix2dos_format(s,True)
146 /****************************************************************************
147 send an SMBclose on an SMB file handle
148 ****************************************************************************/
149 void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
151 bzero(outbuf,smb_size);
152 set_message(outbuf,3,0,True);
154 CVAL (outbuf,smb_com) = SMBclose;
155 SSVAL(outbuf,smb_tid,c_num);
156 cli_setup_pkt(outbuf);
157 SSVAL (outbuf,smb_vwv0, f_num);
158 SIVALS(outbuf,smb_vwv1, -1);
160 send_smb(clnt_fd, outbuf);
161 receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
164 /****************************************************************************
165 write to a local file with CR/LF->LF translation if appropriate. return the
166 number taken from the buffer. This may not equal the number written.
167 ****************************************************************************/
168 static int writefile(int f, char *b, int n)
170 int i;
172 if (!translation)
173 return(write(f,b,n));
175 i = 0;
176 while (i < n)
178 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
180 b++;i++;
182 if (write(f, b, 1) != 1)
184 break;
186 b++;
187 i++;
190 return(i);
193 /****************************************************************************
194 read from a file with LF->CR/LF translation if appropriate. return the
195 number read. read approx n bytes.
196 ****************************************************************************/
197 static int readfile(char *b, int size, int n, FILE *f)
199 int i;
200 int c;
202 if (!translation || (size != 1))
203 return(fread(b,size,n,f));
205 i = 0;
206 while (i < n)
208 if ((c = getc(f)) == EOF)
210 break;
213 if (c == '\n') /* change all LFs to CR/LF */
215 b[i++] = '\r';
216 n++;
219 if(i < n)
220 b[i++] = c;
223 return(i);
227 /****************************************************************************
228 read from a file with print translation. return the number read. read approx n
229 bytes.
230 ****************************************************************************/
231 static int printread(FILE *f,char *b,int n)
233 int i;
235 i = readfile(b,1, n-1,f);
236 #if FORMFEED
237 if (feof(f) && i>0)
238 b[i++] = '\014';
239 #endif
241 return(i);
244 /****************************************************************************
245 check for existance of a dir
246 ****************************************************************************/
247 static BOOL chkpath(char *path,BOOL report)
249 fstring path2;
250 pstring inbuf,outbuf;
251 char *p;
253 strcpy(path2,path);
254 trim_string(path2,NULL,"\\");
255 if (!*path2) *path2 = '\\';
257 bzero(outbuf,smb_size);
258 set_message(outbuf,0,4 + strlen(path2),True);
259 SCVAL(outbuf,smb_com,SMBchkpth);
260 SSVAL(outbuf,smb_tid,cnum);
261 cli_setup_pkt(outbuf);
263 p = smb_buf(outbuf);
264 *p++ = 4;
265 strcpy(p,path2);
267 #if 0
269 /* this little bit of code can be used to extract NT error codes.
270 Just feed a bunch of "cd foo" commands to smbclient then watch
271 in netmon (tridge) */
272 static int code=0;
273 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
274 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
275 code++;
277 #endif
279 send_smb(Client,outbuf);
280 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
282 if (report && CVAL(inbuf,smb_rcls) != 0)
283 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
285 return(CVAL(inbuf,smb_rcls) == 0);
289 /****************************************************************************
290 send a message
291 ****************************************************************************/
292 static void send_message(char *inbuf,char *outbuf)
294 int total_len = 0;
296 char *p;
297 int grp_id;
299 /* send a SMBsendstrt command */
300 bzero(outbuf,smb_size);
301 set_message(outbuf,0,0,True);
302 CVAL(outbuf,smb_com) = SMBsendstrt;
303 SSVAL(outbuf,smb_tid,cnum);
305 p = smb_buf(outbuf);
306 *p++ = 4;
307 strcpy(p,username);
308 p = skip_string(p,1);
309 *p++ = 4;
310 strcpy(p,desthost);
311 p = skip_string(p,1);
313 set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
315 send_smb(Client,outbuf);
318 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
320 printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
321 return;
324 grp_id = SVAL(inbuf,smb_vwv0);
326 printf("Connected. Type your message, ending it with a Control-D\n");
328 while (!feof(stdin) && total_len < 1600)
330 int maxlen = MIN(1600 - total_len,127);
331 pstring msg;
332 int l=0;
333 int c;
335 bzero(msg,smb_size);
337 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
339 if (c == '\n')
340 msg[l++] = '\r';
341 msg[l] = c;
344 CVAL(outbuf,smb_com) = SMBsendtxt;
346 set_message(outbuf,1,l+3,True);
348 SSVAL(outbuf,smb_vwv0,grp_id);
350 p = smb_buf(outbuf);
351 *p = 1;
352 SSVAL(p,1,l);
353 memcpy(p+3,msg,l);
355 send_smb(Client,outbuf);
358 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
360 printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
361 return;
364 total_len += l;
367 if (total_len >= 1600)
368 printf("the message was truncated to 1600 bytes ");
369 else
370 printf("sent %d bytes ",total_len);
372 printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
374 CVAL(outbuf,smb_com) = SMBsendend;
375 set_message(outbuf,1,0,False);
376 SSVAL(outbuf,smb_vwv0,grp_id);
378 send_smb(Client,outbuf);
381 if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
383 printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
384 return;
390 /****************************************************************************
391 check the space on a device
392 ****************************************************************************/
393 static void do_dskattr(void)
395 pstring inbuf,outbuf;
397 bzero(outbuf,smb_size);
398 set_message(outbuf,0,0,True);
399 CVAL(outbuf,smb_com) = SMBdskattr;
400 SSVAL(outbuf,smb_tid,cnum);
401 cli_setup_pkt(outbuf);
403 send_smb(Client,outbuf);
404 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
406 if (CVAL(inbuf,smb_rcls) != 0)
407 DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));
409 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
410 SVAL(inbuf,smb_vwv0),
411 SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
412 SVAL(inbuf,smb_vwv3)));
415 /****************************************************************************
416 show cd/pwd
417 ****************************************************************************/
418 static void cmd_pwd(void)
420 DEBUG(0,("Current directory is %s",CNV_LANG(service)));
421 DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
425 /****************************************************************************
426 change directory - inner section
427 ****************************************************************************/
428 static void do_cd(char *newdir)
430 char *p = newdir;
431 pstring saved_dir;
432 pstring dname;
434 /* Save the current directory in case the
435 new directory is invalid */
436 strcpy(saved_dir, cur_dir);
437 if (*p == '\\')
438 strcpy(cur_dir,p);
439 else
440 strcat(cur_dir,p);
441 if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
442 strcat(cur_dir, "\\");
444 dos_clean_name(cur_dir);
445 strcpy(dname,cur_dir);
446 strcat(cur_dir,"\\");
447 dos_clean_name(cur_dir);
449 if (!strequal(cur_dir,"\\"))
450 if (!chkpath(dname,True))
451 strcpy(cur_dir,saved_dir);
453 strcpy(cd_path,cur_dir);
456 /****************************************************************************
457 change directory
458 ****************************************************************************/
459 static void cmd_cd(char *inbuf,char *outbuf)
461 fstring buf;
463 if (next_token(NULL,buf,NULL))
464 do_cd(buf);
465 else
466 DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
470 /****************************************************************************
471 display info about a file
472 ****************************************************************************/
473 static void display_finfo(file_info *finfo)
475 if (do_this_one(finfo)) {
476 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
477 DEBUG(0,(" %-30s%7.7s%10d %s",
478 CNV_LANG(finfo->name),
479 attrib_string(finfo->mode),
480 finfo->size,
481 asctime(LocalTime(&t))));
482 dir_total += finfo->size;
487 /****************************************************************************
488 do a directory listing, calling fn on each file found. Use the TRANSACT2
489 call for long filenames
490 ****************************************************************************/
491 static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
493 int max_matches = 512;
494 int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
495 char *p;
496 pstring mask;
497 file_info finfo;
498 int i;
499 char *dirlist = NULL;
500 int dirlist_len = 0;
501 int total_received = 0;
502 BOOL First = True;
503 char *resp_data=NULL;
504 char *resp_param=NULL;
505 int resp_data_len = 0;
506 int resp_param_len=0;
508 int ff_resume_key = 0;
509 int ff_searchcount=0;
510 int ff_eos=0;
511 int ff_lastname=0;
512 int ff_dir_handle=0;
513 int loop_count = 0;
515 uint16 setup;
516 pstring param;
518 strcpy(mask,Mask);
520 while (ff_eos == 0)
522 loop_count++;
523 if (loop_count > 200)
525 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
526 break;
529 if (First)
531 setup = TRANSACT2_FINDFIRST;
532 SSVAL(param,0,attribute); /* attribute */
533 SSVAL(param,2,max_matches); /* max count */
534 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
535 SSVAL(param,6,info_level);
536 SIVAL(param,8,0);
537 strcpy(param+12,mask);
539 else
541 setup = TRANSACT2_FINDNEXT;
542 SSVAL(param,0,ff_dir_handle);
543 SSVAL(param,2,max_matches); /* max count */
544 SSVAL(param,4,info_level);
545 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
546 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
547 strcpy(param+12,mask);
549 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
550 ff_dir_handle,ff_resume_key,ff_lastname,mask));
552 /* ??? original code added 1 pad byte after param */
554 cli_send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
555 NULL,param,&setup,
556 0,12+strlen(mask)+1,1,
557 BUFFER_SIZE,10,0);
559 if (!cli_receive_trans_response(inbuf,SMBtrans2,
560 &resp_data_len,&resp_param_len,
561 &resp_data,&resp_param))
563 DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
564 break;
567 /* parse out some important return info */
568 p = resp_param;
569 if (First)
571 ff_dir_handle = SVAL(p,0);
572 ff_searchcount = SVAL(p,2);
573 ff_eos = SVAL(p,4);
574 ff_lastname = SVAL(p,8);
576 else
578 ff_searchcount = SVAL(p,0);
579 ff_eos = SVAL(p,2);
580 ff_lastname = SVAL(p,6);
583 if (ff_searchcount == 0)
584 break;
586 /* point to the data bytes */
587 p = resp_data;
589 /* we might need the lastname for continuations */
590 if (ff_lastname > 0)
592 switch(info_level)
594 case 260:
595 ff_resume_key =0;
596 StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
597 /* strcpy(mask,p+ff_lastname+94); */
598 break;
599 case 1:
600 strcpy(mask,p + ff_lastname + 1);
601 ff_resume_key = 0;
602 break;
605 else
606 strcpy(mask,"");
608 /* and add them to the dirlist pool */
609 dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
611 if (!dirlist)
613 DEBUG(0,("Failed to expand dirlist\n"));
614 break;
617 /* put in a length for the last entry, to ensure we can chain entries
618 into the next packet */
620 char *p2;
621 for (p2=p,i=0;i<(ff_searchcount-1);i++)
622 p2 += interpret_long_filename(info_level,p2,NULL);
623 SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
626 /* grab the data for later use */
627 memcpy(dirlist+dirlist_len,p,resp_data_len);
628 dirlist_len += resp_data_len;
630 total_received += ff_searchcount;
632 if (resp_data) free(resp_data); resp_data = NULL;
633 if (resp_param) free(resp_param); resp_param = NULL;
635 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
636 ff_searchcount,ff_eos,ff_resume_key));
638 First = False;
641 if (!fn)
642 for (p=dirlist,i=0;i<total_received;i++)
644 p += interpret_long_filename(info_level,p,&finfo);
645 display_finfo(&finfo);
648 for (p=dirlist,i=0;i<total_received;i++)
650 p += interpret_long_filename(info_level,p,&finfo);
651 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
654 /* free up the dirlist buffer */
655 if (dirlist) free(dirlist);
656 return(total_received);
660 /****************************************************************************
661 do a directory listing, calling fn on each file found
662 ****************************************************************************/
663 static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
665 char *p;
666 int received = 0;
667 BOOL first = True;
668 char status[21];
669 int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
670 int num_received = 0;
671 int i;
672 char *dirlist = NULL;
673 pstring mask;
674 file_info finfo;
676 finfo = def_finfo;
678 bzero(status,21);
680 strcpy(mask,Mask);
682 while (1)
684 bzero(outbuf,smb_size);
685 if (first)
686 set_message(outbuf,2,5 + strlen(mask),True);
687 else
688 set_message(outbuf,2,5 + 21,True);
690 #if FFIRST
691 if (Protocol >= PROTOCOL_LANMAN1)
692 CVAL(outbuf,smb_com) = SMBffirst;
693 else
694 #endif
695 CVAL(outbuf,smb_com) = SMBsearch;
697 SSVAL(outbuf,smb_tid,cnum);
698 cli_setup_pkt(outbuf);
700 SSVAL(outbuf,smb_vwv0,num_asked);
701 SSVAL(outbuf,smb_vwv1,attribute);
703 p = smb_buf(outbuf);
704 *p++ = 4;
706 if (first)
707 strcpy(p,mask);
708 else
709 strcpy(p,"");
710 p += strlen(p) + 1;
712 *p++ = 5;
713 if (first)
714 SSVAL(p,0,0);
715 else
717 SSVAL(p,0,21);
718 p += 2;
719 memcpy(p,status,21);
722 send_smb(Client,outbuf);
723 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
725 received = SVAL(inbuf,smb_vwv0);
727 DEBUG(5,("dir received %d\n",received));
729 DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
731 if (received <= 0) break;
733 first = False;
735 dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
737 if (!dirlist)
738 return 0;
740 p = smb_buf(inbuf) + 3;
742 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
743 p,received*DIR_STRUCT_SIZE);
745 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
747 num_received += received;
749 if (CVAL(inbuf,smb_rcls) != 0) break;
752 #if FFIRST
753 if (!first && Protocol >= PROTOCOL_LANMAN1)
755 bzero(outbuf,smb_size);
756 CVAL(outbuf,smb_com) = SMBfclose;
758 SSVAL(outbuf,smb_tid,cnum);
759 cli_setup_pkt(outbuf);
761 p = smb_buf(outbuf);
762 *p++ = 4;
764 strcpy(p,"");
765 p += strlen(p) + 1;
767 *p++ = 5;
768 SSVAL(p,0,21);
769 p += 2;
770 memcpy(p,status,21);
772 send_smb(Client,outbuf);
773 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
775 if (CVAL(inbuf,smb_rcls) != 0)
776 DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));
778 #endif
780 if (!fn)
781 for (p=dirlist,i=0;i<num_received;i++)
783 p += interpret_short_filename(p,&finfo);
784 display_finfo(&finfo);
787 for (p=dirlist,i=0;i<num_received;i++)
789 p += interpret_short_filename(p,&finfo);
790 dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
793 if (dirlist) free(dirlist);
794 return(num_received);
799 /****************************************************************************
800 do a directory listing, calling fn on each file found
801 ****************************************************************************/
802 void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
804 DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
805 if (Protocol >= PROTOCOL_LANMAN2)
807 if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
808 return;
811 expand_mask(Mask,False);
812 do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
813 return;
816 /*******************************************************************
817 decide if a file should be operated on
818 ********************************************************************/
819 static BOOL do_this_one(file_info *finfo)
821 if (finfo->mode & aDIR) return(True);
823 if (newer_than && finfo->mtime < newer_than)
824 return(False);
826 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
827 return(False);
829 return(True);
833 /*****************************************************************************
834 Convert a character pointer in a cli_call_api() response to a form we can use.
835 This function contains code to prevent core dumps if the server returns
836 invalid data.
837 *****************************************************************************/
838 static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
840 if( datap == 0 ) /* turn NULL pointers */
841 { /* into zero length strings */
842 return "";
844 else
846 unsigned int offset = datap - converter;
848 if( offset >= rdrcnt )
850 DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt));
851 return "<ERROR>";
853 else
855 return &rdata[offset];
860 /****************************************************************************
861 interpret a short filename structure
862 The length of the structure is returned
863 ****************************************************************************/
864 static int interpret_short_filename(char *p,file_info *finfo)
866 finfo->mode = CVAL(p,21);
868 /* this date is converted to GMT by make_unix_date */
869 finfo->ctime = make_unix_date(p+22);
870 finfo->mtime = finfo->atime = finfo->ctime;
871 finfo->size = IVAL(p,26);
872 strcpy(finfo->name,p+30);
874 return(DIR_STRUCT_SIZE);
877 /****************************************************************************
878 interpret a long filename structure - this is mostly guesses at the moment
879 The length of the structure is returned
880 The structure of a long filename depends on the info level. 260 is used
881 by NT and 2 is used by OS/2
882 ****************************************************************************/
883 static int interpret_long_filename(int level,char *p,file_info *finfo)
885 if (finfo)
886 memcpy(finfo,&def_finfo,sizeof(*finfo));
888 switch (level)
890 case 1: /* OS/2 understands this */
891 if (finfo)
893 /* these dates are converted to GMT by make_unix_date */
894 finfo->ctime = make_unix_date2(p+4);
895 finfo->atime = make_unix_date2(p+8);
896 finfo->mtime = make_unix_date2(p+12);
897 finfo->size = IVAL(p,16);
898 finfo->mode = CVAL(p,24);
899 strcpy(finfo->name,p+27);
901 return(28 + CVAL(p,26));
903 case 2: /* this is what OS/2 uses mostly */
904 if (finfo)
906 /* these dates are converted to GMT by make_unix_date */
907 finfo->ctime = make_unix_date2(p+4);
908 finfo->atime = make_unix_date2(p+8);
909 finfo->mtime = make_unix_date2(p+12);
910 finfo->size = IVAL(p,16);
911 finfo->mode = CVAL(p,24);
912 strcpy(finfo->name,p+31);
914 return(32 + CVAL(p,30));
916 /* levels 3 and 4 are untested */
917 case 3:
918 if (finfo)
920 /* these dates are probably like the other ones */
921 finfo->ctime = make_unix_date2(p+8);
922 finfo->atime = make_unix_date2(p+12);
923 finfo->mtime = make_unix_date2(p+16);
924 finfo->size = IVAL(p,20);
925 finfo->mode = CVAL(p,28);
926 strcpy(finfo->name,p+33);
928 return(SVAL(p,4)+4);
930 case 4:
931 if (finfo)
933 /* these dates are probably like the other ones */
934 finfo->ctime = make_unix_date2(p+8);
935 finfo->atime = make_unix_date2(p+12);
936 finfo->mtime = make_unix_date2(p+16);
937 finfo->size = IVAL(p,20);
938 finfo->mode = CVAL(p,28);
939 strcpy(finfo->name,p+37);
941 return(SVAL(p,4)+4);
943 case 260: /* NT uses this, but also accepts 2 */
944 if (finfo)
946 int ret = SVAL(p,0);
947 int namelen;
948 p += 4; /* next entry offset */
949 p += 4; /* fileindex */
951 /* these dates appear to arrive in a weird way. It seems to
952 be localtime plus the serverzone given in the initial
953 connect. This is GMT when DST is not in effect and one
954 hour from GMT otherwise. Can this really be right??
956 I suppose this could be called kludge-GMT. Is is the GMT
957 you get by using the current DST setting on a different
958 localtime. It will be cheap to calculate, I suppose, as
959 no DST tables will be needed */
961 finfo->ctime = interpret_long_date(p); p += 8;
962 finfo->atime = interpret_long_date(p); p += 8;
963 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
964 finfo->size = IVAL(p,0); p += 8;
965 p += 8; /* alloc size */
966 finfo->mode = CVAL(p,0); p += 4;
967 namelen = IVAL(p,0); p += 4;
968 p += 4; /* EA size */
969 p += 2; /* short name len? */
970 p += 24; /* short name? */
971 StrnCpy(finfo->name,p,namelen);
972 return(ret);
974 return(SVAL(p,0));
977 DEBUG(1,("Unknown long filename format %d\n",level));
978 return(SVAL(p,0));
984 /****************************************************************************
985 act on the files in a dir listing
986 ****************************************************************************/
987 static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
990 if (!((finfo->mode & aDIR) == 0 && *fileselection &&
991 !mask_match(finfo->name,fileselection,False,False)) &&
992 !(recurse_dir && (strequal(finfo->name,".") ||
993 strequal(finfo->name,".."))))
995 if (recurse_dir && (finfo->mode & aDIR))
997 pstring mask2;
998 pstring sav_dir;
999 strcpy(sav_dir,cur_dir);
1000 strcat(cur_dir,finfo->name);
1001 strcat(cur_dir,"\\");
1002 strcpy(mask2,cur_dir);
1004 if (!fn)
1005 DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
1007 strcat(mask2,"*");
1009 if (longdir)
1010 do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);
1011 else
1012 do_dir(inbuf,outbuf,mask2,attribute,fn,True);
1014 strcpy(cur_dir,sav_dir);
1016 else
1018 if (fn && do_this_one(finfo))
1019 fn(finfo);
1025 /****************************************************************************
1026 get a directory listing
1027 ****************************************************************************/
1028 static void cmd_dir(char *inbuf,char *outbuf)
1030 int attribute = aDIR | aSYSTEM | aHIDDEN;
1031 pstring mask;
1032 fstring buf;
1033 char *p=buf;
1035 dir_total = 0;
1036 strcpy(mask,cur_dir);
1037 if(mask[strlen(mask)-1]!='\\')
1038 strcat(mask,"\\");
1040 if (next_token(NULL,buf,NULL))
1042 if (*p == '\\')
1043 strcpy(mask,p);
1044 else
1045 strcat(mask,p);
1047 else {
1048 strcat(mask,"*");
1051 do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
1053 do_dskattr();
1055 DEBUG(3, ("Total bytes listed: %d\n", dir_total));
1060 /****************************************************************************
1061 get a file from rname to lname
1062 ****************************************************************************/
1063 static void do_get(char *rname,char *lname,file_info *finfo1)
1065 int handle=0,fnum;
1066 uint32 nread=0;
1067 char *p;
1068 BOOL newhandle = False;
1069 char *inbuf,*outbuf;
1070 file_info finfo;
1071 BOOL close_done = False;
1072 BOOL ignore_close_error = False;
1073 char *dataptr=NULL;
1074 int datalen=0;
1076 struct timeval tp_start;
1077 GetTimeOfDay(&tp_start);
1079 if (finfo1)
1080 finfo = *finfo1;
1081 else
1082 finfo = def_finfo;
1084 if (lowercase)
1085 strlower(lname);
1088 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1089 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1091 if (!inbuf || !outbuf)
1093 DEBUG(0,("out of memory\n"));
1094 return;
1097 bzero(outbuf,smb_size);
1098 set_message(outbuf,15,1 + strlen(rname),True);
1100 CVAL(outbuf,smb_com) = SMBopenX;
1101 SSVAL(outbuf,smb_tid,cnum);
1102 cli_setup_pkt(outbuf);
1104 SSVAL(outbuf,smb_vwv0,0xFF);
1105 SSVAL(outbuf,smb_vwv2,1);
1106 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1107 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1108 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1109 SSVAL(outbuf,smb_vwv8,1);
1110 SSVAL(outbuf,smb_vwv11,0xffff);
1111 SSVAL(outbuf,smb_vwv12,0xffff);
1113 p = smb_buf(outbuf);
1114 strcpy(p,rname);
1115 p = skip_string(p,1);
1117 /* do a chained openX with a readX? */
1118 #if 1
1119 if (finfo.size > 0)
1121 DEBUG(3,("Chaining readX wth openX\n"));
1122 SSVAL(outbuf,smb_vwv0,SMBreadX);
1123 SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
1124 bzero(p,200);
1125 p -= smb_wct;
1126 SSVAL(p,smb_wct,10);
1127 SSVAL(p,smb_vwv0,0xFF);
1128 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1129 SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
1130 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1132 #endif
1134 if(!strcmp(lname,"-"))
1135 handle = fileno(stdout);
1136 else
1138 handle = creat(lname,0644);
1139 newhandle = True;
1141 if (handle < 0)
1143 DEBUG(0,("Error opening local file %s\n",lname));
1144 free(inbuf);free(outbuf);
1145 return;
1148 send_smb(Client,outbuf);
1149 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1151 if (CVAL(inbuf,smb_rcls) != 0)
1153 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1154 SVAL(inbuf,smb_err) == ERRnoresource &&
1155 cli_reopen_connection(inbuf,outbuf))
1157 do_get(rname,lname,finfo1);
1158 return;
1160 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1161 if(newhandle)
1162 close(handle);
1163 free(inbuf);free(outbuf);
1164 return;
1167 strcpy(finfo.name,rname);
1169 if (!finfo1)
1171 finfo.mode = SVAL(inbuf,smb_vwv3);
1172 /* these times arrive as LOCAL time, using the DST offset
1173 corresponding to that time, we convert them to GMT */
1174 finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
1175 finfo.atime = finfo.ctime = finfo.mtime;
1176 finfo.size = IVAL(inbuf,smb_vwv6);
1179 DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
1181 fnum = SVAL(inbuf,smb_vwv2);
1183 /* we might have got some data from a chained readX */
1184 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1186 p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
1187 datalen = SVAL(p,smb_vwv5);
1188 dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
1190 else
1192 dataptr = NULL;
1193 datalen = 0;
1197 DEBUG(2,("getting file %s of size %d bytes as %s ",
1198 CNV_LANG(finfo.name),
1199 finfo.size,
1200 lname));
1202 while (nread < finfo.size && !close_done)
1204 int method = -1;
1205 static BOOL can_chain_close = True;
1207 p=NULL;
1209 DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
1211 /* 3 possible read types. readbraw if a large block is required.
1212 readX + close if not much left and read if neither is supported */
1214 /* we might have already read some data from a chained readX */
1215 if (dataptr && datalen>0)
1216 method=3;
1218 /* if we can finish now then readX+close */
1219 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1220 ((finfo.size - nread) <
1221 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1222 method = 0;
1224 /* if we support readraw then use that */
1225 if (method<0 && readbraw_supported)
1226 method = 1;
1228 /* if we can then use readX */
1229 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1230 method = 2;
1232 switch (method)
1234 /* use readX */
1235 case 0:
1236 case 2:
1237 if (method == 0)
1238 close_done = True;
1240 /* use readX + close */
1241 bzero(outbuf,smb_size);
1242 set_message(outbuf,10,0,True);
1243 CVAL(outbuf,smb_com) = SMBreadX;
1244 SSVAL(outbuf,smb_tid,cnum);
1245 cli_setup_pkt(outbuf);
1247 if (close_done)
1249 CVAL(outbuf,smb_vwv0) = SMBclose;
1250 SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
1252 else
1253 CVAL(outbuf,smb_vwv0) = 0xFF;
1255 SSVAL(outbuf,smb_vwv2,fnum);
1256 SIVAL(outbuf,smb_vwv3,nread);
1257 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1258 SSVAL(outbuf,smb_vwv6,0);
1259 SIVAL(outbuf,smb_vwv7,0);
1260 SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
1262 if (close_done)
1264 p = smb_buf(outbuf);
1265 bzero(p,9);
1267 CVAL(p,0) = 3;
1268 SSVAL(p,1,fnum);
1269 SIVALS(p,3,-1);
1271 /* now set the total packet length */
1272 smb_setlen(outbuf,smb_len(outbuf)+9);
1275 send_smb(Client,outbuf);
1276 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1278 if (CVAL(inbuf,smb_rcls) != 0)
1280 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1281 break;
1284 if (close_done &&
1285 SVAL(inbuf,smb_vwv0) != SMBclose)
1287 /* NOTE: WfWg sometimes just ignores the chained
1288 command! This seems to break the spec? */
1289 DEBUG(3,("Rejected chained close?\n"));
1290 close_done = False;
1291 can_chain_close = False;
1292 ignore_close_error = True;
1295 datalen = SVAL(inbuf,smb_vwv5);
1296 dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
1297 break;
1299 /* use readbraw */
1300 case 1:
1302 static int readbraw_size = BUFFER_SIZE;
1304 extern int Client;
1305 bzero(outbuf,smb_size);
1306 set_message(outbuf,8,0,True);
1307 CVAL(outbuf,smb_com) = SMBreadbraw;
1308 SSVAL(outbuf,smb_tid,cnum);
1309 cli_setup_pkt(outbuf);
1310 SSVAL(outbuf,smb_vwv0,fnum);
1311 SIVAL(outbuf,smb_vwv1,nread);
1312 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1313 SSVAL(outbuf,smb_vwv4,0);
1314 SIVALS(outbuf,smb_vwv5,-1);
1315 send_smb(Client,outbuf);
1317 /* Now read the raw data into the buffer and write it */
1318 if(read_smb_length(Client,inbuf,0) == -1) {
1319 DEBUG(0,("Failed to read length in readbraw\n"));
1320 exit(1);
1323 /* Even though this is not an smb message, smb_len
1324 returns the generic length of an smb message */
1325 datalen = smb_len(inbuf);
1327 if (datalen == 0)
1329 /* we got a readbraw error */
1330 DEBUG(4,("readbraw error - reducing size\n"));
1331 readbraw_size = (readbraw_size * 9) / 10;
1333 if (readbraw_size < max_xmit)
1335 DEBUG(0,("disabling readbraw\n"));
1336 readbraw_supported = False;
1339 dataptr=NULL;
1340 continue;
1343 if(read_data(Client,inbuf,datalen) != datalen) {
1344 DEBUG(0,("Failed to read data in readbraw\n"));
1345 exit(1);
1347 dataptr = inbuf;
1349 break;
1351 case 3:
1352 /* we've already read some data with a chained readX */
1353 break;
1355 default:
1356 /* use plain read */
1357 bzero(outbuf,smb_size);
1358 set_message(outbuf,5,0,True);
1359 CVAL(outbuf,smb_com) = SMBread;
1360 SSVAL(outbuf,smb_tid,cnum);
1361 cli_setup_pkt(outbuf);
1363 SSVAL(outbuf,smb_vwv0,fnum);
1364 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1365 SIVAL(outbuf,smb_vwv2,nread);
1366 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1368 send_smb(Client,outbuf);
1369 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1371 if (CVAL(inbuf,smb_rcls) != 0)
1373 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1374 break;
1377 datalen = SVAL(inbuf,smb_vwv0);
1378 dataptr = smb_buf(inbuf) + 3;
1379 break;
1382 if (writefile(handle,dataptr,datalen) != datalen)
1384 DEBUG(0,("Error writing local file\n"));
1385 break;
1388 nread += datalen;
1389 if (datalen == 0)
1391 DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
1392 break;
1395 dataptr=NULL;
1396 datalen=0;
1401 if (!close_done)
1403 cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
1405 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1407 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1408 if(newhandle)
1409 close(handle);
1410 free(inbuf);free(outbuf);
1411 return;
1415 if(newhandle)
1416 close(handle);
1418 if (archive_level >= 2 && (finfo.mode & aARCH)) {
1419 bzero(outbuf,smb_size);
1420 set_message(outbuf,8,strlen(rname)+4,True);
1421 CVAL(outbuf,smb_com) = SMBsetatr;
1422 SSVAL(outbuf,smb_tid,cnum);
1423 cli_setup_pkt(outbuf);
1424 SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
1425 SIVALS(outbuf,smb_vwv1,0);
1426 p = smb_buf(outbuf);
1427 *p++ = 4;
1428 strcpy(p,rname);
1429 p += strlen(p)+1;
1430 *p++ = 4;
1431 *p = 0;
1432 send_smb(Client,outbuf);
1433 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1437 struct timeval tp_end;
1438 int this_time;
1440 GetTimeOfDay(&tp_end);
1441 this_time =
1442 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1443 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1444 get_total_time_ms += this_time;
1445 get_total_size += finfo.size;
1447 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1448 finfo.size / (1.024*this_time + 1.0e-4),
1449 get_total_size / (1.024*get_total_time_ms)));
1452 free(inbuf);free(outbuf);
1456 /****************************************************************************
1457 get a file
1458 ****************************************************************************/
1459 static void cmd_get(void)
1461 pstring lname;
1462 pstring rname;
1463 char *p;
1465 strcpy(rname,cur_dir);
1466 strcat(rname,"\\");
1468 p = rname + strlen(rname);
1470 if (!next_token(NULL,p,NULL)) {
1471 DEBUG(0,("get <filename>\n"));
1472 return;
1474 strcpy(lname,p);
1475 dos_clean_name(rname);
1477 next_token(NULL,lname,NULL);
1479 do_get(rname,lname,NULL);
1483 /****************************************************************************
1484 do a mget operation on one file
1485 ****************************************************************************/
1486 static void do_mget(file_info *finfo)
1488 pstring rname;
1489 pstring quest;
1491 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1492 return;
1494 if (abort_mget)
1496 DEBUG(0,("mget aborted\n"));
1497 return;
1500 if (finfo->mode & aDIR)
1501 sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
1502 else
1503 sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
1505 if (prompt && !yesno(quest)) return;
1507 if (finfo->mode & aDIR)
1509 pstring saved_curdir;
1510 pstring mget_mask;
1511 char *inbuf,*outbuf;
1513 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1514 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1516 if (!inbuf || !outbuf)
1518 DEBUG(0,("out of memory\n"));
1519 return;
1522 strcpy(saved_curdir,cur_dir);
1524 strcat(cur_dir,finfo->name);
1525 strcat(cur_dir,"\\");
1527 unix_format(finfo->name);
1529 if (lowercase)
1530 strlower(finfo->name);
1532 if (!directory_exist(finfo->name,NULL) &&
1533 sys_mkdir(finfo->name,0777) != 0)
1535 DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
1536 strcpy(cur_dir,saved_curdir);
1537 free(inbuf);free(outbuf);
1538 return;
1541 if (sys_chdir(finfo->name) != 0)
1543 DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
1544 strcpy(cur_dir,saved_curdir);
1545 free(inbuf);free(outbuf);
1546 return;
1550 strcpy(mget_mask,cur_dir);
1551 strcat(mget_mask,"*");
1553 do_dir((char *)inbuf,(char *)outbuf,
1554 mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
1555 chdir("..");
1556 strcpy(cur_dir,saved_curdir);
1557 free(inbuf);free(outbuf);
1559 else
1561 strcpy(rname,cur_dir);
1562 strcat(rname,finfo->name);
1563 do_get(rname,finfo->name,finfo);
1567 /****************************************************************************
1568 view the file using the pager
1569 ****************************************************************************/
1570 static void cmd_more(void)
1572 fstring rname,lname,tmpname,pager_cmd;
1573 char *pager;
1575 strcpy(rname,cur_dir);
1576 strcat(rname,"\\");
1577 sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
1578 strcpy(lname,tmpname);
1580 if (!next_token(NULL,rname+strlen(rname),NULL)) {
1581 DEBUG(0,("more <filename>\n"));
1582 return;
1584 dos_clean_name(rname);
1586 do_get(rname,lname,NULL);
1588 pager=getenv("PAGER");
1589 sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
1590 system(pager_cmd);
1591 unlink(tmpname);
1596 /****************************************************************************
1597 do a mget command
1598 ****************************************************************************/
1599 static void cmd_mget(char *inbuf,char *outbuf)
1601 int attribute = aSYSTEM | aHIDDEN;
1602 pstring mget_mask;
1603 fstring buf;
1604 char *p=buf;
1606 *mget_mask = 0;
1608 if (recurse)
1609 attribute |= aDIR;
1611 abort_mget = False;
1613 while (next_token(NULL,p,NULL))
1615 strcpy(mget_mask,cur_dir);
1616 if(mget_mask[strlen(mget_mask)-1]!='\\')
1617 strcat(mget_mask,"\\");
1619 if (*p == '\\')
1620 strcpy(mget_mask,p);
1621 else
1622 strcat(mget_mask,p);
1623 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1626 if (! *mget_mask)
1628 strcpy(mget_mask,cur_dir);
1629 if(mget_mask[strlen(mget_mask)-1]!='\\')
1630 strcat(mget_mask,"\\");
1631 strcat(mget_mask,"*");
1632 do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
1636 /****************************************************************************
1637 make a directory of name "name"
1638 ****************************************************************************/
1639 static BOOL do_mkdir(char *name)
1641 char *p;
1642 char *inbuf,*outbuf;
1644 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1645 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1647 if (!inbuf || !outbuf)
1649 DEBUG(0,("out of memory\n"));
1650 return False;
1653 bzero(outbuf,smb_size);
1654 set_message(outbuf,0,2 + strlen(name),True);
1656 CVAL(outbuf,smb_com) = SMBmkdir;
1657 SSVAL(outbuf,smb_tid,cnum);
1658 cli_setup_pkt(outbuf);
1661 p = smb_buf(outbuf);
1662 *p++ = 4;
1663 strcpy(p,name);
1665 send_smb(Client,outbuf);
1666 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1668 if (CVAL(inbuf,smb_rcls) != 0)
1670 DEBUG(0,("%s making remote directory %s\n",
1671 smb_errstr(inbuf),CNV_LANG(name)));
1673 free(inbuf);free(outbuf);
1674 return(False);
1677 free(inbuf);free(outbuf);
1678 return(True);
1682 /****************************************************************************
1683 make a directory
1684 ****************************************************************************/
1685 static void cmd_mkdir(char *inbuf,char *outbuf)
1687 pstring mask;
1688 fstring buf;
1689 char *p=buf;
1691 strcpy(mask,cur_dir);
1693 if (!next_token(NULL,p,NULL))
1695 if (!recurse)
1696 DEBUG(0,("mkdir <dirname>\n"));
1697 return;
1699 strcat(mask,p);
1701 if (recurse)
1703 pstring ddir;
1704 pstring ddir2;
1705 *ddir2 = 0;
1707 strcpy(ddir,mask);
1708 trim_string(ddir,".",NULL);
1709 p = strtok(ddir,"/\\");
1710 while (p)
1712 strcat(ddir2,p);
1713 if (!chkpath(ddir2,False))
1715 do_mkdir(ddir2);
1717 strcat(ddir2,"\\");
1718 p = strtok(NULL,"/\\");
1721 else
1722 do_mkdir(mask);
1726 /*******************************************************************
1727 write to a file using writebraw
1728 ********************************************************************/
1729 static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
1731 extern int Client;
1732 pstring inbuf;
1734 bzero(outbuf,smb_size);
1735 bzero(inbuf,smb_size);
1736 set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
1738 CVAL(outbuf,smb_com) = SMBwritebraw;
1739 SSVAL(outbuf,smb_tid,cnum);
1740 cli_setup_pkt(outbuf);
1742 SSVAL(outbuf,smb_vwv0,fnum);
1743 SSVAL(outbuf,smb_vwv1,n);
1744 SIVAL(outbuf,smb_vwv3,pos);
1745 SSVAL(outbuf,smb_vwv7,1);
1747 send_smb(Client,outbuf);
1749 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
1750 return(0);
1752 _smb_setlen(buf-4,n); /* HACK! XXXX */
1754 if (write_socket(Client,buf-4,n+4) != n+4)
1755 return(0);
1757 if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
1758 DEBUG(0,("Error writing remote file (2)\n"));
1759 return(0);
1761 return(SVAL(inbuf,smb_vwv0));
1766 /*******************************************************************
1767 write to a file
1768 ********************************************************************/
1769 static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
1771 pstring inbuf;
1773 if (writebraw_supported && n > (max_xmit-200))
1774 return(smb_writeraw(outbuf,fnum,pos,buf,n));
1776 bzero(outbuf,smb_size);
1777 bzero(inbuf,smb_size);
1778 set_message(outbuf,5,n + 3,True);
1780 CVAL(outbuf,smb_com) = SMBwrite;
1781 SSVAL(outbuf,smb_tid,cnum);
1782 cli_setup_pkt(outbuf);
1784 SSVAL(outbuf,smb_vwv0,fnum);
1785 SSVAL(outbuf,smb_vwv1,n);
1786 SIVAL(outbuf,smb_vwv2,pos);
1787 SSVAL(outbuf,smb_vwv4,0);
1788 CVAL(smb_buf(outbuf),0) = 1;
1789 SSVAL(smb_buf(outbuf),1,n);
1791 memcpy(smb_buf(outbuf)+3,buf,n);
1793 send_smb(Client,outbuf);
1794 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1796 if (CVAL(inbuf,smb_rcls) != 0) {
1797 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
1798 return(0);
1800 return(SVAL(inbuf,smb_vwv0));
1805 /****************************************************************************
1806 put a single file
1807 ****************************************************************************/
1808 static void do_put(char *rname,char *lname,file_info *finfo)
1810 int fnum;
1811 FILE *f;
1812 int nread=0;
1813 char *p;
1814 char *inbuf,*outbuf;
1815 time_t close_time = finfo->mtime;
1816 char *buf=NULL;
1817 static int maxwrite=0;
1819 struct timeval tp_start;
1820 GetTimeOfDay(&tp_start);
1822 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1823 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1825 if (!inbuf || !outbuf)
1827 DEBUG(0,("out of memory\n"));
1828 return;
1831 bzero(outbuf,smb_size);
1832 set_message(outbuf,3,2 + strlen(rname),True);
1834 if (finfo->mtime == 0 || finfo->mtime == -1)
1835 finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
1837 CVAL(outbuf,smb_com) = SMBcreate;
1838 SSVAL(outbuf,smb_tid,cnum);
1839 cli_setup_pkt(outbuf);
1841 SSVAL(outbuf,smb_vwv0,finfo->mode);
1842 put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
1844 p = smb_buf(outbuf);
1845 *p++ = 4;
1846 strcpy(p,rname);
1848 send_smb(Client,outbuf);
1849 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1851 if (CVAL(inbuf,smb_rcls) != 0)
1853 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1855 free(inbuf);free(outbuf);if (buf) free(buf);
1856 return;
1859 f = fopen(lname,"r");
1861 if (!f)
1863 DEBUG(0,("Error opening local file %s\n",lname));
1864 free(inbuf);free(outbuf);
1865 return;
1869 fnum = SVAL(inbuf,smb_vwv0);
1870 if (finfo->size < 0)
1871 finfo->size = file_size(lname);
1873 DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
1875 if (!maxwrite)
1876 maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
1878 while (nread < finfo->size)
1880 int n = maxwrite;
1881 int ret;
1883 n = MIN(n,finfo->size - nread);
1885 buf = (char *)Realloc(buf,n+4);
1887 fseek(f,nread,SEEK_SET);
1888 if ((n = readfile(buf+4,1,n,f)) < 1)
1890 DEBUG(0,("Error reading local file\n"));
1891 break;
1894 ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
1896 if (n != ret) {
1897 if (!maxwrite) {
1898 DEBUG(0,("Error writing file\n"));
1899 break;
1900 } else {
1901 maxwrite /= 2;
1902 continue;
1906 nread += n;
1911 bzero(outbuf,smb_size);
1912 set_message(outbuf,3,0,True);
1913 CVAL(outbuf,smb_com) = SMBclose;
1914 SSVAL(outbuf,smb_tid,cnum);
1915 cli_setup_pkt(outbuf);
1917 SSVAL(outbuf,smb_vwv0,fnum);
1918 put_dos_date3(outbuf,smb_vwv1,close_time);
1920 send_smb(Client,outbuf);
1921 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1923 if (CVAL(inbuf,smb_rcls) != 0)
1925 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
1926 fclose(f);
1927 free(inbuf);free(outbuf);
1928 if (buf) free(buf);
1929 return;
1933 fclose(f);
1934 free(inbuf);free(outbuf);
1935 if (buf) free(buf);
1938 struct timeval tp_end;
1939 int this_time;
1941 GetTimeOfDay(&tp_end);
1942 this_time =
1943 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1944 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1945 put_total_time_ms += this_time;
1946 put_total_size += finfo->size;
1948 DEBUG(1,("(%g kb/s) (average %g kb/s)\n",
1949 finfo->size / (1.024*this_time + 1.0e-4),
1950 put_total_size / (1.024*put_total_time_ms)));
1956 /****************************************************************************
1957 put a file
1958 ****************************************************************************/
1959 static void cmd_put(void)
1961 pstring lname;
1962 pstring rname;
1963 fstring buf;
1964 char *p=buf;
1965 file_info finfo;
1966 finfo = def_finfo;
1968 strcpy(rname,cur_dir);
1969 strcat(rname,"\\");
1972 if (!next_token(NULL,p,NULL))
1974 DEBUG(0,("put <filename>\n"));
1975 return;
1977 strcpy(lname,p);
1979 if (next_token(NULL,p,NULL))
1980 strcat(rname,p);
1981 else
1982 strcat(rname,lname);
1984 dos_clean_name(rname);
1987 struct stat st;
1988 if (!file_exist(lname,&st)) {
1989 DEBUG(0,("%s does not exist\n",lname));
1990 return;
1992 finfo.mtime = st.st_mtime;
1995 do_put(rname,lname,&finfo);
1998 /****************************************************************************
1999 seek in a directory/file list until you get something that doesn't start with
2000 the specified name
2001 ****************************************************************************/
2002 static BOOL seek_list(FILE *f,char *name)
2004 pstring s;
2005 while (!feof(f))
2007 if (fscanf(f,"%s",s) != 1) return(False);
2008 trim_string(s,"./",NULL);
2009 if (strncmp(s,name,strlen(name)) != 0)
2011 strcpy(name,s);
2012 return(True);
2016 return(False);
2020 /****************************************************************************
2021 set the file selection mask
2022 ****************************************************************************/
2023 static void cmd_select(void)
2025 strcpy(fileselection,"");
2026 next_token(NULL,fileselection,NULL);
2030 /****************************************************************************
2031 mput some files
2032 ****************************************************************************/
2033 static void cmd_mput(void)
2035 pstring lname;
2036 pstring rname;
2037 file_info finfo;
2038 fstring buf;
2039 char *p=buf;
2041 finfo = def_finfo;
2044 while (next_token(NULL,p,NULL))
2046 struct stat st;
2047 pstring cmd;
2048 pstring tmpname;
2049 FILE *f;
2051 sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid());
2052 if (recurse)
2053 sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
2054 else
2055 sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
2056 system(cmd);
2058 f = fopen(tmpname,"r");
2059 if (!f) continue;
2061 while (!feof(f))
2063 pstring quest;
2065 if (fscanf(f,"%s",lname) != 1) break;
2066 trim_string(lname,"./",NULL);
2068 again1:
2070 /* check if it's a directory */
2071 if (directory_exist(lname,&st))
2073 if (!recurse) continue;
2074 sprintf(quest,"Put directory %s? ",lname);
2075 if (prompt && !yesno(quest))
2077 strcat(lname,"/");
2078 if (!seek_list(f,lname))
2079 break;
2080 goto again1;
2083 strcpy(rname,cur_dir);
2084 strcat(rname,lname);
2085 if (!chkpath(rname,False) && !do_mkdir(rname)) {
2086 strcat(lname,"/");
2087 if (!seek_list(f,lname))
2088 break;
2089 goto again1;
2092 continue;
2094 else
2096 sprintf(quest,"Put file %s? ",lname);
2097 if (prompt && !yesno(quest)) continue;
2099 strcpy(rname,cur_dir);
2100 strcat(rname,lname);
2102 dos_format(rname);
2104 /* null size so do_put knows to ignore it */
2105 finfo.size = -1;
2107 /* set the date on the file */
2108 finfo.mtime = st.st_mtime;
2110 do_put(rname,lname,&finfo);
2112 fclose(f);
2113 unlink(tmpname);
2117 /****************************************************************************
2118 cancel a print job
2119 ****************************************************************************/
2120 static void do_cancel(int job)
2122 char *rparam = NULL;
2123 char *rdata = NULL;
2124 char *p;
2125 int rdrcnt,rprcnt;
2126 pstring param;
2128 bzero(param,sizeof(param));
2130 p = param;
2131 SSVAL(p,0,81); /* DosPrintJobDel() */
2132 p += 2;
2133 strcpy(p,"W");
2134 p = skip_string(p,1);
2135 strcpy(p,"");
2136 p = skip_string(p,1);
2137 SSVAL(p,0,job);
2138 p += 2;
2140 if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param),0, 0,
2141 6, 1000,
2142 &rprcnt,&rdrcnt,
2143 param,NULL, NULL,
2144 &rparam,&rdata))
2146 int res = SVAL(rparam,0);
2148 if (!res)
2149 printf("Job %d cancelled\n",job);
2150 else
2151 printf("Error %d calcelling job %d\n",res,job);
2152 return;
2154 else
2155 printf("Server refused cancel request\n");
2157 if (rparam) free(rparam);
2158 if (rdata) free(rdata);
2160 return;
2164 /****************************************************************************
2165 cancel a print job
2166 ****************************************************************************/
2167 static void cmd_cancel(char *inbuf,char *outbuf )
2169 fstring buf;
2170 int job;
2172 if (!connect_as_printer)
2174 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2175 DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
2178 if (!next_token(NULL,buf,NULL)) {
2179 printf("cancel <jobid> ...\n");
2180 return;
2182 do {
2183 job = atoi(buf);
2184 do_cancel(job);
2185 } while (next_token(NULL,buf,NULL));
2189 /****************************************************************************
2190 get info on a file
2191 ****************************************************************************/
2192 static void cmd_stat(char *inbuf,char *outbuf)
2194 fstring buf;
2195 pstring param;
2196 char *resp_data=NULL;
2197 char *resp_param=NULL;
2198 int resp_data_len = 0;
2199 int resp_param_len=0;
2200 char *p;
2201 uint16 setup = TRANSACT2_QPATHINFO;
2203 if (!next_token(NULL,buf,NULL)) {
2204 printf("stat <file>\n");
2205 return;
2208 bzero(param,6);
2209 SSVAL(param,0,4); /* level */
2210 p = param+6;
2211 strcpy(p,cur_dir);
2212 strcat(p,buf);
2214 cli_send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
2215 NULL,param,&setup,
2216 0,6 + strlen(p)+1,1,
2217 BUFFER_SIZE,2,0);
2219 cli_receive_trans_response(inbuf,SMBtrans2,
2220 &resp_data_len,&resp_param_len,
2221 &resp_data,&resp_param);
2223 if (resp_data) free(resp_data); resp_data = NULL;
2224 if (resp_param) free(resp_param); resp_param = NULL;
2228 /****************************************************************************
2229 print a file
2230 ****************************************************************************/
2231 static void cmd_print(char *inbuf,char *outbuf )
2233 int fnum;
2234 FILE *f = NULL;
2235 uint32 nread=0;
2236 pstring lname;
2237 pstring rname;
2238 char *p;
2240 if (!connect_as_printer)
2242 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2243 DEBUG(0,("Trying to print without -P may fail\n"));
2246 if (!next_token(NULL,lname,NULL))
2248 DEBUG(0,("print <filename>\n"));
2249 return;
2252 strcpy(rname,lname);
2253 p = strrchr(rname,'/');
2254 if (p)
2256 pstring tname;
2257 strcpy(tname,p+1);
2258 strcpy(rname,tname);
2261 if ((int)strlen(rname) > 14)
2262 rname[14] = 0;
2264 if (strequal(lname,"-"))
2266 f = stdin;
2267 strcpy(rname,"stdin");
2270 dos_clean_name(rname);
2272 bzero(outbuf,smb_size);
2273 set_message(outbuf,2,2 + strlen(rname),True);
2275 CVAL(outbuf,smb_com) = SMBsplopen;
2276 SSVAL(outbuf,smb_tid,cnum);
2277 cli_setup_pkt(outbuf);
2279 SSVAL(outbuf,smb_vwv0,0);
2280 SSVAL(outbuf,smb_vwv1,printmode);
2282 p = smb_buf(outbuf);
2283 *p++ = 4;
2284 strcpy(p,rname);
2286 send_smb(Client,outbuf);
2287 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2289 if (CVAL(inbuf,smb_rcls) != 0)
2291 DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
2292 return;
2295 if (!f)
2296 f = fopen(lname,"r");
2297 if (!f)
2299 DEBUG(0,("Error opening local file %s\n",lname));
2300 return;
2304 fnum = SVAL(inbuf,smb_vwv0);
2306 DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
2308 while (!feof(f))
2310 int n;
2312 bzero(outbuf,smb_size);
2313 set_message(outbuf,1,3,True);
2315 /* for some strange reason the OS/2 print server can't handle large
2316 packets when printing. weird */
2317 n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
2319 if (translation)
2320 n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
2321 else
2322 n = readfile(smb_buf(outbuf)+3,1,n,f);
2323 if (n <= 0)
2325 DEBUG(0,("read gave %d\n",n));
2326 break;
2329 smb_setlen(outbuf,smb_len(outbuf) + n);
2331 CVAL(outbuf,smb_com) = SMBsplwr;
2332 SSVAL(outbuf,smb_tid,cnum);
2333 cli_setup_pkt(outbuf);
2335 SSVAL(outbuf,smb_vwv0,fnum);
2336 SSVAL(outbuf,smb_vwv1,n+3);
2337 CVAL(smb_buf(outbuf),0) = 1;
2338 SSVAL(smb_buf(outbuf),1,n);
2340 send_smb(Client,outbuf);
2341 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2343 if (CVAL(inbuf,smb_rcls) != 0)
2345 DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
2346 break;
2349 nread += n;
2352 DEBUG(2,("%d bytes printed\n",nread));
2354 bzero(outbuf,smb_size);
2355 set_message(outbuf,1,0,True);
2356 CVAL(outbuf,smb_com) = SMBsplclose;
2357 SSVAL(outbuf,smb_tid,cnum);
2358 cli_setup_pkt(outbuf);
2360 SSVAL(outbuf,smb_vwv0,fnum);
2362 send_smb(Client,outbuf);
2363 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2365 if (CVAL(inbuf,smb_rcls) != 0)
2367 DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
2368 if (f != stdin)
2369 fclose(f);
2370 return;
2373 if (f != stdin)
2374 fclose(f);
2377 /****************************************************************************
2378 show a print queue - this is deprecated as it uses the old smb that
2379 has limited support - the correct call is the cmd_p_queue_4() after this.
2380 ****************************************************************************/
2381 static void cmd_queue(char *inbuf,char *outbuf )
2383 int count;
2384 char *p;
2386 bzero(outbuf,smb_size);
2387 set_message(outbuf,2,0,True);
2389 CVAL(outbuf,smb_com) = SMBsplretq;
2390 SSVAL(outbuf,smb_tid,cnum);
2391 cli_setup_pkt(outbuf);
2393 SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
2394 SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
2396 send_smb(Client,outbuf);
2397 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2399 if (CVAL(inbuf,smb_rcls) != 0)
2401 DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
2402 return;
2405 count = SVAL(inbuf,smb_vwv0);
2406 p = smb_buf(inbuf) + 3;
2407 if (count <= 0)
2409 DEBUG(0,("No entries in the print queue\n"));
2410 return;
2414 char status[20];
2416 DEBUG(0,("Job Name Size Status\n"));
2418 while (count--)
2420 switch (CVAL(p,4))
2422 case 0x01: sprintf(status,"held or stopped"); break;
2423 case 0x02: sprintf(status,"printing"); break;
2424 case 0x03: sprintf(status,"awaiting print"); break;
2425 case 0x04: sprintf(status,"in intercept"); break;
2426 case 0x05: sprintf(status,"file had error"); break;
2427 case 0x06: sprintf(status,"printer error"); break;
2428 default: sprintf(status,"unknown"); break;
2431 DEBUG(0,("%-6d %-16.16s %-9d %s\n",
2432 SVAL(p,5),p+12,IVAL(p,7),status));
2433 p += 28;
2440 /****************************************************************************
2441 show information about a print queue
2442 ****************************************************************************/
2443 static void cmd_p_queue_4(char *inbuf,char *outbuf )
2445 char *rparam = NULL;
2446 char *rdata = NULL;
2447 char *p;
2448 int rdrcnt, rprcnt;
2449 pstring param;
2450 int result_code=0;
2452 if (!connect_as_printer)
2454 DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
2455 DEBUG(0,("Trying to print without -P may fail\n"));
2458 bzero(param,sizeof(param));
2460 p = param;
2461 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2462 p += 2;
2463 strcpy(p,"zWrLeh"); /* parameter description? */
2464 p = skip_string(p,1);
2465 strcpy(p,"WWzWWDDzz"); /* returned data format */
2466 p = skip_string(p,1);
2467 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2468 p = skip_string(p,1);
2469 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2470 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2471 p += 4;
2472 strcpy(p,""); /* subformat */
2473 p = skip_string(p,1);
2475 DEBUG(1,("Calling DosPrintJobEnum()...\n"));
2476 if( cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param), 0,
2477 10, 0, 4096,
2478 &rprcnt, &rdrcnt,
2479 param, NULL, NULL,
2480 &rparam, &rdata) )
2482 int converter;
2483 result_code = SVAL(rparam,0);
2484 converter = SVAL(rparam,2); /* conversion factor */
2486 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2488 if (result_code == 0) /* if no error, */
2490 int i;
2491 uint16 JobId;
2492 uint16 Priority;
2493 uint32 Size;
2494 char *UserName;
2495 char *JobName;
2496 char *JobTimeStr;
2497 time_t JobTime;
2498 char PrinterName[20];
2500 strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */
2501 strlower(PrinterName); /* in lower case */
2503 p = rdata; /* received data */
2504 for( i = 0; i < SVAL(rparam,4); ++i)
2506 JobId = SVAL(p,0);
2507 Priority = SVAL(p,2);
2508 UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
2509 strlower(UserName);
2510 Priority = SVAL(p,2);
2511 JobTime = make_unix_date3( p + 12);
2512 JobTimeStr = asctime(LocalTime( &JobTime));
2513 Size = IVAL(p,16);
2514 JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
2517 printf("%s-%u %s priority %u %s %s %u bytes\n",
2518 PrinterName, JobId, UserName,
2519 Priority, JobTimeStr, JobName, Size);
2521 #if 0 /* DEBUG code */
2522 printf("Job Id: \"%u\"\n", SVAL(p,0));
2523 printf("Priority: \"%u\"\n", SVAL(p,2));
2525 printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
2526 printf("Position: \"%u\"\n", SVAL(p,8));
2527 printf("Status: \"%u\"\n", SVAL(p,10));
2529 JobTime = make_unix_date3( p + 12);
2530 printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
2531 printf("date: \"%u\"\n", SVAL(p,12));
2533 printf("Size: \"%u\"\n", SVAL(p,16));
2534 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2535 printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2536 #endif /* DEBUG CODE */
2537 p += 28;
2541 else /* cli_call_api() failed */
2543 printf("Failed, error = %d\n", result_code);
2546 /* If any parameters or data were returned, free the storage. */
2547 if(rparam) free(rparam);
2548 if(rdata) free(rdata);
2550 return;
2553 /****************************************************************************
2554 show information about a print queue
2555 ****************************************************************************/
2556 static void cmd_qinfo(char *inbuf,char *outbuf )
2558 char *rparam = NULL;
2559 char *rdata = NULL;
2560 char *p;
2561 int rdrcnt, rprcnt;
2562 pstring param;
2563 int result_code=0;
2565 bzero(param,sizeof(param));
2567 p = param;
2568 SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */
2569 p += 2;
2570 strcpy(p,"zWrLh"); /* parameter description? */
2571 p = skip_string(p,1);
2572 strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */
2573 p = skip_string(p,1);
2574 strcpy(p,strrchr(service,'\\')+1); /* name of queue */
2575 p = skip_string(p,1);
2576 SSVAL(p,0,3); /* API function level 3, just queue info, no job info */
2577 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2578 p += 4;
2579 strcpy(p,""); /* subformat */
2580 p = skip_string(p,1);
2582 DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
2583 if( cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param), 0, 0,
2584 10, 4096,
2585 &rprcnt, &rdrcnt,
2586 param, NULL, NULL,
2587 &rparam, &rdata) )
2589 int converter;
2590 result_code = SVAL(rparam,0);
2591 converter = SVAL(rparam,2); /* conversion factor */
2593 DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
2595 if (result_code == 0) /* if no error, */
2597 p = rdata; /* received data */
2599 printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) );
2600 printf("Priority: %u\n", SVAL(p,4) );
2601 printf("Start time: %u\n", SVAL(p,6) );
2602 printf("Until time: %u\n", SVAL(p,8) );
2603 printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) );
2604 printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) );
2605 printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
2606 printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
2607 printf("Status: %u\n", SVAL(p,28) );
2608 printf("Jobs: %u\n", SVAL(p,30) );
2609 printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) );
2610 printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) );
2612 /* Dump the driver data */
2614 int count, x, y, c;
2615 char *ddptr;
2617 ddptr = rdata + SVAL(p,40) - converter;
2618 if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);}
2619 printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) );
2621 for(x=8; x < count; x+=16)
2623 for(y=0; y < 16; y++)
2625 if( (x+y) < count )
2626 printf("%2.2X ", CVAL(ddptr,(x+y)) );
2627 else
2628 fputs(" ", stdout);
2630 for(y=0; y < 16 && (x+y) < count; y++)
2632 c = CVAL(ddptr,(x+y));
2633 if(isprint(c))
2634 fputc(c, stdout);
2635 else
2636 fputc('.', stdout);
2638 fputc('\n', stdout);
2644 else /* cli_call_api() failed */
2646 printf("Failed, error = %d\n", result_code);
2649 /* If any parameters or data were returned, free the storage. */
2650 if(rparam) free(rparam);
2651 if(rdata) free(rdata);
2653 return;
2656 /****************************************************************************
2657 delete some files
2658 ****************************************************************************/
2659 static void do_del(file_info *finfo)
2661 char *p;
2662 char *inbuf,*outbuf;
2663 pstring mask;
2665 strcpy(mask,cur_dir);
2666 strcat(mask,finfo->name);
2668 if (finfo->mode & aDIR)
2669 return;
2671 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2672 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2674 if (!inbuf || !outbuf)
2676 DEBUG(0,("out of memory\n"));
2677 return;
2680 bzero(outbuf,smb_size);
2681 set_message(outbuf,1,2 + strlen(mask),True);
2683 CVAL(outbuf,smb_com) = SMBunlink;
2684 SSVAL(outbuf,smb_tid,cnum);
2685 cli_setup_pkt(outbuf);
2687 SSVAL(outbuf,smb_vwv0,0);
2689 p = smb_buf(outbuf);
2690 *p++ = 4;
2691 strcpy(p,mask);
2693 send_smb(Client,outbuf);
2694 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2696 if (CVAL(inbuf,smb_rcls) != 0)
2697 DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2699 free(inbuf);free(outbuf);
2703 /****************************************************************************
2704 delete some files
2705 ****************************************************************************/
2706 static void cmd_del(char *inbuf,char *outbuf )
2708 pstring mask;
2709 fstring buf;
2710 int attribute = aSYSTEM | aHIDDEN;
2712 if (recurse)
2713 attribute |= aDIR;
2715 strcpy(mask,cur_dir);
2717 if (!next_token(NULL,buf,NULL))
2719 DEBUG(0,("del <filename>\n"));
2720 return;
2722 strcat(mask,buf);
2724 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
2728 /****************************************************************************
2729 remove a directory
2730 ****************************************************************************/
2731 static void cmd_rmdir(char *inbuf,char *outbuf )
2733 pstring mask;
2734 fstring buf;
2735 char *p;
2737 strcpy(mask,cur_dir);
2739 if (!next_token(NULL,buf,NULL))
2741 DEBUG(0,("rmdir <dirname>\n"));
2742 return;
2744 strcat(mask,buf);
2746 bzero(outbuf,smb_size);
2747 set_message(outbuf,0,2 + strlen(mask),True);
2749 CVAL(outbuf,smb_com) = SMBrmdir;
2750 SSVAL(outbuf,smb_tid,cnum);
2751 cli_setup_pkt(outbuf);
2754 p = smb_buf(outbuf);
2755 *p++ = 4;
2756 strcpy(p,mask);
2758 send_smb(Client,outbuf);
2759 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2761 if (CVAL(inbuf,smb_rcls) != 0)
2763 DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
2764 return;
2769 /****************************************************************************
2770 rename some files
2771 ****************************************************************************/
2772 static void cmd_rename(char *inbuf,char *outbuf )
2774 pstring src,dest;
2775 fstring buf,buf2;
2776 char *p;
2778 strcpy(src,cur_dir);
2779 strcpy(dest,cur_dir);
2781 if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
2783 DEBUG(0,("rename <src> <dest>\n"));
2784 return;
2786 strcat(src,buf);
2787 strcat(dest,buf2);
2789 bzero(outbuf,smb_size);
2790 set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
2792 CVAL(outbuf,smb_com) = SMBmv;
2793 SSVAL(outbuf,smb_tid,cnum);
2794 SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
2795 cli_setup_pkt(outbuf);
2797 p = smb_buf(outbuf);
2798 *p++ = 4;
2799 strcpy(p,src);
2800 p = skip_string(p,1);
2801 *p++ = 4;
2802 strcpy(p,dest);
2804 send_smb(Client,outbuf);
2805 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
2807 if (CVAL(inbuf,smb_rcls) != 0)
2809 DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
2810 return;
2816 /****************************************************************************
2817 toggle the prompt flag
2818 ****************************************************************************/
2819 static void cmd_prompt(void)
2821 prompt = !prompt;
2822 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
2826 /****************************************************************************
2827 set the newer than time
2828 ****************************************************************************/
2829 static void cmd_newer(void)
2831 fstring buf;
2832 BOOL ok;
2833 struct stat sbuf;
2835 ok = next_token(NULL,buf,NULL);
2836 if (ok && (sys_stat(buf,&sbuf) == 0))
2838 newer_than = sbuf.st_mtime;
2839 DEBUG(1,("Getting files newer than %s",
2840 asctime(LocalTime(&newer_than))));
2842 else
2843 newer_than = 0;
2845 if (ok && newer_than == 0)
2846 DEBUG(0,("Error setting newer-than time\n"));
2849 /****************************************************************************
2850 set the archive level
2851 ****************************************************************************/
2852 static void cmd_archive(void)
2854 fstring buf;
2856 if (next_token(NULL,buf,NULL)) {
2857 archive_level = atoi(buf);
2858 } else
2859 DEBUG(0,("Archive level is %d\n",archive_level));
2862 /****************************************************************************
2863 toggle the lowercaseflag
2864 ****************************************************************************/
2865 static void cmd_lowercase(void)
2867 lowercase = !lowercase;
2868 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
2874 /****************************************************************************
2875 toggle the recurse flag
2876 ****************************************************************************/
2877 static void cmd_recurse(void)
2879 recurse = !recurse;
2880 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
2883 /****************************************************************************
2884 toggle the translate flag
2885 ****************************************************************************/
2886 static void cmd_translate(void)
2888 translation = !translation;
2889 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2890 translation?"on":"off"));
2894 /****************************************************************************
2895 do a printmode command
2896 ****************************************************************************/
2897 static void cmd_printmode(void)
2899 fstring buf;
2900 fstring mode;
2902 if (next_token(NULL,buf,NULL))
2904 if (strequal(buf,"text"))
2905 printmode = 0;
2906 else
2908 if (strequal(buf,"graphics"))
2909 printmode = 1;
2910 else
2911 printmode = atoi(buf);
2915 switch(printmode)
2917 case 0:
2918 strcpy(mode,"text");
2919 break;
2920 case 1:
2921 strcpy(mode,"graphics");
2922 break;
2923 default:
2924 sprintf(mode,"%d",printmode);
2925 break;
2928 DEBUG(2,("the printmode is now %s\n",mode));
2931 /****************************************************************************
2932 do the lcd command
2933 ****************************************************************************/
2934 static void cmd_lcd(void)
2936 fstring buf;
2937 pstring d;
2939 if (next_token(NULL,buf,NULL))
2940 sys_chdir(buf);
2941 DEBUG(2,("the local directory is now %s\n",GetWd(d)));
2945 /****************************************************************************
2946 try and browse available connections on a host
2947 ****************************************************************************/
2948 static BOOL browse_host(BOOL sort)
2950 #ifdef NOSTRCASECMP
2951 /* If strcasecmp is already defined, remove it. */
2952 #ifdef strcasecmp
2953 #undef strcasecmp
2954 #endif /* strcasecmp */
2955 #define strcasecmp StrCaseCmp
2956 #endif /* NOSTRCASECMP */
2958 extern int strcasecmp();
2960 char *rparam = NULL;
2961 char *rdata = NULL;
2962 char *p;
2963 int rdrcnt,rprcnt;
2964 pstring param;
2965 int count = -1;
2967 /* now send a SMBtrans command with api RNetShareEnum */
2968 p = param;
2969 SSVAL(p,0,0); /* api number */
2970 p += 2;
2971 strcpy(p,"WrLeh");
2972 p = skip_string(p,1);
2973 strcpy(p,"B13BWz");
2974 p = skip_string(p,1);
2975 SSVAL(p,0,1);
2976 SSVAL(p,2,BUFFER_SIZE);
2977 p += 4;
2979 if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param),0, 0,
2980 1024, BUFFER_SIZE,
2981 &rprcnt,&rdrcnt,
2982 param,NULL, NULL,
2983 &rparam,&rdata))
2985 int res = SVAL(rparam,0);
2986 int converter=SVAL(rparam,2);
2987 int i;
2988 BOOL long_share_name=False;
2990 if (res == 0)
2992 count=SVAL(rparam,4);
2993 p = rdata;
2995 if (count > 0)
2997 printf("\n\tSharename Type Comment\n");
2998 printf("\t--------- ---- -------\n");
3001 if (sort)
3002 qsort(p,count,20,QSORT_CAST strcasecmp);
3004 for (i=0;i<count;i++)
3006 char *sname = p;
3007 int type = SVAL(p,14);
3008 int comment_offset = IVAL(p,16) & 0xFFFF;
3009 fstring typestr;
3010 *typestr=0;
3012 switch (type)
3014 case STYPE_DISKTREE:
3015 strcpy(typestr,"Disk"); break;
3016 case STYPE_PRINTQ:
3017 strcpy(typestr,"Printer"); break;
3018 case STYPE_DEVICE:
3019 strcpy(typestr,"Device"); break;
3020 case STYPE_IPC:
3021 strcpy(typestr,"IPC"); break;
3024 printf("\t%-15.15s%-10.10s%s\n",
3025 sname,
3026 typestr,
3027 comment_offset?rdata+comment_offset-converter:"");
3029 if (strlen(sname)>8) long_share_name=True;
3031 p += 20;
3034 if (long_share_name) {
3035 printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
3040 if (rparam) free(rparam);
3041 if (rdata) free(rdata);
3043 return(count>0);
3047 /****************************************************************************
3048 get some server info
3049 ****************************************************************************/
3050 static void server_info()
3052 char *rparam = NULL;
3053 char *rdata = NULL;
3054 char *p;
3055 int rdrcnt,rprcnt;
3056 pstring param;
3058 bzero(param,sizeof(param));
3060 p = param;
3061 SSVAL(p,0,63); /* NetServerGetInfo()? */
3062 p += 2;
3063 strcpy(p,"WrLh");
3064 p = skip_string(p,1);
3065 strcpy(p,"zzzBBzz");
3066 p = skip_string(p,1);
3067 SSVAL(p,0,10); /* level 10 */
3068 SSVAL(p,2,1000);
3069 p += 6;
3071 if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param),0, 0,
3072 6, 1000,
3073 &rprcnt,&rdrcnt,
3074 param,NULL, NULL,
3075 &rparam,&rdata))
3077 int res = SVAL(rparam,0);
3078 int converter=SVAL(rparam,2);
3080 if (res == 0)
3082 p = rdata;
3084 printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
3085 rdata+SVAL(p,0)-converter,
3086 rdata+SVAL(p,4)-converter,
3087 rdata+SVAL(p,8)-converter,
3088 rdata+SVAL(p,14)-converter);
3092 if (rparam) free(rparam);
3093 if (rdata) free(rdata);
3095 return;
3099 /****************************************************************************
3100 try and browse available connections on a host
3101 ****************************************************************************/
3102 static BOOL list_servers(char *wk_grp)
3104 char *rparam = NULL;
3105 char *rdata = NULL;
3106 int rdrcnt,rprcnt;
3107 char *p,*svtype_p;
3108 pstring param;
3109 int uLevel = 1;
3110 int count = 0;
3111 BOOL ok = False;
3112 BOOL generic_request = False;
3115 if (strequal(wk_grp,"WORKGROUP")) {
3116 /* we won't specify a workgroup */
3117 generic_request = True;
3120 /* now send a SMBtrans command with api ServerEnum? */
3121 p = param;
3122 SSVAL(p,0,0x68); /* api number */
3123 p += 2;
3125 strcpy(p,generic_request?"WrLehDO":"WrLehDz");
3126 p = skip_string(p,1);
3128 strcpy(p,"B16BBDz");
3130 p = skip_string(p,1);
3131 SSVAL(p,0,uLevel);
3132 SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
3133 p += 4;
3135 svtype_p = p;
3136 p += 4;
3138 if (!generic_request) {
3139 strcpy(p, wk_grp);
3140 p = skip_string(p,1);
3143 /* first ask for a list of servers in this workgroup */
3144 SIVAL(svtype_p,0,SV_TYPE_ALL);
3146 if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p+4,param),0, 0,
3147 8, BUFFER_SIZE - SAFETY_MARGIN,
3148 &rprcnt,&rdrcnt,
3149 param,NULL, NULL,
3150 &rparam,&rdata))
3152 int res = SVAL(rparam,0);
3153 int converter=SVAL(rparam,2);
3154 int i;
3156 if (res == 0) {
3157 char *p2 = rdata;
3158 count=SVAL(rparam,4);
3160 if (count > 0) {
3161 printf("\n\nThis machine has a browse list:\n");
3162 printf("\n\tServer Comment\n");
3163 printf("\t--------- -------\n");
3166 for (i=0;i<count;i++) {
3167 char *sname = p2;
3168 int comment_offset = IVAL(p2,22) & 0xFFFF;
3169 printf("\t%-16.16s %s\n",
3170 sname,
3171 comment_offset?rdata+comment_offset-converter:"");
3173 ok=True;
3174 p2 += 26;
3179 if (rparam) {free(rparam); rparam = NULL;}
3180 if (rdata) {free(rdata); rdata = NULL;}
3182 /* now ask for a list of workgroups */
3183 SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
3185 if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p+4,param),0, 0,
3186 8, BUFFER_SIZE - SAFETY_MARGIN,
3187 &rprcnt,&rdrcnt,
3188 param,NULL, NULL,
3189 &rparam,&rdata))
3191 int res = SVAL(rparam,0);
3192 int converter=SVAL(rparam,2);
3193 int i;
3195 if (res == 0) {
3196 char *p2 = rdata;
3197 count=SVAL(rparam,4);
3199 if (count > 0) {
3200 printf("\n\nThis machine has a workgroup list:\n");
3201 printf("\n\tWorkgroup Master\n");
3202 printf("\t--------- -------\n");
3205 for (i=0;i<count;i++) {
3206 char *sname = p2;
3207 int comment_offset = IVAL(p2,22) & 0xFFFF;
3208 printf("\t%-16.16s %s\n",
3209 sname,
3210 comment_offset?rdata+comment_offset-converter:"");
3212 ok=True;
3213 p2 += 26;
3218 if (rparam) free(rparam);
3219 if (rdata) free(rdata);
3221 return(ok);
3225 /* This defines the commands supported by this client */
3226 struct
3228 char *name;
3229 void (*fn)();
3230 char *description;
3231 } commands[] =
3233 {"ls",cmd_dir,"<mask> list the contents of the current directory"},
3234 {"dir",cmd_dir,"<mask> list the contents of the current directory"},
3235 {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
3236 {"cd",cmd_cd,"[directory] change/report the remote directory"},
3237 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
3238 {"get",cmd_get,"<remote name> [local name] get a file"},
3239 {"mget",cmd_mget,"<mask> get all the matching files"},
3240 {"put",cmd_put,"<local name> [remote name] put a file"},
3241 {"mput",cmd_mput,"<mask> put all matching files"},
3242 {"rename",cmd_rename,"<src> <dest> rename some files"},
3243 {"more",cmd_more,"<remote name> view a remote file with your pager"},
3244 {"mask",cmd_select,"<mask> mask all filenames against this"},
3245 {"del",cmd_del,"<mask> delete all matching files"},
3246 {"rm",cmd_del,"<mask> delete all matching files"},
3247 {"mkdir",cmd_mkdir,"<directory> make a directory"},
3248 {"md",cmd_mkdir,"<directory> make a directory"},
3249 {"rmdir",cmd_rmdir,"<directory> remove a directory"},
3250 {"rd",cmd_rmdir,"<directory> remove a directory"},
3251 {"pq",cmd_p_queue_4,"enumerate the print queue"},
3252 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},
3253 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},
3254 {"translate",cmd_translate,"toggle text translation for printing"},
3255 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},
3256 {"print",cmd_print,"<file name> print a file"},
3257 {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
3258 {"queue",cmd_queue,"show the print queue"},
3259 {"qinfo",cmd_qinfo,"show print queue information"},
3260 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
3261 {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
3262 {"quit",cli_send_logout,"logoff the server"},
3263 {"q",cli_send_logout,"logoff the server"},
3264 {"exit",cli_send_logout,"logoff the server"},
3265 {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
3266 {"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"},
3267 {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
3268 {"blocksize",cmd_block,"blocksize <number> (default 20)" },
3269 {"tarmode",cmd_tarmode,
3270 "<full|inc|reset|noreset> tar's behaviour towards archive bits" },
3271 {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
3272 {"help",cmd_help,"[command] give help on a command"},
3273 {"?",cmd_help,"[command] give help on a command"},
3274 {"!",NULL,"run a shell command on the local system"},
3275 {"",NULL,NULL}
3279 /*******************************************************************
3280 lookup a command string in the list of commands, including
3281 abbreviations
3282 ******************************************************************/
3283 static int process_tok(fstring tok)
3285 int i = 0, matches = 0;
3286 int cmd=0;
3287 int tok_len = strlen(tok);
3289 while (commands[i].fn != NULL)
3291 if (strequal(commands[i].name,tok))
3293 matches = 1;
3294 cmd = i;
3295 break;
3297 else if (strnequal(commands[i].name, tok, tok_len+1))
3299 matches++;
3300 cmd = i;
3302 i++;
3305 if (matches == 0)
3306 return(-1);
3307 else if (matches == 1)
3308 return(cmd);
3309 else
3310 return(-2);
3313 /****************************************************************************
3314 help
3315 ****************************************************************************/
3316 void cmd_help(void)
3318 int i=0,j;
3319 fstring buf;
3321 if (next_token(NULL,buf,NULL))
3323 if ((i = process_tok(buf)) >= 0)
3324 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
3326 else
3327 while (commands[i].description)
3329 for (j=0; commands[i].description && (j<5); j++) {
3330 DEBUG(0,("%-15s",commands[i].name));
3331 i++;
3333 DEBUG(0,("\n"));
3337 /****************************************************************************
3338 wait for keyboard activity, swallowing network packets
3339 ****************************************************************************/
3340 #ifdef CLIX
3341 static char wait_keyboard(char *buffer)
3342 #else
3343 static void wait_keyboard(char *buffer)
3344 #endif
3346 fd_set fds;
3347 int selrtn;
3348 struct timeval timeout;
3350 #ifdef CLIX
3351 int delay = 0;
3352 #endif
3354 while (1)
3356 extern int Client;
3357 FD_ZERO(&fds);
3358 FD_SET(Client,&fds);
3359 #ifndef CLIX
3360 FD_SET(fileno(stdin),&fds);
3361 #endif
3363 timeout.tv_sec = 20;
3364 timeout.tv_usec = 0;
3365 #ifdef CLIX
3366 timeout.tv_sec = 0;
3367 #endif
3368 selrtn = sys_select(&fds,&timeout);
3370 #ifndef CLIX
3371 if (FD_ISSET(fileno(stdin),&fds))
3372 return;
3373 #else
3375 char ch;
3376 int readret;
3378 set_blocking(fileno(stdin), False);
3379 readret = read_data( fileno(stdin), &ch, 1);
3380 set_blocking(fileno(stdin), True);
3381 if (readret == -1)
3383 if (errno != EAGAIN)
3385 /* should crash here */
3386 DEBUG(1,("readchar stdin failed\n"));
3389 else if (readret != 0)
3391 return ch;
3394 #endif
3395 if (FD_ISSET(Client,&fds))
3396 receive_smb(Client,buffer,0);
3398 #ifdef CLIX
3399 delay++;
3400 if (delay > 100000)
3402 delay = 0;
3403 chkpath("\\",False);
3405 #else
3406 chkpath("\\",False);
3407 #endif
3412 /****************************************************************************
3413 process commands from the client
3414 ****************************************************************************/
3415 static BOOL process(char *base_directory)
3417 extern FILE *dbf;
3418 pstring line;
3419 char *cmd;
3421 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3422 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3424 if ((InBuffer == NULL) || (OutBuffer == NULL))
3425 return(False);
3427 bzero(OutBuffer,smb_size);
3429 if (!cli_send_login(InBuffer,OutBuffer,True,True))
3430 return(False);
3432 if (*base_directory) do_cd(base_directory);
3434 cmd = cmdstr;
3435 if (cmd[0] != '\0') while (cmd[0] != '\0')
3437 char *p;
3438 fstring tok;
3439 int i;
3441 if ((p = strchr(cmd, ';')) == 0)
3443 strncpy(line, cmd, 999);
3444 line[1000] = '\0';
3445 cmd += strlen(cmd);
3447 else
3449 if (p - cmd > 999) p = cmd + 999;
3450 strncpy(line, cmd, p - cmd);
3451 line[p - cmd] = '\0';
3452 cmd = p + 1;
3455 /* input language code to internal one */
3456 CNV_INPUT (line);
3458 /* and get the first part of the command */
3460 char *ptr = line;
3461 if (!next_token(&ptr,tok,NULL)) continue;
3464 if ((i = process_tok(tok)) >= 0)
3465 commands[i].fn(InBuffer,OutBuffer);
3466 else if (i == -2)
3467 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3468 else
3469 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3471 else while (!feof(stdin))
3473 fstring tok;
3474 int i;
3476 bzero(OutBuffer,smb_size);
3478 /* display a prompt */
3479 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
3480 fflush(dbf);
3482 #ifdef CLIX
3483 line[0] = wait_keyboard(InBuffer);
3484 /* this might not be such a good idea... */
3485 if ( line[0] == EOF)
3486 break;
3487 #else
3488 wait_keyboard(InBuffer);
3489 #endif
3491 /* and get a response */
3492 #ifdef CLIX
3493 fgets( &line[1],999, stdin);
3494 #else
3495 if (!fgets(line,1000,stdin))
3496 break;
3497 #endif
3499 /* input language code to internal one */
3500 CNV_INPUT (line);
3502 /* special case - first char is ! */
3503 if (*line == '!')
3505 system(line + 1);
3506 continue;
3509 /* and get the first part of the command */
3511 char *ptr = line;
3512 if (!next_token(&ptr,tok,NULL)) continue;
3515 if ((i = process_tok(tok)) >= 0)
3516 commands[i].fn(InBuffer,OutBuffer);
3517 else if (i == -2)
3518 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
3519 else
3520 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
3523 cli_send_logout();
3524 return(True);
3527 /****************************************************************************
3528 usage on the program
3529 ****************************************************************************/
3530 static void usage(char *pname)
3532 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
3533 pname));
3535 DEBUG(0,("\nVersion %s\n",VERSION));
3536 DEBUG(0,("\t-p port listen on the specified port\n"));
3537 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
3538 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
3539 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
3540 DEBUG(0,("\t-N don't ask for a password\n"));
3541 DEBUG(0,("\t-P connect to service as a printer\n"));
3542 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
3543 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
3544 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
3545 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
3546 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
3547 DEBUG(0,("\t-U username set the network username\n"));
3548 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
3549 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
3550 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
3551 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
3552 DEBUG(0,("\t-D directory start from directory\n"));
3553 DEBUG(0,("\n"));
3556 /****************************************************************************
3557 main program
3558 ****************************************************************************/
3559 int main(int argc,char *argv[])
3561 fstring base_directory;
3562 char *pname = argv[0];
3563 int port = SMB_PORT;
3564 int opt;
3565 extern FILE *dbf;
3566 extern char *optarg;
3567 extern int optind;
3568 pstring query_host;
3569 BOOL message = False;
3570 BOOL nt_domain_logon = False;
3571 extern char tar_type;
3572 static pstring servicesf = CONFIGFILE;
3573 pstring term_code;
3574 char *p;
3576 #ifdef KANJI
3577 strcpy(term_code, KANJI);
3578 #else /* KANJI */
3579 *term_code = 0;
3580 #endif /* KANJI */
3582 *query_host = 0;
3583 *base_directory = 0;
3585 DEBUGLEVEL = 2;
3587 setup_logging(pname,True);
3589 TimeInit();
3590 charset_initialise();
3592 pid = getpid();
3593 uid = getuid();
3594 gid = getgid();
3595 mid = pid + 100;
3596 myumask = umask(0);
3597 umask(myumask);
3599 if (getenv("USER"))
3601 strcpy(username,getenv("USER"));
3603 /* modification to support userid%passwd syntax in the USER var
3604 25.Aug.97, jdblair@uab.edu */
3606 if ((p=strchr(username,'%')))
3608 *p = 0;
3609 strcpy(password,p+1);
3610 got_pass = True;
3611 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
3613 strupper(username);
3616 /* modification to support PASSWD environmental var
3617 25.Aug.97, jdblair@uab.edu */
3619 if (getenv("PASSWD"))
3620 strcpy(password,getenv("PASSWD"));
3622 if (*username == 0 && getenv("LOGNAME"))
3624 strcpy(username,getenv("LOGNAME"));
3625 strupper(username);
3628 if (argc < 2)
3630 usage(pname);
3631 exit(1);
3634 if (*argv[1] != '-')
3637 strcpy(service,argv[1]);
3638 /* Convert any '/' characters in the service name to '\' characters */
3639 string_replace( service, '/','\\');
3640 argc--;
3641 argv++;
3643 if (count_chars(service,'\\') < 3)
3645 usage(pname);
3646 printf("\n%s: Not enough '\\' characters in service\n",service);
3647 exit(1);
3651 if (count_chars(service,'\\') > 3)
3653 usage(pname);
3654 printf("\n%s: Too many '\\' characters in service\n",service);
3655 exit(1);
3659 if (argc > 1 && (*argv[1] != '-'))
3661 got_pass = True;
3662 strcpy(password,argv[1]);
3663 memset(argv[1],'X',strlen(argv[1]));
3664 argc--;
3665 argv++;
3669 while ((opt =
3670 getopt(argc, argv,"s:B:O:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
3671 switch (opt)
3673 case 'm':
3674 max_protocol = interpret_protocol(optarg,max_protocol);
3675 break;
3676 case 'O':
3677 strcpy(user_socket_options,optarg);
3678 break;
3679 case 'S':
3680 strcpy(desthost,optarg);
3681 strupper(desthost);
3682 nt_domain_logon = True;
3683 break;
3684 case 'M':
3685 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
3686 strcpy(desthost,optarg);
3687 strupper(desthost);
3688 message = True;
3689 break;
3690 case 'B':
3691 iface_set_default(NULL,optarg,NULL);
3692 break;
3693 case 'D':
3694 strcpy(base_directory,optarg);
3695 break;
3696 case 'T':
3697 if (!tar_parseargs(argc, argv, optarg, optind)) {
3698 usage(pname);
3699 exit(1);
3701 break;
3702 case 'i':
3703 strcpy(scope,optarg);
3704 break;
3705 case 'L':
3706 got_pass = True;
3707 strcpy(query_host,optarg);
3708 break;
3709 case 'U':
3711 char *lp;
3712 strcpy(username,optarg);
3713 if ((lp=strchr(username,'%')))
3715 *lp = 0;
3716 strcpy(password,lp+1);
3717 got_pass = True;
3718 memset(strchr(optarg,'%')+1,'X',strlen(password));
3722 break;
3723 case 'W':
3724 strcpy(workgroup,optarg);
3725 break;
3726 case 'E':
3727 dbf = stderr;
3728 break;
3729 case 'I':
3731 dest_ip = *interpret_addr2(optarg);
3732 if (zero_ip(dest_ip)) exit(1);
3733 have_ip = True;
3735 break;
3736 case 'n':
3737 strcpy(myname,optarg);
3738 break;
3739 case 'N':
3740 got_pass = True;
3741 break;
3742 case 'P':
3743 connect_as_printer = True;
3744 break;
3745 case 'd':
3746 if (*optarg == 'A')
3747 DEBUGLEVEL = 10000;
3748 else
3749 DEBUGLEVEL = atoi(optarg);
3750 break;
3751 case 'l':
3752 sprintf(debugf,"%s.client",optarg);
3753 break;
3754 case 'p':
3755 port = atoi(optarg);
3756 break;
3757 case 'c':
3758 cmdstr = optarg;
3759 got_pass = True;
3760 break;
3761 case 'h':
3762 usage(pname);
3763 exit(0);
3764 break;
3765 case 's':
3766 strcpy(servicesf, optarg);
3767 break;
3768 case 't':
3769 strcpy(term_code, optarg);
3770 break;
3771 default:
3772 usage(pname);
3773 exit(1);
3776 if (!tar_type && !*query_host && !*service && !message)
3778 usage(pname);
3779 exit(1);
3783 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
3785 if(!get_myname(myhostname,NULL))
3787 DEBUG(0,("Failed to get my hostname.\n"));
3790 if (!lp_load(servicesf,True)) {
3791 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
3794 codepage_initialise(lp_client_code_page());
3796 if(lp_client_code_page() == KANJI_CODEPAGE)
3798 if (!setup_term_code (term_code))
3800 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
3801 usage (pname);
3802 exit (1);
3806 if (*workgroup == 0)
3807 strcpy(workgroup,lp_workgroup());
3809 load_interfaces();
3810 get_myname((*myname)?NULL:myname,NULL);
3811 strupper(myname);
3813 if (tar_type) {
3814 recurse=True;
3816 if (cli_open_sockets(port)) {
3817 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3818 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3819 int ret;
3821 if ((InBuffer == NULL) || (OutBuffer == NULL))
3822 return(1);
3824 bzero(OutBuffer,smb_size);
3825 if (!cli_send_login(InBuffer,OutBuffer,True,True))
3826 return(False);
3828 if (*base_directory) do_cd(base_directory);
3830 ret=process_tar(InBuffer, OutBuffer);
3832 cli_send_logout();
3833 close_sockets();
3834 return(ret);
3835 } else
3836 return(1);
3839 if (*query_host && !nt_domain_logon)
3841 int ret = 0;
3842 sprintf(service,"\\\\%s\\IPC$",query_host);
3843 strupper(service);
3844 connect_as_ipc = True;
3845 if (cli_open_sockets(port))
3847 #if 0
3848 *username = 0;
3849 #endif
3850 if (!cli_send_login(NULL,NULL,True,True))
3851 return(1);
3853 server_info();
3854 if (!browse_host(True)) {
3855 sleep(1);
3856 browse_host(True);
3858 if (!list_servers(workgroup)) {
3859 sleep(1);
3860 list_servers(workgroup);
3863 cli_send_logout();
3864 close_sockets();
3867 return(ret);
3870 if (message)
3872 int ret = 0;
3873 if (cli_open_sockets(port))
3875 pstring inbuf,outbuf;
3876 bzero(outbuf,smb_size);
3877 if (!cli_send_session_request(inbuf,outbuf))
3878 return(1);
3880 send_message(inbuf,outbuf);
3882 close_sockets();
3885 return(ret);
3888 #ifdef NTDOMAIN
3890 if (nt_domain_logon)
3892 int ret = 0;
3893 sprintf(service,"\\\\%s\\IPC$",query_host);
3894 strupper(service);
3895 connect_as_ipc = True;
3897 DEBUG(5,("NT Domain Logon. Service: %s\n", service));
3899 if (cli_open_sockets(port))
3901 if (!cli_send_login(NULL,NULL,True,True)) return(1);
3903 do_nt_login(desthost, myhostname, Client, cnum);
3905 cli_send_logout();
3906 close_sockets();
3909 return(ret);
3911 #endif
3913 if (cli_open_sockets(port))
3915 if (!process(base_directory))
3917 close_sockets();
3918 return(1);
3920 close_sockets();
3922 else
3923 return(1);
3925 return(0);