~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to server-tools/instance-manager/parse_output.cc

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2004 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#include "parse_output.h"
 
17
 
 
18
#include <my_global.h>
 
19
#include <my_sys.h>
 
20
#include <m_string.h>
 
21
 
 
22
#include <stdio.h>
 
23
 
 
24
#include "parse.h"
 
25
#include "portability.h"
 
26
 
 
27
/**************************************************************************
 
28
  Private module implementation.
 
29
**************************************************************************/
 
30
 
 
31
namespace { /* no-indent */
 
32
 
 
33
/*************************************************************************/
 
34
 
 
35
void trim_space(const char **text, uint *word_len)
 
36
{
 
37
  const char *start= *text;
 
38
  while (*start != 0 && *start == ' ')
 
39
    start++;
 
40
  *text= start;
 
41
 
 
42
  int len= strlen(start);
 
43
  const char *end= start + len - 1;
 
44
  while (end > start && my_isspace(&my_charset_latin1, *end))
 
45
    end--;
 
46
  *word_len= (end - start)+1;
 
47
}
 
48
 
 
49
/*************************************************************************/
 
50
 
 
51
/**
 
52
  @brief A facade to the internal workings of optaining the output from an
 
53
  executed system process.
 
54
*/
 
55
 
 
56
class Mysqld_output_parser
 
57
{
 
58
public:
 
59
  Mysqld_output_parser()
 
60
  { }
 
61
 
 
62
  virtual ~Mysqld_output_parser()
 
63
  { }
 
64
 
 
65
public:
 
66
  bool parse(const char *command,
 
67
             const char *option_name_str,
 
68
             uint option_name_length,
 
69
             char *option_value_buf,
 
70
             size_t option_value_buf_size,
 
71
             enum_option_type option_type);
 
72
 
 
73
protected:
 
74
  /**
 
75
    @brief Run a process and attach stdout- and stdin-pipes to it.
 
76
 
 
77
    @param command The path to the process to be executed
 
78
 
 
79
    @return Error status.
 
80
      @retval TRUE An error occurred
 
81
      @retval FALSE Operation was a success
 
82
  */
 
83
 
 
84
  virtual bool run_command(const char *command)= 0;
 
85
 
 
86
 
 
87
  /**
 
88
    @brief Read a sequence of bytes from the executed process' stdout pipe.
 
89
 
 
90
    The sequence is terminated by either '\0', LF or CRLF tokens. The
 
91
    terminating token is excluded from the result.
 
92
 
 
93
    @param line_buffer A pointer to a character buffer
 
94
    @param line_buffer_size The size of the buffer in bytes
 
95
 
 
96
    @return Error status.
 
97
      @retval TRUE An error occured
 
98
      @retval FALSE Operation was a success
 
99
  */
 
100
 
 
101
  virtual bool read_line(char *line_buffer,
 
102
                         uint line_buffer_size)= 0;
 
103
 
 
104
 
 
105
  /**
 
106
    @brief Release any resources needed after a execution and parsing.
 
107
  */
 
108
 
 
109
  virtual bool cleanup()= 0;
 
110
};
 
111
 
 
112
/*************************************************************************/
 
113
 
 
114
bool Mysqld_output_parser::parse(const char *command,
 
115
                                 const char *option_name_str,
 
116
                                 uint option_name_length,
 
117
                                 char *option_value_buf,
 
118
                                 size_t option_value_buf_size,
 
119
                                 enum_option_type option_type)
 
120
{
 
121
  /* should be enough to store the string from the output */
 
122
  const int LINE_BUFFER_SIZE= 512;
 
123
  char line_buffer[LINE_BUFFER_SIZE];
 
124
 
 
125
  if (run_command(command))
 
126
    return TRUE;
 
127
 
 
128
  while (true)
 
129
  {
 
130
    if (read_line(line_buffer, LINE_BUFFER_SIZE))
 
131
    {
 
132
      cleanup();
 
133
      return TRUE;
 
134
    }
 
135
 
 
136
    uint found_word_len= 0;
 
137
    char *linep= line_buffer;
 
138
 
 
139
    line_buffer[sizeof(line_buffer) - 1]= '\0';        /* safety */
 
140
 
 
141
    /* Find the word(s) we are looking for in the line. */
 
142
 
 
143
    linep= strstr(linep, option_name_str);
 
144
 
 
145
    if (!linep)
 
146
      continue;
 
147
 
 
148
    linep+= option_name_length;
 
149
 
 
150
    switch (option_type)
 
151
    {
 
152
    case GET_VALUE:
 
153
      trim_space((const char**) &linep, &found_word_len);
 
154
 
 
155
      if (option_value_buf_size <= found_word_len)
 
156
      {
 
157
        cleanup();
 
158
        return TRUE;
 
159
      }
 
160
 
 
161
      strmake(option_value_buf, linep, found_word_len);
 
162
 
 
163
      break;
 
164
 
 
165
    case GET_LINE:
 
166
      strmake(option_value_buf, linep, option_value_buf_size - 1);
 
167
 
 
168
      break;
 
169
    }
 
170
 
 
171
    cleanup();
 
172
 
 
173
    return FALSE;
 
174
  }
 
175
}
 
176
 
 
177
/**************************************************************************
 
178
  Platform-specific implementation: UNIX.
 
179
**************************************************************************/
 
180
 
 
181
#ifndef __WIN__
 
182
 
 
183
class Mysqld_output_parser_unix : public Mysqld_output_parser
 
184
{
 
185
public:
 
186
  Mysqld_output_parser_unix() :
 
187
    m_stdout(NULL)
 
188
  { }
 
189
 
 
190
protected:
 
191
  virtual bool run_command(const char *command);
 
192
 
 
193
  virtual bool read_line(char *line_buffer,
 
194
                         uint line_buffer_size);
 
195
 
 
196
  virtual bool cleanup();
 
197
 
 
198
private:
 
199
  FILE *m_stdout;
 
200
};
 
201
 
 
202
bool Mysqld_output_parser_unix::run_command(const char *command)
 
203
{
 
204
  if (!(m_stdout= popen(command, "r")))
 
205
    return TRUE;
 
206
 
 
207
  /*
 
208
    We want fully buffered stream. We also want system to allocate
 
209
    appropriate buffer.
 
210
  */
 
211
 
 
212
  setvbuf(m_stdout, NULL, _IOFBF, 0);
 
213
 
 
214
  return FALSE;
 
215
}
 
216
 
 
217
bool Mysqld_output_parser_unix::read_line(char *line_buffer,
 
218
                                          uint line_buffer_size)
 
219
{
 
220
  char *retbuff = fgets(line_buffer, line_buffer_size, m_stdout);
 
221
  /* Remove any tailing new line charaters */
 
222
  if (line_buffer[line_buffer_size-1] == LF)
 
223
   line_buffer[line_buffer_size-1]= '\0';
 
224
  return (retbuff == NULL);
 
225
}
 
226
 
 
227
bool Mysqld_output_parser_unix::cleanup()
 
228
{
 
229
  if (m_stdout)
 
230
    pclose(m_stdout);
 
231
 
 
232
  return FALSE;
 
233
}
 
234
 
 
235
#else /* Windows */
 
236
 
 
237
/**************************************************************************
 
238
  Platform-specific implementation: Windows.
 
239
**************************************************************************/
 
240
 
 
241
class Mysqld_output_parser_win : public Mysqld_output_parser
 
242
{
 
243
public:
 
244
  Mysqld_output_parser_win() :
 
245
      m_internal_buffer(NULL),
 
246
      m_internal_buffer_offset(0),
 
247
      m_internal_buffer_size(0)
 
248
  { }
 
249
 
 
250
protected:
 
251
  virtual bool run_command(const char *command);
 
252
  virtual bool read_line(char *line_buffer,
 
253
                         uint line_buffer_size);
 
254
  virtual bool cleanup();
 
255
 
 
256
private:
 
257
  HANDLE m_h_child_stdout_wr;
 
258
  HANDLE m_h_child_stdout_rd;
 
259
  uint m_internal_buffer_offset;
 
260
  uint m_internal_buffer_size;
 
261
  char *m_internal_buffer;
 
262
};
 
263
 
 
264
bool Mysqld_output_parser_win::run_command(const char *command)
 
265
{
 
266
  BOOL op_status;
 
267
 
 
268
  SECURITY_ATTRIBUTES sa_attr;
 
269
  sa_attr.nLength= sizeof(SECURITY_ATTRIBUTES);
 
270
  sa_attr.bInheritHandle= TRUE;
 
271
  sa_attr.lpSecurityDescriptor= NULL;
 
272
 
 
273
  op_status= CreatePipe(&m_h_child_stdout_rd,
 
274
                        &m_h_child_stdout_wr,
 
275
                        &sa_attr,
 
276
                        0 /* Use system-default buffer size. */);
 
277
 
 
278
  if (!op_status)
 
279
    return TRUE;
 
280
 
 
281
  SetHandleInformation(m_h_child_stdout_rd, HANDLE_FLAG_INHERIT, 0);
 
282
 
 
283
  STARTUPINFO si_start_info;
 
284
  ZeroMemory(&si_start_info, sizeof(STARTUPINFO));
 
285
  si_start_info.cb= sizeof(STARTUPINFO);
 
286
  si_start_info.hStdError= m_h_child_stdout_wr;
 
287
  si_start_info.hStdOutput= m_h_child_stdout_wr;
 
288
  si_start_info.dwFlags|= STARTF_USESTDHANDLES;
 
289
 
 
290
  PROCESS_INFORMATION pi_proc_info;
 
291
 
 
292
  op_status= CreateProcess(NULL,           /* Application name. */
 
293
                           (char*)command, /* Command line. */
 
294
                           NULL,           /* Process security attributes. */
 
295
                           NULL,           /* Primary thread security attr.*/
 
296
                           TRUE,           /* Handles are inherited. */
 
297
                           0,              /* Creation flags. */
 
298
                           NULL,           /* Use parent's environment. */
 
299
                           NULL,           /* Use parent's curr. directory. */
 
300
                           &si_start_info, /* STARTUPINFO pointer. */
 
301
                           &pi_proc_info); /* Rec. PROCESS_INFORMATION. */
 
302
 
 
303
  if (!op_status)
 
304
  {
 
305
    CloseHandle(m_h_child_stdout_rd);
 
306
    CloseHandle(m_h_child_stdout_wr);
 
307
 
 
308
    return TRUE;
 
309
  }
 
310
 
 
311
  /* Close unnessary handles. */
 
312
 
 
313
  CloseHandle(pi_proc_info.hProcess);
 
314
  CloseHandle(pi_proc_info.hThread);
 
315
 
 
316
  return FALSE;
 
317
}
 
318
 
 
319
bool Mysqld_output_parser_win::read_line(char *line_buffer,
 
320
                                         uint line_buffer_size)
 
321
{
 
322
  DWORD dw_read_count= m_internal_buffer_size;
 
323
  bzero(line_buffer,line_buffer_size);
 
324
  char *buff_ptr= line_buffer;
 
325
  char ch;
 
326
 
 
327
  while ((unsigned)(buff_ptr - line_buffer) < line_buffer_size)
 
328
  {
 
329
    do
 
330
    {
 
331
      ReadFile(m_h_child_stdout_rd, &ch,
 
332
               1, &dw_read_count, NULL);
 
333
    } while ((ch == CR || ch == LF) && buff_ptr == line_buffer);
 
334
 
 
335
    if (dw_read_count == 0)
 
336
      return TRUE;
 
337
 
 
338
    if (ch == CR || ch == LF)
 
339
      break;
 
340
 
 
341
    *buff_ptr++ = ch;
 
342
  }
 
343
 
 
344
  return FALSE;
 
345
}
 
346
 
 
347
bool Mysqld_output_parser_win::cleanup()
 
348
{
 
349
  /* Close all handles. */
 
350
 
 
351
  CloseHandle(m_h_child_stdout_wr);
 
352
  CloseHandle(m_h_child_stdout_rd);
 
353
 
 
354
  return FALSE;
 
355
}
 
356
#endif
 
357
 
 
358
/*************************************************************************/
 
359
 
 
360
} /* End of private module implementation. */
 
361
 
 
362
/*************************************************************************/
 
363
 
 
364
/**
 
365
  @brief Parse output of the given command
 
366
 
 
367
  @param      command               The command to execute.
 
368
  @param      option_name_str       Option name.
 
369
  @param      option_name_length    Length of the option name.
 
370
  @param[out] option_value_buf      The buffer to store option value.
 
371
  @param      option_value_buf_size Size of the option value buffer.
 
372
  @param      option_type           Type of the option:
 
373
                                      - GET_LINE if we want to get all the
 
374
                                        line after the option name;
 
375
                                      - GET_VALUE otherwise.
 
376
 
 
377
  Execute the process by running "command". Find the "option name" and
 
378
  return the next word if "option_type" is GET_VALUE. Return the rest of
 
379
  the parsed string otherwise.
 
380
 
 
381
  @note This function has a separate windows implementation.
 
382
 
 
383
  @return The error status.
 
384
    @retval FALSE Ok, the option name has been found.
 
385
    @retval TRUE Error occured or the option name is not found.
 
386
*/
 
387
 
 
388
bool parse_output_and_get_value(const char *command,
 
389
                                const char *option_name_str,
 
390
                                uint option_name_length,
 
391
                                char *option_value_buf,
 
392
                                size_t option_value_buf_size,
 
393
                                enum_option_type option_type)
 
394
{
 
395
#ifndef __WIN__
 
396
  Mysqld_output_parser_unix parser;
 
397
#else /* __WIN__ */
 
398
  Mysqld_output_parser_win parser;
 
399
#endif
 
400
 
 
401
  return parser.parse(command,
 
402
                      option_name_str,
 
403
                      option_name_length,
 
404
                      option_value_buf,
 
405
                      option_value_buf_size,
 
406
                      option_type);
 
407
}