tools/ctdb: Pass memory context for returning nodes in parse_nodestring
[amitay/samba.git] / ctdb / libctdb / test / log.c
1 /*
2
3 This file is taken from nfsim (http://ozlabs.org/~jk/projects/nfsim/)
4
5 Copyright (c) 2003,2004 Jeremy Kerr & Rusty Russell
6
7 This file is part of nfsim.
8
9 nfsim is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 nfsim is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with nfsim; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 */
23 #include "log.h"
24 #include "tui.h"
25 #include "utils.h"
26 #include "expect.h"
27 #include <string.h>
28 #include <talloc.h>
29 #include <err.h>
30
31 static struct {
32         enum log_type   type;
33         char *          name;
34 } log_names[] = {
35         { LOG_WRITE,    "write" },
36         { LOG_READ,     "read" },
37         { LOG_LIB,      "lib" },
38         { LOG_VERBOSE,  "verbose" },
39 };
40
41 static int typemask = ~LOG_VERBOSE;
42
43 bool log_line(enum log_type type, const char *format, ...)
44 {
45         va_list ap;
46         char *line;
47         bool ret;
48
49         va_start(ap, format);
50         line = talloc_vasprintf(NULL, format, ap);
51         va_end(ap);
52
53         if (!type || (type & typemask)) {
54                 printf("%s\n", line);
55                 fflush(stdout);
56         }
57
58         ret = expect_log_hook(line);
59         talloc_free(line);
60         return ret;
61 }
62
63 static void log_partial_v(enum log_type type,
64                           char *buf,
65                           unsigned bufsize,
66                           const char *format,
67                           va_list ap)
68 {
69         char *ptr;
70         int len = strlen(buf);
71
72         /* write to the end of buffer */
73         if (vsnprintf(buf + len, bufsize - len - 1, format, ap)
74             > bufsize - len - 1) {
75                 errx(1, "log_line_partial buffer is full!");
76         }
77
78         ptr = buf;
79
80         /* print each bit that ends in a newline */
81         for (len = strcspn(ptr, "\n"); *(ptr + len);
82                         ptr += len, len = strcspn(ptr, "\n")) {
83                 log_line(type, "%.*s", len++, ptr);
84         }
85
86         /* if we've printed, copy any remaining (non-newlined)
87            parts (including the \0) to the front of buf */
88         memmove(buf, ptr, strlen(ptr) + 1);
89 }
90
91 void log_partial(enum log_type type, char *buf, unsigned bufsize,
92                  const char *format, ...)
93 {
94         va_list ap;
95
96         va_start(ap, format);
97         log_partial_v(type, buf, bufsize, format, ap);
98         va_end(ap);
99 }
100
101 static inline int parsetype(const char *type)
102 {
103         int i;
104
105         for (i = 0; i < ARRAY_SIZE(log_names); i++)
106                 if (streq(log_names[i].name, type))
107                         return log_names[i].type;
108
109         return 0;
110 }
111
112 static bool log_admin(int argc, char **argv)
113 {
114         int i;
115         int newtypemask = 0;
116
117         if (argc == 1) {
118                 log_line(LOG_UI, "current log types:", typemask);
119
120                 for (i = 0; i < ARRAY_SIZE(log_names); i++) {
121                         if (typemask & log_names[i].type)
122                                 log_line(LOG_UI, "\t%s", log_names[i].name);
123                 }
124                 return true;
125         }
126
127         if (argc == 2) {
128                 log_line(LOG_ALWAYS, "Expected =, + or - then args");
129                 return false;
130         }
131
132         for (i = 2; i < argc; i++) {
133                 int type;
134
135                 if (!(type = parsetype(argv[i]))) {
136                         log_line(LOG_ALWAYS, "no such type %s", argv[i]);
137                         return false;
138                 }
139                 newtypemask |= type;
140         }
141
142         switch (*argv[1]) {
143         case '=':
144                 typemask = newtypemask;
145                 break;
146         case '-':
147                 typemask &= ~newtypemask;
148                 break;
149         case '+':
150                 typemask |= newtypemask;
151                 break;
152         default:
153                 log_line(LOG_ALWAYS, "unknown modifer: %c", *argv[1]);
154                 return false;
155         }
156
157         return true;
158 }
159
160 static void log_admin_help(int agc, char **argv)
161 {
162 #include "generated-log-help:log"
163 /*** XML Help:
164     <section id="c:log">
165      <title><command>log</command></title>
166      <para>Manage logging settings</para>
167      <cmdsynopsis>
168       <command>log</command>
169       <group choice="opt">
170        <arg choice="plain">=</arg>
171        <arg choice="plain">+</arg>
172        <arg choice="plain">-</arg>
173       </group>
174       <arg choice="req"><replaceable>type, ...</replaceable></arg>
175      </cmdsynopsis>
176      <para>Each log message is classified into one of the following
177      types:</para>
178       <varlistentry>
179        <term>UI</term>
180        <listitem>
181         <para>Normal response from command lines.</para>
182        </listitem>
183       </varlistentry>
184       <varlistentry>
185        <term>LIB</term>
186        <listitem>
187         <para>Logging output from libctdb</para>
188        </listitem>
189       </varlistentry>
190      <variablelist>
191       <varlistentry>
192        <term>READ</term>
193        <listitem>
194         <para>Messages from ctdbd</para>
195        </listitem>
196       </varlistentry>
197       <varlistentry>
198        <term>WRITE</term>
199        <listitem>
200         <para>Messages to ctdbd</para>
201        </listitem>
202       </varlistentry>
203       <varlistentry>
204        <term>VERBOSE</term>
205        <listitem>
206         <para>Verbose debug output</para>
207        </listitem>
208       </varlistentry>
209      </variablelist>
210
211      <para>The <command>log</command> command allows you to select
212       which messages are displayed. By default, all messages except
213       debug will be shown.</para>
214
215      <para>Without any arguments, the current logged types are listed.</para>
216
217      <para>With +, - or = character, those types will be added,
218       removed or set as the current types of messages to be logged
219       (repectively).</para>
220
221       <para>Messages generated as a result of user input are always
222       logged.  </para> </section>
223 */
224 }
225
226 static void log_init(void)
227 {
228         if (tui_quiet)
229                 typemask = 0;
230         tui_register_command("log", log_admin, log_admin_help);
231 }
232
233 init_call(log_init);