/* Unix SMB/Netbios implementation. Version 1.9. SMB client Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1998-2000 Copyright (C) Gerald Carter 2000 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef SYSLOG #undef SYSLOG #endif #include "includes.h" #include "rpc_parse.h" #ifndef REGISTER #define REGISTER 0 #endif extern pstring debugf; extern pstring global_myname; extern pstring user_socket_options; /* found in rpc_client/cli_connect.c */ extern struct user_creds *usr_creds; extern int DEBUGLEVEL; #define CNV_LANG(s) dos2unix_format(s,False) #define CNV_INPUT(s) unix2dos_format(s,True) static int process_tok(fstring tok); static uint32 cmd_help(struct client_info *info, int argc, char *argv[]); static uint32 cmd_quit(struct client_info *info, int argc, char *argv[]); static uint32 cmd_set(struct client_info *info, int argc, char *argv[]); static uint32 cmd_use(struct client_info *info, int argc, char *argv[]); static struct user_creds usr; struct client_info cli_info; char **cmd_argv = NULL; uint32 cmd_argc = 0; FILE *out_hnd; static void cmd_set_free(struct command_set *item) { if (item != NULL) safe_free(item->name); safe_free(item); } static struct command_set *cmd_set_dup(const struct command_set *from) { if (from != NULL) { struct command_set *copy; copy = (struct command_set*)malloc(sizeof(struct command_set)); if (copy != NULL) { memcpy(copy, from, sizeof(struct command_set)); if (from->name != NULL) copy->name = strdup(from->name); } return copy; } return NULL; } void free_cmd_set_array(uint32 num_entries, struct command_set **entries) { void (*fn) (void *) = (void (*)(void *))&cmd_set_free; free_void_array(num_entries, (void **)entries, *fn); } struct command_set *add_cmd_set_to_array(uint32 *len, struct command_set ***array, const struct command_set *cmd) { void *(*fn) (const void *) = (void *(*)(const void *))&cmd_set_dup; return (struct command_set *)add_copy_to_array(len, (void ***)array, (const void *)cmd, *fn, False); } static struct command_set **commands = NULL; static uint32 num_commands = 0; /**************************************************************************** add in individual command-sets. ****************************************************************************/ void add_command_set(const struct command_set *cmds) { while (! ((cmds->fn==NULL) && (strlen(cmds->name)==0))) { add_cmd_set_to_array(&num_commands, &commands, cmds); cmds++; } } /**************************************************************************** This defines the commands supported by this client ****************************************************************************/ static struct command_set general_commands[] = { /* * maintenance */ {"General", NULL, NULL, {NULL, NULL}}, { "set", cmd_set, "run rpcclient inside rpcclient (change options etc.)", {NULL, NULL} }, { "use", cmd_use, "net use and net view", {NULL, NULL} }, /* * bye bye */ { "quit", cmd_quit, "logoff the server", {NULL, NULL} }, { "q", cmd_quit, "logoff the server", {NULL, NULL} }, { "exit", cmd_quit, "logoff the server", {NULL, NULL} }, { "bye", cmd_quit, "logoff the server", {NULL, NULL} }, /* * eek! */ { "help", cmd_help, "[command] give help on a command", {NULL, NULL} }, { "?", cmd_help, "[command] give help on a command", {NULL, NULL} }, /* * shell */ { "!", NULL, "run a shell command on the local system", {NULL, NULL} }, /* * oop! */ { "", NULL, NULL, {NULL, NULL} } }; /**************************************************************************** do a (presumably graceful) quit... ****************************************************************************/ static uint32 cmd_quit(struct client_info *info, int argc, char *argv[]) { #ifdef MEM_MAN { extern FILE *dbf; smb_mem_write_status(dbf); smb_mem_write_errors(dbf); smb_mem_write_verbose(dbf); dbgflush(); } #endif free_connections(); exit(0); /* NOTREACHED */ return 0; } /**************************************************************************** help ****************************************************************************/ static uint32 cmd_help(struct client_info *info, int argc, char *argv[]) { int i = 0; /* get help on a specific command */ if (argc > 1) { if ((i = process_tok(argv[0])) >= 0) { fprintf(out_hnd, "HELP %s:\n\t%s\n\n", commands[i]->name, commands[i]->description); } return 0; } /* Print out the list of available commands */ for (i = 0; i < num_commands; i++) { if (commands[i]->fn == NULL) fprintf (out_hnd, "\n"); else fprintf (out_hnd, "\t"); fprintf(out_hnd, "%s\n", commands[i]->name); } return 0; } /******************************************************************* lookup a command string in the list of commands, including abbreviations ******************************************************************/ static int process_tok(char *tok) { int i = 0, matches = 0; int cmd = 0; int tok_len = strlen(tok); for (i = 0; i < num_commands; i++) { if (strequal(commands[i]->name, tok)) { matches = 1; cmd = i; break; } else if (strnequal(commands[i]->name, tok, tok_len)) { matches++; cmd = i; } } if (matches == 0) return (-1); else if (matches == 1) return (cmd); else return (-2); } /**************************************************************************** turn command line into command argument array ****************************************************************************/ static BOOL get_cmd_args(char *line) { char *ptr = line; pstring tok; cmd_argc = 0; cmd_argv = NULL; /* get the first part of the command */ if (!next_token(&ptr, tok, NULL, sizeof(tok))) return False; do { add_chars_to_array(&cmd_argc, &cmd_argv, tok); } while (next_token(NULL, tok, NULL, sizeof(tok))); add_chars_to_array(&cmd_argc, &cmd_argv, NULL); return True; } /* command options mask */ static uint32 cmd_set_options = 0xffffffff; /**************************************************************************** process commands from the client ****************************************************************************/ static uint32 do_command(struct client_info *info, char *line) { uint32 status = 0x0; int i; if (!get_cmd_args(line)) return False; if (cmd_argc == 0) return False; i = process_tok(cmd_argv[0]); if (i >= 0) { int argc = ((int)cmd_argc); char **argv = cmd_argv; optind = 0; status = commands[i]->fn(info, argc, argv); } else if (i == -2) { fprintf(out_hnd, "%s: command abbreviation ambiguous\n", CNV_LANG(cmd_argv[0])); } else { fprintf(out_hnd, "%s: command not found\n", CNV_LANG(cmd_argv[0])); } free_char_array(cmd_argc, cmd_argv); parse_talloc_free(); /* Free up init_XXX memory. */ return status; } /**************************************************************************** process commands from the client ****************************************************************************/ static uint32 process(struct client_info *info, char *cmd_str) { uint32 status = 0; pstring line; char *cmd = cmd_str; if (cmd != NULL) { while (cmd[0] != '\0') { char *p; if ((p = strchr(cmd, ';')) == 0) { strncpy(line, cmd, 999); line[1000] = '\0'; cmd += strlen(cmd); } else { if (p - cmd > 999) p = cmd + 999; strncpy(line, cmd, p - cmd); line[p - cmd] = '\0'; cmd = p + 1; } /* input language code to internal one */ CNV_INPUT(line); status = do_command(info, line); if (status == 0x0) { continue; } } } else { while (!feof(stdin)) { #ifdef HAVE_LIBREADLINE char *ret_line; #endif pstring pline; BOOL at_sym = False; pline[0] = 0; if (info->show_prompt) { safe_strcat(pline, "[", sizeof(pline) - 1); if (usr.ntc.domain[0] != 0) { safe_strcat(pline, usr.ntc.domain, sizeof(pline) - 1); safe_strcat(pline, "\\", sizeof(pline) - 1); at_sym = True; } if (usr.ntc.user_name[0] != 0) { safe_strcat(pline, usr.ntc.user_name, sizeof(pline) - 1); at_sym = True; } if (at_sym) safe_strcat(pline, "@", sizeof(pline) - 1); safe_strcat(pline, cli_info.dest_host, sizeof(pline) - 1); safe_strcat(pline, "]$ ", sizeof(pline) - 1); } #ifndef HAVE_LIBREADLINE /* display a prompt */ fprintf(out_hnd, "%s", CNV_LANG(pline)); fflush(out_hnd); cli_use_wait_keyboard(); /* and get a response */ if (!fgets(line, 1000, stdin)) { break; } #else /* HAVE_LIBREADLINE */ if (!(ret_line = readline(pline))) break; safe_free(ret_line); /* Copy read line to samba buffer */ pstrcpy(line, rl_line_buffer); /* Add to history */ if (strlen(line) > 0) add_history(line); #endif /* input language code to internal one */ CNV_INPUT(line); /* special case - first char is ! */ if (*line == '!') { system(line + 1); continue; } fprintf(out_hnd, "%s\n", line); status = do_command(info, line); if (status == 0x0) { continue; } } } return status; } /**************************************************************************** usage on the program ****************************************************************************/ static void usage(char *pname) { fprintf(out_hnd, "Usage: %s [\\server] [password] [-U user] -[W domain] [-l log] ", pname); fprintf(out_hnd, "\nVersion %s\n", VERSION); fprintf(out_hnd, "\t-d debuglevel set the debuglevel\n"); fprintf(out_hnd, "\t-S <\\>server Server to connect to\n"); fprintf(out_hnd, "\t-l log basename. Basename for log/debug files\n"); fprintf(out_hnd, "\t-n netbios name. Use this name as my netbios name\n"); fprintf(out_hnd, "\t-N don't ask for a password\n"); fprintf(out_hnd, "\t-m max protocol set the max protocol level\n"); fprintf(out_hnd, "\t-I dest IP use this IP to connect to\n"); fprintf(out_hnd, "\t-E write messages to stderr instead of stdout\n"); fprintf(out_hnd, "\t-A filename file from which to read the authentication credentials\n"); fprintf(out_hnd, "\t-P hide prompt (used for shell scripts)\n"); fprintf(out_hnd, "\t-U username set the network username\n"); fprintf(out_hnd, "\t-U username%%pass set the network username and password\n"); fprintf(out_hnd, "\t-W domain set the domain name\n"); fprintf(out_hnd, "\t-c 'command string' execute semicolon separated commands\n"); fprintf(out_hnd, "\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"); fprintf(out_hnd, "\n"); } #ifdef HAVE_LIBREADLINE /**************************************************************************** GNU readline completion functions ****************************************************************************/ /* Complete an rpcclient command */ static char *complete_cmd(char *text, int state) { static int cmd_index; char *name; /* Initialise */ if (state == 0) cmd_index = 0; /* Return the next name which partially matches the list of commands */ while ((cmd_index < num_commands) && (strlen(name = commands[cmd_index++]->name) > 0)) { if (strncmp(name, text, strlen(text)) == 0) return strdup(name); } return NULL; } /* Main completion function */ static char **completion_fn(char *text, int start, int end) { pstring cmd_partial; int cmd_index; int num_words; int i; char lastch = ' '; (void)get_cmd_args(rl_line_buffer); safe_strcpy(cmd_partial, rl_line_buffer, MAX(sizeof(cmd_partial), end) - 1); /* Complete rpcclient command */ if (start == 0) return completion_matches(text, complete_cmd); /* Count # of words in command */ num_words = 0; for (i = 0; i <= end; i++) { if ((rl_line_buffer[i] != ' ') && (lastch == ' ')) num_words++; lastch = rl_line_buffer[i]; } if (rl_line_buffer[end] == ' ') num_words++; /* Work out which command we are completing for */ for (cmd_index = 0; cmd_index < num_commands; cmd_index++) { /* Check each command in array */ if (strncmp(rl_line_buffer, commands[cmd_index]->name, strlen(commands[cmd_index]->name)) == 0) { /* Call appropriate completion function */ if (num_words == 2 || num_words == 3) { char *(*fn) (char *, int); fn = commands[cmd_index]->compl_args[num_words - 2]; if (fn != NULL) return completion_matches(text, fn); } } } /* Eeek! */ return NULL; } /* To avoid filename completion being activated when no valid completions are found, we assign this stub completion function to the rl_completion_entry_function variable. */ static char *complete_cmd_null(char *text, int state) { return NULL; } #endif /* HAVE_LIBREADLINE */ static void set_user_password(struct ntuser_creds *u, BOOL got_pass, char *password) { /* set the password cache info */ if (got_pass) { if (password == NULL) { DEBUG(10, ("set_user_password: NULL pwd\n")); pwd_set_nullpwd(&u->pwd); } else { /* generate 16 byte hashes */ DEBUG(10, ("set_user_password: generate\n")); if (lp_encrypted_passwords()) pwd_make_lm_nt_16(&u->pwd, password); else pwd_set_cleartext(&u->pwd, password); } } else { DEBUG(10, ("set_user_password: read\n")); pwd_read(&u->pwd, "Enter Password:", True); } } static uint32 cmd_use(struct client_info *info, int argc, char *argv[]) { int opt; BOOL net_use = False; BOOL net_use_add = True; BOOL force_close = False; fstring dest_host; fstring srv_name; BOOL null_pwd = False; BOOL got_pwd = False; pstring password; if (usr_creds != NULL) copy_nt_creds(&usr.ntc, &usr_creds->ntc); else copy_nt_creds(&usr.ntc, NULL); pstrcpy(dest_host, cli_info.dest_host); pstrcpy(usr.ntc.user_name, optarg); info->reuse = False; if (argc <= 1) { report(out_hnd, "net [\\\\Server] [-U user%%pass] [-W domain] [-d] [-f]\n"); report(out_hnd, " -d Deletes a connection\n"); report(out_hnd, " -f Forcibly deletes a connection\n"); report(out_hnd, "net -u Shows all connections\n"); return 0; } if (argc > 1 && (*argv[1] != '-')) { if (strnequal("\\\\", argv[1], 2) || strnequal("//", argv[1], 2)) { pstrcpy(dest_host, argv[1] + 2); } argc--; argv++; } while ((opt = getopt(argc, argv, "udU:W:")) != EOF) { switch (opt) { case 'u': { net_use = True; break; } case 'U': { char *lp; pstrcpy(usr.ntc.user_name, optarg); if ((lp = strchr(usr.ntc.user_name, '%'))) { *lp = 0; pstrcpy(password, lp + 1); memset(strchr(optarg, '%') + 1, 'X', strlen(password)); got_pwd = True; } if (usr.ntc.user_name[0] == 0 && password[0] == 0) { null_pwd = True; } break; } case 'N': { null_pwd = True; } case 'W': { pstrcpy(usr.ntc.domain, optarg); break; } case 'd': { net_use_add = False; break; } case 'f': { force_close = True; break; } default: { report(out_hnd, "net -S \\server [-U user%%pass] [-W domain] [-d] [-f]\n"); report(out_hnd, "net -u\n"); break; } } } if (strnequal("\\\\", dest_host, 2)) { fstrcpy(srv_name, dest_host); } else { fstrcpy(srv_name, "\\\\"); fstrcat(srv_name, dest_host); } strupper(srv_name); if (net_use) { int i; uint32 num_uses; struct use_info **use; cli_net_use_enum(&num_uses, &use); if (num_uses == 0) { report(out_hnd, "No connections\n"); } else { report(out_hnd, "Connections:\n"); for (i = 0; i < num_uses; i++) { if (use[i] != NULL && use[i]->connected) { report(out_hnd, "Server:\t%s\t",use[i]->srv_name); report(out_hnd, "Key:\t[%d,%x]\t",use[i]->key.pid, use[i]->key.vuid); report(out_hnd, "User:\t%s\t", use[i]->user_name); report(out_hnd, "Domain:\t%s\n", use[i]->domain); } } } } else if (net_use_add) { BOOL isnew; if (null_pwd) set_user_password(&usr.ntc, True, NULL); else set_user_password(&usr.ntc, got_pwd, password); /* paranoia: destroy the local copy of the password */ ZERO_STRUCT(password); report(out_hnd, "Server:\t%s:\tUser:\t%s\tDomain:\t%s\n", srv_name, usr.ntc.user_name, usr.ntc.domain); report(out_hnd, "Connection:\t"); if (cli_net_use_add(srv_name, &usr.ntc, info->reuse, &isnew) != NULL) report(out_hnd, "OK\n"); else report(out_hnd, "FAILED\n"); } else { BOOL closed; report(out_hnd, "Server:\t%s:\tUser:\t%s\tDomain:\t%s\n", srv_name, usr.ntc.user_name, usr.ntc.domain); report(out_hnd, "Connection:\t"); if (!cli_net_use_del(srv_name, &usr.ntc, force_close, &closed)) report(out_hnd, ": Does not exist\n"); else if (force_close && closed) report(out_hnd, ": Forcibly terminated\n"); else if (closed) report(out_hnd, ": Terminated\n"); else report(out_hnd, ": Unlinked\n"); } /* paranoia: destroy the local copy of the password */ ZERO_STRUCT(password); return 0; } /****************************************************************** allow or disallow automatic connections. rpctorture, because it does not reestablish connections after sys_fork(), fails unless the connection is established AFTER the sys_fork() ******************************************************************/ static BOOL auto_connect = True; void cmd_set_no_autoconnect(void) { auto_connect = False; } #define CMD_STR 0x1 #define CMD_DBF 0x2 #define CMD_SVC 0x4 #define CMD_TERM 0x8 #define CMD_PASS 0x10 #define CMD_USER 0x20 #define CMD_NOPW 0x40 #define CMD_DBLV 0x80 #define CMD_HELP 0x100 #define CMD_SOCK 0x200 #define CMD_IFACE 0x400 #define CMD_DOM 0x800 #define CMD_IP 0x1000 #define CMD_HOST 0x2000 #define CMD_NAME 0x4000 #define CMD_DBG 0x8000 #define CMD_SCOPE 0x10000 #define CMD_INTER 0x20000 static void read_authfile (char *filename, char* username, char* password) { FILE *auth; fstring buf; uint16 len = 0; char *ptr, *val, *param; if ((auth=sys_fopen(filename, "r")) == NULL) { /* fail if we can't open the credentials file */ DEBUG(0,("ERROR: Unable to open credentials file!\n")); return; } while (!feof(auth)) { /* get a line from the file */ if (!fgets (buf, sizeof(buf), auth)) continue; len = strlen(buf); /* skip empty lines */ if ((len) && (buf[len-1]=='\n')) { buf[len-1] = '\0'; len--; } if (len == 0) continue; /* break up the line into parameter & value. will need to eat a little whitespace possibly */ param = buf; if (!(ptr = strchr (buf, '='))) continue; val = ptr+1; *ptr = '\0'; /* eat leading white space */ while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) val++; if (strwicmp("password", param) == 0) { pstrcpy(password, val); cmd_set_options |= CMD_PASS; } else if (strwicmp("username", param) == 0) { pstrcpy(username, val); cmd_set_options |= CMD_USER; } memset(buf, 0, sizeof(buf)); } fclose(auth); return; } static uint32 cmd_set(CLIENT_INFO *info, int argc, char *argv[]) { BOOL interactive = True; char *cmd_str = NULL; int opt; extern FILE *dbf; extern char *optarg; static pstring servicesf = CONFIGFILE; pstring term_code; pstring password; /* local copy only, if one is entered */ fstring srv_name; int new_debuglevel = -1; password[0] = 0; usr_creds = &usr; info->reuse = False; #ifdef KANJI pstrcpy(term_code, KANJI); #else /* KANJI */ *term_code = 0; #endif /* KANJI */ if (argc > 1 && (*argv[1] != '-')) { if (strnequal("\\\\", argv[1], 2) || strnequal("//", argv[1], 2)) { cmd_set_options |= CMD_HOST; pstrcpy(cli_info.dest_host, argv[1] + 2); strupper(cli_info.dest_host); } argc--; argv++; } if (argc > 1 && (*argv[1] != '-')) { cmd_set_options |= CMD_PASS; pstrcpy(password, argv[1]); memset(argv[1], 'X', strlen(argv[1])); argc--; argv++; } while ((opt = getopt(argc, argv,"PRs:O:M:S:i:Nn:d:l:hI:EB:U:L:t:m:W:T:D:c:A:")) != EOF) { switch (opt) { /* reuse connections in the case of a previous authentication */ case 'R': { info->reuse = True; break; } /* max protocol */ case 'm': { /* FIXME ... max_protocol seems to be funny here */ int max_protocol = 0; max_protocol = interpret_protocol(optarg, max_protocol); fprintf(stderr, "max protocol not currently supported\n"); break; } /* socket options */ case 'O': { cmd_set_options |= CMD_SOCK; pstrcpy(user_socket_options, optarg); break; } /* define the server to connect to */ case 'S': { cmd_set_options |= CMD_HOST; pstrcpy(cli_info.dest_host, optarg); strupper(cli_info.dest_host); break; } /* username for the connection -- support the username%password format as well */ case 'U': { char *lp; cmd_set_options |= CMD_USER; pstrcpy(usr.ntc.user_name, optarg); if ((lp = strchr(usr.ntc.user_name, '%'))) { *lp = 0; pstrcpy(password, lp + 1); cmd_set_options |= CMD_PASS; memset(lp+1, 'X', strlen(password)); } break; } /* authfile -- only get the username and password from the file */ case 'A': { read_authfile (optarg, usr.ntc.user_name, password); break; } /* define the workgroup/domain name */ case 'W': { cmd_set_options |= CMD_DOM; pstrcpy(usr.ntc.domain, optarg); break; } /* should we display a command prompt at all */ case 'P': { /* optarg == prompt string ? */ info->show_prompt = False; break; } /* send to stderr instaed of stdout */ case 'E': { cmd_set_options |= CMD_DBG; dbf = stderr; break; } /* IP address of destination host */ case 'I': { cmd_set_options |= CMD_IP; cli_info.dest_ip = *interpret_addr2(optarg); if (zero_ip(cli_info.dest_ip)) { free_connections(); exit(1); } break; } /* define netbios name of client machine we are on */ case 'n': { cmd_set_options |= CMD_NAME; fstrcpy(global_myname, optarg); break; } /* do not prompt for a password. Implies anonymous connection unless the password was passed in username%password form */ case 'N': { cmd_set_options |= CMD_NOPW | CMD_PASS; break; } /* debug level */ case 'd': { cmd_set_options |= CMD_DBLV; if (*optarg == 'A') new_debuglevel = 10000; else new_debuglevel = atoi(optarg); break; } /* log file name */ case 'l': { cmd_set_options |= CMD_INTER; slprintf(debugf, sizeof(debugf) - 1, "%s.client", optarg); interactive = False; break; } /* command string to be executed */ case 'c': { cmd_set_options |= CMD_STR; cmd_str = optarg; break; } /* program usage/help screen */ case 'h': { cmd_set_options |= CMD_HELP; usage(argv[0]); break; } /* config file to use */ case 's': { cmd_set_options |= CMD_SVC; pstrcpy(servicesf, optarg); break; } /* terminal code */ case 't': { cmd_set_options |= CMD_TERM; pstrcpy(term_code, optarg); break; } default: { cmd_set_options |= CMD_HELP; usage(argv[0]); break; } } } if (cmd_set_options & CMD_INTER) { setup_logging(debugf, interactive); if (!interactive) reopen_logs(); } strupper(global_myname); fstrcpy(cli_info.myhostname, global_myname); if (cmd_set_options & CMD_SVC) { if (!lp_load(servicesf, True, False, False)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); } } if (new_debuglevel != -1) { DEBUGLEVEL = new_debuglevel; } if (cmd_set_options & CMD_INTER) { load_interfaces(); } DEBUG(10, ("cmd_set: options: %x\n", cmd_set_options)); if (cmd_set_options & CMD_HELP) { return 0; } /* NULL password if specified or is username is empty */ if ((cmd_set_options & CMD_NOPW) || (strlen(usr.ntc.user_name) == 0)) set_user_password(&usr.ntc, True, NULL); else set_user_password(&usr.ntc, ((cmd_set_options & CMD_PASS) != 0), password); /* paranoia: destroy the local copy of the password */ ZERO_STRUCT(password); if (strcmp(cli_info.dest_host, "*") == 0) { /* special case - we want the PDC */ struct in_addr ip; if (!resolve_srv_name(cli_info.dest_host, cli_info.dest_host, &ip)) { report(out_hnd, "ERROR: Failed to find the PDC\n"); return 1; } } fstrcpy(srv_name, "\\\\"); fstrcat(srv_name, cli_info.dest_host); strupper(srv_name); if (auto_connect) { BOOL isnew; report(out_hnd, "Server:\t%s:\tUser:\t%s\tDomain:\t%s\n", srv_name, usr.ntc.user_name, usr.ntc.domain); report(out_hnd, "Connection:\t"); if (cli_net_use_add(srv_name, &usr.ntc, info->reuse, &isnew) != NULL) { report(out_hnd, "OK\n"); } else { report(out_hnd, "FAILED\n"); } /* ???? --jerry usr_creds = NULL; */ } if (cmd_str != NULL) return process(&cli_info, cmd_str); return 0; } static void read_user_env(struct ntuser_creds *u) { pstring password; password[0] = 0; if (getenv("USER")) { char *p; pstrcpy(u->user_name, getenv("USER")); /* modification to support userid%passwd syntax in the USER var 25.Aug.97, jdblair@uab.edu */ if ((p = strchr(u->user_name, '%'))) { *p = 0; pstrcpy(password, p + 1); memset(strchr(getenv("USER"), '%') + 1, 'X', strlen(password)); } } /* modification to support PASSWD environmental var 25.Aug.97, jdblair@uab.edu */ if (getenv("PASSWD")) pstrcpy(password, getenv("PASSWD")); if (*u->user_name == 0 && getenv("LOGNAME")) pstrcpy(u->user_name, getenv("LOGNAME")); set_user_password(u, True, password); /* paranoia: destroy the local copy of the password */ ZERO_STRUCT(password); } static void readline_init(void) { #ifdef HAVE_LIBREADLINE /* Initialise GNU Readline */ rl_readline_name = "rpcclient"; rl_attempted_completion_function = completion_fn; rl_completion_entry_function = (Function *) complete_cmd_null; /* Initialise history list */ using_history(); #else int x; x = 0; /* stop compiler warnings */ #endif /* HAVE_LIBREADLINE */ } /**************************************************************************** main program ****************************************************************************/ int command_main(int argc, char *argv[]) { uint32 status; mode_t myumask = 0755; char progname[255], path[255], *s; pstring msg; DEBUGLEVEL = 2; charset_initialise(); /* add in the internal command set and the various client RPC groups--spoolss, lsa, etc... */ add_command_set(general_commands); /* usr_creds is a global most recently used set of user credentials retrieved from the connection list. */ copy_user_creds(&usr, NULL); usr_creds = &usr; usr.ptr_ntc = 1; out_hnd = stdout; /* retrieve the binary name used when invoking the program for instances like samedit, etc... */ strncpy(path, argv[0], 255); for (s = strtok(path, "/"); s; s = strtok(NULL, "/")) fstrcpy(progname, s); slprintf(debugf, sizeof(debugf) - 1, "%s/log.%s", LOGFILEBASE, progname); /* initialize usr */ pstrcpy(usr.ntc.domain, ""); pstrcpy(usr.ntc.user_name, ""); pstrcpy(cli_info.myhostname, ""); pstrcpy(cli_info.dest_host, ""); /* init client_info struct */ cli_info.dest_ip.s_addr = 0; cli_info.show_prompt = True; ZERO_STRUCT(cli_info.dom.level3_sid); ZERO_STRUCT(cli_info.dom.level5_sid); fstrcpy(cli_info.dom.level3_dom, ""); fstrcpy(cli_info.dom.level5_dom, ""); readline_init(); TimeInit(); init_connections(); myumask = umask(0); umask(myumask); if (!get_myname(global_myname)) { fprintf(stderr, "Failed to get my hostname.\n"); } if (argc < 2) { usage(argv[0]); free_connections(); exit(1); } read_user_env(&usr.ntc); cmd_set_options &= ~CMD_HELP; cmd_set_options &= ~CMD_STR; cmd_set_options &= ~CMD_NOPW; cmd_set_options &= ~CMD_USER; cmd_set_options &= ~CMD_PASS; codepage_initialise(lp_client_code_page()); /* parse the command line args init the first connection if possible process a command if passed in on the command line */ status = cmd_set(&cli_info, argc, argv); /* Should we exit? Are we done? */ if (cmd_set_options & (CMD_HELP|CMD_STR)) { free_connections(); get_safe_nt_error_msg(status, msg, sizeof(msg)); report(out_hnd, "Exit Status: %s\n", msg); /* unix only has 8 bit error codes - blergh */ exit(status & 0xFF); } DEBUG(3, ("%s client started (version %s)\n", timestring(False), VERSION)); /* enter shell mode */ status = process(&cli_info, NULL); /* cleanup */ free_connections(); free_cmd_set_array(num_commands, commands); num_commands = 0; commands = NULL; /* report and exit */ get_safe_nt_error_msg(status, msg, sizeof(msg)); report(out_hnd, "Exit Status: %s\n", msg); return status; }