1afc2ba1dSToomas Soome /*
2afc2ba1dSToomas Soome * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
38751d36cSAndy Fiddaman * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
4afc2ba1dSToomas Soome * All rights reserved.
5afc2ba1dSToomas Soome *
6afc2ba1dSToomas Soome * Redistribution and use in source and binary forms, with or without
7afc2ba1dSToomas Soome * modification, are permitted provided that the following conditions
8afc2ba1dSToomas Soome * are met:
9afc2ba1dSToomas Soome * 1. Redistributions of source code must retain the above copyright
10afc2ba1dSToomas Soome * notice, this list of conditions and the following disclaimer.
11afc2ba1dSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
12afc2ba1dSToomas Soome * notice, this list of conditions and the following disclaimer in the
13afc2ba1dSToomas Soome * documentation and/or other materials provided with the distribution.
14afc2ba1dSToomas Soome *
15afc2ba1dSToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16afc2ba1dSToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17afc2ba1dSToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18afc2ba1dSToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19afc2ba1dSToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20afc2ba1dSToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21afc2ba1dSToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22afc2ba1dSToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23afc2ba1dSToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24afc2ba1dSToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25afc2ba1dSToomas Soome * SUCH DAMAGE.
26afc2ba1dSToomas Soome */
27afc2ba1dSToomas Soome
28afc2ba1dSToomas Soome #include <sys/types.h>
29afc2ba1dSToomas Soome #include <sys/stat.h>
30afc2ba1dSToomas Soome #include <fcntl.h>
31afc2ba1dSToomas Soome #include <errno.h>
32afc2ba1dSToomas Soome #include <stdlib.h>
33afc2ba1dSToomas Soome #include <stdio.h>
34afc2ba1dSToomas Soome #include <string.h>
35afc2ba1dSToomas Soome #include <strings.h>
36afc2ba1dSToomas Soome #include <limits.h>
37afc2ba1dSToomas Soome #include <unistd.h>
38afc2ba1dSToomas Soome #include <dirent.h>
39afc2ba1dSToomas Soome #include <macros.h>
40afc2ba1dSToomas Soome #include <sys/systeminfo.h>
4195bfa623SToomas Soome #include <sys/linker_set.h>
42afc2ba1dSToomas Soome #include <sys/queue.h>
43afc2ba1dSToomas Soome #include <sys/mnttab.h>
4495bfa623SToomas Soome #include "loader_emu.h"
450bead3caSToomas Soome #include "gfx_fb.h"
46afc2ba1dSToomas Soome #include "ficl.h"
47afc2ba1dSToomas Soome
48afc2ba1dSToomas Soome #define MDIR_REMOVED 0x0001
49afc2ba1dSToomas Soome #define MDIR_NOHINTS 0x0002
50afc2ba1dSToomas Soome
51afc2ba1dSToomas Soome struct moduledir {
52afc2ba1dSToomas Soome char *d_path; /* path of modules directory */
53afc2ba1dSToomas Soome uchar_t *d_hints; /* content of linker.hints file */
54afc2ba1dSToomas Soome int d_hintsz; /* size of hints data */
55afc2ba1dSToomas Soome int d_flags;
56afc2ba1dSToomas Soome STAILQ_ENTRY(moduledir) d_link;
57afc2ba1dSToomas Soome };
58afc2ba1dSToomas Soome static STAILQ_HEAD(, moduledir) moduledir_list =
59afc2ba1dSToomas Soome STAILQ_HEAD_INITIALIZER(moduledir_list);
60afc2ba1dSToomas Soome
61afc2ba1dSToomas Soome static const char *default_searchpath = "/platform/i86pc";
62afc2ba1dSToomas Soome
63afc2ba1dSToomas Soome static char typestr[] = "?fc?d?b? ?l?s?w";
64afc2ba1dSToomas Soome static int ls_getdir(char **pathp);
65afc2ba1dSToomas Soome extern char **_environ;
66afc2ba1dSToomas Soome
67afc2ba1dSToomas Soome char *command_errmsg;
68afc2ba1dSToomas Soome char command_errbuf[256];
69afc2ba1dSToomas Soome
70afc2ba1dSToomas Soome extern void pager_open(void);
71afc2ba1dSToomas Soome extern void pager_close(void);
72afc2ba1dSToomas Soome extern int pager_output(const char *);
73afc2ba1dSToomas Soome extern int pager_file(const char *);
74afc2ba1dSToomas Soome static int page_file(char *);
75afc2ba1dSToomas Soome static int include(const char *);
76afc2ba1dSToomas Soome
77afc2ba1dSToomas Soome static int command_help(int argc, char *argv[]);
78afc2ba1dSToomas Soome static int command_commandlist(int argc, char *argv[]);
79afc2ba1dSToomas Soome static int command_show(int argc, char *argv[]);
80afc2ba1dSToomas Soome static int command_set(int argc, char *argv[]);
81afc2ba1dSToomas Soome static int command_setprop(int argc, char *argv[]);
82afc2ba1dSToomas Soome static int command_unset(int argc, char *argv[]);
83afc2ba1dSToomas Soome static int command_echo(int argc, char *argv[]);
84afc2ba1dSToomas Soome static int command_read(int argc, char *argv[]);
85afc2ba1dSToomas Soome static int command_more(int argc, char *argv[]);
86afc2ba1dSToomas Soome static int command_ls(int argc, char *argv[]);
87afc2ba1dSToomas Soome static int command_include(int argc, char *argv[]);
88afc2ba1dSToomas Soome static int command_autoboot(int argc, char *argv[]);
89afc2ba1dSToomas Soome static int command_boot(int argc, char *argv[]);
90afc2ba1dSToomas Soome static int command_unload(int argc, char *argv[]);
91afc2ba1dSToomas Soome static int command_load(int argc, char *argv[]);
92afc2ba1dSToomas Soome static int command_reboot(int argc, char *argv[]);
938751d36cSAndy Fiddaman static int command_sifting(int argc, char *argv[]);
940bead3caSToomas Soome static int command_framebuffer(int argc, char *argv[]);
95afc2ba1dSToomas Soome
96afc2ba1dSToomas Soome #define BF_PARSE 100
97afc2ba1dSToomas Soome #define BF_DICTSIZE 30000
98afc2ba1dSToomas Soome
99afc2ba1dSToomas Soome /* update when loader version will change */
100afc2ba1dSToomas Soome static const char bootprog_rev[] = "1.1";
101afc2ba1dSToomas Soome
102afc2ba1dSToomas Soome /*
103afc2ba1dSToomas Soome * BootForth Interface to Ficl Forth interpreter.
104afc2ba1dSToomas Soome */
105afc2ba1dSToomas Soome
106afc2ba1dSToomas Soome ficlSystem *bf_sys;
107afc2ba1dSToomas Soome ficlVm *bf_vm;
108afc2ba1dSToomas Soome
109afc2ba1dSToomas Soome /*
110afc2ba1dSToomas Soome * Redistribution and use in source and binary forms, with or without
111afc2ba1dSToomas Soome * modification, are permitted provided that the following conditions
112afc2ba1dSToomas Soome * are met:
113afc2ba1dSToomas Soome * 1. Redistributions of source code must retain the above copyright
114afc2ba1dSToomas Soome * notice, this list of conditions and the following disclaimer.
115afc2ba1dSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
116afc2ba1dSToomas Soome * notice, this list of conditions and the following disclaimer in the
117afc2ba1dSToomas Soome * documentation and/or other materials provided with the distribution.
118afc2ba1dSToomas Soome *
119afc2ba1dSToomas Soome * Jordan K. Hubbard
120afc2ba1dSToomas Soome * 29 August 1998
121afc2ba1dSToomas Soome *
122afc2ba1dSToomas Soome * The meat of the simple parser.
123afc2ba1dSToomas Soome */
124afc2ba1dSToomas Soome
125afc2ba1dSToomas Soome static void clean(void);
126afc2ba1dSToomas Soome static int insert(int *argcp, char *buf);
127afc2ba1dSToomas Soome
128afc2ba1dSToomas Soome #define PARSE_BUFSIZE 1024 /* maximum size of one element */
129afc2ba1dSToomas Soome #define MAXARGS 20 /* maximum number of elements */
130afc2ba1dSToomas Soome static char *args[MAXARGS];
131afc2ba1dSToomas Soome
132afc2ba1dSToomas Soome #define DIGIT(x) \
133afc2ba1dSToomas Soome (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
134afc2ba1dSToomas Soome
135afc2ba1dSToomas Soome /*
136afc2ba1dSToomas Soome * backslash: Return malloc'd copy of str with all standard "backslash
137afc2ba1dSToomas Soome * processing" done on it. Original can be free'd if desired.
138afc2ba1dSToomas Soome */
139afc2ba1dSToomas Soome char *
backslash(char * str)140afc2ba1dSToomas Soome backslash(char *str)
141afc2ba1dSToomas Soome {
142afc2ba1dSToomas Soome /*
143afc2ba1dSToomas Soome * Remove backslashes from the strings. Turn \040 etc. into a single
144afc2ba1dSToomas Soome * character (we allow eight bit values). Currently NUL is not
145afc2ba1dSToomas Soome * allowed.
146afc2ba1dSToomas Soome *
147afc2ba1dSToomas Soome * Turn "\n" and "\t" into '\n' and '\t' characters. Etc.
148afc2ba1dSToomas Soome */
149afc2ba1dSToomas Soome char *new_str;
150afc2ba1dSToomas Soome int seenbs = 0;
151afc2ba1dSToomas Soome int i = 0;
152afc2ba1dSToomas Soome
153afc2ba1dSToomas Soome if ((new_str = strdup(str)) == NULL)
154afc2ba1dSToomas Soome return (NULL);
155afc2ba1dSToomas Soome
156afc2ba1dSToomas Soome while (*str) {
157afc2ba1dSToomas Soome if (seenbs) {
158afc2ba1dSToomas Soome seenbs = 0;
159afc2ba1dSToomas Soome switch (*str) {
160afc2ba1dSToomas Soome case '\\':
161afc2ba1dSToomas Soome new_str[i++] = '\\';
162afc2ba1dSToomas Soome str++;
163afc2ba1dSToomas Soome break;
164afc2ba1dSToomas Soome
165afc2ba1dSToomas Soome /* preserve backslashed quotes, dollar signs */
166afc2ba1dSToomas Soome case '\'':
167afc2ba1dSToomas Soome case '"':
168afc2ba1dSToomas Soome case '$':
169afc2ba1dSToomas Soome new_str[i++] = '\\';
170afc2ba1dSToomas Soome new_str[i++] = *str++;
171afc2ba1dSToomas Soome break;
172afc2ba1dSToomas Soome
173afc2ba1dSToomas Soome case 'b':
174afc2ba1dSToomas Soome new_str[i++] = '\b';
175afc2ba1dSToomas Soome str++;
176afc2ba1dSToomas Soome break;
177afc2ba1dSToomas Soome
178afc2ba1dSToomas Soome case 'f':
179afc2ba1dSToomas Soome new_str[i++] = '\f';
180afc2ba1dSToomas Soome str++;
181afc2ba1dSToomas Soome break;
182afc2ba1dSToomas Soome
183afc2ba1dSToomas Soome case 'r':
184afc2ba1dSToomas Soome new_str[i++] = '\r';
185afc2ba1dSToomas Soome str++;
186afc2ba1dSToomas Soome break;
187afc2ba1dSToomas Soome
188afc2ba1dSToomas Soome case 'n':
189afc2ba1dSToomas Soome new_str[i++] = '\n';
190afc2ba1dSToomas Soome str++;
191afc2ba1dSToomas Soome break;
192afc2ba1dSToomas Soome
193afc2ba1dSToomas Soome case 's':
194afc2ba1dSToomas Soome new_str[i++] = ' ';
195afc2ba1dSToomas Soome str++;
196afc2ba1dSToomas Soome break;
197afc2ba1dSToomas Soome
198afc2ba1dSToomas Soome case 't':
199afc2ba1dSToomas Soome new_str[i++] = '\t';
200afc2ba1dSToomas Soome str++;
201afc2ba1dSToomas Soome break;
202afc2ba1dSToomas Soome
203afc2ba1dSToomas Soome case 'v':
204afc2ba1dSToomas Soome new_str[i++] = '\13';
205afc2ba1dSToomas Soome str++;
206afc2ba1dSToomas Soome break;
207afc2ba1dSToomas Soome
208afc2ba1dSToomas Soome case 'z':
209afc2ba1dSToomas Soome str++;
210afc2ba1dSToomas Soome break;
211afc2ba1dSToomas Soome
212afc2ba1dSToomas Soome case '0': case '1': case '2': case '3': case '4':
213afc2ba1dSToomas Soome case '5': case '6': case '7': case '8': case '9': {
214afc2ba1dSToomas Soome char val;
215afc2ba1dSToomas Soome
216afc2ba1dSToomas Soome /* Three digit octal constant? */
217afc2ba1dSToomas Soome if (*str >= '0' && *str <= '3' &&
218afc2ba1dSToomas Soome *(str + 1) >= '0' && *(str + 1) <= '7' &&
219afc2ba1dSToomas Soome *(str + 2) >= '0' && *(str + 2) <= '7') {
220afc2ba1dSToomas Soome
221afc2ba1dSToomas Soome val = (DIGIT(*str) << 6) +
222afc2ba1dSToomas Soome (DIGIT(*(str + 1)) << 3) +
223afc2ba1dSToomas Soome DIGIT(*(str + 2));
224afc2ba1dSToomas Soome
225afc2ba1dSToomas Soome /*
226afc2ba1dSToomas Soome * Allow null value if user really
227afc2ba1dSToomas Soome * wants to shoot at feet, but beware!
228afc2ba1dSToomas Soome */
229afc2ba1dSToomas Soome new_str[i++] = val;
230afc2ba1dSToomas Soome str += 3;
231afc2ba1dSToomas Soome break;
232afc2ba1dSToomas Soome }
233afc2ba1dSToomas Soome
234afc2ba1dSToomas Soome /*
235afc2ba1dSToomas Soome * One or two digit hex constant?
236afc2ba1dSToomas Soome * If two are there they will both be taken.
237afc2ba1dSToomas Soome * Use \z to split them up if this is not
238afc2ba1dSToomas Soome * wanted.
239afc2ba1dSToomas Soome */
240afc2ba1dSToomas Soome if (*str == '0' &&
241afc2ba1dSToomas Soome (*(str + 1) == 'x' || *(str + 1) == 'X') &&
242afc2ba1dSToomas Soome isxdigit(*(str + 2))) {
243afc2ba1dSToomas Soome val = DIGIT(*(str + 2));
244afc2ba1dSToomas Soome if (isxdigit(*(str + 3))) {
245afc2ba1dSToomas Soome val = (val << 4) +
246afc2ba1dSToomas Soome DIGIT(*(str + 3));
247afc2ba1dSToomas Soome str += 4;
248afc2ba1dSToomas Soome } else
249afc2ba1dSToomas Soome str += 3;
250afc2ba1dSToomas Soome /* Yep, allow null value here too */
251afc2ba1dSToomas Soome new_str[i++] = val;
252afc2ba1dSToomas Soome break;
253afc2ba1dSToomas Soome }
254afc2ba1dSToomas Soome }
255afc2ba1dSToomas Soome break;
256afc2ba1dSToomas Soome
257afc2ba1dSToomas Soome default:
258afc2ba1dSToomas Soome new_str[i++] = *str++;
259afc2ba1dSToomas Soome break;
260afc2ba1dSToomas Soome }
261afc2ba1dSToomas Soome } else {
262afc2ba1dSToomas Soome if (*str == '\\') {
263afc2ba1dSToomas Soome seenbs = 1;
264afc2ba1dSToomas Soome str++;
265afc2ba1dSToomas Soome } else
266afc2ba1dSToomas Soome new_str[i++] = *str++;
267afc2ba1dSToomas Soome }
268afc2ba1dSToomas Soome }
269afc2ba1dSToomas Soome
270afc2ba1dSToomas Soome if (seenbs) {
271afc2ba1dSToomas Soome /*
272afc2ba1dSToomas Soome * The final character was a '\'.
273afc2ba1dSToomas Soome * Put it in as a single backslash.
274afc2ba1dSToomas Soome */
275afc2ba1dSToomas Soome new_str[i++] = '\\';
276afc2ba1dSToomas Soome }
277afc2ba1dSToomas Soome new_str[i] = '\0';
278afc2ba1dSToomas Soome return (new_str);
279afc2ba1dSToomas Soome }
280afc2ba1dSToomas Soome
281afc2ba1dSToomas Soome /*
282afc2ba1dSToomas Soome * parse: accept a string of input and "parse" it for backslash
283afc2ba1dSToomas Soome * substitutions and environment variable expansions (${var}),
284afc2ba1dSToomas Soome * returning an argc/argv style vector of whitespace separated
285afc2ba1dSToomas Soome * arguments. Returns 0 on success, 1 on failure (ok, ok, so I
286afc2ba1dSToomas Soome * wimped-out on the error codes! :).
287afc2ba1dSToomas Soome *
288afc2ba1dSToomas Soome * Note that the argv array returned must be freed by the caller, but
289afc2ba1dSToomas Soome * we own the space allocated for arguments and will free that on next
290afc2ba1dSToomas Soome * invocation. This allows argv consumers to modify the array if
291afc2ba1dSToomas Soome * required.
292afc2ba1dSToomas Soome *
293afc2ba1dSToomas Soome * NB: environment variables that expand to more than one whitespace
294afc2ba1dSToomas Soome * separated token will be returned as a single argv[] element, not
295afc2ba1dSToomas Soome * split in turn. Expanded text is also immune to further backslash
296afc2ba1dSToomas Soome * elimination or expansion since this is a one-pass, non-recursive
297afc2ba1dSToomas Soome * parser. You didn't specify more than this so if you want more, ask
298afc2ba1dSToomas Soome * me. - jkh
299afc2ba1dSToomas Soome */
300afc2ba1dSToomas Soome
301afc2ba1dSToomas Soome #define PARSE_FAIL(expr) \
302afc2ba1dSToomas Soome if (expr) { \
303afc2ba1dSToomas Soome printf("fail at line %d\n", __LINE__); \
304afc2ba1dSToomas Soome clean(); \
305afc2ba1dSToomas Soome free(copy); \
306afc2ba1dSToomas Soome free(buf); \
307afc2ba1dSToomas Soome return (1); \
308afc2ba1dSToomas Soome }
309afc2ba1dSToomas Soome
310afc2ba1dSToomas Soome /* Accept the usual delimiters for a variable, returning counterpart */
311afc2ba1dSToomas Soome static char
isdelim(int ch)312afc2ba1dSToomas Soome isdelim(int ch)
313afc2ba1dSToomas Soome {
314afc2ba1dSToomas Soome if (ch == '{')
315afc2ba1dSToomas Soome return ('}');
316afc2ba1dSToomas Soome else if (ch == '(')
317afc2ba1dSToomas Soome return (')');
318afc2ba1dSToomas Soome return ('\0');
319afc2ba1dSToomas Soome }
320afc2ba1dSToomas Soome
321afc2ba1dSToomas Soome static int
isquote(int ch)322afc2ba1dSToomas Soome isquote(int ch)
323afc2ba1dSToomas Soome {
324afc2ba1dSToomas Soome return (ch == '\'');
325afc2ba1dSToomas Soome }
326afc2ba1dSToomas Soome
327afc2ba1dSToomas Soome static int
isdquote(int ch)328afc2ba1dSToomas Soome isdquote(int ch)
329afc2ba1dSToomas Soome {
330afc2ba1dSToomas Soome return (ch == '"');
331afc2ba1dSToomas Soome }
332afc2ba1dSToomas Soome
333afc2ba1dSToomas Soome int
parse(int * argc,char *** argv,char * str)334afc2ba1dSToomas Soome parse(int *argc, char ***argv, char *str)
335afc2ba1dSToomas Soome {
336afc2ba1dSToomas Soome int ac;
337afc2ba1dSToomas Soome char *val, *p, *q, *copy = NULL;
338afc2ba1dSToomas Soome size_t i = 0;
339afc2ba1dSToomas Soome char token, tmp, quote, dquote, *buf;
340afc2ba1dSToomas Soome enum { STR, VAR, WHITE } state;
341afc2ba1dSToomas Soome
342afc2ba1dSToomas Soome ac = *argc = 0;
343afc2ba1dSToomas Soome dquote = quote = 0;
344afc2ba1dSToomas Soome if (!str || (p = copy = backslash(str)) == NULL)
345afc2ba1dSToomas Soome return (1);
346afc2ba1dSToomas Soome
347afc2ba1dSToomas Soome /* Initialize vector and state */
348afc2ba1dSToomas Soome clean();
349afc2ba1dSToomas Soome state = STR;
350afc2ba1dSToomas Soome buf = (char *)malloc(PARSE_BUFSIZE);
351afc2ba1dSToomas Soome token = 0;
352afc2ba1dSToomas Soome
353afc2ba1dSToomas Soome /* And awaaaaaaaaay we go! */
354afc2ba1dSToomas Soome while (*p) {
355afc2ba1dSToomas Soome switch (state) {
356afc2ba1dSToomas Soome case STR:
357afc2ba1dSToomas Soome if ((*p == '\\') && p[1]) {
358afc2ba1dSToomas Soome p++;
359afc2ba1dSToomas Soome PARSE_FAIL(i == (PARSE_BUFSIZE - 1));
360afc2ba1dSToomas Soome buf[i++] = *p++;
361afc2ba1dSToomas Soome } else if (isquote(*p)) {
362afc2ba1dSToomas Soome quote = quote ? 0 : *p;
363afc2ba1dSToomas Soome if (dquote) { /* keep quote */
364afc2ba1dSToomas Soome PARSE_FAIL(i == (PARSE_BUFSIZE - 1));
365afc2ba1dSToomas Soome buf[i++] = *p++;
366afc2ba1dSToomas Soome } else
367afc2ba1dSToomas Soome ++p;
368afc2ba1dSToomas Soome } else if (isdquote(*p)) {
369afc2ba1dSToomas Soome dquote = dquote ? 0 : *p;
370afc2ba1dSToomas Soome if (quote) { /* keep dquote */
371afc2ba1dSToomas Soome PARSE_FAIL(i == (PARSE_BUFSIZE - 1));
372afc2ba1dSToomas Soome buf[i++] = *p++;
373afc2ba1dSToomas Soome } else
374afc2ba1dSToomas Soome ++p;
375afc2ba1dSToomas Soome } else if (isspace(*p) && !quote && !dquote) {
376afc2ba1dSToomas Soome state = WHITE;
377afc2ba1dSToomas Soome if (i) {
378afc2ba1dSToomas Soome buf[i] = '\0';
379afc2ba1dSToomas Soome PARSE_FAIL(insert(&ac, buf));
380afc2ba1dSToomas Soome i = 0;
381afc2ba1dSToomas Soome }
382afc2ba1dSToomas Soome ++p;
383afc2ba1dSToomas Soome } else if (*p == '$' && !quote) {
384afc2ba1dSToomas Soome token = isdelim(*(p + 1));
385afc2ba1dSToomas Soome if (token)
386afc2ba1dSToomas Soome p += 2;
387afc2ba1dSToomas Soome else
388afc2ba1dSToomas Soome ++p;
389afc2ba1dSToomas Soome state = VAR;
390afc2ba1dSToomas Soome } else {
391afc2ba1dSToomas Soome PARSE_FAIL(i == (PARSE_BUFSIZE - 1));
392afc2ba1dSToomas Soome buf[i++] = *p++;
393afc2ba1dSToomas Soome }
394afc2ba1dSToomas Soome break;
395afc2ba1dSToomas Soome
396afc2ba1dSToomas Soome case WHITE:
397afc2ba1dSToomas Soome if (isspace(*p))
398afc2ba1dSToomas Soome ++p;
399afc2ba1dSToomas Soome else
400afc2ba1dSToomas Soome state = STR;
401afc2ba1dSToomas Soome break;
402afc2ba1dSToomas Soome
403afc2ba1dSToomas Soome case VAR:
404afc2ba1dSToomas Soome if (token) {
405afc2ba1dSToomas Soome PARSE_FAIL((q = strchr(p, token)) == NULL);
406afc2ba1dSToomas Soome } else {
407afc2ba1dSToomas Soome q = p;
408afc2ba1dSToomas Soome while (*q && !isspace(*q))
409c0bb4f73SToomas Soome ++q;
410afc2ba1dSToomas Soome }
411afc2ba1dSToomas Soome tmp = *q;
412afc2ba1dSToomas Soome *q = '\0';
413afc2ba1dSToomas Soome if ((val = getenv(p)) != NULL) {
414afc2ba1dSToomas Soome size_t len = strlen(val);
415afc2ba1dSToomas Soome
416c0bb4f73SToomas Soome (void) strncpy(buf + i, val,
417c0bb4f73SToomas Soome PARSE_BUFSIZE - (i + 1));
418afc2ba1dSToomas Soome i += min(len, PARSE_BUFSIZE - 1);
419afc2ba1dSToomas Soome }
420afc2ba1dSToomas Soome *q = tmp; /* restore value */
421afc2ba1dSToomas Soome p = q + (token ? 1 : 0);
422afc2ba1dSToomas Soome state = STR;
423afc2ba1dSToomas Soome break;
424afc2ba1dSToomas Soome }
425afc2ba1dSToomas Soome }
426afc2ba1dSToomas Soome /* missing terminating ' or " */
427afc2ba1dSToomas Soome PARSE_FAIL(quote || dquote);
428afc2ba1dSToomas Soome /* If at end of token, add it */
429afc2ba1dSToomas Soome if (i && state == STR) {
430afc2ba1dSToomas Soome buf[i] = '\0';
431afc2ba1dSToomas Soome PARSE_FAIL(insert(&ac, buf));
432afc2ba1dSToomas Soome }
433afc2ba1dSToomas Soome args[ac] = NULL;
434afc2ba1dSToomas Soome *argc = ac;
435afc2ba1dSToomas Soome *argv = (char **)malloc((sizeof (char *) * ac + 1));
436afc2ba1dSToomas Soome bcopy(args, *argv, sizeof (char *) * ac + 1);
437afc2ba1dSToomas Soome free(buf);
438afc2ba1dSToomas Soome free(copy);
439afc2ba1dSToomas Soome return (0);
440afc2ba1dSToomas Soome }
441afc2ba1dSToomas Soome
442afc2ba1dSToomas Soome #define MAXARGS 20
443afc2ba1dSToomas Soome
444afc2ba1dSToomas Soome /* Clean vector space */
445afc2ba1dSToomas Soome static void
clean(void)446afc2ba1dSToomas Soome clean(void)
447afc2ba1dSToomas Soome {
448afc2ba1dSToomas Soome int i;
449afc2ba1dSToomas Soome
450afc2ba1dSToomas Soome for (i = 0; i < MAXARGS; i++) {
451afc2ba1dSToomas Soome if (args[i] != NULL) {
452afc2ba1dSToomas Soome free(args[i]);
453afc2ba1dSToomas Soome args[i] = NULL;
454afc2ba1dSToomas Soome }
455afc2ba1dSToomas Soome }
456afc2ba1dSToomas Soome }
457afc2ba1dSToomas Soome
458afc2ba1dSToomas Soome static int
insert(int * argcp,char * buf)459afc2ba1dSToomas Soome insert(int *argcp, char *buf)
460afc2ba1dSToomas Soome {
461afc2ba1dSToomas Soome if (*argcp >= MAXARGS)
462afc2ba1dSToomas Soome return (1);
463afc2ba1dSToomas Soome args[(*argcp)++] = strdup(buf);
464afc2ba1dSToomas Soome return (0);
465afc2ba1dSToomas Soome }
466afc2ba1dSToomas Soome
467afc2ba1dSToomas Soome static char *
isadir(void)468afc2ba1dSToomas Soome isadir(void)
469afc2ba1dSToomas Soome {
470afc2ba1dSToomas Soome char *buf;
471afc2ba1dSToomas Soome size_t bufsize = 20;
472afc2ba1dSToomas Soome int ret;
473afc2ba1dSToomas Soome
474afc2ba1dSToomas Soome if ((buf = malloc(bufsize)) == NULL)
475afc2ba1dSToomas Soome return (NULL);
476afc2ba1dSToomas Soome ret = sysinfo(SI_ARCHITECTURE_K, buf, bufsize);
477afc2ba1dSToomas Soome if (ret == -1) {
478afc2ba1dSToomas Soome free(buf);
479afc2ba1dSToomas Soome return (NULL);
480afc2ba1dSToomas Soome }
481afc2ba1dSToomas Soome return (buf);
482afc2ba1dSToomas Soome }
483afc2ba1dSToomas Soome
484afc2ba1dSToomas Soome /*
485afc2ba1dSToomas Soome * Shim for taking commands from BF and passing them out to 'standard'
486afc2ba1dSToomas Soome * argv/argc command functions.
487afc2ba1dSToomas Soome */
488afc2ba1dSToomas Soome static void
bf_command(ficlVm * vm)489afc2ba1dSToomas Soome bf_command(ficlVm *vm)
490afc2ba1dSToomas Soome {
491afc2ba1dSToomas Soome char *name, *line, *tail, *cp;
492afc2ba1dSToomas Soome size_t len;
49395bfa623SToomas Soome struct bootblk_command **cmdp;
494afc2ba1dSToomas Soome bootblk_cmd_t *cmd;
495afc2ba1dSToomas Soome int nstrings, i;
496afc2ba1dSToomas Soome int argc, result;
497afc2ba1dSToomas Soome char **argv;
498afc2ba1dSToomas Soome
499afc2ba1dSToomas Soome /* Get the name of the current word */
500afc2ba1dSToomas Soome name = vm->runningWord->name;
501afc2ba1dSToomas Soome
502afc2ba1dSToomas Soome /* Find our command structure */
503afc2ba1dSToomas Soome cmd = NULL;
50495bfa623SToomas Soome SET_FOREACH(cmdp, Xcommand_set) {
50595bfa623SToomas Soome if (((*cmdp)->c_name != NULL) &&
50695bfa623SToomas Soome strcmp(name, (*cmdp)->c_name) == 0)
50795bfa623SToomas Soome cmd = (*cmdp)->c_fn;
508afc2ba1dSToomas Soome }
509afc2ba1dSToomas Soome if (cmd == NULL)
510afc2ba1dSToomas Soome printf("callout for unknown command '%s'\n", name);
511afc2ba1dSToomas Soome
512afc2ba1dSToomas Soome /* Check whether we have been compiled or are being interpreted */
513afc2ba1dSToomas Soome if (ficlStackPopInteger(ficlVmGetDataStack(vm))) {
514afc2ba1dSToomas Soome /*
515afc2ba1dSToomas Soome * Get parameters from stack, in the format:
516afc2ba1dSToomas Soome * an un ... a2 u2 a1 u1 n --
517afc2ba1dSToomas Soome * Where n is the number of strings, a/u are pairs of
518afc2ba1dSToomas Soome * address/size for strings, and they will be concatenated
519afc2ba1dSToomas Soome * in LIFO order.
520afc2ba1dSToomas Soome */
521afc2ba1dSToomas Soome nstrings = ficlStackPopInteger(ficlVmGetDataStack(vm));
522afc2ba1dSToomas Soome for (i = 0, len = 0; i < nstrings; i++)
523c0bb4f73SToomas Soome len += ficlStackFetch(ficlVmGetDataStack(vm),
524c0bb4f73SToomas Soome i * 2).i + 1;
525afc2ba1dSToomas Soome line = malloc(strlen(name) + len + 1);
526c0bb4f73SToomas Soome (void) strcpy(line, name);
527afc2ba1dSToomas Soome
528afc2ba1dSToomas Soome if (nstrings)
529afc2ba1dSToomas Soome for (i = 0; i < nstrings; i++) {
530afc2ba1dSToomas Soome len = ficlStackPopInteger(
531afc2ba1dSToomas Soome ficlVmGetDataStack(vm));
532afc2ba1dSToomas Soome cp = ficlStackPopPointer(
533afc2ba1dSToomas Soome ficlVmGetDataStack(vm));
534c0bb4f73SToomas Soome (void) strcat(line, " ");
535c0bb4f73SToomas Soome (void) strncat(line, cp, len);
536afc2ba1dSToomas Soome }
537afc2ba1dSToomas Soome } else {
538afc2ba1dSToomas Soome /* Get remainder of invocation */
539afc2ba1dSToomas Soome tail = ficlVmGetInBuf(vm);
540afc2ba1dSToomas Soome for (cp = tail, len = 0;
541afc2ba1dSToomas Soome cp != vm->tib.end && *cp != 0 && *cp != '\n'; cp++, len++)
542afc2ba1dSToomas Soome ;
543afc2ba1dSToomas Soome
544afc2ba1dSToomas Soome line = malloc(strlen(name) + len + 2);
545c0bb4f73SToomas Soome (void) strcpy(line, name);
546afc2ba1dSToomas Soome if (len > 0) {
547c0bb4f73SToomas Soome (void) strcat(line, " ");
548c0bb4f73SToomas Soome (void) strncat(line, tail, len);
549afc2ba1dSToomas Soome ficlVmUpdateTib(vm, tail + len);
550afc2ba1dSToomas Soome }
551afc2ba1dSToomas Soome }
552afc2ba1dSToomas Soome
553afc2ba1dSToomas Soome command_errmsg = command_errbuf;
554afc2ba1dSToomas Soome command_errbuf[0] = 0;
555afc2ba1dSToomas Soome if (!parse(&argc, &argv, line)) {
556afc2ba1dSToomas Soome result = (cmd)(argc, argv);
557afc2ba1dSToomas Soome free(argv);
558afc2ba1dSToomas Soome } else {
559afc2ba1dSToomas Soome result = BF_PARSE;
560afc2ba1dSToomas Soome }
561afc2ba1dSToomas Soome free(line);
562afc2ba1dSToomas Soome /*
563afc2ba1dSToomas Soome * If there was error during nested ficlExec(), we may no longer have
564afc2ba1dSToomas Soome * valid environment to return. Throw all exceptions from here.
565afc2ba1dSToomas Soome */
566afc2ba1dSToomas Soome if (result != 0)
567afc2ba1dSToomas Soome ficlVmThrow(vm, result);
568afc2ba1dSToomas Soome /* This is going to be thrown!!! */
569afc2ba1dSToomas Soome ficlStackPushInteger(ficlVmGetDataStack(vm), result);
570afc2ba1dSToomas Soome }
571afc2ba1dSToomas Soome
572afc2ba1dSToomas Soome static char *
get_currdev(void)573afc2ba1dSToomas Soome get_currdev(void)
574afc2ba1dSToomas Soome {
575afc2ba1dSToomas Soome int ret;
576afc2ba1dSToomas Soome char *currdev;
577afc2ba1dSToomas Soome FILE *fp;
578afc2ba1dSToomas Soome struct mnttab mpref = {0};
579afc2ba1dSToomas Soome struct mnttab mp = {0};
580afc2ba1dSToomas Soome
581afc2ba1dSToomas Soome mpref.mnt_mountp = "/";
582afc2ba1dSToomas Soome fp = fopen(MNTTAB, "r");
583afc2ba1dSToomas Soome
584afc2ba1dSToomas Soome /* do the best we can to return something... */
585afc2ba1dSToomas Soome if (fp == NULL)
586afc2ba1dSToomas Soome return (strdup(":"));
587afc2ba1dSToomas Soome
588afc2ba1dSToomas Soome ret = getmntany(fp, &mp, &mpref);
589afc2ba1dSToomas Soome (void) fclose(fp);
590afc2ba1dSToomas Soome if (ret == 0)
591afc2ba1dSToomas Soome (void) asprintf(&currdev, "zfs:%s:", mp.mnt_special);
592afc2ba1dSToomas Soome else
593afc2ba1dSToomas Soome return (strdup(":"));
594afc2ba1dSToomas Soome
595afc2ba1dSToomas Soome return (currdev);
596afc2ba1dSToomas Soome }
597afc2ba1dSToomas Soome
598afc2ba1dSToomas Soome /*
599afc2ba1dSToomas Soome * Replace a word definition (a builtin command) with another
600afc2ba1dSToomas Soome * one that:
601afc2ba1dSToomas Soome *
602afc2ba1dSToomas Soome * - Throw error results instead of returning them on the stack
603afc2ba1dSToomas Soome * - Pass a flag indicating whether the word was compiled or is
604afc2ba1dSToomas Soome * being interpreted.
605afc2ba1dSToomas Soome *
606afc2ba1dSToomas Soome * There is one major problem with builtins that cannot be overcome
607afc2ba1dSToomas Soome * in anyway, except by outlawing it. We want builtins to behave
608afc2ba1dSToomas Soome * differently depending on whether they have been compiled or they
609afc2ba1dSToomas Soome * are being interpreted. Notice that this is *not* the interpreter's
610afc2ba1dSToomas Soome * current state. For example:
611afc2ba1dSToomas Soome *
612afc2ba1dSToomas Soome * : example ls ; immediate
613afc2ba1dSToomas Soome * : problem example ; \ "ls" gets executed while compiling
614afc2ba1dSToomas Soome * example \ "ls" gets executed while interpreting
615afc2ba1dSToomas Soome *
616afc2ba1dSToomas Soome * Notice that, though the current state is different in the two
617afc2ba1dSToomas Soome * invocations of "example", in both cases "ls" has been
618afc2ba1dSToomas Soome * *compiled in*, which is what we really want.
619afc2ba1dSToomas Soome *
620afc2ba1dSToomas Soome * The problem arises when you tick the builtin. For example:
621afc2ba1dSToomas Soome *
622afc2ba1dSToomas Soome * : example-1 ['] ls postpone literal ; immediate
623afc2ba1dSToomas Soome * : example-2 example-1 execute ; immediate
624afc2ba1dSToomas Soome * : problem example-2 ;
625afc2ba1dSToomas Soome * example-2
626afc2ba1dSToomas Soome *
627afc2ba1dSToomas Soome * We have no way, when we get EXECUTEd, of knowing what our behavior
628afc2ba1dSToomas Soome * should be. Thus, our only alternative is to "outlaw" this. See RFI
629afc2ba1dSToomas Soome * 0007, and ANS Forth Standard's appendix D, item 6.7 for a related
630afc2ba1dSToomas Soome * problem, concerning compile semantics.
631afc2ba1dSToomas Soome *
632afc2ba1dSToomas Soome * The problem is compounded by the fact that "' builtin CATCH" is valid
633afc2ba1dSToomas Soome * and desirable. The only solution is to create an intermediary word.
634afc2ba1dSToomas Soome * For example:
635afc2ba1dSToomas Soome *
636afc2ba1dSToomas Soome * : my-ls ls ;
637afc2ba1dSToomas Soome * : example ['] my-ls catch ;
638afc2ba1dSToomas Soome *
639afc2ba1dSToomas Soome * So, with the below implementation, here is a summary of the behavior
640afc2ba1dSToomas Soome * of builtins:
641afc2ba1dSToomas Soome *
642afc2ba1dSToomas Soome * ls -l \ "interpret" behavior, ie,
643afc2ba1dSToomas Soome * \ takes parameters from TIB
644afc2ba1dSToomas Soome * : ex-1 s" -l" 1 ls ; \ "compile" behavior, ie,
645afc2ba1dSToomas Soome * \ takes parameters from the stack
646afc2ba1dSToomas Soome * : ex-2 ['] ls catch ; immediate \ undefined behavior
647afc2ba1dSToomas Soome * : ex-3 ['] ls catch ; \ undefined behavior
648afc2ba1dSToomas Soome * ex-2 ex-3 \ "interpret" behavior,
649afc2ba1dSToomas Soome * \ catch works
650afc2ba1dSToomas Soome * : ex-4 ex-2 ; \ "compile" behavior,
651afc2ba1dSToomas Soome * \ catch does not work
652afc2ba1dSToomas Soome * : ex-5 ex-3 ; immediate \ same as ex-2
653afc2ba1dSToomas Soome * : ex-6 ex-3 ; \ same as ex-3
654afc2ba1dSToomas Soome * : ex-7 ['] ex-1 catch ; \ "compile" behavior,
655afc2ba1dSToomas Soome * \ catch works
656afc2ba1dSToomas Soome * : ex-8 postpone ls ; immediate \ same as ex-2
657afc2ba1dSToomas Soome * : ex-9 postpone ls ; \ same as ex-3
658afc2ba1dSToomas Soome *
659afc2ba1dSToomas Soome * As the definition below is particularly tricky, and it's side effects
660afc2ba1dSToomas Soome * must be well understood by those playing with it, I'll be heavy on
661afc2ba1dSToomas Soome * the comments.
662afc2ba1dSToomas Soome *
663afc2ba1dSToomas Soome * (if you edit this definition, pay attention to trailing spaces after
664afc2ba1dSToomas Soome * each word -- I warned you! :-) )
665afc2ba1dSToomas Soome */
666afc2ba1dSToomas Soome #define BUILTIN_CONSTRUCTOR \
667afc2ba1dSToomas Soome ": builtin: " \
668afc2ba1dSToomas Soome ">in @ " /* save the tib index pointer */ \
669afc2ba1dSToomas Soome "' " /* get next word's xt */ \
670afc2ba1dSToomas Soome "swap >in ! " /* point again to next word */ \
671afc2ba1dSToomas Soome "create " /* create a new definition of the next word */ \
672afc2ba1dSToomas Soome ", " /* save previous definition's xt */ \
673afc2ba1dSToomas Soome "immediate " /* make the new definition an immediate word */ \
674afc2ba1dSToomas Soome \
675afc2ba1dSToomas Soome "does> " /* Now, the *new* definition will: */ \
676afc2ba1dSToomas Soome "state @ if " /* if in compiling state: */ \
677afc2ba1dSToomas Soome "1 postpone literal " /* pass 1 flag to indicate compile */ \
678afc2ba1dSToomas Soome "@ compile, " /* compile in previous definition */ \
679afc2ba1dSToomas Soome "postpone throw " /* throw stack-returned result */ \
680afc2ba1dSToomas Soome "else " /* if in interpreting state: */ \
681afc2ba1dSToomas Soome "0 swap " /* pass 0 flag to indicate interpret */ \
682afc2ba1dSToomas Soome "@ execute " /* call previous definition */ \
683afc2ba1dSToomas Soome "throw " /* throw stack-returned result */ \
684afc2ba1dSToomas Soome "then ; "
685afc2ba1dSToomas Soome
686afc2ba1dSToomas Soome extern int ficlExecFD(ficlVm *, int);
687afc2ba1dSToomas Soome
688afc2ba1dSToomas Soome /*
689afc2ba1dSToomas Soome * Initialise the Forth interpreter, create all our commands as words.
690afc2ba1dSToomas Soome */
691afc2ba1dSToomas Soome ficlVm *
bf_init(const char * rc,ficlOutputFunction out)692afc2ba1dSToomas Soome bf_init(const char *rc, ficlOutputFunction out)
693afc2ba1dSToomas Soome {
69495bfa623SToomas Soome struct bootblk_command **cmdp;
695afc2ba1dSToomas Soome char create_buf[41]; /* 31 characters-long builtins */
696afc2ba1dSToomas Soome char *buf;
697afc2ba1dSToomas Soome int fd, rv;
698afc2ba1dSToomas Soome ficlSystemInformation *fsi;
699afc2ba1dSToomas Soome ficlDictionary *dict;
700afc2ba1dSToomas Soome ficlDictionary *env;
701afc2ba1dSToomas Soome
702afc2ba1dSToomas Soome fsi = malloc(sizeof (ficlSystemInformation));
703afc2ba1dSToomas Soome ficlSystemInformationInitialize(fsi);
704afc2ba1dSToomas Soome fsi->textOut = out;
705afc2ba1dSToomas Soome fsi->dictionarySize = BF_DICTSIZE;
706afc2ba1dSToomas Soome
707afc2ba1dSToomas Soome bf_sys = ficlSystemCreate(fsi);
708afc2ba1dSToomas Soome free(fsi);
709afc2ba1dSToomas Soome ficlSystemCompileExtras(bf_sys);
710afc2ba1dSToomas Soome bf_vm = ficlSystemCreateVm(bf_sys);
711afc2ba1dSToomas Soome
712afc2ba1dSToomas Soome buf = isadir();
713afc2ba1dSToomas Soome if (buf == NULL || strcmp(buf, "amd64") != 0) {
714afc2ba1dSToomas Soome (void) setenv("ISADIR", "", 1);
715afc2ba1dSToomas Soome } else {
716afc2ba1dSToomas Soome (void) setenv("ISADIR", buf, 1);
717afc2ba1dSToomas Soome }
718afc2ba1dSToomas Soome if (buf != NULL)
719afc2ba1dSToomas Soome free(buf);
720afc2ba1dSToomas Soome buf = get_currdev();
721afc2ba1dSToomas Soome (void) setenv("currdev", buf, 1);
722afc2ba1dSToomas Soome free(buf);
723*13a19b24SToomas Soome (void) setenv("console", "text", 1);
724afc2ba1dSToomas Soome
725afc2ba1dSToomas Soome /* Put all private definitions in a "builtins" vocabulary */
726afc2ba1dSToomas Soome rv = ficlVmEvaluate(bf_vm,
727afc2ba1dSToomas Soome "vocabulary builtins also builtins definitions");
728afc2ba1dSToomas Soome if (rv != FICL_VM_STATUS_OUT_OF_TEXT) {
729afc2ba1dSToomas Soome printf("error interpreting forth: %d\n", rv);
730afc2ba1dSToomas Soome exit(1);
731afc2ba1dSToomas Soome }
732afc2ba1dSToomas Soome
733afc2ba1dSToomas Soome /* Builtin constructor word */
734afc2ba1dSToomas Soome rv = ficlVmEvaluate(bf_vm, BUILTIN_CONSTRUCTOR);
735afc2ba1dSToomas Soome if (rv != FICL_VM_STATUS_OUT_OF_TEXT) {
736afc2ba1dSToomas Soome printf("error interpreting forth: %d\n", rv);
737afc2ba1dSToomas Soome exit(1);
738afc2ba1dSToomas Soome }
739afc2ba1dSToomas Soome
740afc2ba1dSToomas Soome /* make all commands appear as Forth words */
741afc2ba1dSToomas Soome dict = ficlSystemGetDictionary(bf_sys);
742afc2ba1dSToomas Soome cmdp = NULL;
74395bfa623SToomas Soome
74495bfa623SToomas Soome SET_FOREACH(cmdp, Xcommand_set) {
74595bfa623SToomas Soome (void) ficlDictionaryAppendPrimitive(dict,
74695bfa623SToomas Soome (char *)(*cmdp)->c_name, bf_command, FICL_WORD_DEFAULT);
747afc2ba1dSToomas Soome rv = ficlVmEvaluate(bf_vm, "forth definitions builtins");
748afc2ba1dSToomas Soome if (rv != FICL_VM_STATUS_OUT_OF_TEXT) {
749afc2ba1dSToomas Soome printf("error interpreting forth: %d\n", rv);
750afc2ba1dSToomas Soome exit(1);
751afc2ba1dSToomas Soome }
752c0bb4f73SToomas Soome (void) snprintf(create_buf, sizeof (create_buf), "builtin: %s",
75395bfa623SToomas Soome (*cmdp)->c_name);
754afc2ba1dSToomas Soome rv = ficlVmEvaluate(bf_vm, create_buf);
755afc2ba1dSToomas Soome if (rv != FICL_VM_STATUS_OUT_OF_TEXT) {
756afc2ba1dSToomas Soome printf("error interpreting forth: %d\n", rv);
757afc2ba1dSToomas Soome exit(1);
758afc2ba1dSToomas Soome }
759afc2ba1dSToomas Soome rv = ficlVmEvaluate(bf_vm, "builtins definitions");
760afc2ba1dSToomas Soome if (rv != FICL_VM_STATUS_OUT_OF_TEXT) {
761afc2ba1dSToomas Soome printf("error interpreting forth: %d\n", rv);
762afc2ba1dSToomas Soome exit(1);
763afc2ba1dSToomas Soome }
764afc2ba1dSToomas Soome }
765afc2ba1dSToomas Soome rv = ficlVmEvaluate(bf_vm, "only forth definitions");
766afc2ba1dSToomas Soome if (rv != FICL_VM_STATUS_OUT_OF_TEXT) {
767afc2ba1dSToomas Soome printf("error interpreting forth: %d\n", rv);
768afc2ba1dSToomas Soome exit(1);
769afc2ba1dSToomas Soome }
770afc2ba1dSToomas Soome
771afc2ba1dSToomas Soome /*
772afc2ba1dSToomas Soome * Export some version numbers so that code can detect the
773afc2ba1dSToomas Soome * loader/host version
774afc2ba1dSToomas Soome */
775afc2ba1dSToomas Soome env = ficlSystemGetEnvironment(bf_sys);
776c0bb4f73SToomas Soome (void) ficlDictionarySetConstant(env, "loader_version",
777afc2ba1dSToomas Soome (bootprog_rev[0] - '0') * 10 + (bootprog_rev[2] - '0'));
778afc2ba1dSToomas Soome
779afc2ba1dSToomas Soome /* try to load and run init file if present */
780afc2ba1dSToomas Soome if (rc == NULL)
781afc2ba1dSToomas Soome rc = "/boot/forth/boot.4th";
782afc2ba1dSToomas Soome if (*rc != '\0') {
783afc2ba1dSToomas Soome fd = open(rc, O_RDONLY);
784afc2ba1dSToomas Soome if (fd != -1) {
785afc2ba1dSToomas Soome (void) ficlExecFD(bf_vm, fd);
786c0bb4f73SToomas Soome (void) close(fd);
787afc2ba1dSToomas Soome }
788afc2ba1dSToomas Soome }
789afc2ba1dSToomas Soome
7900bead3caSToomas Soome gfx_framework_init();
791afc2ba1dSToomas Soome return (bf_vm);
792afc2ba1dSToomas Soome }
793afc2ba1dSToomas Soome
794afc2ba1dSToomas Soome void
bf_fini(void)795afc2ba1dSToomas Soome bf_fini(void)
796afc2ba1dSToomas Soome {
797afc2ba1dSToomas Soome ficlSystemDestroy(bf_sys);
7980bead3caSToomas Soome gfx_framework_fini();
799afc2ba1dSToomas Soome }
800afc2ba1dSToomas Soome
801afc2ba1dSToomas Soome /*
802afc2ba1dSToomas Soome * Feed a line of user input to the Forth interpreter
803afc2ba1dSToomas Soome */
804afc2ba1dSToomas Soome int
bf_run(char * line)805afc2ba1dSToomas Soome bf_run(char *line)
806afc2ba1dSToomas Soome {
807afc2ba1dSToomas Soome int result;
808afc2ba1dSToomas Soome ficlString s;
809afc2ba1dSToomas Soome
810afc2ba1dSToomas Soome FICL_STRING_SET_FROM_CSTRING(s, line);
811afc2ba1dSToomas Soome result = ficlVmExecuteString(bf_vm, s);
812afc2ba1dSToomas Soome
813afc2ba1dSToomas Soome switch (result) {
814afc2ba1dSToomas Soome case FICL_VM_STATUS_OUT_OF_TEXT:
815afc2ba1dSToomas Soome case FICL_VM_STATUS_ABORTQ:
816afc2ba1dSToomas Soome case FICL_VM_STATUS_QUIT:
817afc2ba1dSToomas Soome case FICL_VM_STATUS_ERROR_EXIT:
818afc2ba1dSToomas Soome break;
819afc2ba1dSToomas Soome case FICL_VM_STATUS_USER_EXIT:
820afc2ba1dSToomas Soome break;
821afc2ba1dSToomas Soome case FICL_VM_STATUS_ABORT:
822afc2ba1dSToomas Soome printf("Aborted!\n");
823afc2ba1dSToomas Soome break;
824afc2ba1dSToomas Soome case BF_PARSE:
825afc2ba1dSToomas Soome printf("Parse error!\n");
826afc2ba1dSToomas Soome break;
827afc2ba1dSToomas Soome default:
82832b706a1SToomas Soome if (command_errmsg != NULL) {
82932b706a1SToomas Soome printf("%s\n", command_errmsg);
83032b706a1SToomas Soome command_errmsg = NULL;
83132b706a1SToomas Soome }
832afc2ba1dSToomas Soome }
833afc2ba1dSToomas Soome
834c0bb4f73SToomas Soome (void) setenv("interpret", bf_vm->state ? "" : "ok", 1);
835afc2ba1dSToomas Soome
836afc2ba1dSToomas Soome return (result);
837afc2ba1dSToomas Soome }
838afc2ba1dSToomas Soome
839afc2ba1dSToomas Soome char *
get_dev(const char * path)840afc2ba1dSToomas Soome get_dev(const char *path)
841afc2ba1dSToomas Soome {
842afc2ba1dSToomas Soome FILE *fp;
843afc2ba1dSToomas Soome struct mnttab mpref = {0};
844afc2ba1dSToomas Soome struct mnttab mp = {0};
845afc2ba1dSToomas Soome char *currdev;
846afc2ba1dSToomas Soome int ret;
847afc2ba1dSToomas Soome char *buf;
848afc2ba1dSToomas Soome char *tmppath;
849afc2ba1dSToomas Soome char *tmpdev;
850afc2ba1dSToomas Soome char *cwd = NULL;
851afc2ba1dSToomas Soome
852afc2ba1dSToomas Soome fp = fopen(MNTTAB, "r");
853afc2ba1dSToomas Soome
854afc2ba1dSToomas Soome /* do the best we can to return something... */
855afc2ba1dSToomas Soome if (fp == NULL)
856afc2ba1dSToomas Soome return (strdup(path));
857afc2ba1dSToomas Soome
858afc2ba1dSToomas Soome /*
859afc2ba1dSToomas Soome * the path can have device provided, check for it
860afc2ba1dSToomas Soome * and extract it.
861afc2ba1dSToomas Soome */
862afc2ba1dSToomas Soome buf = strrchr(path, ':');
863afc2ba1dSToomas Soome if (buf != NULL) {
864afc2ba1dSToomas Soome tmppath = buf+1; /* real path */
865afc2ba1dSToomas Soome buf = strchr(path, ':'); /* skip zfs: */
866afc2ba1dSToomas Soome buf++;
867afc2ba1dSToomas Soome tmpdev = strdup(buf);
868afc2ba1dSToomas Soome buf = strchr(tmpdev, ':'); /* get ending : */
869afc2ba1dSToomas Soome *buf = '\0';
870afc2ba1dSToomas Soome } else {
871afc2ba1dSToomas Soome tmppath = (char *)path;
872afc2ba1dSToomas Soome if (tmppath[0] != '/')
873afc2ba1dSToomas Soome if ((cwd = getcwd(NULL, PATH_MAX)) == NULL) {
874afc2ba1dSToomas Soome (void) fclose(fp);
875afc2ba1dSToomas Soome return (strdup(path));
876afc2ba1dSToomas Soome }
877afc2ba1dSToomas Soome
878afc2ba1dSToomas Soome currdev = getenv("currdev");
879afc2ba1dSToomas Soome buf = strchr(currdev, ':'); /* skip zfs: */
880afc2ba1dSToomas Soome if (buf == NULL) {
881afc2ba1dSToomas Soome (void) fclose(fp);
882afc2ba1dSToomas Soome return (strdup(path));
883afc2ba1dSToomas Soome }
884afc2ba1dSToomas Soome buf++;
885afc2ba1dSToomas Soome tmpdev = strdup(buf);
886afc2ba1dSToomas Soome buf = strchr(tmpdev, ':'); /* get ending : */
887afc2ba1dSToomas Soome *buf = '\0';
888afc2ba1dSToomas Soome }
889afc2ba1dSToomas Soome
890afc2ba1dSToomas Soome mpref.mnt_special = tmpdev;
891afc2ba1dSToomas Soome ret = getmntany(fp, &mp, &mpref);
892afc2ba1dSToomas Soome (void) fclose(fp);
893afc2ba1dSToomas Soome free(tmpdev);
894afc2ba1dSToomas Soome
895afc2ba1dSToomas Soome if (cwd == NULL)
896afc2ba1dSToomas Soome (void) asprintf(&buf, "%s/%s", ret? "":mp.mnt_mountp, tmppath);
897afc2ba1dSToomas Soome else {
898afc2ba1dSToomas Soome (void) asprintf(&buf, "%s/%s/%s", ret? "":mp.mnt_mountp, cwd,
899afc2ba1dSToomas Soome tmppath);
900afc2ba1dSToomas Soome free(cwd);
901afc2ba1dSToomas Soome }
902afc2ba1dSToomas Soome return (buf);
903afc2ba1dSToomas Soome }
904afc2ba1dSToomas Soome
905afc2ba1dSToomas Soome static void
ngets(char * buf,int n)906afc2ba1dSToomas Soome ngets(char *buf, int n)
907afc2ba1dSToomas Soome {
908afc2ba1dSToomas Soome int c;
909afc2ba1dSToomas Soome char *lp;
910afc2ba1dSToomas Soome
911afc2ba1dSToomas Soome for (lp = buf; ; )
912afc2ba1dSToomas Soome switch (c = getchar() & 0177) {
913afc2ba1dSToomas Soome case '\n':
914afc2ba1dSToomas Soome case '\r':
915afc2ba1dSToomas Soome *lp = '\0';
916c0bb4f73SToomas Soome (void) putchar('\n');
917c0bb4f73SToomas Soome return;
918afc2ba1dSToomas Soome case '\b':
919afc2ba1dSToomas Soome case '\177':
920afc2ba1dSToomas Soome if (lp > buf) {
921afc2ba1dSToomas Soome lp--;
922c0bb4f73SToomas Soome (void) putchar('\b');
923c0bb4f73SToomas Soome (void) putchar(' ');
924c0bb4f73SToomas Soome (void) putchar('\b');
925afc2ba1dSToomas Soome }
926c0bb4f73SToomas Soome break;
927afc2ba1dSToomas Soome case 'r'&037: {
928afc2ba1dSToomas Soome char *p;
929afc2ba1dSToomas Soome
930c0bb4f73SToomas Soome (void) putchar('\n');
931afc2ba1dSToomas Soome for (p = buf; p < lp; ++p)
932c0bb4f73SToomas Soome (void) putchar(*p);
933c0bb4f73SToomas Soome break;
934afc2ba1dSToomas Soome }
935afc2ba1dSToomas Soome case 'u'&037:
936afc2ba1dSToomas Soome case 'w'&037:
937afc2ba1dSToomas Soome lp = buf;
938c0bb4f73SToomas Soome (void) putchar('\n');
939c0bb4f73SToomas Soome break;
940afc2ba1dSToomas Soome default:
941afc2ba1dSToomas Soome if ((n < 1) || ((lp - buf) < n - 1)) {
942afc2ba1dSToomas Soome *lp++ = c;
943c0bb4f73SToomas Soome (void) putchar(c);
944afc2ba1dSToomas Soome }
945afc2ba1dSToomas Soome }
946afc2ba1dSToomas Soome /*NOTREACHED*/
947afc2ba1dSToomas Soome }
948afc2ba1dSToomas Soome
949afc2ba1dSToomas Soome static int
fgetstr(char * buf,int size,int fd)950afc2ba1dSToomas Soome fgetstr(char *buf, int size, int fd)
951afc2ba1dSToomas Soome {
952afc2ba1dSToomas Soome char c;
953afc2ba1dSToomas Soome int err, len;
954afc2ba1dSToomas Soome
955afc2ba1dSToomas Soome size--; /* leave space for terminator */
956afc2ba1dSToomas Soome len = 0;
957afc2ba1dSToomas Soome while (size != 0) {
958afc2ba1dSToomas Soome err = read(fd, &c, sizeof (c));
959afc2ba1dSToomas Soome if (err < 0) /* read error */
960afc2ba1dSToomas Soome return (-1);
961afc2ba1dSToomas Soome
962afc2ba1dSToomas Soome if (err == 0) { /* EOF */
963afc2ba1dSToomas Soome if (len == 0)
964afc2ba1dSToomas Soome return (-1); /* nothing to read */
965afc2ba1dSToomas Soome break;
966afc2ba1dSToomas Soome }
967afc2ba1dSToomas Soome if ((c == '\r') || (c == '\n')) /* line terminators */
968afc2ba1dSToomas Soome break;
969afc2ba1dSToomas Soome *buf++ = c; /* keep char */
970afc2ba1dSToomas Soome size--;
971afc2ba1dSToomas Soome len++;
972afc2ba1dSToomas Soome }
973afc2ba1dSToomas Soome *buf = 0;
974afc2ba1dSToomas Soome return (len);
975afc2ba1dSToomas Soome }
976afc2ba1dSToomas Soome
977afc2ba1dSToomas Soome static char *
unargv(int argc,char * argv[])978afc2ba1dSToomas Soome unargv(int argc, char *argv[])
979afc2ba1dSToomas Soome {
980afc2ba1dSToomas Soome size_t hlong;
981afc2ba1dSToomas Soome int i;
982afc2ba1dSToomas Soome char *cp;
983afc2ba1dSToomas Soome
984afc2ba1dSToomas Soome for (i = 0, hlong = 0; i < argc; i++)
985afc2ba1dSToomas Soome hlong += strlen(argv[i]) + 2;
986afc2ba1dSToomas Soome
987afc2ba1dSToomas Soome if (hlong == 0)
988afc2ba1dSToomas Soome return (NULL);
989afc2ba1dSToomas Soome
990afc2ba1dSToomas Soome cp = malloc(hlong);
991afc2ba1dSToomas Soome cp[0] = 0;
992afc2ba1dSToomas Soome for (i = 0; i < argc; i++) {
993c0bb4f73SToomas Soome (void) strcat(cp, argv[i]);
994afc2ba1dSToomas Soome if (i < (argc - 1))
995c0bb4f73SToomas Soome (void) strcat(cp, " ");
996afc2ba1dSToomas Soome }
997afc2ba1dSToomas Soome
998afc2ba1dSToomas Soome return (cp);
999afc2ba1dSToomas Soome }
1000afc2ba1dSToomas Soome
1001afc2ba1dSToomas Soome /*
1002afc2ba1dSToomas Soome * Help is read from a formatted text file.
1003afc2ba1dSToomas Soome *
1004afc2ba1dSToomas Soome * Entries in the file are formatted as:
1005afc2ba1dSToomas Soome * # Ttopic [Ssubtopic] Ddescription
1006afc2ba1dSToomas Soome * help
1007afc2ba1dSToomas Soome * text
1008afc2ba1dSToomas Soome * here
1009afc2ba1dSToomas Soome * #
1010afc2ba1dSToomas Soome *
1011afc2ba1dSToomas Soome * Note that for code simplicity's sake, the above format must be followed
1012afc2ba1dSToomas Soome * exactly.
1013afc2ba1dSToomas Soome *
1014afc2ba1dSToomas Soome * Subtopic entries must immediately follow the topic (this is used to
1015afc2ba1dSToomas Soome * produce the listing of subtopics).
1016afc2ba1dSToomas Soome *
1017afc2ba1dSToomas Soome * If no argument(s) are supplied by the user, the help for 'help' is displayed.
1018afc2ba1dSToomas Soome */
1019afc2ba1dSToomas Soome static int
help_getnext(int fd,char ** topic,char ** subtopic,char ** desc)1020afc2ba1dSToomas Soome help_getnext(int fd, char **topic, char **subtopic, char **desc)
1021afc2ba1dSToomas Soome {
1022afc2ba1dSToomas Soome char line[81], *cp, *ep;
1023afc2ba1dSToomas Soome
10240a4f1df1SToomas Soome *topic = *subtopic = *desc = NULL;
1025afc2ba1dSToomas Soome for (;;) {
1026afc2ba1dSToomas Soome if (fgetstr(line, 80, fd) < 0)
1027afc2ba1dSToomas Soome return (0);
1028afc2ba1dSToomas Soome
1029e4768a34SToomas Soome if (strlen(line) < 3 || line[0] != '#' || line[1] != ' ')
1030afc2ba1dSToomas Soome continue;
1031afc2ba1dSToomas Soome
1032afc2ba1dSToomas Soome *topic = *subtopic = *desc = NULL;
1033afc2ba1dSToomas Soome cp = line + 2;
1034e4768a34SToomas Soome while (cp != NULL && *cp != 0) {
1035afc2ba1dSToomas Soome ep = strchr(cp, ' ');
1036e4768a34SToomas Soome if (*cp == 'T' && *topic == NULL) {
1037afc2ba1dSToomas Soome if (ep != NULL)
1038afc2ba1dSToomas Soome *ep++ = 0;
1039afc2ba1dSToomas Soome *topic = strdup(cp + 1);
1040e4768a34SToomas Soome } else if (*cp == 'S' && *subtopic == NULL) {
1041afc2ba1dSToomas Soome if (ep != NULL)
1042afc2ba1dSToomas Soome *ep++ = 0;
1043afc2ba1dSToomas Soome *subtopic = strdup(cp + 1);
1044afc2ba1dSToomas Soome } else if (*cp == 'D') {
1045afc2ba1dSToomas Soome *desc = strdup(cp + 1);
1046afc2ba1dSToomas Soome ep = NULL;
1047afc2ba1dSToomas Soome }
1048afc2ba1dSToomas Soome cp = ep;
1049afc2ba1dSToomas Soome }
1050afc2ba1dSToomas Soome if (*topic == NULL) {
10510a4f1df1SToomas Soome free(*subtopic);
10520a4f1df1SToomas Soome free(*desc);
1053afc2ba1dSToomas Soome continue;
1054afc2ba1dSToomas Soome }
1055afc2ba1dSToomas Soome return (1);
1056afc2ba1dSToomas Soome }
1057afc2ba1dSToomas Soome }
1058afc2ba1dSToomas Soome
1059afc2ba1dSToomas Soome static int
help_emitsummary(char * topic,char * subtopic,char * desc)1060afc2ba1dSToomas Soome help_emitsummary(char *topic, char *subtopic, char *desc)
1061afc2ba1dSToomas Soome {
1062afc2ba1dSToomas Soome int i;
1063afc2ba1dSToomas Soome
1064c0bb4f73SToomas Soome (void) pager_output(" ");
1065c0bb4f73SToomas Soome (void) pager_output(topic);
1066afc2ba1dSToomas Soome i = strlen(topic);
1067afc2ba1dSToomas Soome if (subtopic != NULL) {
1068c0bb4f73SToomas Soome (void) pager_output(" ");
1069c0bb4f73SToomas Soome (void) pager_output(subtopic);
1070afc2ba1dSToomas Soome i += strlen(subtopic) + 1;
1071afc2ba1dSToomas Soome }
1072afc2ba1dSToomas Soome if (desc != NULL) {
1073afc2ba1dSToomas Soome do {
1074c0bb4f73SToomas Soome (void) pager_output(" ");
1075afc2ba1dSToomas Soome } while (i++ < 30);
1076c0bb4f73SToomas Soome (void) pager_output(desc);
1077afc2ba1dSToomas Soome }
1078afc2ba1dSToomas Soome return (pager_output("\n"));
1079afc2ba1dSToomas Soome }
1080afc2ba1dSToomas Soome
108195bfa623SToomas Soome COMMAND_SET(help, "help", "detailed help", command_help);
108295bfa623SToomas Soome
1083afc2ba1dSToomas Soome static int
command_help(int argc,char * argv[])1084afc2ba1dSToomas Soome command_help(int argc, char *argv[])
1085afc2ba1dSToomas Soome {
1086afc2ba1dSToomas Soome char buf[81]; /* XXX buffer size? */
1087afc2ba1dSToomas Soome int hfd, matched, doindex;
1088afc2ba1dSToomas Soome char *topic, *subtopic, *t, *s, *d;
1089afc2ba1dSToomas Soome
1090afc2ba1dSToomas Soome /* page the help text from our load path */
1091c0bb4f73SToomas Soome (void) snprintf(buf, sizeof (buf), "/boot/loader.help");
1092afc2ba1dSToomas Soome if ((hfd = open(buf, O_RDONLY)) < 0) {
1093afc2ba1dSToomas Soome printf("Verbose help not available, "
1094afc2ba1dSToomas Soome "use '?' to list commands\n");
1095afc2ba1dSToomas Soome return (CMD_OK);
1096afc2ba1dSToomas Soome }
1097afc2ba1dSToomas Soome
1098afc2ba1dSToomas Soome /* pick up request from arguments */
1099afc2ba1dSToomas Soome topic = subtopic = NULL;
1100afc2ba1dSToomas Soome switch (argc) {
1101afc2ba1dSToomas Soome case 3:
1102afc2ba1dSToomas Soome subtopic = strdup(argv[2]);
1103d65dfb0aSToomas Soome /* FALLTHROUGH */
1104afc2ba1dSToomas Soome case 2:
1105afc2ba1dSToomas Soome topic = strdup(argv[1]);
1106afc2ba1dSToomas Soome break;
1107afc2ba1dSToomas Soome case 1:
1108afc2ba1dSToomas Soome topic = strdup("help");
1109afc2ba1dSToomas Soome break;
1110afc2ba1dSToomas Soome default:
1111afc2ba1dSToomas Soome command_errmsg = "usage is 'help <topic> [<subtopic>]";
1112c0bb4f73SToomas Soome (void) close(hfd);
1113afc2ba1dSToomas Soome return (CMD_ERROR);
1114afc2ba1dSToomas Soome }
1115afc2ba1dSToomas Soome
1116afc2ba1dSToomas Soome /* magic "index" keyword */
1117afc2ba1dSToomas Soome doindex = strcmp(topic, "index") == 0;
1118afc2ba1dSToomas Soome matched = doindex;
1119afc2ba1dSToomas Soome
1120afc2ba1dSToomas Soome /* Scan the helpfile looking for help matching the request */
1121afc2ba1dSToomas Soome pager_open();
1122afc2ba1dSToomas Soome while (help_getnext(hfd, &t, &s, &d)) {
1123afc2ba1dSToomas Soome if (doindex) { /* dink around formatting */
1124afc2ba1dSToomas Soome if (help_emitsummary(t, s, d))
1125afc2ba1dSToomas Soome break;
1126afc2ba1dSToomas Soome
1127afc2ba1dSToomas Soome } else if (strcmp(topic, t)) {
1128afc2ba1dSToomas Soome /* topic mismatch */
1129afc2ba1dSToomas Soome /* nothing more on this topic, stop scanning */
1130afc2ba1dSToomas Soome if (matched)
1131afc2ba1dSToomas Soome break;
1132afc2ba1dSToomas Soome } else {
1133afc2ba1dSToomas Soome /* topic matched */
1134afc2ba1dSToomas Soome matched = 1;
1135e4768a34SToomas Soome if ((subtopic == NULL && s == NULL) ||
1136e4768a34SToomas Soome (subtopic != NULL && s != NULL &&
1137afc2ba1dSToomas Soome strcmp(subtopic, s) == 0)) {
1138afc2ba1dSToomas Soome /* exact match, print text */
1139e4768a34SToomas Soome while (fgetstr(buf, 80, hfd) >= 0 &&
1140e4768a34SToomas Soome buf[0] != '#') {
1141afc2ba1dSToomas Soome if (pager_output(buf))
1142afc2ba1dSToomas Soome break;
1143afc2ba1dSToomas Soome if (pager_output("\n"))
1144afc2ba1dSToomas Soome break;
1145afc2ba1dSToomas Soome }
1146e4768a34SToomas Soome } else if (subtopic == NULL && s != NULL) {
1147afc2ba1dSToomas Soome /* topic match, list subtopics */
1148afc2ba1dSToomas Soome if (help_emitsummary(t, s, d))
1149afc2ba1dSToomas Soome break;
1150afc2ba1dSToomas Soome }
1151afc2ba1dSToomas Soome }
1152afc2ba1dSToomas Soome free(t);
1153afc2ba1dSToomas Soome free(s);
1154afc2ba1dSToomas Soome free(d);
11550a4f1df1SToomas Soome t = s = d = NULL;
1156afc2ba1dSToomas Soome }
11570a4f1df1SToomas Soome free(t);
11580a4f1df1SToomas Soome free(s);
11590a4f1df1SToomas Soome free(d);
1160afc2ba1dSToomas Soome pager_close();
1161c0bb4f73SToomas Soome (void) close(hfd);
1162afc2ba1dSToomas Soome if (!matched) {
1163c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1164afc2ba1dSToomas Soome "no help available for '%s'", topic);
1165afc2ba1dSToomas Soome free(topic);
11660a4f1df1SToomas Soome free(subtopic);
1167afc2ba1dSToomas Soome return (CMD_ERROR);
1168afc2ba1dSToomas Soome }
1169afc2ba1dSToomas Soome free(topic);
11700a4f1df1SToomas Soome free(subtopic);
1171afc2ba1dSToomas Soome return (CMD_OK);
1172afc2ba1dSToomas Soome }
1173afc2ba1dSToomas Soome
117495bfa623SToomas Soome COMMAND_SET(commandlist, "?", "list commands", command_commandlist);
117595bfa623SToomas Soome
1176afc2ba1dSToomas Soome static int
command_commandlist(int argc __unused,char * argv[]__unused)11770a4f1df1SToomas Soome command_commandlist(int argc __unused, char *argv[] __unused)
1178afc2ba1dSToomas Soome {
117995bfa623SToomas Soome struct bootblk_command **cmdp;
1180afc2ba1dSToomas Soome int res;
1181afc2ba1dSToomas Soome char name[20];
1182afc2ba1dSToomas Soome
1183afc2ba1dSToomas Soome res = 0;
1184afc2ba1dSToomas Soome pager_open();
1185afc2ba1dSToomas Soome res = pager_output("Available commands:\n");
118695bfa623SToomas Soome SET_FOREACH(cmdp, Xcommand_set) {
1187afc2ba1dSToomas Soome if (res)
1188afc2ba1dSToomas Soome break;
118995bfa623SToomas Soome if ((*cmdp)->c_name != NULL && (*cmdp)->c_desc != NULL) {
1190c0bb4f73SToomas Soome (void) snprintf(name, sizeof (name), " %-15s ",
119195bfa623SToomas Soome (*cmdp)->c_name);
1192c0bb4f73SToomas Soome (void) pager_output(name);
119395bfa623SToomas Soome (void) pager_output((*cmdp)->c_desc);
1194afc2ba1dSToomas Soome res = pager_output("\n");
1195afc2ba1dSToomas Soome }
1196afc2ba1dSToomas Soome }
1197afc2ba1dSToomas Soome pager_close();
1198afc2ba1dSToomas Soome return (CMD_OK);
1199afc2ba1dSToomas Soome }
1200afc2ba1dSToomas Soome
1201afc2ba1dSToomas Soome /*
1202afc2ba1dSToomas Soome * XXX set/show should become set/echo if we have variable
1203afc2ba1dSToomas Soome * substitution happening.
1204afc2ba1dSToomas Soome */
120595bfa623SToomas Soome COMMAND_SET(show, "show", "show variable(s)", command_show);
120695bfa623SToomas Soome COMMAND_SET(printenv, "printenv", "show variable(s)", command_show);
120795bfa623SToomas Soome
1208afc2ba1dSToomas Soome static int
command_show(int argc,char * argv[])1209afc2ba1dSToomas Soome command_show(int argc, char *argv[])
1210afc2ba1dSToomas Soome {
1211afc2ba1dSToomas Soome char **ev;
1212afc2ba1dSToomas Soome char *cp;
1213afc2ba1dSToomas Soome
1214afc2ba1dSToomas Soome if (argc < 2) {
1215afc2ba1dSToomas Soome /*
1216afc2ba1dSToomas Soome * With no arguments, print everything.
1217afc2ba1dSToomas Soome */
1218afc2ba1dSToomas Soome pager_open();
1219afc2ba1dSToomas Soome for (ev = _environ; *ev != NULL; ev++) {
1220c0bb4f73SToomas Soome (void) pager_output(*ev);
1221afc2ba1dSToomas Soome cp = getenv(*ev);
1222afc2ba1dSToomas Soome if (cp != NULL) {
1223c0bb4f73SToomas Soome (void) pager_output("=");
1224c0bb4f73SToomas Soome (void) pager_output(cp);
1225afc2ba1dSToomas Soome }
1226afc2ba1dSToomas Soome if (pager_output("\n"))
1227afc2ba1dSToomas Soome break;
1228afc2ba1dSToomas Soome }
1229afc2ba1dSToomas Soome pager_close();
1230afc2ba1dSToomas Soome } else {
1231afc2ba1dSToomas Soome if ((cp = getenv(argv[1])) != NULL) {
1232afc2ba1dSToomas Soome printf("%s\n", cp);
1233afc2ba1dSToomas Soome } else {
1234c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1235afc2ba1dSToomas Soome "variable '%s' not found", argv[1]);
1236afc2ba1dSToomas Soome return (CMD_ERROR);
1237afc2ba1dSToomas Soome }
1238afc2ba1dSToomas Soome }
1239afc2ba1dSToomas Soome return (CMD_OK);
1240afc2ba1dSToomas Soome }
1241afc2ba1dSToomas Soome
124295bfa623SToomas Soome COMMAND_SET(set, "set", "set a variable", command_set);
1243afc2ba1dSToomas Soome static int
command_set(int argc,char * argv[])1244afc2ba1dSToomas Soome command_set(int argc, char *argv[])
1245afc2ba1dSToomas Soome {
1246afc2ba1dSToomas Soome int err;
1247afc2ba1dSToomas Soome char *value, *copy;
1248afc2ba1dSToomas Soome
1249afc2ba1dSToomas Soome if (argc != 2) {
1250afc2ba1dSToomas Soome command_errmsg = "wrong number of arguments";
1251afc2ba1dSToomas Soome return (CMD_ERROR);
1252afc2ba1dSToomas Soome } else {
1253afc2ba1dSToomas Soome copy = strdup(argv[1]);
1254afc2ba1dSToomas Soome if (copy == NULL) {
1255afc2ba1dSToomas Soome command_errmsg = strerror(errno);
1256afc2ba1dSToomas Soome return (CMD_ERROR);
1257afc2ba1dSToomas Soome }
1258afc2ba1dSToomas Soome if ((value = strchr(copy, '=')) != NULL)
1259afc2ba1dSToomas Soome *(value++) = 0;
1260afc2ba1dSToomas Soome else
1261afc2ba1dSToomas Soome value = "";
1262afc2ba1dSToomas Soome if ((err = setenv(copy, value, 1)) != 0) {
1263afc2ba1dSToomas Soome free(copy);
1264afc2ba1dSToomas Soome command_errmsg = strerror(errno);
1265afc2ba1dSToomas Soome return (CMD_ERROR);
1266afc2ba1dSToomas Soome }
1267afc2ba1dSToomas Soome free(copy);
1268afc2ba1dSToomas Soome }
1269afc2ba1dSToomas Soome return (CMD_OK);
1270afc2ba1dSToomas Soome }
1271afc2ba1dSToomas Soome
127295bfa623SToomas Soome COMMAND_SET(setprop, "setprop", "set a variable", command_setprop);
1273afc2ba1dSToomas Soome static int
command_setprop(int argc,char * argv[])1274afc2ba1dSToomas Soome command_setprop(int argc, char *argv[])
1275afc2ba1dSToomas Soome {
1276afc2ba1dSToomas Soome int err;
1277afc2ba1dSToomas Soome
1278afc2ba1dSToomas Soome if (argc != 3) {
1279afc2ba1dSToomas Soome command_errmsg = "wrong number of arguments";
1280afc2ba1dSToomas Soome return (CMD_ERROR);
1281afc2ba1dSToomas Soome } else {
1282afc2ba1dSToomas Soome if ((err = setenv(argv[1], argv[2], 1)) != 0) {
1283afc2ba1dSToomas Soome command_errmsg = strerror(err);
1284afc2ba1dSToomas Soome return (CMD_ERROR);
1285afc2ba1dSToomas Soome }
1286afc2ba1dSToomas Soome }
1287afc2ba1dSToomas Soome return (CMD_OK);
1288afc2ba1dSToomas Soome }
1289afc2ba1dSToomas Soome
129095bfa623SToomas Soome COMMAND_SET(unset, "unset", "unset a variable", command_unset);
1291afc2ba1dSToomas Soome static int
command_unset(int argc,char * argv[])1292afc2ba1dSToomas Soome command_unset(int argc, char *argv[])
1293afc2ba1dSToomas Soome {
1294afc2ba1dSToomas Soome int err;
1295afc2ba1dSToomas Soome
1296afc2ba1dSToomas Soome if (argc != 2) {
1297afc2ba1dSToomas Soome command_errmsg = "wrong number of arguments";
1298afc2ba1dSToomas Soome return (CMD_ERROR);
1299afc2ba1dSToomas Soome } else {
1300afc2ba1dSToomas Soome if ((err = unsetenv(argv[1])) != 0) {
1301afc2ba1dSToomas Soome command_errmsg = strerror(err);
1302afc2ba1dSToomas Soome return (CMD_ERROR);
1303afc2ba1dSToomas Soome }
1304afc2ba1dSToomas Soome }
1305afc2ba1dSToomas Soome return (CMD_OK);
1306afc2ba1dSToomas Soome }
1307afc2ba1dSToomas Soome
130895bfa623SToomas Soome COMMAND_SET(echo, "echo", "echo arguments", command_echo);
1309afc2ba1dSToomas Soome static int
command_echo(int argc,char * argv[])1310afc2ba1dSToomas Soome command_echo(int argc, char *argv[])
1311afc2ba1dSToomas Soome {
1312afc2ba1dSToomas Soome char *s;
1313afc2ba1dSToomas Soome int nl, ch;
1314afc2ba1dSToomas Soome
1315afc2ba1dSToomas Soome nl = 0;
1316afc2ba1dSToomas Soome optind = 1;
1317afc2ba1dSToomas Soome opterr = 1;
1318afc2ba1dSToomas Soome while ((ch = getopt(argc, argv, "n")) != -1) {
1319afc2ba1dSToomas Soome switch (ch) {
1320afc2ba1dSToomas Soome case 'n':
1321afc2ba1dSToomas Soome nl = 1;
1322afc2ba1dSToomas Soome break;
1323afc2ba1dSToomas Soome case '?':
1324afc2ba1dSToomas Soome default:
1325afc2ba1dSToomas Soome /* getopt has already reported an error */
1326afc2ba1dSToomas Soome return (CMD_OK);
1327afc2ba1dSToomas Soome }
1328afc2ba1dSToomas Soome }
1329afc2ba1dSToomas Soome argv += (optind);
1330afc2ba1dSToomas Soome argc -= (optind);
1331afc2ba1dSToomas Soome
1332afc2ba1dSToomas Soome s = unargv(argc, argv);
1333afc2ba1dSToomas Soome if (s != NULL) {
1334afc2ba1dSToomas Soome printf("%s", s);
1335afc2ba1dSToomas Soome free(s);
1336afc2ba1dSToomas Soome }
1337afc2ba1dSToomas Soome if (!nl)
1338afc2ba1dSToomas Soome printf("\n");
1339afc2ba1dSToomas Soome return (CMD_OK);
1340afc2ba1dSToomas Soome }
1341afc2ba1dSToomas Soome
1342afc2ba1dSToomas Soome /*
1343afc2ba1dSToomas Soome * A passable emulation of the sh(1) command of the same name.
1344afc2ba1dSToomas Soome */
1345afc2ba1dSToomas Soome static int
ischar(void)1346afc2ba1dSToomas Soome ischar(void)
1347afc2ba1dSToomas Soome {
1348afc2ba1dSToomas Soome return (1);
1349afc2ba1dSToomas Soome }
1350afc2ba1dSToomas Soome
135195bfa623SToomas Soome COMMAND_SET(read, "read", "read input from the terminal", command_read);
1352afc2ba1dSToomas Soome static int
command_read(int argc,char * argv[])1353afc2ba1dSToomas Soome command_read(int argc, char *argv[])
1354afc2ba1dSToomas Soome {
1355afc2ba1dSToomas Soome char *prompt;
1356afc2ba1dSToomas Soome int timeout;
1357afc2ba1dSToomas Soome time_t when;
1358afc2ba1dSToomas Soome char *cp;
1359afc2ba1dSToomas Soome char *name;
1360afc2ba1dSToomas Soome char buf[256]; /* XXX size? */
1361afc2ba1dSToomas Soome int c;
1362afc2ba1dSToomas Soome
1363afc2ba1dSToomas Soome timeout = -1;
1364afc2ba1dSToomas Soome prompt = NULL;
1365afc2ba1dSToomas Soome optind = 1;
1366afc2ba1dSToomas Soome opterr = 1;
1367afc2ba1dSToomas Soome while ((c = getopt(argc, argv, "p:t:")) != -1) {
1368afc2ba1dSToomas Soome switch (c) {
1369afc2ba1dSToomas Soome case 'p':
1370afc2ba1dSToomas Soome prompt = optarg;
1371afc2ba1dSToomas Soome break;
1372afc2ba1dSToomas Soome case 't':
1373afc2ba1dSToomas Soome timeout = strtol(optarg, &cp, 0);
1374afc2ba1dSToomas Soome if (cp == optarg) {
1375c0bb4f73SToomas Soome (void) snprintf(command_errbuf,
1376afc2ba1dSToomas Soome sizeof (command_errbuf),
1377afc2ba1dSToomas Soome "bad timeout '%s'", optarg);
1378afc2ba1dSToomas Soome return (CMD_ERROR);
1379afc2ba1dSToomas Soome }
1380afc2ba1dSToomas Soome break;
1381afc2ba1dSToomas Soome default:
1382afc2ba1dSToomas Soome return (CMD_OK);
1383afc2ba1dSToomas Soome }
1384afc2ba1dSToomas Soome }
1385afc2ba1dSToomas Soome
1386afc2ba1dSToomas Soome argv += (optind);
1387afc2ba1dSToomas Soome argc -= (optind);
1388afc2ba1dSToomas Soome name = (argc > 0) ? argv[0]: NULL;
1389afc2ba1dSToomas Soome
1390afc2ba1dSToomas Soome if (prompt != NULL)
1391afc2ba1dSToomas Soome printf("%s", prompt);
1392afc2ba1dSToomas Soome if (timeout >= 0) {
1393afc2ba1dSToomas Soome when = time(NULL) + timeout;
1394afc2ba1dSToomas Soome while (!ischar())
1395afc2ba1dSToomas Soome if (time(NULL) >= when)
1396afc2ba1dSToomas Soome return (CMD_OK); /* is timeout an error? */
1397afc2ba1dSToomas Soome }
1398afc2ba1dSToomas Soome
1399afc2ba1dSToomas Soome ngets(buf, sizeof (buf));
1400afc2ba1dSToomas Soome
1401afc2ba1dSToomas Soome if (name != NULL)
1402c0bb4f73SToomas Soome (void) setenv(name, buf, 1);
1403afc2ba1dSToomas Soome return (CMD_OK);
1404afc2ba1dSToomas Soome }
1405afc2ba1dSToomas Soome
1406afc2ba1dSToomas Soome /*
1407afc2ba1dSToomas Soome * File pager
1408afc2ba1dSToomas Soome */
140995bfa623SToomas Soome COMMAND_SET(more, "more", "show contents of a file", command_more);
1410afc2ba1dSToomas Soome static int
command_more(int argc,char * argv[])1411afc2ba1dSToomas Soome command_more(int argc, char *argv[])
1412afc2ba1dSToomas Soome {
1413afc2ba1dSToomas Soome int i;
1414afc2ba1dSToomas Soome int res;
1415afc2ba1dSToomas Soome char line[80];
1416afc2ba1dSToomas Soome char *name;
1417afc2ba1dSToomas Soome
1418afc2ba1dSToomas Soome res = 0;
1419afc2ba1dSToomas Soome pager_open();
1420afc2ba1dSToomas Soome for (i = 1; (i < argc) && (res == 0); i++) {
1421c0bb4f73SToomas Soome (void) snprintf(line, sizeof (line), "*** FILE %s BEGIN ***\n",
14220a4f1df1SToomas Soome argv[i]);
1423afc2ba1dSToomas Soome if (pager_output(line))
1424afc2ba1dSToomas Soome break;
1425afc2ba1dSToomas Soome name = get_dev(argv[i]);
1426afc2ba1dSToomas Soome res = page_file(name);
1427afc2ba1dSToomas Soome free(name);
1428afc2ba1dSToomas Soome if (!res) {
1429c0bb4f73SToomas Soome (void) snprintf(line, sizeof (line),
1430c0bb4f73SToomas Soome "*** FILE %s END ***\n", argv[i]);
1431afc2ba1dSToomas Soome res = pager_output(line);
1432afc2ba1dSToomas Soome }
1433afc2ba1dSToomas Soome }
1434afc2ba1dSToomas Soome pager_close();
1435afc2ba1dSToomas Soome
1436afc2ba1dSToomas Soome if (res == 0)
1437afc2ba1dSToomas Soome return (CMD_OK);
1438afc2ba1dSToomas Soome return (CMD_ERROR);
1439afc2ba1dSToomas Soome }
1440afc2ba1dSToomas Soome
1441afc2ba1dSToomas Soome static int
page_file(char * filename)1442afc2ba1dSToomas Soome page_file(char *filename)
1443afc2ba1dSToomas Soome {
1444afc2ba1dSToomas Soome int result;
1445afc2ba1dSToomas Soome
1446afc2ba1dSToomas Soome result = pager_file(filename);
1447afc2ba1dSToomas Soome
1448afc2ba1dSToomas Soome if (result == -1) {
1449c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1450afc2ba1dSToomas Soome "error showing %s", filename);
1451afc2ba1dSToomas Soome }
1452afc2ba1dSToomas Soome
1453afc2ba1dSToomas Soome return (result);
1454afc2ba1dSToomas Soome }
1455afc2ba1dSToomas Soome
145695bfa623SToomas Soome COMMAND_SET(ls, "ls", "list files", command_ls);
1457afc2ba1dSToomas Soome static int
command_ls(int argc,char * argv[])1458afc2ba1dSToomas Soome command_ls(int argc, char *argv[])
1459afc2ba1dSToomas Soome {
1460afc2ba1dSToomas Soome DIR *dir;
1461afc2ba1dSToomas Soome int fd;
1462afc2ba1dSToomas Soome struct stat sb;
1463afc2ba1dSToomas Soome struct dirent *d;
1464afc2ba1dSToomas Soome char *buf, *path;
1465afc2ba1dSToomas Soome char lbuf[128]; /* one line */
1466afc2ba1dSToomas Soome int result, ch;
1467afc2ba1dSToomas Soome int verbose;
1468afc2ba1dSToomas Soome
1469afc2ba1dSToomas Soome result = CMD_OK;
1470afc2ba1dSToomas Soome fd = -1;
1471afc2ba1dSToomas Soome verbose = 0;
1472afc2ba1dSToomas Soome optind = 1;
1473afc2ba1dSToomas Soome opterr = 1;
1474afc2ba1dSToomas Soome while ((ch = getopt(argc, argv, "l")) != -1) {
1475afc2ba1dSToomas Soome switch (ch) {
1476afc2ba1dSToomas Soome case 'l':
1477afc2ba1dSToomas Soome verbose = 1;
1478afc2ba1dSToomas Soome break;
1479afc2ba1dSToomas Soome case '?':
1480afc2ba1dSToomas Soome default:
1481afc2ba1dSToomas Soome /* getopt has already reported an error */
1482afc2ba1dSToomas Soome return (CMD_OK);
1483afc2ba1dSToomas Soome }
1484afc2ba1dSToomas Soome }
1485afc2ba1dSToomas Soome argv += (optind - 1);
1486afc2ba1dSToomas Soome argc -= (optind - 1);
1487afc2ba1dSToomas Soome
1488afc2ba1dSToomas Soome if (argc < 2) {
1489afc2ba1dSToomas Soome path = "";
1490afc2ba1dSToomas Soome } else {
1491afc2ba1dSToomas Soome path = argv[1];
1492afc2ba1dSToomas Soome }
1493afc2ba1dSToomas Soome
1494afc2ba1dSToomas Soome fd = ls_getdir(&path);
1495afc2ba1dSToomas Soome if (fd == -1) {
1496afc2ba1dSToomas Soome result = CMD_ERROR;
1497afc2ba1dSToomas Soome goto out;
1498afc2ba1dSToomas Soome }
1499afc2ba1dSToomas Soome dir = fdopendir(fd);
1500afc2ba1dSToomas Soome pager_open();
1501c0bb4f73SToomas Soome (void) pager_output(path);
1502c0bb4f73SToomas Soome (void) pager_output("\n");
1503afc2ba1dSToomas Soome
1504afc2ba1dSToomas Soome while ((d = readdir(dir)) != NULL) {
1505afc2ba1dSToomas Soome if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) {
1506afc2ba1dSToomas Soome /* stat the file, if possible */
15070a4f1df1SToomas Soome if (path[0] == '\0') {
1508d9c27481SToomas Soome (void) asprintf(&buf, "%s", d->d_name);
1509c0bb4f73SToomas Soome } else {
1510d9c27481SToomas Soome (void) asprintf(&buf, "%s/%s", path, d->d_name);
1511d9c27481SToomas Soome }
1512d9c27481SToomas Soome if (buf != NULL) {
1513d9c27481SToomas Soome /* ignore return, could be symlink, etc. */
1514d9c27481SToomas Soome if (stat(buf, &sb)) {
1515d9c27481SToomas Soome sb.st_size = 0;
1516d9c27481SToomas Soome sb.st_mode = 0;
1517d9c27481SToomas Soome }
1518d9c27481SToomas Soome free(buf);
15190a4f1df1SToomas Soome }
1520afc2ba1dSToomas Soome if (verbose) {
1521c0bb4f73SToomas Soome (void) snprintf(lbuf, sizeof (lbuf),
1522c0bb4f73SToomas Soome " %c %8d %s\n",
1523afc2ba1dSToomas Soome typestr[sb.st_mode >> 12],
1524afc2ba1dSToomas Soome (int)sb.st_size, d->d_name);
1525afc2ba1dSToomas Soome } else {
1526c0bb4f73SToomas Soome (void) snprintf(lbuf, sizeof (lbuf),
1527c0bb4f73SToomas Soome " %c %s\n",
1528afc2ba1dSToomas Soome typestr[sb.st_mode >> 12], d->d_name);
1529afc2ba1dSToomas Soome }
1530afc2ba1dSToomas Soome if (pager_output(lbuf))
1531afc2ba1dSToomas Soome goto out;
1532afc2ba1dSToomas Soome }
1533afc2ba1dSToomas Soome }
1534afc2ba1dSToomas Soome out:
1535afc2ba1dSToomas Soome pager_close();
1536afc2ba1dSToomas Soome if (fd != -1)
1537c0bb4f73SToomas Soome (void) closedir(dir);
1538afc2ba1dSToomas Soome if (path != NULL)
1539afc2ba1dSToomas Soome free(path);
1540afc2ba1dSToomas Soome return (result);
1541afc2ba1dSToomas Soome }
1542afc2ba1dSToomas Soome
1543afc2ba1dSToomas Soome /*
1544afc2ba1dSToomas Soome * Given (path) containing a vaguely reasonable path specification, return an fd
1545afc2ba1dSToomas Soome * on the directory, and an allocated copy of the path to the directory.
1546afc2ba1dSToomas Soome */
1547afc2ba1dSToomas Soome static int
ls_getdir(char ** pathp)1548afc2ba1dSToomas Soome ls_getdir(char **pathp)
1549afc2ba1dSToomas Soome {
1550afc2ba1dSToomas Soome struct stat sb;
1551afc2ba1dSToomas Soome int fd;
1552afc2ba1dSToomas Soome char *cp, *path;
1553afc2ba1dSToomas Soome
1554afc2ba1dSToomas Soome fd = -1;
1555afc2ba1dSToomas Soome
1556afc2ba1dSToomas Soome /* one extra byte for a possible trailing slash required */
1557afc2ba1dSToomas Soome path = malloc(strlen(*pathp) + 2);
1558c0bb4f73SToomas Soome (void) strcpy(path, *pathp);
1559afc2ba1dSToomas Soome
1560afc2ba1dSToomas Soome /* Make sure the path is respectable to begin with */
1561afc2ba1dSToomas Soome if ((cp = get_dev(path)) == NULL) {
1562c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1563afc2ba1dSToomas Soome "bad path '%s'", path);
1564afc2ba1dSToomas Soome goto out;
1565afc2ba1dSToomas Soome }
1566afc2ba1dSToomas Soome
1567afc2ba1dSToomas Soome /* If there's no path on the device, assume '/' */
1568afc2ba1dSToomas Soome if (*cp == 0)
1569c0bb4f73SToomas Soome (void) strcat(path, "/");
1570afc2ba1dSToomas Soome
1571afc2ba1dSToomas Soome fd = open(cp, O_RDONLY);
1572afc2ba1dSToomas Soome if (fd < 0) {
1573c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1574afc2ba1dSToomas Soome "open '%s' failed: %s", path, strerror(errno));
1575afc2ba1dSToomas Soome goto out;
1576afc2ba1dSToomas Soome }
1577afc2ba1dSToomas Soome if (fstat(fd, &sb) < 0) {
1578c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1579afc2ba1dSToomas Soome "stat failed: %s", strerror(errno));
1580afc2ba1dSToomas Soome goto out;
1581afc2ba1dSToomas Soome }
1582afc2ba1dSToomas Soome if (!S_ISDIR(sb.st_mode)) {
1583c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1584afc2ba1dSToomas Soome "%s: %s", path, strerror(ENOTDIR));
1585afc2ba1dSToomas Soome goto out;
1586afc2ba1dSToomas Soome }
1587afc2ba1dSToomas Soome
1588afc2ba1dSToomas Soome free(cp);
1589afc2ba1dSToomas Soome *pathp = path;
1590afc2ba1dSToomas Soome return (fd);
1591afc2ba1dSToomas Soome
1592afc2ba1dSToomas Soome out:
1593afc2ba1dSToomas Soome free(cp);
1594afc2ba1dSToomas Soome free(path);
1595afc2ba1dSToomas Soome *pathp = NULL;
1596afc2ba1dSToomas Soome if (fd != -1)
1597c0bb4f73SToomas Soome (void) close(fd);
1598afc2ba1dSToomas Soome return (-1);
1599afc2ba1dSToomas Soome }
1600afc2ba1dSToomas Soome
160195bfa623SToomas Soome COMMAND_SET(include, "include", "read commands from a file", command_include);
1602afc2ba1dSToomas Soome static int
command_include(int argc,char * argv[])1603afc2ba1dSToomas Soome command_include(int argc, char *argv[])
1604afc2ba1dSToomas Soome {
1605afc2ba1dSToomas Soome int i;
1606afc2ba1dSToomas Soome int res;
1607afc2ba1dSToomas Soome char **argvbuf;
1608afc2ba1dSToomas Soome
1609afc2ba1dSToomas Soome /*
1610afc2ba1dSToomas Soome * Since argv is static, we need to save it here.
1611afc2ba1dSToomas Soome */
1612afc2ba1dSToomas Soome argvbuf = (char **)calloc(argc, sizeof (char *));
1613afc2ba1dSToomas Soome for (i = 0; i < argc; i++)
1614afc2ba1dSToomas Soome argvbuf[i] = strdup(argv[i]);
1615afc2ba1dSToomas Soome
1616afc2ba1dSToomas Soome res = CMD_OK;
1617afc2ba1dSToomas Soome for (i = 1; (i < argc) && (res == CMD_OK); i++)
1618afc2ba1dSToomas Soome res = include(argvbuf[i]);
1619afc2ba1dSToomas Soome
1620afc2ba1dSToomas Soome for (i = 0; i < argc; i++)
1621afc2ba1dSToomas Soome free(argvbuf[i]);
1622afc2ba1dSToomas Soome free(argvbuf);
1623afc2ba1dSToomas Soome
1624afc2ba1dSToomas Soome return (res);
1625afc2ba1dSToomas Soome }
1626afc2ba1dSToomas Soome
1627afc2ba1dSToomas Soome /*
1628afc2ba1dSToomas Soome * Header prepended to each line. The text immediately follows the header.
1629afc2ba1dSToomas Soome * We try to make this short in order to save memory -- the loader has
1630afc2ba1dSToomas Soome * limited memory available, and some of the forth files are very long.
1631afc2ba1dSToomas Soome */
1632afc2ba1dSToomas Soome struct includeline
1633afc2ba1dSToomas Soome {
1634afc2ba1dSToomas Soome struct includeline *next;
1635afc2ba1dSToomas Soome int line;
1636afc2ba1dSToomas Soome char text[];
1637afc2ba1dSToomas Soome };
1638afc2ba1dSToomas Soome
1639afc2ba1dSToomas Soome int
include(const char * filename)1640afc2ba1dSToomas Soome include(const char *filename)
1641afc2ba1dSToomas Soome {
1642afc2ba1dSToomas Soome struct includeline *script, *se, *sp;
1643afc2ba1dSToomas Soome int res = CMD_OK;
1644afc2ba1dSToomas Soome int prevsrcid, fd, line;
1645afc2ba1dSToomas Soome char *cp, input[256]; /* big enough? */
1646afc2ba1dSToomas Soome char *path;
1647afc2ba1dSToomas Soome
1648afc2ba1dSToomas Soome path = get_dev(filename);
1649afc2ba1dSToomas Soome if (((fd = open(path, O_RDONLY)) == -1)) {
1650c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1651afc2ba1dSToomas Soome "can't open '%s': %s", filename,
1652afc2ba1dSToomas Soome strerror(errno));
1653afc2ba1dSToomas Soome free(path);
1654afc2ba1dSToomas Soome return (CMD_ERROR);
1655afc2ba1dSToomas Soome }
1656afc2ba1dSToomas Soome
1657afc2ba1dSToomas Soome free(path);
1658afc2ba1dSToomas Soome /*
1659afc2ba1dSToomas Soome * Read the script into memory.
1660afc2ba1dSToomas Soome */
1661afc2ba1dSToomas Soome script = se = NULL;
1662afc2ba1dSToomas Soome line = 0;
1663afc2ba1dSToomas Soome
1664afc2ba1dSToomas Soome while (fgetstr(input, sizeof (input), fd) >= 0) {
1665afc2ba1dSToomas Soome line++;
1666afc2ba1dSToomas Soome cp = input;
1667afc2ba1dSToomas Soome /* Allocate script line structure and copy line, flags */
1668afc2ba1dSToomas Soome if (*cp == '\0')
1669afc2ba1dSToomas Soome continue; /* ignore empty line, save memory */
1670afc2ba1dSToomas Soome if (cp[0] == '\\' && cp[1] == ' ')
1671afc2ba1dSToomas Soome continue; /* ignore comment */
1672afc2ba1dSToomas Soome
1673afc2ba1dSToomas Soome sp = malloc(sizeof (struct includeline) + strlen(cp) + 1);
1674afc2ba1dSToomas Soome /*
1675afc2ba1dSToomas Soome * On malloc failure (it happens!), free as much as possible
1676afc2ba1dSToomas Soome * and exit
1677afc2ba1dSToomas Soome */
1678afc2ba1dSToomas Soome if (sp == NULL) {
1679afc2ba1dSToomas Soome while (script != NULL) {
1680afc2ba1dSToomas Soome se = script;
1681afc2ba1dSToomas Soome script = script->next;
1682afc2ba1dSToomas Soome free(se);
1683afc2ba1dSToomas Soome }
1684c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1685afc2ba1dSToomas Soome "file '%s' line %d: memory allocation "
1686afc2ba1dSToomas Soome "failure - aborting", filename, line);
1687afc2ba1dSToomas Soome return (CMD_ERROR);
1688afc2ba1dSToomas Soome }
1689c0bb4f73SToomas Soome (void) strcpy(sp->text, cp);
1690afc2ba1dSToomas Soome sp->line = line;
1691afc2ba1dSToomas Soome sp->next = NULL;
1692afc2ba1dSToomas Soome
1693afc2ba1dSToomas Soome if (script == NULL) {
1694afc2ba1dSToomas Soome script = sp;
1695afc2ba1dSToomas Soome } else {
1696afc2ba1dSToomas Soome se->next = sp;
1697afc2ba1dSToomas Soome }
1698afc2ba1dSToomas Soome se = sp;
1699afc2ba1dSToomas Soome }
1700c0bb4f73SToomas Soome (void) close(fd);
1701afc2ba1dSToomas Soome
1702afc2ba1dSToomas Soome /*
1703afc2ba1dSToomas Soome * Execute the script
1704afc2ba1dSToomas Soome */
1705afc2ba1dSToomas Soome
1706afc2ba1dSToomas Soome prevsrcid = bf_vm->sourceId.i;
1707afc2ba1dSToomas Soome bf_vm->sourceId.i = fd+1; /* 0 is user input device */
1708afc2ba1dSToomas Soome
1709afc2ba1dSToomas Soome res = CMD_OK;
1710afc2ba1dSToomas Soome
1711afc2ba1dSToomas Soome for (sp = script; sp != NULL; sp = sp->next) {
1712afc2ba1dSToomas Soome res = bf_run(sp->text);
1713afc2ba1dSToomas Soome if (res != FICL_VM_STATUS_OUT_OF_TEXT) {
1714c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1715afc2ba1dSToomas Soome "Error while including %s, in the line %d:\n%s",
1716afc2ba1dSToomas Soome filename, sp->line, sp->text);
1717afc2ba1dSToomas Soome res = CMD_ERROR;
1718afc2ba1dSToomas Soome break;
1719afc2ba1dSToomas Soome } else
1720afc2ba1dSToomas Soome res = CMD_OK;
1721afc2ba1dSToomas Soome }
1722afc2ba1dSToomas Soome
1723afc2ba1dSToomas Soome bf_vm->sourceId.i = -1;
1724afc2ba1dSToomas Soome (void) bf_run("");
1725afc2ba1dSToomas Soome bf_vm->sourceId.i = prevsrcid;
1726afc2ba1dSToomas Soome
1727afc2ba1dSToomas Soome while (script != NULL) {
1728afc2ba1dSToomas Soome se = script;
1729afc2ba1dSToomas Soome script = script->next;
1730afc2ba1dSToomas Soome free(se);
1731afc2ba1dSToomas Soome }
1732afc2ba1dSToomas Soome
1733afc2ba1dSToomas Soome return (res);
1734afc2ba1dSToomas Soome }
1735afc2ba1dSToomas Soome
173695bfa623SToomas Soome COMMAND_SET(boot, "boot", "boot a file or loaded kernel", command_boot);
1737afc2ba1dSToomas Soome static int
command_boot(int argc,char * argv[])1738afc2ba1dSToomas Soome command_boot(int argc, char *argv[])
1739afc2ba1dSToomas Soome {
1740afc2ba1dSToomas Soome return (CMD_OK);
1741afc2ba1dSToomas Soome }
1742afc2ba1dSToomas Soome
174395bfa623SToomas Soome COMMAND_SET(autoboot, "autoboot", "boot automatically after a delay",
174495bfa623SToomas Soome command_autoboot);
1745afc2ba1dSToomas Soome static int
command_autoboot(int argc,char * argv[])1746afc2ba1dSToomas Soome command_autoboot(int argc, char *argv[])
1747afc2ba1dSToomas Soome {
1748afc2ba1dSToomas Soome return (CMD_OK);
1749afc2ba1dSToomas Soome }
1750afc2ba1dSToomas Soome
1751afc2ba1dSToomas Soome static void
moduledir_rebuild(void)1752afc2ba1dSToomas Soome moduledir_rebuild(void)
1753afc2ba1dSToomas Soome {
1754afc2ba1dSToomas Soome struct moduledir *mdp, *mtmp;
1755afc2ba1dSToomas Soome const char *path, *cp, *ep;
1756afc2ba1dSToomas Soome int cplen;
1757afc2ba1dSToomas Soome
1758afc2ba1dSToomas Soome path = getenv("module_path");
1759afc2ba1dSToomas Soome if (path == NULL)
1760afc2ba1dSToomas Soome path = default_searchpath;
1761afc2ba1dSToomas Soome /*
1762afc2ba1dSToomas Soome * Rebuild list of module directories if it changed
1763afc2ba1dSToomas Soome */
1764afc2ba1dSToomas Soome STAILQ_FOREACH(mdp, &moduledir_list, d_link)
1765afc2ba1dSToomas Soome mdp->d_flags |= MDIR_REMOVED;
1766afc2ba1dSToomas Soome
1767afc2ba1dSToomas Soome for (ep = path; *ep != 0; ep++) {
1768afc2ba1dSToomas Soome cp = ep;
1769afc2ba1dSToomas Soome for (; *ep != 0 && *ep != ';'; ep++)
1770afc2ba1dSToomas Soome ;
1771afc2ba1dSToomas Soome /*
1772afc2ba1dSToomas Soome * Ignore trailing slashes
1773afc2ba1dSToomas Soome */
1774afc2ba1dSToomas Soome for (cplen = ep - cp; cplen > 1 && cp[cplen - 1] == '/';
1775afc2ba1dSToomas Soome cplen--)
1776afc2ba1dSToomas Soome ;
1777afc2ba1dSToomas Soome STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
1778afc2ba1dSToomas Soome if (strlen(mdp->d_path) != cplen ||
1779afc2ba1dSToomas Soome bcmp(cp, mdp->d_path, cplen) != 0)
1780afc2ba1dSToomas Soome continue;
1781afc2ba1dSToomas Soome mdp->d_flags &= ~MDIR_REMOVED;
1782afc2ba1dSToomas Soome break;
1783afc2ba1dSToomas Soome }
1784afc2ba1dSToomas Soome if (mdp == NULL) {
1785afc2ba1dSToomas Soome mdp = malloc(sizeof (*mdp) + cplen + 1);
1786afc2ba1dSToomas Soome if (mdp == NULL)
1787afc2ba1dSToomas Soome return;
1788afc2ba1dSToomas Soome mdp->d_path = (char *)(mdp + 1);
1789afc2ba1dSToomas Soome bcopy(cp, mdp->d_path, cplen);
1790afc2ba1dSToomas Soome mdp->d_path[cplen] = 0;
1791afc2ba1dSToomas Soome mdp->d_hints = NULL;
1792afc2ba1dSToomas Soome mdp->d_flags = 0;
1793afc2ba1dSToomas Soome STAILQ_INSERT_TAIL(&moduledir_list, mdp, d_link);
1794afc2ba1dSToomas Soome }
1795afc2ba1dSToomas Soome if (*ep == 0)
1796afc2ba1dSToomas Soome break;
1797afc2ba1dSToomas Soome }
1798afc2ba1dSToomas Soome /*
1799afc2ba1dSToomas Soome * Delete unused directories if any
1800afc2ba1dSToomas Soome */
1801afc2ba1dSToomas Soome mdp = STAILQ_FIRST(&moduledir_list);
1802afc2ba1dSToomas Soome while (mdp) {
1803afc2ba1dSToomas Soome if ((mdp->d_flags & MDIR_REMOVED) == 0) {
1804afc2ba1dSToomas Soome mdp = STAILQ_NEXT(mdp, d_link);
1805afc2ba1dSToomas Soome } else {
1806afc2ba1dSToomas Soome if (mdp->d_hints)
1807afc2ba1dSToomas Soome free(mdp->d_hints);
1808afc2ba1dSToomas Soome mtmp = mdp;
1809afc2ba1dSToomas Soome mdp = STAILQ_NEXT(mdp, d_link);
1810afc2ba1dSToomas Soome STAILQ_REMOVE(&moduledir_list, mtmp, moduledir, d_link);
1811afc2ba1dSToomas Soome free(mtmp);
1812afc2ba1dSToomas Soome }
1813afc2ba1dSToomas Soome }
1814afc2ba1dSToomas Soome }
1815afc2ba1dSToomas Soome
1816afc2ba1dSToomas Soome static char *
file_lookup(const char * path,const char * name,int namelen)1817afc2ba1dSToomas Soome file_lookup(const char *path, const char *name, int namelen)
1818afc2ba1dSToomas Soome {
1819afc2ba1dSToomas Soome struct stat st;
1820afc2ba1dSToomas Soome char *result, *cp, *gz;
1821afc2ba1dSToomas Soome int pathlen;
1822afc2ba1dSToomas Soome
1823afc2ba1dSToomas Soome pathlen = strlen(path);
1824afc2ba1dSToomas Soome result = malloc(pathlen + namelen + 2);
1825afc2ba1dSToomas Soome if (result == NULL)
1826afc2ba1dSToomas Soome return (NULL);
1827afc2ba1dSToomas Soome bcopy(path, result, pathlen);
1828afc2ba1dSToomas Soome if (pathlen > 0 && result[pathlen - 1] != '/')
1829afc2ba1dSToomas Soome result[pathlen++] = '/';
1830afc2ba1dSToomas Soome cp = result + pathlen;
1831afc2ba1dSToomas Soome bcopy(name, cp, namelen);
1832afc2ba1dSToomas Soome cp += namelen;
1833afc2ba1dSToomas Soome *cp = '\0';
1834afc2ba1dSToomas Soome if (stat(result, &st) == 0 && S_ISREG(st.st_mode))
1835afc2ba1dSToomas Soome return (result);
1836afc2ba1dSToomas Soome /* also check for gz file */
1837afc2ba1dSToomas Soome (void) asprintf(&gz, "%s.gz", result);
1838afc2ba1dSToomas Soome if (gz != NULL) {
1839afc2ba1dSToomas Soome int res = stat(gz, &st);
1840afc2ba1dSToomas Soome free(gz);
1841afc2ba1dSToomas Soome if (res == 0)
1842afc2ba1dSToomas Soome return (result);
1843afc2ba1dSToomas Soome }
1844afc2ba1dSToomas Soome free(result);
1845afc2ba1dSToomas Soome return (NULL);
1846afc2ba1dSToomas Soome }
1847afc2ba1dSToomas Soome
1848afc2ba1dSToomas Soome static char *
file_search(const char * name)1849afc2ba1dSToomas Soome file_search(const char *name)
1850afc2ba1dSToomas Soome {
1851afc2ba1dSToomas Soome struct moduledir *mdp;
1852afc2ba1dSToomas Soome struct stat sb;
1853afc2ba1dSToomas Soome char *result;
1854afc2ba1dSToomas Soome int namelen;
1855afc2ba1dSToomas Soome
1856afc2ba1dSToomas Soome if (name == NULL)
1857afc2ba1dSToomas Soome return (NULL);
1858afc2ba1dSToomas Soome if (*name == 0)
1859afc2ba1dSToomas Soome return (strdup(name));
1860afc2ba1dSToomas Soome
1861afc2ba1dSToomas Soome if (strchr(name, '/') != NULL) {
1862afc2ba1dSToomas Soome char *gz;
1863afc2ba1dSToomas Soome if (stat(name, &sb) == 0)
1864afc2ba1dSToomas Soome return (strdup(name));
1865afc2ba1dSToomas Soome /* also check for gz file */
1866afc2ba1dSToomas Soome (void) asprintf(&gz, "%s.gz", name);
1867afc2ba1dSToomas Soome if (gz != NULL) {
1868afc2ba1dSToomas Soome int res = stat(gz, &sb);
1869afc2ba1dSToomas Soome free(gz);
1870afc2ba1dSToomas Soome if (res == 0)
1871afc2ba1dSToomas Soome return (strdup(name));
1872afc2ba1dSToomas Soome }
1873afc2ba1dSToomas Soome return (NULL);
1874afc2ba1dSToomas Soome }
1875afc2ba1dSToomas Soome
1876afc2ba1dSToomas Soome moduledir_rebuild();
1877afc2ba1dSToomas Soome result = NULL;
1878afc2ba1dSToomas Soome namelen = strlen(name);
1879afc2ba1dSToomas Soome STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
1880afc2ba1dSToomas Soome result = file_lookup(mdp->d_path, name, namelen);
1881afc2ba1dSToomas Soome if (result)
1882afc2ba1dSToomas Soome break;
1883afc2ba1dSToomas Soome }
1884afc2ba1dSToomas Soome return (result);
1885afc2ba1dSToomas Soome }
1886afc2ba1dSToomas Soome
188795bfa623SToomas Soome COMMAND_SET(load, "load", "load a kernel or module", command_load);
1888afc2ba1dSToomas Soome static int
command_load(int argc,char * argv[])1889afc2ba1dSToomas Soome command_load(int argc, char *argv[])
1890afc2ba1dSToomas Soome {
1891afc2ba1dSToomas Soome int dofile, ch;
1892afc2ba1dSToomas Soome char *typestr = NULL;
1893afc2ba1dSToomas Soome char *filename;
1894afc2ba1dSToomas Soome dofile = 0;
1895afc2ba1dSToomas Soome optind = 1;
1896afc2ba1dSToomas Soome
1897afc2ba1dSToomas Soome if (argc == 1) {
1898afc2ba1dSToomas Soome command_errmsg = "no filename specified";
1899afc2ba1dSToomas Soome return (CMD_ERROR);
1900afc2ba1dSToomas Soome }
1901afc2ba1dSToomas Soome
1902afc2ba1dSToomas Soome while ((ch = getopt(argc, argv, "kt:")) != -1) {
1903afc2ba1dSToomas Soome switch (ch) {
1904afc2ba1dSToomas Soome case 'k':
1905afc2ba1dSToomas Soome break;
1906afc2ba1dSToomas Soome case 't':
1907afc2ba1dSToomas Soome typestr = optarg;
1908afc2ba1dSToomas Soome dofile = 1;
1909afc2ba1dSToomas Soome break;
1910afc2ba1dSToomas Soome case '?':
1911afc2ba1dSToomas Soome default:
1912afc2ba1dSToomas Soome return (CMD_OK);
1913afc2ba1dSToomas Soome }
1914afc2ba1dSToomas Soome }
1915afc2ba1dSToomas Soome argv += (optind - 1);
1916afc2ba1dSToomas Soome argc -= (optind - 1);
1917afc2ba1dSToomas Soome if (dofile) {
1918afc2ba1dSToomas Soome if ((typestr == NULL) || (*typestr == 0)) {
1919afc2ba1dSToomas Soome command_errmsg = "invalid load type";
1920afc2ba1dSToomas Soome return (CMD_ERROR);
1921afc2ba1dSToomas Soome }
1922afc2ba1dSToomas Soome #if 0
1923afc2ba1dSToomas Soome return (file_loadraw(argv[1], typestr, argc - 2, argv + 2, 1)
1924afc2ba1dSToomas Soome ? CMD_OK : CMD_ERROR);
1925afc2ba1dSToomas Soome #endif
1926afc2ba1dSToomas Soome return (CMD_OK);
1927afc2ba1dSToomas Soome }
1928afc2ba1dSToomas Soome
1929afc2ba1dSToomas Soome filename = file_search(argv[1]);
1930afc2ba1dSToomas Soome if (filename == NULL) {
1931c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
1932afc2ba1dSToomas Soome "can't find '%s'", argv[1]);
1933afc2ba1dSToomas Soome return (CMD_ERROR);
1934afc2ba1dSToomas Soome }
1935c0bb4f73SToomas Soome (void) setenv("kernelname", filename, 1);
1936afc2ba1dSToomas Soome
1937afc2ba1dSToomas Soome return (CMD_OK);
1938afc2ba1dSToomas Soome }
1939afc2ba1dSToomas Soome
194095bfa623SToomas Soome COMMAND_SET(unload, "unload", "unload all modules", command_unload);
1941afc2ba1dSToomas Soome static int
command_unload(int argc,char * argv[])1942afc2ba1dSToomas Soome command_unload(int argc, char *argv[])
1943afc2ba1dSToomas Soome {
1944c0bb4f73SToomas Soome (void) unsetenv("kernelname");
1945afc2ba1dSToomas Soome return (CMD_OK);
1946afc2ba1dSToomas Soome }
1947afc2ba1dSToomas Soome
194895bfa623SToomas Soome COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
1949afc2ba1dSToomas Soome static int
command_reboot(int argc,char * argv[])1950afc2ba1dSToomas Soome command_reboot(int argc, char *argv[])
1951afc2ba1dSToomas Soome {
1952afc2ba1dSToomas Soome exit(0);
1953afc2ba1dSToomas Soome return (CMD_OK);
1954afc2ba1dSToomas Soome }
19558751d36cSAndy Fiddaman
195695bfa623SToomas Soome COMMAND_SET(sifting, "sifting", "find words", command_sifting);
19578751d36cSAndy Fiddaman static int
command_sifting(int argc,char * argv[])19588751d36cSAndy Fiddaman command_sifting(int argc, char *argv[])
19598751d36cSAndy Fiddaman {
19608751d36cSAndy Fiddaman if (argc != 2) {
19618751d36cSAndy Fiddaman command_errmsg = "wrong number of arguments";
19628751d36cSAndy Fiddaman return (CMD_ERROR);
19638751d36cSAndy Fiddaman }
19648751d36cSAndy Fiddaman ficlPrimitiveSiftingImpl(bf_vm, argv[1]);
19658751d36cSAndy Fiddaman return (CMD_OK);
19668751d36cSAndy Fiddaman }
19670bead3caSToomas Soome
19680bead3caSToomas Soome /* Only implement get and list. Ignore arguments on, off and set. */
196995bfa623SToomas Soome COMMAND_SET(framebuffer, "framebuffer", "framebuffer mode management",
197095bfa623SToomas Soome command_framebuffer);
19710bead3caSToomas Soome static int
command_framebuffer(int argc,char * argv[])19720bead3caSToomas Soome command_framebuffer(int argc, char *argv[])
19730bead3caSToomas Soome {
19740bead3caSToomas Soome if (fb.fd < 0) {
19750bead3caSToomas Soome printf("Framebuffer is not available.\n");
19760bead3caSToomas Soome return (CMD_OK);
19770bead3caSToomas Soome }
19780bead3caSToomas Soome
19790bead3caSToomas Soome if (argc == 2 && strcmp(argv[1], "get") == 0) {
19800bead3caSToomas Soome printf("\nSystem frame buffer: %s\n", fb.ident.name);
19810bead3caSToomas Soome printf("%dx%dx%d, stride=%d\n", fb.fb_width, fb.fb_height,
19820bead3caSToomas Soome fb.fb_depth, (fb.fb_pitch << 3) / fb.fb_depth);
19830bead3caSToomas Soome return (CMD_OK);
19840bead3caSToomas Soome }
19850bead3caSToomas Soome if (argc == 2 && strcmp(argv[1], "list") == 0) {
19860bead3caSToomas Soome printf("0: %dx%dx%d\n", fb.fb_width, fb.fb_height, fb.fb_depth);
19870bead3caSToomas Soome return (CMD_OK);
19880bead3caSToomas Soome }
19890bead3caSToomas Soome if (argc == 3 && strcmp(argv[1], "set") == 0)
19900bead3caSToomas Soome return (CMD_OK);
19910bead3caSToomas Soome if (argc == 2 && strcmp(argv[1], "on") == 0)
19920bead3caSToomas Soome return (CMD_OK);
19930bead3caSToomas Soome if (argc == 2 && strcmp(argv[1], "off") == 0)
19940bead3caSToomas Soome return (CMD_OK);
19950bead3caSToomas Soome
1996c0bb4f73SToomas Soome (void) snprintf(command_errbuf, sizeof (command_errbuf),
19970bead3caSToomas Soome "usage: %s get | list", argv[0]);
19980bead3caSToomas Soome return (CMD_ERROR);
19990bead3caSToomas Soome }
2000