]>
Commit | Line | Data |
---|---|---|
2bd0ea18 | 1 | /* |
da23017d NS |
2 | * Copyright (c) 2000-2003 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | |
dfc130f3 | 4 | * |
da23017d NS |
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 | |
2bd0ea18 | 7 | * published by the Free Software Foundation. |
dfc130f3 | 8 | * |
da23017d NS |
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. | |
dfc130f3 | 13 | * |
da23017d NS |
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 | |
2bd0ea18 NS |
17 | */ |
18 | ||
6b803e5a | 19 | #include "libxfs.h" |
2bd0ea18 | 20 | #include <signal.h> |
2bd0ea18 | 21 | #include "command.h" |
2bd0ea18 NS |
22 | #include "input.h" |
23 | #include "output.h" | |
24 | #include "sig.h" | |
25 | #include "malloc.h" | |
26 | #include "init.h" | |
27 | ||
d4b9ebda | 28 | #if defined(ENABLE_READLINE) |
e246ba5f NS |
29 | # include <readline/history.h> |
30 | # include <readline/readline.h> | |
d4b9ebda NS |
31 | #elif defined(ENABLE_EDITLINE) |
32 | # include <histedit.h> | |
e246ba5f NS |
33 | #endif |
34 | ||
2bd0ea18 NS |
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 = | |
9ee7055c AM |
43 | { "source", NULL, source_f, 1, 1, 0, N_("source-file"), |
44 | N_("get commands from source-file"), NULL }; | |
2bd0ea18 NS |
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 | ||
d4b9ebda NS |
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 | ||
e246ba5f NS |
148 | static char * |
149 | fetchline_internal(void) | |
2bd0ea18 NS |
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 | |
d4b9ebda | 163 | dbprintf(get_prompt(), progname); |
2bd0ea18 NS |
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 | ||
e246ba5f NS |
220 | #ifdef ENABLE_READLINE |
221 | char * | |
222 | fetchline(void) | |
2bd0ea18 | 223 | { |
d4b9ebda | 224 | char *line; |
e246ba5f NS |
225 | |
226 | if (inputstacksize == 1) { | |
d4b9ebda NS |
227 | line = readline(get_prompt()); |
228 | if (line && *line) { | |
e246ba5f | 229 | add_history(line); |
e246ba5f | 230 | logprintf("%s", line); |
d4b9ebda | 231 | } |
e246ba5f NS |
232 | } else { |
233 | line = fetchline_internal(); | |
234 | } | |
235 | return line; | |
236 | } | |
d4b9ebda NS |
237 | #elif defined(ENABLE_EDITLINE) |
238 | static char *el_get_prompt(EditLine *e) { return get_prompt(); } | |
e246ba5f NS |
239 | char * |
240 | fetchline(void) | |
f8149110 | 241 | { |
d4b9ebda NS |
242 | static EditLine *el; |
243 | static History *hist; | |
244 | HistEvent hevent; | |
f8149110 | 245 | char *line; |
d4b9ebda NS |
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; | |
2bd0ea18 | 272 | } |
d4b9ebda NS |
273 | #else |
274 | char * fetchline(void) { return fetchline_internal(); } | |
e246ba5f | 275 | #endif |
2bd0ea18 NS |
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); | |
dfc130f3 | 286 | |
2bd0ea18 | 287 | inputstacksize--; |
dfc130f3 | 288 | if (inputstacksize) { |
2bd0ea18 NS |
289 | inputstack = |
290 | xrealloc(inputstack, inputstacksize * sizeof(*inputstack)); | |
dfc130f3 RC |
291 | curinput = inputstack[inputstacksize - 1]; |
292 | } else { | |
293 | free(inputstack); | |
294 | curinput = NULL; | |
295 | inputstack = NULL; | |
296 | } | |
2bd0ea18 NS |
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) | |
9ee7055c | 320 | dbprintf(_("can't open %s\n"), argv[0]); |
2bd0ea18 NS |
321 | else |
322 | pushfile(f); | |
323 | return 0; | |
324 | } | |
e246ba5f NS |
325 | |
326 | void | |
327 | input_init(void) | |
328 | { | |
329 | add_command(&source_cmd); | |
330 | } |