00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "includes.h"
00026 #include "libsmbclient.h"
00027 #include "client/client_proto.h"
00028 #ifndef REGISTER
00029 #define REGISTER 0
00030 #endif
00031
00032 extern BOOL AllowDebugChange;
00033 extern BOOL override_logfile;
00034 extern char tar_type;
00035 extern BOOL in_client;
00036 static int port = 0;
00037 pstring cur_dir = "/";
00038 static pstring service;
00039 static pstring desthost;
00040 static pstring username;
00041 static pstring workgroup;
00042 static pstring calling_name;
00043 static BOOL grepable=False;
00044 static char *cmdstr = NULL;
00045
00046 static int io_bufsize = 64512;
00047
00048 static int name_type = 0x20;
00049 extern int max_protocol;
00050
00051 static int process_tok(pstring tok);
00052 static int cmd_help(void);
00053
00054
00055 #define CLIENT_TIMEOUT (30*1000)
00056 #define SHORT_TIMEOUT (5*1000)
00057
00058
00059 #define FID_UNUSED (0xFFFF)
00060
00061 time_t newer_than = 0;
00062 static int archive_level = 0;
00063
00064 static BOOL translation = False;
00065 static BOOL have_ip;
00066
00067
00068 extern int blocksize;
00069 extern BOOL tar_inc;
00070 extern BOOL tar_reset;
00071
00072
00073
00074 static BOOL prompt = True;
00075
00076 static BOOL recurse = False;
00077 BOOL lowercase = False;
00078
00079 static struct in_addr dest_ip;
00080
00081 #define SEPARATORS " \t\n\r"
00082
00083 static BOOL abort_mget = True;
00084
00085 static pstring fileselection = "";
00086
00087 extern file_info def_finfo;
00088
00089
00090 SMB_BIG_UINT get_total_size = 0;
00091 unsigned int get_total_time_ms = 0;
00092 static SMB_BIG_UINT put_total_size = 0;
00093 static unsigned int put_total_time_ms = 0;
00094
00095
00096 static double dir_total;
00097
00098
00099
00100 struct cli_state *cli;
00101
00102
00103
00104
00105
00106
00107 static void
00108 get_auth_data_fn(const char * pServer, const char * pShare,
00109 char * pWorkgroup, int maxLenWorkgroup,
00110 char * pUsername, int maxLenUsername,
00111 char * pPassword, int maxLenPassword)
00112 {
00113 char temp[sizeof(fstring)];
00114
00115 static char authUsername[sizeof(fstring)];
00116 static char authWorkgroup[sizeof(fstring)];
00117 static char authPassword[sizeof(fstring)];
00118 static char authSet = 0;
00119
00120
00121 if (authSet)
00122 {
00123 strncpy(pWorkgroup, authWorkgroup, maxLenWorkgroup - 1);
00124 strncpy(pUsername, authUsername, maxLenUsername - 1);
00125 strncpy(pPassword, authPassword, maxLenPassword - 1);
00126 }
00127 else
00128 {
00129 d_printf("Workgroup: %s\n", workgroup);
00130 strncpy(pWorkgroup, workgroup, maxLenWorkgroup - 1);
00131 strncpy(authWorkgroup, workgroup, maxLenWorkgroup - 1);
00132
00133 d_printf("Username: %s\n", username);
00134 strncpy(pUsername, username, maxLenUsername - 1);
00135 strncpy(authUsername, username, maxLenUsername - 1);
00136
00137 if (cmdline_auth_info.got_pass)
00138 {
00139 strncpy(pPassword, cmdline_auth_info.password, maxLenPassword - 1);
00140 strncpy(authPassword, cmdline_auth_info.password, maxLenPassword - 1);
00141 }
00142 else
00143 {
00144 char *pass = getpass("Password: ");
00145 if (pass)
00146 fstrcpy(temp, pass);
00147 if (temp[strlen(temp) - 1] == '\n')
00148 {
00149 temp[strlen(temp) - 1] = '\0';
00150 }
00151 if (temp[0] != '\0')
00152 {
00153 strncpy(pPassword, temp, maxLenPassword - 1);
00154 strncpy(authPassword, pPassword, maxLenPassword - 1);
00155 }
00156 }
00157 pstrcpy(cmdline_auth_info.username, authUsername);
00158 pstrcpy(cmdline_auth_info.password, authPassword);
00159 cmdline_auth_info.got_pass = True;
00160 set_global_myworkgroup(authWorkgroup);
00161 cli_cm_set_credentials(&cmdline_auth_info);
00162 authSet = 1;
00163 }
00164 }
00165
00166
00167
00168
00169
00170 fstring *mode_t_string(mode_t mode)
00171 {
00172 static fstring attrstr;
00173
00174 attrstr[0] = 0;
00175
00176 S_ISDIR(mode) ? fstrcat(attrstr, "d") : fstrcat(attrstr, "-");
00177 (mode & S_IRUSR) ? fstrcat(attrstr, "r") : fstrcat(attrstr, "-");
00178 (mode & S_IWUSR) ? fstrcat(attrstr, "w") : fstrcat(attrstr, "-");
00179 (mode & S_IXUSR) ? fstrcat(attrstr, "x") : fstrcat(attrstr, "-");
00180
00181 (mode & S_IRGRP) ? fstrcat(attrstr, "r") : fstrcat(attrstr, "-");
00182 (mode & S_IWGRP) ? fstrcat(attrstr, "w") : fstrcat(attrstr, "-");
00183 (mode & S_IXGRP) ? fstrcat(attrstr, "x") : fstrcat(attrstr, "-");
00184
00185 (mode & S_IROTH) ? fstrcat(attrstr, "r") : fstrcat(attrstr, "-");
00186 (mode & S_IWOTH) ? fstrcat(attrstr, "w") : fstrcat(attrstr, "-");
00187 (mode & S_IXOTH) ? fstrcat(attrstr, "x") : fstrcat(attrstr, "-");
00188
00189
00190 return(&attrstr);
00191 }
00192
00193
00194
00195
00196
00197
00198 static int writefile(int f, char *b, int n)
00199 {
00200 int i;
00201
00202 if (!translation) {
00203 return write(f,b,n);
00204 }
00205
00206 i = 0;
00207 while (i < n) {
00208 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') {
00209 b++;i++;
00210 }
00211 if (write(f, b, 1) != 1) {
00212 break;
00213 }
00214 b++;
00215 i++;
00216 }
00217
00218 return(i);
00219 }
00220
00221
00222
00223
00224
00225
00226 static int readfile(char *b, int n, XFILE *f)
00227 {
00228 int i;
00229 int c;
00230
00231 if (!translation)
00232 return x_fread(b,1,n,f);
00233
00234 i = 0;
00235 while (i < (n - 1) && (i < BUFFER_SIZE)) {
00236 if ((c = x_getc(f)) == EOF) {
00237 break;
00238 }
00239
00240 if (c == '\n') {
00241 b[i++] = '\r';
00242 }
00243
00244 b[i++] = c;
00245 }
00246
00247 return(i);
00248 }
00249
00250
00251
00252
00253
00254 static void send_message(void)
00255 {
00256 int total_len = 0;
00257 int grp_id;
00258
00259 if (!cli_message_start(cli, desthost, username, &grp_id)) {
00260 d_printf("message start: %s\n", cli_errstr(cli));
00261 return;
00262 }
00263
00264
00265 d_printf("Connected. Type your message, ending it with a Control-D\n");
00266
00267 while (!feof(stdin) && total_len < 1600) {
00268 int maxlen = MIN(1600 - total_len,127);
00269 pstring msg;
00270 int l=0;
00271 int c;
00272
00273 ZERO_ARRAY(msg);
00274
00275 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++) {
00276 if (c == '\n')
00277 msg[l++] = '\r';
00278 msg[l] = c;
00279 }
00280
00281 if (!cli_message_text(cli, msg, l, grp_id)) {
00282 d_printf("SMBsendtxt failed (%s)\n",cli_errstr(cli));
00283 return;
00284 }
00285
00286 total_len += l;
00287 }
00288
00289 if (total_len >= 1600)
00290 d_printf("the message was truncated to 1600 bytes\n");
00291 else
00292 d_printf("sent %d bytes\n",total_len);
00293
00294 if (!cli_message_end(cli, grp_id)) {
00295 d_printf("SMBsendend failed (%s)\n",cli_errstr(cli));
00296 return;
00297 }
00298 }
00299
00300
00301
00302
00303
00304 static int do_dskattr(void)
00305 {
00306 int total, bsize, avail;
00307 struct cli_state *targetcli;
00308 pstring targetpath;
00309
00310 if ( !cli_resolve_path( "", cli, cur_dir, &targetcli, targetpath ) ) {
00311 d_printf("Error in dskattr: %s\n", cli_errstr(cli));
00312 return 1;
00313 }
00314
00315 if (!cli_dskattr(targetcli, &bsize, &total, &avail)) {
00316 d_printf("Error in dskattr: %s\n",cli_errstr(targetcli));
00317 return 1;
00318 }
00319
00320 d_printf("\n\t\t%d blocks of size %d. %d blocks available\n",
00321 total, bsize, avail);
00322
00323 return 0;
00324 }
00325
00326
00327
00328
00329
00330 static int cmd_pwd(void)
00331 {
00332 d_printf("Current directory is %s",service);
00333 d_printf("%s\n",cur_dir);
00334 return 0;
00335 }
00336
00337
00338
00339
00340
00341 static int do_cd(char *newdir)
00342 {
00343 char *p = newdir;
00344 pstring saved_dir;
00345 pstring dname;
00346 pstring targetpath;
00347 struct cli_state *targetcli;
00348 SMB_STRUCT_STAT sbuf;
00349 uint32 attributes;
00350 int dh;
00351
00352 unix_format(newdir);
00353
00354
00355 pstrcpy(saved_dir, cur_dir);
00356
00357 pstrcpy(dname, p);
00358
00359 if (*p == '/')
00360 pstrcpy(cur_dir,dname);
00361 else
00362 pstrcat(cur_dir,dname);
00363
00364 if (*(cur_dir+strlen(cur_dir)-1) != '/') {
00365 pstrcat(cur_dir, "/");
00366 }
00367
00368 all_string_sub(cur_dir, "/./", "/", 0);
00369
00370
00371 clean_name(cur_dir);
00372 all_string_sub(cur_dir, "/./", "/", 0);
00373 pstrcpy(targetpath, "smb:");
00374 pstrcat(targetpath, service);
00375 pstrcat(targetpath, cur_dir);
00376 unix_format(targetpath);
00377
00378 dh = smbc_opendir(targetpath);
00379
00380 if (dh < 0)
00381 {
00382 d_printf("%s changing to directory %s\n", strerror(errno), cur_dir);
00383 pstrcpy(cur_dir, saved_dir);
00384 return 1;
00385 }
00386 smbc_closedir(dh);
00387
00388 return 0;
00389 }
00390
00391
00392
00393
00394
00395 static int cmd_cd(void)
00396 {
00397 pstring buf;
00398 int rc = 0;
00399
00400 if (next_token_nr(NULL,buf,NULL,sizeof(buf)))
00401 rc = do_cd(buf);
00402 else
00403 d_printf("Current directory is %s\n",cur_dir);
00404
00405 return rc;
00406 }
00407
00408
00409
00410
00411
00412 static BOOL do_this_one(file_info *finfo)
00413 {
00414 if (finfo->mode & aDIR)
00415 return(True);
00416
00417 if (*fileselection &&
00418 !mask_match(finfo->name,fileselection,False)) {
00419 DEBUG(3,("mask_match %s failed\n", finfo->name));
00420 return False;
00421 }
00422
00423 if (newer_than && finfo->mtime < newer_than) {
00424 DEBUG(3,("newer_than %s failed\n", finfo->name));
00425 return(False);
00426 }
00427
00428 if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH)) {
00429 DEBUG(3,("archive %s failed\n", finfo->name));
00430 return(False);
00431 }
00432
00433 return(True);
00434 }
00435
00436
00437
00438
00439
00440 static void display_finfo(file_info *finfo)
00441 {
00442 if (do_this_one(finfo)) {
00443 time_t t = finfo->mtime;
00444 d_printf(" %-30s%7.7s %8.0f %s",
00445 finfo->name,
00446 attrib_string(finfo->mode),
00447 (double)finfo->size,
00448 time_to_asc(t));
00449 dir_total += finfo->size;
00450 }
00451 }
00452
00453
00454
00455
00456
00457 static void display_stat(char *name, struct stat *st)
00458 {
00459 time_t t = st->st_mtime;
00460 pstring time_str;
00461 pstrcpy(time_str, time_to_asc(t));
00462 time_str[strlen(time_str)-1] = 0;
00463 d_printf("> %-30s", name);
00464 d_printf("%10.10s %8.0f %s\n", *mode_t_string(st->st_mode), (double)st->st_size, time_str);
00465 }
00466
00467
00468
00469
00470
00471 static void do_du(file_info *finfo)
00472 {
00473 if (do_this_one(finfo)) {
00474 dir_total += finfo->size;
00475 }
00476 }
00477
00478 static BOOL do_list_recurse;
00479 static BOOL do_list_dirs;
00480 static char *do_list_queue = 0;
00481 static long do_list_queue_size = 0;
00482 static long do_list_queue_start = 0;
00483 static long do_list_queue_end = 0;
00484 static void (*do_list_fn)(file_info *);
00485 static void (*tool_list_fn)(char *, struct stat *);
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 static void reset_do_list_queue(void)
00504 {
00505 SAFE_FREE(do_list_queue);
00506 do_list_queue_size = 0;
00507 do_list_queue_start = 0;
00508 do_list_queue_end = 0;
00509 }
00510
00511 static void init_do_list_queue(void)
00512 {
00513 reset_do_list_queue();
00514 do_list_queue_size = 1024;
00515 do_list_queue = SMB_MALLOC(do_list_queue_size);
00516 if (do_list_queue == 0) {
00517 d_printf("malloc fail for size %d\n",
00518 (int)do_list_queue_size);
00519 reset_do_list_queue();
00520 } else {
00521 memset(do_list_queue, 0, do_list_queue_size);
00522 }
00523 }
00524
00525 static void adjust_do_list_queue(void)
00526 {
00527
00528
00529
00530
00531
00532 if (do_list_queue == NULL) {
00533 DEBUG(4,("do_list_queue is empty\n"));
00534 do_list_queue_start = do_list_queue_end = 0;
00535 return;
00536 }
00537
00538 if (do_list_queue_start == do_list_queue_end) {
00539 DEBUG(4,("do_list_queue is empty\n"));
00540 do_list_queue_start = do_list_queue_end = 0;
00541 *do_list_queue = '\0';
00542 } else if (do_list_queue_start > (do_list_queue_size / 2)) {
00543 DEBUG(4,("sliding do_list_queue backward\n"));
00544 memmove(do_list_queue,
00545 do_list_queue + do_list_queue_start,
00546 do_list_queue_end - do_list_queue_start);
00547 do_list_queue_end -= do_list_queue_start;
00548 do_list_queue_start = 0;
00549 }
00550 }
00551
00552 static void add_to_do_list_queue(const char* entry)
00553 {
00554 long new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
00555 while (new_end > do_list_queue_size) {
00556 do_list_queue_size *= 2;
00557 DEBUG(4,("enlarging do_list_queue to %d\n",
00558 (int)do_list_queue_size));
00559 do_list_queue = SMB_REALLOC(do_list_queue, do_list_queue_size);
00560 if (!do_list_queue) {
00561 d_printf("failure enlarging do_list_queue to %d bytes\n",
00562 (int)do_list_queue_size);
00563 reset_do_list_queue();
00564 } else {
00565 memset(do_list_queue + do_list_queue_size / 2,
00566 0, do_list_queue_size / 2);
00567 }
00568 }
00569 if (do_list_queue) {
00570 safe_strcpy_base(do_list_queue + do_list_queue_end,
00571 entry, do_list_queue, do_list_queue_size);
00572 do_list_queue_end = new_end;
00573 DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n",
00574 entry, (int)do_list_queue_start, (int)do_list_queue_end));
00575 }
00576 }
00577
00578 static char *do_list_queue_head(void)
00579 {
00580 return do_list_queue + do_list_queue_start;
00581 }
00582
00583 static void remove_do_list_queue_head(void)
00584 {
00585 if (do_list_queue_end > do_list_queue_start) {
00586 do_list_queue_start += strlen(do_list_queue_head()) + 1;
00587 adjust_do_list_queue();
00588 DEBUG(4,("removed head of do_list_queue (start=%d, end=%d)\n",
00589 (int)do_list_queue_start, (int)do_list_queue_end));
00590 }
00591 }
00592
00593 static int do_list_queue_empty(void)
00594 {
00595 return (! (do_list_queue && *do_list_queue));
00596 }
00597
00598
00599
00600
00601
00602 static void tool_list_helper(const char *mntpoint, struct stat *f, const char *mask, void *state)
00603 {
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 }
00623
00624
00625
00626
00627
00628
00629 int tool_list( char *mask,
00630 mode_t mode,
00631 void (*fn)(char *, struct stat *),
00632 BOOL rec,
00633 BOOL dirs)
00634 {
00635 int dh;
00636 pstring dentname;
00637 pstring res;
00638 struct stat stat;
00639 struct smbc_dirent* dent;
00640
00641 pstrcpy(res, "smb:");
00642 pstrcat(res, service);
00643 pstrcat(res, cur_dir);
00644
00645 if ((dh = smbc_opendir(res)) < 1)
00646 {
00647 d_printf("Error: %s opening %s\n", strerror(errno), res);
00648 return 1;
00649 }
00650
00651 while (dent = smbc_readdir(dh))
00652 {
00653 switch(dent->smbc_type)
00654 {
00655 case SMBC_WORKGROUP:
00656 case SMBC_SERVER:
00657 case SMBC_FILE_SHARE:
00658 case SMBC_PRINTER_SHARE:
00659 case SMBC_COMMS_SHARE:
00660 case SMBC_IPC_SHARE:
00661 break;
00662 case SMBC_DIR:
00663 if (!dirs)
00664 break;
00665 case SMBC_FILE:
00666 pstrcpy(dentname, res);
00667 pstrcat(dentname, dent->name);
00668
00669 if (mask_match(dentname, mask, False))
00670 {
00671 if (smbc_stat(dentname, &stat) < 0)
00672 {
00673 d_printf("> %s - stat error: %s\n", dent->name, strerror(errno));
00674 }
00675 else
00676 {
00677 fn(dent->name, &stat);
00678 }
00679 }
00680 break;
00681 case SMBC_LINK:
00682 break;
00683 }
00684 }
00685 smbc_closedir(dh);
00686 }
00687
00688
00689
00690
00691
00692 static void do_list_helper(const char *mntpoint, file_info *f, const char *mask, void *state)
00693 {
00694 if (f->mode & aDIR) {
00695 if (do_list_dirs && do_this_one(f)) {
00696 do_list_fn(f);
00697 }
00698 if (do_list_recurse &&
00699 !strequal(f->name,".") &&
00700 !strequal(f->name,"..")) {
00701 pstring mask2;
00702 char *p;
00703
00704 if (!f->name[0]) {
00705 d_printf("Empty dir name returned. Possible server misconfiguration.\n");
00706 return;
00707 }
00708
00709 pstrcpy(mask2, mntpoint);
00710 pstrcat(mask2, mask);
00711 p = strrchr_m(mask2,'/');
00712 if (!p)
00713 return;
00714 p[1] = 0;
00715 pstrcat(mask2, f->name);
00716 pstrcat(mask2,"/*");
00717 add_to_do_list_queue(mask2);
00718 }
00719 return;
00720 }
00721
00722 if (do_this_one(f)) {
00723 do_list_fn(f);
00724 }
00725 }
00726
00727
00728
00729
00730
00731 void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec, BOOL dirs)
00732 {
00733 static int in_do_list = 0;
00734 struct cli_state *targetcli;
00735 pstring targetpath;
00736
00737 if (in_do_list && rec) {
00738 fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n");
00739 exit(1);
00740 }
00741
00742 in_do_list = 1;
00743
00744 do_list_recurse = rec;
00745 do_list_dirs = dirs;
00746 do_list_fn = fn;
00747
00748 if (rec) {
00749 init_do_list_queue();
00750 add_to_do_list_queue(mask);
00751
00752 while (! do_list_queue_empty()) {
00753
00754
00755
00756
00757
00758
00759
00760 pstring head;
00761 pstrcpy(head, do_list_queue_head());
00762
00763
00764
00765 if ( !cli_resolve_path( "", cli, head, &targetcli, targetpath ) ) {
00766 d_printf("do_list: [%s] %s\n", head, cli_errstr(cli));
00767 remove_do_list_queue_head();
00768 continue;
00769 }
00770
00771 cli_list(targetcli, targetpath, attribute, do_list_helper, NULL);
00772 remove_do_list_queue_head();
00773 if ((! do_list_queue_empty()) && (fn == display_finfo)) {
00774 char* next_file = do_list_queue_head();
00775 char* save_ch = 0;
00776 if ((strlen(next_file) >= 2) &&
00777 (next_file[strlen(next_file) - 1] == '*') &&
00778 (next_file[strlen(next_file) - 2] == '/')) {
00779 save_ch = next_file +
00780 strlen(next_file) - 2;
00781 *save_ch = '\0';
00782 }
00783 d_printf("\n%s\n",next_file);
00784 if (save_ch) {
00785 *save_ch = '/';
00786 }
00787 }
00788 }
00789 } else {
00790
00791
00792 if ( cli_resolve_path( "", cli, mask, &targetcli, targetpath ) ) {
00793 if (cli_list(targetcli, targetpath, attribute, do_list_helper, NULL) == -1)
00794 d_printf("%s listing %s\n", cli_errstr(targetcli), targetpath);
00795 }
00796 else
00797 d_printf("do_list: [%s] %s\n", mask, cli_errstr(cli));
00798
00799 }
00800
00801 in_do_list = 0;
00802 reset_do_list_queue();
00803 }
00804
00805
00806
00807
00808
00809 static int cmd_dir(void)
00810 {
00811 mode_t mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
00812 pstring mask;
00813 pstring buf;
00814 char *p=buf;
00815
00816 pstrcpy(mask, "smb:");
00817 pstrcat(mask, service);
00818 pstrcat(mask, cur_dir);
00819
00820 if (next_token_nr(NULL,buf,NULL,sizeof(buf)))
00821 pstrcat(mask,buf);
00822 else
00823 pstrcat(mask,"*");
00824
00825 tool_list(mask, mode, display_stat, recurse, True);
00826 return 0;
00827 }
00828
00829
00830
00831
00832
00833 static int cmd_du(void)
00834 {
00835 uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
00836 pstring mask;
00837 pstring buf;
00838 char *p=buf;
00839 int rc;
00840
00841 dir_total = 0;
00842 pstrcpy(mask,cur_dir);
00843 if(mask[strlen(mask)-1]!='/')
00844 pstrcat(mask,"/");
00845
00846 if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
00847 dos_format(p);
00848 if (*p == '/')
00849 pstrcpy(mask,p);
00850 else
00851 pstrcat(mask,p);
00852 } else {
00853 pstrcat(mask,"*");
00854 }
00855
00856 do_list(mask, attribute, do_du, recurse, True);
00857
00858 rc = do_dskattr();
00859
00860 d_printf("Total number of bytes: %.0f\n", dir_total);
00861
00862 return rc;
00863 }
00864
00865
00866
00867
00868
00869 static int do_get(char *rname, char *lname, BOOL reget)
00870 {
00871 int handle = 0, fnum;
00872 BOOL newhandle = False;
00873 char *data;
00874 struct timeval tp_start;
00875 int read_size = io_bufsize;
00876
00877 struct stat stat;
00878 off_t start = 0;
00879 off_t nread = 0;
00880 int rc = 0;
00881
00882 if (lowercase) {
00883 strlower_m(lname);
00884 }
00885
00886 GetTimeOfDay(&tp_start);
00887
00888 fnum = smbc_open(rname, O_RDONLY, 0666);
00889 if (fnum < 0)
00890 {
00891 d_printf("%s opening remote file %s\n", strerror(errno), rname);
00892 return 1;
00893 }
00894
00895 if(!strcmp(lname,"-")) {
00896 handle = fileno(stdout);
00897 } else {
00898 if (reget) {
00899 handle = sys_open(lname, O_WRONLY|O_CREAT, 0644);
00900 if (handle >= 0) {
00901 start = sys_lseek(handle, 0, SEEK_END);
00902 if (start == -1) {
00903 smbc_close(fnum);
00904 d_printf("Error seeking local file\n");
00905 return 1;
00906 }
00907 }
00908 } else {
00909 handle = sys_open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
00910 }
00911 newhandle = True;
00912 }
00913 if (handle < 0) {
00914 d_printf("Error opening local file %s\n",lname);
00915 smbc_close(fnum);
00916 return 1;
00917 }
00918
00919 if (smbc_fstat(fnum, &stat) < 0)
00920 {
00921 d_printf("%s trying to stat remote file %s\n", strerror(errno), rname);
00922 if (newhandle)
00923 close(handle);
00924 smbc_close(fnum);
00925 return 1;
00926 }
00927
00928 DEBUG(1,("getting file %s of size %.0f as %s ",
00929 rname, (double)stat.st_size, lname));
00930
00931 if(!(data = (char *)SMB_MALLOC(read_size))) {
00932 d_printf("malloc fail for size %d\n", read_size);
00933 if (newhandle)
00934 close(handle);
00935 smbc_close(fnum);
00936 return 1;
00937 }
00938
00939 if (smbc_lseek(fnum, start, SEEK_SET) < 0)
00940 {
00941 d_printf("%s trying to lseek remote file %s\n", strerror(errno), rname);
00942 if (newhandle)
00943 close(handle);
00944 smbc_close(fnum);
00945 SAFE_FREE(data);
00946 return 1;
00947 }
00948 while (1) {
00949 int n = smbc_read(fnum, data, read_size);
00950
00951 if (n < 0)
00952 {
00953 d_printf("%s while reading remote file %s\n", strerror(errno), rname);
00954 if (newhandle)
00955 close(handle);
00956 smbc_close(fnum);
00957 SAFE_FREE(data);
00958 return 1;
00959 }
00960 if (n == 0)
00961 break;
00962
00963 if (writefile(handle,data, n) != n) {
00964 d_printf("Error writing local file\n");
00965 rc = 1;
00966 break;
00967 }
00968
00969 nread += n;
00970 }
00971
00972 if (nread + start < stat.st_size) {
00973 DEBUG (1, ("Short read when getting file %s. Only got %ld bytes.\n", rname, (long)nread));
00974 rc = 1;
00975 }
00976
00977 SAFE_FREE(data);
00978
00979 if (smbc_close(fnum) < 0)
00980 {
00981 d_printf("%s closing remote file %s\n", strerror(errno), rname);
00982 rc = 1;
00983 }
00984
00985 if (newhandle) {
00986 close(handle);
00987 }
00988
00989
00990
00991
00992
00993 {
00994 struct timeval tp_end;
00995 int this_time;
00996
00997 GetTimeOfDay(&tp_end);
00998 this_time =
00999 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
01000 (tp_end.tv_usec - tp_start.tv_usec)/1000;
01001 get_total_time_ms += this_time;
01002 get_total_size += nread;
01003
01004 DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
01005 nread / (1.024*this_time + 1.0e-4),
01006 get_total_size / (1.024*get_total_time_ms)));
01007 }
01008
01009 return rc;
01010 }
01011
01012
01013
01014
01015
01016 static int cmd_get(void)
01017 {
01018 pstring lname;
01019 pstring rname;
01020 char *p;
01021
01022 pstrcpy(rname, "smb:");
01023 pstrcat(rname, service);
01024 pstrcat(rname, cur_dir);
01025
01026 p = rname + strlen(rname);
01027
01028 if (!next_token_nr(NULL,p,NULL,sizeof(rname)-strlen(rname))) {
01029 d_printf("get <filename>\n");
01030 return 1;
01031 }
01032 pstrcpy(lname,p);
01033
01034 next_token_nr(NULL,lname,NULL,sizeof(lname));
01035
01036 return do_get(rname, lname, False);
01037 }
01038
01039
01040
01041
01042
01043 static void do_mget(char *name, struct stat *st)
01044 {
01045 pstring rname;
01046 pstring quest;
01047 pstring saved_curdir;
01048 pstring mget_mask;
01049 mode_t mode;
01050
01051 if (strequal(name,".") || strequal(name,".."))
01052 return;
01053
01054 if (S_ISDIR(st->st_mode))
01055 slprintf(quest,sizeof(pstring)-1, "Get directory %s%s? ", cur_dir, name);
01056 else
01057 slprintf(quest,sizeof(pstring)-1, "Get file %s%s? ", cur_dir, name);
01058
01059 if (prompt && !yesno(quest))
01060 return;
01061
01062 if (!S_ISDIR(st->st_mode)) {
01063 pstrcpy(rname,"smb:");
01064 pstrcat(rname,service);
01065 pstrcat(rname,cur_dir);
01066 pstrcat(rname,name);
01067 do_get(rname,name, False);
01068 return;
01069 }
01070
01071
01072
01073 pstrcpy(saved_curdir,cur_dir);
01074
01075 pstrcat(cur_dir,name);
01076 pstrcat(cur_dir,"/");
01077
01078 unix_format(name);
01079 if (lowercase)
01080 strlower_m(name);
01081
01082 if (!directory_exist(name,NULL) &&
01083 mkdir(name,0777) != 0) {
01084 d_printf("failed to create directory %s\n",name);
01085 pstrcpy(cur_dir,saved_curdir);
01086 return;
01087 }
01088
01089 if (chdir(name) != 0) {
01090 d_printf("failed to chdir to directory %s\n",name);
01091 pstrcpy(cur_dir,saved_curdir);
01092 return;
01093 }
01094
01095 pstrcpy(mget_mask,"smb:");
01096 pstrcat(mget_mask,service);
01097 pstrcat(mget_mask,cur_dir);
01098 pstrcat(mget_mask,"*");
01099
01100
01101 tool_list(mget_mask, mode, do_mget, recurse, recurse);
01102 chdir("..");
01103 pstrcpy(cur_dir,saved_curdir);
01104 }
01105
01106
01107
01108
01109
01110 static int cmd_more(void)
01111 {
01112 pstring rname,lname,pager_cmd;
01113 char *pager;
01114 int fd;
01115 int rc = 0;
01116
01117 pstrcpy(rname,cur_dir);
01118 pstrcat(rname,"/");
01119
01120 slprintf(lname,sizeof(lname)-1, "%s/smbmore.XXXXXX",tmpdir());
01121 fd = smb_mkstemp(lname);
01122 if (fd == -1) {
01123 d_printf("failed to create temporary file for more\n");
01124 return 1;
01125 }
01126 close(fd);
01127
01128 if (!next_token_nr(NULL,rname+strlen(rname),NULL,sizeof(rname)-strlen(rname))) {
01129 d_printf("more <filename>\n");
01130 unlink(lname);
01131 return 1;
01132 }
01133 clean_name(rname);
01134
01135 rc = do_get(rname, lname, False);
01136
01137 pager=getenv("PAGER");
01138
01139 slprintf(pager_cmd,sizeof(pager_cmd)-1,
01140 "%s %s",(pager? pager:PAGER), lname);
01141 system(pager_cmd);
01142 unlink(lname);
01143
01144 return rc;
01145 }
01146
01147
01148
01149
01150
01151 static int cmd_mget(void)
01152 {
01153 mode_t mode;
01154 pstring mget_mask;
01155 pstring buf;
01156 char *p=buf;
01157
01158 *mget_mask = 0;
01159
01160 while (next_token_nr(NULL,p,NULL,sizeof(buf))) {
01161 pstrcpy(mget_mask, "smb:");
01162 pstrcat(mget_mask, service);
01163 pstrcat(mget_mask,cur_dir);
01164 if(mget_mask[strlen(mget_mask)-1]!='/')
01165 pstrcat(mget_mask,"/");
01166
01167 if (*p == '/')
01168 {
01169 pstrcpy(mget_mask, "smb:");
01170 pstrcat(mget_mask, service);
01171 pstrcat(mget_mask,p);
01172 }
01173 else
01174 pstrcat(mget_mask,p);
01175
01176
01177 tool_list(mget_mask, mode, do_mget, recurse, recurse);
01178 }
01179
01180 if (!*mget_mask) {
01181 pstrcpy(mget_mask, "smb:");
01182 pstrcat(mget_mask, service);
01183 pstrcat(mget_mask,cur_dir);
01184 if(mget_mask[strlen(mget_mask)-1]!='/')
01185 pstrcat(mget_mask,"/");
01186 pstrcat(mget_mask,"*");
01187 tool_list(mget_mask, mode, do_mget, recurse, recurse);
01188 }
01189
01190 return 0;
01191 }
01192
01193
01194
01195
01196
01197 static BOOL do_mkdir(char *name)
01198 {
01199 if (smbc_mkdir(name, 755) < 0)
01200 {
01201 d_printf("Error: %s making remote directory %s\n", strerror(errno), name);
01202 return False;
01203 }
01204
01205 return True;
01206 }
01207
01208
01209
01210
01211
01212 static BOOL do_altname(char *name)
01213 {
01214 pstring altname;
01215 if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
01216 d_printf("%s getting alt name for %s\n",
01217 cli_errstr(cli),name);
01218 return(False);
01219 }
01220 d_printf("%s\n", altname);
01221
01222 return(True);
01223 }
01224
01225
01226
01227
01228
01229 static int cmd_quit(void)
01230 {
01231 cli_cm_shutdown();
01232 exit(0);
01233
01234 return 0;
01235 }
01236
01237
01238
01239
01240
01241 static int cmd_mkdir(void)
01242 {
01243 int dh;
01244 pstring mask;
01245 pstring buf;
01246 pstring targetname;
01247 char *p=buf;
01248
01249 pstrcpy(mask,cur_dir);
01250
01251 if (!next_token_nr(NULL,p,NULL,sizeof(buf))) {
01252 if (!recurse)
01253 d_printf("mkdir <dirname>\n");
01254 return 1;
01255 }
01256 pstrcat(mask,p);
01257
01258 if (recurse) {
01259 pstring ddir;
01260 pstring ddir2;
01261 *ddir2 = 0;
01262
01263 pstrcpy(ddir,mask);
01264 trim_char(ddir,'.','\0');
01265 p = strtok(ddir,"/\\");
01266 while (p) {
01267 pstrcat(ddir2,p);
01268
01269 pstrcpy(targetname, "smb:");
01270 pstrcat(targetname, service);
01271 pstrcat(targetname, "/");
01272 pstrcat(targetname, ddir2);
01273 DEBUG(3, ("Recursively making directory %s\n", targetname));
01274 if ((dh = smbc_opendir(targetname)) < 0) {
01275 if (!do_mkdir(targetname))
01276 return 1;
01277 }
01278 else
01279 smbc_closedir(dh);
01280
01281 pstrcat(ddir2,"/");
01282 p = strtok(NULL,"/\\");
01283 }
01284 }
01285 else {
01286 pstrcpy(targetname, "smb:");
01287 pstrcat(targetname, service);
01288 pstrcat(targetname, mask);
01289
01290 if (!do_mkdir(targetname))
01291 return 1;
01292 }
01293
01294 return 0;
01295 }
01296
01297
01298
01299
01300
01301 static int cmd_altname(void)
01302 {
01303 pstring name;
01304 pstring buf;
01305 char *p=buf;
01306
01307 pstrcpy(name,cur_dir);
01308
01309 if (!next_token_nr(NULL,p,NULL,sizeof(buf))) {
01310 d_printf("altname <file>\n");
01311 return 1;
01312 }
01313 pstrcat(name,p);
01314
01315 do_altname(name);
01316
01317 return 0;
01318 }
01319
01320
01321
01322
01323
01324 static int do_put(char *rname, char *lname, BOOL reput)
01325 {
01326 int fnum;
01327 XFILE *f;
01328 SMB_OFF_T start = 0;
01329 off_t nread = 0;
01330 char *buf = NULL;
01331 int maxwrite = io_bufsize;
01332 int rc = 0;
01333 struct timeval tp_start;
01334 struct stat stat;
01335
01336 GetTimeOfDay(&tp_start);
01337
01338 if (reput) {
01339 fnum = smbc_open(rname, O_RDWR|O_CREAT, 0644);
01340 if (fnum < 0)
01341 {
01342 d_printf("%s opening remote file %s\n", strerror(errno), rname);
01343 return 1;
01344 }
01345 if (smbc_fstat(fnum, &stat) < 0)
01346 {
01347 d_printf("%s trying to stat remote file %s\n", strerror(errno), rname);
01348 smbc_close(fnum);
01349 return 1;
01350 }
01351 start = stat.st_size;
01352 } else {
01353 fnum = smbc_creat(rname, 0644);
01354 if (fnum < 0)
01355 {
01356 d_printf("%s trying to create remote file %s\n", strerror(errno), rname);
01357 return 1;
01358 }
01359 }
01360
01361
01362
01363
01364
01365
01366 if (!strcmp(lname, "-")) {
01367 f = x_stdin;
01368
01369 } else {
01370 f = x_fopen(lname,O_RDONLY, 0);
01371 if (f && reput) {
01372 if (x_tseek(f, start, SEEK_SET) == -1) {
01373 d_printf("Error seeking local file\n");
01374 smbc_close(fnum);
01375 x_fclose(f);
01376 return 1;
01377 }
01378 }
01379 }
01380
01381 if (!f) {
01382 d_printf("Error opening local file %s\n",lname);
01383 smbc_close(fnum);
01384 return 1;
01385 }
01386
01387 DEBUG(1,("putting file %s as %s ",lname,rname));
01388
01389 buf = (char *)SMB_MALLOC(maxwrite);
01390 if (!buf) {
01391 d_printf("ERROR: Not enough memory!\n");
01392 smbc_close(fnum);
01393 if (f != x_stdin)
01394 x_fclose(f);
01395 return 1;
01396 }
01397
01398 if (smbc_lseek(fnum, start, SEEK_SET) < 0)
01399 {
01400 d_printf("%s trying to lseek remote file %s\n", strerror(errno), rname);
01401 if (f != x_stdin)
01402 x_fclose(f);
01403 smbc_close(fnum);
01404 SAFE_FREE(buf);
01405 return 1;
01406 }
01407 while (!x_feof(f)) {
01408 int n = maxwrite;
01409 int ret;
01410
01411 if ((n = readfile(buf,n,f)) < 1) {
01412 if((n == 0) && x_feof(f))
01413 break;
01414
01415 d_printf("Error reading local file: %s\n", strerror(errno));
01416 rc = 1;
01417 break;
01418 }
01419
01420 ret = smbc_write(fnum, buf, n);
01421
01422 if (n != ret) {
01423 d_printf("Error writing file: %s\n", strerror(errno));
01424 rc = 1;
01425 break;
01426 }
01427
01428 nread += n;
01429 }
01430
01431 if (smbc_close(fnum) < 0) {
01432 d_printf("%s closing remote file %s\n",strerror(errno),rname);
01433 if (f != x_stdin)
01434 x_fclose(f);
01435 SAFE_FREE(buf);
01436 return 1;
01437 }
01438
01439
01440 if (f != x_stdin) {
01441 x_fclose(f);
01442 }
01443
01444 SAFE_FREE(buf);
01445
01446 {
01447 struct timeval tp_end;
01448 int this_time;
01449
01450 GetTimeOfDay(&tp_end);
01451 this_time =
01452 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
01453 (tp_end.tv_usec - tp_start.tv_usec)/1000;
01454 put_total_time_ms += this_time;
01455 put_total_size += nread;
01456
01457 DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
01458 nread / (1.024*this_time + 1.0e-4),
01459 put_total_size / (1.024*put_total_time_ms)));
01460 }
01461
01462 if (f == x_stdin) {
01463 cli_cm_shutdown();
01464 exit(0);
01465 }
01466
01467 return rc;
01468 }
01469
01470
01471
01472
01473
01474 static int cmd_put(void)
01475 {
01476 pstring lname;
01477 pstring rname;
01478 pstring buf;
01479 char *p=buf;
01480
01481 pstrcpy(rname, "smb:");
01482 pstrcat(rname, service);
01483 pstrcat(rname, cur_dir);
01484
01485 if (!next_token_nr(NULL,p,NULL,sizeof(buf))) {
01486 d_printf("put <filename>\n");
01487 return 1;
01488 }
01489 pstrcpy(lname,p);
01490
01491 if (next_token_nr(NULL,p,NULL,sizeof(buf)))
01492 pstrcat(rname,p);
01493 else
01494 pstrcat(rname,lname);
01495
01496 {
01497 SMB_STRUCT_STAT st;
01498
01499
01500 if (!file_exist(lname,&st) &&
01501 (strcmp(lname,"-"))) {
01502 d_printf("%s does not exist\n",lname);
01503 return 1;
01504 }
01505 }
01506
01507
01508 return do_put(rname, lname, False);
01509 }
01510
01511
01512
01513
01514
01515 static struct file_list {
01516 struct file_list *prev, *next;
01517 char *file_path;
01518 BOOL isdir;
01519 } *file_list;
01520
01521
01522
01523
01524
01525 static void free_file_list (struct file_list * list)
01526 {
01527 struct file_list *tmp;
01528
01529 while (list) {
01530 tmp = list;
01531 DLIST_REMOVE(list, list);
01532 SAFE_FREE(tmp->file_path);
01533 SAFE_FREE(tmp);
01534 }
01535 }
01536
01537
01538
01539
01540
01541
01542 static BOOL seek_list(struct file_list *list, char *name)
01543 {
01544 while (list) {
01545 trim_string(list->file_path,"./","\n");
01546 if (strncmp(list->file_path, name, strlen(name)) != 0) {
01547 return(True);
01548 }
01549 list = list->next;
01550 }
01551
01552 return(False);
01553 }
01554
01555
01556
01557
01558
01559 static int cmd_select(void)
01560 {
01561 pstrcpy(fileselection,"");
01562 next_token_nr(NULL,fileselection,NULL,sizeof(fileselection));
01563
01564 return 0;
01565 }
01566
01567
01568
01569
01570
01571
01572 static int file_find(struct file_list **list, const char *directory,
01573 const char *expression, BOOL match)
01574 {
01575 DIR *dir;
01576 struct file_list *entry;
01577 struct stat statbuf;
01578 int ret;
01579 char *path;
01580 BOOL isdir;
01581 const char *dname;
01582
01583 dir = opendir(directory);
01584 if (!dir)
01585 return -1;
01586
01587 while ((dname = readdirname(dir))) {
01588 if (!strcmp("..", dname))
01589 continue;
01590 if (!strcmp(".", dname))
01591 continue;
01592
01593 if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
01594 continue;
01595 }
01596
01597 isdir = False;
01598 if (!match || !gen_fnmatch(expression, dname)) {
01599 if (recurse) {
01600 ret = stat(path, &statbuf);
01601 if (ret == 0) {
01602 if (S_ISDIR(statbuf.st_mode)) {
01603 isdir = True;
01604 ret = file_find(list, path, expression, False);
01605 }
01606 } else {
01607 d_printf("file_find: cannot stat file %s\n", path);
01608 }
01609
01610 if (ret == -1) {
01611 SAFE_FREE(path);
01612 closedir(dir);
01613 return -1;
01614 }
01615 }
01616 entry = SMB_MALLOC_P(struct file_list);
01617 if (!entry) {
01618 d_printf("Out of memory in file_find\n");
01619 closedir(dir);
01620 return -1;
01621 }
01622 entry->file_path = path;
01623 entry->isdir = isdir;
01624 DLIST_ADD(*list, entry);
01625 } else {
01626 SAFE_FREE(path);
01627 }
01628 }
01629
01630 closedir(dir);
01631 return 0;
01632 }
01633
01634
01635
01636
01637
01638 static int cmd_mput(void)
01639 {
01640 pstring buf;
01641 char *p=buf;
01642
01643 while (next_token_nr(NULL,p,NULL,sizeof(buf))) {
01644 int ret;
01645 struct file_list *temp_list;
01646 char *quest, *lname, *rname;
01647
01648 file_list = NULL;
01649
01650 ret = file_find(&file_list, ".", p, True);
01651 if (ret) {
01652 free_file_list(file_list);
01653 continue;
01654 }
01655
01656 quest = NULL;
01657 lname = NULL;
01658 rname = NULL;
01659
01660 for (temp_list = file_list; temp_list;
01661 temp_list = temp_list->next) {
01662
01663 SAFE_FREE(lname);
01664 if (asprintf(&lname, "%s/", temp_list->file_path) <= 0)
01665 continue;
01666 trim_string(lname, "./", "/");
01667
01668
01669 if (temp_list->isdir) {
01670
01671
01672 SAFE_FREE(quest);
01673 if (asprintf(&quest, "Put directory %s? ", lname) < 0) break;
01674 if (prompt && !yesno(quest)) {
01675
01676 lname[strlen(lname)-1] = '/';
01677 if (!seek_list(temp_list, lname))
01678 break;
01679 } else {
01680 SAFE_FREE(rname);
01681 if(asprintf(&rname, "smb:%s%s%s", service, cur_dir, lname) < 0) break;
01682
01683
01684
01685
01686
01687
01688
01689
01690 ret = smbc_mkdir(rname, 755);
01691 if ((ret != 0) && (errno != EEXIST))
01692 {
01693 d_printf("Error: %s. Unable to open or create dir %s, skipping...\n", strerror(errno), rname);
01694
01695 lname[strlen(lname)-1] = '/';
01696 if (!seek_list(temp_list, lname))
01697 break;
01698 }
01699 }
01700 continue;
01701 } else {
01702 SAFE_FREE(quest);
01703 if (asprintf(&quest,"Put file %s? ", lname) < 0) break;
01704 if (prompt && !yesno(quest))
01705 continue;
01706
01707
01708 SAFE_FREE(rname);
01709 if (asprintf(&rname, "smb:%s%s%s", service, cur_dir, lname) < 0) break;
01710 }
01711
01712
01713 do_put(rname, lname, False);
01714 }
01715 free_file_list(file_list);
01716 SAFE_FREE(quest);
01717 SAFE_FREE(lname);
01718 SAFE_FREE(rname);
01719 }
01720
01721 return 0;
01722 }
01723
01724
01725
01726
01727
01728 static int do_cancel(int job)
01729 {
01730 if (cli_printjob_del(cli, job)) {
01731 d_printf("Job %d cancelled\n",job);
01732 return 0;
01733 } else {
01734 d_printf("Error cancelling job %d : %s\n",job,cli_errstr(cli));
01735 return 1;
01736 }
01737 }
01738
01739
01740
01741
01742
01743 static int cmd_cancel(void)
01744 {
01745 pstring buf;
01746 int job;
01747
01748 if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01749 d_printf("cancel <jobid> ...\n");
01750 return 1;
01751 }
01752 do {
01753 job = atoi(buf);
01754 do_cancel(job);
01755 } while (next_token_nr(NULL,buf,NULL,sizeof(buf)));
01756
01757 return 0;
01758 }
01759
01760
01761
01762
01763
01764 static int cmd_print(void)
01765 {
01766 pstring lname;
01767 pstring rname;
01768 char *p;
01769
01770 if (!next_token_nr(NULL,lname,NULL, sizeof(lname))) {
01771 d_printf("print <filename>\n");
01772 return 1;
01773 }
01774
01775 pstrcpy(rname,lname);
01776 p = strrchr_m(rname,'/');
01777 if (p) {
01778 slprintf(rname, sizeof(rname)-1, "%s-%d", p+1, (int)sys_getpid());
01779 }
01780
01781 if (strequal(lname,"-")) {
01782 slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)sys_getpid());
01783 }
01784
01785 return do_put(rname, lname, False);
01786 }
01787
01788
01789
01790
01791
01792 static void queue_fn(struct print_job_info *p)
01793 {
01794 d_printf("%-6d %-9d %s\n", (int)p->id, (int)p->size, p->name);
01795 }
01796
01797
01798
01799
01800
01801 static int cmd_queue(void)
01802 {
01803 cli_print_queue(cli, queue_fn);
01804
01805 return 0;
01806 }
01807
01808
01809
01810
01811
01812 static void do_del(file_info *finfo)
01813 {
01814 pstring mask;
01815
01816 pstrcpy(mask,cur_dir);
01817 pstrcat(mask,finfo->name);
01818
01819 if (finfo->mode & aDIR)
01820 return;
01821
01822 if (!cli_unlink(cli, mask)) {
01823 d_printf("%s deleting remote file %s\n",cli_errstr(cli),mask);
01824 }
01825 }
01826
01827
01828
01829
01830
01831 static int cmd_del(void)
01832 {
01833 pstring mask;
01834 pstring buf;
01835 uint16 attribute = aSYSTEM | aHIDDEN;
01836
01837 if (recurse)
01838 attribute |= aDIR;
01839
01840 pstrcpy(mask,cur_dir);
01841
01842 if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01843 d_printf("del <filename>\n");
01844 return 1;
01845 }
01846 pstrcat(mask,buf);
01847
01848 do_list(mask, attribute,do_del,False,False);
01849
01850 return 0;
01851 }
01852
01853
01854
01855
01856 static int cmd_open(void)
01857 {
01858 pstring mask;
01859 pstring buf;
01860 struct cli_state *targetcli;
01861 pstring targetname;
01862
01863 pstrcpy(mask,cur_dir);
01864
01865 if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01866 d_printf("open <filename>\n");
01867 return 1;
01868 }
01869 pstrcat(mask,buf);
01870
01871 if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
01872 d_printf("open %s: %s\n", mask, cli_errstr(cli));
01873 return 1;
01874 }
01875
01876 cli_nt_create(targetcli, targetname, FILE_READ_DATA);
01877
01878 return 0;
01879 }
01880
01881
01882
01883
01884
01885
01886 static int cmd_rmdir(void)
01887 {
01888 pstring mask;
01889 pstring buf;
01890 struct cli_state *targetcli;
01891 pstring targetname;
01892
01893 pstrcpy(mask, "smb:");
01894 pstrcat(mask, service);
01895 pstrcat(mask,cur_dir);
01896
01897 if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
01898 d_printf("rmdir <dirname>\n");
01899 return 1;
01900 }
01901 pstrcat(mask,buf);
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913 if (smbc_rmdir(mask) < 0)
01914 d_printf("Error: %s removing remote directory file %s\n", strerror(errno), mask);
01915
01916 return 0;
01917 }
01918
01919
01920
01921
01922
01923 static int cmd_link(void)
01924 {
01925 pstring oldname,newname;
01926 pstring buf,buf2;
01927 struct cli_state *targetcli;
01928 pstring targetname;
01929
01930 pstrcpy(oldname,cur_dir);
01931 pstrcpy(newname,cur_dir);
01932
01933 if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) ||
01934 !next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
01935 d_printf("link <oldname> <newname>\n");
01936 return 1;
01937 }
01938
01939 pstrcat(oldname,buf);
01940 pstrcat(newname,buf2);
01941
01942 if ( !cli_resolve_path( "", cli, oldname, &targetcli, targetname ) ) {
01943 d_printf("link %s: %s\n", oldname, cli_errstr(cli));
01944 return 1;
01945 }
01946
01947 if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
01948 d_printf("Server doesn't support UNIX CIFS calls.\n");
01949 return 1;
01950 }
01951
01952 if (!cli_unix_hardlink(targetcli, targetname, newname)) {
01953 d_printf("%s linking files (%s -> %s)\n", cli_errstr(targetcli), newname, oldname);
01954 return 1;
01955 }
01956
01957 return 0;
01958 }
01959
01960
01961
01962
01963
01964 static int cmd_symlink(void)
01965 {
01966 pstring oldname,newname;
01967 pstring buf,buf2;
01968
01969 if (!SERVER_HAS_UNIX_CIFS(cli)) {
01970 d_printf("Server doesn't support UNIX CIFS calls.\n");
01971 return 1;
01972 }
01973
01974 pstrcpy(newname,cur_dir);
01975
01976 if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) ||
01977 !next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
01978 d_printf("symlink <oldname> <newname>\n");
01979 return 1;
01980 }
01981
01982 pstrcpy(oldname,buf);
01983 pstrcat(newname,buf2);
01984
01985 if (!cli_unix_symlink(cli, oldname, newname)) {
01986 d_printf("%s symlinking files (%s -> %s)\n",
01987 cli_errstr(cli), newname, oldname);
01988 return 1;
01989 }
01990
01991 return 0;
01992 }
01993
01994
01995
01996
01997
01998 static int cmd_chmod(void)
01999 {
02000 pstring src;
02001 mode_t mode;
02002 pstring buf, buf2;
02003 struct cli_state *targetcli;
02004 pstring targetname;
02005
02006 pstrcpy(src,cur_dir);
02007
02008 if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) ||
02009 !next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
02010 d_printf("chmod mode file\n");
02011 return 1;
02012 }
02013
02014 mode = (mode_t)strtol(buf, NULL, 8);
02015 pstrcat(src,buf2);
02016
02017 if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
02018 d_printf("chmod %s: %s\n", src, cli_errstr(cli));
02019 return 1;
02020 }
02021
02022 if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
02023 d_printf("Server doesn't support UNIX CIFS calls.\n");
02024 return 1;
02025 }
02026
02027 if (!cli_unix_chmod(targetcli, targetname, mode)) {
02028 d_printf("%s chmod file %s 0%o\n",
02029 cli_errstr(targetcli), src, (unsigned int)mode);
02030 return 1;
02031 }
02032
02033 return 0;
02034 }
02035
02036 static const char *filetype_to_str(mode_t mode)
02037 {
02038 if (S_ISREG(mode)) {
02039 return "regular file";
02040 } else if (S_ISDIR(mode)) {
02041 return "directory";
02042 } else
02043 #ifdef S_ISCHR
02044 if (S_ISCHR(mode)) {
02045 return "character device";
02046 } else
02047 #endif
02048 #ifdef S_ISBLK
02049 if (S_ISBLK(mode)) {
02050 return "block device";
02051 } else
02052 #endif
02053 #ifdef S_ISFIFO
02054 if (S_ISFIFO(mode)) {
02055 return "fifo";
02056 } else
02057 #endif
02058 #ifdef S_ISLNK
02059 if (S_ISLNK(mode)) {
02060 return "symbolic link";
02061 } else
02062 #endif
02063 #ifdef S_ISSOCK
02064 if (S_ISSOCK(mode)) {
02065 return "socket";
02066 } else
02067 #endif
02068 return "";
02069 }
02070
02071 static char rwx_to_str(mode_t m, mode_t bt, char ret)
02072 {
02073 if (m & bt) {
02074 return ret;
02075 } else {
02076 return '-';
02077 }
02078 }
02079
02080 static char *unix_mode_to_str(char *s, mode_t m)
02081 {
02082 char *p = s;
02083 const char *str = filetype_to_str(m);
02084
02085 switch(str[0]) {
02086 case 'd':
02087 *p++ = 'd';
02088 break;
02089 case 'c':
02090 *p++ = 'c';
02091 break;
02092 case 'b':
02093 *p++ = 'b';
02094 break;
02095 case 'f':
02096 *p++ = 'p';
02097 break;
02098 case 's':
02099 *p++ = str[1] == 'y' ? 'l' : 's';
02100 break;
02101 case 'r':
02102 default:
02103 *p++ = '-';
02104 break;
02105 }
02106 *p++ = rwx_to_str(m, S_IRUSR, 'r');
02107 *p++ = rwx_to_str(m, S_IWUSR, 'w');
02108 *p++ = rwx_to_str(m, S_IXUSR, 'x');
02109 *p++ = rwx_to_str(m, S_IRGRP, 'r');
02110 *p++ = rwx_to_str(m, S_IWGRP, 'w');
02111 *p++ = rwx_to_str(m, S_IXGRP, 'x');
02112 *p++ = rwx_to_str(m, S_IROTH, 'r');
02113 *p++ = rwx_to_str(m, S_IWOTH, 'w');
02114 *p++ = rwx_to_str(m, S_IXOTH, 'x');
02115 *p++ = '\0';
02116 return s;
02117 }
02118
02119
02120
02121
02122
02123 static char *perms_to_string(fstring permstr, unsigned char perms)
02124 {
02125 fstrcpy(permstr, "---");
02126 if (perms & SMB_POSIX_ACL_READ) {
02127 permstr[0] = 'r';
02128 }
02129 if (perms & SMB_POSIX_ACL_WRITE) {
02130 permstr[1] = 'w';
02131 }
02132 if (perms & SMB_POSIX_ACL_EXECUTE) {
02133 permstr[2] = 'x';
02134 }
02135 return permstr;
02136 }
02137
02138
02139
02140
02141
02142 static int cmd_getfacl(void)
02143 {
02144 pstring src, name;
02145 uint16 major, minor;
02146 uint32 caplow, caphigh;
02147 char *retbuf = NULL;
02148 size_t rb_size = 0;
02149 SMB_STRUCT_STAT sbuf;
02150 uint16 num_file_acls = 0;
02151 uint16 num_dir_acls = 0;
02152 uint16 i;
02153 struct cli_state *targetcli;
02154 pstring targetname;
02155
02156 pstrcpy(src,cur_dir);
02157
02158 if (!next_token_nr(NULL,name,NULL,sizeof(name))) {
02159 d_printf("stat file\n");
02160 return 1;
02161 }
02162
02163 pstrcat(src,name);
02164
02165 if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
02166 d_printf("stat %s: %s\n", src, cli_errstr(cli));
02167 return 1;
02168 }
02169
02170 if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
02171 d_printf("Server doesn't support UNIX CIFS calls.\n");
02172 return 1;
02173 }
02174
02175 if (!cli_unix_extensions_version(targetcli, &major, &minor, &caplow, &caphigh)) {
02176 d_printf("Can't get UNIX CIFS version from server.\n");
02177 return 1;
02178 }
02179
02180 if (!(caplow & CIFS_UNIX_POSIX_ACLS_CAP)) {
02181 d_printf("This server supports UNIX extensions but doesn't support POSIX ACLs.\n");
02182 return 1;
02183 }
02184
02185
02186 if (!cli_unix_stat(targetcli, targetname, &sbuf)) {
02187 d_printf("%s getfacl doing a stat on file %s\n",
02188 cli_errstr(targetcli), src);
02189 return 1;
02190 }
02191
02192 if (!cli_unix_getfacl(targetcli, targetname, &rb_size, &retbuf)) {
02193 d_printf("%s getfacl file %s\n",
02194 cli_errstr(targetcli), src);
02195 return 1;
02196 }
02197
02198
02199 if (SVAL(retbuf,0) != SMB_POSIX_ACL_VERSION || rb_size < 6) {
02200 d_printf("getfacl file %s, unknown POSIX acl version %u.\n",
02201 src, (unsigned int)CVAL(retbuf,0) );
02202 SAFE_FREE(retbuf);
02203 return 1;
02204 }
02205
02206 num_file_acls = SVAL(retbuf,2);
02207 num_dir_acls = SVAL(retbuf,4);
02208 if (rb_size != SMB_POSIX_ACL_HEADER_SIZE + SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls)) {
02209 d_printf("getfacl file %s, incorrect POSIX acl buffer size (should be %u, was %u).\n",
02210 src,
02211 (unsigned int)(SMB_POSIX_ACL_HEADER_SIZE + SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls)),
02212 (unsigned int)rb_size);
02213
02214 SAFE_FREE(retbuf);
02215 return 1;
02216 }
02217
02218 d_printf("# file: %s\n", src);
02219 d_printf("# owner: %u\n# group: %u\n", (unsigned int)sbuf.st_uid, (unsigned int)sbuf.st_gid);
02220
02221 if (num_file_acls == 0 && num_dir_acls == 0) {
02222 d_printf("No acls found.\n");
02223 }
02224
02225 for (i = 0; i < num_file_acls; i++) {
02226 uint32 uorg;
02227 fstring permstring;
02228 unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE));
02229 unsigned char perms = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+1);
02230
02231 switch(tagtype) {
02232 case SMB_POSIX_ACL_USER_OBJ:
02233 d_printf("user::");
02234 break;
02235 case SMB_POSIX_ACL_USER:
02236 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
02237 d_printf("user:%u:", uorg);
02238 break;
02239 case SMB_POSIX_ACL_GROUP_OBJ:
02240 d_printf("group::");
02241 break;
02242 case SMB_POSIX_ACL_GROUP:
02243 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
02244 d_printf("group:%u", uorg);
02245 break;
02246 case SMB_POSIX_ACL_MASK:
02247 d_printf("mask::");
02248 break;
02249 case SMB_POSIX_ACL_OTHER:
02250 d_printf("other::");
02251 break;
02252 default:
02253 d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
02254 src, (unsigned int)tagtype );
02255 SAFE_FREE(retbuf);
02256 return 1;
02257 }
02258
02259 d_printf("%s\n", perms_to_string(permstring, perms));
02260 }
02261
02262 for (i = 0; i < num_dir_acls; i++) {
02263 uint32 uorg;
02264 fstring permstring;
02265 unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE));
02266 unsigned char perms = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+1);
02267
02268 switch(tagtype) {
02269 case SMB_POSIX_ACL_USER_OBJ:
02270 d_printf("default:user::");
02271 break;
02272 case SMB_POSIX_ACL_USER:
02273 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
02274 d_printf("default:user:%u:", uorg);
02275 break;
02276 case SMB_POSIX_ACL_GROUP_OBJ:
02277 d_printf("default:group::");
02278 break;
02279 case SMB_POSIX_ACL_GROUP:
02280 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
02281 d_printf("default:group:%u", uorg);
02282 break;
02283 case SMB_POSIX_ACL_MASK:
02284 d_printf("default:mask::");
02285 break;
02286 case SMB_POSIX_ACL_OTHER:
02287 d_printf("default:other::");
02288 break;
02289 default:
02290 d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
02291 src, (unsigned int)tagtype );
02292 SAFE_FREE(retbuf);
02293 return 1;
02294 }
02295
02296 d_printf("%s\n", perms_to_string(permstring, perms));
02297 }
02298
02299 SAFE_FREE(retbuf);
02300 return 0;
02301 }
02302
02303
02304
02305
02306
02307 static int cmd_stat(void)
02308 {
02309 pstring src, name;
02310 fstring mode_str;
02311 SMB_STRUCT_STAT sbuf;
02312 struct cli_state *targetcli;
02313 struct tm *lt;
02314 pstring targetname;
02315
02316 if (!SERVER_HAS_UNIX_CIFS(cli)) {
02317 d_printf("Server doesn't support UNIX CIFS calls.\n");
02318 return 1;
02319 }
02320
02321 pstrcpy(src,cur_dir);
02322
02323 if (!next_token_nr(NULL,name,NULL,sizeof(name))) {
02324 d_printf("stat file\n");
02325 return 1;
02326 }
02327
02328 pstrcat(src,name);
02329
02330
02331 if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
02332 d_printf("stat %s: %s\n", src, cli_errstr(cli));
02333 return 1;
02334 }
02335
02336 if (!cli_unix_stat(targetcli, targetname, &sbuf)) {
02337 d_printf("%s stat file %s\n",
02338 cli_errstr(targetcli), src);
02339 return 1;
02340 }
02341
02342
02343 d_printf("File: %s\n", src);
02344 d_printf("Size: %-12.0f\tBlocks: %u\t%s\n",
02345 (double)sbuf.st_size,
02346 (unsigned int)sbuf.st_blocks,
02347 filetype_to_str(sbuf.st_mode));
02348
02349 #if defined(S_ISCHR) && defined(S_ISBLK)
02350 if (S_ISCHR(sbuf.st_mode) || S_ISBLK(sbuf.st_mode)) {
02351 d_printf("Inode: %.0f\tLinks: %u\tDevice type: %u,%u\n",
02352 (double)sbuf.st_ino,
02353 (unsigned int)sbuf.st_nlink,
02354 unix_dev_major(sbuf.st_rdev),
02355 unix_dev_minor(sbuf.st_rdev));
02356 } else
02357 #endif
02358 d_printf("Inode: %.0f\tLinks: %u\n",
02359 (double)sbuf.st_ino,
02360 (unsigned int)sbuf.st_nlink);
02361
02362 d_printf("Access: (0%03o/%s)\tUid: %u\tGid: %u\n",
02363 ((int)sbuf.st_mode & 0777),
02364 unix_mode_to_str(mode_str, sbuf.st_mode),
02365 (unsigned int)sbuf.st_uid,
02366 (unsigned int)sbuf.st_gid);
02367
02368 lt = localtime(&sbuf.st_atime);
02369 if (lt) {
02370 strftime(mode_str, sizeof(mode_str), "%F %T %z", lt);
02371 } else {
02372 fstrcpy(mode_str, "unknown");
02373 }
02374 d_printf("Access: %s\n", mode_str);
02375
02376 lt = localtime(&sbuf.st_mtime);
02377 if (lt) {
02378 strftime(mode_str, sizeof(mode_str), "%F %T %z", lt);
02379 } else {
02380 fstrcpy(mode_str, "unknown");
02381 }
02382 d_printf("Modify: %s\n", mode_str);
02383
02384 lt = localtime(&sbuf.st_ctime);
02385 if (lt) {
02386 strftime(mode_str, sizeof(mode_str), "%F %T %z", lt);
02387 } else {
02388 fstrcpy(mode_str, "unknown");
02389 }
02390 d_printf("Change: %s\n", mode_str);
02391
02392 return 0;
02393 }
02394
02395
02396
02397
02398
02399
02400 static int cmd_chown(void)
02401 {
02402 pstring src;
02403 uid_t uid;
02404 gid_t gid;
02405 pstring buf, buf2, buf3;
02406 struct cli_state *targetcli;
02407 pstring targetname;
02408
02409 pstrcpy(src,cur_dir);
02410
02411 if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) ||
02412 !next_token_nr(NULL,buf2,NULL, sizeof(buf2)) ||
02413 !next_token_nr(NULL,buf3,NULL, sizeof(buf3))) {
02414 d_printf("chown uid gid file\n");
02415 return 1;
02416 }
02417
02418 uid = (uid_t)atoi(buf);
02419 gid = (gid_t)atoi(buf2);
02420 pstrcat(src,buf3);
02421
02422 if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
02423 d_printf("chown %s: %s\n", src, cli_errstr(cli));
02424 return 1;
02425 }
02426
02427
02428 if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
02429 d_printf("Server doesn't support UNIX CIFS calls.\n");
02430 return 1;
02431 }
02432
02433 if (!cli_unix_chown(targetcli, targetname, uid, gid)) {
02434 d_printf("%s chown file %s uid=%d, gid=%d\n",
02435 cli_errstr(targetcli), src, (int)uid, (int)gid);
02436 return 1;
02437 }
02438
02439 return 0;
02440 }
02441
02442
02443
02444
02445
02446 static int cmd_rename(void)
02447 {
02448 int err;
02449 pstring src, dest;
02450 pstring oname, nname;
02451
02452 pstrcpy(src, "smb:");
02453 pstrcat(src, service);
02454 pstrcat(src, cur_dir);
02455 pstrcpy(dest, src);
02456
02457 if (!next_token_nr(NULL,oname,NULL,sizeof(oname)) ||
02458 !next_token_nr(NULL,nname,NULL, sizeof(nname))) {
02459 d_printf("rename <src> <dest>\n");
02460 return 1;
02461 }
02462
02463 pstrcat(src, oname);
02464 pstrcat(dest, nname);
02465
02466 DEBUG(4, ("O: %s\nN: %s\n", src, dest));
02467
02468 err = smbc_rename(src, dest);
02469 if (err < 0)
02470 {
02471 d_printf("%s renaming files\n", strerror(errno));
02472 return 1;
02473 }
02474
02475 return 0;
02476 }
02477
02478
02479
02480
02481
02482 static int cmd_volume(void)
02483 {
02484 fstring volname;
02485 uint32 serial_num;
02486 time_t create_date;
02487
02488 if (!cli_get_fs_volume_info(cli, volname, &serial_num, &create_date)) {
02489 d_printf("Errr %s getting volume info\n",cli_errstr(cli));
02490 return 1;
02491 }
02492
02493 d_printf("Volume: |%s| serial number 0x%x\n", volname, (unsigned int)serial_num);
02494 return 0;
02495 }
02496
02497
02498
02499
02500
02501 static int cmd_hardlink(void)
02502 {
02503 pstring src,dest;
02504 pstring buf,buf2;
02505 struct cli_state *targetcli;
02506 pstring targetname;
02507
02508 pstrcpy(src,cur_dir);
02509 pstrcpy(dest,cur_dir);
02510
02511 if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) ||
02512 !next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
02513 d_printf("hardlink <src> <dest>\n");
02514 return 1;
02515 }
02516
02517 pstrcat(src,buf);
02518 pstrcat(dest,buf2);
02519
02520 if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
02521 d_printf("hardlink %s: %s\n", src, cli_errstr(cli));
02522 return 1;
02523 }
02524
02525 if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
02526 d_printf("Server doesn't support UNIX CIFS calls.\n");
02527 return 1;
02528 }
02529
02530 if (!cli_nt_hardlink(targetcli, targetname, dest)) {
02531 d_printf("%s doing an NT hard link of files\n",cli_errstr(targetcli));
02532 return 1;
02533 }
02534
02535 return 0;
02536 }
02537
02538
02539
02540
02541
02542 static int cmd_prompt(void)
02543 {
02544 prompt = !prompt;
02545 DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
02546
02547 return 1;
02548 }
02549
02550
02551
02552
02553
02554 static int cmd_newer(void)
02555 {
02556 pstring buf;
02557 BOOL ok;
02558 SMB_STRUCT_STAT sbuf;
02559
02560 ok = next_token_nr(NULL,buf,NULL,sizeof(buf));
02561 if (ok && (sys_stat(buf,&sbuf) == 0)) {
02562 newer_than = sbuf.st_mtime;
02563 DEBUG(1,("Getting files newer than %s",
02564 time_to_asc(newer_than)));
02565 } else {
02566 newer_than = 0;
02567 }
02568
02569 if (ok && newer_than == 0) {
02570 d_printf("Error setting newer-than time\n");
02571 return 1;
02572 }
02573
02574 return 0;
02575 }
02576
02577
02578
02579
02580
02581 static int cmd_archive(void)
02582 {
02583 pstring buf;
02584
02585 if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02586 archive_level = atoi(buf);
02587 } else
02588 d_printf("Archive level is %d\n",archive_level);
02589
02590 return 0;
02591 }
02592
02593
02594
02595
02596
02597 static int cmd_lowercase(void)
02598 {
02599 lowercase = !lowercase;
02600 DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
02601
02602 return 0;
02603 }
02604
02605
02606
02607
02608
02609 static int cmd_setcase(void)
02610 {
02611 BOOL orig_case_sensitive = cli_set_case_sensitive(cli, False);
02612
02613 cli_set_case_sensitive(cli, !orig_case_sensitive);
02614 DEBUG(2,("filename case sensitivity is now %s\n",!orig_case_sensitive ?
02615 "on":"off"));
02616
02617 return 0;
02618 }
02619
02620
02621
02622
02623
02624 static int cmd_recurse(void)
02625 {
02626 recurse = !recurse;
02627 DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
02628
02629 return 0;
02630 }
02631
02632
02633
02634
02635
02636 static int cmd_translate(void)
02637 {
02638 translation = !translation;
02639 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
02640 translation?"on":"off"));
02641
02642 return 0;
02643 }
02644
02645
02646
02647
02648
02649 static int cmd_lcd(void)
02650 {
02651 pstring buf;
02652 pstring d;
02653
02654 if (next_token_nr(NULL,buf,NULL,sizeof(buf)))
02655 chdir(buf);
02656 DEBUG(2,("the local directory is now %s\n",sys_getwd(d)));
02657
02658 return 0;
02659 }
02660
02661
02662
02663
02664
02665 static int cmd_reget(void)
02666 {
02667 pstring local_name;
02668 pstring remote_name;
02669 char *p;
02670
02671 pstrcpy(remote_name, cur_dir);
02672 pstrcat(remote_name, "/");
02673
02674 p = remote_name + strlen(remote_name);
02675
02676 if (!next_token_nr(NULL, p, NULL, sizeof(remote_name) - strlen(remote_name))) {
02677 d_printf("reget <filename>\n");
02678 return 1;
02679 }
02680 pstrcpy(local_name, p);
02681 clean_name(remote_name);
02682
02683 next_token_nr(NULL, local_name, NULL, sizeof(local_name));
02684
02685 return do_get(remote_name, local_name, True);
02686 }
02687
02688
02689
02690
02691
02692 static int cmd_reput(void)
02693 {
02694 pstring local_name;
02695 pstring remote_name;
02696 pstring buf;
02697 char *p = buf;
02698 SMB_STRUCT_STAT st;
02699
02700 pstrcpy(remote_name, cur_dir);
02701 pstrcat(remote_name, "/");
02702
02703 if (!next_token_nr(NULL, p, NULL, sizeof(buf))) {
02704 d_printf("reput <filename>\n");
02705 return 1;
02706 }
02707 pstrcpy(local_name, p);
02708
02709 if (!file_exist(local_name, &st)) {
02710 d_printf("%s does not exist\n", local_name);
02711 return 1;
02712 }
02713
02714 if (next_token_nr(NULL, p, NULL, sizeof(buf)))
02715 pstrcat(remote_name, p);
02716 else
02717 pstrcat(remote_name, local_name);
02718
02719 clean_name(remote_name);
02720
02721 return do_put(remote_name, local_name, True);
02722 }
02723
02724
02725
02726
02727
02728 static void browse_fn(const char *name, uint32 m,
02729 const char *comment, void *state)
02730 {
02731 fstring typestr;
02732
02733 *typestr=0;
02734
02735 switch (m)
02736 {
02737 case STYPE_DISKTREE:
02738 fstrcpy(typestr,"Disk"); break;
02739 case STYPE_PRINTQ:
02740 fstrcpy(typestr,"Printer"); break;
02741 case STYPE_DEVICE:
02742 fstrcpy(typestr,"Device"); break;
02743 case STYPE_IPC:
02744 fstrcpy(typestr,"IPC"); break;
02745 }
02746
02747
02748
02749 if (!grepable) {
02750 d_printf("\t%-15s %-10.10s%s\n",
02751 name,typestr,comment);
02752 } else {
02753 d_printf ("%s|%s|%s\n",typestr,name,comment);
02754 }
02755 }
02756
02757
02758
02759
02760
02761 static BOOL browse_host(BOOL sort)
02762 {
02763 int ret;
02764 if (!grepable) {
02765 d_printf("\n\tSharename Type Comment\n");
02766 d_printf("\t--------- ---- -------\n");
02767 }
02768
02769 if((ret = cli_RNetShareEnum(cli, browse_fn, NULL)) == -1)
02770 d_printf("Error returning browse list: %s\n", cli_errstr(cli));
02771
02772 return (ret != -1);
02773 }
02774
02775
02776
02777
02778
02779 static void server_fn(const char *name, uint32 m,
02780 const char *comment, void *state)
02781 {
02782
02783 if (!grepable){
02784 d_printf("\t%-16s %s\n", name, comment);
02785 } else {
02786 d_printf("%s|%s|%s\n",(char *)state, name, comment);
02787 }
02788 }
02789
02790
02791
02792
02793
02794 static BOOL list_servers(const char *wk_grp)
02795 {
02796 fstring state;
02797
02798 if (!cli->server_domain)
02799 return False;
02800
02801 if (!grepable) {
02802 d_printf("\n\tServer Comment\n");
02803 d_printf("\t--------- -------\n");
02804 };
02805 fstrcpy( state, "Server" );
02806 cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL, server_fn,
02807 state);
02808
02809 if (!grepable) {
02810 d_printf("\n\tWorkgroup Master\n");
02811 d_printf("\t--------- -------\n");
02812 };
02813
02814 fstrcpy( state, "Workgroup" );
02815 cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM,
02816 server_fn, state);
02817 return True;
02818 }
02819
02820
02821
02822
02823
02824 static int cmd_vuid(void)
02825 {
02826 fstring buf;
02827
02828 if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02829 d_printf("Current VUID is %d\n", cli->vuid);
02830 return 0;
02831 }
02832
02833 cli->vuid = atoi(buf);
02834 return 0;
02835 }
02836
02837
02838
02839
02840
02841 static int cmd_logon(void)
02842 {
02843 pstring l_username, l_password;
02844 pstring buf,buf2;
02845
02846 if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
02847 d_printf("logon <username> [<password>]\n");
02848 return 0;
02849 }
02850
02851 pstrcpy(l_username, buf);
02852
02853 if (!next_token_nr(NULL,buf2,NULL,sizeof(buf)))
02854 {
02855 char *pass = getpass("Password: ");
02856 if (pass)
02857 pstrcpy(l_password, pass);
02858 }
02859 else
02860 pstrcpy(l_password, buf2);
02861
02862 if (!cli_session_setup(cli, l_username,
02863 l_password, strlen(l_password),
02864 l_password, strlen(l_password),
02865 lp_workgroup())) {
02866 d_printf("session setup failed: %s\n", cli_errstr(cli));
02867 return -1;
02868 }
02869
02870 d_printf("Current VUID is %d\n", cli->vuid);
02871 return 0;
02872 }
02873
02874
02875
02876
02877
02878
02879 static int cmd_list_connect(void)
02880 {
02881 cli_cm_display();
02882
02883 return 0;
02884 }
02885
02886
02887
02888
02889
02890 static int cmd_show_connect( void )
02891 {
02892 struct cli_state *targetcli;
02893 pstring targetpath;
02894
02895 if ( !cli_resolve_path( "", cli, cur_dir, &targetcli, targetpath ) ) {
02896 d_printf("showconnect %s: %s\n", cur_dir, cli_errstr(cli));
02897 return 1;
02898 }
02899
02900 d_printf("//%s/%s\n", targetcli->desthost, targetcli->share);
02901 return 0;
02902 }
02903
02904
02905
02906 #define COMPL_NONE 0
02907 #define COMPL_REMOTE 1
02908 #define COMPL_LOCAL 2
02909
02910
02911
02912
02913
02914
02915 static struct
02916 {
02917 const char *name;
02918 int (*fn)(void);
02919 const char *description;
02920 char compl_args[2];
02921 } commands[] = {
02922 {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
02923
02924 {"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}},
02925 {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
02926
02927
02928 {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
02929
02930
02931
02932 {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
02933
02934 {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
02935 {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
02936
02937
02938 {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
02939 {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
02940 {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
02941
02942
02943
02944 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},
02945 {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
02946
02947 {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
02948 {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
02949 {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
02950
02951 {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
02952 {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
02953
02954
02955 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
02956 {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
02957 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
02958 {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
02959
02960 {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
02961 {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
02962 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},
02963
02964 {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
02965
02966
02967 {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
02968
02969
02970
02971
02972 {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
02973 {"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
02974 {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
02975
02976
02977
02978
02979 {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
02980 {NULL,NULL,NULL,{COMPL_NONE,COMPL_NONE}}
02981 };
02982
02983
02984
02985
02986
02987
02988 static int process_tok(pstring tok)
02989 {
02990 int i = 0, matches = 0;
02991 int cmd=0;
02992 int tok_len = strlen(tok);
02993
02994 while ((commands[i].fn != NULL) || (strequal(commands[i].name, "!"))) {
02995 if (strequal(commands[i].name,tok)) {
02996 matches = 1;
02997 cmd = i;
02998 break;
02999 } else if (strnequal(commands[i].name, tok, tok_len)) {
03000 matches++;
03001 cmd = i;
03002 }
03003 i++;
03004 }
03005
03006 if (matches == 0)
03007 return(-1);
03008 else if (matches == 1)
03009 return(cmd);
03010 else
03011 return(-2);
03012 }
03013
03014
03015
03016
03017
03018 static int cmd_help(void)
03019 {
03020 int i=0,j;
03021 pstring buf;
03022
03023 if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
03024 if ((i = process_tok(buf)) >= 0)
03025 d_printf("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description);
03026 } else {
03027 while (commands[i].description) {
03028 for (j=0; commands[i].description && (j<5); j++) {
03029 d_printf("%-15s",commands[i].name);
03030 i++;
03031 }
03032 d_printf("\n");
03033 }
03034 }
03035 return 0;
03036 }
03037
03038
03039
03040
03041
03042 static int process_command_string(char *cmd)
03043 {
03044 pstring line;
03045 const char *ptr;
03046 int rc = 0;
03047
03048
03049
03050 if (!cli) {
03051 cli = cli_cm_open(desthost, service, True);
03052 if (!cli)
03053 return 0;
03054 }
03055
03056 while (cmd[0] != '\0') {
03057 char *p;
03058 pstring tok;
03059 int i;
03060
03061 if ((p = strchr_m(cmd, ';')) == 0) {
03062 strncpy(line, cmd, 999);
03063 line[1000] = '\0';
03064 cmd += strlen(cmd);
03065 } else {
03066 if (p - cmd > 999)
03067 p = cmd + 999;
03068 strncpy(line, cmd, p - cmd);
03069 line[p - cmd] = '\0';
03070 cmd = p + 1;
03071 }
03072
03073
03074 ptr = line;
03075 if (!next_token_nr(&ptr,tok,NULL,sizeof(tok))) continue;
03076
03077 if ((i = process_tok(tok)) >= 0) {
03078 rc = commands[i].fn();
03079 } else if (i == -2) {
03080 d_printf("%s: command abbreviation ambiguous\n",tok);
03081 } else {
03082 d_printf("%s: command not found\n",tok);
03083 }
03084 }
03085
03086 return rc;
03087 }
03088
03089 #define MAX_COMPLETIONS 100
03090
03091 typedef struct {
03092 pstring dirmask;
03093 char **matches;
03094 int count, samelen;
03095 const char *text;
03096 int len;
03097 } completion_remote_t;
03098
03099 static void completion_remote_filter(const char *mnt, file_info *f, const char *mask, void *state)
03100 {
03101 completion_remote_t *info = (completion_remote_t *)state;
03102
03103 if ((info->count < MAX_COMPLETIONS - 1) && (strncmp(info->text, f->name, info->len) == 0) && (strcmp(f->name, ".") != 0) && (strcmp(f->name, "..") != 0)) {
03104 if ((info->dirmask[0] == 0) && !(f->mode & aDIR))
03105 info->matches[info->count] = SMB_STRDUP(f->name);
03106 else {
03107 pstring tmp;
03108
03109 if (info->dirmask[0] != 0)
03110 pstrcpy(tmp, info->dirmask);
03111 else
03112 tmp[0] = 0;
03113 pstrcat(tmp, f->name);
03114 if (f->mode & aDIR)
03115 pstrcat(tmp, "/");
03116 info->matches[info->count] = SMB_STRDUP(tmp);
03117 }
03118 if (info->matches[info->count] == NULL)
03119 return;
03120 if (f->mode & aDIR)
03121 smb_readline_ca_char(0);
03122
03123 if (info->count == 1)
03124 info->samelen = strlen(info->matches[info->count]);
03125 else
03126 while (strncmp(info->matches[info->count], info->matches[info->count-1], info->samelen) != 0)
03127 info->samelen--;
03128 info->count++;
03129 }
03130 }
03131
03132 static char **remote_completion(const char *text, int len)
03133 {
03134 pstring dirmask;
03135 int i;
03136 completion_remote_t info = { "", NULL, 1, 0, NULL, 0 };
03137
03138
03139
03140 info.samelen = len;
03141 info.text = text;
03142 info.len = len;
03143
03144 if (len >= PATH_MAX)
03145 return(NULL);
03146
03147 info.matches = SMB_MALLOC_ARRAY(char *,MAX_COMPLETIONS);
03148 if (!info.matches) return NULL;
03149 info.matches[0] = NULL;
03150
03151 for (i = len-1; i >= 0; i--)
03152 if ((text[i] == '/') || (text[i] == '\\'))
03153 break;
03154 info.text = text+i+1;
03155 info.samelen = info.len = len-i-1;
03156
03157 if (i > 0) {
03158 strncpy(info.dirmask, text, i+1);
03159 info.dirmask[i+1] = 0;
03160 pstr_sprintf(dirmask, "%s%*s*", cur_dir, i-1, text);
03161 } else
03162 pstr_sprintf(dirmask, "%s*", cur_dir);
03163
03164 if (cli_list(cli, dirmask, aDIR | aSYSTEM | aHIDDEN, completion_remote_filter, &info) < 0)
03165 goto cleanup;
03166
03167 if (info.count == 2)
03168 info.matches[0] = SMB_STRDUP(info.matches[1]);
03169 else {
03170 info.matches[0] = SMB_MALLOC(info.samelen+1);
03171 if (!info.matches[0])
03172 goto cleanup;
03173 strncpy(info.matches[0], info.matches[1], info.samelen);
03174 info.matches[0][info.samelen] = 0;
03175 }
03176 info.matches[info.count] = NULL;
03177 return info.matches;
03178
03179 cleanup:
03180 for (i = 0; i < info.count; i++)
03181 free(info.matches[i]);
03182 free(info.matches);
03183 return NULL;
03184 }
03185
03186 static char **completion_fn(const char *text, int start, int end)
03187 {
03188 smb_readline_ca_char(' ');
03189
03190 if (start) {
03191 const char *buf, *sp;
03192 int i;
03193 char compl_type;
03194
03195 buf = smb_readline_get_line_buffer();
03196 if (buf == NULL)
03197 return NULL;
03198
03199 sp = strchr(buf, ' ');
03200 if (sp == NULL)
03201 return NULL;
03202
03203 for (i = 0; commands[i].name; i++)
03204 if ((strncmp(commands[i].name, text, sp - buf) == 0) && (commands[i].name[sp - buf] == 0))
03205 break;
03206 if (commands[i].name == NULL)
03207 return NULL;
03208
03209 while (*sp == ' ')
03210 sp++;
03211
03212 if (sp == (buf + start))
03213 compl_type = commands[i].compl_args[0];
03214 else
03215 compl_type = commands[i].compl_args[1];
03216
03217 if (compl_type == COMPL_REMOTE)
03218 return remote_completion(text, end - start);
03219 else
03220 return NULL;
03221 } else {
03222 char **matches;
03223 int i, len, samelen = 0, count=1;
03224
03225 matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
03226 if (!matches) {
03227 return NULL;
03228 }
03229 matches[0] = NULL;
03230
03231 len = strlen(text);
03232 for (i=0;commands[i].fn && count < MAX_COMPLETIONS-1;i++) {
03233 if (strncmp(text, commands[i].name, len) == 0) {
03234 matches[count] = SMB_STRDUP(commands[i].name);
03235 if (!matches[count])
03236 goto cleanup;
03237 if (count == 1)
03238 samelen = strlen(matches[count]);
03239 else
03240 while (strncmp(matches[count], matches[count-1], samelen) != 0)
03241 samelen--;
03242 count++;
03243 }
03244 }
03245
03246 switch (count) {
03247 case 0:
03248 case 1:
03249 goto cleanup;
03250 case 2:
03251 matches[0] = SMB_STRDUP(matches[1]);
03252 break;
03253 default:
03254 matches[0] = SMB_MALLOC(samelen+1);
03255 if (!matches[0])
03256 goto cleanup;
03257 strncpy(matches[0], matches[1], samelen);
03258 matches[0][samelen] = 0;
03259 }
03260 matches[count] = NULL;
03261 return matches;
03262
03263 cleanup:
03264 for (i = 0; i < count; i++)
03265 free(matches[i]);
03266
03267 free(matches);
03268 return NULL;
03269 }
03270 }
03271
03272
03273
03274
03275
03276 static void readline_callback(void)
03277 {
03278 fd_set fds;
03279 struct timeval timeout;
03280 static time_t last_t;
03281 time_t t;
03282
03283 t = time(NULL);
03284
03285 if (t - last_t < 5)
03286 return;
03287
03288 last_t = t;
03289
03290 again:
03291
03292 if (cli->fd == -1)
03293 return;
03294
03295 FD_ZERO(&fds);
03296 FD_SET(cli->fd,&fds);
03297
03298 timeout.tv_sec = 0;
03299 timeout.tv_usec = 0;
03300 sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
03301
03302
03303
03304
03305
03306 if (FD_ISSET(cli->fd,&fds)) {
03307 receive_smb(cli->fd,cli->inbuf,cli->bufsize,0);
03308 goto again;
03309 }
03310
03311 cli_chkpath(cli, "/");
03312 }
03313
03314
03315
03316
03317
03318 static int process_stdin(void)
03319 {
03320 const char *ptr;
03321 int rc = 0;
03322
03323 while (1) {
03324 pstring tok;
03325 pstring the_prompt;
03326 char *cline;
03327 pstring line;
03328 int i;
03329
03330
03331 slprintf(the_prompt, sizeof(the_prompt)-1, "smb: %s> ", cur_dir);
03332
03333
03334 cline = smb_readline(the_prompt, NULL, completion_fn);
03335
03336 if (!cline) break;
03337
03338 pstrcpy(line, cline);
03339
03340
03341 if (*line == '!') {
03342 system(line + 1);
03343 continue;
03344 }
03345
03346
03347 ptr = line;
03348 if (!next_token_nr(&ptr,tok,NULL,sizeof(tok))) continue;
03349
03350 if ((i = process_tok(tok)) >= 0) {
03351 rc = commands[i].fn();
03352 } else if (i == -2) {
03353 d_printf("%s: command abbreviation ambiguous\n",tok);
03354 } else {
03355 d_printf("%s: command not found\n",tok);
03356 }
03357 }
03358 return rc;
03359 }
03360
03361
03362
03363
03364
03365 static int process(char *base_directory)
03366 {
03367 int rc = 0;
03368
03369
03370
03371
03372
03373 rc = smbc_init(get_auth_data_fn, 0);
03374 if (rc < 0)
03375 {
03376 d_printf("Error initializing libsmbclient: %s\n", strerror(errno));
03377 return 1;
03378 }
03379
03380 if (*base_directory) {
03381 rc = do_cd(base_directory);
03382 if (rc) {
03383 cli_cm_shutdown();
03384 return rc;
03385 }
03386 }
03387 else
03388 {
03389 rc = do_cd("/");
03390 if (rc)
03391 return rc;
03392 }
03393
03394 if (cmdstr) {
03395 rc = process_command_string(cmdstr);
03396 } else {
03397 process_stdin();
03398 }
03399
03400 cli_cm_shutdown();
03401 return rc;
03402 }
03403
03404
03405
03406
03407
03408 static int do_host_query(char *query_host)
03409 {
03410 cli = cli_cm_open(query_host, "IPC$", True);
03411 if (!cli)
03412 return 1;
03413
03414 browse_host(True);
03415
03416 if (port != 139) {
03417
03418
03419
03420
03421 cli_cm_shutdown();
03422 cli_cm_set_port( 139 );
03423 cli = cli_cm_open(query_host, "IPC$", True);
03424 }
03425
03426 if (cli == NULL) {
03427 d_printf("NetBIOS over TCP disabled -- no workgroup available\n");
03428 return 1;
03429 }
03430
03431 list_servers(lp_workgroup());
03432
03433 cli_cm_shutdown();
03434
03435 return(0);
03436 }
03437
03438
03439
03440
03441
03442 static int do_tar_op(char *base_directory)
03443 {
03444 int ret;
03445
03446
03447 if (!cli) {
03448 cli = cli_cm_open(desthost, service, True);
03449 if (!cli)
03450 return 1;
03451 }
03452
03453 recurse=True;
03454
03455 if (*base_directory) {
03456 ret = do_cd(base_directory);
03457 if (ret) {
03458 cli_cm_shutdown();
03459 return ret;
03460 }
03461 }
03462
03463 ret=process_tar();
03464
03465 cli_cm_shutdown();
03466
03467 return(ret);
03468 }
03469
03470
03471
03472
03473
03474 static int do_message_op(void)
03475 {
03476 struct in_addr ip;
03477 struct nmb_name called, calling;
03478 fstring server_name;
03479 char name_type_hex[10];
03480 int msg_port;
03481
03482 make_nmb_name(&calling, calling_name, 0x0);
03483 make_nmb_name(&called , desthost, name_type);
03484
03485 fstrcpy(server_name, desthost);
03486 snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
03487 fstrcat(server_name, name_type_hex);
03488
03489 zero_ip(&ip);
03490 if (have_ip)
03491 ip = dest_ip;
03492
03493
03494
03495 msg_port = port ? port : 139;
03496
03497 if (!(cli=cli_initialise()) || (cli_set_port(cli, msg_port) != msg_port) ||
03498 !cli_connect(cli, server_name, &ip)) {
03499 d_printf("Connection to %s failed\n", desthost);
03500 return 1;
03501 }
03502
03503 if (!cli_session_request(cli, &calling, &called)) {
03504 d_printf("session request failed\n");
03505 cli_cm_shutdown();
03506 return 1;
03507 }
03508
03509 send_message();
03510 cli_cm_shutdown();
03511
03512 return 0;
03513 }
03514
03515
03516
03517
03518
03519
03520 int main(int argc,char *argv[])
03521 {
03522 pstring base_directory;
03523 int opt;
03524 pstring query_host;
03525 BOOL message = False;
03526 pstring term_code;
03527 static const char *new_name_resolve_order = NULL;
03528 poptContext pc;
03529 char *p;
03530 int rc = 0;
03531 fstring new_workgroup;
03532 struct poptOption long_options[] = {
03533 POPT_AUTOHELP
03534
03535 { "name-resolve", 'R', POPT_ARG_STRING, &new_name_resolve_order, 'R', "Use these name resolution services only", "NAME-RESOLVE-ORDER" },
03536 { "message", 'M', POPT_ARG_STRING, NULL, 'M', "Send message", "HOST" },
03537 { "ip-address", 'I', POPT_ARG_STRING, NULL, 'I', "Use this IP to connect to", "IP" },
03538 { "stderr", 'E', POPT_ARG_NONE, NULL, 'E', "Write messages to stderr instead of stdout" },
03539 { "list", 'L', POPT_ARG_STRING, NULL, 'L', "Get a list of shares available on a host", "HOST" },
03540 { "terminal", 't', POPT_ARG_STRING, NULL, 't', "Terminal I/O code {sjis|euc|jis7|jis8|junet|hex}", "CODE" },
03541 { "max-protocol", 'm', POPT_ARG_STRING, NULL, 'm', "Set the max protocol level", "LEVEL" },
03542 { "tar", 'T', POPT_ARG_STRING, NULL, 'T', "Command line tar", "<c|x>IXFqgbNan" },
03543 { "directory", 'D', POPT_ARG_STRING, NULL, 'D', "Start from directory", "DIR" },
03544 { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" },
03545 { "send-buffer", 'b', POPT_ARG_INT, &io_bufsize, 'b', "Changes the transmit/send buffer", "BYTES" },
03546 { "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" },
03547 { "grepable", 'g', POPT_ARG_NONE, NULL, 'g', "Produce grepable output" },
03548 POPT_COMMON_SAMBA
03549 POPT_COMMON_CONNECTION
03550 POPT_COMMON_CREDENTIALS
03551 POPT_TABLEEND
03552 };
03553
03554
03555 #ifdef KANJI
03556 pstrcpy(term_code, KANJI);
03557 #else
03558 *term_code = 0;
03559 #endif
03560
03561 *query_host = 0;
03562 *base_directory = 0;
03563
03564
03565
03566
03567 set_global_myworkgroup( "" );
03568 set_global_myname( "" );
03569
03570
03571 setup_logging( "smbctool", True );
03572 DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
03573 if ((dbf = x_fdup(x_stderr))) {
03574 x_setbuf( dbf, NULL );
03575 }
03576
03577 pc = poptGetContext("smbclient", argc, (const char **) argv, long_options,
03578 POPT_CONTEXT_KEEP_FIRST);
03579 poptSetOtherOptionHelp(pc, "service <password>");
03580
03581 in_client = True;
03582
03583 while ((opt = poptGetNextOpt(pc)) != -1) {
03584 switch (opt) {
03585 case 'M':
03586
03587
03588
03589
03590 name_type = 0x03;
03591 cli_cm_set_dest_name_type( name_type );
03592 pstrcpy(desthost,poptGetOptArg(pc));
03593 if( !port )
03594 cli_cm_set_port( 139 );
03595 message = True;
03596 break;
03597 case 'I':
03598 {
03599 dest_ip = *interpret_addr2(poptGetOptArg(pc));
03600 if (is_zero_ip(dest_ip))
03601 exit(1);
03602 have_ip = True;
03603
03604 cli_cm_set_dest_ip( dest_ip );
03605 }
03606 break;
03607 case 'E':
03608 if (dbf) {
03609 x_fclose(dbf);
03610 }
03611 dbf = x_stderr;
03612 display_set_stderr();
03613 break;
03614
03615 case 'L':
03616 pstrcpy(query_host, poptGetOptArg(pc));
03617 break;
03618 case 't':
03619 pstrcpy(term_code, poptGetOptArg(pc));
03620 break;
03621 case 'm':
03622 max_protocol = interpret_protocol(poptGetOptArg(pc), max_protocol);
03623 break;
03624 case 'T':
03625
03626
03627 {
03628 int i, optnum;
03629 for (i = 1; i < argc; i++) {
03630 if (strncmp("-T", argv[i],2)==0)
03631 break;
03632 }
03633 i++;
03634 if (!(optnum = tar_parseargs(argc, argv, poptGetOptArg(pc), i))) {
03635 poptPrintUsage(pc, stderr, 0);
03636 exit(1);
03637 }
03638
03639
03640
03641 optnum -= i;
03642 for (i = 0; i < optnum; i++)
03643 poptGetOptArg(pc);
03644 }
03645 break;
03646 case 'D':
03647 pstrcpy(base_directory,poptGetOptArg(pc));
03648 break;
03649 case 'g':
03650 grepable=True;
03651 break;
03652 }
03653 }
03654
03655 poptGetArg(pc);
03656
03657
03658
03659 if ( port != 0 )
03660 cli_cm_set_port( port );
03661
03662
03663
03664
03665
03666 AllowDebugChange = False;
03667
03668
03669
03670
03671
03672
03673
03674 fstrcpy( new_workgroup, lp_workgroup() );
03675 pstrcpy( calling_name, global_myname() );
03676
03677 if ( override_logfile )
03678 setup_logging( lp_logfile(), False );
03679
03680 load_case_tables();
03681
03682 if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) {
03683 fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n",
03684 argv[0], dyn_CONFIGFILE);
03685 }
03686
03687 load_interfaces();
03688
03689 if ( strlen(new_workgroup) != 0 )
03690 set_global_myworkgroup( new_workgroup );
03691 pstrcpy(workgroup, lp_workgroup());
03692
03693 if ( strlen(calling_name) != 0 )
03694 set_global_myname( calling_name );
03695 else
03696 pstrcpy( calling_name, global_myname() );
03697
03698 if(poptPeekArg(pc)) {
03699 pstrcpy(service,poptGetArg(pc));
03700
03701 string_replace(service, '\\','/');
03702
03703 if (count_chars(service,'/') < 3) {
03704 d_printf("\n%s: Not enough '/' characters in service\n",service);
03705 poptPrintUsage(pc, stderr, 0);
03706 exit(1);
03707 }
03708 }
03709
03710 if (poptPeekArg(pc) && !cmdline_auth_info.got_pass) {
03711 cmdline_auth_info.got_pass = True;
03712 pstrcpy(cmdline_auth_info.password,poptGetArg(pc));
03713 }
03714
03715 init_names();
03716
03717 if(new_name_resolve_order)
03718 lp_set_name_resolve_order(new_name_resolve_order);
03719
03720 if (!tar_type && !*query_host && !*service && !message) {
03721 poptPrintUsage(pc, stderr, 0);
03722 exit(1);
03723 }
03724
03725 poptFreeContext(pc);
03726
03727
03728
03729 cli_cm_set_credentials( &cmdline_auth_info );
03730 pstrcpy(username, cmdline_auth_info.username);
03731
03732 DEBUG(3,("Client started (version %s).\n", SAMBA_VERSION_STRING));
03733
03734 if (tar_type) {
03735 if (cmdstr)
03736 process_command_string(cmdstr);
03737 return do_tar_op(base_directory);
03738 }
03739
03740 if (*query_host) {
03741 char *qhost = query_host;
03742 char *slash;
03743
03744 while (*qhost == '\\' || *qhost == '/')
03745 qhost++;
03746
03747 if ((slash = strchr_m(qhost, '/'))
03748 || (slash = strchr_m(qhost, '\\'))) {
03749 *slash = 0;
03750 }
03751
03752 if ((p=strchr_m(qhost, '#'))) {
03753 *p = 0;
03754 p++;
03755 sscanf(p, "%x", &name_type);
03756 cli_cm_set_dest_name_type( name_type );
03757 }
03758
03759 return do_host_query(qhost);
03760 }
03761
03762 if (message) {
03763 return do_message_op();
03764 }
03765
03766 if (process(base_directory)) {
03767 return 1;
03768 }
03769
03770 return rc;
03771 }