1 /*
2 Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <ndb_global.h>
26 #include <ndb_opts.h>
27
28 // copied from mysql.cc to get readline
29 extern "C" {
30 #if defined(_WIN32)
31 #include <conio.h>
32 #elif !defined(__NETWARE__)
33 #include <readline.h>
34 extern "C" int add_history(const char *command); /* From readline directory */
35 extern "C" int read_history(const char *command);
36 extern "C" int write_history(const char *command);
37 #define HAVE_READLINE
38 #endif
39 }
40
41 #include <NdbMain.h>
42 #include <BaseString.hpp>
43 #include <NdbOut.hpp>
44 #include <mgmapi.h>
45 #include <ndb_version.h>
46
47 #include "ndb_mgmclient.hpp"
48
49 const char *load_default_groups[]= { "mysql_cluster","ndb_mgm",0 };
50
51
52 static Ndb_mgmclient* com;
53
54 static const char default_prompt[]= "ndb_mgm> ";
55 static unsigned opt_try_reconnect;
56 static const char *prompt= default_prompt;
57 static char *opt_execute_str= 0;
58 static unsigned opt_verbose = 1;
59
60 static struct my_option my_long_options[] =
61 {
62 NDB_STD_OPTS("ndb_mgm"),
63 { "execute", 'e',
64 "execute command and exit",
65 (uchar**) &opt_execute_str, (uchar**) &opt_execute_str, 0,
66 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
67 { "try-reconnect", 't',
68 "Specify number of tries for connecting to ndb_mgmd (0 = infinite)",
69 (uchar**) &opt_try_reconnect, (uchar**) &opt_try_reconnect, 0,
70 GET_UINT, REQUIRED_ARG, 3, 0, 0, 0, 0, 0 },
71 { "verbose", 'v',
72 "Control the amount of printout",
73 (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0,
74 GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
75 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
76 };
77
short_usage_sub(void)78 static void short_usage_sub(void)
79 {
80 ndb_short_usage_sub("[hostname [port]]");
81 }
82
usage()83 static void usage()
84 {
85 ndb_usage(short_usage_sub, load_default_groups, my_long_options);
86 }
87
88 static bool
read_and_execute(int try_reconnect)89 read_and_execute(int try_reconnect)
90 {
91 static char *line_read = (char *)NULL;
92
93 /* If the buffer has already been allocated, return the memory
94 to the free pool. */
95 if (line_read)
96 {
97 free (line_read);
98 line_read = (char *)NULL;
99 }
100 #ifdef HAVE_READLINE
101 /* Get a line from the user. */
102 line_read = readline (prompt);
103 /* If the line has any text in it, save it on the history. */
104 if (line_read && *line_read)
105 add_history (line_read);
106 #else
107 static char linebuffer[254];
108 fputs(prompt, stdout);
109 linebuffer[sizeof(linebuffer)-1]=0;
110 line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
111 if (line_read == linebuffer) {
112 char *q=linebuffer;
113 while (*q > 31) q++;
114 *q=0;
115 line_read= strdup(linebuffer);
116 }
117 #endif
118 return com->execute(line_read, try_reconnect, 1);
119 }
120
main(int argc,char ** argv)121 int main(int argc, char** argv){
122 NDB_INIT(argv[0]);
123
124 ndb_opt_set_usage_funcs(short_usage_sub, usage);
125 ndb_load_defaults(NULL, load_default_groups,&argc,&argv);
126 int ho_error;
127 #ifndef NDEBUG
128 opt_debug= "d:t:O,/tmp/ndb_mgm.trace";
129 #endif
130 if ((ho_error=handle_options(&argc, &argv, my_long_options,
131 ndb_std_get_one_option)))
132 exit(ho_error);
133
134 BaseString connect_str(opt_ndb_connectstring);
135 if(argc == 1) {
136 connect_str.assfmt("%s", argv[0]);
137 } else if (argc >= 2) {
138 connect_str.assfmt("%s:%s", argv[0], argv[1]);
139 }
140
141 if (!isatty(0) || opt_execute_str)
142 {
143 prompt= 0;
144 }
145
146 com = new Ndb_mgmclient(connect_str.c_str(), opt_verbose);
147 int ret= 0;
148 BaseString histfile;
149 if (!opt_execute_str)
150 {
151 #ifdef HAVE_READLINE
152 char *histfile_env= getenv("NDB_MGM_HISTFILE");
153 if (histfile_env)
154 histfile.assign(histfile_env,strlen(histfile_env));
155 else if(getenv("HOME"))
156 {
157 histfile.assign(getenv("HOME"),strlen(getenv("HOME")));
158 histfile.append("/.ndb_mgm_history");
159 }
160 if (histfile.length())
161 read_history(histfile.c_str());
162 #endif
163
164 ndbout << "-- NDB Cluster -- Management Client --" << endl;
165 while(read_and_execute(opt_try_reconnect))
166 ;
167
168 #ifdef HAVE_READLINE
169 if (histfile.length())
170 {
171 BaseString histfile_tmp;
172 histfile_tmp.assign(histfile);
173 histfile_tmp.append(".TMP");
174 if(!write_history(histfile_tmp.c_str()))
175 my_rename(histfile_tmp.c_str(), histfile.c_str(), MYF(MY_WME));
176 }
177 #endif
178 }
179 else
180 {
181 com->execute(opt_execute_str, opt_try_reconnect, 0, &ret);
182 }
183 delete com;
184
185 ndb_end(opt_ndb_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
186
187 // Don't allow negative return code
188 if (ret < 0)
189 ret = 255;
190 return ret;
191 }
192
193