1/* 2 Unix SMB/Netbios implementation. 3 Version 1.9. 4 SMB client 5 Copyright (C) Andrew Tridgell 1994-1998 6 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. 11 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. 16 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. 20*/ 21 22#define NO_SYSLOG 23 24#include "includes.h" 25 26#ifndef REGISTER 27#define REGISTER 0 28#endif 29 30struct cli_state *cli; 31extern BOOL in_client; 32static int port = SMB_PORT; 33pstring cur_dir = "\\"; 34pstring cd_path = ""; 35static pstring service; 36static pstring desthost; 37extern pstring global_myname; 38static pstring password; 39static pstring username; 40static pstring workgroup; 41static char *cmdstr; 42static BOOL got_pass; 43static int io_bufsize = 65520; 44extern struct in_addr ipzero; 45 46static int name_type = 0x20; 47 48extern pstring user_socket_options; 49 50static int process_tok(fstring tok); 51static void cmd_help(void); 52 53/* 30 second timeout on most commands */ 54#define CLIENT_TIMEOUT (30*1000) 55#define SHORT_TIMEOUT (5*1000) 56 57/* value for unused fid field in trans2 secondary request */ 58#define FID_UNUSED (0xFFFF) 59 60time_t newer_than = 0; 61int archive_level = 0; 62 63extern pstring debugf; 64extern int DEBUGLEVEL; 65 66BOOL translation = False; 67 68static BOOL have_ip; 69 70/* clitar bits insert */ 71extern int blocksize; 72extern BOOL tar_inc; 73extern BOOL tar_reset; 74/* clitar bits end */ 75 76 77mode_t myumask = 0755; 78 79BOOL prompt = True; 80 81int printmode = 1; 82 83static BOOL recurse = False; 84BOOL lowercase = False; 85 86struct in_addr dest_ip; 87 88#define SEPARATORS " \t\n\r" 89 90BOOL abort_mget = True; 91 92pstring fileselection = ""; 93 94extern file_info def_finfo; 95 96/* timing globals */ 97int get_total_size = 0; 98int get_total_time_ms = 0; 99int put_total_size = 0; 100int put_total_time_ms = 0; 101 102/* totals globals */ 103static double dir_total; 104 105#define USENMB 106 107/**************************************************************************** 108write to a local file with CR/LF->LF translation if appropriate. return the 109number taken from the buffer. This may not equal the number written. 110****************************************************************************/ 111static int writefile(int f, char *b, int n) 112{ 113 int i; 114 115 if (!translation) { 116 return write(f,b,n); 117 } 118 119 i = 0; 120 while (i < n) { 121 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') { 122 b++;i++; 123 } 124 if (write(f, b, 1) != 1) { 125 break; 126 } 127 b++; 128 i++; 129 } 130 131 return(i); 132} 133 134/**************************************************************************** 135 read from a file with LF->CR/LF translation if appropriate. return the 136 number read. read approx n bytes. 137****************************************************************************/ 138static int readfile(char *b, int size, int n, FILE *f) 139{ 140 int i; 141 int c; 142 143 if (!translation || (size != 1)) 144 return(fread(b,size,n,f)); 145 146 i = 0; 147 while (i < (n - 1) && (i < BUFFER_SIZE)) { 148 if ((c = getc(f)) == EOF) { 149 break; 150 } 151 152 if (c == '\n') { /* change all LFs to CR/LF */ 153 b[i++] = '\r'; 154 } 155 156 b[i++] = c; 157 } 158 159 return(i); 160} 161 162 163/**************************************************************************** 164send a message 165****************************************************************************/ 166static void send_message(void) 167{ 168 int total_len = 0; 169 int grp_id; 170 171 if (!cli_message_start(cli, desthost, username, &grp_id)) { 172 DEBUG(0,("message start: %s\n", cli_errstr(cli))); 173 return; 174 } 175 176 177 printf("Connected. Type your message, ending it with a Control-D\n"); 178 179 while (!feof(stdin) && total_len < 1600) { 180 int maxlen = MIN(1600 - total_len,127); 181 pstring msg; 182 int l=0; 183 int c; 184 185 ZERO_ARRAY(msg); 186 187 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++) { 188 if (c == '\n') 189 msg[l++] = '\r'; 190 msg[l] = c; 191 } 192 193 /* 194 * The message is in UNIX codepage format. Convert to 195 * DOS before sending. 196 */ 197 198 unix_to_dos(msg, True); 199 200 if (!cli_message_text(cli, msg, l, grp_id)) { 201 printf("SMBsendtxt failed (%s)\n",cli_errstr(cli)); 202 return; 203 } 204 205 total_len += l; 206 } 207 208 if (total_len >= 1600) 209 printf("the message was truncated to 1600 bytes\n"); 210 else 211 printf("sent %d bytes\n",total_len); 212 213 if (!cli_message_end(cli, grp_id)) { 214 printf("SMBsendend failed (%s)\n",cli_errstr(cli)); 215 return; 216 } 217} 218 219 220 221/**************************************************************************** 222check the space on a device 223****************************************************************************/ 224static void do_dskattr(void) 225{ 226 int total, bsize, avail; 227 228 if (!cli_dskattr(cli, &bsize, &total, &avail)) { 229 DEBUG(0,("Error in dskattr: %s\n",cli_errstr(cli))); 230 return; 231 } 232 233 DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n", 234 total, bsize, avail)); 235} 236 237/**************************************************************************** 238show cd/pwd 239****************************************************************************/ 240static void cmd_pwd(void) 241{ 242 DEBUG(0,("Current directory is %s",service)); 243 DEBUG(0,("%s\n",cur_dir)); 244} 245 246 247/**************************************************************************** 248change directory - inner section 249****************************************************************************/ 250static void do_cd(char *newdir) 251{ 252 char *p = newdir; 253 pstring saved_dir; 254 pstring dname; 255 256 dos_format(newdir); 257 258 /* Save the current directory in case the 259 new directory is invalid */ 260 pstrcpy(saved_dir, cur_dir); 261 if (*p == '\\') 262 pstrcpy(cur_dir,p); 263 else 264 pstrcat(cur_dir,p); 265 if (*(cur_dir+strlen(cur_dir)-1) != '\\') { 266 pstrcat(cur_dir, "\\"); 267 } 268 dos_clean_name(cur_dir); 269 pstrcpy(dname,cur_dir); 270 pstrcat(cur_dir,"\\"); 271 dos_clean_name(cur_dir); 272 273 if (!strequal(cur_dir,"\\")) { 274 if (!cli_chkpath(cli, dname)) { 275 DEBUG(0,("cd %s: %s\n", dname, cli_errstr(cli))); 276 pstrcpy(cur_dir,saved_dir); 277 } 278 } 279 280 pstrcpy(cd_path,cur_dir); 281} 282 283/**************************************************************************** 284change directory 285****************************************************************************/ 286static void cmd_cd(void) 287{ 288 fstring buf; 289 290 if (next_token(NULL,buf,NULL,sizeof(buf))) 291 do_cd(buf); 292 else 293 DEBUG(0,("Current directory is %s\n",cur_dir)); 294} 295 296 297/******************************************************************* 298 decide if a file should be operated on 299 ********************************************************************/ 300static BOOL do_this_one(file_info *finfo) 301{ 302 if (finfo->mode & aDIR) return(True); 303 304 if (*fileselection && 305 !mask_match(finfo->name,fileselection,False,False)) { 306 DEBUG(3,("match_match %s failed\n", finfo->name)); 307 return False; 308 } 309 310 if (newer_than && finfo->mtime < newer_than) { 311 DEBUG(3,("newer_than %s failed\n", finfo->name)); 312 return(False); 313 } 314 315 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH)) { 316 DEBUG(3,("archive %s failed\n", finfo->name)); 317 return(False); 318 } 319 320 return(True); 321} 322 323/**************************************************************************** 324 display info about a file 325 ****************************************************************************/ 326static void display_finfo(file_info *finfo) 327{ 328 if (do_this_one(finfo)) { 329 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */ 330 DEBUG(0,(" %-30s%7.7s %8.0f %s", 331 finfo->name, 332 attrib_string(finfo->mode), 333 (double)finfo->size, 334 asctime(LocalTime(&t)))); 335 dir_total += finfo->size; 336 } 337} 338 339 340/**************************************************************************** 341 accumulate size of a file 342 ****************************************************************************/ 343static void do_du(file_info *finfo) 344{ 345 if (do_this_one(finfo)) { 346 dir_total += finfo->size; 347 } 348} 349 350static BOOL do_list_recurse; 351static BOOL do_list_dirs; 352static char *do_list_queue = 0; 353static long do_list_queue_size = 0; 354static long do_list_queue_start = 0; 355static long do_list_queue_end = 0; 356static void (*do_list_fn)(file_info *); 357 358/**************************************************************************** 359functions for do_list_queue 360 ****************************************************************************/ 361 362/* 363 * The do_list_queue is a NUL-separated list of strings stored in a 364 * char*. Since this is a FIFO, we keep track of the beginning and 365 * ending locations of the data in the queue. When we overflow, we 366 * double the size of the char*. When the start of the data passes 367 * the midpoint, we move everything back. This is logically more 368 * complex than a linked list, but easier from a memory management 369 * angle. In any memory error condition, do_list_queue is reset. 370 * Functions check to ensure that do_list_queue is non-NULL before 371 * accessing it. 372 */ 373static void reset_do_list_queue(void) 374{ 375 if (do_list_queue) 376 { 377 free(do_list_queue); 378 } 379 do_list_queue = 0; 380 do_list_queue_size = 0; 381 do_list_queue_start = 0; 382 do_list_queue_end = 0; 383} 384 385static void init_do_list_queue(void) 386{ 387 reset_do_list_queue(); 388 do_list_queue_size = 1024; 389 do_list_queue = malloc(do_list_queue_size); 390 if (do_list_queue == 0) { 391 DEBUG(0,("malloc fail for size %d\n", 392 (int)do_list_queue_size)); 393 reset_do_list_queue(); 394 } else { 395 memset(do_list_queue, 0, do_list_queue_size); 396 } 397} 398 399static void adjust_do_list_queue(void) 400{ 401 /* 402 * If the starting point of the queue is more than half way through, 403 * move everything toward the beginning. 404 */ 405 if (do_list_queue && (do_list_queue_start == do_list_queue_end)) 406 { 407 DEBUG(4,("do_list_queue is empty\n")); 408 do_list_queue_start = do_list_queue_end = 0; 409 *do_list_queue = '\0'; 410 } 411 else if (do_list_queue_start > (do_list_queue_size / 2)) 412 { 413 DEBUG(4,("sliding do_list_queue backward\n")); 414 memmove(do_list_queue, 415 do_list_queue + do_list_queue_start, 416 do_list_queue_end - do_list_queue_start); 417 do_list_queue_end -= do_list_queue_start; 418 do_list_queue_start = 0; 419 } 420 421} 422 423static void add_to_do_list_queue(const char* entry) 424{ 425 long new_end = do_list_queue_end + ((long)strlen(entry)) + 1; 426 while (new_end > do_list_queue_size) 427 { 428 do_list_queue_size *= 2; 429 DEBUG(4,("enlarging do_list_queue to %d\n", 430 (int)do_list_queue_size)); 431 do_list_queue = Realloc(do_list_queue, do_list_queue_size); 432 if (! do_list_queue) { 433 DEBUG(0,("failure enlarging do_list_queue to %d bytes\n", 434 (int)do_list_queue_size)); 435 reset_do_list_queue(); 436 } 437 else 438 { 439 memset(do_list_queue + do_list_queue_size / 2, 440 0, do_list_queue_size / 2); 441 } 442 } 443 if (do_list_queue) 444 { 445 pstrcpy(do_list_queue + do_list_queue_end, entry); 446 do_list_queue_end = new_end; 447 DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n", 448 entry, (int)do_list_queue_start, (int)do_list_queue_end)); 449 } 450} 451 452static char *do_list_queue_head(void) 453{ 454 return do_list_queue + do_list_queue_start; 455} 456 457static void remove_do_list_queue_head(void) 458{ 459 if (do_list_queue_end > do_list_queue_start) 460 { 461 do_list_queue_start += strlen(do_list_queue_head()) + 1; 462 adjust_do_list_queue(); 463 DEBUG(4,("removed head of do_list_queue (start=%d, end=%d)\n", 464 (int)do_list_queue_start, (int)do_list_queue_end)); 465 } 466} 467 468static int do_list_queue_empty(void) 469{ 470 return (! (do_list_queue && *do_list_queue)); 471} 472 473/**************************************************************************** 474a helper for do_list 475 ****************************************************************************/ 476static void do_list_helper(file_info *f, const char *mask) 477{ 478 if (f->mode & aDIR) { 479 if (do_list_dirs && do_this_one(f)) { 480 do_list_fn(f); 481 } 482 if (do_list_recurse && 483 !strequal(f->name,".") && 484 !strequal(f->name,"..")) { 485 pstring mask2; 486 char *p; 487 488 pstrcpy(mask2, mask); 489 p = strrchr(mask2,'\\'); 490 if (!p) return; 491 p[1] = 0; 492 pstrcat(mask2, f->name); 493 pstrcat(mask2,"\\*"); 494 add_to_do_list_queue(mask2); 495 } 496 return; 497 } 498 499 if (do_this_one(f)) { 500 do_list_fn(f); 501 } 502} 503 504 505/**************************************************************************** 506a wrapper around cli_list that adds recursion 507 ****************************************************************************/ 508void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec, BOOL dirs) 509{ 510 static int in_do_list = 0; 511 512 if (in_do_list && rec) 513 { 514 fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n"); 515 exit(1); 516 } 517 518 in_do_list = 1; 519 520 do_list_recurse = rec; 521 do_list_dirs = dirs; 522 do_list_fn = fn; 523 524 if (rec) 525 { 526 init_do_list_queue(); 527 add_to_do_list_queue(mask); 528 529 while (! do_list_queue_empty()) 530 { 531 /* 532 * Need to copy head so that it doesn't become 533 * invalid inside the call to cli_list. This 534 * would happen if the list were expanded 535 * during the call. 536 * Fix from E. Jay Berkenbilt (ejb@ql.org) 537 */ 538 pstring head; 539 pstrcpy(head, do_list_queue_head()); 540 cli_list(cli, head, attribute, do_list_helper); 541 remove_do_list_queue_head(); 542 if ((! do_list_queue_empty()) && (fn == display_finfo)) 543 { 544 char* next_file = do_list_queue_head(); 545 char* save_ch = 0; 546 if ((strlen(next_file) >= 2) && 547 (next_file[strlen(next_file) - 1] == '*') && 548 (next_file[strlen(next_file) - 2] == '\\')) 549 { 550 save_ch = next_file + 551 strlen(next_file) - 2; 552 *save_ch = '\0'; 553 } 554 DEBUG(0,("\n%s\n",next_file)); 555 if (save_ch) 556 { 557 *save_ch = '\\'; 558 } 559 } 560 } 561 } 562 else 563 { 564 if (cli_list(cli, mask, attribute, do_list_helper) == -1) 565 { 566 DEBUG(0, ("%s listing %s\n", cli_errstr(cli), mask)); 567 } 568 } 569 570 in_do_list = 0; 571 reset_do_list_queue(); 572} 573 574/**************************************************************************** 575 get a directory listing 576 ****************************************************************************/ 577static void cmd_dir(void) 578{ 579 uint16 attribute = aDIR | aSYSTEM | aHIDDEN; 580 pstring mask; 581 fstring buf; 582 char *p=buf; 583 584 dir_total = 0; 585 pstrcpy(mask,cur_dir); 586 if(mask[strlen(mask)-1]!='\\') 587 pstrcat(mask,"\\"); 588 589 if (next_token(NULL,buf,NULL,sizeof(buf))) { 590 dos_format(p); 591 if (*p == '\\') 592 pstrcpy(mask,p); 593 else 594 pstrcat(mask,p); 595 } 596 else { 597 pstrcat(mask,"*"); 598 } 599 600 do_list(mask, attribute, display_finfo, recurse, True); 601 602 do_dskattr(); 603 604 DEBUG(3, ("Total bytes listed: %.0f\n", dir_total)); 605} 606 607 608/**************************************************************************** 609 get a directory listing 610 ****************************************************************************/ 611static void cmd_du(void) 612{ 613 uint16 attribute = aDIR | aSYSTEM | aHIDDEN; 614 pstring mask; 615 fstring buf; 616 char *p=buf; 617 618 dir_total = 0; 619 pstrcpy(mask,cur_dir); 620 if(mask[strlen(mask)-1]!='\\') 621 pstrcat(mask,"\\"); 622 623 if (next_token(NULL,buf,NULL,sizeof(buf))) { 624 dos_format(p); 625 if (*p == '\\') 626 pstrcpy(mask,p); 627 else 628 pstrcat(mask,p); 629 } else { 630 pstrcat(mask,"*"); 631 } 632 633 do_list(mask, attribute, do_du, recurse, True); 634 635 do_dskattr(); 636 637 DEBUG(0, ("Total number of bytes: %.0f\n", dir_total)); 638} 639 640 641/**************************************************************************** 642 get a file from rname to lname 643 ****************************************************************************/ 644static void do_get(char *rname,char *lname) 645{ 646 int handle=0,fnum; 647 BOOL newhandle = False; 648 char *data; 649 struct timeval tp_start; 650 int read_size = io_bufsize; 651 uint16 attr; 652 size_t size; 653 off_t nread = 0; 654 655 GetTimeOfDay(&tp_start); 656 657 if (lowercase) { 658 strlower(lname); 659 } 660 661 fnum = cli_open(cli, rname, O_RDONLY, DENY_NONE); 662 663 if (fnum == -1) { 664 DEBUG(0,("%s opening remote file %s\n",cli_errstr(cli),rname)); 665 return; 666 } 667 668 if(!strcmp(lname,"-")) { 669 handle = fileno(stdout); 670 } else { 671 handle = sys_open(lname,O_WRONLY|O_CREAT|O_TRUNC,0644); 672 newhandle = True; 673 } 674 if (handle < 0) { 675 DEBUG(0,("Error opening local file %s\n",lname)); 676 return; 677 } 678 679 680 if (!cli_qfileinfo(cli, fnum, 681 &attr, &size, NULL, NULL, NULL, NULL, NULL) && 682 !cli_getattrE(cli, fnum, 683 &attr, &size, NULL, NULL, NULL)) { 684 DEBUG(0,("getattrib: %s\n",cli_errstr(cli))); 685 return; 686 } 687 688 DEBUG(2,("getting file %s of size %.0f as %s ", 689 lname, (double)size, lname)); 690 691 if(!(data = (char *)malloc(read_size))) { 692 DEBUG(0,("malloc fail for size %d\n", read_size)); 693 cli_close(cli, fnum); 694 return; 695 } 696 697 while (1) { 698 int n = cli_read(cli, fnum, data, nread, read_size); 699 700 if (n <= 0) break; 701 702 if (writefile(handle,data, n) != n) { 703 DEBUG(0,("Error writing local file\n")); 704 break; 705 } 706 707 nread += n; 708 } 709 710 if (nread < size) { 711 DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n", 712 rname, (long)nread)); 713 } 714 715 free(data); 716 717 if (!cli_close(cli, fnum)) { 718 DEBUG(0,("Error %s closing remote file\n",cli_errstr(cli))); 719 } 720 721 if (newhandle) { 722 close(handle); 723 } 724 725 if (archive_level >= 2 && (attr & aARCH)) { 726 cli_setatr(cli, rname, attr & ~(uint16)aARCH, 0); 727 } 728 729 { 730 struct timeval tp_end; 731 int this_time; 732 733 GetTimeOfDay(&tp_end); 734 this_time = 735 (tp_end.tv_sec - tp_start.tv_sec)*1000 + 736 (tp_end.tv_usec - tp_start.tv_usec)/1000; 737 get_total_time_ms += this_time; 738 get_total_size += nread; 739 740 DEBUG(2,("(%g kb/s) (average %g kb/s)\n", 741 nread / (1.024*this_time + 1.0e-4), 742 get_total_size / (1.024*get_total_time_ms))); 743 } 744} 745 746 747/**************************************************************************** 748 get a file 749 ****************************************************************************/ 750static void cmd_get(void) 751{ 752 pstring lname; 753 pstring rname; 754 char *p; 755 756 pstrcpy(rname,cur_dir); 757 pstrcat(rname,"\\"); 758 759 p = rname + strlen(rname); 760 761 if (!next_token(NULL,p,NULL,sizeof(rname)-strlen(rname))) { 762 DEBUG(0,("get <filename>\n")); 763 return; 764 } 765 pstrcpy(lname,p); 766 dos_clean_name(rname); 767 768 next_token(NULL,lname,NULL,sizeof(lname)); 769 770 do_get(rname, lname); 771} 772 773 774/**************************************************************************** 775 do a mget operation on one file 776 ****************************************************************************/ 777static void do_mget(file_info *finfo) 778{ 779 pstring rname; 780 pstring quest; 781 pstring saved_curdir; 782 pstring mget_mask; 783 784 if (strequal(finfo->name,".") || strequal(finfo->name,"..")) 785 return; 786 787 if (abort_mget) { 788 DEBUG(0,("mget aborted\n")); 789 return; 790 } 791 792 if (finfo->mode & aDIR) 793 slprintf(quest,sizeof(pstring)-1, 794 "Get directory %s? ",finfo->name); 795 else 796 slprintf(quest,sizeof(pstring)-1, 797 "Get file %s? ",finfo->name); 798 799 if (prompt && !yesno(quest)) return; 800 801 if (!(finfo->mode & aDIR)) { 802 pstrcpy(rname,cur_dir); 803 pstrcat(rname,finfo->name); 804 do_get(rname,finfo->name); 805 return; 806 } 807 808 /* handle directories */ 809 pstrcpy(saved_curdir,cur_dir); 810 811 pstrcat(cur_dir,finfo->name); 812 pstrcat(cur_dir,"\\"); 813 814 unix_format(finfo->name); 815 if (lowercase) 816 strlower(finfo->name); 817 818 if (!directory_exist(finfo->name,NULL) && 819 mkdir(finfo->name,0777) != 0) { 820 DEBUG(0,("failed to create directory %s\n",finfo->name)); 821 pstrcpy(cur_dir,saved_curdir); 822 return; 823 } 824 825 if (chdir(finfo->name) != 0) { 826 DEBUG(0,("failed to chdir to directory %s\n",finfo->name)); 827 pstrcpy(cur_dir,saved_curdir); 828 return; 829 } 830 831 pstrcpy(mget_mask,cur_dir); 832 pstrcat(mget_mask,"*"); 833 834 do_list(mget_mask, aSYSTEM | aHIDDEN | aDIR,do_mget,False, True); 835 chdir(".."); 836 pstrcpy(cur_dir,saved_curdir); 837} 838 839 840/**************************************************************************** 841view the file using the pager 842****************************************************************************/ 843static void cmd_more(void) 844{ 845 fstring rname,lname,pager_cmd; 846 char *pager; 847 int fd; 848 849 fstrcpy(rname,cur_dir); 850 fstrcat(rname,"\\"); 851 852 slprintf(lname,sizeof(lname)-1, "%s/smbmore.XXXXXX",tmpdir()); 853 fd = smb_mkstemp(lname); 854 if (fd == -1) { 855 DEBUG(0,("failed to create temporary file for more\n")); 856 return; 857 } 858 close(fd); 859 860 if (!next_token(NULL,rname+strlen(rname),NULL,sizeof(rname)-strlen(rname))) { 861 DEBUG(0,("more <filename>\n")); 862 unlink(lname); 863 return; 864 } 865 dos_clean_name(rname); 866 867 do_get(rname,lname); 868 869 pager=getenv("PAGER"); 870 871 slprintf(pager_cmd,sizeof(pager_cmd)-1, 872 "%s %s",(pager? pager:PAGER), lname); 873 system(pager_cmd); 874 unlink(lname); 875} 876 877 878 879/**************************************************************************** 880do a mget command 881****************************************************************************/ 882static void cmd_mget(void) 883{ 884 uint16 attribute = aSYSTEM | aHIDDEN; 885 pstring mget_mask; 886 fstring buf; 887 char *p=buf; 888 889 *mget_mask = 0; 890 891 if (recurse) 892 attribute |= aDIR; 893 894 abort_mget = False; 895 896 while (next_token(NULL,p,NULL,sizeof(buf))) { 897 pstrcpy(mget_mask,cur_dir); 898 if(mget_mask[strlen(mget_mask)-1]!='\\') 899 pstrcat(mget_mask,"\\"); 900 901 if (*p == '\\') 902 pstrcpy(mget_mask,p); 903 else 904 pstrcat(mget_mask,p); 905 do_list(mget_mask, attribute,do_mget,False,True); 906 } 907 908 if (!*mget_mask) { 909 pstrcpy(mget_mask,cur_dir); 910 if(mget_mask[strlen(mget_mask)-1]!='\\') 911 pstrcat(mget_mask,"\\"); 912 pstrcat(mget_mask,"*"); 913 do_list(mget_mask, attribute,do_mget,False,True); 914 } 915} 916 917 918/**************************************************************************** 919make a directory of name "name" 920****************************************************************************/ 921static BOOL do_mkdir(char *name) 922{ 923 if (!cli_mkdir(cli, name)) { 924 DEBUG(0,("%s making remote directory %s\n", 925 cli_errstr(cli),name)); 926 return(False); 927 } 928 929 return(True); 930} 931 932 933/**************************************************************************** 934 Exit client. 935****************************************************************************/ 936static void cmd_quit(void) 937{ 938 cli_shutdown(cli); 939 exit(0); 940} 941 942 943/**************************************************************************** 944 make a directory 945 ****************************************************************************/ 946static void cmd_mkdir(void) 947{ 948 pstring mask; 949 fstring buf; 950 char *p=buf; 951 952 pstrcpy(mask,cur_dir); 953 954 if (!next_token(NULL,p,NULL,sizeof(buf))) { 955 if (!recurse) 956 DEBUG(0,("mkdir <dirname>\n")); 957 return; 958 } 959 pstrcat(mask,p); 960 961 if (recurse) { 962 pstring ddir; 963 pstring ddir2; 964 *ddir2 = 0; 965 966 pstrcpy(ddir,mask); 967 trim_string(ddir,".",NULL); 968 p = strtok(ddir,"/\\"); 969 while (p) { 970 pstrcat(ddir2,p); 971 if (!cli_chkpath(cli, ddir2)) { 972 do_mkdir(ddir2); 973 } 974 pstrcat(ddir2,"\\"); 975 p = strtok(NULL,"/\\"); 976 } 977 } else { 978 do_mkdir(mask); 979 } 980} 981 982 983/**************************************************************************** 984 put a single file 985 ****************************************************************************/ 986static void do_put(char *rname,char *lname) 987{ 988 int fnum; 989 FILE *f; 990 int nread=0; 991 char *buf=NULL; 992 int maxwrite=io_bufsize; 993 994 struct timeval tp_start; 995 GetTimeOfDay(&tp_start); 996 997 fnum = cli_open(cli, rname, O_WRONLY|O_CREAT|O_TRUNC, DENY_NONE); 998 999 if (fnum == -1) { 1000 DEBUG(0,("%s opening remote file %s\n",cli_errstr(cli),rname)); 1001 return; 1002 } 1003 1004 /* allow files to be piped into smbclient 1005 jdblair 24.jun.98 */ 1006 if (!strcmp(lname, "-")) { 1007 f = stdin; 1008 /* size of file is not known */ 1009 } else { 1010 f = sys_fopen(lname,"r"); 1011 } 1012 1013 if (!f) { 1014 DEBUG(0,("Error opening local file %s\n",lname)); 1015 return; 1016 } 1017 1018 1019 DEBUG(1,("putting file %s as %s ",lname, 1020 rname)); 1021 1022 buf = (char *)malloc(maxwrite); 1023 while (!feof(f)) { 1024 int n = maxwrite; 1025 int ret; 1026 1027 if ((n = readfile(buf,1,n,f)) < 1) { 1028 if((n == 0) && feof(f)) 1029 break; /* Empty local file. */ 1030 1031 DEBUG(0,("Error reading local file: %s\n", strerror(errno) )); 1032 break; 1033 } 1034 1035 ret = cli_write(cli, fnum, 0, buf, nread, n); 1036 1037 if (n != ret) { 1038 DEBUG(0,("Error writing file: %s\n", cli_errstr(cli))); 1039 break; 1040 } 1041 1042 nread += n; 1043 } 1044 1045 if (!cli_close(cli, fnum)) { 1046 DEBUG(0,("%s closing remote file %s\n",cli_errstr(cli),rname)); 1047 fclose(f); 1048 if (buf) free(buf); 1049 return; 1050 } 1051 1052 1053 fclose(f); 1054 if (buf) free(buf); 1055 1056 { 1057 struct timeval tp_end; 1058 int this_time; 1059 1060 GetTimeOfDay(&tp_end); 1061 this_time = 1062 (tp_end.tv_sec - tp_start.tv_sec)*1000 + 1063 (tp_end.tv_usec - tp_start.tv_usec)/1000; 1064 put_total_time_ms += this_time; 1065 put_total_size += nread; 1066 1067 DEBUG(1,("(%g kb/s) (average %g kb/s)\n", 1068 nread / (1.024*this_time + 1.0e-4), 1069 put_total_size / (1.024*put_total_time_ms))); 1070 } 1071 1072 if (f == stdin) { 1073 cli_shutdown(cli); 1074 exit(0); 1075 } 1076} 1077 1078 1079 1080/**************************************************************************** 1081 put a file 1082 ****************************************************************************/ 1083static void cmd_put(void) 1084{ 1085 pstring lname; 1086 pstring rname; 1087 fstring buf; 1088 char *p=buf; 1089 1090 pstrcpy(rname,cur_dir); 1091 pstrcat(rname,"\\"); 1092 1093 if (!next_token(NULL,p,NULL,sizeof(buf))) { 1094 DEBUG(0,("put <filename>\n")); 1095 return; 1096 } 1097 pstrcpy(lname,p); 1098 1099 if (next_token(NULL,p,NULL,sizeof(buf))) 1100 pstrcat(rname,p); 1101 else 1102 pstrcat(rname,lname); 1103 1104 dos_clean_name(rname); 1105 1106 { 1107 SMB_STRUCT_STAT st; 1108 /* allow '-' to represent stdin 1109 jdblair, 24.jun.98 */ 1110 if (!file_exist(lname,&st) && 1111 (strcmp(lname,"-"))) { 1112 DEBUG(0,("%s does not exist\n",lname)); 1113 return; 1114 } 1115 } 1116 1117 do_put(rname,lname); 1118} 1119 1120 1121/**************************************************************************** 1122 seek in a directory/file list until you get something that doesn't start with 1123 the specified name 1124 ****************************************************************************/ 1125static BOOL seek_list(FILE *f,char *name) 1126{ 1127 pstring s; 1128 while (!feof(f)) { 1129 if (!fgets(s,sizeof(s),f)) return(False); 1130 trim_string(s,"./","\n"); 1131 if (strncmp(s,name,strlen(name)) != 0) { 1132 pstrcpy(name,s); 1133 return(True); 1134 } 1135 } 1136 1137 return(False); 1138} 1139 1140 1141/**************************************************************************** 1142 set the file selection mask 1143 ****************************************************************************/ 1144static void cmd_select(void) 1145{ 1146 pstrcpy(fileselection,""); 1147 next_token(NULL,fileselection,NULL,sizeof(fileselection)); 1148} 1149 1150 1151/**************************************************************************** 1152 mput some files 1153 ****************************************************************************/ 1154static void cmd_mput(void) 1155{ 1156 pstring lname; 1157 pstring rname; 1158 fstring buf; 1159 char *p=buf; 1160 1161 while (next_token(NULL,p,NULL,sizeof(buf))) { 1162 SMB_STRUCT_STAT st; 1163 pstring cmd; 1164 pstring tmpname; 1165 FILE *f; 1166 int fd; 1167 1168 slprintf(tmpname,sizeof(tmpname)-1, "%s/ls.smb.XXXXXX", 1169 tmpdir()); 1170 fd = smb_mkstemp(tmpname); 1171 1172 if (fd == -1) { 1173 DEBUG(0,("Failed to create temporary file %s\n", 1174 tmpname)); 1175 continue; 1176 } 1177 1178 if (recurse) 1179 slprintf(cmd,sizeof(pstring)-1, 1180 "find . -name \"%s\" -print > %s",p,tmpname); 1181 else 1182 slprintf(cmd,sizeof(pstring)-1, 1183 "find . -maxdepth 1 -name \"%s\" -print > %s",p,tmpname); 1184 system(cmd); 1185 close(fd); 1186 1187 f = sys_fopen(tmpname,"r"); 1188 if (!f) continue; 1189 unlink(tmpname); 1190 1191 while (!feof(f)) { 1192 pstring quest; 1193 1194 if (!fgets(lname,sizeof(lname),f)) break; 1195 trim_string(lname,"./","\n"); 1196 1197 again1: 1198 1199 /* check if it's a directory */ 1200 if (directory_exist(lname,&st)) { 1201 if (!recurse) continue; 1202 slprintf(quest,sizeof(pstring)-1, 1203 "Put directory %s? ",lname); 1204 if (prompt && !yesno(quest)) { 1205 pstrcat(lname,"/"); 1206 if (!seek_list(f,lname)) 1207 break; 1208 goto again1; 1209 } 1210 1211 pstrcpy(rname,cur_dir); 1212 pstrcat(rname,lname); 1213 dos_format(rname); 1214 if (!cli_chkpath(cli, rname) && !do_mkdir(rname)) { 1215 pstrcat(lname,"/"); 1216 if (!seek_list(f,lname)) 1217 break; 1218 goto again1; 1219 } 1220 continue; 1221 } else { 1222 slprintf(quest,sizeof(quest)-1, 1223 "Put file %s? ",lname); 1224 if (prompt && !yesno(quest)) continue; 1225 1226 pstrcpy(rname,cur_dir); 1227 pstrcat(rname,lname); 1228 } 1229 1230 dos_format(rname); 1231 1232 do_put(rname,lname); 1233 } 1234 fclose(f); 1235 } 1236} 1237 1238 1239/**************************************************************************** 1240 cancel a print job 1241 ****************************************************************************/ 1242static void do_cancel(int job) 1243{ 1244 if (cli_printjob_del(cli, job)) { 1245 printf("Job %d cancelled\n",job); 1246 } else { 1247 printf("Error calcelling job %d : %s\n",job,cli_errstr(cli)); 1248 } 1249} 1250 1251 1252/**************************************************************************** 1253 cancel a print job 1254 ****************************************************************************/ 1255static void cmd_cancel(void) 1256{ 1257 fstring buf; 1258 int job; 1259 1260 if (!next_token(NULL,buf,NULL,sizeof(buf))) { 1261 printf("cancel <jobid> ...\n"); 1262 return; 1263 } 1264 do { 1265 job = atoi(buf); 1266 do_cancel(job); 1267 } while (next_token(NULL,buf,NULL,sizeof(buf))); 1268} 1269 1270 1271/**************************************************************************** 1272 print a file 1273 ****************************************************************************/ 1274static void cmd_print(void) 1275{ 1276 pstring lname; 1277 pstring rname; 1278 char *p; 1279 1280 if (!next_token(NULL,lname,NULL, sizeof(lname))) { 1281 DEBUG(0,("print <filename>\n")); 1282 return; 1283 } 1284 1285 pstrcpy(rname,lname); 1286 p = strrchr(rname,'/'); 1287 if (p) { 1288 slprintf(rname, sizeof(rname)-1, "%s-%d", p+1, (int)getpid()); 1289 } 1290 1291 if (strequal(lname,"-")) { 1292 slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)getpid()); 1293 } 1294 1295 do_put(rname, lname); 1296} 1297 1298 1299/**************************************************************************** 1300 show a print queue entry 1301****************************************************************************/ 1302static void queue_fn(struct print_job_info *p) 1303{ 1304 DEBUG(0,("%-6d %-9d %s\n", (int)p->id, (int)p->size, p->name)); 1305} 1306 1307/**************************************************************************** 1308 show a print queue 1309****************************************************************************/ 1310static void cmd_queue(void) 1311{ 1312 cli_print_queue(cli, queue_fn); 1313} 1314 1315/**************************************************************************** 1316delete some files 1317****************************************************************************/ 1318static void do_del(file_info *finfo) 1319{ 1320 pstring mask; 1321 1322 pstrcpy(mask,cur_dir); 1323 pstrcat(mask,finfo->name); 1324 1325 if (finfo->mode & aDIR) 1326 return; 1327 1328 if (!cli_unlink(cli, mask)) { 1329 DEBUG(0,("%s deleting remote file %s\n",cli_errstr(cli),mask)); 1330 } 1331} 1332 1333/**************************************************************************** 1334delete some files 1335****************************************************************************/ 1336static void cmd_del(void) 1337{ 1338 pstring mask; 1339 fstring buf; 1340 uint16 attribute = aSYSTEM | aHIDDEN; 1341 1342 if (recurse) 1343 attribute |= aDIR; 1344 1345 pstrcpy(mask,cur_dir); 1346 1347 if (!next_token(NULL,buf,NULL,sizeof(buf))) { 1348 DEBUG(0,("del <filename>\n")); 1349 return; 1350 } 1351 pstrcat(mask,buf); 1352 1353 do_list(mask, attribute,do_del,False,False); 1354} 1355 1356/**************************************************************************** 1357****************************************************************************/ 1358static void cmd_open(void) 1359{ 1360 pstring mask; 1361 fstring buf; 1362 1363 pstrcpy(mask,cur_dir); 1364 1365 if (!next_token(NULL,buf,NULL,sizeof(buf))) { 1366 DEBUG(0,("del <filename>\n")); 1367 return; 1368 } 1369 pstrcat(mask,buf); 1370 1371 cli_open(cli, mask, O_RDWR, DENY_ALL); 1372} 1373 1374 1375/**************************************************************************** 1376remove a directory 1377****************************************************************************/ 1378static void cmd_rmdir(void) 1379{ 1380 pstring mask; 1381 fstring buf; 1382 1383 pstrcpy(mask,cur_dir); 1384 1385 if (!next_token(NULL,buf,NULL,sizeof(buf))) { 1386 DEBUG(0,("rmdir <dirname>\n")); 1387 return; 1388 } 1389 pstrcat(mask,buf); 1390 1391 if (!cli_rmdir(cli, mask)) { 1392 DEBUG(0,("%s removing remote directory file %s\n", 1393 cli_errstr(cli),mask)); 1394 } 1395} 1396 1397/**************************************************************************** 1398rename some files 1399****************************************************************************/ 1400static void cmd_rename(void) 1401{ 1402 pstring src,dest; 1403 fstring buf,buf2; 1404 1405 pstrcpy(src,cur_dir); 1406 pstrcpy(dest,cur_dir); 1407 1408 if (!next_token(NULL,buf,NULL,sizeof(buf)) || 1409 !next_token(NULL,buf2,NULL, sizeof(buf2))) { 1410 DEBUG(0,("rename <src> <dest>\n")); 1411 return; 1412 } 1413 1414 pstrcat(src,buf); 1415 pstrcat(dest,buf2); 1416 1417 if (!cli_rename(cli, src, dest)) { 1418 DEBUG(0,("%s renaming files\n",cli_errstr(cli))); 1419 return; 1420 } 1421} 1422 1423 1424/**************************************************************************** 1425toggle the prompt flag 1426****************************************************************************/ 1427static void cmd_prompt(void) 1428{ 1429 prompt = !prompt; 1430 DEBUG(2,("prompting is now %s\n",prompt?"on":"off")); 1431} 1432 1433 1434/**************************************************************************** 1435set the newer than time 1436****************************************************************************/ 1437static void cmd_newer(void) 1438{ 1439 fstring buf; 1440 BOOL ok; 1441 SMB_STRUCT_STAT sbuf; 1442 1443 ok = next_token(NULL,buf,NULL,sizeof(buf)); 1444 if (ok && (sys_stat(buf,&sbuf) == 0)) { 1445 newer_than = sbuf.st_mtime; 1446 DEBUG(1,("Getting files newer than %s", 1447 asctime(LocalTime(&newer_than)))); 1448 } else { 1449 newer_than = 0; 1450 } 1451 1452 if (ok && newer_than == 0) 1453 DEBUG(0,("Error setting newer-than time\n")); 1454} 1455 1456/**************************************************************************** 1457set the archive level 1458****************************************************************************/ 1459static void cmd_archive(void) 1460{ 1461 fstring buf; 1462 1463 if (next_token(NULL,buf,NULL,sizeof(buf))) { 1464 archive_level = atoi(buf); 1465 } else 1466 DEBUG(0,("Archive level is %d\n",archive_level)); 1467} 1468 1469/**************************************************************************** 1470toggle the lowercaseflag 1471****************************************************************************/ 1472static void cmd_lowercase(void) 1473{ 1474 lowercase = !lowercase; 1475 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off")); 1476} 1477 1478 1479 1480 1481/**************************************************************************** 1482toggle the recurse flag 1483****************************************************************************/ 1484static void cmd_recurse(void) 1485{ 1486 recurse = !recurse; 1487 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off")); 1488} 1489 1490/**************************************************************************** 1491toggle the translate flag 1492****************************************************************************/ 1493static void cmd_translate(void) 1494{ 1495 translation = !translation; 1496 DEBUG(2,("CR/LF<->LF and print text translation now %s\n", 1497 translation?"on":"off")); 1498} 1499 1500 1501/**************************************************************************** 1502do a printmode command 1503****************************************************************************/ 1504static void cmd_printmode(void) 1505{ 1506 fstring buf; 1507 fstring mode; 1508 1509 if (next_token(NULL,buf,NULL,sizeof(buf))) { 1510 if (strequal(buf,"text")) { 1511 printmode = 0; 1512 } else { 1513 if (strequal(buf,"graphics")) 1514 printmode = 1; 1515 else 1516 printmode = atoi(buf); 1517 } 1518 } 1519 1520 switch(printmode) 1521 { 1522 case 0: 1523 fstrcpy(mode,"text"); 1524 break; 1525 case 1: 1526 fstrcpy(mode,"graphics"); 1527 break; 1528 default: 1529 slprintf(mode,sizeof(mode)-1,"%d",printmode); 1530 break; 1531 } 1532 1533 DEBUG(2,("the printmode is now %s\n",mode)); 1534} 1535 1536/**************************************************************************** 1537do the lcd command 1538****************************************************************************/ 1539static void cmd_lcd(void) 1540{ 1541 fstring buf; 1542 pstring d; 1543 1544 if (next_token(NULL,buf,NULL,sizeof(buf))) 1545 chdir(buf); 1546 DEBUG(2,("the local directory is now %s\n",sys_getwd(d))); 1547} 1548 1549/**************************************************************************** 1550list a share name 1551****************************************************************************/ 1552static void browse_fn(const char *name, uint32 m, const char *comment) 1553{ 1554 fstring typestr; 1555 1556 *typestr=0; 1557 1558 switch (m) 1559 { 1560 case STYPE_DISKTREE: 1561 fstrcpy(typestr,"Disk"); break; 1562 case STYPE_PRINTQ: 1563 fstrcpy(typestr,"Printer"); break; 1564 case STYPE_DEVICE: 1565 fstrcpy(typestr,"Device"); break; 1566 case STYPE_IPC: 1567 fstrcpy(typestr,"IPC"); break; 1568 } 1569 1570 printf("\t%-15.15s%-10.10s%s\n", 1571 name, typestr,comment); 1572} 1573 1574 1575/**************************************************************************** 1576try and browse available connections on a host 1577****************************************************************************/ 1578static BOOL browse_host(BOOL sort) 1579{ 1580 int ret; 1581 1582 printf("\n\tSharename Type Comment\n"); 1583 printf("\t--------- ---- -------\n"); 1584 1585 if((ret = cli_RNetShareEnum(cli, browse_fn)) == -1) 1586 printf("Error returning browse list: %s\n", cli_errstr(cli)); 1587 1588 return (ret != -1); 1589} 1590 1591/**************************************************************************** 1592list a server name 1593****************************************************************************/ 1594static void server_fn(const char *name, uint32 m, const char *comment) 1595{ 1596 printf("\t%-16.16s %s\n", name, comment); 1597} 1598 1599/**************************************************************************** 1600try and browse available connections on a host 1601****************************************************************************/ 1602static BOOL list_servers(char *wk_grp) 1603{ 1604 if (!cli->server_domain) return False; 1605 1606 printf("\n\tServer Comment\n"); 1607 printf("\t--------- -------\n"); 1608 1609 cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL, server_fn); 1610 1611 printf("\n\tWorkgroup Master\n"); 1612 printf("\t--------- -------\n"); 1613 1614 cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM, server_fn); 1615 return True; 1616} 1617 1618#if defined(HAVE_LIBREADLINE) 1619# if defined(HAVE_READLINE_HISTORY_H) || defined(HAVE_HISTORY_H) 1620/**************************************************************************** 1621history 1622****************************************************************************/ 1623static void cmd_history(void) 1624{ 1625 HIST_ENTRY **hlist; 1626 register int i; 1627 1628 hlist = history_list (); /* Get pointer to history list */ 1629 1630 if (hlist) /* If list not empty */ 1631 { 1632 for (i = 0; hlist[i]; i++) /* then display it */ 1633 DEBUG(0, ("%d: %s\n", i, hlist[i]->line)); 1634 } 1635} 1636# endif 1637#endif 1638 1639/* Some constants for completing filename arguments */ 1640 1641#define COMPL_NONE 0 /* No completions */ 1642#define COMPL_REMOTE 1 /* Complete remote filename */ 1643#define COMPL_LOCAL 2 /* Complete local filename */ 1644 1645/* This defines the commands supported by this client */ 1646struct 1647{ 1648 char *name; 1649 void (*fn)(void); 1650 char *description; 1651 char compl_args[2]; /* Completion argument info */ 1652} commands[] = 1653{ 1654 {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}}, 1655 {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}}, 1656 {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}}, 1657 {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}}, 1658 {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}}, 1659 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}}, 1660 {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}}, 1661 {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}}, 1662 {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}}, 1663 {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}}, 1664 {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}}, 1665 {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}}, 1666 {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}}, 1667 {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}}, 1668 {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}}, 1669 {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}}, 1670 {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}}, 1671 {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}}, 1672 {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}}, 1673 {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}}, 1674 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}}, 1675 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}}, 1676 {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}}, 1677 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}}, 1678 {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}}, 1679 {"printmode",cmd_printmode,"<graphics or text> set the print mode",{COMPL_NONE,COMPL_NONE}}, 1680 {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}}, 1681 {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}}, 1682 {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}}, 1683 {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}}, 1684 {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}}, 1685 {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}}, 1686 {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}}, 1687 {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}}, 1688 {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}}, 1689 {"tarmode",cmd_tarmode, 1690 "<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}}, 1691 {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}}, 1692 {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}}, 1693 {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}}, 1694#ifdef HAVE_LIBREADLINE 1695 {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}}, 1696#endif 1697 {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}}, 1698 {"",NULL,NULL,{COMPL_NONE,COMPL_NONE}} 1699}; 1700 1701 1702/******************************************************************* 1703 lookup a command string in the list of commands, including 1704 abbreviations 1705 ******************************************************************/ 1706static int process_tok(fstring tok) 1707{ 1708 int i = 0, matches = 0; 1709 int cmd=0; 1710 int tok_len = strlen(tok); 1711 1712 while (commands[i].fn != NULL) { 1713 if (strequal(commands[i].name,tok)) { 1714 matches = 1; 1715 cmd = i; 1716 break; 1717 } else if (strnequal(commands[i].name, tok, tok_len)) { 1718 matches++; 1719 cmd = i; 1720 } 1721 i++; 1722 } 1723 1724 if (matches == 0) 1725 return(-1); 1726 else if (matches == 1) 1727 return(cmd); 1728 else 1729 return(-2); 1730} 1731 1732/**************************************************************************** 1733help 1734****************************************************************************/ 1735static void cmd_help(void) 1736{ 1737 int i=0,j; 1738 fstring buf; 1739 1740 if (next_token(NULL,buf,NULL,sizeof(buf))) { 1741 if ((i = process_tok(buf)) >= 0) 1742 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description)); 1743 } else { 1744 while (commands[i].description) { 1745 for (j=0; commands[i].description && (j<5); j++) { 1746 DEBUG(0,("%-15s",commands[i].name)); 1747 i++; 1748 } 1749 DEBUG(0,("\n")); 1750 } 1751 } 1752} 1753 1754#ifndef HAVE_LIBREADLINE 1755/**************************************************************************** 1756wait for keyboard activity, swallowing network packets 1757****************************************************************************/ 1758static void wait_keyboard(void) 1759{ 1760 fd_set fds; 1761 struct timeval timeout; 1762 1763 while (1) { 1764 FD_ZERO(&fds); 1765 FD_SET(cli->fd,&fds); 1766 FD_SET(fileno(stdin),&fds); 1767 1768 timeout.tv_sec = 20; 1769 timeout.tv_usec = 0; 1770 sys_select(MAX(cli->fd,fileno(stdin))+1,&fds,&timeout); 1771 1772 if (FD_ISSET(fileno(stdin),&fds)) 1773 return; 1774 1775 /* We deliberately use receive_smb instead of 1776 client_receive_smb as we want to receive 1777 session keepalives and then drop them here. 1778 */ 1779 if (FD_ISSET(cli->fd,&fds)) 1780 receive_smb(cli->fd,cli->inbuf,0); 1781 1782 cli_chkpath(cli, "\\"); 1783 } 1784} 1785#endif 1786 1787/**************************************************************************** 1788process a -c command string 1789****************************************************************************/ 1790static void process_command_string(char *cmd) 1791{ 1792 pstring line; 1793 char *ptr; 1794 1795 while (cmd[0] != '\0') { 1796 char *p; 1797 fstring tok; 1798 int i; 1799 1800 if ((p = strchr(cmd, ';')) == 0) { 1801 strncpy(line, cmd, 999); 1802 line[1000] = '\0'; 1803 cmd += strlen(cmd); 1804 } else { 1805 if (p - cmd > 999) p = cmd + 999; 1806 strncpy(line, cmd, p - cmd); 1807 line[p - cmd] = '\0'; 1808 cmd = p + 1; 1809 } 1810 1811 /* and get the first part of the command */ 1812 ptr = line; 1813 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue; 1814 1815 if ((i = process_tok(tok)) >= 0) { 1816 commands[i].fn(); 1817 } else if (i == -2) { 1818 DEBUG(0,("%s: command abbreviation ambiguous\n",tok)); 1819 } else { 1820 DEBUG(0,("%s: command not found\n",tok)); 1821 } 1822 } 1823} 1824 1825/**************************************************************************** 1826process commands on stdin 1827****************************************************************************/ 1828static void process_stdin(void) 1829{ 1830 pstring line; 1831 char *ptr; 1832 1833#ifdef HAVE_LIBREADLINE 1834/* Minimal readline support, 29Jun1999, s.xenitellis@rhbnc.ac.uk */ 1835#ifdef PROMPTSIZE 1836#undef PROMPTSIZE 1837#endif 1838#define PROMPTSIZE 2048 1839 char prompt_str[PROMPTSIZE]; /* This holds the buffer "smb: \dir1\> " */ 1840 1841 char *temp; /* Gets the buffer from readline() */ 1842 temp = (char *)NULL; 1843#endif 1844 while (!feof(stdin)) { 1845 fstring tok; 1846 int i; 1847#ifdef HAVE_LIBREADLINE 1848 if ( temp != (char *)NULL ) 1849 { 1850 free( temp ); /* Free memory allocated every time by readline() */ 1851 temp = (char *)NULL; 1852 } 1853 1854 snprintf( prompt_str, PROMPTSIZE - 1, "smb: %s> ", cur_dir ); 1855 1856 temp = readline( prompt_str ); /* We read the line here */ 1857 1858 if ( !temp ) 1859 break; /* EOF occured */ 1860 1861 if ( *temp ) /* If non-empty line, save to history */ 1862 add_history (temp); 1863 1864 strncpy( line, temp, 1023 ); /* Maximum size of (pstring)line. Null is guarranteed. */ 1865#else 1866 /* display a prompt */ 1867 DEBUG(0,("smb: %s> ", cur_dir)); 1868 dbgflush( ); 1869 1870 wait_keyboard(); 1871 1872 /* and get a response */ 1873 if (!fgets(line,1000,stdin)) 1874 break; 1875#endif 1876 1877 /* special case - first char is ! */ 1878 if (*line == '!') { 1879 system(line + 1); 1880 continue; 1881 } 1882 1883 /* and get the first part of the command */ 1884 ptr = line; 1885 if (!next_token(&ptr,tok,NULL,sizeof(tok))) continue; 1886 1887 if ((i = process_tok(tok)) >= 0) { 1888 commands[i].fn(); 1889 } else if (i == -2) { 1890 DEBUG(0,("%s: command abbreviation ambiguous\n",tok)); 1891 } else { 1892 DEBUG(0,("%s: command not found\n",tok)); 1893 } 1894 } 1895} 1896 1897 1898/***************************************************** 1899return a connection to a server 1900*******************************************************/ 1901struct cli_state *do_connect(char *server, char *share) 1902{ 1903 struct cli_state *c; 1904 struct nmb_name called, calling; 1905 char *server_n; 1906 struct in_addr ip; 1907 extern struct in_addr ipzero; 1908 1909 if (*share == '\\') { 1910 server = share+2; 1911 share = strchr(server,'\\'); 1912 if (!share) return NULL; 1913 *share = 0; 1914 share++; 1915 } 1916 1917 server_n = server; 1918 1919 ip = ipzero; 1920 1921 make_nmb_name(&calling, global_myname, 0x0); 1922 make_nmb_name(&called , server, name_type); 1923 1924 again: 1925 ip = ipzero; 1926 if (have_ip) ip = dest_ip; 1927 1928 /* have to open a new connection */ 1929 if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) == 0) || 1930 !cli_connect(c, server_n, &ip)) { 1931 DEBUG(0,("Connection to %s failed\n", server_n)); 1932 return NULL; 1933 } 1934 1935 if (!cli_session_request(c, &calling, &called)) { 1936 char *p; 1937 DEBUG(0,("session request to %s failed (%s)\n", 1938 called.name, cli_errstr(c))); 1939 cli_shutdown(c); 1940 if ((p=strchr(called.name, '.'))) { 1941 *p = 0; 1942 goto again; 1943 } 1944 if (strcmp(called.name, "*SMBSERVER")) { 1945 make_nmb_name(&called , "*SMBSERVER", 0x20); 1946 goto again; 1947 } 1948 return NULL; 1949 } 1950 1951 DEBUG(4,(" session request ok\n")); 1952 1953 if (!cli_negprot(c)) { 1954 DEBUG(0,("protocol negotiation failed\n")); 1955 cli_shutdown(c); 1956 return NULL; 1957 } 1958 1959 if (!got_pass) { 1960 char *pass = getpass("Password: "); 1961 if (pass) { 1962 pstrcpy(password, pass); 1963 } 1964 } 1965 1966 if (!cli_session_setup(c, username, 1967 password, strlen(password), 1968 password, strlen(password), 1969 workgroup)) { 1970 /* if a password was not supplied then try again with a null username */ 1971 if (password[0] || !username[0] || 1972 !cli_session_setup(c, "", "", 0, "", 0, workgroup)) { 1973 DEBUG(0,("session setup failed: %s\n", cli_errstr(c))); 1974 return NULL; 1975 } 1976 DEBUG(0,("Anonymous login successful\n")); 1977 } 1978 1979 /* 1980 * These next two lines are needed to emulate 1981 * old client behaviour for people who have 1982 * scripts based on client output. 1983 * QUESTION ? Do we want to have a 'client compatibility 1984 * mode to turn these on/off ? JRA. 1985 */ 1986 1987 if (*c->server_domain || *c->server_os || *c->server_type) 1988 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n", 1989 c->server_domain,c->server_os,c->server_type)); 1990 1991 DEBUG(4,(" session setup ok\n")); 1992 1993 if (!cli_send_tconX(c, share, "?????", 1994 password, strlen(password)+1)) { 1995 DEBUG(0,("tree connect failed: %s\n", cli_errstr(c))); 1996 cli_shutdown(c); 1997 return NULL; 1998 } 1999 2000 DEBUG(4,(" tconx ok\n")); 2001 2002 return c; 2003} 2004 2005 2006/**************************************************************************** 2007 process commands from the client 2008****************************************************************************/ 2009static BOOL process(char *base_directory) 2010{ 2011 cli = do_connect(desthost, service); 2012 if (!cli) { 2013 return(False); 2014 } 2015 2016 if (*base_directory) do_cd(base_directory); 2017 2018 if (cmdstr) { 2019 process_command_string(cmdstr); 2020 } else { 2021 process_stdin(); 2022 } 2023 2024 cli_shutdown(cli); 2025 return(True); 2026} 2027 2028/**************************************************************************** 2029usage on the program 2030****************************************************************************/ 2031static void usage(char *pname) 2032{ 2033 DEBUG(0,("Usage: %s service <password> [options]", pname)); 2034 2035 DEBUG(0,("\nVersion %s\n",VERSION)); 2036 DEBUG(0,("\t-s smb.conf pathname to smb.conf file\n")); 2037 DEBUG(0,("\t-O socket_options socket options to use\n")); 2038 DEBUG(0,("\t-R name resolve order use these name resolution services only\n")); 2039 DEBUG(0,("\t-M host send a winpopup message to the host\n")); 2040 DEBUG(0,("\t-i scope use this NetBIOS scope\n")); 2041 DEBUG(0,("\t-N don't ask for a password\n")); 2042 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n")); 2043 DEBUG(0,("\t-d debuglevel set the debuglevel\n")); 2044 DEBUG(0,("\t-P connect to service as a printer\n")); 2045 DEBUG(0,("\t-p port connect to the specified port\n")); 2046 DEBUG(0,("\t-l log basename. Basename for log/debug files\n")); 2047 DEBUG(0,("\t-h Print this help message.\n")); 2048 DEBUG(0,("\t-I dest IP use this IP to connect to\n")); 2049 DEBUG(0,("\t-E write messages to stderr instead of stdout\n")); 2050 DEBUG(0,("\t-U username set the network username\n")); 2051 DEBUG(0,("\t-L host get a list of shares available on a host\n")); 2052 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n")); 2053 DEBUG(0,("\t-m max protocol set the max protocol level\n")); 2054 DEBUG(0,("\t-W workgroup set the workgroup name\n")); 2055 DEBUG(0,("\t-T<c|x>IXFqgbNan command line tar\n")); 2056 DEBUG(0,("\t-D directory start from directory\n")); 2057 DEBUG(0,("\t-c command string execute semicolon separated commands\n")); 2058 DEBUG(0,("\t-b xmit/send buffer changes the transmit/send buffer (default: 65520)\n")); 2059 DEBUG(0,("\n")); 2060} 2061 2062 2063/**************************************************************************** 2064get a password from a a file or file descriptor 2065exit on failure 2066****************************************************************************/ 2067static void get_password_file(void) 2068{ 2069 int fd = -1; 2070 char *p; 2071 BOOL close_it = False; 2072 pstring spec; 2073 char pass[128]; 2074 2075 if ((p = getenv("PASSWD_FD")) != NULL) { 2076 pstrcpy(spec, "descriptor "); 2077 pstrcat(spec, p); 2078 sscanf(p, "%d", &fd); 2079 close_it = False; 2080 } else if ((p = getenv("PASSWD_FILE")) != NULL) { 2081 fd = sys_open(p, O_RDONLY, 0); 2082 pstrcpy(spec, p); 2083 if (fd < 0) { 2084 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", 2085 spec, strerror(errno)); 2086 exit(1); 2087 } 2088 close_it = True; 2089 } 2090 2091 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ 2092 p && p - pass < sizeof(pass);) { 2093 switch (read(fd, p, 1)) { 2094 case 1: 2095 if (*p != '\n' && *p != '\0') { 2096 *++p = '\0'; /* advance p, and null-terminate pass */ 2097 break; 2098 } 2099 case 0: 2100 if (p - pass) { 2101 *p = '\0'; /* null-terminate it, just in case... */ 2102 p = NULL; /* then force the loop condition to become false */ 2103 break; 2104 } else { 2105 fprintf(stderr, "Error reading password from file %s: %s\n", 2106 spec, "empty password\n"); 2107 exit(1); 2108 } 2109 2110 default: 2111 fprintf(stderr, "Error reading password from file %s: %s\n", 2112 spec, strerror(errno)); 2113 exit(1); 2114 } 2115 } 2116 pstrcpy(password, pass); 2117 if (close_it) 2118 close(fd); 2119} 2120 2121 2122 2123/**************************************************************************** 2124handle a -L query 2125****************************************************************************/ 2126static int do_host_query(char *query_host) 2127{ 2128 cli = do_connect(query_host, "IPC$"); 2129 if (!cli) 2130 return 1; 2131 2132 browse_host(True); 2133 list_servers(workgroup); 2134 2135 cli_shutdown(cli); 2136 2137 return(0); 2138} 2139 2140 2141/**************************************************************************** 2142handle a tar operation 2143****************************************************************************/ 2144static int do_tar_op(char *base_directory) 2145{ 2146 int ret; 2147 cli = do_connect(desthost, service); 2148 if (!cli) 2149 return 1; 2150 2151 recurse=True; 2152 2153 if (*base_directory) do_cd(base_directory); 2154 2155 ret=process_tar(); 2156 2157 cli_shutdown(cli); 2158 2159 return(ret); 2160} 2161 2162/**************************************************************************** 2163handle a message operation 2164****************************************************************************/ 2165static int do_message_op(void) 2166{ 2167 struct in_addr ip; 2168 struct nmb_name called, calling; 2169 2170 ip = ipzero; 2171 2172 make_nmb_name(&calling, global_myname, 0x0); 2173 make_nmb_name(&called , desthost, name_type); 2174 2175 ip = ipzero; 2176 if (have_ip) ip = dest_ip; 2177 else { 2178 if (!resolve_name( desthost, &ip, name_type )) { 2179 DEBUG(0,("Unable to resolve name %s\n", desthost)); 2180 return 1; 2181 } 2182 } 2183 2184 if (!(cli=cli_initialise(NULL)) || !cli_connect(cli, desthost, &ip)) { 2185 DEBUG(0,("Connection to %s failed\n", desthost)); 2186 return 1; 2187 } 2188 2189 if (!cli_session_request(cli, &calling, &called)) { 2190 DEBUG(0,("session request failed\n")); 2191 cli_shutdown(cli); 2192 return 1; 2193 } 2194 2195 send_message(); 2196 cli_shutdown(cli); 2197 2198 return 0; 2199} 2200 2201 2202/**************************************************************************** 2203 main program 2204****************************************************************************/ 2205 int main(int argc,char *argv[]) 2206{ 2207 fstring base_directory; 2208 char *pname = argv[0]; 2209 int opt; 2210 extern FILE *dbf; 2211 extern char *optarg; 2212 extern int optind; 2213 pstring query_host; 2214 BOOL message = False; 2215 extern char tar_type; 2216 static pstring servicesf = CONFIGFILE; 2217 pstring term_code; 2218 pstring new_name_resolve_order; 2219 char *p; 2220 2221#ifdef KANJI 2222 pstrcpy(term_code, KANJI); 2223#else /* KANJI */ 2224 *term_code = 0; 2225#endif /* KANJI */ 2226 2227 *query_host = 0; 2228 *base_directory = 0; 2229 2230 *new_name_resolve_order = 0; 2231 2232 DEBUGLEVEL = 2; 2233 2234#ifdef HAVE_LIBREADLINE 2235 /* Allow conditional parsing of the ~/.inputrc file. */ 2236 rl_readline_name = "smbclient"; 2237#endif 2238 setup_logging(pname,True); 2239 2240 /* 2241 * If the -E option is given, be careful not to clobber stdout 2242 * before processing the options. 28.Feb.99, richard@hacom.nl. 2243 * Also pre-parse the -s option to get the service file name. 2244 */ 2245 2246 for (opt = 1; opt < argc; opt++) { 2247 if (strcmp(argv[opt], "-E") == 0) 2248 dbf = stderr; 2249 else if(strncmp(argv[opt], "-s", 2) == 0) { 2250 if(argv[opt][2] != '\0') 2251 pstrcpy(servicesf, &argv[opt][2]); 2252 else if(argv[opt+1] != NULL) { 2253 /* 2254 * At least one more arg left. 2255 */ 2256 pstrcpy(servicesf, argv[opt+1]); 2257 } else { 2258 usage(pname); 2259 exit(1); 2260 } 2261 } 2262 } 2263 2264 TimeInit(); 2265 charset_initialise(); 2266 2267 in_client = True; /* Make sure that we tell lp_load we are */ 2268 2269 if (!lp_load(servicesf,True,False,False)) { 2270 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); 2271 } 2272 2273 codepage_initialise(lp_client_code_page()); 2274 2275#ifdef WITH_SSL 2276 sslutil_init(0); 2277#endif 2278 2279 pstrcpy(workgroup,lp_workgroup()); 2280 2281 load_interfaces(); 2282 myumask = umask(0); 2283 umask(myumask); 2284 2285 if (getenv("USER")) { 2286 pstrcpy(username,getenv("USER")); 2287 2288 /* modification to support userid%passwd syntax in the USER var 2289 25.Aug.97, jdblair@uab.edu */ 2290 2291 if ((p=strchr(username,'%'))) { 2292 *p = 0; 2293 pstrcpy(password,p+1); 2294 got_pass = True; 2295 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password)); 2296 } 2297 strupper(username); 2298 } 2299 2300 /* modification to support PASSWD environmental var 2301 25.Aug.97, jdblair@uab.edu */ 2302 if (getenv("PASSWD")) { 2303 pstrcpy(password,getenv("PASSWD")); 2304 got_pass = True; 2305 } 2306 2307 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { 2308 get_password_file(); 2309 got_pass = True; 2310 } 2311 2312 if (*username == 0 && getenv("LOGNAME")) { 2313 pstrcpy(username,getenv("LOGNAME")); 2314 strupper(username); 2315 } 2316 2317 if (*username == 0) { 2318 pstrcpy(username,"GUEST"); 2319 } 2320 2321 if (argc < 2) { 2322 usage(pname); 2323 exit(1); 2324 } 2325 2326 if (*argv[1] != '-') { 2327 pstrcpy(service,argv[1]); 2328 /* Convert any '/' characters in the service name to '\' characters */ 2329 string_replace( service, '/','\\'); 2330 argc--; 2331 argv++; 2332 2333 if (count_chars(service,'\\') < 3) { 2334 usage(pname); 2335 printf("\n%s: Not enough '\\' characters in service\n",service); 2336 exit(1); 2337 } 2338 2339 if (argc > 1 && (*argv[1] != '-')) { 2340 got_pass = True; 2341 pstrcpy(password,argv[1]); 2342 memset(argv[1],'X',strlen(argv[1])); 2343 argc--; 2344 argv++; 2345 } 2346 } 2347 2348 while ((opt = 2349 getopt(argc, argv,"s:O:R:M:i:Nn:d:Pp:l:hI:EU:L:t:m:W:T:D:c:b:")) != EOF) { 2350 switch (opt) { 2351 case 's': 2352 pstrcpy(servicesf, optarg); 2353 break; 2354 case 'O': 2355 pstrcpy(user_socket_options,optarg); 2356 break; 2357 case 'R': 2358 pstrcpy(new_name_resolve_order, optarg); 2359 break; 2360 case 'M': 2361 name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */ 2362 pstrcpy(desthost,optarg); 2363 message = True; 2364 break; 2365 case 'i': 2366 { 2367 extern pstring global_scope; 2368 pstrcpy(global_scope,optarg); 2369 strupper(global_scope); 2370 } 2371 break; 2372 case 'N': 2373 got_pass = True; 2374 break; 2375 case 'n': 2376 pstrcpy(global_myname,optarg); 2377 break; 2378 case 'd': 2379 if (*optarg == 'A') 2380 DEBUGLEVEL = 10000; 2381 else 2382 DEBUGLEVEL = atoi(optarg); 2383 break; 2384 case 'P': 2385 /* not needed anymore */ 2386 break; 2387 case 'p': 2388 port = atoi(optarg); 2389 break; 2390 case 'l': 2391 slprintf(debugf,sizeof(debugf)-1, "%s.client",optarg); 2392 break; 2393 case 'h': 2394 usage(pname); 2395 exit(0); 2396 break; 2397 case 'I': 2398 { 2399 dest_ip = *interpret_addr2(optarg); 2400 if (zero_ip(dest_ip)) 2401 exit(1); 2402 have_ip = True; 2403 } 2404 break; 2405 case 'E': 2406 dbf = stderr; 2407 break; 2408 case 'U': 2409 { 2410 char *lp; 2411 pstrcpy(username,optarg); 2412 if ((lp=strchr(username,'%'))) { 2413 *lp = 0; 2414 pstrcpy(password,lp+1); 2415 got_pass = True; 2416 memset(strchr(optarg,'%')+1,'X',strlen(password)); 2417 } 2418 } 2419 break; 2420 case 'L': 2421 p = optarg; 2422 while(*p == '\\' || *p == '/') 2423 p++; 2424 pstrcpy(query_host,p); 2425 break; 2426 case 't': 2427 pstrcpy(term_code, optarg); 2428 break; 2429 case 'm': 2430 /* no longer supported */ 2431 break; 2432 case 'W': 2433 pstrcpy(workgroup,optarg); 2434 break; 2435 case 'T': 2436 if (!tar_parseargs(argc, argv, optarg, optind)) { 2437 usage(pname); 2438 exit(1); 2439 } 2440 break; 2441 case 'D': 2442 pstrcpy(base_directory,optarg); 2443 break; 2444 case 'c': 2445 cmdstr = optarg; 2446 got_pass = True; 2447 break; 2448 case 'b': 2449 io_bufsize = MAX(1, atoi(optarg)); 2450 break; 2451 default: 2452 usage(pname); 2453 exit(1); 2454 } 2455 } 2456 2457 get_myname((*global_myname)?NULL:global_myname); 2458 2459 if(*new_name_resolve_order) 2460 lp_set_name_resolve_order(new_name_resolve_order); 2461 2462 if (*term_code) 2463 interpret_coding_system(term_code); 2464 2465 if (!tar_type && !*query_host && !*service && !message) { 2466 usage(pname); 2467 exit(1); 2468 } 2469 2470 DEBUG( 3, ( "Client started (version %s).\n", VERSION ) ); 2471 2472 if (tar_type) { 2473 return do_tar_op(base_directory); 2474 } 2475 2476 if ((p=strchr(query_host,'#'))) { 2477 *p = 0; 2478 p++; 2479 sscanf(p, "%x", &name_type); 2480 } 2481 2482 if (*query_host) { 2483 return do_host_query(query_host); 2484 } 2485 2486 if (message) { 2487 return do_message_op(); 2488 } 2489 2490 if (!process(base_directory)) { 2491 return(1); 2492 } 2493 2494 return(0); 2495} 2496