]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/input.c
bb687c215e336af0213efc0a52424e7df60672dd
[thirdparty/xfsprogs-dev.git] / db / input.c
1 /*
2 * Copyright (c) 2000-2003 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <xfs/libxfs.h>
20 #include <signal.h>
21 #include "command.h"
22 #include "input.h"
23 #include "output.h"
24 #include "sig.h"
25 #include "malloc.h"
26 #include "init.h"
27
28 #if defined(ENABLE_READLINE)
29 # include <readline/history.h>
30 # include <readline/readline.h>
31 #elif defined(ENABLE_EDITLINE)
32 # include <histedit.h>
33 #endif
34
35 int inputstacksize;
36 FILE **inputstack;
37 FILE *curinput;
38
39 static void popfile(void);
40 static int source_f(int argc, char **argv);
41
42 static const cmdinfo_t source_cmd =
43 { "source", NULL, source_f, 1, 1, 0, "source-file",
44 "get commands from source-file", NULL };
45
46 /* our homegrown strtok that understands strings */
47
48 static char *
49 tokenize(
50 char *inp)
51 {
52 static char *last_place = NULL;
53 char *start;
54 char *walk;
55 int in_string = 0;
56 int in_escape = 0;
57
58 if (inp) {
59 start = inp;
60 } else {
61 if (last_place == NULL)
62 return NULL;
63
64 /* we're done */
65 if (*last_place != '\0')
66 return NULL;
67
68 start = last_place + 1;
69 }
70 last_place = NULL;
71
72 /* eat whitespace */
73 while (*start == ' ' || *start == '\t')
74 start++;
75
76 walk = start;
77 for (;*walk != '\0'; walk++) {
78 if (in_escape) {
79 in_escape = 0;
80 continue;
81 }
82 if (*walk == '\\')
83 in_escape = 1;
84 else if (*walk == '\"')
85 in_string ^= 1;
86
87 if (!in_string && !in_escape &&
88 (*walk == ' ' || *walk == '\t')) {
89 last_place = walk;
90 *last_place = '\0';
91 break;
92 }
93 }
94 if (walk == start)
95 return NULL;
96
97 return start;
98 }
99
100 char **
101 breakline(
102 char *input,
103 int *count)
104 {
105 int c;
106 char *inp;
107 char *p;
108 char **rval;
109
110 c = 0;
111 inp = input;
112 rval = xcalloc(sizeof(char *), 1);
113 for (;;) {
114
115 p = tokenize(inp);
116
117 if (p == NULL)
118 break;
119 inp = NULL;
120 c++;
121 rval = xrealloc(rval, sizeof(*rval) * (c + 1));
122 rval[c - 1] = p;
123 rval[c] = NULL;
124 }
125 *count = c;
126 return rval;
127 }
128
129 void
130 doneline(
131 char *input,
132 char **vec)
133 {
134 xfree(input);
135 xfree(vec);
136 }
137
138 static char *
139 get_prompt(void)
140 {
141 static char prompt[FILENAME_MAX + 1];
142
143 if (!prompt[0])
144 snprintf(prompt, sizeof(prompt), "%s> ", progname);
145 return prompt;
146 }
147
148 static char *
149 fetchline_internal(void)
150 {
151 char buf[1024];
152 int iscont;
153 size_t len;
154 size_t rlen;
155 char *rval;
156
157 rval = NULL;
158 for (rlen = iscont = 0; ; ) {
159 if (inputstacksize == 1) {
160 if (iscont)
161 dbprintf("... ");
162 else
163 dbprintf(get_prompt(), progname);
164 fflush(stdin);
165 }
166 if (seenint() ||
167 (!fgets(buf, sizeof(buf), curinput) &&
168 ferror(curinput) && seenint())) {
169 clearint();
170 dbprintf("^C\n");
171 clearerr(curinput);
172 if (iscont) {
173 iscont = 0;
174 rlen = 0;
175 if (rval) {
176 xfree(rval);
177 rval = NULL;
178 }
179 }
180 continue;
181 }
182 if (ferror(curinput) || feof(curinput) ||
183 (len = strlen(buf)) == 0) {
184 popfile();
185 if (curinput == NULL) {
186 dbprintf("\n");
187 return NULL;
188 }
189 iscont = 0;
190 rlen = 0;
191 if (rval) {
192 xfree(rval);
193 rval = NULL;
194 }
195 continue;
196 }
197 if (inputstacksize == 1)
198 logprintf("%s", buf);
199 rval = xrealloc(rval, rlen + len + 1);
200 if (rlen == 0)
201 rval[0] = '\0';
202 rlen += len;
203 strcat(rval, buf);
204 if (buf[len - 1] == '\n') {
205 if (len > 1 && buf[len - 2] == '\\') {
206 rval[rlen - 2] = ' ';
207 rval[rlen - 1] = '\0';
208 rlen--;
209 iscont = 1;
210 } else {
211 rval[rlen - 1] = '\0';
212 rlen--;
213 break;
214 }
215 }
216 }
217 return rval;
218 }
219
220 #ifdef ENABLE_READLINE
221 char *
222 fetchline(void)
223 {
224 char *line;
225
226 if (inputstacksize == 1) {
227 line = readline(get_prompt());
228 if (line && *line) {
229 add_history(line);
230 logprintf("%s", line);
231 }
232 } else {
233 line = fetchline_internal();
234 }
235 return line;
236 }
237 #elif defined(ENABLE_EDITLINE)
238 static char *el_get_prompt(EditLine *e) { return get_prompt(); }
239 char *
240 fetchline(void)
241 {
242 static EditLine *el;
243 static History *hist;
244 HistEvent hevent;
245 char *line;
246 int count;
247
248 if (!el) {
249 hist = history_init();
250 history(hist, &hevent, H_SETSIZE, 100);
251 el = el_init(progname, stdin, stdout, stderr);
252 el_source(el, NULL);
253 el_set(el, EL_SIGNAL, 1);
254 el_set(el, EL_PROMPT, el_get_prompt);
255 el_set(el, EL_HIST, history, (const char *)hist);
256 }
257
258 if (inputstacksize == 1) {
259 line = xstrdup(el_gets(el, &count));
260 if (line) {
261 if (count > 0)
262 line[count-1] = '\0';
263 if (*line) {
264 history(hist, &hevent, H_ENTER, line);
265 logprintf("%s", line);
266 }
267 }
268 } else {
269 line = fetchline_internal();
270 }
271 return line;
272 }
273 #else
274 char * fetchline(void) { return fetchline_internal(); }
275 #endif
276
277 static void
278 popfile(void)
279 {
280 if (inputstacksize == 0) {
281 curinput = NULL;
282 return;
283 }
284 if (curinput != stdin)
285 fclose(curinput);
286
287 inputstacksize--;
288 if (inputstacksize) {
289 inputstack =
290 xrealloc(inputstack, inputstacksize * sizeof(*inputstack));
291 curinput = inputstack[inputstacksize - 1];
292 } else {
293 free(inputstack);
294 curinput = NULL;
295 inputstack = NULL;
296 }
297 }
298
299 void
300 pushfile(
301 FILE *file)
302 {
303 inputstack =
304 xrealloc(inputstack,
305 (inputstacksize + 1) * sizeof(*inputstack));
306 inputstacksize++;
307 curinput = inputstack[inputstacksize - 1] = file;
308 }
309
310 /* ARGSUSED */
311 static int
312 source_f(
313 int argc,
314 char **argv)
315 {
316 FILE *f;
317
318 f = fopen(argv[1], "r");
319 if (f == NULL)
320 dbprintf("can't open %s\n", argv[0]);
321 else
322 pushfile(f);
323 return 0;
324 }
325
326 void
327 input_init(void)
328 {
329 add_command(&source_cmd);
330 }