]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - db/input.c
xfsprogs: Release v6.7.0
[thirdparty/xfsprogs-dev.git] / db / input.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
da23017d
NS
3 * Copyright (c) 2000-2003 Silicon Graphics, Inc.
4 * All Rights Reserved.
2bd0ea18
NS
5 */
6
6b803e5a 7#include "libxfs.h"
2bd0ea18 8#include <signal.h>
2bd0ea18 9#include "command.h"
2bd0ea18
NS
10#include "input.h"
11#include "output.h"
12#include "sig.h"
13#include "malloc.h"
14#include "init.h"
15
bbe12eb9 16#ifdef ENABLE_EDITLINE
d4b9ebda 17# include <histedit.h>
e246ba5f
NS
18#endif
19
00ff2b10
ES
20static int inputstacksize;
21static FILE **inputstack;
22static FILE *curinput;
2bd0ea18
NS
23
24static void popfile(void);
25static int source_f(int argc, char **argv);
26
27static const cmdinfo_t source_cmd =
9ee7055c
AM
28 { "source", NULL, source_f, 1, 1, 0, N_("source-file"),
29 N_("get commands from source-file"), NULL };
2bd0ea18
NS
30
31/* our homegrown strtok that understands strings */
32
33static char *
34tokenize(
35 char *inp)
36{
37 static char *last_place = NULL;
38 char *start;
39 char *walk;
40 int in_string = 0;
41 int in_escape = 0;
42
43 if (inp) {
44 start = inp;
45 } else {
46 if (last_place == NULL)
47 return NULL;
48
49 /* we're done */
50 if (*last_place != '\0')
51 return NULL;
52
53 start = last_place + 1;
54 }
55 last_place = NULL;
56
57 /* eat whitespace */
58 while (*start == ' ' || *start == '\t')
59 start++;
60
61 walk = start;
62 for (;*walk != '\0'; walk++) {
63 if (in_escape) {
64 in_escape = 0;
65 continue;
66 }
67 if (*walk == '\\')
68 in_escape = 1;
69 else if (*walk == '\"')
70 in_string ^= 1;
71
72 if (!in_string && !in_escape &&
73 (*walk == ' ' || *walk == '\t')) {
74 last_place = walk;
75 *last_place = '\0';
76 break;
77 }
78 }
79 if (walk == start)
80 return NULL;
81
82 return start;
83}
84
85char **
86breakline(
87 char *input,
88 int *count)
89{
90 int c;
91 char *inp;
92 char *p;
93 char **rval;
94
95 c = 0;
96 inp = input;
97 rval = xcalloc(sizeof(char *), 1);
98 for (;;) {
99
100 p = tokenize(inp);
101
102 if (p == NULL)
103 break;
104 inp = NULL;
105 c++;
106 rval = xrealloc(rval, sizeof(*rval) * (c + 1));
107 rval[c - 1] = p;
108 rval[c] = NULL;
109 }
110 *count = c;
111 return rval;
112}
113
114void
115doneline(
116 char *input,
117 char **vec)
118{
119 xfree(input);
120 xfree(vec);
121}
122
d4b9ebda
NS
123static char *
124get_prompt(void)
125{
126 static char prompt[FILENAME_MAX + 1];
127
128 if (!prompt[0])
129 snprintf(prompt, sizeof(prompt), "%s> ", progname);
130 return prompt;
131}
132
e246ba5f
NS
133static char *
134fetchline_internal(void)
2bd0ea18
NS
135{
136 char buf[1024];
137 int iscont;
138 size_t len;
139 size_t rlen;
140 char *rval;
141
142 rval = NULL;
143 for (rlen = iscont = 0; ; ) {
c8dc4235 144 if (curinput == stdin) {
2bd0ea18
NS
145 if (iscont)
146 dbprintf("... ");
147 else
d4b9ebda 148 dbprintf(get_prompt(), progname);
2bd0ea18
NS
149 fflush(stdin);
150 }
151 if (seenint() ||
152 (!fgets(buf, sizeof(buf), curinput) &&
153 ferror(curinput) && seenint())) {
154 clearint();
155 dbprintf("^C\n");
156 clearerr(curinput);
157 if (iscont) {
158 iscont = 0;
159 rlen = 0;
160 if (rval) {
161 xfree(rval);
162 rval = NULL;
163 }
164 }
165 continue;
166 }
167 if (ferror(curinput) || feof(curinput) ||
168 (len = strlen(buf)) == 0) {
c8dc4235
DW
169 /*
170 * No more input at this inputstack level; pop
171 * our fd off and return so that a lower
172 * level fetchline can handle us. If this was
173 * an interactive session, print a newline
174 * because ^D doesn't emit one.
175 */
176 if (curinput == stdin)
2bd0ea18 177 dbprintf("\n");
c8dc4235
DW
178
179 popfile();
2bd0ea18
NS
180 iscont = 0;
181 rlen = 0;
182 if (rval) {
183 xfree(rval);
184 rval = NULL;
185 }
c8dc4235 186 return NULL;
2bd0ea18
NS
187 }
188 if (inputstacksize == 1)
189 logprintf("%s", buf);
190 rval = xrealloc(rval, rlen + len + 1);
191 if (rlen == 0)
192 rval[0] = '\0';
193 rlen += len;
194 strcat(rval, buf);
195 if (buf[len - 1] == '\n') {
196 if (len > 1 && buf[len - 2] == '\\') {
197 rval[rlen - 2] = ' ';
198 rval[rlen - 1] = '\0';
199 rlen--;
200 iscont = 1;
201 } else {
202 rval[rlen - 1] = '\0';
203 rlen--;
204 break;
205 }
206 }
207 }
208 return rval;
209}
210
bbe12eb9 211#ifdef ENABLE_EDITLINE
d4b9ebda 212static char *el_get_prompt(EditLine *e) { return get_prompt(); }
e246ba5f
NS
213char *
214fetchline(void)
f8149110 215{
d4b9ebda
NS
216 static EditLine *el;
217 static History *hist;
218 HistEvent hevent;
f8149110 219 char *line;
d4b9ebda
NS
220 int count;
221
222 if (!el) {
223 hist = history_init();
224 history(hist, &hevent, H_SETSIZE, 100);
225 el = el_init(progname, stdin, stdout, stderr);
226 el_source(el, NULL);
227 el_set(el, EL_SIGNAL, 1);
228 el_set(el, EL_PROMPT, el_get_prompt);
229 el_set(el, EL_HIST, history, (const char *)hist);
3aef6357 230 el_set(el, EL_EDITOR, "emacs");
d4b9ebda
NS
231 }
232
233 if (inputstacksize == 1) {
cafb847b
DW
234 const char *cmd;
235
236 cmd = el_gets(el, &count);
237 if (!cmd)
238 return NULL;
239
240 line = xstrdup(cmd);
241 if (!line)
242 return NULL;
243
244 if (count > 0)
245 line[count-1] = '\0';
246 if (*line) {
247 history(hist, &hevent, H_ENTER, line);
248 logprintf("%s", line);
d4b9ebda
NS
249 }
250 } else {
251 line = fetchline_internal();
252 }
253 return line;
2bd0ea18 254}
d4b9ebda
NS
255#else
256char * fetchline(void) { return fetchline_internal(); }
e246ba5f 257#endif
2bd0ea18
NS
258
259static void
260popfile(void)
261{
262 if (inputstacksize == 0) {
263 curinput = NULL;
264 return;
265 }
266 if (curinput != stdin)
267 fclose(curinput);
dfc130f3 268
2bd0ea18 269 inputstacksize--;
dfc130f3 270 if (inputstacksize) {
2bd0ea18
NS
271 inputstack =
272 xrealloc(inputstack, inputstacksize * sizeof(*inputstack));
dfc130f3
RC
273 curinput = inputstack[inputstacksize - 1];
274 } else {
275 free(inputstack);
276 curinput = NULL;
277 inputstack = NULL;
278 }
2bd0ea18
NS
279}
280
281void
282pushfile(
283 FILE *file)
284{
285 inputstack =
286 xrealloc(inputstack,
287 (inputstacksize + 1) * sizeof(*inputstack));
288 inputstacksize++;
289 curinput = inputstack[inputstacksize - 1] = file;
290}
291
292/* ARGSUSED */
293static int
294source_f(
295 int argc,
296 char **argv)
297{
298 FILE *f;
c8dc4235
DW
299 int c, done = 0;
300 char *input;
301 char **v;
2bd0ea18
NS
302
303 f = fopen(argv[1], "r");
c8dc4235 304 if (f == NULL) {
9ee7055c 305 dbprintf(_("can't open %s\n"), argv[0]);
c8dc4235
DW
306 return 0;
307 }
308
309 /* Run the sourced commands now. */
310 pushfile(f);
311 while (!done) {
312 if ((input = fetchline_internal()) == NULL)
313 break;
314 v = breakline(input, &c);
315 if (c)
316 done = command(c, v);
317 doneline(input, v);
318 }
319
2bd0ea18
NS
320 return 0;
321}
e246ba5f
NS
322
323void
324input_init(void)
325{
326 add_command(&source_cmd);
327}